summaryrefslogtreecommitdiff
path: root/runtime/autoload
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-02-02 13:59:48 +0000
committerBram Moolenaar <Bram@vim.org>2023-02-02 13:59:48 +0000
commitbe4e01637e71c8d5095c33b9861fd70b41476732 (patch)
treed521021e32c070a7c7a913fc96a14b3de8c81afe /runtime/autoload
parent685bf83b73d0fe6fd36bb2949bebd6aae66a139e (diff)
downloadvim-git-be4e01637e71c8d5095c33b9861fd70b41476732.tar.gz
Update runtime files.
Diffstat (limited to 'runtime/autoload')
-rw-r--r--runtime/autoload/dist/vimindent.vim320
-rw-r--r--runtime/autoload/tohtml.vim424
2 files changed, 408 insertions, 336 deletions
diff --git a/runtime/autoload/dist/vimindent.vim b/runtime/autoload/dist/vimindent.vim
index 898f22f65..8d86543cb 100644
--- a/runtime/autoload/dist/vimindent.vim
+++ b/runtime/autoload/dist/vimindent.vim
@@ -2,12 +2,12 @@ vim9script
# Language: Vim script
# Maintainer: github user lacygoill
-# Last Change: 2023 Jan 03
+# Last Change: 2023 Feb 01
# NOTE: Whenever you change the code, make sure the tests are still passing:
#
# $ cd runtime/indent/
-# $ make clean; make test || vimdiff testdir/vim.{fail,ok}
+# $ make clean; make test || vimdiff testdir/vim.{ok,fail}
# Config {{{1
@@ -112,6 +112,10 @@ const DICT_KEY: string = '^\s*\%('
.. '\)'
.. ':\%(\s\|$\)'
+# NOT_A_DICT_KEY {{{3
+
+const NOT_A_DICT_KEY: string = ':\@!'
+
# END_OF_COMMAND {{{3
const END_OF_COMMAND: string = $'\s*\%($\|||\@!\|{INLINE_COMMENT}\)'
@@ -144,19 +148,43 @@ const HEREDOC_OPERATOR: string = '\s=<<\s\@=\%(\s\+\%(trim\|eval\)\)\{,2}'
#
# But sometimes, it can be too costly and cause `E363` to be given.
const PATTERN_DELIMITER: string = '[-+*/%]\%(=\s\)\@!'
-
-# QUOTE {{{3
-
-const QUOTE: string = '["'']'
# }}}2
# Syntaxes {{{2
-# ASSIGNS_HEREDOC {{{3
-
-const ASSIGNS_HEREDOC: string = $'^\%({COMMENT}\)\@!.*\%({HEREDOC_OPERATOR}\)\s\+\zs[A-Z]\+{END_OF_LINE}'
-
-# CD_COMMAND {{{3
-
-const CD_COMMAND: string = $'\<[lt]\=cd!\=\s\+-{END_OF_COMMAND}'
+# BLOCKS {{{3
+
+const BLOCKS: list<list<string>> = [
+ ['if', 'el\%[se]', 'elseif\=', 'en\%[dif]'],
+ ['for', 'endfor\='],
+ ['wh\%[ile]', 'endw\%[hile]'],
+ ['try', 'cat\%[ch]', 'fina\|finally\=', 'endt\%[ry]'],
+ ['def', 'enddef'],
+ ['fu\%[nction](\@!', 'endf\%[unction]'],
+ ['class', 'endclass'],
+ ['interface', 'endinterface'],
+ ['enum', 'endenum'],
+ ['aug\%[roup]\%(\s\+[eE][nN][dD]\)\@!\s\+\S\+', 'aug\%[roup]\s\+[eE][nN][dD]'],
+]
+
+# MODIFIERS {{{3
+
+# some keywords can be prefixed by modifiers (e.g. `def` can be prefixed by `export`)
+const MODIFIERS: dict<string> = {
+ def: ['export', 'static'],
+ class: ['export', 'abstract', 'export abstract'],
+ interface: ['export'],
+}
+# ...
+# class: ['export', 'abstract', 'export abstract'],
+# ...
+# →
+# ...
+# class: '\%(export\|abstract\|export\s\+abstract\)\s\+',
+# ...
+->map((_, mods: list<string>): string =>
+ '\%(' .. mods
+ ->join('\|')
+ ->substitute('\s\+', '\\s\\+', 'g')
+ .. '\)' .. '\s\+')
# HIGHER_ORDER_COMMAND {{{3
@@ -174,58 +202,102 @@ patterns =<< trim eval END
g\%[lobal]!\={PATTERN_DELIMITER}.*
v\%[global]!\={PATTERN_DELIMITER}.*
END
-const HIGHER_ORDER_COMMAND: string = $'\%(^\|{BAR_SEPARATION}\)\s*\<\%(' .. patterns->join('\|') .. '\):\@!'
-# MAPPING_COMMAND {{{3
+const HIGHER_ORDER_COMMAND: string = $'\%(^\|{BAR_SEPARATION}\)\s*\<\%({patterns->join('\|')}\){NOT_A_DICT_KEY}'
-const MAPPING_COMMAND: string = '\%(\<sil\%[ent]!\=\s\+\)\=\<[nvxsoilct]\=\%(nore\|un\)map!\=\s'
+# START_MIDDLE_END {{{3
-# NORMAL_COMMAND {{{3
+# Let's derive this constant from `BLOCKS`:
+#
+# [['if', 'el\%[se]', 'elseif\=', 'en\%[dif]'],
+# ['for', 'endfor\='],
+# ...,
+# [...]]
+# →
+# {
+# 'for': ['for', '', 'endfor\='],
+# 'endfor': ['for', '', 'endfor\='],
+# 'if': ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
+# 'else': ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
+# 'elseif': ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
+# 'endif': ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
+# ...
+# }
+var START_MIDDLE_END: dict<list<string>>
+
+def Unshorten(kwd: string): string
+ return BlockStartKeyword(kwd)
+enddef
-const NORMAL_COMMAND: string = '\<norm\%[al]!\=\s*\S\+$'
+def BlockStartKeyword(line: string): string
+ var kwd: string = line->matchstr('\l\+')
+ return fullcommand(kwd, false)
+enddef
-# PLUS_MINUS_COMMAND {{{3
+{
+ for kwds: list<string> in BLOCKS
+ var [start: string, middle: string, end: string] = [kwds[0], '', kwds[-1]]
+ if MODIFIERS->has_key(start->Unshorten())
+ start = $'\%({MODIFIERS[start]}\)\={start}'
+ endif
+ if kwds->len() > 2
+ middle = kwds[1 : -2]->join('\|')
+ endif
+ for kwd: string in kwds
+ START_MIDDLE_END->extend({[kwd->Unshorten()]: [start, middle, end]})
+ endfor
+ endfor
+}
-# In legacy, the `:+` and `:-` commands are not required to be preceded by a colon.
-# As a result, when `+` or `-` is alone on a line, there is ambiguity.
-# It might be an operator or a command.
-# To not break the indentation in legacy scripts, we might need to consider such
-# lines as commands.
-const PLUS_MINUS_COMMAND: string = '^\s*[+-]\s*$'
+START_MIDDLE_END = START_MIDDLE_END
+ ->map((_, kwds: list<string>) =>
+ kwds->map((_, kwd: string) => kwd == ''
+ ? ''
+ : $'\%(^\|{BAR_SEPARATION}\|\<sil\%[ent]\|{HIGHER_ORDER_COMMAND}\)\s*'
+ .. $'\<\%({kwd}\)\>\%(\s*{OPERATOR}\)\@!'))
+
+lockvar! START_MIDDLE_END
# ENDS_BLOCK {{{3
const ENDS_BLOCK: string = '^\s*\%('
- .. 'en\%[dif]'
- .. '\|' .. 'endfor\='
- .. '\|' .. 'endw\%[hile]'
- .. '\|' .. 'endt\%[ry]'
- .. '\|' .. 'enddef'
- .. '\|' .. 'endclass'
- .. '\|' .. 'endf\%[unction]'
- .. '\|' .. 'aug\%[roup]\s\+[eE][nN][dD]'
+ .. BLOCKS
+ ->copy()
+ ->map((_, kwds: list<string>): string => kwds[-1])
+ ->join('\|')
.. '\|' .. CLOSING_BRACKET
.. $'\){END_OF_COMMAND}'
# ENDS_BLOCK_OR_CLAUSE {{{3
-patterns =<< trim END
- en\%[dif]
- el\%[se]
- endfor\=
- endclass
- endw\%[hile]
- endt\%[ry]
- fina\|finally\=
- enddef
- endf\%[unction]
- aug\%[roup]\s\+[eE][nN][dD]
-END
+patterns = BLOCKS
+ ->copy()
+ ->map((_, kwds: list<string>) => kwds[1 :])
+ ->flattennew()
+ # `catch` and `elseif` need to be handled as special cases
+ ->filter((_, pat: string): bool => pat->Unshorten() !~ '^\%(catch\|elseif\)\>')
const ENDS_BLOCK_OR_CLAUSE: string = '^\s*\%(' .. patterns->join('\|') .. $'\){END_OF_COMMAND}'
.. $'\|^\s*cat\%[ch]\%(\s\+\({PATTERN_DELIMITER}\).*\1\)\={END_OF_COMMAND}'
.. $'\|^\s*elseif\=\>\%({OPERATOR}\)\@!'
+# STARTS_NAMED_BLOCK {{{3
+
+patterns = []
+{
+ for kwds: list<string> in BLOCKS
+ for kwd: string in kwds[0 : -2]
+ if MODIFIERS->has_key(kwd->Unshorten())
+ patterns += [$'\%({MODIFIERS[kwd]}\)\={kwd}']
+ else
+ patterns += [kwd]
+ endif
+ endfor
+ endfor
+}
+
+const STARTS_NAMED_BLOCK: string = $'^\s*\%(sil\%[ent]\s\+\)\=\%({patterns->join('\|')}\)\>{NOT_A_DICT_KEY}'
+
# STARTS_CURLY_BLOCK {{{3
# TODO: `{` alone on a line is not necessarily the start of a block.
@@ -238,73 +310,57 @@ const STARTS_CURLY_BLOCK: string = '\%('
.. '\|' .. $'^\%(\s*\|.*{BAR_SEPARATION}\s*\)\%(com\%[mand]\|au\%[tocmd]\).*\zs\s{{'
.. '\)' .. END_OF_COMMAND
-# STARTS_NAMED_BLOCK {{{3
-
-# All of these will be used at the start of a line (or after a bar).
-# NOTE: Don't replace `\%x28` with `(`.{{{
-#
-# Otherwise, the paren would be unbalanced which might cause syntax highlighting
-# issues much later in the code of the current script (sometimes, the syntax
-# highlighting plugin fails to correctly recognize a heredoc which is far away
-# and/or not displayed because inside a fold).
-# }}}
-patterns =<< trim END
- if
- el\%[se]
- elseif\=
- for
- class
- wh\%[ile]
- try
- cat\%[ch]
- fina\|finally\=
- fu\%[nction]\%x28\@!
- \%(export\s\+\)\=def
- aug\%[roup]\%(\s\+[eE][nN][dD]\)\@!\s\+\S\+
-END
-const STARTS_NAMED_BLOCK: string = '^\s*\%(sil\%[ent]\s\+\)\=\%(' .. patterns->join('\|') .. '\)\>:\@!'
-
# STARTS_FUNCTION {{{3
-const STARTS_FUNCTION: string = '^\s*\%(export\s\+\)\=def\>:\@!'
+const STARTS_FUNCTION: string = $'^\s*\%({MODIFIERS.def}\)\=def\>{NOT_A_DICT_KEY}'
# ENDS_FUNCTION {{{3
-const ENDS_FUNCTION: string = $'^\s*enddef\>:\@!{END_OF_COMMAND}'
+const ENDS_FUNCTION: string = $'^\s*enddef\>{END_OF_COMMAND}'
-# START_MIDDLE_END {{{3
+# ASSIGNS_HEREDOC {{{3
+
+const ASSIGNS_HEREDOC: string = $'^\%({COMMENT}\)\@!.*\%({HEREDOC_OPERATOR}\)\s\+\zs[A-Z]\+{END_OF_LINE}'
-const START_MIDDLE_END: dict<list<string>> = {
- if: ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
- else: ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
- elseif: ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
- endif: ['if', 'el\%[se]\|elseif\=', 'en\%[dif]'],
- for: ['for', '', 'endfor\='],
- endfor: ['for', '', 'endfor\='],
- class: ['class', '', 'endclass'],
- endclass: ['class', '', 'endclass'],
- while: ['wh\%[ile]', '', 'endw\%[hile]'],
- endwhile: ['wh\%[ile]', '', 'endw\%[hile]'],
- try: ['try', 'cat\%[ch]\|fina\|finally\=', 'endt\%[ry]'],
- catch: ['try', 'cat\%[ch]\|fina\|finally\=', 'endt\%[ry]'],
- finally: ['try', 'cat\%[ch]\|fina\|finally\=', 'endt\%[ry]'],
- endtry: ['try', 'cat\%[ch]\|fina\|finally\=', 'endt\%[ry]'],
- def: ['\%(export\s\+\)\=def', '', 'enddef'],
- enddef: ['\%(export\s\+\)\=def', '', 'enddef'],
- function: ['fu\%[nction]', '', 'endf\%[unction]'],
- endfunction: ['fu\%[nction]', '', 'endf\%[unction]'],
- augroup: ['aug\%[roup]\%(\s\+[eE][nN][dD]\)\@!\s\+\S\+', '', 'aug\%[roup]\s\+[eE][nN][dD]'],
-}->map((_, kwds: list<string>) =>
- kwds->map((_, kwd: string) => kwd == ''
- ? ''
- : $'\%(^\|{BAR_SEPARATION}\|\<sil\%[ent]\|{HIGHER_ORDER_COMMAND}\)\s*'
- .. $'\%({printf('\C\<\%%(%s\)\>:\@!\%%(\s*%s\)\@!', kwd, OPERATOR)}\)'))
+# PLUS_MINUS_COMMAND {{{3
+
+# In legacy, the `:+` and `:-` commands are not required to be preceded by a colon.
+# As a result, when `+` or `-` is alone on a line, there is ambiguity.
+# It might be an operator or a command.
+# To not break the indentation in legacy scripts, we might need to consider such
+# lines as commands.
+const PLUS_MINUS_COMMAND: string = '^\s*[+-]\s*$'
+
+# TRICKY_COMMANDS {{{3
+
+# Some commands are tricky because they accept an argument which can be
+# conflated with an operator. Examples:
+#
+# argdelete *
+# cd -
+# normal! ==
+# nunmap <buffer> (
+#
+# TODO: Other commands might accept operators as argument. Handle them too.
+patterns =<< trim eval END
+ {'\'}<argd\%[elete]\s\+\*\s*$
+ \<[lt]\=cd!\=\s\+-\s*$
+ \<norm\%[al]!\=\s*\S\+$
+ \%(\<sil\%[ent]!\=\s\+\)\=\<[nvxsoilct]\=\%(nore\|un\)map!\=\s
+ {PLUS_MINUS_COMMAND}
+END
+
+const TRICKY_COMMANDS: string = patterns->join('\|')
# }}}2
# EOL {{{2
# OPENING_BRACKET_AT_EOL {{{3
const OPENING_BRACKET_AT_EOL: string = OPENING_BRACKET .. END_OF_VIM9_LINE
+# CLOSING_BRACKET_AT_EOL {{{3
+
+const CLOSING_BRACKET_AT_EOL: string = CLOSING_BRACKET .. END_OF_VIM9_LINE
+
# COMMA_AT_EOL {{{3
const COMMA_AT_EOL: string = $',{END_OF_VIM9_LINE}'
@@ -392,6 +448,7 @@ export def Expr(lnum = v:lnum): number # {{{2
endif
if line_A->AtStartOf('FuncHeader')
+ && !IsInInterface()
line_A.lnum->CacheFuncHeader()
elseif line_A.lnum->IsInside('FuncHeader')
return b:vimindent.startindent + 2 * shiftwidth()
@@ -430,6 +487,7 @@ export def Expr(lnum = v:lnum): number # {{{2
if line_A.text->ContinuesBelowBracketBlock(line_B, past_bracket_block)
&& line_A.text !~ CLOSING_BRACKET_AT_SOL
return past_bracket_block.startindent
+ + (past_bracket_block.startline =~ STARTS_NAMED_BLOCK ? 2 * shiftwidth() : 0)
endif
# Problem: If we press `==` on the line right below the start of a multiline
@@ -438,6 +496,18 @@ export def Expr(lnum = v:lnum): number # {{{2
if line_B->EndsWithLambdaArrow()
return Indent(line_B.lnum) + shiftwidth() + IndentMoreInBracketBlock()
endif
+ # FIXME: Similar issue here:
+ #
+ # var x = []
+ # ->filter((_, _) =>
+ # true)
+ # ->items()
+ #
+ # Press `==` on last line.
+ # Expected: The `->items()` line is indented like `->filter(...)`.
+ # Actual: It's indented like `true)`.
+ # Is it worth fixing? `=ip` gives the correct indentation, because then the
+ # cache is used.
# Don't move this block before the heredoc one.{{{
#
@@ -536,8 +606,13 @@ def Offset( # {{{2
line_B: dict<any>,
): number
+ if line_B->AtStartOf('FuncHeader')
+ && IsInInterface()
+ return 0
+
# increase indentation inside a block
- if line_B.text =~ STARTS_NAMED_BLOCK || line_B->EndsWithCurlyBlock()
+ elseif line_B.text =~ STARTS_NAMED_BLOCK
+ || line_B->EndsWithCurlyBlock()
# But don't indent if the line starting the block also closes it.
if line_B->AlsoClosesBlock()
return 0
@@ -807,11 +882,6 @@ def Indent(lnum: number): number # {{{3
return indent(lnum)
enddef
-def BlockStartKeyword(line: string): string # {{{3
- var kwd: string = line->matchstr('\l\+')
- return fullcommand(kwd, false)
-enddef
-
def MatchingOpenBracket(line: dict<any>): number # {{{3
var end: string = line.text->matchstr(CLOSING_BRACKET)
var start: string = {']': '[', '}': '{', ')': '('}[end]
@@ -908,7 +978,8 @@ def SearchPair( # {{{3
if end == '[' || end == ']'
e = e->escape('[]')
endif
- return searchpair(s, middle, e, flags, (): bool => InCommentOrString(), stopline, TIMEOUT)
+ return searchpair('\C' .. s, (middle == '' ? '' : '\C' .. middle), '\C' .. e,
+ flags, (): bool => InCommentOrString(), stopline, TIMEOUT)
enddef
def SearchPairStart( # {{{3
@@ -1016,6 +1087,10 @@ def IsInThisBlock(line_A: dict<any>, lnum: number): bool # {{{3
return line_A.lnum <= end
enddef
+def IsInInterface(): bool # {{{3
+ return SearchPair('interface', '', 'endinterface', 'nW') > 0
+enddef
+
def IsFirstLineOfCommand(line_1: dict<any>, line_2: dict<any>): bool # {{{3
if line_1.text->Is_IN_KeywordForLoop(line_2.text)
return false
@@ -1096,6 +1171,10 @@ def EndsWithOpeningBracket(line: dict<any>): bool # {{{3
return NonCommentedMatch(line, OPENING_BRACKET_AT_EOL)
enddef
+def EndsWithClosingBracket(line: dict<any>): bool # {{{3
+ return NonCommentedMatch(line, CLOSING_BRACKET_AT_EOL)
+enddef
+
def NonCommentedMatch(line: dict<any>, pat: string): bool # {{{3
# Could happen if there is no code above us, and we're not on the 1st line.
# In that case, `PrevCodeLine()` returns `{lnum: 0, line: ''}`.
@@ -1103,16 +1182,6 @@ def NonCommentedMatch(line: dict<any>, pat: string): bool # {{{3
return false
endif
- if line.text =~ PLUS_MINUS_COMMAND
- return false
- endif
-
- # In `argdelete *`, `*` is not a multiplication operator.
- # TODO: Other commands can accept `*` as an argument. Handle them too.
- if line.text =~ '\<argd\%[elete]\s\+\*\s*$'
- return false
- endif
-
# Technically, that's wrong. A line might start with a range and end with a
# line continuation symbol. But it's unlikely. And it's useful to assume the
# opposite because it prevents us from conflating a mark with an operator or
@@ -1179,24 +1248,7 @@ def NonCommentedMatch(line: dict<any>, pat: string): bool # {{{3
return false
endif
- # `:help cd-`
- if line.text =~ CD_COMMAND
- return false
- endif
-
- # At the end of a mapping, any character might appear; e.g. a paren:
- #
- # nunmap <buffer> (
- #
- # Don't conflate this with a line continuation symbol.
- if line.text =~ MAPPING_COMMAND
- return false
- endif
-
- # not a comparison operator
- # vv
- # normal! ==
- if line.text =~ NORMAL_COMMAND
+ if line.text =~ TRICKY_COMMANDS
return false
endif
diff --git a/runtime/autoload/tohtml.vim b/runtime/autoload/tohtml.vim
index 270891abc..108634747 100644
--- a/runtime/autoload/tohtml.vim
+++ b/runtime/autoload/tohtml.vim
@@ -1,6 +1,6 @@
" Vim autoload file for the tohtml plugin.
" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2019 Aug 16
+" Last Change: 2023 Jan 01
"
" Additional contributors:
"
@@ -351,63 +351,65 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{
let s:old_magic = &magic
set magic
- if s:settings.use_xhtml
- if s:settings.encoding != ""
- let xml_line = "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>"
- else
- let xml_line = "<?xml version=\"1.0\"?>"
+ let html = []
+ if !s:settings.no_doc
+ if s:settings.use_xhtml
+ if s:settings.encoding != ""
+ let xml_line = "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>"
+ else
+ let xml_line = "<?xml version=\"1.0\"?>"
+ endif
+ let tag_close = ' />'
endif
- let tag_close = ' />'
- endif
- let style = [s:settings.use_xhtml ? "" : '-->']
- let body_line = ''
+ let style = [s:settings.use_xhtml ? "" : '-->']
+ let body_line = ''
- let html = []
- let s:html5 = 0
- if s:settings.use_xhtml
- call add(html, xml_line)
- endif
- if s:settings.use_xhtml
- call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
- call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">')
- elseif s:settings.use_css && !s:settings.no_pre
- call add(html, "<!DOCTYPE html>")
- call add(html, '<html>')
- let s:html5 = 1
- else
- call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
- call add(html, ' "http://www.w3.org/TR/html4/loose.dtd">')
- call add(html, '<html>')
- endif
- call add(html, '<head>')
-
- " include encoding as close to the top as possible, but only if not already
- " contained in XML information
- if s:settings.encoding != "" && !s:settings.use_xhtml
- if s:html5
- call add(html, '<meta charset="' . s:settings.encoding . '"' . tag_close)
+ let s:html5 = 0
+ if s:settings.use_xhtml
+ call add(html, xml_line)
+ endif
+ if s:settings.use_xhtml
+ call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
+ call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">')
+ elseif s:settings.use_css && !s:settings.no_pre
+ call add(html, "<!DOCTYPE html>")
+ call add(html, '<html>')
+ let s:html5 = 1
else
- call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close)
+ call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
+ call add(html, ' "http://www.w3.org/TR/html4/loose.dtd">')
+ call add(html, '<html>')
endif
- endif
+ call add(html, '<head>')
- call add(html, '<title>diff</title>')
- call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close)
- call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close)
- call add(html, '<meta name="settings" content="'.
- \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
- \ ',prevent_copy='.s:settings.prevent_copy.
- \ ',use_input_for_pc='.s:settings.use_input_for_pc.
- \ '"'.tag_close)
- call add(html, '<meta name="colorscheme" content="'.
- \ (exists('g:colors_name')
- \ ? g:colors_name
- \ : 'none'). '"'.tag_close)
-
- call add(html, '</head>')
- let body_line_num = len(html)
- call add(html, '<body'.(s:settings.line_ids ? ' onload="JumpToLine();"' : '').'>')
+ " include encoding as close to the top as possible, but only if not already
+ " contained in XML information
+ if s:settings.encoding != "" && !s:settings.use_xhtml
+ if s:html5
+ call add(html, '<meta charset="' . s:settings.encoding . '"' . tag_close)
+ else
+ call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close)
+ endif
+ endif
+
+ call add(html, '<title>diff</title>')
+ call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close)
+ call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close)
+ call add(html, '<meta name="settings" content="'.
+ \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
+ \ ',prevent_copy='.s:settings.prevent_copy.
+ \ ',use_input_for_pc='.s:settings.use_input_for_pc.
+ \ '"'.tag_close)
+ call add(html, '<meta name="colorscheme" content="'.
+ \ (exists('g:colors_name')
+ \ ? g:colors_name
+ \ : 'none'). '"'.tag_close)
+
+ call add(html, '</head>')
+ let body_line_num = len(html)
+ call add(html, '<body'.(s:settings.line_ids ? ' onload="JumpToLine();"' : '').'>')
+ endif
call add(html, "<table ".(s:settings.use_css? "" : "border='1' width='100%' ")."id='vimCodeElement".s:settings.id_suffix."'>")
call add(html, '<tr>')
@@ -430,47 +432,53 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{
" When not using CSS or when using xhtml, the <body> line can be important.
" Assume it will be the same for all buffers and grab it from the first
" buffer. Similarly, need to grab the body end line as well.
- if body_line == ''
- 1
- call search('<body')
- let body_line = getline('.')
- $
- call search('</body>', 'b')
- let s:body_end_line = getline('.')
- endif
+ if !s:settings.no_doc
+ if body_line == ''
+ 1
+ call search('<body')
+ let body_line = getline('.')
+ $
+ call search('</body>', 'b')
+ let s:body_end_line = getline('.')
+ endif
- " Grab the style information. Some of this will be duplicated so only insert
- " it if it's not already there. {{{
- 1
- let style_start = search('^<style\( type="text/css"\)\?>')
- 1
- let style_end = search('^</style>')
- if style_start > 0 && style_end > 0
- let buf_styles = getline(style_start + 1, style_end - 1)
- for a_style in buf_styles
- if index(style, a_style) == -1
- if diff_style_start == 0
- if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)'
- let diff_style_start = len(style)-1
+ " Grab the style information. Some of this will be duplicated so only insert
+ " it if it's not already there. {{{
+ 1
+ let style_start = search('^<style\( type="text/css"\)\?>')
+ 1
+ let style_end = search('^</style>')
+ if style_start > 0 && style_end > 0
+ let buf_styles = getline(style_start + 1, style_end - 1)
+ for a_style in buf_styles
+ if index(style, a_style) == -1
+ if diff_style_start == 0
+ if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)'
+ let diff_style_start = len(style)-1
+ endif
endif
+ call insert(style, a_style, insert_index)
+ let insert_index += 1
endif
- call insert(style, a_style, insert_index)
- let insert_index += 1
- endif
- endfor
- endif " }}}
+ endfor
+ endif " }}}
- " everything new will get added before the diff styles so diff highlight
- " properly overrides normal highlight
- if diff_style_start != 0
- let insert_index = diff_style_start
- endif
+ " everything new will get added before the diff styles so diff highlight
+ " properly overrides normal highlight
+ if diff_style_start != 0
+ let insert_index = diff_style_start
+ endif
- " Delete those parts that are not needed so we can include the rest into the
- " resulting table.
- 1,/^<body.*\%(\n<!--.*-->\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_
- $
- ?</body>?,$d_
+ " Delete those parts that are not needed so we can include the rest into the
+ " resulting table.
+ 1,/^<body.*\%(\n<!--.*-->\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_
+ $
+ ?</body>?,$d_
+ elseif !s:settings.no_modeline
+ " remove modeline from source files if it is included and we haven't deleted
+ " due to removing html footer already
+ $d
+ endif
let temp = getline(1,'$')
" clean out id on the main content container because we already set it on
" the table
@@ -478,7 +486,11 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{
" undo deletion of start and end part
" so we can later save the file as valid html
" TODO: restore using grabbed lines if undolevel is 1?
- normal! 2u
+ if !s:settings.no_doc
+ normal! 2u
+ elseif !s:settings.no_modeline
+ normal! u
+ endif
if s:settings.use_css
call add(html, '<td><div>')
elseif s:settings.use_xhtml
@@ -495,17 +507,23 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{
quit!
endfor
- let html[body_line_num] = body_line
+ if !s:settings.no_doc
+ let html[body_line_num] = body_line
+ endif
call add(html, '</tr>')
call add(html, '</table>')
- call add(html, s:body_end_line)
- call add(html, '</html>')
+ if !s:settings.no_doc
+ call add(html, s:body_end_line)
+ call add(html, '</html>')
+ endif
" The generated HTML is admittedly ugly and takes a LONG time to fold.
" Make sure the user doesn't do syntax folding when loading a generated file,
" using a modeline.
- call add(html, '<!-- vim: set foldmethod=manual : -->')
+ if !s:settings.no_modeline
+ call add(html, '<!-- vim: set foldmethod=manual : -->')
+ endif
let i = 1
let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html")
@@ -542,129 +560,131 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{
call append(0, html)
- if len(style) > 0
- 1
- let style_start = search('^</head>')-1
+ if !s:settings.no_doc
+ if len(style) > 0
+ 1
+ let style_start = search('^</head>')-1
- " add required javascript in reverse order so we can just call append again
- " and again without adjusting {{{
+ " add required javascript in reverse order so we can just call append again
+ " and again without adjusting {{{
- let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids
+ let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids
- " insert script closing tag if needed
- if s:uses_script
- call append(style_start, [
- \ '',
- \ s:settings.use_xhtml ? '//]]>' : '-->',
- \ "</script>"
- \ ])
- endif
+ " insert script closing tag if needed
+ if s:uses_script
+ call append(style_start, [
+ \ '',
+ \ s:settings.use_xhtml ? '//]]>' : '-->',
+ \ "</script>"
+ \ ])
+ endif
- " insert javascript to get IDs from line numbers, and to open a fold before
- " jumping to any lines contained therein
- if s:settings.line_ids
- call append(style_start, [
- \ " /* Always jump to new location even if the line was hidden inside a fold, or",
- \ " * we corrected the raw number to a line ID.",
- \ " */",
- \ " if (lineElem) {",
- \ " lineElem.scrollIntoView(true);",
- \ " }",
- \ " return true;",
- \ "}",
- \ "if ('onhashchange' in window) {",
- \ " window.onhashchange = JumpToLine;",
- \ "}"
- \ ])
+ " insert javascript to get IDs from line numbers, and to open a fold before
+ " jumping to any lines contained therein
+ if s:settings.line_ids
+ call append(style_start, [
+ \ " /* Always jump to new location even if the line was hidden inside a fold, or",
+ \ " * we corrected the raw number to a line ID.",
+ \ " */",
+ \ " if (lineElem) {",
+ \ " lineElem.scrollIntoView(true);",
+ \ " }",
+ \ " return true;",
+ \ "}",
+ \ "if ('onhashchange' in window) {",
+ \ " window.onhashchange = JumpToLine;",
+ \ "}"
+ \ ])
- if s:settings.dynamic_folds
+ if s:settings.dynamic_folds
+ call append(style_start, [
+ \ "",
+ \ " /* navigate upwards in the DOM tree to open all folds containing the line */",
+ \ " var node = lineElem;",
+ \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')",
+ \ " {",
+ \ " if (node.className == 'closed-fold')",
+ \ " {",
+ \ " /* toggle open the fold ID (remove window ID) */",
+ \ " toggleFold(node.id.substr(4));",
+ \ " }",
+ \ " node = node.parentNode;",
+ \ " }",
+ \ ])
+ endif
+ endif
+
+ if s:settings.line_ids
call append(style_start, [
\ "",
- \ " /* navigate upwards in the DOM tree to open all folds containing the line */",
- \ " var node = lineElem;",
- \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')",
- \ " {",
- \ " if (node.className == 'closed-fold')",
- \ " {",
- \ " /* toggle open the fold ID (remove window ID) */",
- \ " toggleFold(node.id.substr(4));",
- \ " }",
- \ " node = node.parentNode;",
+ \ "/* function to open any folds containing a jumped-to line before jumping to it */",
+ \ "function JumpToLine()",
+ \ "{",
+ \ " var lineNum;",
+ \ " lineNum = window.location.hash;",
+ \ " lineNum = lineNum.substr(1); /* strip off '#' */",
+ \ "",
+ \ " if (lineNum.indexOf('L') == -1) {",
+ \ " lineNum = 'L'+lineNum;",
+ \ " }",
+ \ " if (lineNum.indexOf('W') == -1) {",
+ \ " lineNum = 'W1'+lineNum;",
\ " }",
+ \ " var lineElem = document.getElementById(lineNum);"
\ ])
endif
- endif
- if s:settings.line_ids
- call append(style_start, [
- \ "",
- \ "/* function to open any folds containing a jumped-to line before jumping to it */",
- \ "function JumpToLine()",
- \ "{",
- \ " var lineNum;",
- \ " lineNum = window.location.hash;",
- \ " lineNum = lineNum.substr(1); /* strip off '#' */",
- \ "",
- \ " if (lineNum.indexOf('L') == -1) {",
- \ " lineNum = 'L'+lineNum;",
- \ " }",
- \ " if (lineNum.indexOf('W') == -1) {",
- \ " lineNum = 'W1'+lineNum;",
- \ " }",
- \ " var lineElem = document.getElementById(lineNum);"
- \ ])
- endif
+ " Insert javascript to toggle matching folds open and closed in all windows,
+ " if dynamic folding is active.
+ if s:settings.dynamic_folds
+ call append(style_start, [
+ \ " function toggleFold(objID)",
+ \ " {",
+ \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)",
+ \ " {",
+ \ " var fold;",
+ \ ' fold = document.getElementById("win"+win_num+objID);',
+ \ " if(fold.className == 'closed-fold')",
+ \ " {",
+ \ " fold.className = 'open-fold';",
+ \ " }",
+ \ " else if (fold.className == 'open-fold')",
+ \ " {",
+ \ " fold.className = 'closed-fold';",
+ \ " }",
+ \ " }",
+ \ " }",
+ \ ])
+ endif
- " Insert javascript to toggle matching folds open and closed in all windows,
- " if dynamic folding is active.
- if s:settings.dynamic_folds
- call append(style_start, [
- \ " function toggleFold(objID)",
- \ " {",
- \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)",
- \ " {",
- \ " var fold;",
- \ ' fold = document.getElementById("win"+win_num+objID);',
- \ " if(fold.className == 'closed-fold')",
- \ " {",
- \ " fold.className = 'open-fold';",
- \ " }",
- \ " else if (fold.className == 'open-fold')",
- \ " {",
- \ " fold.className = 'closed-fold';",
- \ " }",
- \ " }",
- \ " }",
- \ ])
- endif
+ if s:uses_script
+ " insert script tag if needed
+ call append(style_start, [
+ \ "<script" . (s:html5 ? "" : " type='text/javascript'") . ">",
+ \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
+ endif
- if s:uses_script
- " insert script tag if needed
- call append(style_start, [
- \ "<script" . (s:html5 ? "" : " type='text/javascript'") . ">",
- \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
+ " Insert styles from all the generated html documents and additional styles
+ " for the table-based layout of the side-by-side diff. The diff should take
+ " up the full browser window (but not more), and be static in size,
+ " horizontally scrollable when the lines are too long. Otherwise, the diff
+ " is pretty useless for really long lines. {{{
+ if s:settings.use_css
+ call append(style_start,
+ \ ['<style' . (s:html5 ? '' : 'type="text/css"') . '>']+
+ \ style+
+ \ [ s:settings.use_xhtml ? '' : '<!--',
+ \ 'table { table-layout: fixed; }',
+ \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
+ \ 'table, td, th { border: 1px solid; }',
+ \ 'td { vertical-align: top; }',
+ \ 'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }',
+ \ 'td div { overflow: auto; }',
+ \ s:settings.use_xhtml ? '' : '-->',
+ \ '</style>'
+ \])
+ endif "}}}
endif
-
- " Insert styles from all the generated html documents and additional styles
- " for the table-based layout of the side-by-side diff. The diff should take
- " up the full browser window (but not more), and be static in size,
- " horizontally scrollable when the lines are too long. Otherwise, the diff
- " is pretty useless for really long lines. {{{
- if s:settings.use_css
- call append(style_start,
- \ ['<style' . (s:html5 ? '' : 'type="text/css"') . '>']+
- \ style+
- \ [ s:settings.use_xhtml ? '' : '<!--',
- \ 'table { table-layout: fixed; }',
- \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
- \ 'table, td, th { border: 1px solid; }',
- \ 'td { vertical-align: top; }',
- \ 'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }',
- \ 'td div { overflow: auto; }',
- \ s:settings.use_xhtml ? '' : '-->',
- \ '</style>'
- \])
- endif "}}}
endif
let &paste = s:old_paste