diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 13af2b05ce..ee70e95ab2 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -886,9 +886,9 @@ When the result is a |List| then the items are joined with separating line breaks. Thus each item becomes a line, except that they can contain line breaks themselves. -The whole matched text can be accessed with "submatch(0)". The text matched -with the first pair of () with "submatch(1)". Likewise for further -sub-matches in (). +The |submatch()| function can be used to obtain matched text. The whole +matched text can be accessed with "submatch(0)". The text matched with the +first pair of () with "submatch(1)". Likewise for further sub-matches in (). Be careful: The separation character must not appear in the expression! Consider using a character like "@" or ":". There is no problem if the result diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d72b845ecd..95aa4647d9 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4698,7 +4698,7 @@ gettagstack([{nr}]) *gettagstack()* getwinpos([{timeout}]) *getwinpos()* The result is a list with two numbers, the result of - getwinposx() and getwinposy() combined: + getwinposx() and getwinposy() combined: [x-pos, y-pos] {timeout} can be used to specify how long to wait in msec for a response from the terminal. When omitted 100 msec is used. diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 7fcf08e2a1..a2e1962ce5 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -106,7 +106,6 @@ Basic editing ~ |scroll.txt| scrolling the text in the window |insert.txt| Insert and Replace mode |change.txt| deleting and replacing text -|indent.txt| automatic indenting for C and other languages |undo.txt| Undo and Redo |repeat.txt| repeating commands, Vim scripts and debugging |visual.txt| using the Visual mode (selecting a text area) @@ -119,30 +118,36 @@ Advanced editing ~ |pattern.txt| regexp patterns and search commands |map.txt| key mapping and abbreviations |tagsrch.txt| tags and special searches -|quickfix.txt| commands for a quick edit-compile-fix cycle |windows.txt| commands for using multiple windows and buffers |tabpage.txt| commands for using multiple tab pages -|syntax.txt| syntax highlighting |spell.txt| spell checking |diff.txt| working with two to four versions of the same file |autocmd.txt| automatically executing commands on an event -|filetype.txt| settings done specifically for a type of file |eval.txt| expression evaluation, conditional commands |fold.txt| hide (fold) ranges of lines Special issues ~ |print.txt| printing |remote.txt| using Vim as a server or client -|digraph.txt| list of available digraphs -|mbyte.txt| multi-byte text support -|mlang.txt| non-English language support -|arabic.txt| Arabic language support and editing -|hebrew.txt| Hebrew language support and editing -|russian.txt| Russian language support and editing + +Programming language support ~ +|indent.txt| automatic indenting for C and other languages +|syntax.txt| syntax highlighting +|textprop.txt| Attaching properties to text for highlighting or other +|filetype.txt| settings done specifically for a type of file +|quickfix.txt| commands for a quick edit-compile-fix cycle |ft_ada.txt| Ada (the programming language) support |ft_rust.txt| Filetype plugin for Rust |ft_sql.txt| about the SQL filetype plugin + +Language support ~ +|digraph.txt| list of available digraphs +|mbyte.txt| multi-byte text support +|mlang.txt| non-English language support |rileft.txt| right-to-left editing mode +|arabic.txt| Arabic language support and editing +|hebrew.txt| Hebrew language support and editing +|russian.txt| Russian language support and editing GUI ~ |gui.txt| Graphical User Interface (GUI) diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 74c9a2a003..53b9f36ba0 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1190,7 +1190,7 @@ reported if any are supplied). However, it is possible to specify that the command can take arguments, using the -nargs attribute. Valid cases are: -nargs=0 No arguments are allowed (the default) - -nargs=1 Exactly one argument is required, it includes spaces + -nargs=1 Exactly one argument is required, it includes spaces -nargs=* Any number of arguments are allowed (0, 1, or many), separated by white space -nargs=? 0 or 1 arguments are allowed @@ -1213,8 +1213,9 @@ defined, not where it is invoked! Example: Executing script2.vim will result in "None" being echoed. Not what you intended! Calling a function may be an alternative. -Completion behavior *:command-completion* *E179* - *E180* *E181* *:command-complete* + Completion behavior ~ + *:command-completion* *E179* *E180* *E181* + *:command-complete* By default, the arguments of user defined commands do not undergo completion. However, by specifying one or the other of the following attributes, argument completion can be enabled: @@ -1335,12 +1336,13 @@ which by default correspond to the current line, last line and the whole buffer, relate to arguments, (loaded) buffers, windows or tab pages. Possible values are: - -addr=lines Range of lines (this is the default) - -addr=arguments Range for arguments - -addr=buffers Range for buffers (also not loaded buffers) - -addr=loaded_buffers Range for loaded buffers - -addr=windows Range for windows - -addr=tabs Range for tab pages + -addr=lines Range of lines (this is the default) + -addr=arguments Range for arguments + -addr=buffers Range for buffers (also not loaded buffers) + -addr=loaded_buffers Range for loaded buffers + -addr=windows Range for windows + -addr=tabs Range for tab pages + -addr=other other kind of range Special cases *:command-bang* *:command-bar* diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 0a552a1309..d4eb3f0f6e 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -306,7 +306,10 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. ||. :scr[iptnames][!] {scriptId} *:script* - Edit script {scriptId}. Suggested name is ":script". + Edit script {scriptId}. Although ":scriptnames name" + works, using ":script name" is recommended. + When the current buffer can't be |abandon|ed and the ! + is not present, the command fails. *:fini* *:finish* *E168* :fini[sh] Stop sourcing a script. Can only be used in a Vim diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index ae119f6fdd..b710829d40 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -346,20 +346,9 @@ Upon loading a file, Vim finds the relevant syntax file as follows: syntax. ============================================================================== -4. Syntax file remarks *:syn-file-remarks* +4. Conversion to HTML *2html.vim* *convert-to-HTML* - *b:current_syntax-variable* -Vim stores the name of the syntax that has been loaded in the -"b:current_syntax" variable. You can use this if you want to load other -settings, depending on which syntax is active. Example: > - :au BufReadPost * if b:current_syntax == "csh" - :au BufReadPost * do-some-things - :au BufReadPost * endif - - -2HTML *2html.vim* *convert-to-HTML* - -This is not a syntax file itself, but a script that converts the current +2html is not a syntax file itself, but a script that converts the current window into HTML. Vim opens a new window in which it builds the HTML file. After you save the resulting file, you can view it with any browser. The @@ -751,6 +740,18 @@ When 1, generate XHTML 1.0 instead (XML compliant HTML). > :let g:html_use_xhtml = 1 < +============================================================================== +5. Syntax file remarks *:syn-file-remarks* + + *b:current_syntax-variable* +Vim stores the name of the syntax that has been loaded in the +"b:current_syntax" variable. You can use this if you want to load other +settings, depending on which syntax is active. Example: > + :au BufReadPost * if b:current_syntax == "csh" + :au BufReadPost * do-some-things + :au BufReadPost * endif + + ABEL *abel.vim* *ft-abel-syntax* @@ -3440,7 +3441,7 @@ The syntax script for zsh allows for syntax-based folding: > :let g:zsh_fold_enable = 1 ============================================================================== -5. Defining a syntax *:syn-define* *E410* +6. Defining a syntax *:syn-define* *E410* Vim understands three types of syntax items: @@ -3799,7 +3800,7 @@ DEFINING REGIONS *:syn-region* *:syn-start* *:syn-skip* *:syn-end* The maximum number of syntax groups is 19999. ============================================================================== -6. :syntax arguments *:syn-arguments* +7. :syntax arguments *:syn-arguments* The :syntax commands that define syntax items take a number of arguments. The common ones are explained here. The arguments may be given in any order @@ -4120,7 +4121,7 @@ IMPLICIT CONCEAL *:syn-conceal-implicit* Show either "syntax conceal on" or "syntax conceal off" (translated). ============================================================================== -7. Syntax patterns *:syn-pattern* *E401* *E402* +8. Syntax patterns *:syn-pattern* *E401* *E402* In the syntax commands, a pattern must be surrounded by two identical characters. This is like it works for the ":s" command. The most common to @@ -4298,7 +4299,7 @@ Note that only matches within a single line can be used. Multi-line matches cannot be referred to. ============================================================================== -8. Syntax clusters *:syn-cluster* *E400* +9. Syntax clusters *:syn-cluster* *E400* :sy[ntax] cluster {cluster-name} [contains={group-name}..] [add={group-name}..] @@ -4344,7 +4345,7 @@ This also has implications for nested clusters: > The maximum number of clusters is 9767. ============================================================================== -9. Including syntax files *:syn-include* *E397* +10. Including syntax files *:syn-include* *E397* It is often useful for one language's syntax file to include a syntax file for a related language. Depending on the exact relationship, this can be done in @@ -4385,7 +4386,7 @@ two different ways: The maximum number of includes is 999. ============================================================================== -10. Synchronizing *:syn-sync* *E403* *E404* +11. Synchronizing *:syn-sync* *E403* *E404* Vim wants to be able to start redrawing in any position in the document. To make this possible it needs to know the syntax state at the position where @@ -4577,7 +4578,7 @@ You can clear specific sync patterns with: > :syntax sync clear {sync-group-name} .. ============================================================================== -11. Listing syntax items *:syntax* *:sy* *:syn* *:syn-list* +12. Listing syntax items *:syntax* *:sy* *:syn* *:syn-list* This command lists all the syntax items: > @@ -5090,7 +5091,7 @@ Without the "default" in the C syntax file, the highlighting would be overruled when the syntax file is loaded. ============================================================================== -14. Cleaning up *:syn-clear* *E391* +15. Cleaning up *:syn-clear* *E391* If you want to clear the syntax stuff for the current buffer, you can use this command: > @@ -5180,7 +5181,7 @@ syntax/syncolor.vim files are loaded: them. ============================================================================== -15. Highlighting tags *tag-highlight* +16. Highlighting tags *tag-highlight* If you want to highlight all the tags in your file, you can use the following mappings. @@ -5215,7 +5216,7 @@ And put these lines in your vimrc: > autocmd BufRead,BufNewFile *.[ch] endif ============================================================================== -16. Window-local syntax *:ownsyntax* +17. Window-local syntax *:ownsyntax* Normally all windows on a buffer share the same syntax settings. It is possible, however, to set a particular window on a file to have its own diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 360932126f..eb50dc421a 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -995,7 +995,7 @@ Various: *various-functions* py3eval() evaluate Python expression (|+python3|) pyeval() evaluate Python expression (|+python|) pyxeval() evaluate |python_x| expression - debugbreak() interrupt a program being debugged + debugbreak() interrupt a program being debugged ============================================================================== *41.7* Defining a function diff --git a/runtime/indent/falcon.vim b/runtime/indent/falcon.vim index b34e7cfd47..664ad61aa5 100644 --- a/runtime/indent/falcon.vim +++ b/runtime/indent/falcon.vim @@ -368,7 +368,7 @@ function FalconGetIndent(...) return indent('.') endif else - call cursor(clnum, vcol) + call cursor(clnum, 0) " FIXME: column was vcol end endif diff --git a/runtime/indent/matlab.vim b/runtime/indent/matlab.vim index 6a31624389..d2818a18ea 100644 --- a/runtime/indent/matlab.vim +++ b/runtime/indent/matlab.vim @@ -1,74 +1,121 @@ -" Matlab indent file -" Language: Matlab -" Maintainer: Christophe Poucet -" Last Change: 6 January, 2001 +" Vim indent file +" Language: MATLAB +" Maintainer: Axel Forsman +" Previous maintainer: Christophe Poucet -" Only load this indent file when no other was loaded. -if exists("b:did_indent") - finish -endif +" Only load if no other indent file is loaded +if exists('b:did_indent') | finish | endif let b:did_indent = 1 -" Some preliminary setting -setlocal indentkeys=!,o,O=end,=case,=else,=elseif,=otherwise,=catch +setlocal indentexpr=GetMatlabIndent() +setlocal indentkeys=!,o,O,e,0=end,0=elseif,0=case,0=otherwise,0=catch,0=function,0=elsei +" The value of the Function indenting format in +" MATLAB Editor/Debugger Language Preferences. +" The possible values are 0 for Classic, 1 for Indent nested functions +" and 2 for Indent all functions (default). +let b:MATLAB_function_indent = get(g:, 'MATLAB_function_indent', 2) +" The previous value of b:changedtick +let b:MATLAB_lasttick = -1 +" The previously indented line +let b:MATLAB_lastline = -1 +" Whether the line above was a line continuation +let b:MATLAB_waslc = 0 +let b:MATLAB_bracketlevel = 0 -setlocal indentexpr=GetMatlabIndent(v:lnum) +" Only define the function once +if exists("*GetMatlabIndent") | finish | endif -" Only define the function once. -if exists("*GetMatlabIndent") - finish -endif +let s:keepcpo = &cpo +set cpo&vim -function GetMatlabIndent(lnum) - " Give up if this line is explicitly joined. - if getline(a:lnum - 1) =~ '\\$' - return -1 - endif +let s:end = '\\%([^(]*)\)\@!' " Array indexing heuristic +let s:open_pat = 'for\|if\|parfor\|spmd\|switch\|try\|while\|classdef\|properties\|methods\|events\|enumeration' +let s:dedent_pat = '\C^\s*\zs\<\%(end\|else\|elseif\|catch\|\(case\|otherwise\|function\)\)\>' +let s:start_pat = '\C\<\%(function\|' . s:open_pat . '\)\>' +let s:bracket_pair_pat = '\(\[\|{\)\|\(\]\|}\)' +let s:zflag = has('patch-7.4.984') ? 'z' : '' - " Search backwards for the first non-empty line. - let plnum = a:lnum - 1 - while plnum > 0 && getline(plnum) =~ '^\s*$' - let plnum = plnum - 1 - endwhile - - if plnum == 0 - " This is the first non-empty line, use zero indent. - return 0 - endif - - let curind = indent(plnum) - - " If the current line is a stop-block statement... - if getline(v:lnum) =~ '^\s*\(end\|else\|elseif\|case\|otherwise\|catch\)\>' - " See if this line does not follow the line right after an openblock - if getline(plnum) =~ '^\s*\(for\|if\|else\|elseif\|case\|while\|switch\|try\|otherwise\|catch\)\>' - " See if the user has already dedented - elseif indent(v:lnum) > curind - shiftwidth() - " If not, recommend one dedent - let curind = curind - shiftwidth() - else - " Otherwise, trust the user - return -1 - endif -" endif - - " If the previous line opened a block - elseif getline(plnum) =~ '^\s*\(for\|if\|else\|elseif\|case\|while\|switch\|try\|otherwise\|catch\)\>' - " See if the user has already indented - if indent(v:lnum) < curind + shiftwidth() - "If not, recommend indent - let curind = curind + shiftwidth() - else - " Otherwise, trust the user - return -1 - endif - endif - - - - " If we got to here, it means that the user takes the standardversion, so we return it - return curind +" Returns whether a comment or string envelops the specified column. +function! s:IsCommentOrString(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), "name") =~# 'matlabComment\|matlabMultilineComment\|matlabString' endfunction -" vim:sw=2 +" Returns whether the specified line continues on the next line. +function! s:IsLineContinuation(lnum) + let l = getline(a:lnum) | let c = -3 + while 1 + let c = match(l, '\.\{3}', c + 3) + if c == -1 | return 0 + elseif !s:IsCommentOrString(a:lnum, c) | return 1 | endif + endwhile +endfunction + +function! s:SubmatchCount(lnum, pattern, ...) + let endcol = a:0 >= 1 ? a:1 : 1 / 0 | let x = [0, 0, 0, 0] + call cursor(a:lnum, 1) + while 1 + let [lnum, c, submatch] = searchpos(a:pattern, 'cpe' . s:zflag, a:lnum) + if !submatch || c >= endcol | break | endif + if !s:IsCommentOrString(lnum, c) | let x[submatch - 2] += 1 | endif + if cursor(0, c + 1) == -1 || col('.') == c | break | endif + endwhile + return x +endfunction + +function! s:GetOpenCloseCount(lnum, pattern, ...) + let counts = call('s:SubmatchCount', [a:lnum, a:pattern] + a:000) + return counts[0] - counts[1] +endfunction + +function! GetMatlabIndent() + let prevlnum = prevnonblank(v:lnum - 1) + + if b:MATLAB_lasttick != b:changedtick || b:MATLAB_lastline != prevlnum + " Recalculate bracket count (only have to check same block and line above) + let b:MATLAB_bracketlevel = 0 + let previndent = indent(prevlnum) | let l = prevlnum + while 1 + let l = prevnonblank(l - 1) | let indent = indent(l) + if l <= 0 || previndent < indent | break | endif + let b:MATLAB_bracketlevel += s:GetOpenCloseCount(l, s:bracket_pair_pat) + if previndent != indent | break | endif + endwhile + + let b:MATLAB_waslc = s:IsLineContinuation(prevlnum - 1) + endif + " If line above was blank it can impossibly have been a LC + let above_lc = b:MATLAB_lasttick == b:changedtick && prevlnum != v:lnum - 1 && b:MATLAB_lastline == prevlnum ? 0 : s:IsLineContinuation(v:lnum - 1) + + let pair_pat = '\C\<\(' . s:open_pat . '\|' + \ . (b:MATLAB_function_indent == 1 ? '^\@= 1 ? 'function\|' : '') + \ . '\|\%(^\s*\)\@<=\%(else\|elseif\|case\|otherwise\|catch\)\)\>' + \ . '\|\S\s*\zs\(' . s:end . '\)' + let [open, close, b_open, b_close] = prevlnum ? s:SubmatchCount(prevlnum, + \ pair_pat . '\|' . s:bracket_pair_pat) : [0, 0, 0, 0] + let curbracketlevel = b:MATLAB_bracketlevel + b_open - b_close + + call cursor(v:lnum, 1) + let submatch = search(s:dedent_pat, 'cp' . s:zflag, v:lnum) + if submatch && !s:IsCommentOrString(v:lnum, col('.')) + " Align end, et cetera with start of block + let [lnum, col] = searchpairpos(s:start_pat, '', '\C' . s:end, 'bW', 's:IsCommentOrString(line("."), col("."))') + let result = lnum ? indent(lnum) + shiftwidth() * (s:GetOpenCloseCount(lnum, pair_pat, col) + submatch == 2) : 0 + else + " Count how many blocks the previous line opens/closes + " Line continuations/brackets indent once per statement + let result = indent(prevlnum) + shiftwidth() * (open - close + \ + (b:MATLAB_bracketlevel ? -!curbracketlevel : !!curbracketlevel) + \ + (curbracketlevel <= 0) * (above_lc - b:MATLAB_waslc)) + endif + + let b:MATLAB_waslc = above_lc + let b:MATLAB_bracketlevel = curbracketlevel + let b:MATLAB_lasttick = b:changedtick + let b:MATLAB_lastline = v:lnum + return result +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo diff --git a/runtime/indent/testdir/matlab.in b/runtime/indent/testdir/matlab.in index 1a2bc83d4b..5bba1a56dd 100644 --- a/runtime/indent/testdir/matlab.in +++ b/runtime/indent/testdir/matlab.in @@ -15,3 +15,66 @@ catch exception statements end % END_INDENT + +% START_INDENT +if true, ... +if true +disp hello +end +end +% END_INDENT + +% START_INDENT +switch a +case expr +if true, foo; end +disp hello +otherwise +disp bar +end +% END_INDENT + +% START_INDENT +if true +A(1:end - 1) +disp foo +end +% END_INDENT + +% START_INDENT +A = [{ +} +] ... +disp foo +disp bar +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 0 +function foo +disp foo +function nested +disp bar +end +end +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 1 +function foo +disp foo +function nested +disp bar +end +end +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 2 +function foo +disp foo +function nested +disp bar +end +end +% END_INDENT diff --git a/runtime/indent/testdir/matlab.ok b/runtime/indent/testdir/matlab.ok index 88e1d86b06..b1112263b2 100644 --- a/runtime/indent/testdir/matlab.ok +++ b/runtime/indent/testdir/matlab.ok @@ -15,3 +15,66 @@ catch exception statements end % END_INDENT + +% START_INDENT +if true, ... + if true + disp hello + end +end +% END_INDENT + +% START_INDENT +switch a + case expr + if true, foo; end + disp hello + otherwise + disp bar +end +% END_INDENT + +% START_INDENT +if true + A(1:end - 1) + disp foo +end +% END_INDENT + +% START_INDENT +A = [{ + } + ] ... + disp foo +disp bar +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 0 +function foo +disp foo + function nested + disp bar + end +end +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 1 +function foo +disp foo + function nested + disp bar + end +end +% END_INDENT + +% START_INDENT +% INDENT_EXE let b:MATLAB_function_indent = 2 +function foo + disp foo + function nested + disp bar + end +end +% END_INDENT diff --git a/runtime/indent/testdir/tcl.in b/runtime/indent/testdir/tcl.in index 3ef4ebc0a8..c769d5bf5e 100644 --- a/runtime/indent/testdir/tcl.in +++ b/runtime/indent/testdir/tcl.in @@ -1,4 +1,4 @@ -# vim: set filetype=tcl shiftwidth=4 tabstop=4: +# vim: set filetype=tcl shiftwidth=4 tabstop=8 expandtab : # START_INDENT proc abc {} { diff --git a/runtime/indent/testdir/tcl.ok b/runtime/indent/testdir/tcl.ok index 0fb52e782f..77f24e9044 100644 --- a/runtime/indent/testdir/tcl.ok +++ b/runtime/indent/testdir/tcl.ok @@ -1,19 +1,19 @@ -# vim: set filetype=tcl shiftwidth=4 tabstop=4: +# vim: set filetype=tcl shiftwidth=4 tabstop=8 expandtab : # START_INDENT proc abc {} { - set a 5 - if {[some_cmd]==1} { - foreach i [list {1 2 3}] { - # Does this comment affect anything? - puts $i - } - } + set a 5 + if {[some_cmd]==1} { + foreach i [list {1 2 3}] { + # Does this comment affect anything? + puts $i + } + } } command_with_a_long_time -arg1 "First" \ - -arg2 "Second" \ - -arg3 "Third" + -arg2 "Second" \ + -arg3 "Third" puts "Move indent back after line continuation is complete" # END_INDENT diff --git a/runtime/indent/testdir/xml.in b/runtime/indent/testdir/xml.in index d184681c86..b6333340e2 100644 --- a/runtime/indent/testdir/xml.in +++ b/runtime/indent/testdir/xml.in @@ -1,4 +1,4 @@ - + diff --git a/runtime/indent/testdir/xml.ok b/runtime/indent/testdir/xml.ok index a8e2c92a16..529198572a 100644 --- a/runtime/indent/testdir/xml.ok +++ b/runtime/indent/testdir/xml.ok @@ -1,32 +1,32 @@ - + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + diff --git a/runtime/indent/xml.vim b/runtime/indent/xml.vim index 7afcc89b7f..bc64aacfe1 100644 --- a/runtime/indent/xml.vim +++ b/runtime/indent/xml.vim @@ -1,15 +1,21 @@ -" Language: xml -" Repository: https://github.com/chrisbra/vim-xml-ftplugin -" Maintainer: Christian Brabandt -" Previous Maintainer: Johannes Zellner -" Last Change: 20181022 - Do not overwrite indentkeys setting -" https://github.com/chrisbra/vim-xml-ftplugin/issues/1 -" 20180724 - Correctly indent xml comments https://github.com/vim/vim/issues/3200 -" Notes: 1) does not indent pure non-xml code (e.g. embedded scripts) -" 2) will be confused by unbalanced tags in comments -" or CDATA sections. -" 2009-05-26 patch by Nikolai Weibull -" TODO: implement pre-like tags, see xml_indent_open / xml_indent_close +" Language: xml +" Repository: https://github.com/chrisbra/vim-xml-ftplugin +" Last Changed: Dec 07th, 2018 +" Maintainer: Christian Brabandt +" Previous Maintainer: Johannes Zellner +" Last Change: +" 20181116 - Fix indentation when tags start with a colon or an underscore +" https://github.com/vim/vim/pull/926 +" 20181022 - Do not overwrite indentkeys setting +" https://github.com/chrisbra/vim-xml-ftplugin/issues/1 +" 20180724 - Correctly indent xml comments https://github.com/vim/vim/issues/3200 +" +" Notes: +" 1) does not indent pure non-xml code (e.g. embedded scripts) +" 2) will be confused by unbalanced tags in comments +" or CDATA sections. +" 2009-05-26 patch by Nikolai Weibull +" TODO: implement pre-like tags, see xml_indent_open / xml_indent_close " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -20,11 +26,12 @@ let s:keepcpo= &cpo set cpo&vim " [-- local settings (must come before aborting the script) --] +" Attention: Parameter use_syntax_check is used by the docbk.vim indent script setlocal indentexpr=XmlIndentGet(v:lnum,1) setlocal indentkeys=o,O,*,<>>,<<>,/,{,},!^F if !exists('b:xml_indent_open') - let b:xml_indent_open = '.\{-}<\a' + let b:xml_indent_open = '.\{-}<[:A-Z_a-z]' " pre tag, e.g.
" let b:xml_indent_open = '.\{-}<[/]\@!\(address\)\@!' endif @@ -40,7 +47,7 @@ unlet s:keepcpo " [-- finish, if the function already exists --] if exists('*XmlIndentGet') - finish + finish endif let s:keepcpo= &cpo @@ -53,13 +60,13 @@ endfun " [-- check if it's xml --] fun! XmlIndentSynCheck(lnum) - if '' != &syntax - let syn1 = synIDattr(synID(a:lnum, 1, 1), 'name') - let syn2 = synIDattr(synID(a:lnum, strlen(getline(a:lnum)) - 1, 1), 'name') - if '' != syn1 && syn1 !~ 'xml' && '' != syn2 && syn2 !~ 'xml' - " don't indent pure non-xml code - return 0 - endif + if &syntax != '' + let syn1 = synIDattr(synID(a:lnum, 1, 1), 'name') + let syn2 = synIDattr(synID(a:lnum, strlen(getline(a:lnum)) - 1, 1), 'name') + if syn1 != '' && syn1 !~ 'xml' && syn2 != '' && syn2 !~ 'xml' + " don't indent pure non-xml code + return 0 + endif endif return 1 endfun @@ -68,41 +75,72 @@ endfun fun! XmlIndentSum(lnum, style, add) let line = getline(a:lnum) if a:style == match(line, '^\s*XmlIndentWithPattern(line, b:xml_indent_open) - \ - XmlIndentWithPattern(line, b:xml_indent_close) - \ - XmlIndentWithPattern(line, '.\{-}/>'))) + a:add + return (shiftwidth() * + \ (XmlIndentWithPattern(line, b:xml_indent_open) + \ - XmlIndentWithPattern(line, b:xml_indent_close) + \ - XmlIndentWithPattern(line, '.\{-}/>'))) + a:add else - return a:add + return a:add endif endfun +" Main indent function fun! XmlIndentGet(lnum, use_syntax_check) " Find a non-empty line above the current line. - let lnum = prevnonblank(a:lnum - 1) + let plnum = prevnonblank(a:lnum - 1) + " Find previous line with a tag (regardless whether open or closed) + let ptag = search('.\{-}<[/:A-Z_a-z]', 'bnw') " Hit the start of the file, use zero indent. - if lnum == 0 - return 0 + if plnum == 0 + return 0 endif + let syn_name = '' if a:use_syntax_check - let check_lnum = XmlIndentSynCheck(lnum) - let check_alnum = XmlIndentSynCheck(a:lnum) - if 0 == check_lnum || 0 == check_alnum - return indent(a:lnum) - elseif -1 == check_lnum || -1 == check_alnum - return -1 - endif + let check_lnum = XmlIndentSynCheck(plnum) + let check_alnum = XmlIndentSynCheck(a:lnum) + if check_lnum == 0 || check_alnum == 0 + return indent(a:lnum) + endif + let syn_name = synIDattr(synID(a:lnum, strlen(getline(a:lnum)) - 1, 1), 'name') endif - let ind = XmlIndentSum(lnum, -1, indent(lnum)) - let ind = XmlIndentSum(a:lnum, 0, ind) + if syn_name =~ 'Comment' + return XmlIndentComment(a:lnum) + endif + " Get indent from previous tag line + let ind = XmlIndentSum(ptag, -1, indent(ptag)) + " Determine indent from current line + let ind = XmlIndentSum(a:lnum, 0, ind) return ind endfun +" return indent for a commented line, +" the middle part might be indented on additional level +func! XmlIndentComment(lnum) + let ptagopen = search(b:xml_indent_open, 'bnw') + let ptagclose = search(b:xml_indent_close, 'bnw') + if getline(a:lnum) =~ '' + " end of comment, same as start of comment + return indent(search('