1071d4279SBram Moolenaar" Vim syntax support file 2349b2fb0SBram Moolenaar" Maintainer: Ben Fritz <[email protected]> 32963456fSBram Moolenaar" Last Change: 2020 Jan 05 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 230c0734d5SBram Moolenaarlet s:ei_sav = &eventignore 246c35beaaSBram Moolenaarset cpo&vim 255c73622aSBram Moolenaar 260c0734d5SBram Moolenaar" HTML filetype can take a while to load/highlight if the destination file 270c0734d5SBram Moolenaar" already exists. 280c0734d5SBram Moolenaarset eventignore+=FileType 290c0734d5SBram Moolenaar 30349b2fb0SBram Moolenaarlet s:end=line('$') 31349b2fb0SBram Moolenaar 32313b7237SBram Moolenaar" Font 33b02cbe34SBram Moolenaarif exists("g:html_font") 3460cce2fbSBram Moolenaar if type(g:html_font) == type([]) 3560cce2fbSBram Moolenaar let s:htmlfont = "'". join(g:html_font,"','") . "', monospace" 3660cce2fbSBram Moolenaar else 37076e8b2aSBram Moolenaar let s:htmlfont = "'". g:html_font . "', monospace" 3860cce2fbSBram Moolenaar endif 39313b7237SBram Moolenaarelse 40313b7237SBram Moolenaar let s:htmlfont = "monospace" 41313b7237SBram Moolenaarendif 42313b7237SBram Moolenaar 43076e8b2aSBram Moolenaarlet s:settings = tohtml#GetUserSettings() 445c73622aSBram Moolenaar 450c0734d5SBram Moolenaarif s:settings.use_xhtml 460c0734d5SBram Moolenaar let s:html5 = 0 470c0734d5SBram Moolenaarelseif s:settings.use_css && !s:settings.no_pre 480c0734d5SBram Moolenaar let s:html5 = 1 490c0734d5SBram Moolenaarelse 500c0734d5SBram Moolenaar let s:html5 = 0 510c0734d5SBram Moolenaarendif 520c0734d5SBram Moolenaar 536c35beaaSBram Moolenaarif !exists('s:FOLDED_ID') 546c35beaaSBram Moolenaar let s:FOLDED_ID = hlID("Folded") | lockvar s:FOLDED_ID 556c35beaaSBram Moolenaar let s:FOLD_C_ID = hlID("FoldColumn") | lockvar s:FOLD_C_ID 566c35beaaSBram Moolenaar let s:LINENR_ID = hlID('LineNr') | lockvar s:LINENR_ID 576c35beaaSBram Moolenaar let s:DIFF_D_ID = hlID("DiffDelete") | lockvar s:DIFF_D_ID 586c35beaaSBram Moolenaar let s:DIFF_A_ID = hlID("DiffAdd") | lockvar s:DIFF_A_ID 596c35beaaSBram Moolenaar let s:DIFF_C_ID = hlID("DiffChange") | lockvar s:DIFF_C_ID 606c35beaaSBram Moolenaar let s:DIFF_T_ID = hlID("DiffText") | lockvar s:DIFF_T_ID 616c35beaaSBram Moolenaar let s:CONCEAL_ID = hlID('Conceal') | lockvar s:CONCEAL_ID 626c35beaaSBram Moolenaarendif 636c35beaaSBram Moolenaar 648e5af3e5SBram Moolenaar" Whitespace 658e5af3e5SBram Moolenaarif s:settings.pre_wrap 668e5af3e5SBram Moolenaar let s:whitespace = "white-space: pre-wrap; " 678e5af3e5SBram Moolenaarelse 688e5af3e5SBram Moolenaar let s:whitespace = "" 698e5af3e5SBram Moolenaarendif 708e5af3e5SBram Moolenaar 716c35beaaSBram Moolenaarif !empty(s:settings.prevent_copy) 726c35beaaSBram Moolenaar if s:settings.no_invalid 736c35beaaSBram Moolenaar " User has decided they don't want invalid markup. Still works in 746c35beaaSBram Moolenaar " OpenOffice, and for text editors, but when pasting into Microsoft Word the 756c35beaaSBram Moolenaar " input elements get pasted too and they cannot be deleted (at least not 766c35beaaSBram Moolenaar " easily). 776c35beaaSBram Moolenaar let s:unselInputType = "" 786c35beaaSBram Moolenaar else 796c35beaaSBram Moolenaar " Prevent from copy-pasting the input elements into Microsoft Word where 806c35beaaSBram Moolenaar " they cannot be deleted easily by deliberately inserting invalid markup. 816c35beaaSBram Moolenaar let s:unselInputType = " type='invalid_input_type'" 826c35beaaSBram Moolenaar endif 836c35beaaSBram Moolenaarendif 846c35beaaSBram Moolenaar 850c0734d5SBram Moolenaar" When gui colors are not supported, we can only guess the colors. 860c0734d5SBram Moolenaar" TODO - is this true anymore? Is there a way to ask the terminal what colors 870c0734d5SBram Moolenaar" each number means or read them from some file? 880c0734d5SBram Moolenaarif &termguicolors || has("gui_running") 89071d4279SBram Moolenaar let s:whatterm = "gui" 90071d4279SBram Moolenaarelse 91071d4279SBram Moolenaar let s:whatterm = "cterm" 92071d4279SBram Moolenaar if &t_Co == 8 936c35beaaSBram Moolenaar let s:cterm_color = { 946c35beaaSBram Moolenaar \ 0: "#808080", 1: "#ff6060", 2: "#00ff00", 3: "#ffff00", 956c35beaaSBram Moolenaar \ 4: "#8080ff", 5: "#ff40ff", 6: "#00ffff", 7: "#ffffff" 966c35beaaSBram Moolenaar \ } 97071d4279SBram Moolenaar else 986c35beaaSBram Moolenaar let s:cterm_color = { 996c35beaaSBram Moolenaar \ 0: "#000000", 1: "#c00000", 2: "#008000", 3: "#804000", 1006c35beaaSBram Moolenaar \ 4: "#0000c0", 5: "#c000c0", 6: "#008080", 7: "#c0c0c0", 1016c35beaaSBram Moolenaar \ 8: "#808080", 9: "#ff6060", 10: "#00ff00", 11: "#ffff00", 1026c35beaaSBram Moolenaar \ 12: "#8080ff", 13: "#ff40ff", 14: "#00ffff", 15: "#ffffff" 1036c35beaaSBram Moolenaar \ } 104313b7237SBram Moolenaar 105313b7237SBram Moolenaar " Colors for 88 and 256 come from xterm. 106313b7237SBram Moolenaar if &t_Co == 88 1076c35beaaSBram Moolenaar call extend(s:cterm_color, { 1086c35beaaSBram Moolenaar \ 16: "#000000", 17: "#00008b", 18: "#0000cd", 19: "#0000ff", 1096c35beaaSBram Moolenaar \ 20: "#008b00", 21: "#008b8b", 22: "#008bcd", 23: "#008bff", 1106c35beaaSBram Moolenaar \ 24: "#00cd00", 25: "#00cd8b", 26: "#00cdcd", 27: "#00cdff", 1116c35beaaSBram Moolenaar \ 28: "#00ff00", 29: "#00ff8b", 30: "#00ffcd", 31: "#00ffff", 1126c35beaaSBram Moolenaar \ 32: "#8b0000", 33: "#8b008b", 34: "#8b00cd", 35: "#8b00ff", 1136c35beaaSBram Moolenaar \ 36: "#8b8b00", 37: "#8b8b8b", 38: "#8b8bcd", 39: "#8b8bff", 1146c35beaaSBram Moolenaar \ 40: "#8bcd00", 41: "#8bcd8b", 42: "#8bcdcd", 43: "#8bcdff", 1156c35beaaSBram Moolenaar \ 44: "#8bff00", 45: "#8bff8b", 46: "#8bffcd", 47: "#8bffff", 1166c35beaaSBram Moolenaar \ 48: "#cd0000", 49: "#cd008b", 50: "#cd00cd", 51: "#cd00ff", 1176c35beaaSBram Moolenaar \ 52: "#cd8b00", 53: "#cd8b8b", 54: "#cd8bcd", 55: "#cd8bff", 1186c35beaaSBram Moolenaar \ 56: "#cdcd00", 57: "#cdcd8b", 58: "#cdcdcd", 59: "#cdcdff", 1196c35beaaSBram Moolenaar \ 60: "#cdff00", 61: "#cdff8b", 62: "#cdffcd", 63: "#cdffff", 1206c35beaaSBram Moolenaar \ 64: "#ff0000" 1216c35beaaSBram Moolenaar \ }) 1226c35beaaSBram Moolenaar call extend(s:cterm_color, { 1236c35beaaSBram Moolenaar \ 65: "#ff008b", 66: "#ff00cd", 67: "#ff00ff", 68: "#ff8b00", 1246c35beaaSBram Moolenaar \ 69: "#ff8b8b", 70: "#ff8bcd", 71: "#ff8bff", 72: "#ffcd00", 1256c35beaaSBram Moolenaar \ 73: "#ffcd8b", 74: "#ffcdcd", 75: "#ffcdff", 76: "#ffff00", 1266c35beaaSBram Moolenaar \ 77: "#ffff8b", 78: "#ffffcd", 79: "#ffffff", 80: "#2e2e2e", 1276c35beaaSBram Moolenaar \ 81: "#5c5c5c", 82: "#737373", 83: "#8b8b8b", 84: "#a2a2a2", 1286c35beaaSBram Moolenaar \ 85: "#b9b9b9", 86: "#d0d0d0", 87: "#e7e7e7" 1296c35beaaSBram Moolenaar \ }) 130313b7237SBram Moolenaar elseif &t_Co == 256 1316c35beaaSBram Moolenaar call extend(s:cterm_color, { 1326c35beaaSBram Moolenaar \ 16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af", 1336c35beaaSBram Moolenaar \ 20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f", 1346c35beaaSBram Moolenaar \ 24: "#005f87", 25: "#005faf", 26: "#005fd7", 27: "#005fff", 1356c35beaaSBram Moolenaar \ 28: "#008700", 29: "#00875f", 30: "#008787", 31: "#0087af", 1366c35beaaSBram Moolenaar \ 32: "#0087d7", 33: "#0087ff", 34: "#00af00", 35: "#00af5f", 1376c35beaaSBram Moolenaar \ 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff", 1386c35beaaSBram Moolenaar \ 40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af", 1396c35beaaSBram Moolenaar \ 44: "#00d7d7", 45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f", 1406c35beaaSBram Moolenaar \ 48: "#00ff87", 49: "#00ffaf", 50: "#00ffd7", 51: "#00ffff", 1416c35beaaSBram Moolenaar \ 52: "#5f0000", 53: "#5f005f", 54: "#5f0087", 55: "#5f00af", 1426c35beaaSBram Moolenaar \ 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f", 1436c35beaaSBram Moolenaar \ 60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff", 1446c35beaaSBram Moolenaar \ 64: "#5f8700" 1456c35beaaSBram Moolenaar \ }) 1466c35beaaSBram Moolenaar call extend(s:cterm_color, { 1476c35beaaSBram Moolenaar \ 65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7", 1486c35beaaSBram Moolenaar \ 69: "#5f87ff", 70: "#5faf00", 71: "#5faf5f", 72: "#5faf87", 1496c35beaaSBram Moolenaar \ 73: "#5fafaf", 74: "#5fafd7", 75: "#5fafff", 76: "#5fd700", 1506c35beaaSBram Moolenaar \ 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af", 80: "#5fd7d7", 1516c35beaaSBram Moolenaar \ 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87", 1526c35beaaSBram Moolenaar \ 85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000", 1536c35beaaSBram Moolenaar \ 89: "#87005f", 90: "#870087", 91: "#8700af", 92: "#8700d7", 1546c35beaaSBram Moolenaar \ 93: "#8700ff", 94: "#875f00", 95: "#875f5f", 96: "#875f87", 1556c35beaaSBram Moolenaar \ 97: "#875faf", 98: "#875fd7", 99: "#875fff", 100: "#878700", 1566c35beaaSBram Moolenaar \ 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7", 1576c35beaaSBram Moolenaar \ 105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87", 1586c35beaaSBram Moolenaar \ 109: "#87afaf", 110: "#87afd7", 111: "#87afff", 112: "#87d700" 1596c35beaaSBram Moolenaar \ }) 1606c35beaaSBram Moolenaar call extend(s:cterm_color, { 1616c35beaaSBram Moolenaar \ 113: "#87d75f", 114: "#87d787", 115: "#87d7af", 116: "#87d7d7", 1626c35beaaSBram Moolenaar \ 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f", 120: "#87ff87", 1636c35beaaSBram Moolenaar \ 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000", 1646c35beaaSBram Moolenaar \ 125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7", 1656c35beaaSBram Moolenaar \ 129: "#af00ff", 130: "#af5f00", 131: "#af5f5f", 132: "#af5f87", 1666c35beaaSBram Moolenaar \ 133: "#af5faf", 134: "#af5fd7", 135: "#af5fff", 136: "#af8700", 1676c35beaaSBram Moolenaar \ 137: "#af875f", 138: "#af8787", 139: "#af87af", 140: "#af87d7", 1686c35beaaSBram Moolenaar \ 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87", 1696c35beaaSBram Moolenaar \ 145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700", 1706c35beaaSBram Moolenaar \ 149: "#afd75f", 150: "#afd787", 151: "#afd7af", 152: "#afd7d7", 1716c35beaaSBram Moolenaar \ 153: "#afd7ff", 154: "#afff00", 155: "#afff5f", 156: "#afff87", 1726c35beaaSBram Moolenaar \ 157: "#afffaf", 158: "#afffd7" 1736c35beaaSBram Moolenaar \ }) 1746c35beaaSBram Moolenaar call extend(s:cterm_color, { 1756c35beaaSBram Moolenaar \ 159: "#afffff", 160: "#d70000", 161: "#d7005f", 162: "#d70087", 1766c35beaaSBram Moolenaar \ 163: "#d700af", 164: "#d700d7", 165: "#d700ff", 166: "#d75f00", 1776c35beaaSBram Moolenaar \ 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf", 170: "#d75fd7", 1786c35beaaSBram Moolenaar \ 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787", 1796c35beaaSBram Moolenaar \ 175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#d7af00", 1806c35beaaSBram Moolenaar \ 179: "#d7af5f", 180: "#d7af87", 181: "#d7afaf", 182: "#d7afd7", 1816c35beaaSBram Moolenaar \ 183: "#d7afff", 184: "#d7d700", 185: "#d7d75f", 186: "#d7d787", 1826c35beaaSBram Moolenaar \ 187: "#d7d7af", 188: "#d7d7d7", 189: "#d7d7ff", 190: "#d7ff00", 1836c35beaaSBram Moolenaar \ 191: "#d7ff5f", 192: "#d7ff87", 193: "#d7ffaf", 194: "#d7ffd7", 1846c35beaaSBram Moolenaar \ 195: "#d7ffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087", 1856c35beaaSBram Moolenaar \ 199: "#ff00af", 200: "#ff00d7", 201: "#ff00ff", 202: "#ff5f00", 1866c35beaaSBram Moolenaar \ 203: "#ff5f5f", 204: "#ff5f87" 1876c35beaaSBram Moolenaar \ }) 1886c35beaaSBram Moolenaar call extend(s:cterm_color, { 1896c35beaaSBram Moolenaar \ 205: "#ff5faf", 206: "#ff5fd7", 207: "#ff5fff", 208: "#ff8700", 1906c35beaaSBram Moolenaar \ 209: "#ff875f", 210: "#ff8787", 211: "#ff87af", 212: "#ff87d7", 1916c35beaaSBram Moolenaar \ 213: "#ff87ff", 214: "#ffaf00", 215: "#ffaf5f", 216: "#ffaf87", 1926c35beaaSBram Moolenaar \ 217: "#ffafaf", 218: "#ffafd7", 219: "#ffafff", 220: "#ffd700", 1936c35beaaSBram Moolenaar \ 221: "#ffd75f", 222: "#ffd787", 223: "#ffd7af", 224: "#ffd7d7", 1946c35beaaSBram Moolenaar \ 225: "#ffd7ff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87", 1956c35beaaSBram Moolenaar \ 229: "#ffffaf", 230: "#ffffd7", 231: "#ffffff", 232: "#080808", 1966c35beaaSBram Moolenaar \ 233: "#121212", 234: "#1c1c1c", 235: "#262626", 236: "#303030", 1976c35beaaSBram Moolenaar \ 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e", 240: "#585858", 1986c35beaaSBram Moolenaar \ 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080", 1996c35beaaSBram Moolenaar \ 245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8", 2006c35beaaSBram Moolenaar \ 249: "#b2b2b2", 250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0", 2016c35beaaSBram Moolenaar \ 253: "#dadada", 254: "#e4e4e4", 255: "#eeeeee" 2026c35beaaSBram Moolenaar \ }) 203313b7237SBram Moolenaar endif 204071d4279SBram Moolenaar endif 205071d4279SBram Moolenaarendif 206071d4279SBram Moolenaar 207071d4279SBram Moolenaar" Return good color specification: in GUI no transformation is done, in 208313b7237SBram Moolenaar" terminal return RGB values of known colors and empty string for unknown 209071d4279SBram Moolenaarif s:whatterm == "gui" 210071d4279SBram Moolenaar function! s:HtmlColor(color) 211071d4279SBram Moolenaar return a:color 212071d4279SBram Moolenaar endfun 213071d4279SBram Moolenaarelse 214071d4279SBram Moolenaar function! s:HtmlColor(color) 215313b7237SBram Moolenaar if has_key(s:cterm_color, a:color) 216313b7237SBram Moolenaar return s:cterm_color[a:color] 217071d4279SBram Moolenaar else 218071d4279SBram Moolenaar return "" 219071d4279SBram Moolenaar endif 220071d4279SBram Moolenaar endfun 221071d4279SBram Moolenaarendif 222071d4279SBram Moolenaar 2236c35beaaSBram Moolenaar" Find out the background and foreground color for use later 2246c35beaaSBram Moolenaarlet s:fgc = s:HtmlColor(synIDattr(hlID("Normal"), "fg#", s:whatterm)) 2256c35beaaSBram Moolenaarlet s:bgc = s:HtmlColor(synIDattr(hlID("Normal"), "bg#", s:whatterm)) 2266c35beaaSBram Moolenaarif s:fgc == "" 2276c35beaaSBram Moolenaar let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" ) 2286c35beaaSBram Moolenaarendif 2296c35beaaSBram Moolenaarif s:bgc == "" 2306c35beaaSBram Moolenaar let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" ) 2316c35beaaSBram Moolenaarendif 2326c35beaaSBram Moolenaar 233bebca9daSBram Moolenaarif !s:settings.use_css 234071d4279SBram Moolenaar " Return opening HTML tag for given highlight id 235543b7ef7SBram Moolenaar function! s:HtmlOpening(id, extra_attrs) 236071d4279SBram Moolenaar let a = "" 237071d4279SBram Moolenaar if synIDattr(a:id, "inverse") 238071d4279SBram Moolenaar " For inverse, we always must set both colors (and exchange them) 239071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm)) 240543b7ef7SBram Moolenaar let a = a . '<span '.a:extra_attrs.'style="background-color: ' . ( x != "" ? x : s:fgc ) . '">' 241071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm)) 242071d4279SBram Moolenaar let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">' 243071d4279SBram Moolenaar else 244071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm)) 245543b7ef7SBram Moolenaar if x != "" 246543b7ef7SBram Moolenaar let a = a . '<span '.a:extra_attrs.'style="background-color: ' . x . '">' 247543b7ef7SBram Moolenaar elseif !empty(a:extra_attrs) 248543b7ef7SBram Moolenaar let a = a . '<span '.a:extra_attrs.'>' 249543b7ef7SBram Moolenaar endif 250071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm)) 251071d4279SBram Moolenaar if x != "" | let a = a . '<font color="' . x . '">' | endif 252071d4279SBram Moolenaar endif 253071d4279SBram Moolenaar if synIDattr(a:id, "bold") | let a = a . "<b>" | endif 254071d4279SBram Moolenaar if synIDattr(a:id, "italic") | let a = a . "<i>" | endif 255071d4279SBram Moolenaar if synIDattr(a:id, "underline") | let a = a . "<u>" | endif 256071d4279SBram Moolenaar return a 257071d4279SBram Moolenaar endfun 258071d4279SBram Moolenaar 259071d4279SBram Moolenaar " Return closing HTML tag for given highlight id 260543b7ef7SBram Moolenaar function! s:HtmlClosing(id, has_extra_attrs) 261071d4279SBram Moolenaar let a = "" 262071d4279SBram Moolenaar if synIDattr(a:id, "underline") | let a = a . "</u>" | endif 263071d4279SBram Moolenaar if synIDattr(a:id, "italic") | let a = a . "</i>" | endif 264071d4279SBram Moolenaar if synIDattr(a:id, "bold") | let a = a . "</b>" | endif 265071d4279SBram Moolenaar if synIDattr(a:id, "inverse") 266071d4279SBram Moolenaar let a = a . '</font></span>' 267071d4279SBram Moolenaar else 268071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm)) 269071d4279SBram Moolenaar if x != "" | let a = a . '</font>' | endif 270071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm)) 271543b7ef7SBram Moolenaar if x != "" || a:has_extra_attrs | let a = a . '</span>' | endif 272071d4279SBram Moolenaar endif 273071d4279SBram Moolenaar return a 274071d4279SBram Moolenaar endfun 275071d4279SBram Moolenaarendif 276071d4279SBram Moolenaar 2776c35beaaSBram Moolenaar" Use a different function for formatting based on user options. This way we 2786c35beaaSBram Moolenaar" can avoid a lot of logic during the actual execution. 2796c35beaaSBram Moolenaar" 2806c35beaaSBram Moolenaar" Build the function line by line containing only what is needed for the options 2816c35beaaSBram Moolenaar" in use for maximum code sharing with minimal branch logic for greater speed. 2826c35beaaSBram Moolenaar" 2836c35beaaSBram Moolenaar" Note, 'exec' commands do not recognize line continuations, so must concatenate 2846c35beaaSBram Moolenaar" lines rather than continue them. 2856c35beaaSBram Moolenaarif s:settings.use_css 2866c35beaaSBram Moolenaar " save CSS to a list of rules to add to the output at the end of processing 2876c35beaaSBram Moolenaar 2886c35beaaSBram Moolenaar " first, get the style names we need 2896c35beaaSBram Moolenaar let wrapperfunc_lines = [ 290543b7ef7SBram Moolenaar \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, make_unselectable, unformatted)', 2916c35beaaSBram Moolenaar \ '', 2926c35beaaSBram Moolenaar \ ' let l:style_name = synIDattr(a:style_id, "name", s:whatterm)' 2936c35beaaSBram Moolenaar \ ] 2946c35beaaSBram Moolenaar if &diff 2956c35beaaSBram Moolenaar let wrapperfunc_lines += [ 2966c35beaaSBram Moolenaar \ ' let l:diff_style_name = synIDattr(a:diff_style_id, "name", s:whatterm)'] 2976c35beaaSBram Moolenaar 2986c35beaaSBram Moolenaar " Add normal groups and diff groups to separate lists so we can order them to 2996c35beaaSBram Moolenaar " allow diff highlight to override normal highlight 3006c35beaaSBram Moolenaar 3016c35beaaSBram Moolenaar " if primary style IS a diff style, grab it from the diff cache instead 3026c35beaaSBram Moolenaar " (always succeeds because we pre-populate it) 3036c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3046c35beaaSBram Moolenaar \ '', 3056c35beaaSBram Moolenaar \ ' if a:style_id == s:DIFF_D_ID || a:style_id == s:DIFF_A_ID ||'. 3066c35beaaSBram Moolenaar \ ' a:style_id == s:DIFF_C_ID || a:style_id == s:DIFF_T_ID', 3076c35beaaSBram Moolenaar \ ' let l:saved_style = get(s:diffstylelist,a:style_id)', 3086c35beaaSBram Moolenaar \ ' else' 3096c35beaaSBram Moolenaar \ ] 3106c35beaaSBram Moolenaar endif 3116c35beaaSBram Moolenaar 3126c35beaaSBram Moolenaar " get primary style info from cache or build it on the fly if not found 3136c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3146c35beaaSBram Moolenaar \ ' let l:saved_style = get(s:stylelist,a:style_id)', 3156c35beaaSBram Moolenaar \ ' if type(l:saved_style) == type(0)', 3166c35beaaSBram Moolenaar \ ' unlet l:saved_style', 3176c35beaaSBram Moolenaar \ ' let l:saved_style = s:CSS1(a:style_id)', 3186c35beaaSBram Moolenaar \ ' if l:saved_style != ""', 3196c35beaaSBram Moolenaar \ ' let l:saved_style = "." . l:style_name . " { " . l:saved_style . "}"', 3206c35beaaSBram Moolenaar \ ' endif', 3216c35beaaSBram Moolenaar \ ' let s:stylelist[a:style_id]= l:saved_style', 3226c35beaaSBram Moolenaar \ ' endif' 3236c35beaaSBram Moolenaar \ ] 3246c35beaaSBram Moolenaar if &diff 3256c35beaaSBram Moolenaar let wrapperfunc_lines += [ ' endif' ] 3266c35beaaSBram Moolenaar endif 3276c35beaaSBram Moolenaar 3286c35beaaSBram Moolenaar " Build the wrapper tags around the text. It turns out that caching these 3296c35beaaSBram Moolenaar " gives pretty much zero performance gain and adds a lot of logic. 3306c35beaaSBram Moolenaar 3316c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3326c35beaaSBram Moolenaar \ '', 333543b7ef7SBram Moolenaar \ ' if l:saved_style == "" && empty(a:extra_attrs)' 3346c35beaaSBram Moolenaar \ ] 3356c35beaaSBram Moolenaar if &diff 3366c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3376c35beaaSBram Moolenaar \ ' if a:diff_style_id <= 0' 3386c35beaaSBram Moolenaar \ ] 3396c35beaaSBram Moolenaar endif 3406c35beaaSBram Moolenaar " no surroundings if neither primary nor diff style has any info 3416c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3426c35beaaSBram Moolenaar \ ' return a:text' 3436c35beaaSBram Moolenaar \ ] 3446c35beaaSBram Moolenaar if &diff 3456c35beaaSBram Moolenaar " no primary style, but diff style 3466c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3476c35beaaSBram Moolenaar \ ' else', 3486c35beaaSBram Moolenaar \ ' return "<span class=\"" .l:diff_style_name . "\">".a:text."</span>"', 3496c35beaaSBram Moolenaar \ ' endif' 3506c35beaaSBram Moolenaar \ ] 3516c35beaaSBram Moolenaar endif 3526c35beaaSBram Moolenaar " open tag for non-empty primary style 3536c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3546c35beaaSBram Moolenaar \ ' else'] 3556c35beaaSBram Moolenaar " non-empty primary style. handle either empty or non-empty diff style. 3566c35beaaSBram Moolenaar " 3576c35beaaSBram Moolenaar " separate the two classes by a space to apply them both if there is a diff 3586c35beaaSBram Moolenaar " style name, unless the primary style is empty, then just use the diff style 3596c35beaaSBram Moolenaar " name 3606c35beaaSBram Moolenaar let diffstyle = 3616c35beaaSBram Moolenaar \ (&diff ? '(a:diff_style_id <= 0 ? "" : " ". l:diff_style_name) .' 3626c35beaaSBram Moolenaar \ : "") 3636c35beaaSBram Moolenaar if s:settings.prevent_copy == "" 3646c35beaaSBram Moolenaar let wrapperfunc_lines += [ 365543b7ef7SBram Moolenaar \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'.diffstyle.'"\">".a:text."</span>"' 3666c35beaaSBram Moolenaar \ ] 3676c35beaaSBram Moolenaar else 3686c35beaaSBram Moolenaar 3690c0734d5SBram Moolenaar " New method: use generated content in the CSS. The only thing needed here 3700c0734d5SBram Moolenaar " is a span with no content, with an attribute holding the desired text. 3710c0734d5SBram Moolenaar " 3720c0734d5SBram Moolenaar " Old method: use an <input> element when text is unsectable. This is still 3730c0734d5SBram Moolenaar " used in conditional comments for Internet Explorer, where the new method 3740c0734d5SBram Moolenaar " doesn't work. 3756c35beaaSBram Moolenaar " 3766c35beaaSBram Moolenaar " Wrap the <input> in a <span> to allow fixing the stupid bug in some fonts 3776c35beaaSBram Moolenaar " which cause browsers to display a 1px gap between lines when these 3786c35beaaSBram Moolenaar " <input>s have a background color (maybe not really a bug, this isn't 3796c35beaaSBram Moolenaar " well-defined) 3806c35beaaSBram Moolenaar " 3816c35beaaSBram Moolenaar " use strwidth, because we care only about how many character boxes are 3826c35beaaSBram Moolenaar " needed to size the input, we don't care how many characters (including 3836c35beaaSBram Moolenaar " separately counted composing chars, from strchars()) or bytes (from 3846c35beaaSBram Moolenaar " len())the string contains. strdisplaywidth() is not needed because none of 3856c35beaaSBram Moolenaar " the unselectable groups can contain tab characters (fold column, fold 3866c35beaaSBram Moolenaar " text, line number). 3876c35beaaSBram Moolenaar " 3886c35beaaSBram Moolenaar " Note, if maxlength property needs to be added in the future, it will need 3896c35beaaSBram Moolenaar " to use strchars(), because HTML specifies that the maxlength parameter 3906c35beaaSBram Moolenaar " uses the number of unique codepoints for its limit. 3916c35beaaSBram Moolenaar let wrapperfunc_lines += [ 3926c35beaaSBram Moolenaar \ ' if a:make_unselectable', 3930c0734d5SBram Moolenaar \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'.diffstyle.'"\"' 3940c0734d5SBram Moolenaar \ ] 3950c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'all' 3960c0734d5SBram Moolenaar let wrapperfunc_lines[-1] .= ' " . "data-" . l:style_name . "-content=\"".a:text."\"' 3970c0734d5SBram Moolenaar endif 3980c0734d5SBram Moolenaar let wrapperfunc_lines[-1] .= '>' 3990c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'none' 4000c0734d5SBram Moolenaar let wrapperfunc_lines[-1] .= 4016c35beaaSBram Moolenaar \ '<input'.s:unselInputType.' class=\"" . l:style_name .'.diffstyle.'"\"'. 4026c35beaaSBram Moolenaar \ ' value=\"".substitute(a:unformatted,''\s\+$'',"","")."\"'. 4036c35beaaSBram Moolenaar \ ' onselect=''this.blur(); return false;'''. 4046c35beaaSBram Moolenaar \ ' onmousedown=''this.blur(); return false;'''. 4056c35beaaSBram Moolenaar \ ' onclick=''this.blur(); return false;'''. 4066c35beaaSBram Moolenaar \ ' readonly=''readonly'''. 4076c35beaaSBram Moolenaar \ ' size=\"".strwidth(a:unformatted)."\"'. 4080c0734d5SBram Moolenaar \ (s:settings.use_xhtml ? '/' : '').'>' 4090c0734d5SBram Moolenaar endif 4100c0734d5SBram Moolenaar let wrapperfunc_lines[-1] .= '</span>"' 4110c0734d5SBram Moolenaar let wrapperfunc_lines += [ 4126c35beaaSBram Moolenaar \ ' else', 413543b7ef7SBram Moolenaar \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'. diffstyle .'"\">".a:text."</span>"' 4146c35beaaSBram Moolenaar \ ] 4156c35beaaSBram Moolenaar endif 4166c35beaaSBram Moolenaar let wrapperfunc_lines += [ 4176c35beaaSBram Moolenaar \ ' endif', 4186c35beaaSBram Moolenaar \ 'endfun' 4196c35beaaSBram Moolenaar \ ] 4206c35beaaSBram Moolenaarelse 4216c35beaaSBram Moolenaar " Non-CSS method just needs the wrapper. 4226c35beaaSBram Moolenaar " 4236c35beaaSBram Moolenaar " Functions used to get opening/closing automatically return null strings if 4246c35beaaSBram Moolenaar " no styles exist. 4256c35beaaSBram Moolenaar if &diff 4266c35beaaSBram Moolenaar let wrapperfunc_lines = [ 427543b7ef7SBram Moolenaar \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)', 428543b7ef7SBram Moolenaar \ ' return s:HtmlOpening(a:style_id, a:extra_attrs).(a:diff_style_id <= 0 ? "" :'. 429543b7ef7SBram Moolenaar \ 's:HtmlOpening(a:diff_style_id, "")).a:text.'. 430543b7ef7SBram Moolenaar \ '(a:diff_style_id <= 0 ? "" : s:HtmlClosing(a:diff_style_id, 0)).s:HtmlClosing(a:style_id, !empty(a:extra_attrs))', 4316c35beaaSBram Moolenaar \ 'endfun' 4326c35beaaSBram Moolenaar \ ] 4336c35beaaSBram Moolenaar else 4346c35beaaSBram Moolenaar let wrapperfunc_lines = [ 435543b7ef7SBram Moolenaar \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)', 436543b7ef7SBram Moolenaar \ ' return s:HtmlOpening(a:style_id, a:extra_attrs).a:text.s:HtmlClosing(a:style_id, !empty(a:extra_attrs))', 4376c35beaaSBram Moolenaar \ 'endfun' 4386c35beaaSBram Moolenaar \ ] 4396c35beaaSBram Moolenaar endif 4406c35beaaSBram Moolenaarendif 4416c35beaaSBram Moolenaar 4426c35beaaSBram Moolenaar" create the function we built line by line above 4436c35beaaSBram Moolenaarexec join(wrapperfunc_lines, "\n") 4446c35beaaSBram Moolenaar 4456c35beaaSBram Moolenaarlet s:diff_mode = &diff 4466c35beaaSBram Moolenaar 44735a9aaabSBram Moolenaar" Return HTML valid characters enclosed in a span of class style_name with 44835a9aaabSBram Moolenaar" unprintable characters expanded and double spaces replaced as necessary. 4496c35beaaSBram Moolenaar" 4506c35beaaSBram Moolenaar" TODO: eliminate unneeded logic like done for BuildStyleWrapper 451543b7ef7SBram Moolenaarfunction! s:HtmlFormat(text, style_id, diff_style_id, extra_attrs, make_unselectable) 45235a9aaabSBram Moolenaar " Replace unprintable characters 4536c35beaaSBram Moolenaar let unformatted = strtrans(a:text) 45435a9aaabSBram Moolenaar 4556c35beaaSBram Moolenaar let formatted = unformatted 4568ada2ccaSBram Moolenaar 45735a9aaabSBram Moolenaar " Replace the reserved html characters 4582a8a3ecbSBram Moolenaar let formatted = substitute(formatted, '&', '\&', 'g') 4592a8a3ecbSBram Moolenaar let formatted = substitute(formatted, '<', '\<', 'g') 4602a8a3ecbSBram Moolenaar let formatted = substitute(formatted, '>', '\>', 'g') 4612a8a3ecbSBram Moolenaar let formatted = substitute(formatted, '"', '\"', 'g') 4626c35beaaSBram Moolenaar " ' is not valid in HTML but it is in XHTML, so just use the numeric 4636c35beaaSBram Moolenaar " reference for it instead. Needed because it could appear in quotes 4646c35beaaSBram Moolenaar " especially if unselectable regions is turned on. 4656c35beaaSBram Moolenaar let formatted = substitute(formatted, '"', '\'', 'g') 4662a8a3ecbSBram Moolenaar 4672a8a3ecbSBram Moolenaar " Replace a "form feed" character with HTML to do a page break 4686c35beaaSBram Moolenaar " TODO: need to prevent this in unselectable areas? Probably it should never 4696c35beaaSBram Moolenaar " BE in an unselectable area... 4702a8a3ecbSBram Moolenaar let formatted = substitute(formatted, "\x0c", '<hr class="PAGE-BREAK">', 'g') 4712a8a3ecbSBram Moolenaar 4728df7f888SBram Moolenaar " Replace double spaces, leading spaces, and trailing spaces if needed 47335a9aaabSBram Moolenaar if ' ' != s:HtmlSpace 47435a9aaabSBram Moolenaar let formatted = substitute(formatted, ' ', s:HtmlSpace . s:HtmlSpace, 'g') 4758424a624SBram Moolenaar let formatted = substitute(formatted, '^ ', s:HtmlSpace, 'g') 4768df7f888SBram Moolenaar let formatted = substitute(formatted, ' \+$', s:HtmlSpace, 'g') 47735a9aaabSBram Moolenaar endif 47835a9aaabSBram Moolenaar 4796c35beaaSBram Moolenaar " Enclose in the correct format 480543b7ef7SBram Moolenaar return s:BuildStyleWrapper(a:style_id, a:diff_style_id, a:extra_attrs, formatted, a:make_unselectable, unformatted) 48135a9aaabSBram Moolenaarendfun 48235a9aaabSBram Moolenaar 4836c35beaaSBram Moolenaar" set up functions to call HtmlFormat in certain ways based on whether the 4846c35beaaSBram Moolenaar" element is supposed to be unselectable or not 4856c35beaaSBram Moolenaarif s:settings.prevent_copy =~# 'n' 486543b7ef7SBram Moolenaar if s:settings.number_lines 48731c31679SBram Moolenaar if s:settings.line_ids 488543b7ef7SBram Moolenaar function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr) 489543b7ef7SBram Moolenaar if a:lnr > 0 49031c31679SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.s:settings.id_suffix.'" ', 1) 491543b7ef7SBram Moolenaar else 492543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) 493543b7ef7SBram Moolenaar endif 4946c35beaaSBram Moolenaar endfun 4956c35beaaSBram Moolenaar else 49631c31679SBram Moolenaar function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr) 49731c31679SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) 49831c31679SBram Moolenaar endfun 49931c31679SBram Moolenaar endif 50031c31679SBram Moolenaar elseif s:settings.line_ids 501543b7ef7SBram Moolenaar " if lines are not being numbered the only reason this function gets called 502*6c391a74SBram Moolenaar " is to put the line IDs on each line; "text" will be empty but lnr will 503543b7ef7SBram Moolenaar " always be non-zero, however we don't want to use the <input> because that 504543b7ef7SBram Moolenaar " won't work as nice for empty text 505543b7ef7SBram Moolenaar function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr) 50631c31679SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.s:settings.id_suffix.'" ', 0) 507543b7ef7SBram Moolenaar endfun 508543b7ef7SBram Moolenaar endif 509543b7ef7SBram Moolenaarelse 51031c31679SBram Moolenaar if s:settings.line_ids 511543b7ef7SBram Moolenaar function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr) 512543b7ef7SBram Moolenaar if a:lnr > 0 51331c31679SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.s:settings.id_suffix.'" ', 0) 514543b7ef7SBram Moolenaar else 515543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0) 516543b7ef7SBram Moolenaar endif 5176c35beaaSBram Moolenaar endfun 51831c31679SBram Moolenaar else 51931c31679SBram Moolenaar function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr) 52031c31679SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0) 52131c31679SBram Moolenaar endfun 52231c31679SBram Moolenaar endif 5236c35beaaSBram Moolenaarendif 5246c35beaaSBram Moolenaarif s:settings.prevent_copy =~# 'd' 5256c35beaaSBram Moolenaar function! s:HtmlFormat_d(text, style_id, diff_style_id) 526543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) 5276c35beaaSBram Moolenaar endfun 5286c35beaaSBram Moolenaarelse 5296c35beaaSBram Moolenaar function! s:HtmlFormat_d(text, style_id, diff_style_id) 530543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0) 5316c35beaaSBram Moolenaar endfun 5326c35beaaSBram Moolenaarendif 5336c35beaaSBram Moolenaarif s:settings.prevent_copy =~# 'f' 5340c0734d5SBram Moolenaar if s:settings.use_input_for_pc ==# 'none' 5350c0734d5SBram Moolenaar " Simply space-pad to the desired width inside the generated content (note 5360c0734d5SBram Moolenaar " that the FoldColumn definition includes a whitespace:pre rule) 5370c0734d5SBram Moolenaar function! s:FoldColumn_build(char, len, numfill, char2, class, click) 5380c0734d5SBram Moolenaar return "<a href='#' class='".a:class."' onclick='".a:click."' data-FoldColumn-content='". 5390c0734d5SBram Moolenaar \ repeat(a:char, a:len).a:char2.repeat(' ', a:numfill). 5400c0734d5SBram Moolenaar \ "'></a>" 5410c0734d5SBram Moolenaar endfun 5420c0734d5SBram Moolenaar function! s:FoldColumn_fill() 5430c0734d5SBram Moolenaar return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, "", 1) 5440c0734d5SBram Moolenaar endfun 5450c0734d5SBram Moolenaar else 5466c35beaaSBram Moolenaar " Note the <input> elements for fill spaces will have a single space for 5476c35beaaSBram Moolenaar " content, to allow active cursor CSS selection to work. 5486c35beaaSBram Moolenaar " 5496c35beaaSBram Moolenaar " Wrap the whole thing in a span for the 1px padding workaround for gaps. 5500c0734d5SBram Moolenaar " 5510c0734d5SBram Moolenaar " Build the function line by line containing only what is needed for the 5520c0734d5SBram Moolenaar " options in use for maximum code sharing with minimal branch logic for 5530c0734d5SBram Moolenaar " greater speed. 5540c0734d5SBram Moolenaar " 5550c0734d5SBram Moolenaar " Note, 'exec' commands do not recognize line continuations, so must 5560c0734d5SBram Moolenaar " concatenate lines rather than continue them. 5570c0734d5SBram Moolenaar let build_fun_lines = [ 5580c0734d5SBram Moolenaar \ 'function! s:FoldColumn_build(char, len, numfill, char2, class, click)', 5590c0734d5SBram Moolenaar \ ' let l:input_open = "<input readonly=''readonly''".s:unselInputType.'. 5600c0734d5SBram Moolenaar \ ' " onselect=''this.blur(); return false;''".'. 5610c0734d5SBram Moolenaar \ ' " onmousedown=''this.blur(); ".a:click." return false;''".'. 5620c0734d5SBram Moolenaar \ ' " onclick=''return false;'' size=''".'. 5630c0734d5SBram Moolenaar \ ' string(a:len + (empty(a:char2) ? 0 : 1) + a:numfill) .'. 5640c0734d5SBram Moolenaar \ ' "'' "', 5650c0734d5SBram Moolenaar \ ' let l:common_attrs = "class=''FoldColumn'' value=''"', 5660c0734d5SBram Moolenaar \ ' let l:input_close = (s:settings.use_xhtml ? "'' />" : "''>")' 5670c0734d5SBram Moolenaar \ ] 5680c0734d5SBram Moolenaar if s:settings.use_input_for_pc ==# 'fallback' 5690c0734d5SBram Moolenaar let build_fun_lines += [ 5700c0734d5SBram Moolenaar \ ' let l:gen_content_link ='. 5710c0734d5SBram Moolenaar \ ' "<a href=''#'' class=''FoldColumn'' onclick=''".a:click."'' data-FoldColumn-content=''".'. 5720c0734d5SBram Moolenaar \ ' repeat(a:char, a:len).a:char2.repeat('' '', a:numfill).'. 5730c0734d5SBram Moolenaar \ ' "''></a>"' 5740c0734d5SBram Moolenaar \ ] 5750c0734d5SBram Moolenaar endif 5760c0734d5SBram Moolenaar let build_fun_lines += [ 5770c0734d5SBram Moolenaar \ ' return "<span class=''".a:class."''>".'. 5780c0734d5SBram Moolenaar \ ' l:input_open.l:common_attrs.repeat(a:char, a:len).(a:char2).'. 5790c0734d5SBram Moolenaar \ ' l:input_close.'. 5800c0734d5SBram Moolenaar \ (s:settings.use_input_for_pc ==# 'fallback' ? 'l:gen_content_link.' : ""). 5810c0734d5SBram Moolenaar \ ' "</span>"', 5820c0734d5SBram Moolenaar \ 'endfun' 5830c0734d5SBram Moolenaar \ ] 5840c0734d5SBram Moolenaar " create the function we built line by line above 5850c0734d5SBram Moolenaar exec join(build_fun_lines, "\n") 5860c0734d5SBram Moolenaar 5876c35beaaSBram Moolenaar function! s:FoldColumn_fill() 5886c35beaaSBram Moolenaar return s:FoldColumn_build(' ', s:foldcolumn, 0, '', 'FoldColumn', '') 5896c35beaaSBram Moolenaar endfun 5900c0734d5SBram Moolenaar endif 5916c35beaaSBram Moolenaarelse 5926c35beaaSBram Moolenaar " For normal fold columns, simply space-pad to the desired width (note that 5936c35beaaSBram Moolenaar " the FoldColumn definition includes a whitespace:pre rule) 5946c35beaaSBram Moolenaar function! s:FoldColumn_build(char, len, numfill, char2, class, click) 5956c35beaaSBram Moolenaar return "<a href='#' class='".a:class."' onclick='".a:click."'>". 5966c35beaaSBram Moolenaar \ repeat(a:char, a:len).a:char2.repeat(' ', a:numfill). 5976c35beaaSBram Moolenaar \ "</a>" 5986c35beaaSBram Moolenaar endfun 5996c35beaaSBram Moolenaar function! s:FoldColumn_fill() 600543b7ef7SBram Moolenaar return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, "", 0) 6016c35beaaSBram Moolenaar endfun 6026c35beaaSBram Moolenaarendif 6036c35beaaSBram Moolenaarif s:settings.prevent_copy =~# 't' 6046c35beaaSBram Moolenaar " put an extra empty span at the end for dynamic folds, so the linebreak can 6056c35beaaSBram Moolenaar " be surrounded. Otherwise do it as normal. 6066c35beaaSBram Moolenaar " 6076c35beaaSBram Moolenaar " TODO: isn't there a better way to do this, than placing it here and using a 6086c35beaaSBram Moolenaar " substitute later? 6096c35beaaSBram Moolenaar if s:settings.dynamic_folds 6106c35beaaSBram Moolenaar function! s:HtmlFormat_t(text, style_id, diff_style_id) 611543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) . 612543b7ef7SBram Moolenaar \ s:HtmlFormat("", a:style_id, 0, "", 0) 6136c35beaaSBram Moolenaar endfun 6146c35beaaSBram Moolenaar else 6156c35beaaSBram Moolenaar function! s:HtmlFormat_t(text, style_id, diff_style_id) 616543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) 6176c35beaaSBram Moolenaar endfun 6186c35beaaSBram Moolenaar endif 6196c35beaaSBram Moolenaarelse 6206c35beaaSBram Moolenaar function! s:HtmlFormat_t(text, style_id, diff_style_id) 621543b7ef7SBram Moolenaar return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0) 6226c35beaaSBram Moolenaar endfun 6236c35beaaSBram Moolenaarendif 6246c35beaaSBram Moolenaar 625071d4279SBram Moolenaar" Return CSS style describing given highlight id (can be empty) 626071d4279SBram Moolenaarfunction! s:CSS1(id) 627071d4279SBram Moolenaar let a = "" 628071d4279SBram Moolenaar if synIDattr(a:id, "inverse") 629071d4279SBram Moolenaar " For inverse, we always must set both colors (and exchange them) 630071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm)) 631071d4279SBram Moolenaar let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; " 632071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm)) 633071d4279SBram Moolenaar let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; " 634071d4279SBram Moolenaar else 635071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm)) 636071d4279SBram Moolenaar if x != "" | let a = a . "color: " . x . "; " | endif 637071d4279SBram Moolenaar let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm)) 6386c35beaaSBram Moolenaar if x != "" 6396c35beaaSBram Moolenaar let a = a . "background-color: " . x . "; " 6406c35beaaSBram Moolenaar " stupid hack because almost every browser seems to have at least one font 6416c35beaaSBram Moolenaar " which shows 1px gaps between lines which have background 6426c35beaaSBram Moolenaar let a = a . "padding-bottom: 1px; " 6436c35beaaSBram Moolenaar elseif (a:id == s:FOLDED_ID || a:id == s:LINENR_ID || a:id == s:FOLD_C_ID) && !empty(s:settings.prevent_copy) 6446c35beaaSBram Moolenaar " input elements default to a different color than the rest of the page 6456c35beaaSBram Moolenaar let a = a . "background-color: " . s:bgc . "; " 6466c35beaaSBram Moolenaar endif 647071d4279SBram Moolenaar endif 648071d4279SBram Moolenaar if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif 649071d4279SBram Moolenaar if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif 650071d4279SBram Moolenaar if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif 651071d4279SBram Moolenaar return a 652071d4279SBram Moolenaarendfun 653071d4279SBram Moolenaar 654076e8b2aSBram Moolenaarif s:settings.dynamic_folds 6555c73622aSBram Moolenaar " compares two folds as stored in our list of folds 6565c73622aSBram Moolenaar " A fold is "less" than another if it starts at an earlier line number, 6575c73622aSBram Moolenaar " or ends at a later line number, ties broken by fold level 6585c73622aSBram Moolenaar function! s:FoldCompare(f1, f2) 6595c73622aSBram Moolenaar if a:f1.firstline != a:f2.firstline 6605c73622aSBram Moolenaar " put it before if it starts earlier 6615c73622aSBram Moolenaar return a:f1.firstline - a:f2.firstline 6625c73622aSBram Moolenaar elseif a:f1.lastline != a:f2.lastline 6635c73622aSBram Moolenaar " put it before if it ends later 6645c73622aSBram Moolenaar return a:f2.lastline - a:f1.lastline 6655c73622aSBram Moolenaar else 6665c73622aSBram Moolenaar " if folds begin and end on the same lines, put lowest fold level first 6675c73622aSBram Moolenaar return a:f1.level - a:f2.level 6685c73622aSBram Moolenaar endif 6695c73622aSBram Moolenaar endfunction 6705c73622aSBram Moolenaar 6715c73622aSBram Moolenaarendif 6725c73622aSBram Moolenaar 673071d4279SBram Moolenaar 674071d4279SBram Moolenaar" Set some options to make it work faster. 675071d4279SBram Moolenaar" Don't report changes for :substitute, there will be many of them. 6768df7f888SBram Moolenaar" Don't change other windows; turn off scroll bind temporarily 677071d4279SBram Moolenaarlet s:old_title = &title 678071d4279SBram Moolenaarlet s:old_icon = &icon 679071d4279SBram Moolenaarlet s:old_et = &l:et 6808df7f888SBram Moolenaarlet s:old_bind = &l:scrollbind 681071d4279SBram Moolenaarlet s:old_report = &report 682071d4279SBram Moolenaarlet s:old_search = @/ 683349b2fb0SBram Moolenaarlet s:old_more = &more 684071d4279SBram Moolenaarset notitle noicon 685071d4279SBram Moolenaarsetlocal et 686349b2fb0SBram Moolenaarset nomore 687071d4279SBram Moolenaarset report=1000000 6888df7f888SBram Moolenaarsetlocal noscrollbind 689071d4279SBram Moolenaar 6907510fe74SBram Moolenaarif exists(':ownsyntax') && exists('w:current_syntax') 6917510fe74SBram Moolenaar let s:current_syntax = w:current_syntax 6927510fe74SBram Moolenaarelseif exists('b:current_syntax') 6937510fe74SBram Moolenaar let s:current_syntax = b:current_syntax 6947510fe74SBram Moolenaarelse 6957510fe74SBram Moolenaar let s:current_syntax = 'none' 6967510fe74SBram Moolenaarendif 6977510fe74SBram Moolenaar 6987510fe74SBram Moolenaarif s:current_syntax == '' 6997510fe74SBram Moolenaar let s:current_syntax = 'none' 7007510fe74SBram Moolenaarendif 7017510fe74SBram Moolenaar 702f0d58efcSBram Moolenaar" If the user is sourcing this script directly then the plugin version isn't 703f0d58efcSBram Moolenaar" known because the main plugin script didn't load. In the usual case where the 704f0d58efcSBram Moolenaar" user still has the full Vim runtime installed, or has this full plugin 705f0d58efcSBram Moolenaar" installed in a package or something, then we can extract the version from the 706f0d58efcSBram Moolenaar" main plugin file at it's usual spot relative to this file. Otherwise the user 707f0d58efcSBram Moolenaar" is assembling their runtime piecemeal and we have no idea what versions of 708f0d58efcSBram Moolenaar" other files may be present so don't even try to make a guess or assume the 709f0d58efcSBram Moolenaar" presence of other specific files with specific meaning. 710f0d58efcSBram Moolenaar" 711f0d58efcSBram Moolenaar" We don't want to actually source the main plugin file here because the user 712f0d58efcSBram Moolenaar" may have a good reason not to (e.g. they define their own TOhtml command or 713f0d58efcSBram Moolenaar" something). 714f0d58efcSBram Moolenaar" 715f0d58efcSBram Moolenaar" If this seems way too complicated and convoluted, it is. Probably I should 716f0d58efcSBram Moolenaar" have put the version information in the autoload file from the start. But the 717f0d58efcSBram Moolenaar" version has been in the global variable for so long that changing it could 718f0d58efcSBram Moolenaar" break a lot of user scripts. 719f0d58efcSBram Moolenaarif exists("g:loaded_2html_plugin") 720f0d58efcSBram Moolenaar let s:pluginversion = g:loaded_2html_plugin 721f0d58efcSBram Moolenaarelse 722f0d58efcSBram Moolenaar if !exists("g:unloaded_tohtml_plugin") 723f0d58efcSBram Moolenaar let s:main_plugin_path = expand("<sfile>:p:h:h")."/plugin/tohtml.vim" 724f0d58efcSBram Moolenaar if filereadable(s:main_plugin_path) 725f0d58efcSBram Moolenaar let s:lines = readfile(s:main_plugin_path, "", 20) 726f0d58efcSBram Moolenaar call filter(s:lines, 'v:val =~ "loaded_2html_plugin = "') 727f0d58efcSBram Moolenaar if empty(s:lines) 728f0d58efcSBram Moolenaar let g:unloaded_tohtml_plugin = "unknown" 729f0d58efcSBram Moolenaar else 730f0d58efcSBram Moolenaar let g:unloaded_tohtml_plugin = substitute(s:lines[0], '.*loaded_2html_plugin = \([''"]\)\(\%(\1\@!.\)\+\)\1', '\2', '') 731f0d58efcSBram Moolenaar endif 732f0d58efcSBram Moolenaar unlet s:lines 733f0d58efcSBram Moolenaar else 734f0d58efcSBram Moolenaar let g:unloaded_tohtml_plugin = "unknown" 735f0d58efcSBram Moolenaar endif 736f0d58efcSBram Moolenaar unlet s:main_plugin_path 737f0d58efcSBram Moolenaar endif 738f0d58efcSBram Moolenaar let s:pluginversion = g:unloaded_tohtml_plugin 739f0d58efcSBram Moolenaarendif 740f0d58efcSBram Moolenaar 741071d4279SBram Moolenaar" Split window to create a buffer with the HTML file. 742071d4279SBram Moolenaarlet s:orgbufnr = winbufnr(0) 743349b2fb0SBram Moolenaarlet s:origwin_stl = &l:stl 744071d4279SBram Moolenaarif expand("%") == "" 745543b7ef7SBram Moolenaar if exists('g:html_diff_win_num') 746543b7ef7SBram Moolenaar exec 'new Untitled_win'.g:html_diff_win_num.'.'.(s:settings.use_xhtml ? 'x' : '').'html' 747543b7ef7SBram Moolenaar else 748076e8b2aSBram Moolenaar exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html' 749543b7ef7SBram Moolenaar endif 750071d4279SBram Moolenaarelse 751076e8b2aSBram Moolenaar exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html' 752071d4279SBram Moolenaarendif 753349b2fb0SBram Moolenaar 754349b2fb0SBram Moolenaar" Resize the new window to very small in order to make it draw faster 755349b2fb0SBram Moolenaarlet s:old_winheight = winheight(0) 756349b2fb0SBram Moolenaarlet s:old_winfixheight = &l:winfixheight 757349b2fb0SBram Moolenaarif s:old_winheight > 2 758349b2fb0SBram Moolenaar resize 1 " leave enough room to view one line at a time 759349b2fb0SBram Moolenaar norm! G 760349b2fb0SBram Moolenaar norm! zt 761349b2fb0SBram Moolenaarendif 762349b2fb0SBram Moolenaarsetlocal winfixheight 763349b2fb0SBram Moolenaar 764349b2fb0SBram Moolenaarlet s:newwin_stl = &l:stl 765349b2fb0SBram Moolenaar 766349b2fb0SBram Moolenaar" on the new window, set the least time-consuming fold method 7678df7f888SBram Moolenaarlet s:old_fen = &foldenable 768349b2fb0SBram Moolenaarsetlocal foldmethod=manual 7698df7f888SBram Moolenaarsetlocal nofoldenable 770349b2fb0SBram Moolenaar 771071d4279SBram Moolenaarlet s:newwin = winnr() 772071d4279SBram Moolenaarlet s:orgwin = bufwinnr(s:orgbufnr) 773071d4279SBram Moolenaar 774349b2fb0SBram Moolenaarsetlocal modifiable 775071d4279SBram Moolenaar%d 776071d4279SBram Moolenaarlet s:old_paste = &paste 777071d4279SBram Moolenaarset paste 778071d4279SBram Moolenaarlet s:old_magic = &magic 779071d4279SBram Moolenaarset magic 780071d4279SBram Moolenaar 781166af9bbSBram Moolenaar" set the fileencoding to match the charset we'll be using 782166af9bbSBram Moolenaarlet &l:fileencoding=s:settings.vim_encoding 783166af9bbSBram Moolenaar 784166af9bbSBram Moolenaar" According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte 785166af9bbSBram Moolenaar" order mark is highly recommend on the web when using multibyte encodings. But, 786166af9bbSBram Moolenaar" it is not a good idea to include it on UTF-8 files. Otherwise, let Vim 787166af9bbSBram Moolenaar" determine when it is actually inserted. 788166af9bbSBram Moolenaarif s:settings.vim_encoding == 'utf-8' 789166af9bbSBram Moolenaar setlocal nobomb 790166af9bbSBram Moolenaarelse 791166af9bbSBram Moolenaar setlocal bomb 792166af9bbSBram Moolenaarendif 793166af9bbSBram Moolenaar 794349b2fb0SBram Moolenaarlet s:lines = [] 795349b2fb0SBram Moolenaar 796076e8b2aSBram Moolenaarif s:settings.use_xhtml 797bebca9daSBram Moolenaar if s:settings.encoding != "" 798bebca9daSBram Moolenaar call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>") 7991cd871b5SBram Moolenaar else 800349b2fb0SBram Moolenaar call add(s:lines, "<?xml version=\"1.0\"?>") 8011cd871b5SBram Moolenaar endif 80235a9aaabSBram Moolenaar let s:tag_close = ' />' 803071d4279SBram Moolenaarelse 80435a9aaabSBram Moolenaar let s:tag_close = '>' 80535a9aaabSBram Moolenaarendif 80635a9aaabSBram Moolenaar 80735a9aaabSBram Moolenaarlet s:HtmlSpace = ' ' 808c1e37901SBram Moolenaarlet s:LeadingSpace = ' ' 80935a9aaabSBram Moolenaarlet s:HtmlEndline = '' 810076e8b2aSBram Moolenaarif s:settings.no_pre 81135a9aaabSBram Moolenaar let s:HtmlEndline = '<br' . s:tag_close 812543b7ef7SBram Moolenaar let s:LeadingSpace = s:settings.use_xhtml ? ' ' : ' ' 813c1e37901SBram Moolenaar let s:HtmlSpace = '\' . s:LeadingSpace 814071d4279SBram Moolenaarendif 815071d4279SBram Moolenaar 816071d4279SBram Moolenaar" HTML header, with the title and generator ;-). Left free space for the CSS, 817071d4279SBram Moolenaar" to be filled at the end. 818349b2fb0SBram Moolenaarcall extend(s:lines, [ 819349b2fb0SBram Moolenaar \ "<html>", 820bebca9daSBram Moolenaar \ "<head>"]) 821bebca9daSBram Moolenaar" include encoding as close to the top as possible, but only if not already 822bebca9daSBram Moolenaar" contained in XML information (to avoid haggling over content type) 823bebca9daSBram Moolenaarif s:settings.encoding != "" && !s:settings.use_xhtml 8240c0734d5SBram Moolenaar if s:html5 8250c0734d5SBram Moolenaar call add(s:lines, '<meta charset="' . s:settings.encoding . '"' . s:tag_close) 8260c0734d5SBram Moolenaar else 827bebca9daSBram Moolenaar call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close) 828bebca9daSBram Moolenaar endif 8290c0734d5SBram Moolenaarendif 830bebca9daSBram Moolenaarcall extend(s:lines, [ 831349b2fb0SBram Moolenaar \ ("<title>".expand("%:p:~")."</title>"), 832349b2fb0SBram Moolenaar \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close), 833f0d58efcSBram Moolenaar \ ("<meta name=\"plugin-version\" content=\"".s:pluginversion.'"'.s:tag_close) 834349b2fb0SBram Moolenaar \ ]) 8357510fe74SBram Moolenaarcall add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close) 836076e8b2aSBram Moolenaarcall add(s:lines, '<meta name="settings" content="'. 837076e8b2aSBram Moolenaar \ join(filter(keys(s:settings),'s:settings[v:val]'),','). 8386c35beaaSBram Moolenaar \ ',prevent_copy='.s:settings.prevent_copy. 8390c0734d5SBram Moolenaar \ ',use_input_for_pc='.s:settings.use_input_for_pc. 840076e8b2aSBram Moolenaar \ '"'.s:tag_close) 8416c35beaaSBram Moolenaarcall add(s:lines, '<meta name="colorscheme" content="'. 8426c35beaaSBram Moolenaar \ (exists('g:colors_name') 8436c35beaaSBram Moolenaar \ ? g:colors_name 8446c35beaaSBram Moolenaar \ : 'none'). '"'.s:tag_close) 845313b7237SBram Moolenaar 846076e8b2aSBram Moolenaarif s:settings.use_css 8470c0734d5SBram Moolenaar call extend(s:lines, [ 8480c0734d5SBram Moolenaar \ "<style" . (s:html5 ? "" : " type=\"text/css\"") . ">", 8490c0734d5SBram Moolenaar \ s:settings.use_xhtml ? "" : "<!--"]) 8500c0734d5SBram Moolenaar let s:ieonly = [] 851076e8b2aSBram Moolenaar if s:settings.dynamic_folds 852076e8b2aSBram Moolenaar if s:settings.hover_unfold 8535c73622aSBram Moolenaar " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6 854349b2fb0SBram Moolenaar call extend(s:lines, [ 855349b2fb0SBram Moolenaar \ ".FoldColumn { text-decoration: none; white-space: pre; }", 856349b2fb0SBram Moolenaar \ "", 857349b2fb0SBram Moolenaar \ "body * { margin: 0; padding: 0; }", "", 8580c0734d5SBram Moolenaar \ ".open-fold > span.Folded { display: none; }", 859349b2fb0SBram Moolenaar \ ".open-fold > .fulltext { display: inline; }", 860349b2fb0SBram Moolenaar \ ".closed-fold > .fulltext { display: none; }", 8610c0734d5SBram Moolenaar \ ".closed-fold > span.Folded { display: inline; }", 862349b2fb0SBram Moolenaar \ "", 863349b2fb0SBram Moolenaar \ ".open-fold > .toggle-open { display: none; }", 864349b2fb0SBram Moolenaar \ ".open-fold > .toggle-closed { display: inline; }", 865349b2fb0SBram Moolenaar \ ".closed-fold > .toggle-open { display: inline; }", 866349b2fb0SBram Moolenaar \ ".closed-fold > .toggle-closed { display: none; }", 867349b2fb0SBram Moolenaar \ "", "", 868349b2fb0SBram Moolenaar \ '/* opening a fold while hovering won''t be supported by IE6 and other', 869349b2fb0SBram Moolenaar \ "similar browsers, but it should fail gracefully. */", 870349b2fb0SBram Moolenaar \ ".closed-fold:hover > .fulltext { display: inline; }", 871349b2fb0SBram Moolenaar \ ".closed-fold:hover > .toggle-filler { display: none; }", 8720c0734d5SBram Moolenaar \ ".closed-fold:hover > .Folded { display: none; }"]) 8730c0734d5SBram Moolenaar " TODO: IE6 is REALLY old and I can't even test it anymore. Maybe we 8740c0734d5SBram Moolenaar " should remove this? Leave it in for now, it was working at one point, 8750c0734d5SBram Moolenaar " and doesn't affect any modern browsers. Even newer IE versions should 8760c0734d5SBram Moolenaar " support the above code and ignore the following. 8770c0734d5SBram Moolenaar let s:ieonly = [ 878349b2fb0SBram Moolenaar \ "<!--[if lt IE 7]><style type=\"text/css\">", 879349b2fb0SBram Moolenaar \ ".open-fold .fulltext { display: inline; }", 8800c0734d5SBram Moolenaar \ ".open-fold span.Folded { display: none; }", 881349b2fb0SBram Moolenaar \ ".open-fold .toggle-open { display: none; }", 8820c0734d5SBram Moolenaar \ ".open-fold .toggle-closed { display: inline; }", 883349b2fb0SBram Moolenaar \ "", 884349b2fb0SBram Moolenaar \ ".closed-fold .fulltext { display: none; }", 8850c0734d5SBram Moolenaar \ ".closed-fold span.Folded { display: inline; }", 886349b2fb0SBram Moolenaar \ ".closed-fold .toggle-open { display: inline; }", 887349b2fb0SBram Moolenaar \ ".closed-fold .toggle-closed { display: none; }", 888349b2fb0SBram Moolenaar \ "</style>", 889349b2fb0SBram Moolenaar \ "<![endif]-->", 8900c0734d5SBram Moolenaar \] 8915c73622aSBram Moolenaar else 8925c73622aSBram Moolenaar " if we aren't doing hover_unfold, use CSS 1 only 893349b2fb0SBram Moolenaar call extend(s:lines, [ 894349b2fb0SBram Moolenaar \ ".FoldColumn { text-decoration: none; white-space: pre; }", 895349b2fb0SBram Moolenaar \ ".open-fold .fulltext { display: inline; }", 8960c0734d5SBram Moolenaar \ ".open-fold span.Folded { display: none; }", 897349b2fb0SBram Moolenaar \ ".open-fold .toggle-open { display: none; }", 8980c0734d5SBram Moolenaar \ ".open-fold .toggle-closed { display: inline; }", 899349b2fb0SBram Moolenaar \ "", 900349b2fb0SBram Moolenaar \ ".closed-fold .fulltext { display: none; }", 9010c0734d5SBram Moolenaar \ ".closed-fold span.Folded { display: inline; }", 902349b2fb0SBram Moolenaar \ ".closed-fold .toggle-open { display: inline; }", 903349b2fb0SBram Moolenaar \ ".closed-fold .toggle-closed { display: none; }", 904349b2fb0SBram Moolenaar \]) 9055c73622aSBram Moolenaar endif 9060c0734d5SBram Moolenaar endif 9070c0734d5SBram Moolenaar " else we aren't doing any dynamic folding, no need for any special rules 9080c0734d5SBram Moolenaar 909349b2fb0SBram Moolenaar call extend(s:lines, [ 910bebca9daSBram Moolenaar \ s:settings.use_xhtml ? "" : '-->', 911349b2fb0SBram Moolenaar \ "</style>", 912349b2fb0SBram Moolenaar \]) 9130c0734d5SBram Moolenaar call extend(s:lines, s:ieonly) 9140c0734d5SBram Moolenaar unlet s:ieonly 9155c73622aSBram Moolenaarendif 9165c73622aSBram Moolenaar 9170c0734d5SBram Moolenaarlet s:uses_script = s:settings.dynamic_folds || s:settings.line_ids 918f0d58efcSBram Moolenaar 919f0d58efcSBram Moolenaar" insert script tag if needed 920f0d58efcSBram Moolenaarif s:uses_script 9216c35beaaSBram Moolenaar call extend(s:lines, [ 9226c35beaaSBram Moolenaar \ "", 9230c0734d5SBram Moolenaar \ "<script" . (s:html5 ? "" : " type='text/javascript'") . ">", 9246c35beaaSBram Moolenaar \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"]) 925f0d58efcSBram Moolenaarendif 9266c35beaaSBram Moolenaar 9275c73622aSBram Moolenaar" insert javascript to toggle folds open and closed 928076e8b2aSBram Moolenaarif s:settings.dynamic_folds 929349b2fb0SBram Moolenaar call extend(s:lines, [ 930349b2fb0SBram Moolenaar \ "", 931349b2fb0SBram Moolenaar \ "function toggleFold(objID)", 932349b2fb0SBram Moolenaar \ "{", 933349b2fb0SBram Moolenaar \ " var fold;", 934349b2fb0SBram Moolenaar \ " fold = document.getElementById(objID);", 935349b2fb0SBram Moolenaar \ " if (fold.className == 'closed-fold')", 936349b2fb0SBram Moolenaar \ " {", 937349b2fb0SBram Moolenaar \ " fold.className = 'open-fold';", 938349b2fb0SBram Moolenaar \ " }", 939349b2fb0SBram Moolenaar \ " else if (fold.className == 'open-fold')", 940349b2fb0SBram Moolenaar \ " {", 941349b2fb0SBram Moolenaar \ " fold.className = 'closed-fold';", 942349b2fb0SBram Moolenaar \ " }", 9436c35beaaSBram Moolenaar \ "}" 9446c35beaaSBram Moolenaar \ ]) 9456c35beaaSBram Moolenaarendif 9466c35beaaSBram Moolenaar 94731c31679SBram Moolenaarif s:settings.line_ids 948543b7ef7SBram Moolenaar " insert javascript to get IDs from line numbers, and to open a fold before 949543b7ef7SBram Moolenaar " jumping to any lines contained therein 950543b7ef7SBram Moolenaar call extend(s:lines, [ 951543b7ef7SBram Moolenaar \ "", 952543b7ef7SBram Moolenaar \ "/* function to open any folds containing a jumped-to line before jumping to it */", 953543b7ef7SBram Moolenaar \ "function JumpToLine()", 954543b7ef7SBram Moolenaar \ "{", 955543b7ef7SBram Moolenaar \ " var lineNum;", 956543b7ef7SBram Moolenaar \ " lineNum = window.location.hash;", 957543b7ef7SBram Moolenaar \ " lineNum = lineNum.substr(1); /* strip off '#' */", 958543b7ef7SBram Moolenaar \ "", 959543b7ef7SBram Moolenaar \ " if (lineNum.indexOf('L') == -1) {", 960543b7ef7SBram Moolenaar \ " lineNum = 'L'+lineNum;", 961543b7ef7SBram Moolenaar \ " }", 962f0d58efcSBram Moolenaar \ " var lineElem = document.getElementById(lineNum);" 963543b7ef7SBram Moolenaar \ ]) 964f0d58efcSBram Moolenaar 965543b7ef7SBram Moolenaar if s:settings.dynamic_folds 966543b7ef7SBram Moolenaar call extend(s:lines, [ 967543b7ef7SBram Moolenaar \ "", 968543b7ef7SBram Moolenaar \ " /* navigate upwards in the DOM tree to open all folds containing the line */", 969543b7ef7SBram Moolenaar \ " var node = lineElem;", 97031c31679SBram Moolenaar \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')", 971543b7ef7SBram Moolenaar \ " {", 972543b7ef7SBram Moolenaar \ " if (node.className == 'closed-fold')", 973543b7ef7SBram Moolenaar \ " {", 974543b7ef7SBram Moolenaar \ " node.className = 'open-fold';", 975543b7ef7SBram Moolenaar \ " }", 976543b7ef7SBram Moolenaar \ " node = node.parentNode;", 977543b7ef7SBram Moolenaar \ " }", 978543b7ef7SBram Moolenaar \ ]) 979543b7ef7SBram Moolenaar endif 980543b7ef7SBram Moolenaar call extend(s:lines, [ 981543b7ef7SBram Moolenaar \ " /* Always jump to new location even if the line was hidden inside a fold, or", 982543b7ef7SBram Moolenaar \ " * we corrected the raw number to a line ID.", 983543b7ef7SBram Moolenaar \ " */", 984543b7ef7SBram Moolenaar \ " if (lineElem) {", 985543b7ef7SBram Moolenaar \ " lineElem.scrollIntoView(true);", 986543b7ef7SBram Moolenaar \ " }", 987543b7ef7SBram Moolenaar \ " return true;", 988543b7ef7SBram Moolenaar \ "}", 989543b7ef7SBram Moolenaar \ "if ('onhashchange' in window) {", 990543b7ef7SBram Moolenaar \ " window.onhashchange = JumpToLine;", 991543b7ef7SBram Moolenaar \ "}" 992543b7ef7SBram Moolenaar \ ]) 99331c31679SBram Moolenaarendif 994543b7ef7SBram Moolenaar 995f0d58efcSBram Moolenaar" insert script closing tag if needed 996f0d58efcSBram Moolenaarif s:uses_script 9976c35beaaSBram Moolenaar call extend(s:lines, [ 9986c35beaaSBram Moolenaar \ '', 999bebca9daSBram Moolenaar \ s:settings.use_xhtml ? '//]]>' : '-->', 1000349b2fb0SBram Moolenaar \ "</script>" 1001349b2fb0SBram Moolenaar \ ]) 1002f0d58efcSBram Moolenaarendif 10035c73622aSBram Moolenaar 10040c0734d5SBram Moolenaarcall extend(s:lines, ["</head>", 10050c0734d5SBram Moolenaar \ "<body".(s:settings.line_ids ? " onload='JumpToLine();'" : "").">"]) 10060c0734d5SBram Moolenaar 10076c35beaaSBram Moolenaarif s:settings.no_pre 10086c35beaaSBram Moolenaar " if we're not using CSS we use a font tag which can't have a div inside 10096c35beaaSBram Moolenaar if s:settings.use_css 101031c31679SBram Moolenaar call extend(s:lines, ["<div id='vimCodeElement".s:settings.id_suffix."'>"]) 10116c35beaaSBram Moolenaar endif 10126c35beaaSBram Moolenaarelse 101331c31679SBram Moolenaar call extend(s:lines, ["<pre id='vimCodeElement".s:settings.id_suffix."'>"]) 1014071d4279SBram Moolenaarendif 1015071d4279SBram Moolenaar 1016071d4279SBram Moolenaarexe s:orgwin . "wincmd w" 1017071d4279SBram Moolenaar 10186c35beaaSBram Moolenaar" caches of style data 10196c35beaaSBram Moolenaar" initialize to include line numbers if using them 10206c35beaaSBram Moolenaarif s:settings.number_lines 10216c35beaaSBram Moolenaar let s:stylelist = { s:LINENR_ID : ".LineNr { " . s:CSS1( s:LINENR_ID ) . "}" } 10226c35beaaSBram Moolenaarelse 10236c35beaaSBram Moolenaar let s:stylelist = {} 10246c35beaaSBram Moolenaarendif 10256c35beaaSBram Moolenaarlet s:diffstylelist = { 10266c35beaaSBram Moolenaar \ s:DIFF_A_ID : ".DiffAdd { " . s:CSS1( s:DIFF_A_ID ) . "}", 10276c35beaaSBram Moolenaar \ s:DIFF_C_ID : ".DiffChange { " . s:CSS1( s:DIFF_C_ID ) . "}", 10286c35beaaSBram Moolenaar \ s:DIFF_D_ID : ".DiffDelete { " . s:CSS1( s:DIFF_D_ID ) . "}", 10296c35beaaSBram Moolenaar \ s:DIFF_T_ID : ".DiffText { " . s:CSS1( s:DIFF_T_ID ) . "}" 10306c35beaaSBram Moolenaar \ } 1031071d4279SBram Moolenaar 1032349b2fb0SBram Moolenaar" set up progress bar in the status line 1033076e8b2aSBram Moolenaarif !s:settings.no_progress 1034349b2fb0SBram Moolenaar " ProgressBar Indicator 1035349b2fb0SBram Moolenaar let s:progressbar={} 1036349b2fb0SBram Moolenaar 1037*6c391a74SBram Moolenaar " Progressbar specific functions 10380c0734d5SBram Moolenaar 10390c0734d5SBram Moolenaar func! s:SetProgbarColor() 10400c0734d5SBram Moolenaar if hlID("TOhtmlProgress") != 0 10410c0734d5SBram Moolenaar hi! link TOhtmlProgress_auto TOhtmlProgress 10420c0734d5SBram Moolenaar elseif hlID("TOhtmlProgress_auto")==0 || 10430c0734d5SBram Moolenaar \ !exists("s:last_colors_name") || !exists("g:colors_name") || 10440c0734d5SBram Moolenaar \ g:colors_name != s:last_colors_name 10450c0734d5SBram Moolenaar let s:last_colors_name = exists("g:colors_name") ? g:colors_name : "none" 10460c0734d5SBram Moolenaar 10470c0734d5SBram Moolenaar let l:diffatr = synIDattr(hlID("DiffDelete"), "reverse", s:whatterm) ? "fg#" : "bg#" 10480c0734d5SBram Moolenaar let l:stlatr = synIDattr(hlID("StatusLine"), "reverse", s:whatterm) ? "fg#" : "bg#" 10490c0734d5SBram Moolenaar 10500c0734d5SBram Moolenaar let l:progbar_color = synIDattr(hlID("DiffDelete"), l:diffatr, s:whatterm) 10510c0734d5SBram Moolenaar let l:stl_color = synIDattr(hlID("StatusLine"), l:stlatr, s:whatterm) 10520c0734d5SBram Moolenaar 10530c0734d5SBram Moolenaar if "" == l:progbar_color 10540c0734d5SBram Moolenaar let l:progbar_color = synIDattr(hlID("DiffDelete"), "reverse", s:whatterm) ? s:fgc : s:bgc 10550c0734d5SBram Moolenaar endif 10560c0734d5SBram Moolenaar if "" == l:stl_color 10570c0734d5SBram Moolenaar let l:stl_color = synIDattr(hlID("StatusLine"), "reverse", s:whatterm) ? s:fgc : s:bgc 10580c0734d5SBram Moolenaar endif 10590c0734d5SBram Moolenaar 10600c0734d5SBram Moolenaar if l:progbar_color == l:stl_color 10610c0734d5SBram Moolenaar if s:whatterm == 'cterm' 10620c0734d5SBram Moolenaar if l:progbar_color >= (&t_Co/2) 10630c0734d5SBram Moolenaar let l:progbar_color-=1 10640c0734d5SBram Moolenaar else 10650c0734d5SBram Moolenaar let l:progbar_color+=1 10660c0734d5SBram Moolenaar endif 10670c0734d5SBram Moolenaar else 10680c0734d5SBram Moolenaar let l:rgb = map(matchlist(l:progbar_color, '#\zs\x\x\ze\(\x\x\)\(\x\x\)')[:2], 'str2nr(v:val, 16)') 10690c0734d5SBram Moolenaar let l:avg = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3 10700c0734d5SBram Moolenaar if l:avg >= 128 10710c0734d5SBram Moolenaar let l:avg_new = l:avg 10720c0734d5SBram Moolenaar while l:avg - l:avg_new < 0x15 10730c0734d5SBram Moolenaar let l:rgb = map(l:rgb, 'v:val * 3 / 4') 10740c0734d5SBram Moolenaar let l:avg_new = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3 10750c0734d5SBram Moolenaar endwhile 10760c0734d5SBram Moolenaar else 10770c0734d5SBram Moolenaar let l:avg_new = l:avg 10780c0734d5SBram Moolenaar while l:avg_new - l:avg < 0x15 10790c0734d5SBram Moolenaar let l:rgb = map(l:rgb, 'min([max([v:val, 4]) * 5 / 4, 255])') 10800c0734d5SBram Moolenaar let l:avg_new = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3 10810c0734d5SBram Moolenaar endwhile 10820c0734d5SBram Moolenaar endif 10830c0734d5SBram Moolenaar let l:progbar_color = printf("#%02x%02x%02x", l:rgb[0], l:rgb[1], l:rgb[2]) 10840c0734d5SBram Moolenaar endif 10850c0734d5SBram Moolenaar echomsg "diff detected progbar color set to" l:progbar_color 10860c0734d5SBram Moolenaar endif 10870c0734d5SBram Moolenaar exe "hi TOhtmlProgress_auto" s:whatterm."bg=".l:progbar_color 10880c0734d5SBram Moolenaar endif 10890c0734d5SBram Moolenaar endfun 10900c0734d5SBram Moolenaar 1091349b2fb0SBram Moolenaar func! s:ProgressBar(title, max_value, winnr) 1092349b2fb0SBram Moolenaar let pgb=copy(s:progressbar) 1093349b2fb0SBram Moolenaar let pgb.title = a:title.' ' 1094349b2fb0SBram Moolenaar let pgb.max_value = a:max_value 1095349b2fb0SBram Moolenaar let pgb.winnr = a:winnr 1096349b2fb0SBram Moolenaar let pgb.cur_value = 0 10970c0734d5SBram Moolenaar 1098349b2fb0SBram Moolenaar let pgb.items = { 'title' : { 'color' : 'Statusline' }, 10990c0734d5SBram Moolenaar \'bar' : { 'color' : 'Statusline' , 'fillcolor' : 'TOhtmlProgress_auto' , 'bg' : 'Statusline' } , 1100349b2fb0SBram Moolenaar \'counter' : { 'color' : 'Statusline' } } 1101349b2fb0SBram Moolenaar let pgb.last_value = 0 1102349b2fb0SBram Moolenaar let pgb.needs_redraw = 0 1103349b2fb0SBram Moolenaar " Note that you must use len(split) instead of len() if you want to use 1104349b2fb0SBram Moolenaar " unicode in title. 1105349b2fb0SBram Moolenaar " 1106349b2fb0SBram Moolenaar " Subtract 3 for spacing around the title. 1107349b2fb0SBram Moolenaar " Subtract 4 for the percentage display. 1108349b2fb0SBram Moolenaar " Subtract 2 for spacing before this. 1109349b2fb0SBram Moolenaar " Subtract 2 more for the '|' on either side of the progress bar 1110349b2fb0SBram Moolenaar let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2 1111349b2fb0SBram Moolenaar let pgb.max_len = 0 1112349b2fb0SBram Moolenaar set laststatus=2 1113349b2fb0SBram Moolenaar return pgb 1114349b2fb0SBram Moolenaar endfun 1115349b2fb0SBram Moolenaar 1116349b2fb0SBram Moolenaar " Function: progressbar.calculate_ticks() {{{1 1117349b2fb0SBram Moolenaar func! s:progressbar.calculate_ticks(pb_len) 1118349b2fb0SBram Moolenaar if a:pb_len<=0 1119349b2fb0SBram Moolenaar let pb_len = 100 1120349b2fb0SBram Moolenaar else 1121349b2fb0SBram Moolenaar let pb_len = a:pb_len 1122349b2fb0SBram Moolenaar endif 1123349b2fb0SBram Moolenaar let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len") 1124349b2fb0SBram Moolenaar endfun 1125349b2fb0SBram Moolenaar 1126349b2fb0SBram Moolenaar "Function: progressbar.paint() 1127349b2fb0SBram Moolenaar func! s:progressbar.paint() 1128349b2fb0SBram Moolenaar " Recalculate widths. 1129349b2fb0SBram Moolenaar let max_len = winwidth(self.winnr) 1130349b2fb0SBram Moolenaar let pb_len = 0 1131349b2fb0SBram Moolenaar " always true on first call because of initial value of self.max_len 1132349b2fb0SBram Moolenaar if max_len != self.max_len 1133349b2fb0SBram Moolenaar let self.max_len = max_len 1134349b2fb0SBram Moolenaar 1135349b2fb0SBram Moolenaar " Progressbar length 1136349b2fb0SBram Moolenaar let pb_len = max_len - self.subtractedlen 1137349b2fb0SBram Moolenaar 1138349b2fb0SBram Moolenaar call self.calculate_ticks(pb_len) 1139349b2fb0SBram Moolenaar 1140349b2fb0SBram Moolenaar let self.needs_redraw = 1 1141349b2fb0SBram Moolenaar let cur_value = 0 1142349b2fb0SBram Moolenaar let self.pb_len = pb_len 1143349b2fb0SBram Moolenaar else 1144349b2fb0SBram Moolenaar " start searching at the last found index to make the search for the 1145349b2fb0SBram Moolenaar " appropriate tick value normally take 0 or 1 comparisons 1146349b2fb0SBram Moolenaar let cur_value = self.last_value 1147349b2fb0SBram Moolenaar let pb_len = self.pb_len 1148349b2fb0SBram Moolenaar endif 1149349b2fb0SBram Moolenaar 1150349b2fb0SBram Moolenaar let cur_val_max = pb_len > 0 ? pb_len : 100 1151349b2fb0SBram Moolenaar 1152349b2fb0SBram Moolenaar " find the current progress bar position based on precalculated thresholds 1153349b2fb0SBram Moolenaar while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value] 1154349b2fb0SBram Moolenaar let cur_value += 1 1155349b2fb0SBram Moolenaar endwhile 1156349b2fb0SBram Moolenaar 1157349b2fb0SBram Moolenaar " update progress bar 1158349b2fb0SBram Moolenaar if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value 1159349b2fb0SBram Moolenaar let self.needs_redraw = 1 1160349b2fb0SBram Moolenaar let self.last_value = cur_value 1161349b2fb0SBram Moolenaar 1162349b2fb0SBram Moolenaar let t_color = self.items.title.color 1163349b2fb0SBram Moolenaar let b_fcolor = self.items.bar.fillcolor 1164349b2fb0SBram Moolenaar let b_color = self.items.bar.color 1165349b2fb0SBram Moolenaar let c_color = self.items.counter.color 1166349b2fb0SBram Moolenaar 1167349b2fb0SBram Moolenaar let stl = "%#".t_color."#%-( ".self.title." %)". 1168349b2fb0SBram Moolenaar \"%#".b_color."#". 1169349b2fb0SBram Moolenaar \(pb_len>0 ? 1170349b2fb0SBram Moolenaar \ ('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)". 1171349b2fb0SBram Moolenaar \ '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"): 1172349b2fb0SBram Moolenaar \ ('')). 1173349b2fb0SBram Moolenaar \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)" 1174349b2fb0SBram Moolenaar call setwinvar(self.winnr, '&stl', stl) 1175349b2fb0SBram Moolenaar endif 1176349b2fb0SBram Moolenaar endfun 1177349b2fb0SBram Moolenaar 1178349b2fb0SBram Moolenaar func! s:progressbar.incr( ... ) 1179349b2fb0SBram Moolenaar let self.cur_value += (a:0 ? a:1 : 1) 1180349b2fb0SBram Moolenaar " if we were making a general-purpose progress bar, we'd need to limit to a 1181349b2fb0SBram Moolenaar " lower limit as well, but since we always increment with a positive value 1182349b2fb0SBram Moolenaar " in this script, we only need limit the upper value 1183349b2fb0SBram Moolenaar let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value) 1184349b2fb0SBram Moolenaar call self.paint() 1185349b2fb0SBram Moolenaar endfun 1186349b2fb0SBram Moolenaar " }}} 1187076e8b2aSBram Moolenaar if s:settings.dynamic_folds 1188349b2fb0SBram Moolenaar " to process folds we make two passes through each line 1189349b2fb0SBram Moolenaar let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin) 1190349b2fb0SBram Moolenaar endif 11910c0734d5SBram Moolenaar 11920c0734d5SBram Moolenaar call s:SetProgbarColor() 1193349b2fb0SBram Moolenaarendif 1194349b2fb0SBram Moolenaar 11955c73622aSBram Moolenaar" First do some preprocessing for dynamic folding. Do this for the entire file 11965c73622aSBram Moolenaar" so we don't accidentally start within a closed fold or something. 11975c73622aSBram Moolenaarlet s:allfolds = [] 11985c73622aSBram Moolenaar 1199076e8b2aSBram Moolenaarif s:settings.dynamic_folds 12005c73622aSBram Moolenaar let s:lnum = 1 12015c73622aSBram Moolenaar let s:end = line('$') 12025c73622aSBram Moolenaar " save the fold text and set it to the default so we can find fold levels 12035c73622aSBram Moolenaar let s:foldtext_save = &foldtext 1204349b2fb0SBram Moolenaar setlocal foldtext& 12055c73622aSBram Moolenaar 12065c73622aSBram Moolenaar " we will set the foldcolumn in the html to the greater of the maximum fold 12075c73622aSBram Moolenaar " level and the current foldcolumn setting 12085c73622aSBram Moolenaar let s:foldcolumn = &foldcolumn 12095c73622aSBram Moolenaar 12105c73622aSBram Moolenaar " get all info needed to describe currently closed folds 1211349b2fb0SBram Moolenaar while s:lnum <= s:end 12125c73622aSBram Moolenaar if foldclosed(s:lnum) == s:lnum 12135c73622aSBram Moolenaar " default fold text has '+-' and then a number of dashes equal to fold 12145c73622aSBram Moolenaar " level, so subtract 2 from index of first non-dash after the dashes 12155c73622aSBram Moolenaar " in order to get the fold level of the current fold 12165c73622aSBram Moolenaar let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2 12175c73622aSBram Moolenaar " store fold info for later use 12185c73622aSBram Moolenaar let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"} 12195c73622aSBram Moolenaar call add(s:allfolds, s:newfold) 12205c73622aSBram Moolenaar " open the fold so we can find any contained folds 12215c73622aSBram Moolenaar execute s:lnum."foldopen" 12225c73622aSBram Moolenaar else 1223076e8b2aSBram Moolenaar if !s:settings.no_progress 1224349b2fb0SBram Moolenaar call s:pgb.incr() 1225349b2fb0SBram Moolenaar if s:pgb.needs_redraw 1226349b2fb0SBram Moolenaar redrawstatus 1227349b2fb0SBram Moolenaar let s:pgb.needs_redraw = 0 1228349b2fb0SBram Moolenaar endif 1229349b2fb0SBram Moolenaar endif 12305c73622aSBram Moolenaar let s:lnum = s:lnum + 1 12315c73622aSBram Moolenaar endif 12325c73622aSBram Moolenaar endwhile 12335c73622aSBram Moolenaar 12345c73622aSBram Moolenaar " close all folds to get info for originally open folds 12355c73622aSBram Moolenaar silent! %foldclose! 12365c73622aSBram Moolenaar let s:lnum = 1 12375c73622aSBram Moolenaar 12385c73622aSBram Moolenaar " the originally open folds will be all folds we encounter that aren't 12395c73622aSBram Moolenaar " already in the list of closed folds 1240349b2fb0SBram Moolenaar while s:lnum <= s:end 12415c73622aSBram Moolenaar if foldclosed(s:lnum) == s:lnum 12425c73622aSBram Moolenaar " default fold text has '+-' and then a number of dashes equal to fold 12435c73622aSBram Moolenaar " level, so subtract 2 from index of first non-dash after the dashes 12445c73622aSBram Moolenaar " in order to get the fold level of the current fold 12455c73622aSBram Moolenaar let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2 12465c73622aSBram Moolenaar let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"} 12475c73622aSBram Moolenaar " only add the fold if we don't already have it 12485c73622aSBram Moolenaar if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1 12495c73622aSBram Moolenaar let s:newfold.type = "open-fold" 12505c73622aSBram Moolenaar call add(s:allfolds, s:newfold) 12515c73622aSBram Moolenaar endif 12525c73622aSBram Moolenaar " open the fold so we can find any contained folds 12535c73622aSBram Moolenaar execute s:lnum."foldopen" 12545c73622aSBram Moolenaar else 1255076e8b2aSBram Moolenaar if !s:settings.no_progress 1256349b2fb0SBram Moolenaar call s:pgb.incr() 1257349b2fb0SBram Moolenaar if s:pgb.needs_redraw 1258349b2fb0SBram Moolenaar redrawstatus 1259349b2fb0SBram Moolenaar let s:pgb.needs_redraw = 0 1260349b2fb0SBram Moolenaar endif 1261349b2fb0SBram Moolenaar endif 12625c73622aSBram Moolenaar let s:lnum = s:lnum + 1 12635c73622aSBram Moolenaar endif 12645c73622aSBram Moolenaar endwhile 12655c73622aSBram Moolenaar 12665c73622aSBram Moolenaar " sort the folds so that we only ever need to look at the first item in the 12675c73622aSBram Moolenaar " list of folds 12685c73622aSBram Moolenaar call sort(s:allfolds, "s:FoldCompare") 12695c73622aSBram Moolenaar 1270349b2fb0SBram Moolenaar let &l:foldtext = s:foldtext_save 12715c73622aSBram Moolenaar unlet s:foldtext_save 12725c73622aSBram Moolenaar 12735c73622aSBram Moolenaar " close all folds again so we can get the fold text as we go 12745c73622aSBram Moolenaar silent! %foldclose! 12752a8a3ecbSBram Moolenaar 1276251e1912SBram Moolenaar " Go through and remove folds we don't need to (or cannot) process in the 1277251e1912SBram Moolenaar " current conversion range 1278251e1912SBram Moolenaar " 1279251e1912SBram Moolenaar " If a fold is removed which contains other folds, which are included, we need 1280251e1912SBram Moolenaar " to adjust the level of the included folds as used by the conversion logic 1281251e1912SBram Moolenaar " (avoiding special cases is good) 1282251e1912SBram Moolenaar " 1283251e1912SBram Moolenaar " Note any time we remove a fold, either all of the included folds are in it, 1284251e1912SBram Moolenaar " or none of them, because we only remove a fold if neither its start nor its 1285251e1912SBram Moolenaar " end are within the conversion range. 1286251e1912SBram Moolenaar let leveladjust = 0 12872a8a3ecbSBram Moolenaar for afold in s:allfolds 12882a8a3ecbSBram Moolenaar let removed = 0 12892a8a3ecbSBram Moolenaar if exists("g:html_start_line") && exists("g:html_end_line") 12902a8a3ecbSBram Moolenaar if afold.firstline < g:html_start_line 1291251e1912SBram Moolenaar if afold.lastline <= g:html_end_line && afold.lastline >= g:html_start_line 12922a8a3ecbSBram Moolenaar " if a fold starts before the range to convert but stops within the 12932a8a3ecbSBram Moolenaar " range, we need to include it. Make it start on the first converted 12942a8a3ecbSBram Moolenaar " line. 12952a8a3ecbSBram Moolenaar let afold.firstline = g:html_start_line 12962a8a3ecbSBram Moolenaar else 12972a8a3ecbSBram Moolenaar " if the fold lies outside the range or the start and stop enclose 12982a8a3ecbSBram Moolenaar " the entire range, don't bother parsing it 12992a8a3ecbSBram Moolenaar call remove(s:allfolds, index(s:allfolds, afold)) 13002a8a3ecbSBram Moolenaar let removed = 1 1301251e1912SBram Moolenaar if afold.lastline > g:html_end_line 1302251e1912SBram Moolenaar let leveladjust += 1 1303251e1912SBram Moolenaar endif 13042a8a3ecbSBram Moolenaar endif 13052a8a3ecbSBram Moolenaar elseif afold.firstline > g:html_end_line 13062a8a3ecbSBram Moolenaar " If the entire fold lies outside the range we need to remove it. 13072a8a3ecbSBram Moolenaar call remove(s:allfolds, index(s:allfolds, afold)) 13082a8a3ecbSBram Moolenaar let removed = 1 13092a8a3ecbSBram Moolenaar endif 13102a8a3ecbSBram Moolenaar elseif exists("g:html_start_line") 13112a8a3ecbSBram Moolenaar if afold.firstline < g:html_start_line 13122a8a3ecbSBram Moolenaar " if there is no last line, but there is a first line, the end of the 13132a8a3ecbSBram Moolenaar " fold will always lie within the region of interest, so keep it 13142a8a3ecbSBram Moolenaar let afold.firstline = g:html_start_line 13152a8a3ecbSBram Moolenaar endif 13162a8a3ecbSBram Moolenaar elseif exists("g:html_end_line") 13172a8a3ecbSBram Moolenaar " if there is no first line we default to the first line in the buffer so 13182a8a3ecbSBram Moolenaar " the fold start will always be included if the fold itself is included. 13192a8a3ecbSBram Moolenaar " If however the entire fold lies outside the range we need to remove it. 13202a8a3ecbSBram Moolenaar if afold.firstline > g:html_end_line 13212a8a3ecbSBram Moolenaar call remove(s:allfolds, index(s:allfolds, afold)) 13222a8a3ecbSBram Moolenaar let removed = 1 13232a8a3ecbSBram Moolenaar endif 13242a8a3ecbSBram Moolenaar endif 13252a8a3ecbSBram Moolenaar if !removed 1326251e1912SBram Moolenaar let afold.level -= leveladjust 13272a8a3ecbSBram Moolenaar if afold.level+1 > s:foldcolumn 13282a8a3ecbSBram Moolenaar let s:foldcolumn = afold.level+1 13292a8a3ecbSBram Moolenaar endif 13302a8a3ecbSBram Moolenaar endif 13312a8a3ecbSBram Moolenaar endfor 1332251e1912SBram Moolenaar 1333251e1912SBram Moolenaar " if we've removed folds containing the conversion range from processing, 1334251e1912SBram Moolenaar " getting foldtext as we go won't know to open the removed folds, so the 1335251e1912SBram Moolenaar " foldtext would be wrong; open them now. 1336251e1912SBram Moolenaar " 1337251e1912SBram Moolenaar " Note that only when a start and an end line is specified will a fold 1338251e1912SBram Moolenaar " containing the current range ever be removed. 1339251e1912SBram Moolenaar while leveladjust > 0 1340251e1912SBram Moolenaar exe g:html_start_line."foldopen" 1341251e1912SBram Moolenaar let leveladjust -= 1 1342251e1912SBram Moolenaar endwhile 13435c73622aSBram Moolenaarendif 13445c73622aSBram Moolenaar 13455c73622aSBram Moolenaar" Now loop over all lines in the original text to convert to html. 1346071d4279SBram Moolenaar" Use html_start_line and html_end_line if they are set. 1347b02cbe34SBram Moolenaarif exists("g:html_start_line") 1348071d4279SBram Moolenaar let s:lnum = html_start_line 1349071d4279SBram Moolenaar if s:lnum < 1 || s:lnum > line("$") 1350071d4279SBram Moolenaar let s:lnum = 1 1351071d4279SBram Moolenaar endif 1352071d4279SBram Moolenaarelse 1353071d4279SBram Moolenaar let s:lnum = 1 1354071d4279SBram Moolenaarendif 1355b02cbe34SBram Moolenaarif exists("g:html_end_line") 1356071d4279SBram Moolenaar let s:end = html_end_line 1357071d4279SBram Moolenaar if s:end < s:lnum || s:end > line("$") 1358071d4279SBram Moolenaar let s:end = line("$") 1359071d4279SBram Moolenaar endif 1360071d4279SBram Moolenaarelse 1361071d4279SBram Moolenaar let s:end = line("$") 1362071d4279SBram Moolenaarendif 1363071d4279SBram Moolenaar 13645c73622aSBram Moolenaar" stack to keep track of all the folds containing the current line 13655c73622aSBram Moolenaarlet s:foldstack = [] 13665c73622aSBram Moolenaar 1367076e8b2aSBram Moolenaarif !s:settings.no_progress 1368349b2fb0SBram Moolenaar let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin) 1369349b2fb0SBram Moolenaarendif 1370349b2fb0SBram Moolenaar 1371076e8b2aSBram Moolenaarif s:settings.number_lines 13725c73622aSBram Moolenaar let s:margin = strlen(s:end) + 1 13735c73622aSBram Moolenaarelse 13745c73622aSBram Moolenaar let s:margin = 0 13755c73622aSBram Moolenaarendif 13765c73622aSBram Moolenaar 1377076e8b2aSBram Moolenaarif has('folding') && !s:settings.ignore_folding 137835a9aaabSBram Moolenaar let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')] 137935a9aaabSBram Moolenaar if s:foldfillchar == '' 138035a9aaabSBram Moolenaar let s:foldfillchar = '-' 13817b0294cbSBram Moolenaar endif 138235a9aaabSBram Moolenaarendif 138335a9aaabSBram Moolenaarlet s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')] 138435a9aaabSBram Moolenaarif s:difffillchar == '' 138535a9aaabSBram Moolenaar let s:difffillchar = '-' 13867b0294cbSBram Moolenaarendif 13877b0294cbSBram Moolenaar 13885c73622aSBram Moolenaarlet s:foldId = 0 13897b0294cbSBram Moolenaar 13902a8a3ecbSBram Moolenaarif !s:settings.expand_tabs 13912a8a3ecbSBram Moolenaar " If keeping tabs, add them to printable characters so we keep them when 13922a8a3ecbSBram Moolenaar " formatting text (strtrans() doesn't replace printable chars) 13932a8a3ecbSBram Moolenaar let s:old_isprint = &isprint 13942a8a3ecbSBram Moolenaar setlocal isprint+=9 13952a8a3ecbSBram Moolenaarendif 13962a8a3ecbSBram Moolenaar 1397071d4279SBram Moolenaarwhile s:lnum <= s:end 1398071d4279SBram Moolenaar 139947136d70SBram Moolenaar " If there are filler lines for diff mode, show these above the line. 140047136d70SBram Moolenaar let s:filler = diff_filler(s:lnum) 140147136d70SBram Moolenaar if s:filler > 0 140247136d70SBram Moolenaar let s:n = s:filler 140347136d70SBram Moolenaar while s:n > 0 140435a9aaabSBram Moolenaar let s:new = repeat(s:difffillchar, 3) 140547136d70SBram Moolenaar 1406076e8b2aSBram Moolenaar if s:n > 2 && s:n < s:filler && !s:settings.whole_filler 140735a9aaabSBram Moolenaar let s:new = s:new . " " . s:filler . " inserted lines " 140835a9aaabSBram Moolenaar let s:n = 2 140935a9aaabSBram Moolenaar endif 141035a9aaabSBram Moolenaar 1411076e8b2aSBram Moolenaar if !s:settings.no_pre 141235a9aaabSBram Moolenaar " HTML line wrapping is off--go ahead and fill to the margin 14136c35beaaSBram Moolenaar " TODO: what about when CSS wrapping is turned on? 14145c73622aSBram Moolenaar let s:new = s:new . repeat(s:difffillchar, &columns - strlen(s:new) - s:margin) 14155c73622aSBram Moolenaar else 14165c73622aSBram Moolenaar let s:new = s:new . repeat(s:difffillchar, 3) 141735a9aaabSBram Moolenaar endif 141835a9aaabSBram Moolenaar 14196c35beaaSBram Moolenaar let s:new = s:HtmlFormat_d(s:new, s:DIFF_D_ID, 0) 1420076e8b2aSBram Moolenaar if s:settings.number_lines 14216c35beaaSBram Moolenaar " Indent if line numbering is on. Indent gets style of line number 14226c35beaaSBram Moolenaar " column. 1423543b7ef7SBram Moolenaar let s:new = s:HtmlFormat_n(repeat(' ', s:margin), s:LINENR_ID, 0, 0) . s:new 14246c35beaaSBram Moolenaar endif 14256c35beaaSBram Moolenaar if s:settings.dynamic_folds && !s:settings.no_foldcolumn && s:foldcolumn > 0 14266c35beaaSBram Moolenaar " Indent for foldcolumn if there is one. Assume it's empty, there should 14276c35beaaSBram Moolenaar " not be a fold for deleted lines in diff mode. 14286c35beaaSBram Moolenaar let s:new = s:FoldColumn_fill() . s:new 14295c73622aSBram Moolenaar endif 1430349b2fb0SBram Moolenaar call add(s:lines, s:new.s:HtmlEndline) 143135a9aaabSBram Moolenaar 143247136d70SBram Moolenaar let s:n = s:n - 1 143347136d70SBram Moolenaar endwhile 143447136d70SBram Moolenaar unlet s:n 143547136d70SBram Moolenaar endif 143647136d70SBram Moolenaar unlet s:filler 143747136d70SBram Moolenaar 143847136d70SBram Moolenaar " Start the line with the line number. 1439076e8b2aSBram Moolenaar if s:settings.number_lines 14405c73622aSBram Moolenaar let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) . s:lnum . ' ' 144147136d70SBram Moolenaar endif 144247136d70SBram Moolenaar 14435c73622aSBram Moolenaar let s:new = "" 14445c73622aSBram Moolenaar 1445076e8b2aSBram Moolenaar if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds 14467b0294cbSBram Moolenaar " 14475c73622aSBram Moolenaar " This is the beginning of a folded block (with no dynamic folding) 14486c35beaaSBram Moolenaar let s:new = foldtextresult(s:lnum) 1449076e8b2aSBram Moolenaar if !s:settings.no_pre 145035a9aaabSBram Moolenaar " HTML line wrapping is off--go ahead and fill to the margin 145135a9aaabSBram Moolenaar let s:new = s:new . repeat(s:foldfillchar, &columns - strlen(s:new)) 14527b0294cbSBram Moolenaar endif 14537b0294cbSBram Moolenaar 14546c35beaaSBram Moolenaar " put numcol in a separate group for sake of unselectable text 1455543b7ef7SBram Moolenaar let s:new = (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, s:lnum): "") . s:HtmlFormat_t(s:new, s:FOLDED_ID, 0) 14567b0294cbSBram Moolenaar 14577b0294cbSBram Moolenaar " Skip to the end of the fold 1458349b2fb0SBram Moolenaar let s:new_lnum = foldclosedend(s:lnum) 1459349b2fb0SBram Moolenaar 1460076e8b2aSBram Moolenaar if !s:settings.no_progress 1461349b2fb0SBram Moolenaar call s:pgb.incr(s:new_lnum - s:lnum) 1462349b2fb0SBram Moolenaar endif 1463349b2fb0SBram Moolenaar 1464349b2fb0SBram Moolenaar let s:lnum = s:new_lnum 14657b0294cbSBram Moolenaar 14667b0294cbSBram Moolenaar else 14677b0294cbSBram Moolenaar " 14685c73622aSBram Moolenaar " A line that is not folded, or doing dynamic folding. 14697b0294cbSBram Moolenaar " 147035a9aaabSBram Moolenaar let s:line = getline(s:lnum) 14717b0294cbSBram Moolenaar let s:len = strlen(s:line) 14727b0294cbSBram Moolenaar 1473076e8b2aSBram Moolenaar if s:settings.dynamic_folds 14745c73622aSBram Moolenaar " First insert a closing for any open folds that end on this line 14755c73622aSBram Moolenaar while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1 14765c73622aSBram Moolenaar let s:new = s:new."</span></span>" 14775c73622aSBram Moolenaar call remove(s:foldstack, 0) 14785c73622aSBram Moolenaar endwhile 14795c73622aSBram Moolenaar 14802a8a3ecbSBram Moolenaar " Now insert an opening for any new folds that start on this line 14815c73622aSBram Moolenaar let s:firstfold = 1 14825c73622aSBram Moolenaar while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum 14835c73622aSBram Moolenaar let s:foldId = s:foldId + 1 1484349b2fb0SBram Moolenaar let s:new .= "<span id='" 1485349b2fb0SBram Moolenaar let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "") 148631c31679SBram Moolenaar let s:new .= "fold".s:foldId.s:settings.id_suffix."' class='".s:allfolds[0].type."'>" 1487349b2fb0SBram Moolenaar 14885c73622aSBram Moolenaar 14895c73622aSBram Moolenaar " Unless disabled, add a fold column for the opening line of a fold. 14905c73622aSBram Moolenaar " 14915c73622aSBram Moolenaar " Note that dynamic folds require using css so we just use css to take 14925c73622aSBram Moolenaar " care of the leading spaces rather than using in the case of 14935c73622aSBram Moolenaar " html_no_pre to make it easier 1494076e8b2aSBram Moolenaar if !s:settings.no_foldcolumn 14955c73622aSBram Moolenaar " add fold column that can open the new fold 14965c73622aSBram Moolenaar if s:allfolds[0].level > 1 && s:firstfold 14976c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_build('|', s:allfolds[0].level - 1, 0, "", 149831c31679SBram Moolenaar \ 'toggle-open FoldColumn','javascript:toggleFold("fold'.s:foldstack[0].id.s:settings.id_suffix.'");') 14995c73622aSBram Moolenaar endif 15006c35beaaSBram Moolenaar " add the filler spaces separately from the '+' char so that it can be 15016c35beaaSBram Moolenaar " shown/hidden separately during a hover unfold 15026c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_build("+", 1, 0, "", 150331c31679SBram Moolenaar \ 'toggle-open FoldColumn', 'javascript:toggleFold("fold'.s:foldId.s:settings.id_suffix.'");') 15045c73622aSBram Moolenaar " If this is not the last fold we're opening on this line, we need 15055c73622aSBram Moolenaar " to keep the filler spaces hidden if the fold is opened by mouse 15065c73622aSBram Moolenaar " hover. If it is the last fold to open in the line, we shouldn't hide 15075c73622aSBram Moolenaar " them, so don't apply the toggle-filler class. 15086c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_build(" ", 1, s:foldcolumn - s:allfolds[0].level - 1, "", 15096c35beaaSBram Moolenaar \ 'toggle-open FoldColumn'. (get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum ?" toggle-filler" :""), 151031c31679SBram Moolenaar \ 'javascript:toggleFold("fold'.s:foldId.s:settings.id_suffix.'");') 15115c73622aSBram Moolenaar 15125c73622aSBram Moolenaar " add fold column that can close the new fold 15136c35beaaSBram Moolenaar " only add extra blank space if we aren't opening another fold on the 15146c35beaaSBram Moolenaar " same line 15155c73622aSBram Moolenaar if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum 15166c35beaaSBram Moolenaar let s:extra_space = s:foldcolumn - s:allfolds[0].level 15176c35beaaSBram Moolenaar else 15186c35beaaSBram Moolenaar let s:extra_space = 0 15195c73622aSBram Moolenaar endif 15206c35beaaSBram Moolenaar if s:firstfold 15216c35beaaSBram Moolenaar " the first fold in a line has '|' characters from folds opened in 15226c35beaaSBram Moolenaar " previous lines, before the '-' for this fold 15236c35beaaSBram Moolenaar let s:new .= s:FoldColumn_build('|', s:allfolds[0].level - 1, s:extra_space, '-', 152431c31679SBram Moolenaar \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'.s:foldId.s:settings.id_suffix.'");') 15256c35beaaSBram Moolenaar else 15266c35beaaSBram Moolenaar " any subsequent folds in the line only add a single '-' 15276c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_build("-", 1, s:extra_space, "", 152831c31679SBram Moolenaar \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'.s:foldId.s:settings.id_suffix.'");') 15296c35beaaSBram Moolenaar endif 15305c73622aSBram Moolenaar let s:firstfold = 0 15315c73622aSBram Moolenaar endif 15325c73622aSBram Moolenaar 15336c35beaaSBram Moolenaar " Add fold text, moving the span ending to the next line so collapsing 15346c35beaaSBram Moolenaar " of folds works correctly. 15356c35beaaSBram Moolenaar " Put numcol in a separate group for sake of unselectable text. 1536543b7ef7SBram Moolenaar let s:new = s:new . (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, 0) : "") . substitute(s:HtmlFormat_t(foldtextresult(s:lnum), s:FOLDED_ID, 0), '</span>', s:HtmlEndline.'\n\0', '') 15375c73622aSBram Moolenaar let s:new = s:new . "<span class='fulltext'>" 15385c73622aSBram Moolenaar 15395c73622aSBram Moolenaar " open the fold now that we have the fold text to allow retrieval of 15405c73622aSBram Moolenaar " fold text for subsequent folds 15415c73622aSBram Moolenaar execute s:lnum."foldopen" 15425c73622aSBram Moolenaar call insert(s:foldstack, remove(s:allfolds,0)) 15435c73622aSBram Moolenaar let s:foldstack[0].id = s:foldId 15445c73622aSBram Moolenaar endwhile 15455c73622aSBram Moolenaar 15465c73622aSBram Moolenaar " Unless disabled, add a fold column for other lines. 15475c73622aSBram Moolenaar " 15485c73622aSBram Moolenaar " Note that dynamic folds require using css so we just use css to take 15495c73622aSBram Moolenaar " care of the leading spaces rather than using in the case of 15505c73622aSBram Moolenaar " html_no_pre to make it easier 1551076e8b2aSBram Moolenaar if !s:settings.no_foldcolumn 15525c73622aSBram Moolenaar if empty(s:foldstack) 15537510fe74SBram Moolenaar " add the empty foldcolumn for unfolded lines if there is a fold 15547510fe74SBram Moolenaar " column at all 15557510fe74SBram Moolenaar if s:foldcolumn > 0 15566c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_fill() 15577510fe74SBram Moolenaar endif 15585c73622aSBram Moolenaar else 15595c73622aSBram Moolenaar " add the fold column for folds not on the opening line 15605c73622aSBram Moolenaar if get(s:foldstack, 0).firstline < s:lnum 15616c35beaaSBram Moolenaar let s:new = s:new . s:FoldColumn_build('|', s:foldstack[0].level, s:foldcolumn - s:foldstack[0].level, "", 156231c31679SBram Moolenaar \ 'FoldColumn', 'javascript:toggleFold("fold'.s:foldstack[0].id.s:settings.id_suffix.'");') 15635c73622aSBram Moolenaar endif 15645c73622aSBram Moolenaar endif 15655c73622aSBram Moolenaar endif 15665c73622aSBram Moolenaar endif 15675c73622aSBram Moolenaar 15685c73622aSBram Moolenaar " Now continue with the unfolded line text 1569076e8b2aSBram Moolenaar if s:settings.number_lines 1570543b7ef7SBram Moolenaar let s:new = s:new . s:HtmlFormat_n(s:numcol, s:LINENR_ID, 0, s:lnum) 157131c31679SBram Moolenaar elseif s:settings.line_ids 1572543b7ef7SBram Moolenaar let s:new = s:new . s:HtmlFormat_n("", s:LINENR_ID, 0, s:lnum) 1573071d4279SBram Moolenaar endif 1574071d4279SBram Moolenaar 157547136d70SBram Moolenaar " Get the diff attribute, if any. 157647136d70SBram Moolenaar let s:diffattr = diff_hlID(s:lnum, 1) 157747136d70SBram Moolenaar 15787510fe74SBram Moolenaar " initialize conceal info to act like not concealed, just in case 15797510fe74SBram Moolenaar let s:concealinfo = [0, ''] 15807510fe74SBram Moolenaar 1581071d4279SBram Moolenaar " Loop over each character in the line 1582071d4279SBram Moolenaar let s:col = 1 15838ada2ccaSBram Moolenaar 15848ada2ccaSBram Moolenaar " most of the time we won't use the diff_id, initialize to zero 15858ada2ccaSBram Moolenaar let s:diff_id = 0 15868ada2ccaSBram Moolenaar 158735a9aaabSBram Moolenaar while s:col <= s:len || (s:col == 1 && s:diffattr) 1588071d4279SBram Moolenaar let s:startcol = s:col " The start column for processing text 1589076e8b2aSBram Moolenaar if !s:settings.ignore_conceal && has('conceal') 15907510fe74SBram Moolenaar let s:concealinfo = synconcealed(s:lnum, s:col) 15917510fe74SBram Moolenaar endif 1592076e8b2aSBram Moolenaar if !s:settings.ignore_conceal && s:concealinfo[0] 15937510fe74SBram Moolenaar let s:col = s:col + 1 15947510fe74SBram Moolenaar " Speed loop (it's small - that's the trick) 15957510fe74SBram Moolenaar " Go along till we find a change in the match sequence number (ending 15967510fe74SBram Moolenaar " the specific concealed region) or until there are no more concealed 15977510fe74SBram Moolenaar " characters. 15987510fe74SBram Moolenaar while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile 15997510fe74SBram Moolenaar elseif s:diffattr 16008ada2ccaSBram Moolenaar let s:diff_id = diff_hlID(s:lnum, s:col) 16018ada2ccaSBram Moolenaar let s:id = synID(s:lnum, s:col, 1) 160247136d70SBram Moolenaar let s:col = s:col + 1 160347136d70SBram Moolenaar " Speed loop (it's small - that's the trick) 160447136d70SBram Moolenaar " Go along till we find a change in hlID 16058ada2ccaSBram Moolenaar while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) 16068ada2ccaSBram Moolenaar \ && s:diff_id == diff_hlID(s:lnum, s:col) | 16078ada2ccaSBram Moolenaar \ let s:col = s:col + 1 | 16088ada2ccaSBram Moolenaar \ endwhile 1609076e8b2aSBram Moolenaar if s:len < &columns && !s:settings.no_pre 16108ada2ccaSBram Moolenaar " Add spaces at the end of the raw text line to extend the changed 16118ada2ccaSBram Moolenaar " line to the full width. 16125c73622aSBram Moolenaar let s:line = s:line . repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin) 161335a9aaabSBram Moolenaar let s:len = &columns 161435a9aaabSBram Moolenaar endif 161547136d70SBram Moolenaar else 1616071d4279SBram Moolenaar let s:id = synID(s:lnum, s:col, 1) 1617071d4279SBram Moolenaar let s:col = s:col + 1 1618071d4279SBram Moolenaar " Speed loop (it's small - that's the trick) 1619071d4279SBram Moolenaar " Go along till we find a change in synID 1620071d4279SBram Moolenaar while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile 162147136d70SBram Moolenaar endif 1622071d4279SBram Moolenaar 1623076e8b2aSBram Moolenaar if s:settings.ignore_conceal || !s:concealinfo[0] 16242a8a3ecbSBram Moolenaar " Expand tabs if needed 162535a9aaabSBram Moolenaar let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol) 16262a8a3ecbSBram Moolenaar if s:settings.expand_tabs 16275c73622aSBram Moolenaar let s:offset = 0 16285c73622aSBram Moolenaar let s:idx = stridx(s:expandedtab, "\t") 1629f0d58efcSBram Moolenaar let s:tablist = split(&vts,',') 1630f0d58efcSBram Moolenaar if empty(s:tablist) 1631f0d58efcSBram Moolenaar let s:tablist = [ &ts ] 1632f0d58efcSBram Moolenaar endif 1633f0d58efcSBram Moolenaar let s:tabidx = 0 1634f0d58efcSBram Moolenaar let s:tabwidth = 0 16355c73622aSBram Moolenaar while s:idx >= 0 16360c0734d5SBram Moolenaar if s:startcol + s:idx == 1 16370c0734d5SBram Moolenaar let s:i = s:tablist[0] 16380c0734d5SBram Moolenaar else 16390c0734d5SBram Moolenaar " Get the character, which could be multiple bytes, which falls 16400c0734d5SBram Moolenaar " immediately before the found tab. Extract it by matching a 16410c0734d5SBram Moolenaar " character just prior to the column where the tab matches. 16420c0734d5SBram Moolenaar " We'll use this to get the byte index of the character 16430c0734d5SBram Moolenaar " immediately preceding the tab, so we can then look up the 16440c0734d5SBram Moolenaar " virtual column that character appears in, to determine how 16450c0734d5SBram Moolenaar " much of the current tabstop has been used up. 16460c0734d5SBram Moolenaar if s:idx == 0 16470c0734d5SBram Moolenaar " if the found tab is the first character in the text being 16480c0734d5SBram Moolenaar " processed, we need to get the character prior to the text, 16490c0734d5SBram Moolenaar " given by startcol. 16500c0734d5SBram Moolenaar let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:offset) . 'c') 16510c0734d5SBram Moolenaar else 16520c0734d5SBram Moolenaar " Otherwise, the byte index of the tab into s:expandedtab is 16530c0734d5SBram Moolenaar " given by s:idx. 16540c0734d5SBram Moolenaar let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c') 16550c0734d5SBram Moolenaar endif 16560c0734d5SBram Moolenaar let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)]) 16570c0734d5SBram Moolenaar 16580c0734d5SBram Moolenaar " find the tabstop interval to use for the tab we just found. Keep 16590c0734d5SBram Moolenaar " adding tabstops (which could be variable) until we would exceed 16600c0734d5SBram Moolenaar " the virtual screen position of the start of the found tab. 16610c0734d5SBram Moolenaar while s:vcol >= s:tabwidth + s:tablist[s:tabidx] 1662f0d58efcSBram Moolenaar let s:tabwidth += s:tablist[s:tabidx] 1663f0d58efcSBram Moolenaar if s:tabidx < len(s:tablist)-1 1664f0d58efcSBram Moolenaar let s:tabidx = s:tabidx+1 1665f0d58efcSBram Moolenaar endif 1666f0d58efcSBram Moolenaar endwhile 1667f0d58efcSBram Moolenaar let s:i = s:tablist[s:tabidx] - (s:vcol - s:tabwidth) 16685c73622aSBram Moolenaar endif 16690c0734d5SBram Moolenaar " update offset to keep the index within the line corresponding to 16700c0734d5SBram Moolenaar " actual tab characters instead of replaced spaces; s:idx reflects 16710c0734d5SBram Moolenaar " replaced spaces in s:expandedtab, s:offset cancels out all but 16720c0734d5SBram Moolenaar " the tab character itself. 16735c73622aSBram Moolenaar let s:offset -= s:i - 1 16745c73622aSBram Moolenaar let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '') 16755c73622aSBram Moolenaar let s:idx = stridx(s:expandedtab, "\t") 167635a9aaabSBram Moolenaar endwhile 16772a8a3ecbSBram Moolenaar end 167835a9aaabSBram Moolenaar 16797510fe74SBram Moolenaar " get the highlight group name to use 1680071d4279SBram Moolenaar let s:id = synIDtrans(s:id) 16817510fe74SBram Moolenaar else 16827510fe74SBram Moolenaar " use Conceal highlighting for concealed text 16836c35beaaSBram Moolenaar let s:id = s:CONCEAL_ID 16847510fe74SBram Moolenaar let s:expandedtab = s:concealinfo[1] 16857510fe74SBram Moolenaar endif 16867510fe74SBram Moolenaar 16876c35beaaSBram Moolenaar " Output the text with the same synID, with class set to the highlight ID 16886c35beaaSBram Moolenaar " name, unless it has been concealed completely. 16897510fe74SBram Moolenaar if strlen(s:expandedtab) > 0 1690543b7ef7SBram Moolenaar let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id, s:diff_id, "", 0) 16917510fe74SBram Moolenaar endif 1692071d4279SBram Moolenaar endwhile 16937b0294cbSBram Moolenaar endif 1694071d4279SBram Moolenaar 16957510fe74SBram Moolenaar call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1)) 1696076e8b2aSBram Moolenaar if !s:settings.no_progress && s:pgb.needs_redraw 1697349b2fb0SBram Moolenaar redrawstatus 1698349b2fb0SBram Moolenaar let s:pgb.needs_redraw = 0 1699349b2fb0SBram Moolenaar endif 1700071d4279SBram Moolenaar let s:lnum = s:lnum + 1 1701313b7237SBram Moolenaar 1702076e8b2aSBram Moolenaar if !s:settings.no_progress 1703349b2fb0SBram Moolenaar call s:pgb.incr() 1704349b2fb0SBram Moolenaar endif 1705349b2fb0SBram Moolenaarendwhile 1706349b2fb0SBram Moolenaar 1707076e8b2aSBram Moolenaarif s:settings.dynamic_folds 17085c73622aSBram Moolenaar " finish off any open folds 17095c73622aSBram Moolenaar while !empty(s:foldstack) 1710349b2fb0SBram Moolenaar let s:lines[-1].="</span></span>" 17115c73622aSBram Moolenaar call remove(s:foldstack, 0) 17125c73622aSBram Moolenaar endwhile 17135c73622aSBram Moolenaar 17145c73622aSBram Moolenaar " add fold column to the style list if not already there 17156c35beaaSBram Moolenaar let s:id = s:FOLD_C_ID 17166c35beaaSBram Moolenaar if !has_key(s:stylelist, s:id) 17176c35beaaSBram Moolenaar let s:stylelist[s:id] = '.FoldColumn { ' . s:CSS1(s:id) . '}' 17185c73622aSBram Moolenaar endif 17195c73622aSBram Moolenaarendif 17205c73622aSBram Moolenaar 1721076e8b2aSBram Moolenaarif s:settings.no_pre 1722076e8b2aSBram Moolenaar if !s:settings.use_css 17238ada2ccaSBram Moolenaar " Close off the font tag that encapsulates the whole <body> 1724bebca9daSBram Moolenaar call extend(s:lines, ["</font>", "</body>", "</html>"]) 17258ada2ccaSBram Moolenaar else 17266c35beaaSBram Moolenaar call extend(s:lines, ["</div>", "</body>", "</html>"]) 17278ada2ccaSBram Moolenaar endif 1728071d4279SBram Moolenaarelse 1729349b2fb0SBram Moolenaar call extend(s:lines, ["</pre>", "</body>", "</html>"]) 1730071d4279SBram Moolenaarendif 1731071d4279SBram Moolenaar 1732349b2fb0SBram Moolenaarexe s:newwin . "wincmd w" 1733349b2fb0SBram Moolenaarcall setline(1, s:lines) 1734349b2fb0SBram Moolenaarunlet s:lines 1735071d4279SBram Moolenaar 17366c35beaaSBram Moolenaar" Mangle modelines so Vim doesn't try to use HTML text as a modeline if editing 17376c35beaaSBram Moolenaar" this file in the future; need to do this after generating all the text in case 17386c35beaaSBram Moolenaar" the modeline text has different highlight groups which all turn out to be 17396c35beaaSBram Moolenaar" stripped from the final output. 1740dd007ed5SBram Moolenaar%s!\v(%(^|\s+)%([Vv]i%(m%([<=>]?\d+)?)?|ex)):!\1\:!ge 17416c35beaaSBram Moolenaar 1742543b7ef7SBram Moolenaar" The generated HTML is admittedly ugly and takes a LONG time to fold. 1743543b7ef7SBram Moolenaar" Make sure the user doesn't do syntax folding when loading a generated file, 1744543b7ef7SBram Moolenaar" using a modeline. 1745543b7ef7SBram Moolenaarcall append(line('$'), "<!-- vim: set foldmethod=manual : -->") 1746543b7ef7SBram Moolenaar 1747071d4279SBram Moolenaar" Now, when we finally know which, we define the colors and styles 1748076e8b2aSBram Moolenaarif s:settings.use_css 17490c0734d5SBram Moolenaar 1;/<style\>/+1 1750071d4279SBram Moolenaarendif 1751071d4279SBram Moolenaar 1752071d4279SBram Moolenaar" Normal/global attributes 1753076e8b2aSBram Moolenaarif s:settings.use_css 1754076e8b2aSBram Moolenaar if s:settings.no_pre 17556c35beaaSBram Moolenaar call append('.', "body { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }") 17566c35beaaSBram Moolenaar + 1757071d4279SBram Moolenaar else 17586c35beaaSBram Moolenaar call append('.', "pre { " . s:whitespace . "font-family: ". s:htmlfont ."; color: " . s:fgc . "; background-color: " . s:bgc . "; }") 17596c35beaaSBram Moolenaar + 1760071d4279SBram Moolenaar yank 1761071d4279SBram Moolenaar put 1762071d4279SBram Moolenaar execute "normal! ^cwbody\e" 17638e5af3e5SBram Moolenaar " body should not have the wrap formatting, only the pre section 17648e5af3e5SBram Moolenaar if s:whitespace != '' 17658e5af3e5SBram Moolenaar exec 's#'.s:whitespace 17668e5af3e5SBram Moolenaar endif 1767071d4279SBram Moolenaar endif 17686c35beaaSBram Moolenaar " fix browser inconsistencies (sometimes within the same browser) of different 17696c35beaaSBram Moolenaar " default font size for different elements 17706c35beaaSBram Moolenaar call append('.', '* { font-size: 1em; }') 17716c35beaaSBram Moolenaar + 17726c35beaaSBram Moolenaar " if we use any input elements for unselectable content, make sure they look 17736c35beaaSBram Moolenaar " like normal text 17746c35beaaSBram Moolenaar if !empty(s:settings.prevent_copy) 17750c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# "none" 17766c35beaaSBram Moolenaar call append('.', 'input { border: none; margin: 0; padding: 0; font-family: '.s:htmlfont.'; }') 17776c35beaaSBram Moolenaar + 17786c35beaaSBram Moolenaar " ch units for browsers which support them, em units for a somewhat 17790c0734d5SBram Moolenaar " reasonable fallback. 17800c0734d5SBram Moolenaar for w in range(1, 20, 1) 17816c35beaaSBram Moolenaar call append('.', [ 17820c0734d5SBram Moolenaar \ "input[size='".w."'] { width: ".w."em; width: ".w."ch; }" 17836c35beaaSBram Moolenaar \ ]) 17846c35beaaSBram Moolenaar + 17856c35beaaSBram Moolenaar endfor 17860c0734d5SBram Moolenaar endif 17870c0734d5SBram Moolenaar 17880c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'all' 17890c0734d5SBram Moolenaar let s:unselectable_styles = [] 17900c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 'f' 17910c0734d5SBram Moolenaar call add(s:unselectable_styles, 'FoldColumn') 17920c0734d5SBram Moolenaar endif 17930c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 'n' 17940c0734d5SBram Moolenaar call add(s:unselectable_styles, 'LineNr') 17950c0734d5SBram Moolenaar endif 17960c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 't' && !s:settings.ignore_folding 17970c0734d5SBram Moolenaar call add(s:unselectable_styles, 'Folded') 17980c0734d5SBram Moolenaar endif 17990c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 'd' 18000c0734d5SBram Moolenaar call add(s:unselectable_styles, 'DiffDelete') 18010c0734d5SBram Moolenaar endif 18020c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'none' 18030c0734d5SBram Moolenaar call append('.', [ 18040c0734d5SBram Moolenaar \ '/* Note: IE does not support @supports conditionals, but also does not fully support', 18050c0734d5SBram Moolenaar \ ' "content:" with custom content, so we *want* the check to fail */', 18060c0734d5SBram Moolenaar \ '@supports ( content: attr(data-custom-content) ) {' 18070c0734d5SBram Moolenaar \ ]) 18080c0734d5SBram Moolenaar +3 18090c0734d5SBram Moolenaar endif 18100c0734d5SBram Moolenaar " The line number column inside the foldtext is styled just like the fold 18110c0734d5SBram Moolenaar " text in Vim, but it should use the prevent_copy settings of line number 18120c0734d5SBram Moolenaar " rather than fold text. Apply the prevent_copy styles to foldtext 18130c0734d5SBram Moolenaar " specifically for line numbers, which always come after the fold column, 18140c0734d5SBram Moolenaar " or at the beginning of the line. 18150c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 'n' && !s:settings.ignore_folding 18160c0734d5SBram Moolenaar call append('.', [ 18170c0734d5SBram Moolenaar \ ' .FoldColumn + .Folded, .Folded:first-child { user-select: none; }', 18180c0734d5SBram Moolenaar \ ' .FoldColumn + [data-Folded-content]::before, [data-Folded-content]:first-child::before { content: attr(data-Folded-content); }', 18190c0734d5SBram Moolenaar \ ' .FoldColumn + [data-Folded-content]::before, [data-Folded-content]:first-child::before { padding-bottom: 1px; display: inline-block; /* match the 1-px padding of standard items with background */ }', 18200c0734d5SBram Moolenaar \ ' .FoldColumn + span[data-Folded-content]::before, [data-Folded-content]:first-child::before { cursor: default; }', 18210c0734d5SBram Moolenaar \ ]) 18220c0734d5SBram Moolenaar +4 18230c0734d5SBram Moolenaar endif 18240c0734d5SBram Moolenaar for s:style_name in s:unselectable_styles 18250c0734d5SBram Moolenaar call append('.', [ 18260c0734d5SBram Moolenaar \ ' .'.s:style_name.' { user-select: none; }', 18270c0734d5SBram Moolenaar \ ' [data-'.s:style_name.'-content]::before { content: attr(data-'.s:style_name.'-content); }', 18280c0734d5SBram Moolenaar \ ' [data-'.s:style_name.'-content]::before { padding-bottom: 1px; display: inline-block; /* match the 1-px padding of standard items with background */ }', 18290c0734d5SBram Moolenaar \ ' span[data-'.s:style_name.'-content]::before { cursor: default; }', 18300c0734d5SBram Moolenaar \ ]) 18310c0734d5SBram Moolenaar +4 18320c0734d5SBram Moolenaar endfor 18330c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'none' 18340c0734d5SBram Moolenaar call append('.', [ 18350c0734d5SBram Moolenaar \ ' input { display: none; }', 18360c0734d5SBram Moolenaar \ '}' 18370c0734d5SBram Moolenaar \ ]) 18380c0734d5SBram Moolenaar +2 18390c0734d5SBram Moolenaar endif 18400c0734d5SBram Moolenaar unlet s:unselectable_styles 18410c0734d5SBram Moolenaar endif 18420c0734d5SBram Moolenaar 18430c0734d5SBram Moolenaar " Fix mouse cursor shape for the fallback <input> method of uncopyable text 18440c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'none' 18456c35beaaSBram Moolenaar if s:settings.prevent_copy =~# 'f' 18466c35beaaSBram Moolenaar " Make the cursor show active fold columns as active areas, and empty fold 18476c35beaaSBram Moolenaar " columns as not interactive. 18486c35beaaSBram Moolenaar call append('.', ['input.FoldColumn { cursor: pointer; }', 18490c0734d5SBram Moolenaar \ 'input.FoldColumn[value="'.repeat(' ', s:foldcolumn).'"] { cursor: default; }' 18506c35beaaSBram Moolenaar \ ]) 18516c35beaaSBram Moolenaar +2 18520c0734d5SBram Moolenaar if s:settings.use_input_for_pc !=# 'all' 18530c0734d5SBram Moolenaar call append('.', [ 18540c0734d5SBram Moolenaar \ 'a[data-FoldColumn-content="'.repeat(' ', s:foldcolumn).'"] { cursor: default; }' 18550c0734d5SBram Moolenaar \ ]) 18560c0734d5SBram Moolenaar +1 18570c0734d5SBram Moolenaar end 18586c35beaaSBram Moolenaar endif 18596c35beaaSBram Moolenaar " make line number column show as non-interactive if not selectable 18606c35beaaSBram Moolenaar if s:settings.prevent_copy =~# 'n' 18616c35beaaSBram Moolenaar call append('.', 'input.LineNr { cursor: default; }') 18626c35beaaSBram Moolenaar + 18636c35beaaSBram Moolenaar endif 18646c35beaaSBram Moolenaar " make fold text and line number column within fold text show as 18656c35beaaSBram Moolenaar " non-interactive if not selectable 18666c35beaaSBram Moolenaar if (s:settings.prevent_copy =~# 'n' || s:settings.prevent_copy =~# 't') && !s:settings.ignore_folding 18676c35beaaSBram Moolenaar call append('.', 'input.Folded { cursor: default; }') 18686c35beaaSBram Moolenaar + 18696c35beaaSBram Moolenaar endif 18700c0734d5SBram Moolenaar " make diff filler show as non-interactive if not selectable 18710c0734d5SBram Moolenaar if s:settings.prevent_copy =~# 'd' 18720c0734d5SBram Moolenaar call append('.', 'input.DiffDelete { cursor: default; }') 18730c0734d5SBram Moolenaar + 18740c0734d5SBram Moolenaar endif 18750c0734d5SBram Moolenaar endif 18766c35beaaSBram Moolenaar endif 1877071d4279SBram Moolenaarelse 18780c0734d5SBram Moolenaar " For Netscape 4, set <body> attributes too, though, strictly speaking, it's 18790c0734d5SBram Moolenaar " incorrect. 1880543b7ef7SBram Moolenaar execute '%s:<body\([^>]*\):<body bgcolor="' . s:bgc . '" text="' . s:fgc . '"\1>\r<font face="'. s:htmlfont .'"' 1881071d4279SBram Moolenaarendif 1882071d4279SBram Moolenaar 18836c35beaaSBram Moolenaar" Gather attributes for all other classes. Do diff first so that normal 18846c35beaaSBram Moolenaar" highlight groups are inserted before it. 1885076e8b2aSBram Moolenaarif s:settings.use_css 18866c35beaaSBram Moolenaar if s:diff_mode 18876c35beaaSBram Moolenaar call append('.', filter(map(keys(s:diffstylelist), "s:diffstylelist[v:val]"), 'v:val != ""')) 18886c35beaaSBram Moolenaar endif 18896c35beaaSBram Moolenaar if !empty(s:stylelist) 18906c35beaaSBram Moolenaar call append('.', filter(map(keys(s:stylelist), "s:stylelist[v:val]"), 'v:val != ""')) 1891071d4279SBram Moolenaar endif 1892071d4279SBram Moolenaarendif 1893071d4279SBram Moolenaar 1894071d4279SBram Moolenaar" Add hyperlinks 18956c35beaaSBram Moolenaar" TODO: add option to not do this? Maybe just make the color the same as the 18966c35beaaSBram Moolenaar" text highlight group normally is? 18971cd871b5SBram Moolenaar%s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|>\|<\|"\)+<a href="\1">\1</a>\2+ge 1898071d4279SBram Moolenaar 1899071d4279SBram Moolenaar" The DTD 1900076e8b2aSBram Moolenaarif s:settings.use_xhtml 1901076e8b2aSBram 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\">" 19020c0734d5SBram Moolenaarelseif s:html5 19030c0734d5SBram Moolenaar exe "normal! gg0i<!DOCTYPE html>\n" 19041cd871b5SBram Moolenaarelse 1905076e8b2aSBram Moolenaar exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n" 19061cd871b5SBram Moolenaarendif 19071cd871b5SBram Moolenaar 1908076e8b2aSBram Moolenaarif s:settings.use_xhtml 19091cd871b5SBram Moolenaar exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e" 19101cd871b5SBram Moolenaarendif 1911071d4279SBram Moolenaar 1912071d4279SBram Moolenaar" Cleanup 1913071d4279SBram Moolenaar%s:\s\+$::e 1914071d4279SBram Moolenaar 19152a8a3ecbSBram Moolenaar" Restore old settings (new window first) 1916543b7ef7SBram Moolenaar" 1917543b7ef7SBram Moolenaar" Don't bother restoring foldmethod in case it was syntax because the markup is 1918543b7ef7SBram Moolenaar" so weirdly formatted it can take a LONG time. 19198df7f888SBram Moolenaarlet &l:foldenable = s:old_fen 1920071d4279SBram Moolenaarlet &report = s:old_report 1921071d4279SBram Moolenaarlet &title = s:old_title 1922071d4279SBram Moolenaarlet &icon = s:old_icon 1923071d4279SBram Moolenaarlet &paste = s:old_paste 1924071d4279SBram Moolenaarlet &magic = s:old_magic 1925071d4279SBram Moolenaarlet @/ = s:old_search 1926349b2fb0SBram Moolenaarlet &more = s:old_more 19272a8a3ecbSBram Moolenaar 19282a8a3ecbSBram Moolenaar" switch to original window to restore those settings 1929071d4279SBram Moolenaarexe s:orgwin . "wincmd w" 19302a8a3ecbSBram Moolenaar 19312a8a3ecbSBram Moolenaarif !s:settings.expand_tabs 19322a8a3ecbSBram Moolenaar let &l:isprint = s:old_isprint 19332a8a3ecbSBram Moolenaarendif 1934166af9bbSBram Moolenaarlet &l:stl = s:origwin_stl 1935071d4279SBram Moolenaarlet &l:et = s:old_et 19368df7f888SBram Moolenaarlet &l:scrollbind = s:old_bind 19372a8a3ecbSBram Moolenaar 19382a8a3ecbSBram Moolenaar" and back to the new window again to end there 1939071d4279SBram Moolenaarexe s:newwin . "wincmd w" 19402a8a3ecbSBram Moolenaar 1941166af9bbSBram Moolenaarlet &l:stl = s:newwin_stl 1942349b2fb0SBram Moolenaarexec 'resize' s:old_winheight 1943349b2fb0SBram Moolenaarlet &l:winfixheight = s:old_winfixheight 1944071d4279SBram Moolenaar 1945349b2fb0SBram Moolenaarlet &ls=s:ls 19460c0734d5SBram Moolenaarlet &eventignore=s:ei_sav 1947349b2fb0SBram Moolenaar 1948071d4279SBram Moolenaar" Save a little bit of memory (worth doing?) 19498e5af3e5SBram Moolenaarunlet s:htmlfont s:whitespace 19508df7f888SBram Moolenaarunlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search 1951543b7ef7SBram Moolenaarunlet s:old_magic s:old_more s:old_fen s:old_winheight 19522a8a3ecbSBram Moolenaarunlet! s:old_isprint 19536c35beaaSBram Moolenaarunlet s:whatterm s:stylelist s:diffstylelist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight 19546c35beaaSBram Moolenaarunlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo s:diff_mode 19550c0734d5SBram Moolenaarunlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:ei_sav s:origwin_stl 19568df7f888SBram Moolenaarunlet! s:newwin_stl s:current_syntax 195705159a0cSBram Moolenaarif !v:profiling 1958071d4279SBram Moolenaar delfunc s:HtmlColor 195935a9aaabSBram Moolenaar delfunc s:HtmlFormat 1960071d4279SBram Moolenaar delfunc s:CSS1 19616c35beaaSBram Moolenaar delfunc s:BuildStyleWrapper 1962076e8b2aSBram Moolenaar if !s:settings.use_css 1963071d4279SBram Moolenaar delfunc s:HtmlOpening 1964071d4279SBram Moolenaar delfunc s:HtmlClosing 1965071d4279SBram Moolenaar endif 1966076e8b2aSBram Moolenaar if s:settings.dynamic_folds 19675c73622aSBram Moolenaar delfunc s:FoldCompare 19685c73622aSBram Moolenaar endif 19695c73622aSBram Moolenaar 1970076e8b2aSBram Moolenaar if !s:settings.no_progress 1971349b2fb0SBram Moolenaar delfunc s:ProgressBar 1972349b2fb0SBram Moolenaar delfunc s:progressbar.paint 1973349b2fb0SBram Moolenaar delfunc s:progressbar.incr 1974349b2fb0SBram Moolenaar unlet s:pgb s:progressbar 1975349b2fb0SBram Moolenaar endif 1976349b2fb0SBram Moolenaarendif 1977349b2fb0SBram Moolenaar 19788df7f888SBram Moolenaarunlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace 19796c35beaaSBram Moolenaarunlet! s:LeadingSpace s:HtmlEndline s:firstfold s:numcol s:foldcolumn 19806c35beaaSBram Moolenaarunlet s:foldstack s:allfolds s:foldId s:settings 19815c73622aSBram Moolenaar 19825c73622aSBram Moolenaarlet &cpo = s:cpo_sav 1983349b2fb0SBram Moolenaarunlet! s:cpo_sav 19845c73622aSBram Moolenaar 1985349b2fb0SBram Moolenaar" Make sure any patches will probably use consistent indent 19867c86f4ccSBram Moolenaar" vim: ts=8 sw=2 sts=2 noet 1987