xref: /vim-8.2.3635/runtime/syntax/2html.vim (revision 2a8a3ecb)
1071d4279SBram Moolenaar" Vim syntax support file
2349b2fb0SBram Moolenaar" Maintainer: Ben Fritz <[email protected]>
3*2a8a3ecbSBram Moolenaar" Last Change: 2011 Jan 06
4349b2fb0SBram Moolenaar"
5349b2fb0SBram Moolenaar" Additional contributors:
6349b2fb0SBram Moolenaar"
7349b2fb0SBram Moolenaar"             Original by Bram Moolenaar <[email protected]>
8349b2fb0SBram Moolenaar"             Modified by David Ne\v{c}as (Yeti) <[email protected]>
9349b2fb0SBram Moolenaar"             XHTML support by Panagiotis Issaris <[email protected]>
10349b2fb0SBram Moolenaar"             Made w3 compliant by Edd Barrett <[email protected]>
11349b2fb0SBram Moolenaar"             Added html_font. Edd Barrett <[email protected]>
12349b2fb0SBram Moolenaar"             Progress bar based off code from "progressbar widget" plugin by
13349b2fb0SBram Moolenaar"               Andreas Politz, heavily modified:
14349b2fb0SBram Moolenaar"               http://www.vim.org/scripts/script.php?script_id=2006
15349b2fb0SBram Moolenaar"
16349b2fb0SBram Moolenaar"             See Mercurial change logs for more!
17071d4279SBram Moolenaar
18071d4279SBram Moolenaar" Transform a file into HTML, using the current syntax highlighting.
19071d4279SBram Moolenaar
205c73622aSBram Moolenaar" this file uses line continuations
215c73622aSBram Moolenaarlet s:cpo_sav = &cpo
22349b2fb0SBram Moolenaarlet s:ls  = &ls
235c73622aSBram Moolenaarset cpo-=C
245c73622aSBram Moolenaar
25349b2fb0SBram Moolenaarlet s:end=line('$')
26349b2fb0SBram Moolenaar
27313b7237SBram Moolenaar" Font
28b02cbe34SBram Moolenaarif exists("g:html_font")
29076e8b2aSBram Moolenaar  let s:htmlfont = "'". g:html_font . "', monospace"
30313b7237SBram Moolenaarelse
31313b7237SBram Moolenaar  let s:htmlfont = "monospace"
32313b7237SBram Moolenaarendif
33313b7237SBram Moolenaar
34076e8b2aSBram Moolenaarlet s:settings = tohtml#GetUserSettings()
355c73622aSBram Moolenaar
36071d4279SBram Moolenaar" When not in gui we can only guess the colors.
37071d4279SBram Moolenaarif has("gui_running")
38071d4279SBram Moolenaar  let s:whatterm = "gui"
39071d4279SBram Moolenaarelse
40071d4279SBram Moolenaar  let s:whatterm = "cterm"
41071d4279SBram Moolenaar  if &t_Co == 8
42313b7237SBram Moolenaar    let s:cterm_color = {0: "#808080", 1: "#ff6060", 2: "#00ff00", 3: "#ffff00", 4: "#8080ff", 5: "#ff40ff", 6: "#00ffff", 7: "#ffffff"}
43071d4279SBram Moolenaar  else
44313b7237SBram Moolenaar    let s:cterm_color = {0: "#000000", 1: "#c00000", 2: "#008000", 3: "#804000", 4: "#0000c0", 5: "#c000c0", 6: "#008080", 7: "#c0c0c0", 8: "#808080", 9: "#ff6060", 10: "#00ff00", 11: "#ffff00", 12: "#8080ff", 13: "#ff40ff", 14: "#00ffff", 15: "#ffffff"}
45313b7237SBram Moolenaar
46313b7237SBram Moolenaar    " Colors for 88 and 256 come from xterm.
47313b7237SBram Moolenaar    if &t_Co == 88
48313b7237SBram Moolenaar      call extend(s:cterm_color, {16: "#000000", 17: "#00008b", 18: "#0000cd", 19: "#0000ff", 20: "#008b00", 21: "#008b8b", 22: "#008bcd", 23: "#008bff", 24: "#00cd00", 25: "#00cd8b", 26: "#00cdcd", 27: "#00cdff", 28: "#00ff00", 29: "#00ff8b", 30: "#00ffcd", 31: "#00ffff", 32: "#8b0000", 33: "#8b008b", 34: "#8b00cd", 35: "#8b00ff", 36: "#8b8b00", 37: "#8b8b8b", 38: "#8b8bcd", 39: "#8b8bff", 40: "#8bcd00", 41: "#8bcd8b", 42: "#8bcdcd", 43: "#8bcdff", 44: "#8bff00", 45: "#8bff8b", 46: "#8bffcd", 47: "#8bffff", 48: "#cd0000", 49: "#cd008b", 50: "#cd00cd", 51: "#cd00ff", 52: "#cd8b00", 53: "#cd8b8b", 54: "#cd8bcd", 55: "#cd8bff", 56: "#cdcd00", 57: "#cdcd8b", 58: "#cdcdcd", 59: "#cdcdff", 60: "#cdff00", 61: "#cdff8b", 62: "#cdffcd", 63: "#cdffff", 64: "#ff0000"})
49313b7237SBram Moolenaar      call extend(s:cterm_color, {65: "#ff008b", 66: "#ff00cd", 67: "#ff00ff", 68: "#ff8b00", 69: "#ff8b8b", 70: "#ff8bcd", 71: "#ff8bff", 72: "#ffcd00", 73: "#ffcd8b", 74: "#ffcdcd", 75: "#ffcdff", 76: "#ffff00", 77: "#ffff8b", 78: "#ffffcd", 79: "#ffffff", 80: "#2e2e2e", 81: "#5c5c5c", 82: "#737373", 83: "#8b8b8b", 84: "#a2a2a2", 85: "#b9b9b9", 86: "#d0d0d0", 87: "#e7e7e7"})
50313b7237SBram Moolenaar    elseif &t_Co == 256
51313b7237SBram Moolenaar      call extend(s:cterm_color, {16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af", 20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f", 24: "#005f87", 25: "#005faf", 26: "#005fd7", 27: "#005fff", 28: "#008700", 29: "#00875f", 30: "#008787", 31: "#0087af", 32: "#0087d7", 33: "#0087ff", 34: "#00af00", 35: "#00af5f", 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff", 40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af", 44: "#00d7d7", 45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f", 48: "#00ff87", 49: "#00ffaf", 50: "#00ffd7", 51: "#00ffff", 52: "#5f0000", 53: "#5f005f", 54: "#5f0087", 55: "#5f00af", 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f", 60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff", 64: "#5f8700"})
52313b7237SBram Moolenaar      call extend(s:cterm_color, {65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7", 69: "#5f87ff", 70: "#5faf00", 71: "#5faf5f", 72: "#5faf87", 73: "#5fafaf", 74: "#5fafd7", 75: "#5fafff", 76: "#5fd700", 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af", 80: "#5fd7d7", 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87", 85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000", 89: "#87005f", 90: "#870087", 91: "#8700af", 92: "#8700d7", 93: "#8700ff", 94: "#875f00", 95: "#875f5f", 96: "#875f87", 97: "#875faf", 98: "#875fd7", 99: "#875fff", 100: "#878700", 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7", 105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87", 109: "#87afaf", 110: "#87afd7", 111: "#87afff", 112: "#87d700"})
53313b7237SBram Moolenaar      call extend(s:cterm_color, {113: "#87d75f", 114: "#87d787", 115: "#87d7af", 116: "#87d7d7", 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f", 120: "#87ff87", 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000", 125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7", 129: "#af00ff", 130: "#af5f00", 131: "#af5f5f", 132: "#af5f87", 133: "#af5faf", 134: "#af5fd7", 135: "#af5fff", 136: "#af8700", 137: "#af875f", 138: "#af8787", 139: "#af87af", 140: "#af87d7", 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87", 145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700", 149: "#afd75f", 150: "#afd787", 151: "#afd7af", 152: "#afd7d7", 153: "#afd7ff", 154: "#afff00", 155: "#afff5f", 156: "#afff87", 157: "#afffaf", 158: "#afffd7"})
54313b7237SBram Moolenaar      call extend(s:cterm_color, {159: "#afffff", 160: "#d70000", 161: "#d7005f", 162: "#d70087", 163: "#d700af", 164: "#d700d7", 165: "#d700ff", 166: "#d75f00", 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf", 170: "#d75fd7", 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787", 175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#d7af00", 179: "#d7af5f", 180: "#d7af87", 181: "#d7afaf", 182: "#d7afd7", 183: "#d7afff", 184: "#d7d700", 185: "#d7d75f", 186: "#d7d787", 187: "#d7d7af", 188: "#d7d7d7", 189: "#d7d7ff", 190: "#d7ff00", 191: "#d7ff5f", 192: "#d7ff87", 193: "#d7ffaf", 194: "#d7ffd7", 195: "#d7ffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087", 199: "#ff00af", 200: "#ff00d7", 201: "#ff00ff", 202: "#ff5f00", 203: "#ff5f5f", 204: "#ff5f87"})
55313b7237SBram Moolenaar      call extend(s:cterm_color, {205: "#ff5faf", 206: "#ff5fd7", 207: "#ff5fff", 208: "#ff8700", 209: "#ff875f", 210: "#ff8787", 211: "#ff87af", 212: "#ff87d7", 213: "#ff87ff", 214: "#ffaf00", 215: "#ffaf5f", 216: "#ffaf87", 217: "#ffafaf", 218: "#ffafd7", 219: "#ffafff", 220: "#ffd700", 221: "#ffd75f", 222: "#ffd787", 223: "#ffd7af", 224: "#ffd7d7", 225: "#ffd7ff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87", 229: "#ffffaf", 230: "#ffffd7", 231: "#ffffff", 232: "#080808", 233: "#121212", 234: "#1c1c1c", 235: "#262626", 236: "#303030", 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e", 240: "#585858", 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080", 245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8", 249: "#b2b2b2", 250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0", 253: "#dadada", 254: "#e4e4e4", 255: "#eeeeee"})
56313b7237SBram Moolenaar    endif
57071d4279SBram Moolenaar  endif
58071d4279SBram Moolenaarendif
59071d4279SBram Moolenaar
60071d4279SBram Moolenaar" Return good color specification: in GUI no transformation is done, in
61313b7237SBram Moolenaar" terminal return RGB values of known colors and empty string for unknown
62071d4279SBram Moolenaarif s:whatterm == "gui"
63071d4279SBram Moolenaar  function! s:HtmlColor(color)
64071d4279SBram Moolenaar    return a:color
65071d4279SBram Moolenaar  endfun
66071d4279SBram Moolenaarelse
67071d4279SBram Moolenaar  function! s:HtmlColor(color)
68313b7237SBram Moolenaar    if has_key(s:cterm_color, a:color)
69313b7237SBram Moolenaar      return s:cterm_color[a:color]
70071d4279SBram Moolenaar    else
71071d4279SBram Moolenaar      return ""
72071d4279SBram Moolenaar    endif
73071d4279SBram Moolenaar  endfun
74071d4279SBram Moolenaarendif
75071d4279SBram Moolenaar
76bebca9daSBram Moolenaarif !s:settings.use_css
77071d4279SBram Moolenaar  " Return opening HTML tag for given highlight id
78071d4279SBram Moolenaar  function! s:HtmlOpening(id)
79071d4279SBram Moolenaar    let a = ""
80071d4279SBram Moolenaar    if synIDattr(a:id, "inverse")
81071d4279SBram Moolenaar      " For inverse, we always must set both colors (and exchange them)
82071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
83071d4279SBram Moolenaar      let a = a . '<span style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
84071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
85071d4279SBram Moolenaar      let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">'
86071d4279SBram Moolenaar    else
87071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
88071d4279SBram Moolenaar      if x != "" | let a = a . '<span style="background-color: ' . x . '">' | endif
89071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
90071d4279SBram Moolenaar      if x != "" | let a = a . '<font color="' . x . '">' | endif
91071d4279SBram Moolenaar    endif
92071d4279SBram Moolenaar    if synIDattr(a:id, "bold") | let a = a . "<b>" | endif
93071d4279SBram Moolenaar    if synIDattr(a:id, "italic") | let a = a . "<i>" | endif
94071d4279SBram Moolenaar    if synIDattr(a:id, "underline") | let a = a . "<u>" | endif
95071d4279SBram Moolenaar    return a
96071d4279SBram Moolenaar  endfun
97071d4279SBram Moolenaar
98071d4279SBram Moolenaar  " Return closing HTML tag for given highlight id
99349b2fb0SBram Moolenaar  function! s:HtmlClosing(id)
100071d4279SBram Moolenaar    let a = ""
101071d4279SBram Moolenaar    if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
102071d4279SBram Moolenaar    if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
103071d4279SBram Moolenaar    if synIDattr(a:id, "bold") | let a = a . "</b>" | endif
104071d4279SBram Moolenaar    if synIDattr(a:id, "inverse")
105071d4279SBram Moolenaar      let a = a . '</font></span>'
106071d4279SBram Moolenaar    else
107071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
108071d4279SBram Moolenaar      if x != "" | let a = a . '</font>' | endif
109071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
110071d4279SBram Moolenaar      if x != "" | let a = a . '</span>' | endif
111071d4279SBram Moolenaar    endif
112071d4279SBram Moolenaar    return a
113071d4279SBram Moolenaar  endfun
114071d4279SBram Moolenaarendif
115071d4279SBram Moolenaar
11635a9aaabSBram Moolenaar" Return HTML valid characters enclosed in a span of class style_name with
11735a9aaabSBram Moolenaar" unprintable characters expanded and double spaces replaced as necessary.
1188ada2ccaSBram Moolenaarfunction! s:HtmlFormat(text, style_name, diff_style_name)
11935a9aaabSBram Moolenaar  " Replace unprintable characters
12035a9aaabSBram Moolenaar  let formatted = strtrans(a:text)
12135a9aaabSBram Moolenaar
1228ada2ccaSBram Moolenaar  " separate the two classes by a space to apply them both if there is a diff
1238ada2ccaSBram Moolenaar  " style name
1248ada2ccaSBram Moolenaar  let l:style_name = a:style_name . (a:diff_style_name == '' ? '' : ' ') . a:diff_style_name
1258ada2ccaSBram Moolenaar
12635a9aaabSBram Moolenaar  " Replace the reserved html characters
127*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, '&', '\&amp;',  'g')
128*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, '<', '\&lt;',   'g')
129*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, '>', '\&gt;',   'g')
130*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, '"', '\&quot;', 'g')
131*2a8a3ecbSBram Moolenaar  " TODO: Use &apos; for "'"?
132*2a8a3ecbSBram Moolenaar
133*2a8a3ecbSBram Moolenaar  " Replace a "form feed" character with HTML to do a page break
134*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, "\x0c", '<hr class="PAGE-BREAK">', 'g')
135*2a8a3ecbSBram Moolenaar
136*2a8a3ecbSBram Moolenaar  " Mangle modelines so Vim doesn't try to use HTML text as a modeline if
137*2a8a3ecbSBram Moolenaar  " editing this file in the future
138*2a8a3ecbSBram Moolenaar  let formatted = substitute(formatted, '\v(\s+%(vim?|ex)):', '\1\&#0058;', 'g')
13935a9aaabSBram Moolenaar
1408df7f888SBram Moolenaar  " Replace double spaces, leading spaces, and trailing spaces if needed
14135a9aaabSBram Moolenaar  if ' ' != s:HtmlSpace
14235a9aaabSBram Moolenaar    let formatted = substitute(formatted, '  ', s:HtmlSpace . s:HtmlSpace, 'g')
1438424a624SBram Moolenaar    let formatted = substitute(formatted, '^ ', s:HtmlSpace, 'g')
1448df7f888SBram Moolenaar    let formatted = substitute(formatted, ' \+$', s:HtmlSpace, 'g')
14535a9aaabSBram Moolenaar  endif
14635a9aaabSBram Moolenaar
14735a9aaabSBram Moolenaar  " Enclose in a span of class style_name
1488ada2ccaSBram Moolenaar  let formatted = '<span class="' . l:style_name . '">' . formatted . '</span>'
14935a9aaabSBram Moolenaar
1508ada2ccaSBram Moolenaar  " Add the class to class list if it's not there yet.
1518ada2ccaSBram Moolenaar  " Add normal groups to the beginning so diff groups can override them.
15235a9aaabSBram Moolenaar  let s:id = hlID(a:style_name)
1538ada2ccaSBram Moolenaar  if index(s:idlist, s:id ) == -1
1548ada2ccaSBram Moolenaar    if a:style_name =~ 'Diff\%(Add\|Change\|Delete\|Text\)'
1558ada2ccaSBram Moolenaar      call add(s:idlist, s:id)
1568ada2ccaSBram Moolenaar    else
1578ada2ccaSBram Moolenaar      call insert(s:idlist, s:id)
1588ada2ccaSBram Moolenaar    endif
1598ada2ccaSBram Moolenaar  endif
1608ada2ccaSBram Moolenaar
1618ada2ccaSBram Moolenaar  " Add the diff highlight class to class list if used and it's not there yet.
1628ada2ccaSBram Moolenaar  " Add diff groups to the end so they override the other highlighting.
1638ada2ccaSBram Moolenaar  if a:diff_style_name != ""
1648ada2ccaSBram Moolenaar    let s:diff_id = hlID(a:diff_style_name)
1658ada2ccaSBram Moolenaar    if index(s:idlist, s:diff_id) == -1
1668ada2ccaSBram Moolenaar      call add(s:idlist, s:diff_id)
1678ada2ccaSBram Moolenaar    endif
16835a9aaabSBram Moolenaar  endif
16935a9aaabSBram Moolenaar
17035a9aaabSBram Moolenaar  return formatted
17135a9aaabSBram Moolenaarendfun
17235a9aaabSBram Moolenaar
173071d4279SBram Moolenaar" Return CSS style describing given highlight id (can be empty)
174071d4279SBram Moolenaarfunction! s:CSS1(id)
175071d4279SBram Moolenaar  let a = ""
176071d4279SBram Moolenaar  if synIDattr(a:id, "inverse")
177071d4279SBram Moolenaar    " For inverse, we always must set both colors (and exchange them)
178071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
179071d4279SBram Moolenaar    let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; "
180071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
181071d4279SBram Moolenaar    let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; "
182071d4279SBram Moolenaar  else
183071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
184071d4279SBram Moolenaar    if x != "" | let a = a . "color: " . x . "; " | endif
185071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
186071d4279SBram Moolenaar    if x != "" | let a = a . "background-color: " . x . "; " | endif
187071d4279SBram Moolenaar  endif
188071d4279SBram Moolenaar  if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif
189071d4279SBram Moolenaar  if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif
190071d4279SBram Moolenaar  if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif
191071d4279SBram Moolenaar  return a
192071d4279SBram Moolenaarendfun
193071d4279SBram Moolenaar
194076e8b2aSBram Moolenaarif s:settings.dynamic_folds
1955c73622aSBram Moolenaar  " compares two folds as stored in our list of folds
1965c73622aSBram Moolenaar  " A fold is "less" than another if it starts at an earlier line number,
1975c73622aSBram Moolenaar  " or ends at a later line number, ties broken by fold level
1985c73622aSBram Moolenaar  function! s:FoldCompare(f1, f2)
1995c73622aSBram Moolenaar    if a:f1.firstline != a:f2.firstline
2005c73622aSBram Moolenaar      " put it before if it starts earlier
2015c73622aSBram Moolenaar      return a:f1.firstline - a:f2.firstline
2025c73622aSBram Moolenaar    elseif a:f1.lastline != a:f2.lastline
2035c73622aSBram Moolenaar      " put it before if it ends later
2045c73622aSBram Moolenaar      return a:f2.lastline - a:f1.lastline
2055c73622aSBram Moolenaar    else
2065c73622aSBram Moolenaar      " if folds begin and end on the same lines, put lowest fold level first
2075c73622aSBram Moolenaar      return a:f1.level - a:f2.level
2085c73622aSBram Moolenaar    endif
2095c73622aSBram Moolenaar  endfunction
2105c73622aSBram Moolenaar
2115c73622aSBram Moolenaarendif
2125c73622aSBram Moolenaar
213071d4279SBram Moolenaar
214071d4279SBram Moolenaar" Set some options to make it work faster.
215071d4279SBram Moolenaar" Don't report changes for :substitute, there will be many of them.
2168df7f888SBram Moolenaar" Don't change other windows; turn off scroll bind temporarily
217071d4279SBram Moolenaarlet s:old_title = &title
218071d4279SBram Moolenaarlet s:old_icon = &icon
219071d4279SBram Moolenaarlet s:old_et = &l:et
2208df7f888SBram Moolenaarlet s:old_bind = &l:scrollbind
221071d4279SBram Moolenaarlet s:old_report = &report
222071d4279SBram Moolenaarlet s:old_search = @/
223349b2fb0SBram Moolenaarlet s:old_more = &more
224071d4279SBram Moolenaarset notitle noicon
225071d4279SBram Moolenaarsetlocal et
226349b2fb0SBram Moolenaarset nomore
227071d4279SBram Moolenaarset report=1000000
2288df7f888SBram Moolenaarsetlocal noscrollbind
229071d4279SBram Moolenaar
2307510fe74SBram Moolenaarif exists(':ownsyntax') && exists('w:current_syntax')
2317510fe74SBram Moolenaar  let s:current_syntax = w:current_syntax
2327510fe74SBram Moolenaarelseif exists('b:current_syntax')
2337510fe74SBram Moolenaar  let s:current_syntax = b:current_syntax
2347510fe74SBram Moolenaarelse
2357510fe74SBram Moolenaar  let s:current_syntax = 'none'
2367510fe74SBram Moolenaarendif
2377510fe74SBram Moolenaar
2387510fe74SBram Moolenaarif s:current_syntax == ''
2397510fe74SBram Moolenaar  let s:current_syntax = 'none'
2407510fe74SBram Moolenaarendif
2417510fe74SBram Moolenaar
242071d4279SBram Moolenaar" Split window to create a buffer with the HTML file.
243071d4279SBram Moolenaarlet s:orgbufnr = winbufnr(0)
244349b2fb0SBram Moolenaarlet s:origwin_stl = &l:stl
245071d4279SBram Moolenaarif expand("%") == ""
246076e8b2aSBram Moolenaar  exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
247071d4279SBram Moolenaarelse
248076e8b2aSBram Moolenaar  exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html'
249071d4279SBram Moolenaarendif
250349b2fb0SBram Moolenaar
251349b2fb0SBram Moolenaar" Resize the new window to very small in order to make it draw faster
252349b2fb0SBram Moolenaarlet s:old_winheight = winheight(0)
253349b2fb0SBram Moolenaarlet s:old_winfixheight = &l:winfixheight
254349b2fb0SBram Moolenaarif s:old_winheight > 2
255349b2fb0SBram Moolenaar  resize 1 " leave enough room to view one line at a time
256349b2fb0SBram Moolenaar  norm! G
257349b2fb0SBram Moolenaar  norm! zt
258349b2fb0SBram Moolenaarendif
259349b2fb0SBram Moolenaarsetlocal winfixheight
260349b2fb0SBram Moolenaar
261349b2fb0SBram Moolenaarlet s:newwin_stl = &l:stl
262349b2fb0SBram Moolenaar
263349b2fb0SBram Moolenaar" on the new window, set the least time-consuming fold method
264349b2fb0SBram Moolenaarlet s:old_fdm = &foldmethod
2658df7f888SBram Moolenaarlet s:old_fen = &foldenable
266349b2fb0SBram Moolenaarsetlocal foldmethod=manual
2678df7f888SBram Moolenaarsetlocal nofoldenable
268349b2fb0SBram Moolenaar
269071d4279SBram Moolenaarlet s:newwin = winnr()
270071d4279SBram Moolenaarlet s:orgwin = bufwinnr(s:orgbufnr)
271071d4279SBram Moolenaar
272349b2fb0SBram Moolenaarsetlocal modifiable
273071d4279SBram Moolenaar%d
274071d4279SBram Moolenaarlet s:old_paste = &paste
275071d4279SBram Moolenaarset paste
276071d4279SBram Moolenaarlet s:old_magic = &magic
277071d4279SBram Moolenaarset magic
278071d4279SBram Moolenaar
279166af9bbSBram Moolenaar" set the fileencoding to match the charset we'll be using
280166af9bbSBram Moolenaarlet &l:fileencoding=s:settings.vim_encoding
281166af9bbSBram Moolenaar
282166af9bbSBram Moolenaar" According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
283166af9bbSBram Moolenaar" order mark is highly recommend on the web when using multibyte encodings. But,
284166af9bbSBram Moolenaar" it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
285166af9bbSBram Moolenaar" determine when it is actually inserted.
286166af9bbSBram Moolenaarif s:settings.vim_encoding == 'utf-8'
287166af9bbSBram Moolenaar  setlocal nobomb
288166af9bbSBram Moolenaarelse
289166af9bbSBram Moolenaar  setlocal bomb
290166af9bbSBram Moolenaarendif
291166af9bbSBram Moolenaar
292349b2fb0SBram Moolenaarlet s:lines = []
293349b2fb0SBram Moolenaar
294076e8b2aSBram Moolenaarif s:settings.use_xhtml
295bebca9daSBram Moolenaar  if s:settings.encoding != ""
296bebca9daSBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>")
2971cd871b5SBram Moolenaar  else
298349b2fb0SBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\"?>")
2991cd871b5SBram Moolenaar  endif
30035a9aaabSBram Moolenaar  let s:tag_close = ' />'
301071d4279SBram Moolenaarelse
30235a9aaabSBram Moolenaar  let s:tag_close = '>'
30335a9aaabSBram Moolenaarendif
30435a9aaabSBram Moolenaar
30535a9aaabSBram Moolenaarlet s:HtmlSpace = ' '
306c1e37901SBram Moolenaarlet s:LeadingSpace = ' '
30735a9aaabSBram Moolenaarlet s:HtmlEndline = ''
308076e8b2aSBram Moolenaarif s:settings.no_pre
30935a9aaabSBram Moolenaar  let s:HtmlEndline = '<br' . s:tag_close
310c1e37901SBram Moolenaar  let s:LeadingSpace = '&nbsp;'
311c1e37901SBram Moolenaar  let s:HtmlSpace = '\' . s:LeadingSpace
312071d4279SBram Moolenaarendif
313071d4279SBram Moolenaar
314071d4279SBram Moolenaar" HTML header, with the title and generator ;-). Left free space for the CSS,
315071d4279SBram Moolenaar" to be filled at the end.
316349b2fb0SBram Moolenaarcall extend(s:lines, [
317349b2fb0SBram Moolenaar      \ "<html>",
318bebca9daSBram Moolenaar      \ "<head>"])
319bebca9daSBram Moolenaar" include encoding as close to the top as possible, but only if not already
320bebca9daSBram Moolenaar" contained in XML information (to avoid haggling over content type)
321bebca9daSBram Moolenaarif s:settings.encoding != "" && !s:settings.use_xhtml
322bebca9daSBram Moolenaar  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close)
323bebca9daSBram Moolenaarendif
324bebca9daSBram Moolenaarcall extend(s:lines, [
325349b2fb0SBram Moolenaar      \ ("<title>".expand("%:p:~")."</title>"),
326349b2fb0SBram Moolenaar      \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
327bebca9daSBram Moolenaar      \ ("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close)
328349b2fb0SBram Moolenaar      \ ])
3297510fe74SBram Moolenaarcall add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
330076e8b2aSBram Moolenaarcall add(s:lines, '<meta name="settings" content="'.
331076e8b2aSBram Moolenaar      \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
332076e8b2aSBram Moolenaar      \ '"'.s:tag_close)
333313b7237SBram Moolenaar
334076e8b2aSBram Moolenaarif s:settings.use_css
335076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
336076e8b2aSBram Moolenaar    if s:settings.hover_unfold
3375c73622aSBram Moolenaar      " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
338349b2fb0SBram Moolenaar      call extend(s:lines, [
339349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
340bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : "<!--",
341349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
342349b2fb0SBram Moolenaar	    \ "",
343349b2fb0SBram Moolenaar	    \ "body * { margin: 0; padding: 0; }", "",
344349b2fb0SBram Moolenaar	    \ ".open-fold   > .Folded { display: none;  }",
345349b2fb0SBram Moolenaar	    \ ".open-fold   > .fulltext { display: inline; }",
346349b2fb0SBram Moolenaar	    \ ".closed-fold > .fulltext { display: none;  }",
347349b2fb0SBram Moolenaar	    \ ".closed-fold > .Folded { display: inline; }",
348349b2fb0SBram Moolenaar	    \ "",
349349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-open   { display: none;   }",
350349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-closed { display: inline; }",
351349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-open   { display: inline; }",
352349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-closed { display: none;   }",
353349b2fb0SBram Moolenaar	    \ "", "",
354349b2fb0SBram Moolenaar	    \ '/* opening a fold while hovering won''t be supported by IE6 and other',
355349b2fb0SBram Moolenaar	    \ "similar browsers, but it should fail gracefully. */",
356349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .fulltext { display: inline; }",
357349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .toggle-filler { display: none; }",
358349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .Folded { display: none; }",
359bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
3608df7f888SBram Moolenaar	    \ '</style>'])
361bebca9daSBram Moolenaar      " TODO: IE7 doesn't *actually* support XHTML, maybe we should remove this.
362bebca9daSBram Moolenaar      " But if it's served up as tag soup, maybe the following will work, so
363bebca9daSBram Moolenaar      " leave it in for now.
364bebca9daSBram Moolenaar      call extend(s:lines, [
365349b2fb0SBram Moolenaar	    \ "<!--[if lt IE 7]><style type=\"text/css\">",
366349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
367349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
368349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
369349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
370349b2fb0SBram Moolenaar	    \ "",
371349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
372349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
373349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
374349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
375349b2fb0SBram Moolenaar	    \ "</style>",
376349b2fb0SBram Moolenaar	    \ "<![endif]-->",
377349b2fb0SBram Moolenaar	    \])
3785c73622aSBram Moolenaar    else
3795c73622aSBram Moolenaar      " if we aren't doing hover_unfold, use CSS 1 only
380349b2fb0SBram Moolenaar      call extend(s:lines, [
381349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
382bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" :"<!--",
383349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
384349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
385349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
386349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
387349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
388349b2fb0SBram Moolenaar	    \ "",
389349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
390349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
391349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
392349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
393bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
394349b2fb0SBram Moolenaar	    \ '</style>'
395349b2fb0SBram Moolenaar	    \])
3965c73622aSBram Moolenaar    endif
3975c73622aSBram Moolenaar  else
3985c73622aSBram Moolenaar    " if we aren't doing any dynamic folding, no need for any special rules
399349b2fb0SBram Moolenaar    call extend(s:lines, [
400349b2fb0SBram Moolenaar	  \ "<style type=\"text/css\">",
401bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : "<!--",
402bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : '-->',
403349b2fb0SBram Moolenaar	  \ "</style>",
404349b2fb0SBram Moolenaar	  \])
405071d4279SBram Moolenaar  endif
4065c73622aSBram Moolenaarendif
4075c73622aSBram Moolenaar
4085c73622aSBram Moolenaar" insert javascript to toggle folds open and closed
409076e8b2aSBram Moolenaarif s:settings.dynamic_folds
410349b2fb0SBram Moolenaar  call extend(s:lines, [
411349b2fb0SBram Moolenaar	\ "",
412349b2fb0SBram Moolenaar	\ "<script type='text/javascript'>",
413bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//<![CDATA[' : "<!--",
414349b2fb0SBram Moolenaar	\ "function toggleFold(objID)",
415349b2fb0SBram Moolenaar	\ "{",
416349b2fb0SBram Moolenaar	\ "  var fold;",
417349b2fb0SBram Moolenaar	\ "  fold = document.getElementById(objID);",
418349b2fb0SBram Moolenaar	\ "  if(fold.className == 'closed-fold')",
419349b2fb0SBram Moolenaar	\ "  {",
420349b2fb0SBram Moolenaar	\ "    fold.className = 'open-fold';",
421349b2fb0SBram Moolenaar	\ "  }",
422349b2fb0SBram Moolenaar	\ "  else if (fold.className == 'open-fold')",
423349b2fb0SBram Moolenaar	\ "  {",
424349b2fb0SBram Moolenaar	\ "    fold.className = 'closed-fold';",
425349b2fb0SBram Moolenaar	\ "  }",
426349b2fb0SBram Moolenaar	\ "}",
427bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//]]>' : '-->',
428349b2fb0SBram Moolenaar	\ "</script>"
429349b2fb0SBram Moolenaar	\])
4305c73622aSBram Moolenaarendif
4315c73622aSBram Moolenaar
432076e8b2aSBram Moolenaarif s:settings.no_pre
433349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>"])
434071d4279SBram Moolenaarelse
435349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>", "<pre>"])
436071d4279SBram Moolenaarendif
437071d4279SBram Moolenaar
438071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
439071d4279SBram Moolenaar
440071d4279SBram Moolenaar" List of all id's
4418ada2ccaSBram Moolenaarlet s:idlist = []
442071d4279SBram Moolenaar
443349b2fb0SBram Moolenaar" set up progress bar in the status line
444076e8b2aSBram Moolenaarif !s:settings.no_progress
445349b2fb0SBram Moolenaar  " ProgressBar Indicator
446349b2fb0SBram Moolenaar  let s:progressbar={}
447349b2fb0SBram Moolenaar
448349b2fb0SBram Moolenaar  " Progessbar specific functions
449349b2fb0SBram Moolenaar  func! s:ProgressBar(title, max_value, winnr)
450349b2fb0SBram Moolenaar    let pgb=copy(s:progressbar)
451349b2fb0SBram Moolenaar    let pgb.title = a:title.' '
452349b2fb0SBram Moolenaar    let pgb.max_value = a:max_value
453349b2fb0SBram Moolenaar    let pgb.winnr = a:winnr
454349b2fb0SBram Moolenaar    let pgb.cur_value = 0
455349b2fb0SBram Moolenaar    let pgb.items = { 'title'   : { 'color' : 'Statusline' },
456349b2fb0SBram Moolenaar	  \'bar'     : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
457349b2fb0SBram Moolenaar	  \'counter' : { 'color' : 'Statusline' } }
458349b2fb0SBram Moolenaar    let pgb.last_value = 0
459349b2fb0SBram Moolenaar    let pgb.needs_redraw = 0
460349b2fb0SBram Moolenaar    " Note that you must use len(split) instead of len() if you want to use
461349b2fb0SBram Moolenaar    " unicode in title.
462349b2fb0SBram Moolenaar    "
463349b2fb0SBram Moolenaar    " Subtract 3 for spacing around the title.
464349b2fb0SBram Moolenaar    " Subtract 4 for the percentage display.
465349b2fb0SBram Moolenaar    " Subtract 2 for spacing before this.
466349b2fb0SBram Moolenaar    " Subtract 2 more for the '|' on either side of the progress bar
467349b2fb0SBram Moolenaar    let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
468349b2fb0SBram Moolenaar    let pgb.max_len = 0
469349b2fb0SBram Moolenaar    set laststatus=2
470349b2fb0SBram Moolenaar    return pgb
471349b2fb0SBram Moolenaar  endfun
472349b2fb0SBram Moolenaar
473349b2fb0SBram Moolenaar  " Function: progressbar.calculate_ticks() {{{1
474349b2fb0SBram Moolenaar  func! s:progressbar.calculate_ticks(pb_len)
475349b2fb0SBram Moolenaar    if a:pb_len<=0
476349b2fb0SBram Moolenaar      let pb_len = 100
477349b2fb0SBram Moolenaar    else
478349b2fb0SBram Moolenaar      let pb_len = a:pb_len
479349b2fb0SBram Moolenaar    endif
480349b2fb0SBram Moolenaar    let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
481349b2fb0SBram Moolenaar  endfun
482349b2fb0SBram Moolenaar
483349b2fb0SBram Moolenaar  "Function: progressbar.paint()
484349b2fb0SBram Moolenaar  func! s:progressbar.paint()
485349b2fb0SBram Moolenaar    " Recalculate widths.
486349b2fb0SBram Moolenaar    let max_len = winwidth(self.winnr)
487349b2fb0SBram Moolenaar    let pb_len = 0
488349b2fb0SBram Moolenaar    " always true on first call because of initial value of self.max_len
489349b2fb0SBram Moolenaar    if max_len != self.max_len
490349b2fb0SBram Moolenaar      let self.max_len = max_len
491349b2fb0SBram Moolenaar
492349b2fb0SBram Moolenaar      " Progressbar length
493349b2fb0SBram Moolenaar      let pb_len = max_len - self.subtractedlen
494349b2fb0SBram Moolenaar
495349b2fb0SBram Moolenaar      call self.calculate_ticks(pb_len)
496349b2fb0SBram Moolenaar
497349b2fb0SBram Moolenaar      let self.needs_redraw = 1
498349b2fb0SBram Moolenaar      let cur_value = 0
499349b2fb0SBram Moolenaar      let self.pb_len = pb_len
500349b2fb0SBram Moolenaar    else
501349b2fb0SBram Moolenaar      " start searching at the last found index to make the search for the
502349b2fb0SBram Moolenaar      " appropriate tick value normally take 0 or 1 comparisons
503349b2fb0SBram Moolenaar      let cur_value = self.last_value
504349b2fb0SBram Moolenaar      let pb_len = self.pb_len
505349b2fb0SBram Moolenaar    endif
506349b2fb0SBram Moolenaar
507349b2fb0SBram Moolenaar    let cur_val_max = pb_len > 0 ? pb_len : 100
508349b2fb0SBram Moolenaar
509349b2fb0SBram Moolenaar    " find the current progress bar position based on precalculated thresholds
510349b2fb0SBram Moolenaar    while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
511349b2fb0SBram Moolenaar      let cur_value += 1
512349b2fb0SBram Moolenaar    endwhile
513349b2fb0SBram Moolenaar
514349b2fb0SBram Moolenaar    " update progress bar
515349b2fb0SBram Moolenaar    if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
516349b2fb0SBram Moolenaar      let self.needs_redraw = 1
517349b2fb0SBram Moolenaar      let self.last_value = cur_value
518349b2fb0SBram Moolenaar
519349b2fb0SBram Moolenaar      let t_color  = self.items.title.color
520349b2fb0SBram Moolenaar      let b_fcolor = self.items.bar.fillcolor
521349b2fb0SBram Moolenaar      let b_color  = self.items.bar.color
522349b2fb0SBram Moolenaar      let c_color  = self.items.counter.color
523349b2fb0SBram Moolenaar
524349b2fb0SBram Moolenaar      let stl =  "%#".t_color."#%-( ".self.title." %)".
525349b2fb0SBram Moolenaar	    \"%#".b_color."#".
526349b2fb0SBram Moolenaar	    \(pb_len>0 ?
527349b2fb0SBram Moolenaar	    \	('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
528349b2fb0SBram Moolenaar	    \	 '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
529349b2fb0SBram Moolenaar	    \	('')).
530349b2fb0SBram Moolenaar	    \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
531349b2fb0SBram Moolenaar      call setwinvar(self.winnr, '&stl', stl)
532349b2fb0SBram Moolenaar    endif
533349b2fb0SBram Moolenaar  endfun
534349b2fb0SBram Moolenaar
535349b2fb0SBram Moolenaar  func! s:progressbar.incr( ... )
536349b2fb0SBram Moolenaar    let self.cur_value += (a:0 ? a:1 : 1)
537349b2fb0SBram Moolenaar    " if we were making a general-purpose progress bar, we'd need to limit to a
538349b2fb0SBram Moolenaar    " lower limit as well, but since we always increment with a positive value
539349b2fb0SBram Moolenaar    " in this script, we only need limit the upper value
540349b2fb0SBram Moolenaar    let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
541349b2fb0SBram Moolenaar    call self.paint()
542349b2fb0SBram Moolenaar  endfun
543349b2fb0SBram Moolenaar  " }}}
544076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
545349b2fb0SBram Moolenaar    " to process folds we make two passes through each line
546349b2fb0SBram Moolenaar    let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
547349b2fb0SBram Moolenaar  endif
548349b2fb0SBram Moolenaarendif
549349b2fb0SBram Moolenaar
5505c73622aSBram Moolenaar" First do some preprocessing for dynamic folding. Do this for the entire file
5515c73622aSBram Moolenaar" so we don't accidentally start within a closed fold or something.
5525c73622aSBram Moolenaarlet s:allfolds = []
5535c73622aSBram Moolenaar
554076e8b2aSBram Moolenaarif s:settings.dynamic_folds
5555c73622aSBram Moolenaar  let s:lnum = 1
5565c73622aSBram Moolenaar  let s:end = line('$')
5575c73622aSBram Moolenaar  " save the fold text and set it to the default so we can find fold levels
5585c73622aSBram Moolenaar  let s:foldtext_save = &foldtext
559349b2fb0SBram Moolenaar  setlocal foldtext&
5605c73622aSBram Moolenaar
5615c73622aSBram Moolenaar  " we will set the foldcolumn in the html to the greater of the maximum fold
5625c73622aSBram Moolenaar  " level and the current foldcolumn setting
5635c73622aSBram Moolenaar  let s:foldcolumn = &foldcolumn
5645c73622aSBram Moolenaar
5655c73622aSBram Moolenaar  " get all info needed to describe currently closed folds
566349b2fb0SBram Moolenaar  while s:lnum <= s:end
5675c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5685c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5695c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5705c73622aSBram Moolenaar      " in order to get the fold level of the current fold
5715c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
5725c73622aSBram Moolenaar      " store fold info for later use
5735c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
5745c73622aSBram Moolenaar      call add(s:allfolds, s:newfold)
5755c73622aSBram Moolenaar      " open the fold so we can find any contained folds
5765c73622aSBram Moolenaar      execute s:lnum."foldopen"
5775c73622aSBram Moolenaar    else
578076e8b2aSBram Moolenaar      if !s:settings.no_progress
579349b2fb0SBram Moolenaar	call s:pgb.incr()
580349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
581349b2fb0SBram Moolenaar	  redrawstatus
582349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
583349b2fb0SBram Moolenaar	endif
584349b2fb0SBram Moolenaar      endif
5855c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
5865c73622aSBram Moolenaar    endif
5875c73622aSBram Moolenaar  endwhile
5885c73622aSBram Moolenaar
5895c73622aSBram Moolenaar  " close all folds to get info for originally open folds
5905c73622aSBram Moolenaar  silent! %foldclose!
5915c73622aSBram Moolenaar  let s:lnum = 1
5925c73622aSBram Moolenaar
5935c73622aSBram Moolenaar  " the originally open folds will be all folds we encounter that aren't
5945c73622aSBram Moolenaar  " already in the list of closed folds
595349b2fb0SBram Moolenaar  while s:lnum <= s:end
5965c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5975c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5985c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5995c73622aSBram Moolenaar      " in order to get the fold level of the current fold
6005c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
6015c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
6025c73622aSBram Moolenaar      " only add the fold if we don't already have it
6035c73622aSBram Moolenaar      if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1
6045c73622aSBram Moolenaar	let s:newfold.type = "open-fold"
6055c73622aSBram Moolenaar	call add(s:allfolds, s:newfold)
6065c73622aSBram Moolenaar      endif
6075c73622aSBram Moolenaar      " open the fold so we can find any contained folds
6085c73622aSBram Moolenaar      execute s:lnum."foldopen"
6095c73622aSBram Moolenaar    else
610076e8b2aSBram Moolenaar      if !s:settings.no_progress
611349b2fb0SBram Moolenaar	call s:pgb.incr()
612349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
613349b2fb0SBram Moolenaar	  redrawstatus
614349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
615349b2fb0SBram Moolenaar	endif
616349b2fb0SBram Moolenaar      endif
6175c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
6185c73622aSBram Moolenaar    endif
6195c73622aSBram Moolenaar  endwhile
6205c73622aSBram Moolenaar
6215c73622aSBram Moolenaar  " sort the folds so that we only ever need to look at the first item in the
6225c73622aSBram Moolenaar  " list of folds
6235c73622aSBram Moolenaar  call sort(s:allfolds, "s:FoldCompare")
6245c73622aSBram Moolenaar
625349b2fb0SBram Moolenaar  let &l:foldtext = s:foldtext_save
6265c73622aSBram Moolenaar  unlet s:foldtext_save
6275c73622aSBram Moolenaar
6285c73622aSBram Moolenaar  " close all folds again so we can get the fold text as we go
6295c73622aSBram Moolenaar  silent! %foldclose!
630*2a8a3ecbSBram Moolenaar
631*2a8a3ecbSBram Moolenaar  for afold in s:allfolds
632*2a8a3ecbSBram Moolenaar    let removed = 0
633*2a8a3ecbSBram Moolenaar    if exists("g:html_start_line") && exists("g:html_end_line")
634*2a8a3ecbSBram Moolenaar      if afold.firstline < g:html_start_line
635*2a8a3ecbSBram Moolenaar	if afold.lastline < g:html_end_line && afold.lastline > g:html_start_line
636*2a8a3ecbSBram Moolenaar	  " if a fold starts before the range to convert but stops within the
637*2a8a3ecbSBram Moolenaar	  " range, we need to include it. Make it start on the first converted
638*2a8a3ecbSBram Moolenaar	  " line.
639*2a8a3ecbSBram Moolenaar	  let afold.firstline = g:html_start_line
640*2a8a3ecbSBram Moolenaar	else
641*2a8a3ecbSBram Moolenaar	  " if the fold lies outside the range or the start and stop enclose
642*2a8a3ecbSBram Moolenaar	  " the entire range, don't bother parsing it
643*2a8a3ecbSBram Moolenaar	  call remove(s:allfolds, index(s:allfolds, afold))
644*2a8a3ecbSBram Moolenaar	  let removed = 1
645*2a8a3ecbSBram Moolenaar	endif
646*2a8a3ecbSBram Moolenaar      elseif afold.firstline > g:html_end_line
647*2a8a3ecbSBram Moolenaar	" If the entire fold lies outside the range we need to remove it.
648*2a8a3ecbSBram Moolenaar	call remove(s:allfolds, index(s:allfolds, afold))
649*2a8a3ecbSBram Moolenaar	let removed = 1
650*2a8a3ecbSBram Moolenaar      endif
651*2a8a3ecbSBram Moolenaar    elseif exists("g:html_start_line")
652*2a8a3ecbSBram Moolenaar      if afold.firstline < g:html_start_line
653*2a8a3ecbSBram Moolenaar	" if there is no last line, but there is a first line, the end of the
654*2a8a3ecbSBram Moolenaar	" fold will always lie within the region of interest, so keep it
655*2a8a3ecbSBram Moolenaar	let afold.firstline = g:html_start_line
656*2a8a3ecbSBram Moolenaar      endif
657*2a8a3ecbSBram Moolenaar    elseif exists("g:html_end_line")
658*2a8a3ecbSBram Moolenaar      " if there is no first line we default to the first line in the buffer so
659*2a8a3ecbSBram Moolenaar      " the fold start will always be included if the fold itself is included.
660*2a8a3ecbSBram Moolenaar      " If however the entire fold lies outside the range we need to remove it.
661*2a8a3ecbSBram Moolenaar      if afold.firstline > g:html_end_line
662*2a8a3ecbSBram Moolenaar	call remove(s:allfolds, index(s:allfolds, afold))
663*2a8a3ecbSBram Moolenaar	let removed = 1
664*2a8a3ecbSBram Moolenaar      endif
665*2a8a3ecbSBram Moolenaar    endif
666*2a8a3ecbSBram Moolenaar    if !removed
667*2a8a3ecbSBram Moolenaar      if afold.level+1 > s:foldcolumn
668*2a8a3ecbSBram Moolenaar	let s:foldcolumn = afold.level+1
669*2a8a3ecbSBram Moolenaar      endif
670*2a8a3ecbSBram Moolenaar    endif
671*2a8a3ecbSBram Moolenaar  endfor
6725c73622aSBram Moolenaarendif
6735c73622aSBram Moolenaar
6745c73622aSBram Moolenaar" Now loop over all lines in the original text to convert to html.
675071d4279SBram Moolenaar" Use html_start_line and html_end_line if they are set.
676b02cbe34SBram Moolenaarif exists("g:html_start_line")
677071d4279SBram Moolenaar  let s:lnum = html_start_line
678071d4279SBram Moolenaar  if s:lnum < 1 || s:lnum > line("$")
679071d4279SBram Moolenaar    let s:lnum = 1
680071d4279SBram Moolenaar  endif
681071d4279SBram Moolenaarelse
682071d4279SBram Moolenaar  let s:lnum = 1
683071d4279SBram Moolenaarendif
684b02cbe34SBram Moolenaarif exists("g:html_end_line")
685071d4279SBram Moolenaar  let s:end = html_end_line
686071d4279SBram Moolenaar  if s:end < s:lnum || s:end > line("$")
687071d4279SBram Moolenaar    let s:end = line("$")
688071d4279SBram Moolenaar  endif
689071d4279SBram Moolenaarelse
690071d4279SBram Moolenaar  let s:end = line("$")
691071d4279SBram Moolenaarendif
692071d4279SBram Moolenaar
6935c73622aSBram Moolenaar" stack to keep track of all the folds containing the current line
6945c73622aSBram Moolenaarlet s:foldstack = []
6955c73622aSBram Moolenaar
696076e8b2aSBram Moolenaarif !s:settings.no_progress
697349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
698349b2fb0SBram Moolenaarendif
699349b2fb0SBram Moolenaar
700076e8b2aSBram Moolenaarif s:settings.number_lines
7015c73622aSBram Moolenaar  let s:margin = strlen(s:end) + 1
7025c73622aSBram Moolenaarelse
7035c73622aSBram Moolenaar  let s:margin = 0
7045c73622aSBram Moolenaarendif
7055c73622aSBram Moolenaar
706076e8b2aSBram Moolenaarif has('folding') && !s:settings.ignore_folding
70735a9aaabSBram Moolenaar  let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')]
70835a9aaabSBram Moolenaar  if s:foldfillchar == ''
70935a9aaabSBram Moolenaar    let s:foldfillchar = '-'
7107b0294cbSBram Moolenaar  endif
71135a9aaabSBram Moolenaarendif
71235a9aaabSBram Moolenaarlet s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')]
71335a9aaabSBram Moolenaarif s:difffillchar == ''
71435a9aaabSBram Moolenaar  let s:difffillchar = '-'
7157b0294cbSBram Moolenaarendif
7167b0294cbSBram Moolenaar
7175c73622aSBram Moolenaarlet s:foldId = 0
7187b0294cbSBram Moolenaar
719*2a8a3ecbSBram Moolenaarif !s:settings.expand_tabs
720*2a8a3ecbSBram Moolenaar  " If keeping tabs, add them to printable characters so we keep them when
721*2a8a3ecbSBram Moolenaar  " formatting text (strtrans() doesn't replace printable chars)
722*2a8a3ecbSBram Moolenaar  let s:old_isprint = &isprint
723*2a8a3ecbSBram Moolenaar  setlocal isprint+=9
724*2a8a3ecbSBram Moolenaarendif
725*2a8a3ecbSBram Moolenaar
726071d4279SBram Moolenaarwhile s:lnum <= s:end
727071d4279SBram Moolenaar
72847136d70SBram Moolenaar  " If there are filler lines for diff mode, show these above the line.
72947136d70SBram Moolenaar  let s:filler = diff_filler(s:lnum)
73047136d70SBram Moolenaar  if s:filler > 0
73147136d70SBram Moolenaar    let s:n = s:filler
73247136d70SBram Moolenaar    while s:n > 0
73335a9aaabSBram Moolenaar      let s:new = repeat(s:difffillchar, 3)
73447136d70SBram Moolenaar
735076e8b2aSBram Moolenaar      if s:n > 2 && s:n < s:filler && !s:settings.whole_filler
73635a9aaabSBram Moolenaar	let s:new = s:new . " " . s:filler . " inserted lines "
73735a9aaabSBram Moolenaar	let s:n = 2
73835a9aaabSBram Moolenaar      endif
73935a9aaabSBram Moolenaar
740076e8b2aSBram Moolenaar      if !s:settings.no_pre
74135a9aaabSBram Moolenaar	" HTML line wrapping is off--go ahead and fill to the margin
7425c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, &columns - strlen(s:new) - s:margin)
7435c73622aSBram Moolenaar      else
7445c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, 3)
74535a9aaabSBram Moolenaar      endif
74635a9aaabSBram Moolenaar
7478ada2ccaSBram Moolenaar      let s:new = s:HtmlFormat(s:new, "DiffDelete", "")
748076e8b2aSBram Moolenaar      if s:settings.number_lines
7495c73622aSBram Moolenaar	" Indent if line numbering is on; must be after escaping.
7505c73622aSBram Moolenaar	let s:new = repeat(s:LeadingSpace, s:margin) . s:new
7515c73622aSBram Moolenaar      endif
752349b2fb0SBram Moolenaar      call add(s:lines, s:new.s:HtmlEndline)
75335a9aaabSBram Moolenaar
75447136d70SBram Moolenaar      let s:n = s:n - 1
75547136d70SBram Moolenaar    endwhile
75647136d70SBram Moolenaar    unlet s:n
75747136d70SBram Moolenaar  endif
75847136d70SBram Moolenaar  unlet s:filler
75947136d70SBram Moolenaar
76047136d70SBram Moolenaar  " Start the line with the line number.
761076e8b2aSBram Moolenaar  if s:settings.number_lines
7625c73622aSBram Moolenaar    let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) . s:lnum . ' '
76347136d70SBram Moolenaar  else
7645c73622aSBram Moolenaar    let s:numcol = ""
76547136d70SBram Moolenaar  endif
76647136d70SBram Moolenaar
7675c73622aSBram Moolenaar  let s:new = ""
7685c73622aSBram Moolenaar
769076e8b2aSBram Moolenaar  if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds
7707b0294cbSBram Moolenaar    "
7715c73622aSBram Moolenaar    " This is the beginning of a folded block (with no dynamic folding)
7727b0294cbSBram Moolenaar    "
7735c73622aSBram Moolenaar    let s:new = s:numcol . foldtextresult(s:lnum)
774076e8b2aSBram Moolenaar    if !s:settings.no_pre
77535a9aaabSBram Moolenaar      " HTML line wrapping is off--go ahead and fill to the margin
77635a9aaabSBram Moolenaar      let s:new = s:new . repeat(s:foldfillchar, &columns - strlen(s:new))
7777b0294cbSBram Moolenaar    endif
7787b0294cbSBram Moolenaar
7798ada2ccaSBram Moolenaar    let s:new = s:HtmlFormat(s:new, "Folded", "")
7807b0294cbSBram Moolenaar
7817b0294cbSBram Moolenaar    " Skip to the end of the fold
782349b2fb0SBram Moolenaar    let s:new_lnum = foldclosedend(s:lnum)
783349b2fb0SBram Moolenaar
784076e8b2aSBram Moolenaar    if !s:settings.no_progress
785349b2fb0SBram Moolenaar      call s:pgb.incr(s:new_lnum - s:lnum)
786349b2fb0SBram Moolenaar    endif
787349b2fb0SBram Moolenaar
788349b2fb0SBram Moolenaar    let s:lnum = s:new_lnum
7897b0294cbSBram Moolenaar
7907b0294cbSBram Moolenaar  else
7917b0294cbSBram Moolenaar    "
7925c73622aSBram Moolenaar    " A line that is not folded, or doing dynamic folding.
7937b0294cbSBram Moolenaar    "
79435a9aaabSBram Moolenaar    let s:line = getline(s:lnum)
7957b0294cbSBram Moolenaar    let s:len = strlen(s:line)
7967b0294cbSBram Moolenaar
797076e8b2aSBram Moolenaar    if s:settings.dynamic_folds
7985c73622aSBram Moolenaar      " First insert a closing for any open folds that end on this line
7995c73622aSBram Moolenaar      while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
8005c73622aSBram Moolenaar	let s:new = s:new."</span></span>"
8015c73622aSBram Moolenaar	call remove(s:foldstack, 0)
8025c73622aSBram Moolenaar      endwhile
8035c73622aSBram Moolenaar
804*2a8a3ecbSBram Moolenaar      " Now insert an opening for any new folds that start on this line
8055c73622aSBram Moolenaar      let s:firstfold = 1
8065c73622aSBram Moolenaar      while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
8075c73622aSBram Moolenaar	let s:foldId = s:foldId + 1
808349b2fb0SBram Moolenaar	let s:new .= "<span id='"
809349b2fb0SBram Moolenaar	let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "")
810349b2fb0SBram Moolenaar	let s:new .= "fold".s:foldId."' class='".s:allfolds[0].type."'>"
811349b2fb0SBram Moolenaar
8125c73622aSBram Moolenaar
8135c73622aSBram Moolenaar	" Unless disabled, add a fold column for the opening line of a fold.
8145c73622aSBram Moolenaar	"
8155c73622aSBram Moolenaar	" Note that dynamic folds require using css so we just use css to take
8165c73622aSBram Moolenaar	" care of the leading spaces rather than using &nbsp; in the case of
8175c73622aSBram Moolenaar	" html_no_pre to make it easier
818076e8b2aSBram Moolenaar	if !s:settings.no_foldcolumn
8195c73622aSBram Moolenaar	  " add fold column that can open the new fold
8205c73622aSBram Moolenaar	  if s:allfolds[0].level > 1 && s:firstfold
8215c73622aSBram Moolenaar	    let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
8225c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1) . "</a>"
8235c73622aSBram Moolenaar	  endif
8245c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>+</a>"
8255c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open "
8265c73622aSBram Moolenaar	  " If this is not the last fold we're opening on this line, we need
8275c73622aSBram Moolenaar	  " to keep the filler spaces hidden if the fold is opened by mouse
8285c73622aSBram Moolenaar	  " hover. If it is the last fold to open in the line, we shouldn't hide
8295c73622aSBram Moolenaar	  " them, so don't apply the toggle-filler class.
8305c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum
8315c73622aSBram Moolenaar	    let s:new = s:new . "toggle-filler "
8325c73622aSBram Moolenaar	  endif
8335c73622aSBram Moolenaar	  let s:new = s:new . "FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
8345c73622aSBram Moolenaar	  let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level) . "</a>"
8355c73622aSBram Moolenaar
8365c73622aSBram Moolenaar	  " add fold column that can close the new fold
8375c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-closed FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
8385c73622aSBram Moolenaar	  if s:firstfold
8395c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1)
8405c73622aSBram Moolenaar	  endif
8415c73622aSBram Moolenaar	  let s:new = s:new . "-"
8425c73622aSBram Moolenaar	  " only add spaces if we aren't opening another fold on the same line
8435c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum
8445c73622aSBram Moolenaar	    let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level)
8455c73622aSBram Moolenaar	  endif
8465c73622aSBram Moolenaar	  let s:new = s:new . "</a>"
8475c73622aSBram Moolenaar	  let s:firstfold = 0
8485c73622aSBram Moolenaar	endif
8495c73622aSBram Moolenaar
8505c73622aSBram Moolenaar	" add fold text, moving the span ending to the next line so collapsing
8515c73622aSBram Moolenaar	" of folds works correctly
8528ada2ccaSBram Moolenaar	let s:new = s:new . substitute(s:HtmlFormat(s:numcol . foldtextresult(s:lnum), "Folded", ""), '</span>', s:HtmlEndline.'\n\0', '')
8535c73622aSBram Moolenaar	let s:new = s:new . "<span class='fulltext'>"
8545c73622aSBram Moolenaar
8555c73622aSBram Moolenaar	" open the fold now that we have the fold text to allow retrieval of
8565c73622aSBram Moolenaar	" fold text for subsequent folds
8575c73622aSBram Moolenaar	execute s:lnum."foldopen"
8585c73622aSBram Moolenaar	call insert(s:foldstack, remove(s:allfolds,0))
8595c73622aSBram Moolenaar	let s:foldstack[0].id = s:foldId
8605c73622aSBram Moolenaar      endwhile
8615c73622aSBram Moolenaar
8625c73622aSBram Moolenaar      " Unless disabled, add a fold column for other lines.
8635c73622aSBram Moolenaar      "
8645c73622aSBram Moolenaar      " Note that dynamic folds require using css so we just use css to take
8655c73622aSBram Moolenaar      " care of the leading spaces rather than using &nbsp; in the case of
8665c73622aSBram Moolenaar      " html_no_pre to make it easier
867076e8b2aSBram Moolenaar      if !s:settings.no_foldcolumn
8685c73622aSBram Moolenaar	if empty(s:foldstack)
8697510fe74SBram Moolenaar	  " add the empty foldcolumn for unfolded lines if there is a fold
8707510fe74SBram Moolenaar	  " column at all
8717510fe74SBram Moolenaar	  if s:foldcolumn > 0
8728ada2ccaSBram Moolenaar	    let s:new = s:new . s:HtmlFormat(repeat(' ', s:foldcolumn), "FoldColumn", "")
8737510fe74SBram Moolenaar	  endif
8745c73622aSBram Moolenaar	else
8755c73622aSBram Moolenaar	  " add the fold column for folds not on the opening line
8765c73622aSBram Moolenaar	  if get(s:foldstack, 0).firstline < s:lnum
8775c73622aSBram Moolenaar	    let s:new = s:new . "<a class='FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
8785c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:foldstack[0].level)
8795c73622aSBram Moolenaar	    let s:new = s:new . repeat(' ', s:foldcolumn - s:foldstack[0].level) . "</a>"
8805c73622aSBram Moolenaar	  endif
8815c73622aSBram Moolenaar	endif
8825c73622aSBram Moolenaar      endif
8835c73622aSBram Moolenaar    endif
8845c73622aSBram Moolenaar
8855c73622aSBram Moolenaar    " Now continue with the unfolded line text
886076e8b2aSBram Moolenaar    if s:settings.number_lines
8878ada2ccaSBram Moolenaar      " TODO: why not use the real highlight name here?
8888ada2ccaSBram Moolenaar      let s:new = s:new . s:HtmlFormat(s:numcol, "lnr", "")
889071d4279SBram Moolenaar    endif
890071d4279SBram Moolenaar
89147136d70SBram Moolenaar    " Get the diff attribute, if any.
89247136d70SBram Moolenaar    let s:diffattr = diff_hlID(s:lnum, 1)
89347136d70SBram Moolenaar
8947510fe74SBram Moolenaar    " initialize conceal info to act like not concealed, just in case
8957510fe74SBram Moolenaar    let s:concealinfo = [0, '']
8967510fe74SBram Moolenaar
897071d4279SBram Moolenaar    " Loop over each character in the line
898071d4279SBram Moolenaar    let s:col = 1
8998ada2ccaSBram Moolenaar
9008ada2ccaSBram Moolenaar    " most of the time we won't use the diff_id, initialize to zero
9018ada2ccaSBram Moolenaar    let s:diff_id = 0
9028ada2ccaSBram Moolenaar    let s:diff_id_name = ""
9038ada2ccaSBram Moolenaar
90435a9aaabSBram Moolenaar    while s:col <= s:len || (s:col == 1 && s:diffattr)
905071d4279SBram Moolenaar      let s:startcol = s:col " The start column for processing text
906076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && has('conceal')
9077510fe74SBram Moolenaar	let s:concealinfo = synconcealed(s:lnum, s:col)
9087510fe74SBram Moolenaar      endif
909076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && s:concealinfo[0]
9107510fe74SBram Moolenaar	let s:col = s:col + 1
9117510fe74SBram Moolenaar	" Speed loop (it's small - that's the trick)
9127510fe74SBram Moolenaar	" Go along till we find a change in the match sequence number (ending
9137510fe74SBram Moolenaar	" the specific concealed region) or until there are no more concealed
9147510fe74SBram Moolenaar	" characters.
9157510fe74SBram Moolenaar	while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
9167510fe74SBram Moolenaar      elseif s:diffattr
9178ada2ccaSBram Moolenaar	let s:diff_id = diff_hlID(s:lnum, s:col)
9188ada2ccaSBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
91947136d70SBram Moolenaar	let s:col = s:col + 1
92047136d70SBram Moolenaar	" Speed loop (it's small - that's the trick)
92147136d70SBram Moolenaar	" Go along till we find a change in hlID
9228ada2ccaSBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1)
9238ada2ccaSBram Moolenaar	      \   && s:diff_id == diff_hlID(s:lnum, s:col) |
9248ada2ccaSBram Moolenaar	      \     let s:col = s:col + 1 |
9258ada2ccaSBram Moolenaar	      \ endwhile
926076e8b2aSBram Moolenaar	if s:len < &columns && !s:settings.no_pre
9278ada2ccaSBram Moolenaar	  " Add spaces at the end of the raw text line to extend the changed
9288ada2ccaSBram Moolenaar	  " line to the full width.
9295c73622aSBram Moolenaar	  let s:line = s:line . repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin)
93035a9aaabSBram Moolenaar	  let s:len = &columns
93135a9aaabSBram Moolenaar	endif
93247136d70SBram Moolenaar      else
933071d4279SBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
934071d4279SBram Moolenaar	let s:col = s:col + 1
935071d4279SBram Moolenaar	" Speed loop (it's small - that's the trick)
936071d4279SBram Moolenaar	" Go along till we find a change in synID
937071d4279SBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
93847136d70SBram Moolenaar      endif
939071d4279SBram Moolenaar
940076e8b2aSBram Moolenaar      if s:settings.ignore_conceal || !s:concealinfo[0]
941*2a8a3ecbSBram Moolenaar	" Expand tabs if needed
94235a9aaabSBram Moolenaar	let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
943*2a8a3ecbSBram Moolenaar	if s:settings.expand_tabs
9445c73622aSBram Moolenaar	  let s:offset = 0
9455c73622aSBram Moolenaar	  let s:idx = stridx(s:expandedtab, "\t")
9465c73622aSBram Moolenaar	  while s:idx >= 0
9475c73622aSBram Moolenaar	    if has("multi_byte_encoding")
9485c73622aSBram Moolenaar	      if s:startcol + s:idx == 1
9495c73622aSBram Moolenaar		let s:i = &ts
9505c73622aSBram Moolenaar	      else
9515c73622aSBram Moolenaar		if s:idx == 0
9525c73622aSBram Moolenaar		  let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
9535c73622aSBram Moolenaar		else
9545c73622aSBram Moolenaar		  let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
9555c73622aSBram Moolenaar		endif
9565c73622aSBram Moolenaar		let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
9575c73622aSBram Moolenaar		let s:i = &ts - (s:vcol % &ts)
9585c73622aSBram Moolenaar	      endif
9595c73622aSBram Moolenaar	      let s:offset -= s:i - 1
9605c73622aSBram Moolenaar	    else
9615c73622aSBram Moolenaar	      let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
9625c73622aSBram Moolenaar	    endif
9635c73622aSBram Moolenaar	    let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
9645c73622aSBram Moolenaar	    let s:idx = stridx(s:expandedtab, "\t")
96535a9aaabSBram Moolenaar	  endwhile
966*2a8a3ecbSBram Moolenaar	end
96735a9aaabSBram Moolenaar
9687510fe74SBram Moolenaar	" get the highlight group name to use
969071d4279SBram Moolenaar	let s:id = synIDtrans(s:id)
970071d4279SBram Moolenaar	let s:id_name = synIDattr(s:id, "name", s:whatterm)
9718ada2ccaSBram Moolenaar	if s:diff_id
9728ada2ccaSBram Moolenaar	  let s:diff_id_name = synIDattr(s:diff_id, "name", s:whatterm)
9738ada2ccaSBram Moolenaar	endif
9747510fe74SBram Moolenaar      else
9757510fe74SBram Moolenaar	" use Conceal highlighting for concealed text
9767510fe74SBram Moolenaar	let s:id_name = 'Conceal'
9777510fe74SBram Moolenaar	let s:expandedtab = s:concealinfo[1]
9787510fe74SBram Moolenaar      endif
9797510fe74SBram Moolenaar
9807510fe74SBram Moolenaar      " Output the text with the same synID, with class set to {s:id_name},
9818ada2ccaSBram Moolenaar      " unless it has been concealed completely.
9827510fe74SBram Moolenaar      if strlen(s:expandedtab) > 0
9838ada2ccaSBram Moolenaar	let s:new = s:new . s:HtmlFormat(s:expandedtab,  s:id_name, s:diff_id_name)
9847510fe74SBram Moolenaar      endif
985071d4279SBram Moolenaar    endwhile
9867b0294cbSBram Moolenaar  endif
987071d4279SBram Moolenaar
9887510fe74SBram Moolenaar  call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1))
989076e8b2aSBram Moolenaar  if !s:settings.no_progress && s:pgb.needs_redraw
990349b2fb0SBram Moolenaar    redrawstatus
991349b2fb0SBram Moolenaar    let s:pgb.needs_redraw = 0
992349b2fb0SBram Moolenaar  endif
993071d4279SBram Moolenaar  let s:lnum = s:lnum + 1
994313b7237SBram Moolenaar
995076e8b2aSBram Moolenaar  if !s:settings.no_progress
996349b2fb0SBram Moolenaar    call s:pgb.incr()
997349b2fb0SBram Moolenaar  endif
998349b2fb0SBram Moolenaarendwhile
999349b2fb0SBram Moolenaar
1000076e8b2aSBram Moolenaarif s:settings.dynamic_folds
10015c73622aSBram Moolenaar  " finish off any open folds
10025c73622aSBram Moolenaar  while !empty(s:foldstack)
1003349b2fb0SBram Moolenaar    let s:lines[-1].="</span></span>"
10045c73622aSBram Moolenaar    call remove(s:foldstack, 0)
10055c73622aSBram Moolenaar  endwhile
10065c73622aSBram Moolenaar
10075c73622aSBram Moolenaar  " add fold column to the style list if not already there
10085c73622aSBram Moolenaar  let s:id = hlID('FoldColumn')
10098ada2ccaSBram Moolenaar  if index(s:idlist, s:id) == -1
10108ada2ccaSBram Moolenaar    call insert(s:idlist, s:id)
10115c73622aSBram Moolenaar  endif
10125c73622aSBram Moolenaarendif
10135c73622aSBram Moolenaar
1014076e8b2aSBram Moolenaarif s:settings.no_pre
1015076e8b2aSBram Moolenaar  if !s:settings.use_css
10168ada2ccaSBram Moolenaar    " Close off the font tag that encapsulates the whole <body>
1017bebca9daSBram Moolenaar    call extend(s:lines, ["</font>", "</body>", "</html>"])
10188ada2ccaSBram Moolenaar  else
1019349b2fb0SBram Moolenaar    call extend(s:lines, ["</body>", "</html>"])
10208ada2ccaSBram Moolenaar  endif
1021071d4279SBram Moolenaarelse
1022349b2fb0SBram Moolenaar  call extend(s:lines, ["</pre>", "</body>", "</html>"])
1023071d4279SBram Moolenaarendif
1024071d4279SBram Moolenaar
1025349b2fb0SBram Moolenaarexe s:newwin . "wincmd w"
1026349b2fb0SBram Moolenaarcall setline(1, s:lines)
1027349b2fb0SBram Moolenaarunlet s:lines
1028071d4279SBram Moolenaar
1029071d4279SBram Moolenaar" Now, when we finally know which, we define the colors and styles
1030076e8b2aSBram Moolenaarif s:settings.use_css
1031071d4279SBram Moolenaar  1;/<style type="text/+1
1032071d4279SBram Moolenaarendif
1033071d4279SBram Moolenaar
1034071d4279SBram Moolenaar" Find out the background and foreground color.
1035071d4279SBram Moolenaarlet s:fgc = s:HtmlColor(synIDattr(hlID("Normal"), "fg#", s:whatterm))
1036071d4279SBram Moolenaarlet s:bgc = s:HtmlColor(synIDattr(hlID("Normal"), "bg#", s:whatterm))
1037071d4279SBram Moolenaarif s:fgc == ""
1038071d4279SBram Moolenaar  let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
1039071d4279SBram Moolenaarendif
1040071d4279SBram Moolenaarif s:bgc == ""
1041071d4279SBram Moolenaar  let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
1042071d4279SBram Moolenaarendif
1043071d4279SBram Moolenaar
1044071d4279SBram Moolenaar" Normal/global attributes
1045071d4279SBram Moolenaar" For Netscape 4, set <body> attributes too, though, strictly speaking, it's
1046071d4279SBram Moolenaar" incorrect.
1047076e8b2aSBram Moolenaarif s:settings.use_css
1048076e8b2aSBram Moolenaar  if s:settings.no_pre
1049313b7237SBram Moolenaar    execute "normal! A\nbody { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }\e"
1050071d4279SBram Moolenaar  else
1051313b7237SBram Moolenaar    execute "normal! A\npre { font-family: ". s:htmlfont ."; color: " . s:fgc . "; background-color: " . s:bgc . "; }\e"
1052071d4279SBram Moolenaar    yank
1053071d4279SBram Moolenaar    put
1054071d4279SBram Moolenaar    execute "normal! ^cwbody\e"
1055071d4279SBram Moolenaar  endif
1056071d4279SBram Moolenaarelse
1057bebca9daSBram Moolenaar  execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
1058071d4279SBram Moolenaarendif
1059071d4279SBram Moolenaar
1060071d4279SBram Moolenaar" Line numbering attributes
1061076e8b2aSBram Moolenaarif s:settings.number_lines
1062076e8b2aSBram Moolenaar  if s:settings.use_css
1063071d4279SBram Moolenaar    execute "normal! A\n.lnr { " . s:CSS1(hlID("LineNr")) . "}\e"
1064071d4279SBram Moolenaar  else
10658424a624SBram Moolenaar    execute '%s+^<span class="lnr">\([^<]*\)</span>+' . s:HtmlOpening(hlID("LineNr")) . '\1' . s:HtmlClosing(hlID("LineNr")) . '+g'
1066071d4279SBram Moolenaar  endif
1067071d4279SBram Moolenaarendif
1068071d4279SBram Moolenaar
1069071d4279SBram Moolenaar" Gather attributes for all other classes
1070076e8b2aSBram Moolenaarif !s:settings.no_progress && !empty(s:idlist)
1071349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:newwin)
1072349b2fb0SBram Moolenaarendif
1073349b2fb0SBram Moolenaarwhile !empty(s:idlist)
1074071d4279SBram Moolenaar  let s:attr = ""
1075349b2fb0SBram Moolenaar  let s:id = remove(s:idlist, 0)
1076071d4279SBram Moolenaar  let s:attr = s:CSS1(s:id)
1077071d4279SBram Moolenaar  let s:id_name = synIDattr(s:id, "name", s:whatterm)
1078349b2fb0SBram Moolenaar
1079071d4279SBram Moolenaar  " If the class has some attributes, export the style, otherwise DELETE all
1080071d4279SBram Moolenaar  " its occurences to make the HTML shorter
1081071d4279SBram Moolenaar  if s:attr != ""
1082076e8b2aSBram Moolenaar    if s:settings.use_css
1083071d4279SBram Moolenaar      execute "normal! A\n." . s:id_name . " { " . s:attr . "}"
1084071d4279SBram Moolenaar    else
10858ada2ccaSBram Moolenaar      " replace spans of just this class name with non-CSS style markup
10868ada2ccaSBram Moolenaar      execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '\1' . s:HtmlClosing(s:id) . '+ge'
10878ada2ccaSBram Moolenaar      " Replace spans of this class name AND a diff class with non-CSS style
10888ada2ccaSBram Moolenaar      " markup surrounding a span of just the diff class. The diff class will
10898ada2ccaSBram Moolenaar      " be handled later because we know that information is at the end.
10908ada2ccaSBram Moolenaar      execute '%s+<span class="' . s:id_name . ' \(Diff\%(Add\|Change\|Delete\|Text\)\)">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '<span class="\1">\2</span>' . s:HtmlClosing(s:id) . '+ge'
1091071d4279SBram Moolenaar    endif
1092071d4279SBram Moolenaar  else
1093313b7237SBram Moolenaar    execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+\1+ge'
10948ada2ccaSBram Moolenaar    execute '%s+<span class="' . s:id_name . ' \(Diff\%(Add\|Change\|Delete\|Text\)\)">\([^<]*\)</span>+<span class="\1">\2</span>+ge'
1095076e8b2aSBram Moolenaar    if s:settings.use_css
10968ada2ccaSBram Moolenaar      1;/<\/style>/-2
1097071d4279SBram Moolenaar    endif
1098071d4279SBram Moolenaar  endif
1099349b2fb0SBram Moolenaar
1100076e8b2aSBram Moolenaar  if !s:settings.no_progress
1101349b2fb0SBram Moolenaar    call s:pgb.incr()
1102349b2fb0SBram Moolenaar    if s:pgb.needs_redraw
1103349b2fb0SBram Moolenaar      redrawstatus
1104349b2fb0SBram Moolenaar      let s:pgb.needs_redraw = 0
1105bebca9daSBram Moolenaar      " TODO: sleep here to show the progress bar, but only if total time spent
1106bebca9daSBram Moolenaar      " so far on this step is < 1 second? Too slow for batch runs like the test
1107bebca9daSBram Moolenaar      " suite to sleep all the time. Maybe there's no good reason to sleep at
1108bebca9daSBram Moolenaar      " all.
1109349b2fb0SBram Moolenaar    endif
1110349b2fb0SBram Moolenaar  endif
1111071d4279SBram Moolenaarendwhile
1112071d4279SBram Moolenaar
1113071d4279SBram Moolenaar" Add hyperlinks
11141cd871b5SBram Moolenaar%s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
1115071d4279SBram Moolenaar
1116071d4279SBram Moolenaar" The DTD
1117076e8b2aSBram Moolenaarif s:settings.use_xhtml
1118076e8b2aSBram Moolenaar  exe "normal! gg$a\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
1119076e8b2aSBram Moolenaarelseif s:settings.use_css && !s:settings.no_pre
1120076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
11211cd871b5SBram Moolenaarelse
1122076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
11231cd871b5SBram Moolenaarendif
11241cd871b5SBram Moolenaar
1125076e8b2aSBram Moolenaarif s:settings.use_xhtml
11261cd871b5SBram Moolenaar  exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e"
11271cd871b5SBram Moolenaarendif
1128071d4279SBram Moolenaar
1129071d4279SBram Moolenaar" Cleanup
1130071d4279SBram Moolenaar%s:\s\+$::e
1131071d4279SBram Moolenaar
1132*2a8a3ecbSBram Moolenaar" Restore old settings (new window first)
11338df7f888SBram Moolenaarlet &l:foldenable = s:old_fen
1134349b2fb0SBram Moolenaarlet &l:foldmethod = s:old_fdm
1135071d4279SBram Moolenaarlet &report = s:old_report
1136071d4279SBram Moolenaarlet &title = s:old_title
1137071d4279SBram Moolenaarlet &icon = s:old_icon
1138071d4279SBram Moolenaarlet &paste = s:old_paste
1139071d4279SBram Moolenaarlet &magic = s:old_magic
1140071d4279SBram Moolenaarlet @/ = s:old_search
1141349b2fb0SBram Moolenaarlet &more = s:old_more
1142*2a8a3ecbSBram Moolenaar
1143*2a8a3ecbSBram Moolenaar" switch to original window to restore those settings
1144071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
1145*2a8a3ecbSBram Moolenaar
1146*2a8a3ecbSBram Moolenaarif !s:settings.expand_tabs
1147*2a8a3ecbSBram Moolenaar  let &l:isprint = s:old_isprint
1148*2a8a3ecbSBram Moolenaarendif
1149166af9bbSBram Moolenaarlet &l:stl = s:origwin_stl
1150071d4279SBram Moolenaarlet &l:et = s:old_et
11518df7f888SBram Moolenaarlet &l:scrollbind = s:old_bind
1152*2a8a3ecbSBram Moolenaar
1153*2a8a3ecbSBram Moolenaar" and back to the new window again to end there
1154071d4279SBram Moolenaarexe s:newwin . "wincmd w"
1155*2a8a3ecbSBram Moolenaar
1156166af9bbSBram Moolenaarlet &l:stl = s:newwin_stl
1157349b2fb0SBram Moolenaarexec 'resize' s:old_winheight
1158349b2fb0SBram Moolenaarlet &l:winfixheight = s:old_winfixheight
1159071d4279SBram Moolenaar
1160349b2fb0SBram Moolenaarlet &ls=s:ls
1161349b2fb0SBram Moolenaar
1162071d4279SBram Moolenaar" Save a little bit of memory (worth doing?)
1163313b7237SBram Moolenaarunlet s:htmlfont
11648df7f888SBram Moolenaarunlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
11658df7f888SBram Moolenaarunlet s:old_magic s:old_more s:old_fdm s:old_fen s:old_winheight
1166*2a8a3ecbSBram Moolenaarunlet! s:old_isprint
11678df7f888SBram Moolenaarunlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight
1168076e8b2aSBram Moolenaarunlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo
11698df7f888SBram Moolenaarunlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl
11708df7f888SBram Moolenaarunlet! s:newwin_stl s:current_syntax
117105159a0cSBram Moolenaarif !v:profiling
1172071d4279SBram Moolenaar  delfunc s:HtmlColor
117335a9aaabSBram Moolenaar  delfunc s:HtmlFormat
1174071d4279SBram Moolenaar  delfunc s:CSS1
1175076e8b2aSBram Moolenaar  if !s:settings.use_css
1176071d4279SBram Moolenaar    delfunc s:HtmlOpening
1177071d4279SBram Moolenaar    delfunc s:HtmlClosing
1178071d4279SBram Moolenaar  endif
1179076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
11805c73622aSBram Moolenaar    delfunc s:FoldCompare
11815c73622aSBram Moolenaar  endif
11825c73622aSBram Moolenaar
1183076e8b2aSBram Moolenaar  if !s:settings.no_progress
1184349b2fb0SBram Moolenaar    delfunc s:ProgressBar
1185349b2fb0SBram Moolenaar    delfunc s:progressbar.paint
1186349b2fb0SBram Moolenaar    delfunc s:progressbar.incr
1187349b2fb0SBram Moolenaar    unlet s:pgb s:progressbar
1188349b2fb0SBram Moolenaar  endif
1189349b2fb0SBram Moolenaarendif
1190349b2fb0SBram Moolenaar
11918df7f888SBram Moolenaarunlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace
11928df7f888SBram Moolenaarunlet! s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
1193076e8b2aSBram Moolenaarunlet s:foldstack s:allfolds s:foldId s:numcol s:settings
11945c73622aSBram Moolenaar
11955c73622aSBram Moolenaarlet &cpo = s:cpo_sav
1196349b2fb0SBram Moolenaarunlet! s:cpo_sav
11975c73622aSBram Moolenaar
1198349b2fb0SBram Moolenaar" Make sure any patches will probably use consistent indent
11997c86f4ccSBram Moolenaar"   vim: ts=8 sw=2 sts=2 noet
1200