diff options
Diffstat (limited to 'runtime')
96 files changed, 4278 insertions, 1685 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index a3db4ae87a..69712046a5 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -1,7 +1,7 @@ " Vim functions for file type detection " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2021 Nov 27 +" Last Change: 2022 Jan 11 " These functions are moved here from runtime/filetype.vim to make startup " faster. @@ -67,13 +67,29 @@ func dist#ft#FTasmsyntax() endif endfunc -" Check if one of the first five lines contains "VB_Name". In that case it is -" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype. -func dist#ft#FTVB(alt) - if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)' +func dist#ft#FTbas() + if exists("g:filetype_bas") + exe "setf " . g:filetype_bas + return + endif + + " most frequent FreeBASIC-specific keywords in distro files + let fb_keywords = '\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!' + let fb_preproc = '\c^\s*\%(#\a\+\|option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\)' + let fb_comment = "^\\s*/'" + " OPTION EXPLICIT, without the leading underscore, is common to many dialects + let qb64_preproc = '\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)' + + let lines = getline(1, min([line("$"), 100])) + + if match(lines, fb_preproc) > -1 || match(lines, fb_comment) > -1 || match(lines, fb_keywords) > -1 + setf freebasic + elseif match(lines, qb64_preproc) > -1 + setf qb64 + elseif match(lines, '\cVB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)') > -1 setf vb else - exe "setf " . a:alt + setf basic endif endfunc @@ -811,6 +827,40 @@ func dist#ft#Redif() endwhile endfunc +" This function is called for all files under */debian/patches/*, make sure not +" to non-dep3patch files, such as README and other text files. +func dist#ft#Dep3patch() + if expand('%:t') ==# 'series' + return + endif + + for ln in getline(1, 100) + if ln =~# '^\%(Description\|Subject\|Origin\|Bug\|Forwarded\|Author\|From\|Reviewed-by\|Acked-by\|Last-Updated\|Applied-Upstream\):' + setf dep3patch + return + elseif ln =~# '^---' + " end of headers found. stop processing + return + endif + endfor +endfunc + +" This function checks the first 15 lines for appearance of 'FoamFile' +" and then 'object' in a following line. +" In that case, it's probably an OpenFOAM file +func dist#ft#FTfoam() + let ffile = 0 + let lnum = 1 + while lnum <= 15 + if getline(lnum) =~# '^FoamFile' + let ffile = 1 + elseif ffile == 1 && getline(lnum) =~# '^\s*object' + setf foam + return + endif + let lnum = lnum + 1 + endwhile +endfunc " Restore 'cpoptions' let &cpo = s:cpo_save diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim index 73c1459f86..1d462ad02c 100644 --- a/runtime/autoload/health.vim +++ b/runtime/autoload/health.vim @@ -1,27 +1,3 @@ -function! s:enhance_syntax() abort - syntax case match - - syntax keyword healthError ERROR[:] - \ containedin=markdownCodeBlock,mkdListItemLine - highlight default link healthError Error - - syntax keyword healthWarning WARNING[:] - \ containedin=markdownCodeBlock,mkdListItemLine - highlight default link healthWarning WarningMsg - - syntax keyword healthSuccess OK[:] - \ containedin=markdownCodeBlock,mkdListItemLine - highlight default healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232 - - syntax match healthHelp "|.\{-}|" contains=healthBar - \ containedin=markdownCodeBlock,mkdListItemLine - syntax match healthBar "|" contained conceal - highlight default link healthHelp Identifier - - " We do not care about markdown syntax errors in :checkhealth output. - highlight! link markdownError Normal -endfunction - " Runs the specified healthchecks. " Runs all discovered healthchecks if a:plugin_names is empty. function! health#check(plugin_names) abort @@ -29,13 +5,9 @@ function! health#check(plugin_names) abort \ ? s:discover_healthchecks() \ : s:get_healthcheck(a:plugin_names) - tabnew - setlocal wrap breakindent linebreak - setlocal filetype=markdown - setlocal conceallevel=2 concealcursor=nc - setlocal keywordprg=:help - let &l:iskeyword='!-~,^*,^|,^",192-255' - call s:enhance_syntax() + " create scratch-buffer + execute 'tab sbuffer' nvim_create_buf(v:true, v:true) + setfiletype checkhealth if empty(healthchecks) call setline(1, 'ERROR: No healthchecks found.') @@ -70,8 +42,6 @@ function! health#check(plugin_names) abort " needed for plasticboy/vim-markdown, because it uses fdm=expr normal! zR - setlocal nomodified - setlocal bufhidden=hide redraw|echo '' endfunction diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim index 7b4dce3441..e6523aa215 100644 --- a/runtime/autoload/health/provider.vim +++ b/runtime/autoload/health/provider.vim @@ -523,7 +523,7 @@ function! s:check_virtualenv() abort let hint = '$PATH ambiguities in subshells typically are ' \.'caused by your shell config overriding the $PATH previously set by the ' \.'virtualenv. Either prevent them from doing so, or use this workaround: ' - \.'https://vi.stackexchange.com/a/7654' + \.'https://vi.stackexchange.com/a/34996' let hints[hint] = v:true endif endfor diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index 90d353f9de..b28170b7a1 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -7,7 +7,6 @@ let s:loaded_man = 1 let s:find_arg = '-w' let s:localfile_arg = v:true " Always use -l if possible. #6683 -let s:section_arg = '-S' function! man#init() abort try @@ -216,16 +215,42 @@ endfunction function! s:get_path(sect, name) abort " Some man implementations (OpenBSD) return all available paths from the - " search command, so we get() the first one. #8341 + " search command. Previously, this function would simply select the first one. + " + " However, some searches will report matches that are incorrect: + " man -w strlen may return string.3 followed by strlen.3, and therefore + " selecting the first would get us the wrong page. Thus, we must find the + " first matching one. + " + " There's yet another special case here. Consider the following: + " If you run man -w strlen and string.3 comes up first, this is a problem. We + " should search for a matching named one in the results list. + " However, if you search for man -w clock_gettime, you will *only* get + " clock_getres.2, which is the right page. Searching the resuls for + " clock_gettime will no longer work. In this case, we should just use the + " first one that was found in the correct section. + " + " Finally, we can avoid relying on -S or -s here since they are very + " inconsistently supported. Instead, call -w with a section and a name. if empty(a:sect) - return substitute(get(split(s:system(['man', s:find_arg, a:name])), 0, ''), '\n\+$', '', '') + let results = split(s:system(['man', s:find_arg, a:name])) + else + let results = split(s:system(['man', s:find_arg, a:sect, a:name])) + endif + + if empty(results) + return '' endif - " '-s' flag handles: - " - tokens like 'printf(echo)' - " - sections starting with '-' - " - 3pcap section (found on macOS) - " - commas between sections (for section priority) - return substitute(get(split(s:system(['man', s:find_arg, s:section_arg, a:sect, a:name])), 0, ''), '\n\+$', '', '') + + " find any that match the specified name + let namematches = filter(copy(results), 'fnamemodify(v:val, ":t") =~ a:name') + let sectmatches = [] + + if !empty(namematches) && !empty(a:sect) + let sectmatches = filter(copy(namematches), 'fnamemodify(v:val, ":e") == a:sect') + endif + + return substitute(get(sectmatches, 0, get(namematches, 0, results[0])), '\n\+$', '', '') endfunction " s:verify_exists attempts to find the path to a manpage @@ -243,40 +268,72 @@ endfunction " then we don't do it again in step 2. function! s:verify_exists(sect, name) abort let sect = a:sect - if empty(sect) - let sect = get(b:, 'man_default_sects', '') - endif - try - return s:get_path(sect, a:name) - catch /^command error (/ - endtry - - if !empty(get(b:, 'man_default_sects', '')) && sect !=# b:man_default_sects + if empty(sect) + " no section specified, so search with b:man_default_sects + if exists('b:man_default_sects') + let sects = split(b:man_default_sects, ',') + for sec in sects + try + let res = s:get_path(sec, a:name) + if !empty(res) + return res + endif + catch /^command error (/ + endtry + endfor + endif + else + " try with specified section try - return s:get_path(b:man_default_sects, a:name) + let res = s:get_path(sect, a:name) + if !empty(res) + return res + endif catch /^command error (/ endtry - endif - if !empty(sect) - try - return s:get_path('', a:name) - catch /^command error (/ - endtry + " try again with b:man_default_sects + if exists('b:man_default_sects') + let sects = split(b:man_default_sects, ',') + for sec in sects + try + let res = s:get_path(sec, a:name) + if !empty(res) + return res + endif + catch /^command error (/ + endtry + endfor + endif endif + " if none of the above worked, we will try with no section + try + let res = s:get_path('', a:name) + if !empty(res) + return res + endif + catch /^command error (/ + endtry + + " if that still didn't work, we will check for $MANSECT and try again with it + " unset if !empty($MANSECT) try let MANSECT = $MANSECT call setenv('MANSECT', v:null) - return s:get_path('', a:name) + let res = s:get_path('', a:name) + if !empty(res) + return res + endif catch /^command error (/ finally call setenv('MANSECT', MANSECT) endtry endif + " finally, if that didn't work, there is no hope throw 'no manual entry for ' . a:name endfunction diff --git a/runtime/autoload/msgpack.vim b/runtime/autoload/msgpack.vim index 7dd225e3d9..7f98a5b230 100644 --- a/runtime/autoload/msgpack.vim +++ b/runtime/autoload/msgpack.vim @@ -56,6 +56,7 @@ function s:msgpack_init_python() abort \. " time = datetime.datetime.fromtimestamp(timestamp)\n" \. " return time.strftime(fmt)\n" \. "def shada_dict_strptime():\n" + \. " import calendar\n" \. " import datetime\n" \. " import vim\n" \. " fmt = vim.eval('a:format')\n" @@ -64,7 +65,10 @@ function s:msgpack_init_python() abort \. " try:\n" \. " timestamp = int(timestamp.timestamp())\n" \. " except:\n" - \. " timestamp = int(timestamp.strftime('%s'))\n" + \. " try:\n" + \. " timestamp = int(timestamp.strftime('%s'))\n" + \. " except:\n" + \. " timestamp = calendar.timegm(timestamp.utctimetuple())\n" \. " if timestamp > 2 ** 31:\n" \. " tsabs = abs(timestamp)\n" \. " return ('{\"_TYPE\": v:msgpack_types.integer,'\n" diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 8fb6290e50..2da1f5e40d 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -45,7 +45,7 @@ start with a TCP/IP socket instead, use |--listen| with a TCP-style address: > More endpoints can be started with |serverstart()|. Note that localhost TCP sockets are generally less secure than named pipes, -and can lead to vunerabilities like remote code execution. +and can lead to vulnerabilities like remote code execution. Connecting to the socket is the easiest way a programmer can test the API, which can be done through any msgpack-rpc client library or full-featured @@ -198,7 +198,7 @@ any of these approaches: 2. Start Nvim with |--api-info|. Useful for statically-compiled clients. Example (requires Python "pyyaml" and "msgpack-python" modules): > - nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))' + nvim --api-info | python -c 'import msgpack, sys, yaml; yaml.dump(msgpack.unpackb(sys.stdin.buffer.read()), sys.stdout)' < 3. Use the |api_info()| Vimscript function. > :lua print(vim.inspect(vim.fn.api_info())) @@ -361,7 +361,7 @@ UTF-32 and UTF-16 sizes of the deleted region is also passed as additional arguments {old_utf32_size} and {old_utf16_size}. "on_changedtick" is invoked when |b:changedtick| was incremented but no text -was changed. The parameters recieved are ("changedtick", {buf}, {changedtick}). +was changed. The parameters received are ("changedtick", {buf}, {changedtick}). *api-lua-detach* In-process Lua callbacks can detach by returning `true`. This will detach all @@ -468,7 +468,7 @@ extmark position and enter some text, the extmark migrates forward. > f o o z|b a r line (| = cursor) 4 extmark (after typing "z") -If an extmark is on the last index of a line and you inputsa newline at that +If an extmark is on the last index of a line and you inputs a newline at that point, the extmark will accordingly migrate to the next line: > f o o z b a r| line (| = cursor) @@ -626,6 +626,59 @@ nvim__stats() *nvim__stats()* Return: ~ Map of various internal stats. + *nvim_add_user_command()* +nvim_add_user_command({name}, {command}, {*opts}) + Create a new user command |user-commands| + + {name} is the name of the new command. The name must begin + with an uppercase letter. + + {command} is the replacement text or Lua function to execute. + + Example: > + :call nvim_add_user_command('SayHello', 'echo "Hello world!"', {}) + :SayHello + Hello world! +< + + Parameters: ~ + {name} Name of the new user command. Must begin with + an uppercase letter. + {command} Replacement command to execute when this user + command is executed. When called from Lua, the + command can also be a Lua function. The + function is called with a single table argument + that contains the following keys: + • args: (string) The args passed to the + command, if any |<args>| + • bang: (boolean) "true" if the command was + executed with a ! modifier |<bang>| + • line1: (number) The starting line of the + command range |<line1>| + • line2: (number) The final line of the command + range |<line2>| + • range: (number) The number of items in the + command range: 0, 1, or 2 |<range>| + • count: (number) Any count supplied |<count>| + • reg: (string) The optional register, if + specified |<reg>| + • mods: (string) Command modifiers, if any + |<mods>| + {opts} Optional command attributes. See + |command-attributes| for more details. To use + boolean attributes (such as |:command-bang| or + |:command-bar|) set the value to "true". In + addition to the string options listed in + |:command-complete|, the "complete" key also + accepts a Lua function which works like the + "customlist" completion mode + |:command-completion-customlist|. Additional + parameters: + • desc: (string) Used for listing the command + when a Lua function is used for {command}. + • force: (boolean, default true) Override any + previous definition. + nvim_call_atomic({calls}) *nvim_call_atomic()* Calls many API methods atomically. @@ -634,7 +687,7 @@ nvim_call_atomic({calls}) *nvim_call_atomic()* atomically, i.e. without interleaving redraws, RPC requests from other clients, or user interactions (however API methods may trigger autocommands or event processing which - have such side-effects, e.g. |:sleep| may wake timers). + have such side effects, e.g. |:sleep| may wake timers). 2. To minimize RPC overhead (roundtrips) of a sequence of many requests. @@ -656,8 +709,8 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()* Send data to channel `id` . For a job, it writes it to the stdin of the process. For the stdio channel |channel-stdio|, it writes to Nvim's stdout. For an internal terminal instance - (|nvim_open_term()|) it writes directly to terimal output. See - |channel-bytes| for more information. + (|nvim_open_term()|) it writes directly to terminal output. + See |channel-bytes| for more information. This function writes raw data, not RPC messages. If the channel was created with `rpc=true` then the channel expects @@ -698,7 +751,7 @@ nvim_del_keymap({mode}, {lhs}) *nvim_del_keymap()* |nvim_set_keymap()| nvim_del_mark({name}) *nvim_del_mark()* - Deletes a uppercase/file named mark. See |mark-motions|. + Deletes an uppercase/file named mark. See |mark-motions|. Note: fails with error if a lowercase or buffer local named mark @@ -714,6 +767,12 @@ nvim_del_mark({name}) *nvim_del_mark()* |nvim_buf_del_mark()| |nvim_get_mark()| +nvim_del_user_command({name}) *nvim_del_user_command()* + Delete a user-defined command. + + Parameters: ~ + {name} Name of the command to delete. + nvim_del_var({name}) *nvim_del_var()* Removes a global (g:) variable. @@ -1061,7 +1120,7 @@ nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()* Parameters: ~ {name} Option name {opts} Optional parameters - • scope: One of 'global' or 'local'. Analagous to + • scope: One of 'global' or 'local'. Analogous to |:setglobal| and |:setlocal|, respectively. Return: ~ @@ -1346,7 +1405,7 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) {from_part} Legacy Vim parameter. Usually true. {do_lt} Also translate <lt>. Ignored if `special` is false. - {special} Replace |keycodes|, e.g. <CR> becomes a "\n" + {special} Replace |keycodes|, e.g. <CR> becomes a "\r" char. See also: ~ @@ -1524,8 +1583,11 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()* {rhs} Right-hand-side |{rhs}| of the mapping. {opts} Optional parameters map. Accepts all |:map-arguments| as keys excluding |<buffer>| but - including |noremap|. Values are Booleans. Unknown - key is an error. + including |noremap| and "desc". |desc| can be used + to give a description to keymap. When called from + Lua, also accepts a "callback" key that takes a + Lua function to call when the mapping is executed. + Values are Booleans. Unknown key is an error. nvim_set_option({name}, {value}) *nvim_set_option()* Sets the global value of an option. @@ -1545,7 +1607,7 @@ nvim_set_option_value({name}, {value}, {*opts}) {name} Option name {value} New option value {opts} Optional parameters - • scope: One of 'global' or 'local'. Analagous to + • scope: One of 'global' or 'local'. Analogous to |:setglobal| and |:setlocal|, respectively. nvim_set_var({name}, {value}) *nvim_set_var()* @@ -1790,6 +1852,16 @@ nvim__buf_redraw_range({buffer}, {first}, {last}) nvim__buf_stats({buffer}) *nvim__buf_stats()* TODO: Documentation + *nvim_buf_add_user_command()* +nvim_buf_add_user_command({buffer}, {name}, {command}, {*opts}) + Create a new user command |user-commands| in the given buffer. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer. + + See also: ~ + nvim_add_user_command + nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()* Activates buffer-update events on a channel, or as Lua callbacks. @@ -1925,6 +1997,18 @@ nvim_buf_del_mark({buffer}, {name}) *nvim_buf_del_mark()* |nvim_buf_set_mark()| |nvim_del_mark()| + *nvim_buf_del_user_command()* +nvim_buf_del_user_command({buffer}, {name}) + Delete a buffer-local user-defined command. + + Only commands created with |:command-buffer| or + |nvim_buf_add_user_command()| can be deleted with this + function. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer. + {name} Name of the command to delete. + nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()* Removes a buffer-scoped (b:) variable @@ -2464,6 +2548,10 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) • priority: a priority value for the highlight group. For example treesitter highlighting uses a value of 100. + • strict: boolean that indicates extmark should + not be placed if the line or column value is + past the end of the buffer or end of the line + respectively. Defaults to true. Return: ~ Id of the created/updated extmark @@ -2687,7 +2775,7 @@ nvim_win_is_valid({window}) *nvim_win_is_valid()* true if the window is valid, false otherwise nvim_win_set_buf({window}, {buffer}) *nvim_win_set_buf()* - Sets the current buffer in a window, without side-effects + Sets the current buffer in a window, without side effects Attributes: ~ not allowed when |textlock| is active diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 242631d98c..5e50f9c1f8 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -40,10 +40,10 @@ effects. Be careful not to destroy your text. 2. Defining autocommands *autocmd-define* *:au* *:autocmd* -:au[tocmd] [group] {event} {pat} [++once] [++nested] {cmd} +:au[tocmd] [group] {event} {aupat} [++once] [++nested] {cmd} Add {cmd} to the list of commands that Vim will execute automatically on {event} for a file matching - {pat} |autocmd-pattern|. + {aupat} |autocmd-pattern|. Note: A quote character is seen as argument to the :autocmd and won't start a comment. Nvim always adds {cmd} after existing autocommands so @@ -119,19 +119,19 @@ prompt. When one command outputs two messages this can happen anyway. ============================================================================== 3. Removing autocommands *autocmd-remove* -:au[tocmd]! [group] {event} {pat} [++once] [++nested] {cmd} +:au[tocmd]! [group] {event} {aupat} [++once] [++nested] {cmd} Remove all autocommands associated with {event} and - {pat}, and add the command {cmd}. + {aupat}, and add the command {cmd}. See |autocmd-once| for [++once]. See |autocmd-nested| for [++nested]. -:au[tocmd]! [group] {event} {pat} +:au[tocmd]! [group] {event} {aupat} Remove all autocommands associated with {event} and - {pat}. + {aupat}. -:au[tocmd]! [group] * {pat} - Remove all autocommands associated with {pat} for all - events. +:au[tocmd]! [group] * {aupat} + Remove all autocommands associated with {aupat} for + all events. :au[tocmd]! [group] {event} Remove ALL autocommands for {event}. @@ -151,12 +151,12 @@ with ":augroup"); otherwise, Vim uses the group defined with [group]. ============================================================================== 4. Listing autocommands *autocmd-list* -:au[tocmd] [group] {event} {pat} +:au[tocmd] [group] {event} {aupat} Show the autocommands associated with {event} and - {pat}. + {aupat}. -:au[tocmd] [group] * {pat} - Show the autocommands associated with {pat} for all +:au[tocmd] [group] * {aupat} + Show the autocommands associated with {aupat} for all events. :au[tocmd] [group] {event} @@ -828,6 +828,21 @@ RemoteReply When a reply from a Vim that functions as SearchWrapped After making a search with |n| or |N| if the search wraps around the document back to the start/finish respectively. + *RecordingEnter* +RecordingEnter When a macro starts recording. + The pattern is the current file name, and + |reg_recording()| is the current register that + is used. + *RecordingLeave* +RecordingLeave When a macro stops recording. + The pattern is the current file name, and + |reg_recording()| is the recorded + register. + |reg_recorded()| is only updated after this + event. + Sets these |v:event| keys: + regcontents + regname *SessionLoadPost* SessionLoadPost After loading the session file created using the |:mksession| command. @@ -1060,16 +1075,16 @@ WinScrolled After scrolling the viewport of the current ============================================================================== -6. Patterns *autocmd-pattern* *{pat}* +6. Patterns *autocmd-pattern* *{aupat}* -The {pat} argument can be a comma separated list. This works as if the -command was given with each pattern separately. Thus this command: > +The {aupat} argument of `:autocmd` can be a comma separated list. This works +as if the command was given with each pattern separately. Thus this command: > :autocmd BufRead *.txt,*.info set et Is equivalent to: > :autocmd BufRead *.txt set et :autocmd BufRead *.info set et -The file pattern {pat} is tested for a match against the file name in one of +The file pattern {aupat} is tested for a match against the file name in one of two ways: 1. When there is no '/' in the pattern, Vim checks for a match against only the tail part of the file name (without its leading directory path). diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index ffdd8427f9..953f097a92 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1595,7 +1595,8 @@ r Automatically insert the current comment leader after hitting <Enter> in Insert mode. *fo-o* o Automatically insert the current comment leader after hitting 'o' or - 'O' in Normal mode. + 'O' in Normal mode. In case comment is unwanted in a specific place + use CTRL-U to quickly delete it. |i_CTRL-U| *fo-q* q Allow formatting of comments with "gq". Note that formatting will not change blank lines or lines containing diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt index 5f376a600e..e14427494d 100644 --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -44,7 +44,7 @@ functions like |chansend()| consume channel ids. 2. Reading and writing raw bytes *channel-bytes* Channels opened by Vimscript functions operate with raw bytes by default. For -a job channel using RPC, bytes can still be read over its stderr. Similarily, +a job channel using RPC, bytes can still be read over its stderr. Similarly, only bytes can be written to Nvim's own stderr. *channel-callback* diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 7716af25bd..641cd93386 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -697,7 +697,8 @@ Line numbers may be specified with: *:range* *{address}* Each may be followed (several times) by '+' or '-' and an optional number. This number is added or subtracted from the preceding line number. If the -number is omitted, 1 is used. +number is omitted, 1 is used. If there is nothing before the '+' or '-' then +the current line is used. The "/" and "?" after {pattern} are required to separate the pattern from anything that follows. @@ -727,7 +728,7 @@ Some commands allow for a count after the command. This count is used as the number of lines to be used, starting with the line given in the last line specifier (the default is the cursor line). The commands that accept a count are the ones that use a range but do not have a file name argument (because -a file name can also be a number). +a file name can also be a number). The count cannot be negative. Examples: > :s/x/X/g 5 substitute 'x' by 'X' in the current line and four diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 7127c74134..178b0dc62b 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -105,7 +105,7 @@ in eval.c: - eval_call_provider(name, method, arguments, discard): calls provider#{name}#Call with the method and arguments. If discard is true, any - value returned by the provider will be discarded and and empty value be + value returned by the provider will be discarded and empty value will be returned. - eval_has_provider(name): Checks the `g:loaded_{name}_provider` variable which must be set to 2 by the provider script to indicate that it is diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 0893f1f343..19db3158be 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -132,7 +132,7 @@ with |vim.notify()|: > In this example, there is nothing to do when diagnostics are hidden, so we omit the "hide" function. -Existing handlers can be overriden. For example, use the following to only +Existing handlers can be overridden. For example, use the following to only show a sign for the highest severity diagnostic on a given line: > -- Create a custom namespace. This will aggregate signs from all other @@ -177,8 +177,9 @@ All highlights defined for diagnostics begin with `Diagnostic` followed by the type of highlight (e.g., `Sign`, `Underline`, etc.) and the severity (e.g. `Error`, `Warn`, etc.) -Sign, underline and virtual text highlights (by default) are linked to their -corresponding default highlight. +By default, highlights for signs, floating windows, and virtual text are linked to the +corresponding default highlight. Underline highlights are not linked and use their +own default highlight groups. For example, the default highlighting for |hl-DiagnosticSignError| is linked to |hl-DiagnosticError|. To change the default (and therefore the linked @@ -298,7 +299,6 @@ Example: > autocmd DiagnosticChanged * lua vim.diagnostic.setqflist({open = false }) < ============================================================================== -============================================================================== Lua module: vim.diagnostic *diagnostic-api* config({opts}, {namespace}) *vim.diagnostic.config()* @@ -334,8 +334,9 @@ config({opts}, {namespace}) *vim.diagnostic.config()* that returns any of the above. Parameters: ~ - {opts} table Configuration table with the following - keys: + {opts} table|nil When omitted or "nil", retrieve the + current configuration. Otherwise, a + configuration table with the following keys: • underline: (default true) Use underline for diagnostics. Options: • severity: Only underline diagnostics @@ -343,13 +344,24 @@ config({opts}, {namespace}) *vim.diagnostic.config()* |diagnostic-severity| • virtual_text: (default true) Use virtual - text for diagnostics. Options: + text for diagnostics. If multiple + diagnostics are set for a namespace, one + prefix per diagnostic + the last diagnostic + message are shown. Options: • severity: Only show virtual text for diagnostics matching the given severity |diagnostic-severity| - • source: (string) Include the diagnostic - source in virtual text. One of "always" - or "if_many". + • source: (boolean or string) Include the + diagnostic source in virtual text. Use + "if_many" to only show sources if there + is more than one diagnostic source in the + buffer. Otherwise, any truthy value means + to always show the diagnostic source. + • spacing: (number) Amount of empty spaces + inserted at the beginning of the virtual + text. + • prefix: (string) Prepend diagnostic + message with prefix. • format: (function) A function that takes a diagnostic as input and returns a string. The return value is the text used @@ -608,9 +620,12 @@ open_float({opts}, {...}) *vim.diagnostic.open_float()* is interpreted as a [text, hl_group] tuple. Overrides the setting from |vim.diagnostic.config()|. - • source: (string) Include the diagnostic source - in the message. One of "always" or "if_many". - Overrides the setting from + • source: (boolean or string) Include the + diagnostic source in the message. Use "if_many" + to only show sources if there is more than one + source of diagnostics in the buffer. Otherwise, + any truthy value means to always show the + diagnostic source. Overrides the setting from |vim.diagnostic.config()|. • format: (function) A function that takes a diagnostic as input and returns a string. The diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 6115a5d235..abe99102ee 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -324,8 +324,9 @@ After setting this variable, reload the syntax script: > FINDING THE DIFFERENCES *diff-diffexpr* -The 'diffexpr' option can be set to use something else than the standard -"diff" program to compare two files and find the differences. *E959* +The 'diffexpr' option can be set to use something else than the internal diff +support or the standard "diff" program to compare two files and find the +differences. When 'diffexpr' is empty, Vim uses this command to find the differences between file1 and file2: > @@ -358,7 +359,7 @@ format mentioned. These variables are set to the file names used: v:fname_in original file v:fname_new new version of the same file - v:fname_out resulting diff file + v:fname_out where to write the resulting diff file Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the 'diffopt' option. 'diffexpr' cannot change the value of 'lines' and diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 4e3173cfa9..44987f3b7b 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -845,7 +845,7 @@ Note: When the 'write' option is off, you are not able to write any file. *:w* *:write* *E502* *E503* *E504* *E505* - *E512* *E514* *E667* *E796* *E949* + *E512* *E514* *E667* *E949* :w[rite] [++opt] Write the whole buffer to the current file. This is the normal way to save changes to a file. It fails when the 'readonly' option is set or when there is @@ -1253,10 +1253,12 @@ working directory. If a local working directory (tab or window) does not exist, the next-higher scope in the hierarchy applies. *:cd* *E747* *E472* -:cd[!] On non-Unix systems: Print the current directory - name. On Unix systems: Change the current directory - to the home directory. Use |:pwd| to print the - current directory on all systems. +:cd[!] On non-Unix systems when 'cdhome' is off: Print the + current directory name. + Otherwise: Change the current directory to the home + directory. Clear any window-local directory. + Use |:pwd| to print the current directory on all + systems. :cd[!] {path} Change the current directory to {path}. If {path} is relative, it is searched for in the @@ -1329,6 +1331,7 @@ current directory for that window. Windows where the |:lcd| command has not been used stick to the global or tab-local directory. When jumping to another window the current directory is changed to the last specified local current directory. If none was specified, the global or tab-local directory is used. +When creating a new window it inherits the local directory of the current window. When changing tabs the same behaviour applies. If the current tab has no local working directory the global working directory is used. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 75b782fbff..fa75ead9a3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -111,7 +111,7 @@ When mixing Number and Float the Number is converted to Float. Otherwise there is no automatic conversion of Float. You can use str2float() for String to Float, printf() for Float to String and float2nr() for Float to Number. - *E891* *E892* *E893* *E894* + *E362* *E891* *E892* *E893* *E894* *E907* When expecting a Float a Number can also be used, but nothing else. *no-type-checking* @@ -1195,6 +1195,7 @@ When expr8 is a |Funcref| type variable, invoke the function it refers to. expr8->name([args]) method call *method* *->* expr8->{lambda}([args]) + *E260* *E276* For methods that are also available as global functions this is the same as: > name(expr8 [, args]) There can also be methods specifically for the type of "expr8". @@ -2278,7 +2279,7 @@ USAGE RESULT DESCRIPTION ~ abs({expr}) Float or Number absolute value of {expr} acos({expr}) Float arc cosine of {expr} add({object}, {item}) List/Blob append {item} to {object} -and({expr}, {expr}) Number bitwise AND +and({expr}, {expr}) Number bitwise AND api_info() Dict api metadata append({lnum}, {string}) Number append {string} below line {lnum} append({lnum}, {list}) Number append lines {list} below line {lnum} @@ -2310,7 +2311,7 @@ assert_notmatch({pat}, {text} [, {msg}]) assert_report({msg}) Number report a test failure assert_true({actual} [, {msg}]) Number assert {actual} is true atan({expr}) Float arc tangent of {expr} -atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2} +atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2} browse({save}, {title}, {initdir}, {default}) String put up a file requester browsedir({title}, {initdir}) String put up a directory requester @@ -2336,7 +2337,7 @@ char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr} charidx({string}, {idx} [, {countcc}]) Number char index of byte {idx} in {string} chdir({dir}) String change current working directory -cindent({lnum}) Number C indent for line {lnum} +cindent({lnum}) Number C indent for line {lnum} clearmatches([{win}]) none clear all matches col({expr}) Number column nr of cursor or mark complete({startcol}, {matches}) none set Insert mode completion @@ -2349,7 +2350,7 @@ copy({expr}) any make a shallow copy of {expr} cos({expr}) Float cosine of {expr} cosh({expr}) Float hyperbolic cosine of {expr} count({list}, {expr} [, {ic} [, {start}]]) - Number count how many {expr} are in {list} + Number count how many {expr} are in {list} cscope_connection([{num}, {dbpath} [, {prepend}]]) Number checks existence of cscope connection ctxget([{index}]) Dict return the |context| dict at {index} @@ -2362,7 +2363,7 @@ ctxsize() Number return |context-stack| size cursor({lnum}, {col} [, {off}]) Number move cursor to {lnum}, {col}, {off} cursor({list}) Number move cursor to position in {list} -debugbreak({pid}) Number interrupt process being debugged +debugbreak({pid}) Number interrupt process being debugged deepcopy({expr} [, {noref}]) any make a full copy of {expr} delete({fname} [, {flags}]) Number delete the file or directory {fname} deletebufline({buf}, {first}[, {last}]) @@ -2381,7 +2382,7 @@ eval({string}) any evaluate {string} into its value eventhandler() Number |TRUE| if inside an event handler executable({expr}) Number 1 if executable {expr} exists execute({command}) String execute and capture output of {command} -exepath({expr}) String full path of the command {expr} +exepath({expr}) String full path of the command {expr} exists({expr}) Number |TRUE| if {expr} exists extend({expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} @@ -2410,10 +2411,11 @@ foldlevel({lnum}) Number fold level at {lnum} foldtext() String line displayed for closed fold foldtextresult({lnum}) String text for closed fold at {lnum} foreground() Number bring the Vim window to the foreground +fullcommand({name}) String get full command from {name} funcref({name} [, {arglist}] [, {dict}]) - Funcref reference to function {name} + Funcref reference to function {name} function({name} [, {arglist}] [, {dict}]) - Funcref named reference to function {name} + Funcref named reference to function {name} garbagecollect([{atexit}]) none free memory, breaking cyclic references get({list}, {idx} [, {def}]) any get item {idx} from {list} or {def} get({dict}, {key} [, {def}]) any get item {key} from {dict} or {def} @@ -2501,11 +2503,11 @@ inputlist({textlist}) Number let the user pick from a choice list inputrestore() Number restore typeahead inputsave() Number save and clear typeahead inputsecret({prompt} [, {text}]) - String like input() but hiding the text + String like input() but hiding the text insert({object}, {item} [, {idx}]) List insert {item} in {object} [before {idx}] interrupt() none interrupt script execution -invert({expr}) Number bitwise invert +invert({expr}) Number bitwise invert isdirectory({directory}) Number |TRUE| if {directory} is a directory isinf({expr}) Number determine if {expr} is infinity value (positive or negative) @@ -2525,7 +2527,7 @@ json_encode({expr}) String Convert {expr} to JSON keys({dict}) List keys in {dict} len({expr}) Number the length of {expr} libcall({lib}, {func}, {arg}) String call {func} in library {lib} with {arg} -libcallnr({lib}, {func}, {arg}) Number idem, but return a Number +libcallnr({lib}, {func}, {arg}) Number idem, but return a Number line({expr} [, {winid}]) Number line nr of cursor, last line or mark line2byte({lnum}) Number byte count of line {lnum} lispindent({lnum}) Number Lisp indent for line {lnum} @@ -2567,7 +2569,7 @@ msgpackparse({data}) List parse msgpack to a list of objects nextnonblank({lnum}) Number line nr of non-blank line >= {lnum} nr2char({expr}[, {utf8}]) String single char with ASCII/UTF-8 value {expr} nvim_...({args}...) any call nvim |api| functions -or({expr}, {expr}) Number bitwise OR +or({expr}, {expr}) Number bitwise OR pathshorten({expr}) String shorten directory names in a path perleval({expr}) any evaluate |perl| expression pow({x}, {y}) Float {x} to the power of {y} @@ -2588,6 +2590,7 @@ readdir({dir} [, {expr}]) List file names in {dir} selected by {expr} readfile({fname} [, {type} [, {max}]]) List get list of lines from file {fname} reg_executing() String get the executing register name +reg_recorded() String get the last recorded register name reg_recording() String get the recording register name reltime([{start} [, {end}]]) List get time value reltimefloat({time}) Float turn the time value into a Float @@ -2626,7 +2629,7 @@ screenrow() Number current cursor row screenstring({row}, {col}) String characters at screen position search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) Number search for {pattern} -searchcount([{options}]) Dict Get or update the last search count +searchcount([{options}]) Dict Get or update the last search count searchdecl({name} [, {global} [, {thisblock}]]) Number search for variable declaration searchpair({start}, {middle}, {end} [, {flags} [, {skip} [...]]]) @@ -2698,7 +2701,7 @@ split({expr} [, {pat} [, {keepempty}]]) List make |List| from {pat} separated {expr} sqrt({expr}) Float square root of {expr} stdioopen({dict}) Number open stdio in a headless instance. -stdpath({what}) String/List returns the standard path(s) for {what} +stdpath({what}) String/List returns the standard path(s) for {what} str2float({expr} [, {quoted}]) Float convert String to Float str2list({expr} [, {utf8}]) List convert each character of {expr} to ASCII/UTF-8 value @@ -2734,7 +2737,7 @@ synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col} synIDattr({synID}, {what} [, {mode}]) String attribute {what} of syntax ID {synID} synIDtrans({synID}) Number translated syntax ID of {synID} -synconcealed({lnum}, {col}) List info about concealing +synconcealed({lnum}, {col}) List info about concealing synstack({lnum}, {col}) List stack of syntax IDs at {lnum} and {col} system({cmd} [, {input}]) String output of shell command/filter {cmd} systemlist({cmd} [, {input}]) List output of shell command/filter {cmd} @@ -2770,7 +2773,7 @@ values({dict}) List values in {dict} virtcol({expr}) Number screen column of cursor or mark visualmode([expr]) String last visual mode used wait({timeout}, {condition}[, {interval}]) - Number Wait until {condition} is satisfied + Number Wait until {condition} is satisfied wildmenumode() Number whether 'wildmenu' mode is active win_execute({id}, {command} [, {silent}]) String execute {command} in window {id} @@ -4161,11 +4164,12 @@ expand({string} [, {nosuf} [, {list}]]) *expand()* Can also be used as a |method|: > Getpattern()->expand() -expandcmd({expr}) *expandcmd()* - Expand special items in {expr} like what is done for an Ex - command such as `:edit`. This expands special keywords, like - with |expand()|, and environment variables, anywhere in - {expr}. "~user" and "~/path" are only expanded at the start. +expandcmd({string}) *expandcmd()* + Expand special items in String {string} like what is done for + an Ex command such as `:edit`. This expands special keywords, + like with |expand()|, and environment variables, anywhere in + {string}. "~user" and "~/path" are only expanded at the + start. Returns the expanded string. Example: > :echo expandcmd('make %<.o') @@ -4549,6 +4553,21 @@ foreground() Move the Vim window to the foreground. Useful when sent from |remote_foreground()| instead. {only in the Win32 GUI and console version} +fullcommand({name}) *fullcommand()* + Get the full command name from a short abbreviated command + name; see |20.2| for details on command abbreviations. + + The string argument {name} may start with a `:` and can + include a [range], these are skipped and not returned. + Returns an empty string if a command doesn't exist or if it's + ambiguous (for user-defined commands). + + For example `fullcommand('s')`, `fullcommand('sub')`, + `fullcommand(':%substitute')` all return "substitute". + + Can also be used as a |method|: > + GetName()->fullcommand() +< *funcref()* funcref({name} [, {arglist}] [, {dict}]) Just like |function()|, but the returned Funcref will lookup @@ -4556,8 +4575,10 @@ funcref({name} [, {arglist}] [, {dict}]) function {name} is redefined later. Unlike |function()|, {name} must be an existing user function. - Also for autoloaded functions. {name} cannot be a builtin - function. + It only works for an autoloaded function if it has already + been loaded (to avoid mistakenly loading the autoload script + when only intending to use the function name, use |function()| + instead). {name} cannot be a builtin function. Can also be used as a |method|: > GetFuncname()->funcref([arg]) @@ -5419,8 +5440,9 @@ getreg([{regname} [, 1 [, {list}]]]) *getreg()* The result is a String, which is the contents of register {regname}. Example: > :let cliptext = getreg('*') -< When {regname} was not set the result is an empty string. - The {regname} argument is a string. +< When register {regname} was not set the result is an empty + string. + The {regname} argument must be a string. getreg('=') returns the last evaluated value of the expression register. (For use in maps.) @@ -6873,7 +6895,7 @@ match({expr}, {pat} [, {start} [, {count}]]) *match()* GetText()->match('word') GetList()->match('word') < - *matchadd()* *E798* *E799* *E801* *E957* + *matchadd()* *E798* *E799* *E801* *E957* matchadd({group}, {pattern}[, {priority}[, {id} [, {dict}]]]) Defines a pattern to be highlighted in the current window (a "match"). It will be highlighted with {group}. Returns an @@ -7201,7 +7223,7 @@ mode([expr]) Return a string that indicates the current mode. Rvc Virtual Replace mode completion |compl-generic| Rvx Virtual Replace mode |i_CTRL-X| completion c Command-line editing - cv Vim Ex mode |Q| or |gQ| + cv Vim Ex mode |gQ| r Hit-enter prompt rm The -- more -- prompt r? A |:confirm| query of some sort @@ -7825,6 +7847,11 @@ reg_executing() *reg_executing()* Returns an empty string when no register is being executed. See |@|. +reg_recorded() *reg_recorded()* + Returns the single letter name of the last recorded register. + Returns an empty string string when nothing was recorded yet. + See |q| and |Q|. + reg_recording() *reg_recording()* Returns the single letter name of the register being recorded. Returns an empty string string when not recording. See |q|. @@ -11039,7 +11066,7 @@ See |:verbose-cmd| for more information. command, use line breaks instead of |:bar|: > :exe "func Foo()\necho 'foo'\nendfunc" < - *:delf* *:delfunction* *E130* *E131* *E933* + *:delf* *:delfunction* *E131* *E933* :delf[unction][!] {name} Delete function {name}. {name} can also be a |Dictionary| entry that is a @@ -13129,7 +13156,7 @@ code can be used: > unlet scriptnames_output ============================================================================== -The sandbox *eval-sandbox* *sandbox* *E48* +The sandbox *eval-sandbox* *sandbox* The 'foldexpr', 'formatexpr', 'includeexpr', 'indentexpr', 'statusline' and 'foldtext' options may be evaluated in a sandbox. This means that you are @@ -13138,6 +13165,7 @@ safety for when these options are set from a modeline. It is also used when the command from a tags file is executed and for CTRL-R = in the command line. The sandbox is also used for the |:sandbox| command. + *E48* These items are not allowed in the sandbox: - changing the buffer text - defining or changing mapping, autocommands, user commands diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index bbbe71ec3a..5486c87af9 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -24,12 +24,21 @@ Each time a new or existing file is edited, Vim will try to recognize the type of the file and set the 'filetype' option. This will trigger the FileType event, which can be used to set the syntax highlighting, set options, etc. -Detail: The ":filetype on" command will load this file: +Detail: The ":filetype on" command will load these files: + $VIMRUNTIME/filetype.lua $VIMRUNTIME/filetype.vim - This file is a Vim script that defines autocommands for the - BufNewFile and BufRead events. If the file type is not found by the - name, the file $VIMRUNTIME/scripts.vim is used to detect it from the - contents of the file. + filetype.lua creates an autocommand that fires for all BufNewFile and + BufRead events. It tries to detect the filetype based off of the + file's extension or name. + + filetype.vim is a Vim script that defines autocommands for the + BufNewFile and BufRead events. In contrast to filetype.lua, this + file creates separate BufNewFile and BufRead events for each filetype + pattern. + + If the file type is not found by the name, the file + $VIMRUNTIME/scripts.vim is used to detect it from the contents of the + file. When the GUI is running or will start soon, the |menu.vim| script is also sourced. See |'go-M'| about avoiding that. @@ -122,14 +131,15 @@ shell script: "#!/bin/csh". argument was used. *filetype-overrule* -When the same extension is used for two filetypes, Vim tries to guess what -kind of file it is. This doesn't always work. A number of global variables -can be used to overrule the filetype used for certain extensions: +When the same extension is used for multiple filetypes, Vim tries to guess +what kind of file it is. This doesn't always work. A number of global +variables can be used to overrule the filetype used for certain extensions: file name variable ~ *.asa g:filetype_asa |ft-aspvbs-syntax| |ft-aspperl-syntax| *.asm g:asmsyntax |ft-asm-syntax| *.asp g:filetype_asp |ft-aspvbs-syntax| |ft-aspperl-syntax| + *.bas g:filetype_bas |ft-basic-syntax| *.fs g:filetype_fs |ft-forth-syntax| *.i g:filetype_i |ft-progress-syntax| *.inc g:filetype_inc @@ -149,9 +159,10 @@ is used. The default value is set like this: > This means that the contents of compressed files are not inspected. *new-filetype* -If a file type that you want to use is not detected yet, there are four ways -to add it. In any way, it's better not to modify the $VIMRUNTIME/filetype.vim -file. It will be overwritten when installing a new version of Vim. +If a file type that you want to use is not detected yet, there are a few ways +to add it. In any way, it's better not to modify the $VIMRUNTIME/filetype.lua +or $VIMRUNTIME/filetype.vim files. They will be overwritten when installing a +new version of Nvim. A. If you want to overrule all default file type checks. This works by writing one file for each filetype. The disadvantage is that @@ -191,7 +202,7 @@ B. If you want to detect your file after the default file type checks. au BufRead,BufNewFile * if &ft == 'pascal' | set ft=mypascal | endif -C. If your file type can be detected by the file name. +C. If your file type can be detected by the file name or extension. 1. Create your user runtime directory. You would normally use the first item of the 'runtimepath' option. Example for Unix: > :!mkdir -p ~/.config/nvim @@ -206,9 +217,38 @@ C. If your file type can be detected by the file name. au! BufRead,BufNewFile *.mine setfiletype mine au! BufRead,BufNewFile *.xyz setfiletype drawing augroup END -< Write this file as "filetype.vim" in your user runtime directory. For +< + Write this file as "filetype.vim" in your user runtime directory. For example, for Unix: > :w ~/.config/nvim/filetype.vim +< + Alternatively, create a file called "filetype.lua" that adds new + filetypes. + Example: > + vim.filetype.add({ + extension = { + foo = "fooscript", + }, + filename = { + [".foorc"] = "foorc", + }, + pattern = { + [".*/etc/foo/.*%.conf"] = "foorc", + }, + }) +< + See |vim.filetype.add()|. + *g:do_filetype_lua* + For now, Lua filetype detection is opt-in. You can enable it by adding + the following to your |init.vim|: > + let g:do_filetype_lua = 1 +< *g:did_load_filetypes* + In either case, the builtin filetype detection provided by Nvim can be + disabled by setting the did_load_filetypes global variable. If this + variable exists, $VIMRUNTIME/filetype.vim will not run. + Example: > + " Disable filetype.vim + let g:did_load_filetypes = 1 < 3. To use the new filetype detection you must restart Vim. @@ -245,9 +285,9 @@ D. If your filetype can only be detected by inspecting the contents of the $VIMRUNTIME/scripts.vim. *remove-filetype* -If a file type is detected that is wrong for you, install a filetype.vim or -scripts.vim to catch it (see above). You can set 'filetype' to a non-existing -name to avoid that it will be set later anyway: > +If a file type is detected that is wrong for you, install a filetype.lua, +filetype.vim or scripts.vim to catch it (see above). You can set 'filetype' to +a non-existing name to avoid that it will be set later anyway: > :set filetype=ignored If you are setting up a system with many users, and you don't want each user @@ -314,12 +354,12 @@ define yourself. There are a few ways to avoid this: You need to define your own mapping before the plugin is loaded (before editing a file of that type). The plugin will then skip installing the default mapping. - *no_mail_maps* + *no_mail_maps* *g:no_mail_maps* 3. Disable defining mappings for a specific filetype by setting a variable, which contains the name of the filetype. For the "mail" filetype this would be: > :let no_mail_maps = 1 -< *no_plugin_maps* +< *no_plugin_maps* *g:no_plugin_maps* 4. Disable defining mappings for all filetypes by setting a variable: > :let no_plugin_maps = 1 < diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index 80c934d13b..8bc47a3b10 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -501,7 +501,9 @@ Note the use of backslashes to avoid some characters to be interpreted by the :endfunction Evaluating 'foldtext' is done in the |sandbox|. The current window is set to -the window that displays the line. Errors are ignored. +the window that displays the line. + +Errors are ignored. For debugging set the 'debug' option to "throw". The default value is |foldtext()|. This returns a reasonable text for most types of folding. If you don't like it, you can specify your own 'foldtext' diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index e7b489d6e1..03ec8966d4 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -164,7 +164,7 @@ If you would like to open the help in the current window, see this tip: The initial height of the help window can be set with the 'helpheight' option (default 20). - + *help-buffer-options* When the help buffer is created, several local options are set to make sure the help text is displayed as it was intended: 'iskeyword' nearly all ASCII chars except ' ', '*', '"' and '|' @@ -219,7 +219,7 @@ command: > < *:helpt* *:helptags* - *E154* *E150* *E151* *E152* *E153* *E670* *E856* + *E150* *E151* *E152* *E153* *E154* *E670* *E856* :helpt[ags] [++t] {dir} Generate the help tags file(s) for directory {dir}. When {dir} is ALL then all "doc" directories in diff --git a/runtime/doc/if_cscop.txt b/runtime/doc/if_cscop.txt index f05b3bb8ed..8947aefc1b 100644 --- a/runtime/doc/if_cscop.txt +++ b/runtime/doc/if_cscop.txt @@ -40,7 +40,7 @@ See |cscope-usage| to get started. ============================================================================== Cscope commands *cscope-commands* - *:cscope* *:cs* *:scs* *:scscope* *E259* *E262* *E561* *E560* + *:cscope* *:cs* *:scs* *:scscope* *E259* *E262* *E560* *E561* All cscope commands are accessed through suboptions to the cscope commands. `:cscope` or `:cs` is the main command `:scscope` or `:scs` does the same and splits the window diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index 1b42092616..a76f8636f8 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -872,7 +872,7 @@ For example, with N = 1, this will give: *PHP_outdentphpescape* To indent PHP escape tags as the surrounding non-PHP code (only affects the PHP escape tags): > -:let g:PHP_outdentphpescape = 0 + :let g:PHP_outdentphpescape = 0 ------------- *PHP_removeCRwhenUnix* @@ -1199,7 +1199,7 @@ comments will be indented according to the correctly indented code. VIM *ft-vim-indent* - + *g:vim_indent_cont* For indenting Vim scripts there is one variable that specifies the amount of indent for a continuation line, a line that starts with a backslash: > diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index baa7bc1992..d8689e2c65 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -339,7 +339,6 @@ tag char note action in Normal mode ~ insert text, repeat N times |P| ["x]P 2 put the text [from register x] before the cursor N times -|Q| Q switch to "Ex" mode |R| R 2 enter replace mode: overtype existing characters, repeat the entered text N-1 times @@ -401,6 +400,7 @@ tag char note action in Normal mode ~ |q| q{0-9a-zA-Z"} record typed characters into named register {0-9a-zA-Z"} (uppercase to append) |q| q (while recording) stops recording +|Q| Q replay last recorded macro |q:| q: edit : command-line in command-line window |q/| q/ edit / command-line in command-line window |q?| q? edit ? command-line in command-line window diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index fd1d0f8ea6..ae2b9c4418 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -76,6 +76,8 @@ CTRL-U Delete all entered characters before the cursor in the current line. If there are no newly entered characters and 'backspace' is not empty, delete all characters before the cursor in the current line. + If C-indenting is enabled the indent will be adjusted if the + line becomes blank. See |i_backspacing| about joining lines. *i_CTRL-U-default* By default, sets a new undo point before deleting. @@ -828,7 +830,7 @@ space is preferred). Maximum line length is 510 bytes. For an example, imagine the 'thesaurus' file has a line like this: > angry furious mad enraged -<Placing the cursor after the letters "ang" and typing CTRL-X CTRL-T would +Placing the cursor after the letters "ang" and typing CTRL-X CTRL-T would complete the word "angry"; subsequent presses would change the word to "furious", "mad" etc. @@ -840,7 +842,7 @@ https://github.com/vim/vim/issues/629#issuecomment-443293282 Unpack thesaurus_pkg.zip, put the thesaurus.txt file somewhere, e.g. ~/.vim/thesaurus/english.txt, and the 'thesaurus' option to this file name. - + Completing keywords with 'thesaurusfunc' *compl-thesaurusfunc* If the 'thesaurusfunc' option is set, then the user specified function is @@ -1878,6 +1880,9 @@ When 'autoindent' is on, the indent for a new line is obtained from the previous line. When 'smartindent' or 'cindent' is on, the indent for a line is automatically adjusted for C programs. +'formatoptions' can be set to copy the comment leader when opening a new +line. + 'textwidth' can be set to the maximum width for a line. When a line becomes too long when appending characters a line break is automatically inserted. diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index a89263861b..54999fa163 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -322,7 +322,6 @@ notation meaning equivalent decimal value(s) ~ <Bar> vertical bar | 124 *<Bar>* <Del> delete 127 <CSI> command sequence intro ALT-Esc 155 *<CSI>* -<xCSI> CSI when typed in the GUI *<xCSI>* <EOL> end-of-line (can be <CR>, <NL> or <CR><NL>, depends on system and 'fileformat') *<EOL>* @@ -563,8 +562,8 @@ The command CTRL-\ CTRL-G or <C-\><C-G> can be used to go to Insert mode when make sure Vim is in the mode indicated by 'insertmode', without knowing in what mode Vim currently is. - *gQ* *Q* *mode-Ex* *Ex-mode* *Ex* *EX* *E501* -Q or gQ Switch to Ex mode. This is like typing ":" commands + *gQ* *mode-Ex* *Ex-mode* *Ex* *EX* *E501* +gQ Switch to Ex mode. This is like typing ":" commands one after another, except: - You don't have to keep pressing ":". - The screen doesn't get updated after each command. diff --git a/runtime/doc/lsp-extension.txt b/runtime/doc/lsp-extension.txt index d13303ada6..6e9ad940c7 100644 --- a/runtime/doc/lsp-extension.txt +++ b/runtime/doc/lsp-extension.txt @@ -60,7 +60,7 @@ The example will: return nil end local dir = bufname - -- Just in case our algo is buggy, don't infinite loop. + -- Just in case our algorithm is buggy, don't infinite loop. for _ = 1, 100 do local did_change dir, did_change = dirname(dir) diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 3793a21f36..f6fcbe8fb9 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -214,7 +214,7 @@ For |lsp-request|, each |lsp-handler| has this signature: > request, a table with information about the error is sent. Otherwise, it is `nil`. See |lsp-response|. {result} (Result | Params | nil) - When the language server is able to succesfully + When the language server is able to successfully complete a request, this contains the `result` key of the response. See |lsp-response|. {ctx} (table) @@ -236,7 +236,7 @@ For |lsp-request|, each |lsp-handler| has this signature: > {config} (table) Configuration for the handler. - Each handler can define it's own configuration + Each handler can define its own configuration table that allows users to customize the behavior of a particular handler. @@ -274,7 +274,7 @@ For |lsp-notification|, each |lsp-handler| has this signature: > {config} (table) Configuration for the handler. - Each handler can define it's own configuration + Each handler can define its own configuration table that allows users to customize the behavior of a particular handler. @@ -369,7 +369,7 @@ Handlers can be set by: For example: > vim.lsp.start_client { - ..., -- Other configuration ommitted. + ..., -- Other configuration omitted. handlers = { ["textDocument/definition"] = my_custom_server_definition }, @@ -394,6 +394,9 @@ in the following order: 2. Handler defined in |vim.lsp.start_client()|, if any. 3. Handler defined in |vim.lsp.handlers|, if any. + *vim.lsp.log_levels* +Log levels are defined in |vim.log.levels| + VIM.LSP.PROTOCOL *vim.lsp.protocol* @@ -444,7 +447,7 @@ LspCodeLens |nvim_buf_set_extmark()|. LspCodeLensSeparator *hl-LspCodeLensSeparator* - Used to color the seperator between two or more code lens. + Used to color the separator between two or more code lens. *lsp-highlight-signature* @@ -485,6 +488,16 @@ buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()* {bufnr} (number) Buffer handle, or 0 for current {client_id} (number) Client id +buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()* + Detaches client from the specified buffer. Note: While the + server is notified that the text document (buffer) was closed, + it is still able to send notifications should it ignore this + notification. + + Parameters: ~ + {bufnr} number Buffer handle, or 0 for current + {client_id} number Client id + buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()* Gets a map of client_id:client pairs for the given buffer, where each value is a |vim.lsp.client| object. @@ -736,8 +749,8 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()* set_log_level({level}) *vim.lsp.set_log_level()* Sets the global log level for LSP logging. - Levels by name: "trace", "debug", "info", "warn", "error" - Level numbers begin with "trace" at 0 + Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR" + Level numbers begin with "TRACE" at 0 Use `lsp.log_levels` for reverse lookup. @@ -825,10 +838,10 @@ start_client({config}) *vim.lsp.start_client()* throws an error. `code` is a number describing the error. Other arguments may be passed depending on the error - kind. See |vim.lsp.client_errors| for - possible errors. Use - `vim.lsp.client_errors[code]` to get - human-friendly name. + kind. See |vim.lsp.rpc.client_errors| + for possible errors. Use + `vim.lsp.rpc.client_errors[code]` to + get human-friendly name. {before_init} Callback with parameters (initialize_params, config) invoked before the LSP "initialize" phase, @@ -995,7 +1008,7 @@ document_highlight() *vim.lsp.buf.document_highlight()* Send request to the server to resolve document highlights for the current text document position. This request can be triggered by a key mapping or by events such as `CursorHold` , - eg: + e.g.: > autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight() autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight() @@ -1011,11 +1024,12 @@ document_symbol() *vim.lsp.buf.document_symbol()* Lists all symbols in the current buffer in the quickfix window. -execute_command({command}) *vim.lsp.buf.execute_command()* +execute_command({command_params}) *vim.lsp.buf.execute_command()* Executes an LSP server command. Parameters: ~ - {command} A valid `ExecuteCommandParams` object + {command_params} table A valid `ExecuteCommandParams` + object See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand @@ -1291,7 +1305,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()* {config} table Configuration table. • border: (default=nil) • Add borders to the floating window - • See |vim.api.nvim_open_win()| + • See |nvim_open_win()| *vim.lsp.handlers.signature_help()* signature_help({_}, {result}, {ctx}, {config}) @@ -1318,7 +1332,7 @@ signature_help({_}, {result}, {ctx}, {config}) Lua module: vim.lsp.util *lsp-util* *vim.lsp.util.apply_text_document_edit()* -apply_text_document_edit({text_document_edit}, {index}) +apply_text_document_edit({text_document_edit}, {index}, {offset_encoding}) Applies a `TextDocumentEdit` , which is a list of changes to a single document. @@ -1338,18 +1352,19 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding}) Parameters: ~ {text_edits} table list of `TextEdit` objects {bufnr} number Buffer id - {offset_encoding} string utf-8|utf-16|utf-32|nil defaults - to encoding of first client of `bufnr` + {offset_encoding} string utf-8|utf-16|utf-32 defaults to + encoding of first client of `bufnr` See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit *vim.lsp.util.apply_workspace_edit()* -apply_workspace_edit({workspace_edit}) +apply_workspace_edit({workspace_edit}, {offset_encoding}) Applies a `WorkspaceEdit` . Parameters: ~ - {workspace_edit} (table) `WorkspaceEdit` + {workspace_edit} table `WorkspaceEdit` + {offset_encoding} string utf-8|utf-16|utf-32 (required) buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()* Removes document highlights from a buffer. @@ -1366,9 +1381,7 @@ buf_highlight_references({bufnr}, {references}, {offset_encoding}) {references} table List of `DocumentHighlight` objects to highlight {offset_encoding} string One of "utf-8", "utf-16", - "utf-32", or nil. Defaults to - `offset_encoding` of first client of - `bufnr` + "utf-32". See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight @@ -1457,16 +1470,19 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()* See also: ~ |softtabstop| -jump_to_location({location}) *vim.lsp.util.jump_to_location()* + *vim.lsp.util.jump_to_location()* +jump_to_location({location}, {offset_encoding}) Jumps to a location. Parameters: ~ - {location} ( `Location` | `LocationLink` ) + {location} table ( `Location` | `LocationLink` ) + {offset_encoding} string utf-8|utf-16|utf-32 (required) Return: ~ `true` if the jump succeeded -locations_to_items({locations}) *vim.lsp.util.locations_to_items()* + *vim.lsp.util.locations_to_items()* +locations_to_items({locations}, {offset_encoding}) Returns the items with the byte position calculated correctly and in sorted order, for display in quickfix and location lists. @@ -1475,8 +1491,10 @@ locations_to_items({locations}) *vim.lsp.util.locations_to_items()* |setqflist()| or |setloclist()|. Parameters: ~ - {locations} (table) list of `Location` s or - `LocationLink` s + {locations} table list of `Location` s or + `LocationLink` s + {offset_encoding} string offset_encoding for locations + utf-8|utf-16|utf-32 Return: ~ (table) list of items diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 630df16e79..3d4abed550 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -249,13 +249,15 @@ arguments separated by " " (space) instead of "\t" (tab). *:lua* :[range]lua {chunk} Executes Lua chunk {chunk}. - + if {chunk} starts with "=" the rest of the chunk is + evaluated as an expression and printed. `:lua =expr` + is equivalent to `:lua print(vim.inspect(expr))` Examples: > :lua vim.api.nvim_command('echo "Hello, Nvim!"') < To see the Lua version: > :lua print(_VERSION) < To see the LuaJIT version: > - :lua print(jit.version) + :lua =jit.version < *:lua-heredoc* :[range]lua << [endmarker] @@ -272,7 +274,7 @@ arguments separated by " " (space) instead of "\t" (tab). lua << EOF local linenr = vim.api.nvim_win_get_cursor(0)[1] local curline = vim.api.nvim_buf_get_lines( - 0, linenr, linenr + 1, false)[1] + 0, linenr - 1, linenr, false)[1] print(string.format("Current line [%d] has %d bytes", linenr, #curline)) EOF @@ -708,6 +710,38 @@ vim.mpack.decode({str}) *vim.mpack.decode* Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object. ------------------------------------------------------------------------------ +VIM.SPELL *lua-spell* + +vim.spell.check({str}) *vim.spell.check()* + Check {str} for spelling errors. Similar to the Vimscript function + |spellbadword()|. + + Note: The behaviour of this function is dependent on: 'spelllang', + 'spellfile', 'spellcapcheck' and 'spelloptions' which can all be local + to the buffer. Consider calling this with |nvim_buf_call()|. + + Example: > + vim.spell.check("the quik brown fox") + --> + { + {'quik', 'bad', 4} + } +< + + Parameters: ~ + {str} String to spell check. + + Return: ~ + List of tuples with three items: + - The badly spelled word. + - The type of the spelling error: + "bad" spelling mistake + "rare" rare word + "local" word only valid in another region + "caps" word should start with Capital + - The position in {str} where the word begins. + +------------------------------------------------------------------------------ VIM *lua-builtin* vim.api.{func}({...}) *vim.api* @@ -759,9 +793,9 @@ vim.stricmp({a}, {b}) *vim.stricmp()* respectively. vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()* - Convert byte index to UTF-32 and UTF-16 indicies. If {index} is not - supplied, the length of the string is used. All indicies are zero-based. - Returns two values: the UTF-32 and UTF-16 indicies respectively. + Convert byte index to UTF-32 and UTF-16 indices. If {index} is not + supplied, the length of the string is used. All indices are zero-based. + Returns two values: the UTF-32 and UTF-16 indices respectively. Embedded NUL bytes are treated as terminating the string. Invalid UTF-8 bytes, and embedded surrogates are counted as one code @@ -881,6 +915,15 @@ vim.types *vim.types* `vim.types.dictionary` will not change or that `vim.types` table will only contain values for these three types. + *log_levels* *vim.log.levels* +Log levels are one of the values defined in `vim.log.levels`: + + vim.log.levels.DEBUG + vim.log.levels.ERROR + vim.log.levels.INFO + vim.log.levels.TRACE + vim.log.levels.WARN + ------------------------------------------------------------------------------ LUA-VIMSCRIPT BRIDGE *lua-vimscript* @@ -1197,19 +1240,32 @@ inspect({object}, {options}) *vim.inspect()* https://github.com/kikito/inspect.lua https://github.com/mpeterv/vinspect -notify({msg}, {log_level}, {opts}) *vim.notify()* - Notification provider +notify({msg}, {level}, {opts}) *vim.notify()* + Display a notification to the user. - Without a runtime, writes to :Messages + This function can be overridden by plugins to display + notifications using a custom provider (such as the system + notification provider). By default, writes to |:messages|. Parameters: ~ - {msg} string Content of the notification to show to - the user - {log_level} number|nil enum from vim.log.levels - {opts} table|nil additional options (timeout, etc) + {msg} string Content of the notification to show to the + user. + {level} number|nil One of the values from + |vim.log.levels|. + {opts} table|nil Optional parameters. Unused by default. - See also: ~ - :help nvim_notify +notify_once({msg}, {level}, {opts}) *vim.notify_once()* + Display a notification only one time. + + Like |vim.notify()|, but subsequent calls with the same + message will not display a notification. + + Parameters: ~ + {msg} string Content of the notification to show to the + user. + {level} number|nil One of the values from + |vim.log.levels|. + {opts} table|nil Optional parameters. Unused by default. on_key({fn}, {ns_id}) *vim.on_key()* Adds Lua function {fn} with namespace id {ns_id} as a listener @@ -1273,6 +1329,18 @@ paste({lines}, {phase}) *vim.paste()* See also: ~ |paste| +pretty_print({...}) *vim.pretty_print()* + Prints given arguments in human-readable format. Example: > + -- Print highlight group Normal and store it's contents in a variable. + local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true)) +< + + Return: ~ + given arguments. + + See also: ~ + |vim.inspect()| + region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()* Get a table of lines with start, end columns for a region marked by two points @@ -1615,16 +1683,25 @@ validate({opt}) *vim.validate()* => error('arg1: expected even number, got 3') < + If multiple types are valid they can be given as a list. > + + vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} + => NOP (success) + + vim.validate{arg1={1, {'string', table'}}} + => error('arg1: expected string|table, got number') +< + Parameters: ~ - {opt} Map of parameter names to validations. Each key is - a parameter name; each value is a tuple in one of - these forms: + {opt} table of parameter names to validations. Each key + is a parameter name; each value is a tuple in one + of these forms: 1. (arg_value, type_name, optional) • arg_value: argument value - • type_name: string type name, one of: ("table", - "t", "string", "s", "number", "n", "boolean", - "b", "function", "f", "nil", "thread", - "userdata") + • type_name: string|table type name, one of: + ("table", "t", "string", "s", "number", "n", + "boolean", "b", "function", "f", "nil", + "thread", "userdata") or list of them. • optional: (optional) boolean, if true, `nil` is valid @@ -1728,4 +1805,157 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()* 1-based index of `item` within `item` . `nil` if the user aborted the dialog. + +============================================================================== +Lua module: filetype *lua-filetype* + +add({filetypes}) *vim.filetype.add()* + Add new filetype mappings. + + Filetype mappings can be added either by extension or by + filename (either the "tail" or the full file path). The full + file path is checked first, followed by the file name. If a + match is not found using the filename, then the filename is + matched against the list of patterns (sorted by priority) + until a match is found. Lastly, if pattern matching does not + find a filetype, then the file extension is used. + + The filetype can be either a string (in which case it is used + as the filetype directly) or a function. If a function, it + takes the full path and buffer number of the file as arguments + (along with captures from the matched pattern, if any) and + should return a string that will be used as the buffer's + filetype. + + Filename patterns can specify an optional priority to resolve + cases when a file path matches multiple patterns. Higher + priorities are matched first. When omitted, the priority + defaults to 0. + + See $VIMRUNTIME/lua/vim/filetype.lua for more examples. + + Note that Lua filetype detection is only enabled when + |g:do_filetype_lua| is set to 1. + + Example: > + + vim.filetype.add({ + extension = { + foo = "fooscript", + bar = function(path, bufnr) + if some_condition() then + return "barscript" + end + return "bar" + end, + }, + filename = { + [".foorc"] = "toml", + ["/etc/foo/config"] = "toml", + }, + pattern = { + [".*‍/etc/foo/.*"] = "fooscript", + -- Using an optional priority + [".*‍/etc/foo/.*%.conf"] = { "dosini", { priority = 10 } }, + ["README.(%a+)$"] = function(path, bufnr, ext) + if ext == "md" then + return "markdown" + elseif ext == "rst" then + return "rst" + end + end, + }, + }) +< + + Parameters: ~ + {filetypes} table A table containing new filetype maps + (see example). + +match({name}, {bufnr}) *vim.filetype.match()* + Set the filetype for the given buffer from a file name. + + Parameters: ~ + {name} string File name (can be an absolute or relative + path) + {bufnr} number|nil The buffer to set the filetype for. + Defaults to the current buffer. + + +============================================================================== +Lua module: keymap *lua-keymap* + +del({modes}, {lhs}, {opts}) *vim.keymap.del()* + Remove an existing mapping. Examples: > + + vim.keymap.del('n', 'lhs') + + vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 }) +< + + Parameters: ~ + {opts} table A table of optional arguments: + • buffer: (number or boolean) Remove a mapping + from the given buffer. When "true" or 0, use the + current buffer. + + See also: ~ + |vim.keymap.set()| + +set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()* + Add a new |mapping|. Examples: > + + -- Can add mapping to Lua functions + vim.keymap.set('n', 'lhs', function() print("real lua function") end) + + -- Can use it to map multiple modes + vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true }) + + -- Can add mapping for specific buffer + vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 }) + + -- Expr mappings + vim.keymap.set('i', '<Tab>', function() + return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>" + end, { expr = true }) + -- <Plug> mappings + vim.keymap.set('n', '[%', '<Plug>(MatchitNormalMultiBackward)') +< + + Note that in a mapping like: > + + vim.keymap.set('n', 'asdf', require('jkl').my_fun) +< + + the require('jkl') gets evaluated during this call in order to + access the function. If you want to avoid this cost at startup + you can wrap it in a function, for example: > + + vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end) +< + + Parameters: ~ + {mode} string|table Same mode short names as + |nvim_set_keymap()|. Can also be list of modes to + create mapping on multiple modes. + {lhs} string Left-hand side |{lhs}| of the mapping. + {rhs} string|function Right-hand side |{rhs}| of the + mapping. Can also be a Lua function. + {opts} table A table of |:map-arguments| such as + "silent". In addition to the options listed in + |nvim_set_keymap()|, this table also accepts the + following keys: + • replace_keycodes: (boolean, default true) When + both this and expr is "true", + |nvim_replace_termcodes()| is applied to the + result of Lua expr maps. + • remap: (boolean) Make the mapping recursive. + This is the inverse of the "noremap" option from + |nvim_set_keymap()|. Default `true` if `lhs` is + a string starting with `<plug>` + (case-insensitive), `false` otherwise. + + See also: ~ + |nvim_set_keymap()| + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 0ea2565694..9244638788 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -82,8 +82,7 @@ modes. map command applies. The mapping may remain defined for other modes where it applies. It also works when {lhs} matches the {rhs} of a - mapping. This is for when when an abbreviation - applied. + mapping. This is for when an abbreviation applied. Note: Trailing spaces are included in the {lhs}. This unmap does NOT work: > :map @@ foo @@ -158,7 +157,7 @@ type "a", then "bar" will get inserted. "<unique>" can be used in any order. They must appear right after the command, before any other arguments. - *:map-local* *:map-<buffer>* *E224* *E225* + *:map-local* *:map-<buffer>* *:map-buffer* *E224* *E225* If the first argument to one of these commands is "<buffer>" the mapping will be effective in the current buffer only. Example: > :map <buffer> ,w /[.,;]<CR> @@ -211,7 +210,7 @@ Note: ":map <script>" and ":noremap <script>" do the same thing. The "<script>" overrules the command name. Using ":noremap <script>" is preferred, because it's clearer that remapping is (mostly) disabled. - *:map-<unique>* *E226* *E227* + *:map-<unique>* *:map-unique* *E226* *E227* If the first argument to one of these commands is "<unique>" and it is used to define a new mapping or abbreviation, the command will fail if the mapping or abbreviation already exists. Example: > @@ -245,7 +244,7 @@ go through the main loop (e.g. to update the display), return "\<Ignore>". This is similar to "nothing" but makes Vim return from the loop that waits for input. -Also, keep in mind that the expression may be evaluated when looking for +Keep in mind that the expression may be evaluated when looking for typeahead, before the previous command has been executed. For example: > func StoreColumn() let g:column = col('.') @@ -837,8 +836,7 @@ g@{motion} Call the function set by the 'operatorfunc' option. "line" {motion} was |linewise| "char" {motion} was |charwise| "block" {motion} was |blockwise-visual| - Although "block" would rarely appear, since it can - only result from Visual mode where "g@" is not useful. + The type can be forced, see |forced-motion|. Here is an example that counts the number of spaces with <F4>: > @@ -1219,7 +1217,7 @@ scripts. *:command-verbose* When 'verbose' is non-zero, listing a command will also display where it was -last defined. Example: > +last defined and any completion argument. Example: > :verbose command TOhtml < Name Args Range Complete Definition ~ @@ -1248,8 +1246,8 @@ See |:verbose-cmd| for more information. Command attributes ~ - -User-defined commands are treated by Vim just like any other Ex commands. They + *command-attributes* +User-defined commands are treated by Nvim just like any other Ex commands. They can have arguments, or have a range specified. Arguments are subject to completion as filenames, buffers, etc. Exactly how this works depends upon the command's attributes, which are specified when the command is defined. @@ -1334,6 +1332,8 @@ completion can be enabled: -complete=custom,{func} custom completion, defined via {func} -complete=customlist,{func} custom completion, defined via {func} +If you specify completion while there is nothing to complete (-nargs=0, the +default) then you get error *E1208* . Note: That some completion methods might expand environment variables. @@ -1436,6 +1436,9 @@ There are some special cases as well: -register The first argument to the command can be an optional register name (like :del, :put, :yank). -buffer The command will only be available in the current buffer. + -keepscript Do not use the location of where the user command was + defined for verbose messages, use the location of where + the user command was invoked. In the cases of the -count and -register attributes, if the optional argument is supplied, it is removed from the argument list and is available to the diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt index 3bbf36c642..2aa49cee1e 100644 --- a/runtime/doc/mbyte.txt +++ b/runtime/doc/mbyte.txt @@ -489,8 +489,8 @@ Use the RPM or port for your system. window specific to the input method. -USING XIM *multibyte-input* *E284* *E286* *E287* *E288* - *E285* *E289* +USING XIM *multibyte-input* *E284* *E285* *E286* *E287* + *E288* *E289* Note that Display and Input are independent. It is possible to see your language even though you have no input method for it. But when your Display diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index 6fbd9ec922..950028d9cc 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -112,7 +112,8 @@ wiped out a buffer which contains a mark or is referenced in another way. *E95* > Buffer with this name already exists -You cannot have two buffers with the same name. +You cannot have two buffers with exactly the same name. This includes the +path leading to the file. *E72* > Close error on swap file @@ -513,10 +514,10 @@ If you type "gq", it will execute this mapping, which will call "gq" again. *E22* > Scripts nested too deep -Scripts can be read with the "-s" command-line argument and with the ":source" -command. The script can then again read another script. This can continue -for about 14 levels. When more nesting is done, Vim assumes that there is a -recursive loop somewhere and stops with this error message. +Scripts can be read with the "-s" command-line argument and with the +`:source!` command. The script can then again read another script. This can +continue for about 14 levels. When more nesting is done, Vim assumes that +there is a recursive loop and stops with this error message. *E300* > Swap file already exists (symlink attack?) @@ -686,6 +687,7 @@ Ex command or function was given an invalid argument. Or |jobstart()| or Trailing characters An argument was given to an Ex command that does not permit one. +Or the argument has invalid characters and has not been recognized. *E477* *E478* > No ! allowed diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index e83b17f9a0..f322764ecf 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -90,7 +90,7 @@ Mouse input has the following behavior: - If another window is clicked, terminal focus will be lost and nvim will jump to the clicked window - If the mouse wheel is used while the mouse is positioned in another window, - the terminal wont lose focus and the hovered window will be scrolled. + the terminal won't lose focus and the hovered window will be scrolled. ============================================================================== Configuration *terminal-config* @@ -162,12 +162,11 @@ command name, for example: > This opens two windows: gdb window A terminal window in which "gdb vim" is executed. Here you - can directly interact with gdb. The buffer name is "!gdb". + can directly interact with gdb. program window A terminal window for the executed program. When "run" is used in gdb the program I/O will happen in this window, so - that it does not interfere with controlling gdb. The buffer - name is "gdb program". + that it does not interfere with controlling gdb. The current window is used to show the source code. When gdb pauses the source file location will be displayed, if possible. A sign is used to @@ -391,6 +390,8 @@ GDB command *termdebug-customizing* To change the name of the gdb command, set the "termdebugger" variable before invoking `:Termdebug`: > let termdebugger = "mygdb" +If the command needs an argument use a List: > + let g:termdebugger = ['rr', 'replay', '--'] To not use neovim floating windows for previewing variable evaluation, set the `g:termdebug_useFloatingHover` variable like this: > @@ -426,7 +427,7 @@ When 'background' is "dark": hi debugBreakpoint term=reverse ctermbg=red guibg=red -Shorcuts *termdebug_shortcuts* +Shortcuts *termdebug_shortcuts* You can define your own shortcuts (mappings) to control gdb, that can work in any window, using the TermDebugSendCommand() function. Example: > diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 097cd38400..06236741c2 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -304,7 +304,7 @@ value to the local value, it doesn't switch back to using the global value This will make the local value of 'path' empty, so that the global value is used. Thus it does the same as: > :setlocal path= -Note: In the future more global options can be made global-local. Using +Note: In the future more global options can be made |global-local|. Using ":setlocal" on a global option might work differently then. @@ -686,10 +686,10 @@ A jump table for the options with a short description can be found at |Q_op|. Write the contents of the file, if it has been modified, on each `:next`, `:rewind`, `:last`, `:first`, `:previous`, `:stop`, `:suspend`, `:tag`, `:!`, `:make`, CTRL-] and CTRL-^ command; and when - a :buffer, CTRL-O, CTRL-I, '{A-Z0-9}, or `{A-Z0-9} command takes one + a `:buffer`, CTRL-O, CTRL-I, '{A-Z0-9}, or `{A-Z0-9} command takes one to another file. A buffer is not written if it becomes hidden, e.g. when 'bufhidden' is - set to "hide" and `:next` is used + set to "hide" and `:next` is used. Note that for some commands the 'autowrite' option is not used, see 'autowriteall' for that. Some buffers will not be written, specifically when 'buftype' is @@ -953,7 +953,6 @@ A jump table for the options with a short description can be found at |Q_op|. error Other Error occurred (e.g. try to join last line) (mostly used in |Normal-mode| or |Cmdline-mode|). esc hitting <Esc> in |Normal-mode|. - ex In |Visual-mode|, hitting |Q| results in an error. hangul Ignored. insertmode Pressing <Esc> in 'insertmode'. lang Calling the beep module for Lua/Mzscheme/TCL. @@ -1160,6 +1159,14 @@ A jump table for the options with a short description can be found at |Q_op|. case mapping, the current locale is not effective. This probably only matters for Turkish. + *'cdhome'* *'cdh'* +'cdhome' 'cdh' boolean (default: off) + global + When on, |:cd|, |:tcd| and |:lcd| without an argument changes the + current working directory to the |$HOME| directory like in Unix. + When off, those commands just print the current directory name. + On Unix this option has no effect. + *'cdpath'* *'cd'* *E344* *E346* 'cdpath' 'cd' string (default: equivalent to $CDPATH or ",,") global @@ -5124,7 +5131,8 @@ A jump table for the options with a short description can be found at |Q_op|. Don't include both "curdir" and "sesdir". When neither is included filenames are stored as absolute paths. - + If you leave out "options" many things won't work well after restoring + the session. *'shada'* *'sd'* *E526* *E527* *E528* 'shada' 'sd' string (Vim default for Win32: !,'100,<50,s10,h,rA:,rB: diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index dfed39dba6..634145da3e 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -304,7 +304,7 @@ the pattern. ============================================================================== 2. The definition of a pattern *search-pattern* *pattern* *[pattern]* *regular-expression* *regexp* *Pattern* - *E76* *E383* *E476* + *E383* *E476* For starters, read chapter 27 of the user manual |usr_27.txt|. @@ -1036,6 +1036,8 @@ match ASCII characters, as indicated by the range. \(\) A pattern enclosed by escaped parentheses. */\(* */\(\)* */\)* E.g., "\(^a\)" matches 'a' at the start of a line. + There can only be ten of these. You can use "\%(" to add more, but + not counting it as a sub-expression. *E51* *E54* *E55* *E872* *E873* \1 Matches the same string that was matched by */\1* *E65* @@ -1058,7 +1060,7 @@ x A single character, with no special meaning, matches itself \x A backslash followed by a single character, with no special meaning, is reserved for future expansions -[] (with 'nomagic': \[]) */[]* */\[]* */\_[]* */collection* +[] (with 'nomagic': \[]) */[]* */\[]* */\_[]* */collection* *E76* \_[] A collection. This is a sequence of characters enclosed in square brackets. It matches any single character in the collection. diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index ba1da209f7..873fbd8971 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -232,7 +232,7 @@ processing a quickfix or location list command, it will be aborted. ":qall!" |:qall|, except that Nvim exits non-zero or [count]. - *:cf* *:cfile* + *:cf* *:cfi* *:cfile* :cf[ile][!] [errorfile] Read the error file and jump to the first error. This is done automatically when Vim is started with the -q option. You can use this command when you diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 8cabf05053..af8301f1a0 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -489,6 +489,7 @@ In Insert or Command-line mode: |q| q{a-z} record typed characters into register {a-z} |q| q{A-Z} record typed characters, appended to register {a-z} |q| q stop recording +|Q| Q replay last recorded macro |@| N @{a-z} execute the contents of register {a-z} (N times) |@@| N @@ repeat previous @{a-z} (N times) |:@| :@{a-z} execute the contents of register {a-z} as an Ex @@ -628,6 +629,7 @@ Short explanation of each option: *option-list* 'buflisted' 'bl' whether the buffer shows up in the buffer list 'buftype' 'bt' special type of buffer 'casemap' 'cmp' specifies how case of letters is changed +'cdhome' 'cdh' change directory to the home directory by ":cd" 'cdpath' 'cd' list of directories searched with ":cd" 'cedit' key used to open the command-line window 'charconvert' 'ccv' expression for character encoding conversion @@ -997,7 +999,7 @@ Short explanation of each option: *option-list* |:version| :ve[rsion] show version information |:normal| :norm[al][!] {commands} execute Normal mode commands -|Q| Q switch to "Ex" mode +|gQ| gQ switch to "Ex" mode |:redir| :redir >{file} redirect messages to {file} |:silent| :silent[!] {command} execute {command} silently diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 7e8d93aa71..c7481ad290 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -103,7 +103,7 @@ Which is two characters shorter! When using "global" in Ex mode, a special case is using ":visual" as a command. This will move to a matching line, go to Normal mode to let you -execute commands there until you use |Q| to return to Ex mode. This will be +execute commands there until you use |gQ| to return to Ex mode. This will be repeated for each matching line. While doing this you cannot use ":global". To abort this type CTRL-C twice. @@ -147,6 +147,10 @@ q Stops recording. *@@* *E748* @@ Repeat the previous @{0-9a-z":*} [count] times. + *Q* +Q Repeat the last recorded register [count] times. + See |reg_recorded()|. + *:@* :[addr]@{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} as an Ex command. First set cursor at line [addr] (default is diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 68165f3d3d..5cfa06c33c 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -122,8 +122,9 @@ See |sign_define()| for the equivalent Vim script function. in. Most useful is defining a background color. numhl={group} - Highlighting group used for 'number' column at the associated - line. Overrides |hl-LineNr|, |hl-CursorLineNr|. + Highlighting group used for the line number on the line where + the sign is placed. Overrides |hl-LineNr|, |hl-LineNrAbove|, + |hl-LineNrBelow|, and |hl-CursorLineNr|. text={text} *E239* Define the text that is displayed when there is no icon or the diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index bb775ec884..978142a1e0 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -188,7 +188,7 @@ argument. changes and writing. -e *-e* *-E* --E Start Nvim in Ex mode |gQ|. +-E Start Nvim in Ex mode |gQ|, see |Ex-mode|. If stdin is not a TTY: -e reads/executes stdin as Ex commands. @@ -409,7 +409,12 @@ accordingly, proceeding as follows: 4. Setup |default-mappings| and |default-autocmds|. -5. Load user config (execute Ex commands from files, environment, …). +5. Enable filetype and indent plugins. + This does the same as the command: > + :runtime! ftplugin.vim indent.vim +< Skipped if the "-u NONE" command line argument was given. + +6. Load user config (execute Ex commands from files, environment, …). $VIMINIT environment variable is read as one Ex command line (separate multiple commands with '|' or <NL>). *config* *init.vim* *init.lua* *vimrc* *exrc* @@ -453,21 +458,19 @@ accordingly, proceeding as follows: - The file ".nvimrc" - The file ".exrc" -6. Enable filetype and indent plugins. - This does the same as the commands: > - :runtime! filetype.vim - :runtime! ftplugin.vim - :runtime! indent.vim -< Skipped if ":filetype … off" was called or if the "-u NONE" command - line argument was given. +7. Enable filetype detection. + This does the same as the command: > + :runtime! filetype.lua filetype.vim +< Skipped if ":filetype off" was called or if the "-u NONE" command line + argument was given. -7. Enable syntax highlighting. +8. Enable syntax highlighting. This does the same as the command: > :runtime! syntax/syntax.vim < Skipped if ":syntax off" was called or if the "-u NONE" command line argument was given. -8. Load the plugin scripts. *load-plugins* +9. Load the plugin scripts. *load-plugins* This does the same as the command: > :runtime! plugin/**/*.vim :runtime! plugin/**/*.lua @@ -497,21 +500,21 @@ accordingly, proceeding as follows: if packages have been found, but that should not add a directory ending in "after". -9. Set 'shellpipe' and 'shellredir' +10. Set 'shellpipe' and 'shellredir' The 'shellpipe' and 'shellredir' options are set according to the value of the 'shell' option, unless they have been set before. This means that Nvim will figure out the values of 'shellpipe' and 'shellredir' for you, unless you have set them yourself. -10. Set 'updatecount' to zero, if "-n" command argument used +11. Set 'updatecount' to zero, if "-n" command argument used -11. Set binary options if the |-b| flag was given. +12. Set binary options if the |-b| flag was given. -12. Read the |shada-file|. +13. Read the |shada-file|. -13. Read the quickfix file if the |-q| flag was given, or exit on failure. +14. Read the quickfix file if the |-q| flag was given, or exit on failure. -14. Open all windows +15. Open all windows When the |-o| flag was given, windows will be opened (but not displayed yet). When the |-p| flag was given, tab pages will be created (but not @@ -521,7 +524,7 @@ accordingly, proceeding as follows: Buffers for all windows will be loaded, without triggering |BufAdd| autocommands. -15. Execute startup commands +16. Execute startup commands If a |-t| flag was given, the tag is jumped to. Commands given with |-c| and |+cmd| are executed. If the 'insertmode' option is set, Insert mode is entered. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index d49809599d..be1586ab41 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -920,12 +920,16 @@ in .../after/syntax/baan.vim (see |after-directory|). Eg: > BASIC *basic.vim* *vb.vim* *ft-basic-syntax* *ft-vb-syntax* -Both Visual Basic and "normal" basic use the extension ".bas". To detect +Both Visual Basic and "normal" BASIC use the extension ".bas". To detect which one should be used, Vim checks for the string "VB_Name" in the first five lines of the file. If it is not found, filetype will be "basic", otherwise "vb". Files with the ".frm" extension will always be seen as Visual Basic. +If the automatic detection doesn't work for you or you only edit, for +example, FreeBASIC files, use this in your startup vimrc: > + :let filetype_bas = "freebasic" + C *c.vim* *ft-c-syntax* @@ -1406,7 +1410,7 @@ add the following line to your startup file: > :let g:filetype_euphoria = "euphoria4" -Elixir and Euphoria share the *.ex file extension. If the filetype is +Elixir and Euphoria share the *.ex file extension. If the filetype is specifically set as Euphoria with the g:filetype_euphoria variable, or the file is determined to be Euphoria based on keywords in the file, then the filetype will be set as Euphoria. Otherwise, the filetype will default to @@ -1437,7 +1441,7 @@ The following file extensions are auto-detected as Elixir file types: *.ex, *.exs, *.eex, *.leex, *.lock -Elixir and Euphoria share the *.ex file extension. If the filetype is +Elixir and Euphoria share the *.ex file extension. If the filetype is specifically set as Euphoria with the g:filetype_euphoria variable, or the file is determined to be Euphoria based on keywords in the file, then the filetype will be set as Euphoria. Otherwise, the filetype will default to @@ -4455,7 +4459,7 @@ it marks the "\(\I\i*\)" sub-expression as external; in the end pattern, it changes the \z1 back-reference into an external reference referring to the first external sub-expression in the start pattern. External references can also be used in skip patterns: > - :syn region foo start="start \(\I\i*\)" skip="not end \z1" end="end \z1" + :syn region foo start="start \z(\I\i*\)" skip="not end \z1" end="end \z1" Note that normal and external sub-expressions are completely orthogonal and indexed separately; for instance, if the pattern "\z(..\)\(..\)" is applied diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 935d958729..62e13285f5 100644 --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -133,7 +133,7 @@ capabilities as if they had been in the terminfo definition. If terminfo does not (yet) have this flag, Nvim will fall back to $TERM and other environment variables. It will add constructed "setrgbf" and "setrgbb" -capabilities in the case of the the "rxvt", "linux", "st", "tmux", and "iterm" +capabilities in the case of the "rxvt", "linux", "st", "tmux", and "iterm" terminal types, or when Konsole, genuine Xterm, a libvte terminal emulator version 0.36 or later, or a terminal emulator that sets the COLORTERM environment variable to "truecolor" is detected. diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 8f7241dd46..5829dbdd6b 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -100,7 +100,7 @@ tsnode:prev_named_sibling() *tsnode:prev_named_sibling()* tsnode:iter_children() *tsnode:iter_children()* Iterates over all the direct children of {tsnode}, regardless of - wether they are named or not. + whether they are named or not. Returns the child node plus the eventual field name corresponding to this child node. @@ -155,9 +155,9 @@ tsnode:sexpr() *tsnode:sexpr()* Get an S-expression representing the node as a string. tsnode:id() *tsnode:id()* - Get an unique identier for the node inside its own tree. + Get an unique identifier for the node inside its own tree. - No guarantees are made about this identifer's internal representation, + No guarantees are made about this identifier's internal representation, except for being a primitive lua type with value equality (so not a table). Presently it is a (non-printable) string. @@ -195,7 +195,7 @@ to a match. Treesitter Query Predicates *lua-treesitter-predicates* When writing queries for treesitter, one might use `predicates`, that is, -special scheme nodes that are evaluted to verify things on a captured node for +special scheme nodes that are evaluated to verify things on a captured node for example, the |eq?| predicate : > ((identifier) @foo (#eq? @foo "foo")) @@ -203,16 +203,16 @@ This will only match identifier corresponding to the `"foo"` text. Here is a list of built-in predicates : `eq?` *ts-predicate-eq?* - This predicate will check text correspondance between nodes or + This predicate will check text correspondence between nodes or strings : > ((identifier) @foo (#eq? @foo "foo")) ((node1) @left (node2) @right (#eq? @left @right)) < `match?` *ts-predicate-match?* `vim-match?` *ts-predicate-vim-match?* - This will match if the provived vim regex matches the text + This will match if the provided vim regex matches the text corresponding to a node : > - ((idenfitier) @constant (#match? @constant "^[A-Z_]+$")) + ((identifier) @constant (#match? @constant "^[A-Z_]+$")) < Note: the `^` and `$` anchors will respectively match the start and end of the node's text. @@ -267,7 +267,7 @@ Here is a list of built-in directives: `offset!` *ts-predicate-offset!* Takes the range of the captured node and applies the offsets to it's range : > - ((idenfitier) @constant (#offset! @constant 0 1 0 -1)) + ((identifier) @constant (#offset! @constant 0 1 0 -1)) < This will generate a range object for the captured node with the offsets applied. The arguments are `({capture_id}, {start_row}, {start_col}, {end_row}, {end_col}, {key?})` @@ -467,8 +467,9 @@ parse_query({lang}, {query}) *parse_query()* • `info.patterns` contains information about predicates. Parameters: ~ - {lang} The language - {query} A string containing the query (s-expr syntax) + {lang} string The language + {query} string A string containing the query (s-expr + syntax) Return: ~ The query @@ -665,7 +666,7 @@ LanguageTree:invalidate({self}, {reload}) *LanguageTree:invalidate()* {self} LanguageTree:is_valid({self}) *LanguageTree:is_valid()* - Determines whether this tree is valid. If the tree is invalid, `parse()` must be called to get the an updated tree. + Determines whether this tree is valid. If the tree is invalid, `parse()` must be called to get the updated tree. Parameters: ~ {self} diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt index 2edef0ca23..f93a221e43 100644 --- a/runtime/doc/usr_05.txt +++ b/runtime/doc/usr_05.txt @@ -11,13 +11,12 @@ Vim's capabilities. Or define your own macros. |05.1| The vimrc file |05.2| The example vimrc file explained -|05.3| The defaults.vim file explained -|05.4| Simple mappings -|05.5| Adding a package -|05.6| Adding a plugin -|05.7| Adding a help file -|05.8| The option window -|05.9| Often used options +|05.3| Simple mappings +|05.4| Adding a package +|05.5| Adding a plugin +|05.6| Adding a help file +|05.7| The option window +|05.8| Often used options Next chapter: |usr_06.txt| Using syntax highlighting Previous chapter: |usr_04.txt| Making small changes @@ -200,7 +199,7 @@ mapping. If set (default), this may break plugins (but it's backward compatible). See 'langremap'. ============================================================================== -*05.4* Simple mappings +*05.3* Simple mappings A mapping enables you to bind a set of Vim commands to a single key. Suppose, for example, that you need to surround certain words with curly braces. In @@ -247,7 +246,7 @@ The ":map" command (with no arguments) lists your current mappings. At least the ones for Normal mode. More about mappings in section |40.1|. ============================================================================== -*05.5* Adding a package *add-package* *vimball-install* +*05.4* Adding a package *add-package* *vimball-install* A package is a set of files that you can add to Vim. There are two kinds of packages: optional and automatically loaded on startup. @@ -287,7 +286,7 @@ an archive or as a repository. For an archive you can follow these steps: More information about packages can be found here: |packages|. ============================================================================== -*05.6* Adding a plugin *add-plugin* *plugin* +*05.5* Adding a plugin *add-plugin* *plugin* Vim's functionality can be extended by adding plugins. A plugin is nothing more than a Vim script file that is loaded automatically when Vim starts. You @@ -423,7 +422,7 @@ Further reading: |new-filetype| How to detect a new file type. ============================================================================== -*05.7* Adding a help file *add-local-help* +*05.6* Adding a help file *add-local-help* If you are lucky, the plugin you installed also comes with a help file. We will explain how to install the help file, so that you can easily find help @@ -456,7 +455,7 @@ them through the tag. For writing a local help file, see |write-local-help|. ============================================================================== -*05.8* The option window +*05.7* The option window If you are looking for an option that does what you want, you can search in the help files here: |options|. Another way is by using this command: > @@ -495,7 +494,7 @@ border. This is what the 'scrolloff' option does, it specifies an offset from the window border where scrolling starts. ============================================================================== -*05.9* Often used options +*05.8* Often used options There are an awful lot of options. Most of them you will hardly ever use. Some of the more useful ones will be mentioned here. Don't forget you can diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 6a9284dac9..7e611a47f3 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -852,6 +852,7 @@ Command line: *command-line-functions* getcmdtype() return the current command-line type getcmdwintype() return the current command-line window type getcompletion() list of command-line completion matches + fullcommand() get full command name Quickfix and location lists: *quickfix-functions* getqflist() list of quickfix errors diff --git a/runtime/doc/usr_toc.txt b/runtime/doc/usr_toc.txt index f466a8ece9..bf9c02882c 100644 --- a/runtime/doc/usr_toc.txt +++ b/runtime/doc/usr_toc.txt @@ -99,13 +99,12 @@ Read this from start to end to learn the essential commands. |usr_05.txt| Set your settings |05.1| The vimrc file |05.2| The example vimrc file explained - |05.3| The defaults.vim file explained - |05.4| Simple mappings - |05.5| Adding a package - |05.6| Adding a plugin - |05.7| Adding a help file - |05.8| The option window - |05.9| Often used options + |05.3| Simple mappings + |05.4| Adding a package + |05.5| Adding a plugin + |05.6| Adding a help file + |05.7| The option window + |05.8| Often used options |usr_06.txt| Using syntax highlighting |06.1| Switching it on diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index b0e0bdcb84..fc0230c62d 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -249,7 +249,7 @@ g8 Print the hex values of the bytes used in the To enter |Terminal-mode| automatically: > autocmd TermOpen * startinsert < - *:!cmd* *:!* *E34* + *:!cmd* *:!* :!{cmd} Execute {cmd} with 'shell'. See also |:terminal|. The command runs in a non-interactive shell connected @@ -261,6 +261,7 @@ g8 Print the hex values of the bytes used in the Use |jobstart()| instead. > :call jobstart('foo', {'detach':1}) < + *E34* Any "!" in {cmd} is replaced with the previous external command (see also 'cpoptions'), unless escaped by a backslash. Example: ":!ls" followed by @@ -357,19 +358,19 @@ g8 Print the hex values of the bytes used in the :redi[r] END End redirecting messages. *:filt* *:filter* -:filt[er][!] {pat} {command} -:filt[er][!] /{pat}/ {command} +:filt[er][!] {pattern} {command} +:filt[er][!] /{pattern}/ {command} Restrict the output of {command} to lines matching - with {pat}. For example, to list only xml files: > + with {pattern}. For example, to list only xml files: > :filter /\.xml$/ oldfiles < If the [!] is given, restrict the output of {command} - to lines that do NOT match {pat}. + to lines that do NOT match {pattern}. - {pat} is a Vim search pattern. Instead of enclosing + {pattern} is a Vim search pattern. Instead of enclosing it in / any non-ID character (see |'isident'|) can be - used, so long as it does not appear in {pat}. Without - the enclosing character the pattern cannot include the - bar character. 'ignorecase' is not used. + used, so long as it does not appear in {pattern}. + Without the enclosing character the pattern cannot + include the bar character. 'ignorecase' is not used. The pattern is matched against the relevant part of the output, not necessarily the whole line. Only some @@ -387,7 +388,7 @@ g8 Print the hex values of the bytes used in the |:marks| - filter by text in the current file, or file name for other files |:oldfiles| - filter by file name - |:set| - filter by variable name + |:set| - filter by option name Only normal messages are filtered, error messages are not. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index bc59ea785e..7e61eac404 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -23,8 +23,10 @@ centralized reference of the differences. ============================================================================== 2. Defaults *nvim-defaults* -- Syntax highlighting is enabled by default -- ":filetype plugin indent on" is enabled by default +- Filetype detection is enabled by default. This can be disabled by adding + ":filetype off" to |init.vim|. +- Syntax highlighting is enabled by default. This can be disabled by adding + ":syntax off" to |init.vim|. - 'autoindent' is enabled - 'autoread' is enabled @@ -180,6 +182,8 @@ Commands: |:match| can be invoked before highlight group is defined Events: + |RecordingEnter| + |RecordingLeave| |SearchWrapped| |Signal| |TabNewEntered| @@ -356,7 +360,8 @@ Motion: The |jumplist| avoids useless/phantom jumps. Normal commands: - |Q| is the same as |gQ| + |Q| replays the last recorded macro instead of switching to Ex mode. + Instead |gQ| can be used to enter Ex mode. Options: 'ttimeout', 'ttimeoutlen' behavior was simplified diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index e0c33fa2c9..5b91321c40 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -116,13 +116,15 @@ other windows. If 'mouse' is enabled, a status line can be dragged to resize windows. *filler-lines* -The lines after the last buffer line in a window are called filler lines. -These lines start with a tilde (~) character. By default, these are -highlighted as NonText (|hl-NonText|). The EndOfBuffer highlight group -(|hl-EndOfBuffer|) can be used to change the highlighting of filler lines. +The lines after the last buffer line in a window are called filler lines. By +default, these lines start with a tilde (~) character. The 'eob' item in the +'fillchars' option can be used to change this character. By default, these +characters are highlighted as NonText (|hl-NonText|). The EndOfBuffer +highlight group (|hl-EndOfBuffer|) can be used to change the highlighting of +the filler characters. ============================================================================== -3. Opening and closing a window *opening-window* *E36* +3. Opening and closing a window *opening-window* CTRL-W s *CTRL-W_s* CTRL-W S *CTRL-W_S* @@ -221,6 +223,10 @@ CTRL-W ge *CTRL-W_ge* Note that the 'splitbelow' and 'splitright' options influence where a new window will appear. + *E36* +Creating a window will fail if there is not enough room. Every window needs +at least one screen line and column, sometimes more. Options 'winminheight' +and 'winminwidth' are relevant. *:vert* *:vertical* :vert[ical] {cmd} diff --git a/runtime/filetype.lua b/runtime/filetype.lua new file mode 100644 index 0000000000..fcfc5701f0 --- /dev/null +++ b/runtime/filetype.lua @@ -0,0 +1,26 @@ +if vim.g.did_load_filetypes and vim.g.did_load_filetypes ~= 0 then + return +end + +-- For now, make this opt-in with a global variable +if vim.g.do_filetype_lua ~= 1 then + return +end + +vim.cmd [[ +augroup filetypedetect +au BufRead,BufNewFile * call v:lua.vim.filetype.match(expand('<afile>')) + +" These *must* be sourced after the autocommand above is created +runtime! ftdetect/*.vim +runtime! ftdetect/*.lua + +" Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim +let g:did_load_ftdetect = 1 + +augroup END +]] + +if not vim.g.ft_ignore_pat then + vim.g.ft_ignore_pat = "\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$" +end diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 806748b7cb..f58658a73b 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2021 Dec 03 +" Last Change: 2022 Jan 23 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -189,7 +189,8 @@ au BufNewFile,BufRead *.awk,*.gawk setf awk au BufNewFile,BufRead *.mch,*.ref,*.imp setf b " BASIC or Visual Basic -au BufNewFile,BufRead *.bas call dist#ft#FTVB("basic") +au BufNewFile,BufRead *.bas call dist#ft#FTbas() +au BufNewFile,BufRead *.bi,*.bm call dist#ft#FTbas() " Visual Basic Script (close to Visual Basic) or Visual Basic .NET au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl setf vb @@ -198,7 +199,7 @@ au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl setf vb au BufNewFile,BufRead *.iba,*.ibi setf ibasic " FreeBasic file (similar to QBasic) -au BufNewFile,BufRead *.fb,*.bi setf freebasic +au BufNewFile,BufRead *.fb setf freebasic " Batch file for MSDOS. au BufNewFile,BufRead *.bat,*.sys setf dosbatch @@ -392,7 +393,8 @@ au BufNewFile,BufRead configure.in,configure.ac setf config " CUDA Compute Unified Device Architecture au BufNewFile,BufRead *.cu,*.cuh setf cuda -" Dockerfilb; Podman uses the same syntax with name Containerfile +" Dockerfile; Podman uses the same syntax with name Containerfile +" Also see Dockerfile.* below. au BufNewFile,BufRead Containerfile,Dockerfile,*.Dockerfile setf dockerfile " WildPackets EtherPeek Decoder @@ -486,10 +488,13 @@ au BufNewFile,BufRead dict.conf,.dictrc setf dictconf " Dictd config au BufNewFile,BufRead dictd*.conf setf dictdconf +" DEP3 formatted patch files +au BufNewFile,BufRead */debian/patches/* call dist#ft#Dep3patch() + " Diff files au BufNewFile,BufRead *.diff,*.rej setf diff au BufNewFile,BufRead *.patch - \ if getline(1) =~ '^From [0-9a-f]\{40\} Mon Sep 17 00:00:00 2001$' | + \ if getline(1) =~# '^From [0-9a-f]\{40,\} Mon Sep 17 00:00:00 2001$' | \ setf gitsendemail | \ else | \ setf diff | @@ -668,20 +673,19 @@ autocmd BufRead,BufNewFile *.gift setf gift " Git au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit -au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig +au BufNewFile,BufRead NOTES_EDITMSG,EDIT_DESCRIPTION setf gitcommit +au BufNewFile,BufRead *.git/config,.gitconfig,*/etc/gitconfig setf gitconfig au BufNewFile,BufRead */.config/git/config setf gitconfig +au BufNewFile,BufRead *.git/config.worktree setf gitconfig +au BufNewFile,BufRead *.git/worktrees/*/config.worktree setf gitconfig au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig if !empty($XDG_CONFIG_HOME) au BufNewFile,BufRead $XDG_CONFIG_HOME/git/config setf gitconfig endif au BufNewFile,BufRead git-rebase-todo setf gitrebase au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail -au BufNewFile,BufRead .msg.[0-9]* - \ if getline(1) =~ '^From.*# This line is ignored.$' | - \ setf gitsendemail | - \ endif au BufNewFile,BufRead *.git/* - \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' | + \ if getline(1) =~# '^\x\{40,\}\>\|^ref: ' | \ setf git | \ endif @@ -708,7 +712,7 @@ au BufNewFile,BufRead gitolite.conf setf gitolite au BufNewFile,BufRead {,.}gitolite.rc,example.gitolite.rc setf perl " Gnuplot scripts -au BufNewFile,BufRead *.gpi setf gnuplot +au BufNewFile,BufRead *.gpi,.gnuplot setf gnuplot " Go (Google) au BufNewFile,BufRead *.go setf go @@ -880,6 +884,9 @@ au BufNewFile,BufRead *.jov,*.j73,*.jovial setf jovial " JSON au BufNewFile,BufRead *.json,*.jsonp,*.webmanifest setf json +" JSON5 +au BufNewFile,BufRead *.json5 setf json5 + " JSON Patch (RFC 6902) au BufNewFile,BufRead *.json-patch setf json @@ -955,9 +962,9 @@ au BufNewFile,BufRead lilo.conf setf lilo " Lisp (*.el = ELisp, *.cl = Common Lisp) " *.jl was removed, it's also used for Julia, better skip than guess wrong. if has("fname_case") - au BufNewFile,BufRead *.lsp,*.lisp,*.el,*.cl,*.L,.emacs,.sawfishrc setf lisp + au BufNewFile,BufRead *.lsp,*.lisp,*.asd,*.el,*.cl,*.L,.emacs,.sawfishrc setf lisp else - au BufNewFile,BufRead *.lsp,*.lisp,*.el,*.cl,.emacs,.sawfishrc setf lisp + au BufNewFile,BufRead *.lsp,*.lisp,*.asd,*.el,*.cl,.emacs,.sawfishrc setf lisp endif " SBCL implementation of Common Lisp @@ -1084,7 +1091,9 @@ au BufNewFile,BufRead *.mmp setf mmp " Modsim III (or LambdaProlog) au BufNewFile,BufRead *.mod - \ if getline(1) =~ '\<module\>' | + \ if expand("<afile>") =~ '\<go.mod$' | + \ setf gomod | + \ elseif getline(1) =~ '\<module\>' | \ setf lprolog | \ else | \ setf modsim3 | @@ -1207,6 +1216,9 @@ au BufNewFile,BufRead *.xom,*.xin setf omnimark " OPAM au BufNewFile,BufRead opam,*.opam,*.opam.template setf opam +" OpenFOAM +au BufNewFile,BufRead [a-zA-Z0-9]*Dict\(.*\)\=,[a-zA-Z]*Properties\(.*\)\=,*Transport\(.*\),fvSchemes,fvSolution,fvConstrains,fvModels,*/constant/g,*/0\(\.orig\)\=/* call dist#ft#FTfoam() + " OpenROAD au BufNewFile,BufRead *.or setf openroad @@ -1659,7 +1671,7 @@ au BufNewFile,BufRead .zshrc,.zshenv,.zlogin,.zlogout,.zcompdump setf zsh au BufNewFile,BufRead *.zsh setf zsh " Scheme -au BufNewFile,BufRead *.scm,*.ss,*.rkt,*.rktd,*.rktl setf scheme +au BufNewFile,BufRead *.scm,*.ss,*.sld,*.rkt,*.rktd,*.rktl setf scheme " Screen RC au BufNewFile,BufRead .screenrc,screenrc setf screen @@ -1741,6 +1753,7 @@ au BufNewFile,BufRead *.ice setf slice " Microsoft Visual Studio Solution au BufNewFile,BufRead *.sln setf solution +au BufNewFile,BufRead *.slnf setf json " Spice au BufNewFile,BufRead *.sp,*.spice setf spice @@ -1767,8 +1780,8 @@ au BufNewFile,BufRead *.sqr,*.sqi setf sqr au BufNewFile,BufRead *.nut setf squirrel " OpenSSH configuration -au BufNewFile,BufRead ssh_config,*/.ssh/config setf sshconfig -au BufNewFile,BufRead */etc/ssh/ssh_config.d/*.conf setf sshconfig +au BufNewFile,BufRead ssh_config,*/.ssh/config,*/.ssh/*.conf setf sshconfig +au BufNewFile,BufRead */etc/ssh/ssh_config.d/*.conf setf sshconfig " OpenSSH server configuration au BufNewFile,BufRead sshd_config setf sshdconfig @@ -2231,6 +2244,9 @@ au BufNewFile,BufRead crontab,crontab.*,*/etc/cron.d/* call s:StarSetf('crontab " dnsmasq(8) configuration au BufNewFile,BufRead */etc/dnsmasq.d/* call s:StarSetf('dnsmasq') +" Dockerfile +au BufNewFile,BufRead Dockerfile.*,Containerfile.* call s:StarSetf('dockerfile') + " Dracula au BufNewFile,BufRead drac.* call s:StarSetf('dracula') @@ -2275,6 +2291,9 @@ au BufNewFile,BufRead Kconfig.* call s:StarSetf('kconfig') " Lilo: Linux loader au BufNewFile,BufRead lilo.conf* call s:StarSetf('lilo') +" Libsensors +au BufNewFile,BufRead */etc/sensors.d/[^.]* call s:StarSetf('sensors') + " Logcheck au BufNewFile,BufRead */etc/logcheck/*.d*/* call s:StarSetf('logcheck') @@ -2397,10 +2416,12 @@ au BufNewFile,BufRead *.txt \| setf text \| endif -" Use the filetype detect plugins. They may overrule any of the previously -" detected filetypes. -runtime! ftdetect/*.vim -runtime! ftdetect/*.lua +if !exists('g:did_load_ftdetect') + " Use the filetype detect plugins. They may overrule any of the previously + " detected filetypes. + runtime! ftdetect/*.vim + runtime! ftdetect/*.lua +endif " NOTE: The above command could have ended the filetypedetect autocmd group " and started another one. Let's make sure it has ended to get to a consistent diff --git a/runtime/ftplugin/checkhealth.vim b/runtime/ftplugin/checkhealth.vim new file mode 100644 index 0000000000..3d8e9ace1a --- /dev/null +++ b/runtime/ftplugin/checkhealth.vim @@ -0,0 +1,20 @@ +" Vim filetype plugin +" Language: Neovim checkhealth buffer +" Last Change: 2021 Dec 15 + +if exists("b:did_ftplugin") + finish +endif + +runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim + +setlocal wrap breakindent linebreak +setlocal conceallevel=2 concealcursor=nc +setlocal keywordprg=:help +let &l:iskeyword='!-~,^*,^|,^",192-255' + +if exists("b:undo_ftplugin") + let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<" +else + let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<" +endif diff --git a/runtime/ftplugin/git.vim b/runtime/ftplugin/git.vim deleted file mode 100644 index 75b20f021e..0000000000 --- a/runtime/ftplugin/git.vim +++ /dev/null @@ -1,41 +0,0 @@ -" Vim filetype plugin -" Language: generic git output -" Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2019 Dec 05 - -" Only do this when not done yet for this buffer -if (exists("b:did_ftplugin")) - finish -endif -let b:did_ftplugin = 1 - -if !exists('b:git_dir') - if expand('%:p') =~# '[\/]\.git[\/]modules[\/]\|:[\/][\/]\|^\a\a\+:' - " Stay out of the way - elseif expand('%:p') =~# '[\/]\.git[\/]worktrees' - let b:git_dir = matchstr(expand('%:p'),'.*\.git[\/]worktrees[\/][^\/]\+\>') - elseif expand('%:p') =~# '\.git\>' - let b:git_dir = matchstr(expand('%:p'),'.*\.git\>') - elseif $GIT_DIR != '' - let b:git_dir = $GIT_DIR - endif - if (has('win32') || has('win64')) && exists('b:git_dir') - let b:git_dir = substitute(b:git_dir,'\\','/','g') - endif -endif - -if exists('*shellescape') && exists('b:git_dir') && b:git_dir != '' - if b:git_dir =~# '/\.git$' " Not a bare repository - let &l:path = escape(fnamemodify(b:git_dir,':h'),'\, ').','.&l:path - endif - let &l:path = escape(b:git_dir,'\, ').','.&l:path - let &l:keywordprg = 'git --git-dir='.shellescape(b:git_dir).' show' -else - setlocal keywordprg=git\ show -endif -if has('gui_running') - let &l:keywordprg = substitute(&l:keywordprg,'^git\>','git --no-pager','') -endif - -setlocal includeexpr=substitute(v:fname,'^[^/]\\+/','','') -let b:undo_ftplugin = "setl keywordprg< path< includeexpr<" diff --git a/runtime/ftplugin/gitcommit.vim b/runtime/ftplugin/gitcommit.vim index 9b1998acaa..9342799b56 100644 --- a/runtime/ftplugin/gitcommit.vim +++ b/runtime/ftplugin/gitcommit.vim @@ -1,66 +1,57 @@ " Vim filetype plugin " Language: git commit file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2019 Dec 05 +" Last Change: 2022 Jan 05 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) finish endif -runtime! ftplugin/git.vim let b:did_ftplugin = 1 -setlocal comments=:# commentstring=#\ %s setlocal nomodeline tabstop=8 formatoptions+=tl textwidth=72 setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions-=q formatoptions+=n setlocal formatlistpat+=\\\|^\\s*[-*+]\\s\\+ +setlocal include=^+++ +setlocal includeexpr=substitute(v:fname,'^[bi]/','','') -let b:undo_ftplugin = 'setl modeline< tabstop< formatoptions< tw< com< cms< formatlistpat<' +let b:undo_ftplugin = 'setl modeline< tabstop< formatoptions< tw< com< cms< formatlistpat< inc< inex<' -if exists("g:no_gitcommit_commands") || v:version < 700 - finish -endif +let s:l = search('\C\m^[#;@!$%^&|:] -\{24,\} >8 -\{24,\}$', 'cnW', '', 100) +let &l:comments = ':' . (matchstr(getline(s:l ? s:l : '$'), '^[#;@!$%^&|:]\S\@!') . '#')[0] +let &l:commentstring = &l:comments[1] . ' %s' +unlet s:l -if !exists("b:git_dir") - let b:git_dir = expand("%:p:h") +if exists("g:no_gitcommit_commands") + finish endif -command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0,b:git_dir,<f-args>) +command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0, <f-args>) let b:undo_ftplugin = b:undo_ftplugin . "|delc DiffGitCached" -function! s:diffcomplete(A,L,P) +function! s:diffcomplete(A, L, P) abort let args = "" if a:P <= match(a:L." -- "," -- ")+3 let args = args . "-p\n--stat\n--shortstat\n--summary\n--patch-with-stat\n--no-renames\n-B\n-M\n-C\n" end - if exists("b:git_dir") && a:A !~ '^-' - let tree = fnamemodify(b:git_dir,':h') - if strpart(getcwd(),0,strlen(tree)) == tree - let args = args."\n".system("git diff --cached --name-only") - endif + if a:A !~ '^-' && !empty(getftype('.git')) + let args = args."\n".system("git diff --cached --name-only") endif return args endfunction -function! s:gitdiffcached(bang,gitdir,...) - let tree = fnamemodify(a:gitdir,':h') +function! s:gitdiffcached(bang, ...) abort let name = tempname() - let git = "git" - if strpart(getcwd(),0,strlen(tree)) != tree - let git .= " --git-dir=".(exists("*shellescape") ? shellescape(a:gitdir) : '"'.a:gitdir.'"') - endif if a:0 - let extra = join(map(copy(a:000),exists("*shellescape") ? 'shellescape(v:val)' : "'\"'.v:val.'\"'")) + let extra = join(map(copy(a:000), 'shellescape(v:val)')) else let extra = "-p --stat=".&columns endif - call system(git." diff --cached --no-color --no-ext-diff ".extra." > ".(exists("*shellescape") ? shellescape(name) : name)) - exe "pedit ".(exists("*fnameescape") ? fnameescape(name) : name) + call system("git diff --cached --no-color --no-ext-diff ".extra." > ".shellescape(name)) + exe "pedit " . fnameescape(name) wincmd P - let b:git_dir = a:gitdir - command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0,b:git_dir,<f-args>) - nnoremap <buffer> <silent> q :q<CR> + command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0, <f-args>) setlocal buftype=nowrite nobuflisted noswapfile nomodifiable filetype=git endfunction diff --git a/runtime/ftplugin/gitrebase.vim b/runtime/ftplugin/gitrebase.vim index 2fed53c829..143f86a251 100644 --- a/runtime/ftplugin/gitrebase.vim +++ b/runtime/ftplugin/gitrebase.vim @@ -1,22 +1,20 @@ " Vim filetype plugin " Language: git rebase --interactive " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2019 Dec 05 +" Last Change: 2022 Jan 05 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) finish endif -runtime! ftplugin/git.vim let b:did_ftplugin = 1 -setlocal comments=:# commentstring=#\ %s formatoptions-=t +let &l:comments = ':' . (matchstr(getline('$'), '^[#;@!$%^&|:]\S\@!') . '#')[0] +let &l:commentstring = &l:comments[1] . ' %s' +setlocal formatoptions-=t setlocal nomodeline -if !exists("b:undo_ftplugin") - let b:undo_ftplugin = "" -endif -let b:undo_ftplugin = b:undo_ftplugin."|setl com< cms< fo< ml<" +let b:undo_ftplugin = "setl com< cms< fo< ml<" function! s:choose(word) abort s/^\(\w\+\>\)\=\(\s*\)\ze\x\{4,40\}\>/\=(strlen(submatch(1)) == 1 ? a:word[0] : a:word) . substitute(submatch(2),'^$',' ','')/e @@ -41,8 +39,7 @@ if exists("g:no_plugin_maps") || exists("g:no_gitrebase_maps") finish endif -nnoremap <buffer> <expr> K col('.') < 7 && expand('<Lt>cword>') =~ '\X' && getline('.') =~ '^\w\+\s\+\x\+\>' ? 'wK' : 'K' nnoremap <buffer> <silent> <C-A> :<C-U><C-R>=v:count1<CR>Cycle<CR> nnoremap <buffer> <silent> <C-X> :<C-U><C-R>=v:count1<CR>Cycle!<CR> -let b:undo_ftplugin = b:undo_ftplugin . "|exe 'nunmap <buffer> K'|exe 'nunmap <buffer> <C-A>'|exe 'nunmap <buffer> <C-X>'" +let b:undo_ftplugin = b:undo_ftplugin . "|exe 'nunmap <buffer> <C-A>'|exe 'nunmap <buffer> <C-X>'" diff --git a/runtime/ftplugin/i3config.vim b/runtime/ftplugin/i3config.vim new file mode 100644 index 0000000000..4204510e64 --- /dev/null +++ b/runtime/ftplugin/i3config.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin file +" Language: i3 config file +" Original Author: Mohamed Boughaba <mohamed dot bgb at gmail dot com> +" Maintainer: Quentin Hibon +" Version: 0.4 +" Last Change: 2021 Dec 14 + +if exists("b:did_ftplugin") | finish | endif +let b:did_ftplugin = 1 + +let b:undo_ftplugin = "setlocal cms<" + +setlocal commentstring=#\ %s diff --git a/runtime/ftplugin/solution.vim b/runtime/ftplugin/solution.vim new file mode 100644 index 0000000000..bd30c7bb19 --- /dev/null +++ b/runtime/ftplugin/solution.vim @@ -0,0 +1,37 @@ +" Vim filetype plugin file +" Language: Microsoft Visual Studio Solution +" Maintainer: Doug Kearns <dougkearns@gmail.com> +" Last Change: 2021 Dec 15 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal comments=:# +setlocal commentstring=#\ %s + +let b:undo_ftplugin = "setl com< cms<" + +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_words = + \ '\<Project\>:\<EndProject\>,' .. + \ '\<ProjectSection\>:\<EndProjectSection\>,' .. + \ '\<Global\>:\<EndGlobal\>,' .. + \ '\<GlobalSection\>:\<EndGlobalSection\>' + let b:undo_ftplugin ..= " | unlet! b:match_words" +endif + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Microsoft Visual Studio Solution Files\t*.sln\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8 noet: diff --git a/runtime/ftplugin/zsh.vim b/runtime/ftplugin/zsh.vim index 53ce1417dd..34410f1c62 100644 --- a/runtime/ftplugin/zsh.vim +++ b/runtime/ftplugin/zsh.vim @@ -18,13 +18,13 @@ setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql let b:undo_ftplugin = "setl com< cms< fo< " -if executable('zsh') +if executable('zsh') && &shell !~# '/\%(nologin\|false\)$' if !has('gui_running') && executable('less') - command! -buffer -nargs=1 RunHelp silent exe '!MANPAGER= zsh -ic "autoload -Uz run-help; run-help <args> 2>/dev/null | LESS= less"' | redraw! + command! -buffer -nargs=1 RunHelp silent exe '!MANPAGER= zsh -c "autoload -Uz run-help; run-help <args> 2>/dev/null | LESS= less"' | redraw! elseif has('terminal') - command! -buffer -nargs=1 RunHelp silent exe ':term zsh -ic "autoload -Uz run-help; run-help <args>"' + command! -buffer -nargs=1 RunHelp silent exe ':term zsh -c "autoload -Uz run-help; run-help <args>"' else - command! -buffer -nargs=1 RunHelp echo system('zsh -ic "autoload -Uz run-help; run-help <args> 2>/dev/null"') + command! -buffer -nargs=1 RunHelp echo system('zsh -c "autoload -Uz run-help; run-help <args> 2>/dev/null"') endif if !exists('current_compiler') compiler zsh diff --git a/runtime/indent/sh.vim b/runtime/indent/sh.vim index d2fb1ba452..aa47c6d1bd 100644 --- a/runtime/indent/sh.vim +++ b/runtime/indent/sh.vim @@ -109,7 +109,7 @@ function! GetShIndent() let ind += s:indent_value('continuation-line') endif elseif s:end_block(line) && !s:start_block(line) - let ind -= s:indent_value('default') + let ind = indent(lnum) elseif pnum != 0 && \ s:is_continuation_line(pline) && \ !s:end_block(curline) && diff --git a/runtime/indent/xml.vim b/runtime/indent/xml.vim index da65417939..5bf53ad1f8 100644 --- a/runtime/indent/xml.vim +++ b/runtime/indent/xml.vim @@ -39,6 +39,8 @@ setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,},!^F " autoindent: used when the indentexpr returns -1 setlocal autoindent +let b:undo_indent = "setl ai< inde< indk<" + if !exists('b:xml_indent_open') let b:xml_indent_open = '.\{-}<[:A-Z_a-z]' " pre tag, e.g. <address> @@ -51,6 +53,10 @@ if !exists('b:xml_indent_close') " let b:xml_indent_close = '.\{-}</\(address\)\@!' endif +if !exists('b:xml_indent_continuation_filetype') + let b:xml_indent_continuation_filetype = 'xml' +endif + let &cpo = s:keepcpo unlet s:keepcpo @@ -162,7 +168,7 @@ endfun func! <SID>IsXMLContinuation(line) " Checks, whether or not the line matches a start-of-tag - return a:line !~ '^\s*<' && &ft is# 'xml' + return a:line !~ '^\s*<' && &ft =~# b:xml_indent_continuation_filetype endfunc func! <SID>HasNoTagEnd(line) diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 59cb9f8c5b..b4537c2882 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -30,7 +30,7 @@ M.handlers = setmetatable({}, { __newindex = function(t, name, handler) vim.validate { handler = {handler, "t" } } rawset(t, name, handler) - if not global_diagnostic_options[name] then + if global_diagnostic_options[name] == nil then global_diagnostic_options[name] = true end end, @@ -91,23 +91,22 @@ local function filter_by_severity(severity, diagnostics) end ---@private -local function prefix_source(source, diagnostics) - vim.validate { source = {source, function(v) - return v == "always" or v == "if_many" - end, "'always' or 'if_many'" } } - - if source == "if_many" then - local sources = {} - for _, d in pairs(diagnostics) do - if d.source then - sources[d.source] = true +local function count_sources(bufnr) + local seen = {} + local count = 0 + for _, namespace_diagnostics in pairs(diagnostic_cache[bufnr]) do + for _, diagnostic in ipairs(namespace_diagnostics) do + if diagnostic.source and not seen[diagnostic.source] then + seen[diagnostic.source] = true + count = count + 1 end end - if #vim.tbl_keys(sources) <= 1 then - return diagnostics - end end + return count +end +---@private +local function prefix_source(diagnostics) return vim.tbl_map(function(d) if not d.source then return d @@ -272,6 +271,8 @@ end ---@private local function set_diagnostic_cache(namespace, bufnr, diagnostics) for _, diagnostic in ipairs(diagnostics) do + assert(diagnostic.lnum, "Diagnostic line number is required") + assert(diagnostic.col, "Diagnostic column is required") diagnostic.severity = diagnostic.severity and to_severity(diagnostic.severity) or M.severity.ERROR diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum diagnostic.end_col = diagnostic.end_col or diagnostic.col @@ -297,11 +298,6 @@ local function restore_extmarks(bufnr, last) if not found[extmark[1]] then local opts = extmark[4] opts.id = extmark[1] - -- HACK: end_row should be end_line - if opts.end_row then - opts.end_line = opts.end_row - opts.end_row = nil - end pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, extmark[2], extmark[3], opts) end end @@ -556,15 +552,24 @@ end --- - `table`: Enable this feature with overrides. Use an empty table to use default values. --- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- ----@param opts table Configuration table with the following keys: +---@param opts table|nil When omitted or "nil", retrieve the current configuration. Otherwise, a +--- configuration table with the following keys: --- - underline: (default true) Use underline for diagnostics. Options: --- * severity: Only underline diagnostics matching the given severity --- |diagnostic-severity| ---- - virtual_text: (default true) Use virtual text for diagnostics. Options: +--- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics +--- are set for a namespace, one prefix per diagnostic + the last diagnostic +--- message are shown. +--- Options: --- * severity: Only show virtual text for diagnostics matching the given --- severity |diagnostic-severity| ---- * source: (string) Include the diagnostic source in virtual ---- text. One of "always" or "if_many". +--- * source: (boolean or string) Include the diagnostic source in virtual +--- text. Use "if_many" to only show sources if there is more than +--- one diagnostic source in the buffer. Otherwise, any truthy value +--- means to always show the diagnostic source. +--- * spacing: (number) Amount of empty spaces inserted at the beginning +--- of the virtual text. +--- * prefix: (string) Prepend diagnostic message with prefix. --- * format: (function) A function that takes a diagnostic as input and --- returns a string. The return value is the text used to display --- the diagnostic. Example: @@ -595,7 +600,7 @@ end --- global diagnostic options. function M.config(opts, namespace) vim.validate { - opts = { opts, 't' }, + opts = { opts, 't', true }, namespace = { namespace, 'n', true }, } @@ -607,10 +612,13 @@ function M.config(opts, namespace) t = global_diagnostic_options end - for opt in pairs(global_diagnostic_options) do - if opts[opt] ~= nil then - t[opt] = opts[opt] - end + if not opts then + -- Return current config + return vim.deepcopy(t) + end + + for k, v in pairs(opts) do + t[k] = v end if namespace then @@ -640,7 +648,11 @@ function M.set(namespace, bufnr, diagnostics, opts) vim.validate { namespace = {namespace, 'n'}, bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, + diagnostics = { + diagnostics, + vim.tbl_islist, + "a list of diagnostics", + }, opts = {opts, 't', true}, } @@ -806,11 +818,16 @@ M.handlers.signs = { vim.validate { namespace = {namespace, 'n'}, bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, + diagnostics = { + diagnostics, + vim.tbl_islist, + "a list of diagnostics", + }, opts = {opts, 't', true}, } bufnr = get_bufnr(bufnr) + opts = opts or {} if opts.signs and opts.signs.severity then diagnostics = filter_by_severity(opts.signs.severity, diagnostics) @@ -869,11 +886,16 @@ M.handlers.underline = { vim.validate { namespace = {namespace, 'n'}, bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, + diagnostics = { + diagnostics, + vim.tbl_islist, + "a list of diagnostics", + }, opts = {opts, 't', true}, } bufnr = get_bufnr(bufnr) + opts = opts or {} if opts.underline and opts.underline.severity then diagnostics = filter_by_severity(opts.underline.severity, diagnostics) @@ -917,19 +939,27 @@ M.handlers.virtual_text = { vim.validate { namespace = {namespace, 'n'}, bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, + diagnostics = { + diagnostics, + vim.tbl_islist, + "a list of diagnostics", + }, opts = {opts, 't', true}, } bufnr = get_bufnr(bufnr) + opts = opts or {} local severity if opts.virtual_text then if opts.virtual_text.format then diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics) end - if opts.virtual_text.source then - diagnostics = prefix_source(opts.virtual_text.source, diagnostics) + if + opts.virtual_text.source + and (opts.virtual_text.source ~= "if_many" or count_sources(bufnr) > 1) + then + diagnostics = prefix_source(diagnostics) end if opts.virtual_text.severity then severity = opts.virtual_text.severity @@ -1074,7 +1104,11 @@ function M.show(namespace, bufnr, diagnostics, opts) vim.validate { namespace = { namespace, 'n', true }, bufnr = { bufnr, 'n', true }, - diagnostics = { diagnostics, 't', true }, + diagnostics = { + diagnostics, + function(v) return v == nil or vim.tbl_islist(v) end, + "a list of diagnostics", + }, opts = { opts, 't', true }, } @@ -1154,8 +1188,11 @@ end --- - header: (string or table) String to use as the header for the floating window. If a --- table, it is interpreted as a [text, hl_group] tuple. Overrides the setting --- from |vim.diagnostic.config()|. ---- - source: (string) Include the diagnostic source in the message. One of "always" or ---- "if_many". Overrides the setting from |vim.diagnostic.config()|. +--- - source: (boolean or string) Include the diagnostic source in the message. +--- Use "if_many" to only show sources if there is more than one source of +--- diagnostics in the buffer. Otherwise, any truthy value means to always show +--- the diagnostic source. Overrides the setting from +--- |vim.diagnostic.config()|. --- - format: (function) A function that takes a diagnostic as input and returns a --- string. The return value is the text used to display the diagnostic. --- Overrides the setting from |vim.diagnostic.config()|. @@ -1267,8 +1304,8 @@ function M.open_float(opts, ...) diagnostics = reformat_diagnostics(opts.format, diagnostics) end - if opts.source then - diagnostics = prefix_source(opts.source, diagnostics) + if opts.source and (opts.source ~= "if_many" or count_sources(bufnr) > 1) then + diagnostics = prefix_source(diagnostics) end local prefix_opt = if_nil(opts.prefix, (scope == "cursor" and #diagnostics <= 1) and "" or function(_, i) @@ -1342,16 +1379,16 @@ function M.reset(namespace, bufnr) diagnostic_cache[iter_bufnr][iter_namespace] = nil M.hide(iter_namespace, iter_bufnr) end - end - vim.api.nvim_buf_call(bufnr, function() - vim.api.nvim_command( - string.format( - "doautocmd <nomodeline> DiagnosticChanged %s", - vim.fn.fnameescape(vim.api.nvim_buf_get_name(bufnr)) + vim.api.nvim_buf_call(iter_bufnr, function() + vim.api.nvim_command( + string.format( + "doautocmd <nomodeline> DiagnosticChanged %s", + vim.fn.fnameescape(vim.api.nvim_buf_get_name(iter_bufnr)) + ) ) - ) - end) + end) + end end --- Add all diagnostics to the quickfix list. @@ -1516,7 +1553,13 @@ local errlist_type_map = { ---@param diagnostics table List of diagnostics |diagnostic-structure|. ---@return array of quickfix list items |setqflist-what| function M.toqflist(diagnostics) - vim.validate { diagnostics = {diagnostics, 't'} } + vim.validate { + diagnostics = { + diagnostics, + vim.tbl_islist, + "a list of diagnostics", + }, + } local list = {} for _, v in ipairs(diagnostics) do @@ -1547,7 +1590,13 @@ end --- |getloclist()|. ---@return array of diagnostics |diagnostic-structure| function M.fromqflist(list) - vim.validate { list = {list, 't'} } + vim.validate { + list = { + list, + vim.tbl_islist, + "a list of quickfix items", + }, + } local diagnostics = {} for _, item in ipairs(list) do diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua new file mode 100644 index 0000000000..736ecc1ff7 --- /dev/null +++ b/runtime/lua/vim/filetype.lua @@ -0,0 +1,1579 @@ +local api = vim.api + +local M = {} + +---@private +local function starsetf(ft) + return {function(path) + if not vim.g.fg_ignore_pat then + return ft + end + + local re = vim.regex(vim.g.fg_ignore_pat) + if re:match_str(path) then + return ft + end + end, { + -- Starset matches should always have lowest priority + priority = -math.huge, + }} +end + +---@private +local function getline(bufnr, lnum) + return api.nvim_buf_get_lines(bufnr, lnum-1, lnum, false)[1] +end + +-- Filetypes based on file extension +-- luacheck: push no unused args +local extension = { + -- BEGIN EXTENSION + ["8th"] = "8th", + ["a65"] = "a65", + aap = "aap", + abap = "abap", + abc = "abc", + abl = "abel", + wrm = "acedb", + ads = "ada", + ada = "ada", + gpr = "ada", + adb = "ada", + tdf = "ahdl", + aidl = "aidl", + aml = "aml", + run = "ampl", + scpt = "applescript", + ino = "arduino", + pde = "arduino", + art = "art", + asciidoc = "asciidoc", + adoc = "asciidoc", + ["asn1"] = "asn", + asn = "asn", + atl = "atlas", + as = "atlas", + ahk = "autohotkey", + ["au3"] = "autoit", + ave = "ave", + gawk = "awk", + awk = "awk", + ref = "b", + imp = "b", + mch = "b", + bc = "bc", + bdf = "bdf", + beancount = "beancount", + bib = "bib", + bl = "blank", + bsdl = "bsdl", + bst = "bst", + bzl = "bzl", + bazel = "bzl", + BUILD = "bzl", + qc = "c", + cabal = "cabal", + cdl = "cdl", + toc = "cdrtoc", + cfc = "cf", + cfm = "cf", + cfi = "cf", + cfg = "cfg", + hgrc = "cfg", + chf = "ch", + chai = "chaiscript", + chs = "chaskell", + chopro = "chordpro", + crd = "chordpro", + crdpro = "chordpro", + cho = "chordpro", + chordpro = "chordpro", + eni = "cl", + dcl = "clean", + icl = "clean", + cljx = "clojure", + clj = "clojure", + cljc = "clojure", + cljs = "clojure", + cmake = "cmake", + cmod = "cmod", + lib = "cobol", + cob = "cobol", + cbl = "cobol", + atg = "coco", + recipe = "conaryrecipe", + mklx = "context", + mkiv = "context", + mkii = "context", + mkxl = "context", + mkvi = "context", + moc = "cpp", + hh = "cpp", + tlh = "cpp", + inl = "cpp", + ipp = "cpp", + ["c++"] = "cpp", + C = "cpp", + cxx = "cpp", + H = "cpp", + tcc = "cpp", + hxx = "cpp", + hpp = "cpp", + cpp = function(path, bufnr) + if vim.g.cynlib_syntax_for_cc then + return "cynlib" + end + return "cpp" + end, + cc = function(path, bufnr) + if vim.g.cynlib_syntax_for_cc then + return "cynlib" + end + return "cpp" + end, + crm = "crm", + csx = "cs", + cs = "cs", + csc = "csc", + csdl = "csdl", + fdr = "csp", + csp = "csp", + css = "css", + con = "cterm", + feature = "cucumber", + cuh = "cuda", + cu = "cuda", + pld = "cupl", + si = "cuplsim", + cyn = "cynpp", + dart = "dart", + drt = "dart", + ds = "datascript", + dcd = "dcd", + def = "def", + desc = "desc", + directory = "desktop", + desktop = "desktop", + diff = "diff", + rej = "diff", + Dockerfile = "dockerfile", + sys = "dosbatch", + bat = "dosbatch", + wrap = "dosini", + ini = "dosini", + dot = "dot", + gv = "dot", + drac = "dracula", + drc = "dracula", + dtd = "dtd", + dts = "dts", + dtsi = "dts", + dylan = "dylan", + intr = "dylanintr", + lid = "dylanlid", + ecd = "ecd", + eex = "eelixir", + leex = "eelixir", + exs = "elixir", + elm = "elm", + epp = "epuppet", + erl = "erlang", + hrl = "erlang", + yaws = "erlang", + erb = "eruby", + rhtml = "eruby", + ec = "esqlc", + EC = "esqlc", + strl = "esterel", + exp = "expect", + factor = "factor", + fal = "falcon", + fan = "fan", + fwt = "fan", + fnl = "fennel", + ["m4gl"] = "fgl", + ["4gl"] = "fgl", + ["4gh"] = "fgl", + fish = "fish", + focexec = "focexec", + fex = "focexec", + fth = "forth", + ft = "forth", + FOR = "fortran", + ["f77"] = "fortran", + ["f03"] = "fortran", + fortran = "fortran", + ["F95"] = "fortran", + ["f90"] = "fortran", + ["F03"] = "fortran", + fpp = "fortran", + FTN = "fortran", + ftn = "fortran", + ["for"] = "fortran", + ["F90"] = "fortran", + ["F77"] = "fortran", + ["f95"] = "fortran", + FPP = "fortran", + f = "fortran", + F = "fortran", + ["F08"] = "fortran", + ["f08"] = "fortran", + fpc = "fpcmake", + fsl = "framescript", + fb = "freebasic", + fsi = "fsharp", + fsx = "fsharp", + gdmo = "gdmo", + mo = "gdmo", + ged = "gedcom", + gmi = "gemtext", + gemini = "gemtext", + gift = "gift", + gpi = "gnuplot", + gnuplot = "gnuplot", + go = "go", + gp = "gp", + gs = "grads", + gretl = "gretl", + gradle = "groovy", + groovy = "groovy", + gsp = "gsp", + haml = "haml", + hsm = "hamster", + ["hs-boot"] = "haskell", + hsig = "haskell", + hsc = "haskell", + hs = "haskell", + ht = "haste", + htpp = "hastepreproc", + hb = "hb", + sum = "hercules", + errsum = "hercules", + ev = "hercules", + vc = "hercules", + hex = "hex", + ["h32"] = "hex", + hog = "hog", + hws = "hollywood", + htt = "httest", + htb = "httest", + iba = "ibasic", + ibi = "ibasic", + icn = "icon", + inf = "inform", + INF = "inform", + ii = "initng", + iss = "iss", + mst = "ist", + ist = "ist", + ijs = "j", + JAL = "jal", + jal = "jal", + jpr = "jam", + jpl = "jam", + jav = "java", + java = "java", + jj = "javacc", + jjt = "javacc", + es = "javascript", + mjs = "javascript", + javascript = "javascript", + js = "javascript", + cjs = "javascript", + jsx = "javascriptreact", + clp = "jess", + jgr = "jgraph", + ["j73"] = "jovial", + jov = "jovial", + jovial = "jovial", + properties = "jproperties", + slnf = "json", + json = "json", + jsonp = "json", + webmanifest = "json", + ipynb = "json", + ["json-patch"] = "json", + json5 = "json5", + jsonc = "jsonc", + jsp = "jsp", + jl = "julia", + kv = "kivy", + kix = "kix", + kts = "kotlin", + kt = "kotlin", + ktm = "kotlin", + ks = "kscript", + k = "kwt", + ACE = "lace", + ace = "lace", + latte = "latte", + lte = "latte", + ld = "ld", + ldif = "ldif", + less = "less", + lex = "lex", + lxx = "lex", + ["l++"] = "lex", + l = "lex", + lhs = "lhaskell", + ll = "lifelines", + liquid = "liquid", + cl = "lisp", + L = "lisp", + lisp = "lisp", + el = "lisp", + lsp = "lisp", + asd = "lisp", + lt = "lite", + lite = "lite", + lgt = "logtalk", + lotos = "lotos", + lot = "lotos", + lout = "lout", + lou = "lout", + ulpc = "lpc", + lpc = "lpc", + sig = "lprolog", + lsl = "lsl", + lss = "lss", + nse = "lua", + rockspec = "lua", + lua = "lua", + quake = "m3quake", + at = "m4", + eml = "mail", + mk = "make", + mak = "make", + dsp = "make", + page = "mallard", + map = "map", + mws = "maple", + mpl = "maple", + mv = "maple", + mkdn = "markdown", + md = "markdown", + mdwn = "markdown", + mkd = "markdown", + markdown = "markdown", + mdown = "markdown", + mhtml = "mason", + comp = "mason", + mason = "mason", + master = "master", + mas = "master", + mel = "mel", + mf = "mf", + mgl = "mgl", + mgp = "mgp", + my = "mib", + mib = "mib", + mix = "mix", + mixal = "mix", + nb = "mma", + mmp = "mmp", + DEF = "modula2", + ["m2"] = "modula2", + MOD = "modula2", + mi = "modula2", + ssc = "monk", + monk = "monk", + tsc = "monk", + isc = "monk", + moo = "moo", + mp = "mp", + mof = "msidl", + odl = "msidl", + msql = "msql", + mu = "mupad", + mush = "mush", + mysql = "mysql", + ["n1ql"] = "n1ql", + nql = "n1ql", + nanorc = "nanorc", + ncf = "ncf", + nginx = "nginx", + ninja = "ninja", + nqc = "nqc", + roff = "nroff", + tmac = "nroff", + man = "nroff", + mom = "nroff", + nr = "nroff", + tr = "nroff", + nsi = "nsis", + nsh = "nsis", + obj = "obj", + mlt = "ocaml", + mly = "ocaml", + mll = "ocaml", + mlp = "ocaml", + mlip = "ocaml", + mli = "ocaml", + ml = "ocaml", + occ = "occam", + xom = "omnimark", + xin = "omnimark", + opam = "opam", + ["or"] = "openroad", + ora = "ora", + pxsl = "papp", + papp = "papp", + pxml = "papp", + pas = "pascal", + lpr = "pascal", + dpr = "pascal", + pbtxt = "pbtxt", + g = "pccts", + pcmk = "pcmk", + pdf = "pdf", + plx = "perl", + psgi = "perl", + al = "perl", + ctp = "php", + php = "php", + phtml = "php", + pike = "pike", + pmod = "pike", + rcp = "pilrc", + pli = "pli", + ["pl1"] = "pli", + ["p36"] = "plm", + plm = "plm", + pac = "plm", + plp = "plp", + pls = "plsql", + plsql = "plsql", + po = "po", + pot = "po", + pod = "pod", + pk = "poke", + ps = "postscr", + epsi = "postscr", + afm = "postscr", + epsf = "postscr", + eps = "postscr", + pfa = "postscr", + ai = "postscr", + pov = "pov", + ppd = "ppd", + it = "ppwiz", + ih = "ppwiz", + action = "privoxy", + pc = "proc", + pdb = "prolog", + pml = "promela", + proto = "proto", + ["psd1"] = "ps1", + ["psm1"] = "ps1", + ["ps1"] = "ps1", + pssc = "ps1", + ["ps1xml"] = "ps1xml", + psf = "psf", + psl = "psl", + arr = "pyret", + pxd = "pyrex", + pyx = "pyrex", + pyw = "python", + py = "python", + pyi = "python", + ptl = "python", + rad = "radiance", + mat = "radiance", + ["pod6"] = "raku", + rakudoc = "raku", + rakutest = "raku", + rakumod = "raku", + ["pm6"] = "raku", + raku = "raku", + ["t6"] = "raku", + ["p6"] = "raku", + raml = "raml", + rbs = "rbs", + rego = "rego", + rem = "remind", + remind = "remind", + frt = "reva", + testUnit = "rexx", + rex = "rexx", + orx = "rexx", + rexx = "rexx", + jrexx = "rexx", + rxj = "rexx", + rexxj = "rexx", + testGroup = "rexx", + rxo = "rexx", + Rd = "rhelp", + rd = "rhelp", + rib = "rib", + Rmd = "rmd", + rmd = "rmd", + smd = "rmd", + Smd = "rmd", + rnc = "rnc", + rng = "rng", + rnw = "rnoweb", + snw = "rnoweb", + Rnw = "rnoweb", + Snw = "rnoweb", + rsc = "routeros", + x = "rpcgen", + rpl = "rpl", + Srst = "rrst", + srst = "rrst", + Rrst = "rrst", + rrst = "rrst", + rst = "rst", + rtf = "rtf", + rjs = "ruby", + rxml = "ruby", + rb = "ruby", + rant = "ruby", + ru = "ruby", + rbw = "ruby", + gemspec = "ruby", + builder = "ruby", + rake = "ruby", + rs = "rust", + sas = "sas", + sass = "sass", + sa = "sather", + sbt = "sbt", + scala = "scala", + sc = "scala", + scd = "scdoc", + ss = "scheme", + scm = "scheme", + sld = "scheme", + rkt = "scheme", + rktd = "scheme", + rktl = "scheme", + sce = "scilab", + sci = "scilab", + scss = "scss", + sd = "sd", + sdc = "sdc", + pr = "sdl", + sdl = "sdl", + sed = "sed", + sexp = "sexplib", + sieve = "sieve", + siv = "sieve", + sil = "sil", + sim = "simula", + ["s85"] = "sinda", + sin = "sinda", + ssm = "sisu", + sst = "sisu", + ssi = "sisu", + ["_sst"] = "sisu", + ["-sst"] = "sisu", + il = "skill", + ils = "skill", + cdf = "skill", + sl = "slang", + ice = "slice", + score = "slrnsc", + tpl = "smarty", + ihlp = "smcl", + smcl = "smcl", + hlp = "smcl", + smith = "smith", + smt = "smith", + sml = "sml", + spt = "snobol4", + sno = "snobol4", + sln = "solution", + sparql = "sparql", + rq = "sparql", + spec = "spec", + spice = "spice", + sp = "spice", + spd = "spup", + spdata = "spup", + speedup = "spup", + spi = "spyce", + spy = "spyce", + tyc = "sql", + typ = "sql", + pkb = "sql", + tyb = "sql", + pks = "sql", + sqlj = "sqlj", + sqi = "sqr", + sqr = "sqr", + nut = "squirrel", + ["s28"] = "srec", + ["s37"] = "srec", + srec = "srec", + mot = "srec", + ["s19"] = "srec", + st = "st", + imata = "stata", + ["do"] = "stata", + mata = "stata", + ado = "stata", + stp = "stp", + svelte = "svelte", + svg = "svg", + swift = "swift", + svh = "systemverilog", + sv = "systemverilog", + tak = "tak", + task = "taskedit", + tm = "tcl", + tcl = "tcl", + itk = "tcl", + itcl = "tcl", + tk = "tcl", + jacl = "tcl", + tmpl = "template", + ti = "terminfo", + dtx = "tex", + ltx = "tex", + bbl = "tex", + latex = "tex", + sty = "tex", + texi = "texinfo", + txi = "texinfo", + texinfo = "texinfo", + text = "text", + tf = "tf", + tli = "tli", + toml = "toml", + tpp = "tpp", + treetop = "treetop", + slt = "tsalt", + tsscl = "tsscl", + tssgm = "tssgm", + tssop = "tssop", + tutor = "tutor", + twig = "twig", + ts = function(path, bufnr) + if getline(bufnr, 1):find("<%?xml") then + return "xml" + else + return "typescript" + end + end, + tsx = "typescriptreact", + uc = "uc", + uit = "uil", + uil = "uil", + sba = "vb", + vb = "vb", + dsm = "vb", + ctl = "vb", + vbs = "vb", + vr = "vera", + vri = "vera", + vrh = "vera", + v = "verilog", + va = "verilogams", + vams = "verilogams", + vhdl = "vhdl", + vst = "vhdl", + vhd = "vhdl", + hdl = "vhdl", + vho = "vhdl", + vbe = "vhdl", + vim = "vim", + vba = "vim", + mar = "vmasm", + cm = "voscm", + wrl = "vrml", + vroom = "vroom", + vue = "vue", + wat = "wast", + wast = "wast", + wm = "webmacro", + wbt = "winbatch", + wml = "wml", + wsml = "wsml", + ad = "xdefaults", + xhtml = "xhtml", + xht = "xhtml", + msc = "xmath", + msf = "xmath", + ["psc1"] = "xml", + tpm = "xml", + xliff = "xml", + atom = "xml", + xul = "xml", + cdxml = "xml", + mpd = "xml", + rss = "xml", + fsproj = "xml", + ui = "xml", + vbproj = "xml", + xlf = "xml", + wsdl = "xml", + csproj = "xml", + wpl = "xml", + xmi = "xml", + ["xpm2"] = "xpm2", + xqy = "xquery", + xqm = "xquery", + xquery = "xquery", + xq = "xquery", + xql = "xquery", + xs = "xs", + xsd = "xsd", + xsl = "xslt", + xslt = "xslt", + yy = "yacc", + ["y++"] = "yacc", + yxx = "yacc", + yml = "yaml", + yaml = "yaml", + ["z8a"] = "z8a", + zig = "zig", + zu = "zimbu", + zut = "zimbutempl", + zsh = "zsh", + E = function() vim.fn["dist#ft#FTe"]() end, + EU = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + EW = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + EX = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + EXU = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + EXW = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + PL = function() vim.fn["dist#ft#FTpl"]() end, + R = function() vim.fn["dist#ft#FTr"]() end, + asm = function() vim.fn["dist#ft#FTasm"]() end, + bas = function() vim.fn["dist#ft#FTbas"]() end, + bi = function() vim.fn["dist#ft#FTbas"]() end, + bm = function() vim.fn["dist#ft#FTbas"]() end, + bash = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + btm = function() vim.fn["dist#ft#FTbtm"]() end, + c = function() vim.fn["dist#ft#FTlpc"]() end, + ch = function() vim.fn["dist#ft#FTchange"]() end, + com = function() vim.fn["dist#ft#BindzoneCheck"]('dcl') end, + cpt = function() vim.fn["dist#ft#FThtml"]() end, + csh = function() vim.fn["dist#ft#CSH"]() end, + d = function() vim.fn["dist#ft#DtraceCheck"]() end, + db = function() vim.fn["dist#ft#BindzoneCheck"]('') end, + dtml = function() vim.fn["dist#ft#FThtml"]() end, + e = function() vim.fn["dist#ft#FTe"]() end, + ebuild = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + eclass = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ent = function() vim.fn["dist#ft#FTent"]() end, + env = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + eu = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + ew = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + ex = function() vim.fn["dist#ft#ExCheck"]() end, + exu = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + exw = function() vim.fn["dist#ft#EuphoriaCheck"]() end, + frm = function() vim.fn["dist#ft#FTVB"]("form") end, + fs = function() vim.fn["dist#ft#FTfs"]() end, + h = function() vim.fn["dist#ft#FTheader"]() end, + htm = function() vim.fn["dist#ft#FThtml"]() end, + html = function() vim.fn["dist#ft#FThtml"]() end, + i = function() vim.fn["dist#ft#FTprogress_asm"]() end, + idl = function() vim.fn["dist#ft#FTidl"]() end, + inc = function() vim.fn["dist#ft#FTinc"]() end, + inp = function() vim.fn["dist#ft#Check_inp"]() end, + ksh = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end, + lst = function() vim.fn["dist#ft#FTasm"]() end, + m = function() vim.fn["dist#ft#FTm"]() end, + mac = function() vim.fn["dist#ft#FTasm"]() end, + mc = function() vim.fn["dist#ft#McSetf"]() end, + mm = function() vim.fn["dist#ft#FTmm"]() end, + mms = function() vim.fn["dist#ft#FTmms"]() end, + p = function() vim.fn["dist#ft#FTprogress_pascal"]() end, + patch = function(path, bufnr) + local firstline = getline(bufnr, 1) + if string.find(firstline, "^From " .. string.rep("%x", 40) .. "+ Mon Sep 17 00:00:00 2001$") then + return "gitsendemail" + else + return "diff" + end + end, + pl = function() vim.fn["dist#ft#FTpl"]() end, + pp = function() vim.fn["dist#ft#FTpp"]() end, + pro = function() vim.fn["dist#ft#ProtoCheck"]('idlang') end, + pt = function() vim.fn["dist#ft#FThtml"]() end, + r = function() vim.fn["dist#ft#FTr"]() end, + rdf = function() vim.fn["dist#ft#Redif"]() end, + rules = function() vim.fn["dist#ft#FTRules"]() end, + sh = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + shtml = function() vim.fn["dist#ft#FThtml"]() end, + sql = function() vim.fn["dist#ft#SQL"]() end, + stm = function() vim.fn["dist#ft#FThtml"]() end, + tcsh = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end, + tex = function() vim.fn["dist#ft#FTtex"]() end, + w = function() vim.fn["dist#ft#FTprogress_cweb"]() end, + xml = function() vim.fn["dist#ft#FTxml"]() end, + y = function() vim.fn["dist#ft#FTy"]() end, + zsql = function() vim.fn["dist#ft#SQL"]() end, + txt = function(path, bufnr) + --helpfiles match *.txt, but should have a modeline as last line + if not getline(bufnr, -1):match("vim:.*ft=help") then + return "text" + end + end, + -- END EXTENSION +} + +local filename = { + -- BEGIN FILENAME + ["a2psrc"] = "a2ps", + ["/etc/a2ps.cfg"] = "a2ps", + [".a2psrc"] = "a2ps", + [".asoundrc"] = "alsaconf", + ["/usr/share/alsa/alsa.conf"] = "alsaconf", + ["/etc/asound.conf"] = "alsaconf", + ["build.xml"] = "ant", + [".htaccess"] = "apache", + ["apt.conf"] = "aptconf", + ["/.aptitude/config"] = "aptconf", + ["=tagging-method"] = "arch", + [".arch-inventory"] = "arch", + ["GNUmakefile.am"] = "automake", + ["named.root"] = "bindzone", + WORKSPACE = "bzl", + BUILD = "bzl", + ["cabal.config"] = "cabalconfig", + ["cabal.project"] = "cabalproject", + calendar = "calendar", + catalog = "catalog", + ["/etc/cdrdao.conf"] = "cdrdaoconf", + [".cdrdao"] = "cdrdaoconf", + ["/etc/default/cdrdao"] = "cdrdaoconf", + ["/etc/defaults/cdrdao"] = "cdrdaoconf", + ["cfengine.conf"] = "cfengine", + ["CMakeLists.txt"] = "cmake", + ["auto.master"] = "conf", + ["configure.in"] = "config", + ["configure.ac"] = "config", + [".cvsrc"] = "cvsrc", + ["/debian/changelog"] = "debchangelog", + ["changelog.dch"] = "debchangelog", + ["changelog.Debian"] = "debchangelog", + ["NEWS.dch"] = "debchangelog", + ["NEWS.Debian"] = "debchangelog", + ["/debian/control"] = "debcontrol", + ["/debian/copyright"] = "debcopyright", + ["/etc/apt/sources.list"] = "debsources", + ["denyhosts.conf"] = "denyhosts", + ["dict.conf"] = "dictconf", + [".dictrc"] = "dictconf", + ["/etc/DIR_COLORS"] = "dircolors", + [".dir_colors"] = "dircolors", + [".dircolors"] = "dircolors", + ["/etc/dnsmasq.conf"] = "dnsmasq", + Containerfile = "dockerfile", + Dockerfile = "dockerfile", + npmrc = "dosini", + ["/etc/yum.conf"] = "dosini", + ["/etc/pacman.conf"] = "dosini", + [".npmrc"] = "dosini", + [".editorconfig"] = "dosini", + dune = "dune", + jbuild = "dune", + ["dune-workspace"] = "dune", + ["dune-project"] = "dune", + ["elinks.conf"] = "elinks", + ["mix.lock"] = "elixir", + ["filter-rules"] = "elmfilt", + ["exim.conf"] = "exim", + exports = "exports", + [".fetchmailrc"] = "fetchmail", + fvSchemes = function() vim.fn["dist#ft#FTfoam"]() end, + fvSolution = function() vim.fn["dist#ft#FTfoam"]() end, + fvConstraints = function() vim.fn["dist#ft#FTfoam"]() end, + fvModels = function() vim.fn["dist#ft#FTfoam"]() end, + fstab = "fstab", + mtab = "fstab", + [".gdbinit"] = "gdb", + gdbinit = "gdb", + ["lltxxxxx.txt"] = "gedcom", + ["TAG_EDITMSG"] = "gitcommit", + ["MERGE_MSG"] = "gitcommit", + ["COMMIT_EDITMSG"] = "gitcommit", + ["NOTES_EDITMSG"] = "gitcommit", + ["EDIT_DESCRIPTION"] = "gitcommit", + [".gitconfig"] = "gitconfig", + [".gitmodules"] = "gitconfig", + ["gitolite.conf"] = "gitolite", + ["git-rebase-todo"] = "gitrebase", + gkrellmrc = "gkrellmrc", + [".gnashrc"] = "gnash", + [".gnashpluginrc"] = "gnash", + gnashpluginrc = "gnash", + gnashrc = "gnash", + [".gprc"] = "gp", + ["/.gnupg/gpg.conf"] = "gpg", + ["/.gnupg/options"] = "gpg", + ["/var/backups/gshadow.bak"] = "group", + ["/etc/gshadow"] = "group", + ["/etc/group-"] = "group", + ["/etc/gshadow.edit"] = "group", + ["/etc/gshadow-"] = "group", + ["/etc/group"] = "group", + ["/var/backups/group.bak"] = "group", + ["/etc/group.edit"] = "group", + ["/boot/grub/menu.lst"] = "grub", + ["/etc/grub.conf"] = "grub", + ["/boot/grub/grub.conf"] = "grub", + [".gtkrc"] = "gtkrc", + gtkrc = "gtkrc", + ["snort.conf"] = "hog", + ["vision.conf"] = "hog", + ["/etc/host.conf"] = "hostconf", + ["/etc/hosts.allow"] = "hostsaccess", + ["/etc/hosts.deny"] = "hostsaccess", + ["/i3/config"] = "i3config", + ["/sway/config"] = "i3config", + ["/.sway/config"] = "i3config", + ["/.i3/config"] = "i3config", + ["/.icewm/menu"] = "icemenu", + [".indent.pro"] = "indent", + indentrc = "indent", + inittab = "inittab", + ["ipf.conf"] = "ipfilter", + ["ipf6.conf"] = "ipfilter", + ["ipf.rules"] = "ipfilter", + [".eslintrc"] = "json", + [".babelrc"] = "json", + ["Pipfile.lock"] = "json", + [".firebaserc"] = "json", + [".prettierrc"] = "json", + Kconfig = "kconfig", + ["Kconfig.debug"] = "kconfig", + ["lftp.conf"] = "lftp", + [".lftprc"] = "lftp", + ["/.libao"] = "libao", + ["/etc/libao.conf"] = "libao", + ["lilo.conf"] = "lilo", + ["/etc/limits"] = "limits", + [".emacs"] = "lisp", + sbclrc = "lisp", + [".sbclrc"] = "lisp", + [".sawfishrc"] = "lisp", + ["/etc/login.access"] = "loginaccess", + ["/etc/login.defs"] = "logindefs", + ["lynx.cfg"] = "lynx", + ["m3overrides"] = "m3build", + ["m3makefile"] = "m3build", + ["cm3.cfg"] = "m3quake", + [".followup"] = "mail", + [".article"] = "mail", + [".letter"] = "mail", + ["/etc/aliases"] = "mailaliases", + ["/etc/mail/aliases"] = "mailaliases", + mailcap = "mailcap", + [".mailcap"] = "mailcap", + ["/etc/man.conf"] = "manconf", + ["man.config"] = "manconf", + ["meson.build"] = "meson", + ["meson_options.txt"] = "meson", + ["/etc/conf.modules"] = "modconf", + ["/etc/modules"] = "modconf", + ["/etc/modules.conf"] = "modconf", + ["/.mplayer/config"] = "mplayerconf", + ["mplayer.conf"] = "mplayerconf", + mrxvtrc = "mrxvtrc", + [".mrxvtrc"] = "mrxvtrc", + ["/etc/nanorc"] = "nanorc", + Neomuttrc = "neomuttrc", + [".netrc"] = "netrc", + [".ocamlinit"] = "ocaml", + [".octaverc"] = "octave", + octaverc = "octave", + ["octave.conf"] = "octave", + opam = "opam", + ["/etc/pam.conf"] = "pamconf", + ["pam_env.conf"] = "pamenv", + [".pam_environment"] = "pamenv", + ["/var/backups/passwd.bak"] = "passwd", + ["/var/backups/shadow.bak"] = "passwd", + ["/etc/passwd"] = "passwd", + ["/etc/passwd-"] = "passwd", + ["/etc/shadow.edit"] = "passwd", + ["/etc/shadow-"] = "passwd", + ["/etc/shadow"] = "passwd", + ["/etc/passwd.edit"] = "passwd", + ["pf.conf"] = "pf", + ["main.cf"] = "pfmain", + pinerc = "pine", + [".pinercex"] = "pine", + [".pinerc"] = "pine", + pinercex = "pine", + ["/etc/pinforc"] = "pinfo", + ["/.pinforc"] = "pinfo", + [".povrayrc"] = "povini", + [".procmailrc"] = "procmail", + [".procmail"] = "procmail", + ["/etc/protocols"] = "protocols", + [".pythonstartup"] = "python", + [".pythonrc"] = "python", + SConstruct = "python", + ratpoisonrc = "ratpoison", + [".ratpoisonrc"] = "ratpoison", + v = "rcs", + inputrc = "readline", + [".inputrc"] = "readline", + [".reminders"] = "remind", + ["resolv.conf"] = "resolv", + ["robots.txt"] = "robots", + Gemfile = "ruby", + Puppetfile = "ruby", + [".irbrc"] = "ruby", + irbrc = "ruby", + ["smb.conf"] = "samba", + screenrc = "screen", + [".screenrc"] = "screen", + ["/etc/sensors3.conf"] = "sensors", + ["/etc/sensors.conf"] = "sensors", + ["/etc/services"] = "services", + ["/etc/serial.conf"] = "setserial", + ["/etc/udev/cdsymlinks.conf"] = "sh", + ["/etc/slp.conf"] = "slpconf", + ["/etc/slp.reg"] = "slpreg", + ["/etc/slp.spi"] = "slpspi", + [".slrnrc"] = "slrnrc", + ["sendmail.cf"] = "sm", + ["squid.conf"] = "squid", + ["/.ssh/config"] = "sshconfig", + ["ssh_config"] = "sshconfig", + ["sshd_config"] = "sshdconfig", + ["/etc/sudoers"] = "sudoers", + ["sudoers.tmp"] = "sudoers", + ["/etc/sysctl.conf"] = "sysctl", + tags = "tags", + [".tclshrc"] = "tcl", + [".wishrc"] = "tcl", + ["tclsh.rc"] = "tcl", + ["texmf.cnf"] = "texmf", + COPYING = "text", + README = "text", + LICENSE = "text", + AUTHORS = "text", + tfrc = "tf", + [".tfrc"] = "tf", + ["tidy.conf"] = "tidy", + tidyrc = "tidy", + [".tidyrc"] = "tidy", + [".tmux.conf"] = "tmux", + ["/.cargo/config"] = "toml", + Pipfile = "toml", + ["Gopkg.lock"] = "toml", + ["/.cargo/credentials"] = "toml", + ["Cargo.lock"] = "toml", + ["trustees.conf"] = "trustees", + ["/etc/udev/udev.conf"] = "udevconf", + ["/etc/updatedb.conf"] = "updatedb", + ["fdrupstream.log"] = "upstreamlog", + vgrindefs = "vgrindefs", + [".exrc"] = "vim", + ["_exrc"] = "vim", + ["_viminfo"] = "viminfo", + [".viminfo"] = "viminfo", + [".wgetrc"] = "wget", + wgetrc = "wget", + [".wvdialrc"] = "wvdial", + ["wvdial.conf"] = "wvdial", + [".Xresources"] = "xdefaults", + [".Xpdefaults"] = "xdefaults", + ["xdm-config"] = "xdefaults", + [".Xdefaults"] = "xdefaults", + ["/etc/xinetd.conf"] = "xinetd", + fglrxrc = "xml", + ["/etc/blkid.tab"] = "xml", + ["/etc/blkid.tab.old"] = "xml", + ["/etc/zprofile"] = "zsh", + [".zlogin"] = "zsh", + [".zlogout"] = "zsh", + [".zshrc"] = "zsh", + [".zprofile"] = "zsh", + [".zcompdump"] = "zsh", + [".zshenv"] = "zsh", + [".zfbfmarks"] = "zsh", + [".alias"] = function() vim.fn["dist#ft#CSH"]() end, + [".bashrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + [".cshrc"] = function() vim.fn["dist#ft#CSH"]() end, + [".env"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + [".kshrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end, + [".login"] = function() vim.fn["dist#ft#CSH"]() end, + [".profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + [".tcshrc"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end, + ["/etc/profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + APKBUILD = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + PKGBUILD = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ["bash.bashrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + bashrc = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + crontab = starsetf('crontab'), + ["csh.cshrc"] = function() vim.fn["dist#ft#CSH"]() end, + ["csh.login"] = function() vim.fn["dist#ft#CSH"]() end, + ["csh.logout"] = function() vim.fn["dist#ft#CSH"]() end, + ["indent.pro"] = function() vim.fn["dist#ft#ProtoCheck"]('indent') end, + ["tcsh.login"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end, + ["tcsh.tcshrc"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end, + -- END FILENAME +} + +local pattern = { + -- BEGIN PATTERN + [".*/etc/a2ps/.*%.cfg"] = "a2ps", + [".*/etc/a2ps%.cfg"] = "a2ps", + [".*/usr/share/alsa/alsa%.conf"] = "alsaconf", + [".*/etc/asound%.conf"] = "alsaconf", + [".*/etc/apache2/sites%-.*/.*%.com"] = "apache", + [".*/etc/httpd/.*%.conf"] = "apache", + [".*/%.aptitude/config"] = "aptconf", + ["[mM]akefile%.am"] = "automake", + [".*bsd"] = "bsdl", + ["bzr_log%..*"] = "bzr", + [".*enlightenment/.*%.cfg"] = "c", + [".*/etc/defaults/cdrdao"] = "cdrdaoconf", + [".*/etc/cdrdao%.conf"] = "cdrdaoconf", + [".*/etc/default/cdrdao"] = "cdrdaoconf", + [".*hgrc"] = "cfg", + [".*%.%.ch"] = "chill", + [".*%.cmake%.in"] = "cmake", + [".*/debian/changelog"] = "debchangelog", + [".*/debian/control"] = "debcontrol", + [".*/debian/copyright"] = "debcopyright", + [".*/etc/apt/sources%.list%.d/.*%.list"] = "debsources", + [".*/etc/apt/sources%.list"] = "debsources", + ["dictd.*%.conf"] = "dictdconf", + [".*/etc/DIR_COLORS"] = "dircolors", + [".*/etc/dnsmasq%.conf"] = "dnsmasq", + ["php%.ini%-.*"] = "dosini", + [".*/etc/pacman%.conf"] = "dosini", + [".*/etc/yum%.conf"] = "dosini", + [".*lvs"] = "dracula", + [".*lpe"] = "dracula", + [".*esmtprc"] = "esmtprc", + [".*Eterm/.*%.cfg"] = "eterm", + [".*%.git/modules/.*/config"] = "gitconfig", + [".*%.git/config"] = "gitconfig", + [".*/etc/gitconfig"] = "gitconfig", + [".*/%.config/git/config"] = "gitconfig", + [".*%.git/config%.worktree"] = "gitconfig", + [".*%.git/worktrees/.*/config%.worktree"] = "gitconfig", + ["%.gitsendemail%.msg%......."] = "gitsendemail", + ["gkrellmrc_."] = "gkrellmrc", + [".*/usr/.*/gnupg/options%.skel"] = "gpg", + [".*/%.gnupg/options"] = "gpg", + [".*/%.gnupg/gpg%.conf"] = "gpg", + [".*/etc/group"] = "group", + [".*/etc/gshadow"] = "group", + [".*/etc/group%.edit"] = "group", + [".*/var/backups/gshadow%.bak"] = "group", + [".*/etc/group-"] = "group", + [".*/etc/gshadow-"] = "group", + [".*/var/backups/group%.bak"] = "group", + [".*/etc/gshadow%.edit"] = "group", + [".*/boot/grub/grub%.conf"] = "grub", + [".*/boot/grub/menu%.lst"] = "grub", + [".*/etc/grub%.conf"] = "grub", + ["hg%-editor%-.*%.txt"] = "hgcommit", + [".*/etc/host%.conf"] = "hostconf", + [".*/etc/hosts%.deny"] = "hostsaccess", + [".*/etc/hosts%.allow"] = "hostsaccess", + [".*%.html%.m4"] = "htmlm4", + [".*/%.i3/config"] = "i3config", + [".*/sway/config"] = "i3config", + [".*/i3/config"] = "i3config", + [".*/%.sway/config"] = "i3config", + [".*/%.icewm/menu"] = "icemenu", + [".*/etc/initng/.*/.*%.i"] = "initng", + [".*%.properties_.."] = "jproperties", + [".*%.properties_.._.."] = "jproperties", + [".*lftp/rc"] = "lftp", + [".*/%.libao"] = "libao", + [".*/etc/libao%.conf"] = "libao", + [".*/etc/.*limits%.conf"] = "limits", + [".*/etc/limits"] = "limits", + [".*/etc/.*limits%.d/.*%.conf"] = "limits", + [".*/LiteStep/.*/.*%.rc"] = "litestep", + [".*/etc/login%.access"] = "loginaccess", + [".*/etc/login%.defs"] = "logindefs", + [".*/etc/mail/aliases"] = "mailaliases", + [".*/etc/aliases"] = "mailaliases", + [".*[mM]akefile"] = "make", + [".*/etc/man%.conf"] = "manconf", + [".*/etc/modules%.conf"] = "modconf", + [".*/etc/conf%.modules"] = "modconf", + [".*/etc/modules"] = "modconf", + [".*%.[mi][3g]"] = "modula3", + [".*/%.mplayer/config"] = "mplayerconf", + ["rndc.*%.conf"] = "named", + ["rndc.*%.key"] = "named", + ["named.*%.conf"] = "named", + [".*/etc/nanorc"] = "nanorc", + [".*%.NS[ACGLMNPS]"] = "natural", + ["nginx.*%.conf"] = "nginx", + [".*/etc/nginx/.*"] = "nginx", + [".*nginx%.conf"] = "nginx", + [".*/nginx/.*%.conf"] = "nginx", + [".*/usr/local/nginx/conf/.*"] = "nginx", + [".*%.ml%.cppo"] = "ocaml", + [".*%.mli%.cppo"] = "ocaml", + [".*%.opam%.template"] = "opam", + [".*%.[Oo][Pp][Ll]"] = "opl", + [".*/etc/pam%.conf"] = "pamconf", + [".*/etc/passwd-"] = "passwd", + [".*/etc/shadow"] = "passwd", + [".*/etc/shadow%.edit"] = "passwd", + [".*/var/backups/shadow%.bak"] = "passwd", + [".*/var/backups/passwd%.bak"] = "passwd", + [".*/etc/passwd"] = "passwd", + [".*/etc/passwd%.edit"] = "passwd", + [".*/etc/shadow-"] = "passwd", + [".*/%.pinforc"] = "pinfo", + [".*/etc/pinforc"] = "pinfo", + [".*/etc/protocols"] = "protocols", + [".*baseq[2-3]/.*%.cfg"] = "quake", + [".*quake[1-3]/.*%.cfg"] = "quake", + [".*id1/.*%.cfg"] = "quake", + ["[rR]antfile"] = "ruby", + ["[rR]akefile"] = "ruby", + [".*/etc/sensors%.conf"] = "sensors", + [".*/etc/sensors3%.conf"] = "sensors", + [".*/etc/services"] = "services", + [".*/etc/serial%.conf"] = "setserial", + [".*/etc/udev/cdsymlinks%.conf"] = "sh", + [".*%._sst%.meta"] = "sisu", + [".*%.%-sst%.meta"] = "sisu", + [".*%.sst%.meta"] = "sisu", + [".*/etc/slp%.conf"] = "slpconf", + [".*/etc/slp%.reg"] = "slpreg", + [".*/etc/slp%.spi"] = "slpspi", + [".*/etc/ssh/ssh_config%.d/.*%.conf"] = "sshconfig", + [".*/%.ssh/config"] = "sshconfig", + [".*/etc/ssh/sshd_config%.d/.*%.conf"] = "sshdconfig", + [".*/etc/sudoers"] = "sudoers", + ["svn%-commit.*%.tmp"] = "svn", + [".*%.swift%.gyb"] = "swiftgyb", + [".*/etc/sysctl%.conf"] = "sysctl", + [".*/etc/sysctl%.d/.*%.conf"] = "sysctl", + [".*/etc/systemd/.*%.conf%.d/.*%.conf"] = "systemd", + [".*/%.config/systemd/user/.*%.d/.*%.conf"] = "systemd", + [".*/etc/systemd/system/.*%.d/.*%.conf"] = "systemd", + [".*%.t%.html"] = "tilde", + ["%.?tmux.*%.conf"] = "tmux", + ["%.?tmux.*%.conf.*"] = { "tmux", { priority = -1 } }, + [".*/%.cargo/config"] = "toml", + [".*/%.cargo/credentials"] = "toml", + [".*/etc/udev/udev%.conf"] = "udevconf", + [".*/etc/udev/permissions%.d/.*%.permissions"] = "udevperm", + [".*/etc/updatedb%.conf"] = "updatedb", + [".*/%.init/.*%.override"] = "upstart", + [".*/usr/share/upstart/.*%.conf"] = "upstart", + [".*/%.config/upstart/.*%.override"] = "upstart", + [".*/etc/init/.*%.conf"] = "upstart", + [".*/etc/init/.*%.override"] = "upstart", + [".*/%.config/upstart/.*%.conf"] = "upstart", + [".*/%.init/.*%.conf"] = "upstart", + [".*/usr/share/upstart/.*%.override"] = "upstart", + [".*%.ws[fc]"] = "wsh", + [".*/etc/xinetd%.conf"] = "xinetd", + [".*/etc/blkid%.tab"] = "xml", + [".*/etc/blkid%.tab%.old"] = "xml", + [".*%.vbproj%.user"] = "xml", + [".*%.fsproj%.user"] = "xml", + [".*%.csproj%.user"] = "xml", + [".*/etc/xdg/menus/.*%.menu"] = "xml", + [".*Xmodmap"] = "xmodmap", + [".*/etc/zprofile"] = "zsh", + ["%.bash[_-]aliases"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ["%.bash[_-]logout"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ["%.bash[_-]profile"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ["%.cshrc.*"] = function() vim.fn["dist#ft#CSH"]() end, + ["%.gtkrc.*"] = starsetf('gtkrc'), + ["%.kshrc.*"] = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end, + ["%.login.*"] = function() vim.fn["dist#ft#CSH"]() end, + ["%.neomuttrc.*"] = starsetf('neomuttrc'), + ["%.profile.*"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + ["%.reminders.*"] = starsetf('remind'), + ["%.tcshrc.*"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end, + ["%.zcompdump.*"] = starsetf('zsh'), + ["%.zlog.*"] = starsetf('zsh'), + ["%.zsh.*"] = starsetf('zsh'), + [".*%.[1-9]"] = function() vim.fn["dist#ft#FTnroff"]() end, + [".*%.[aA]"] = function() vim.fn["dist#ft#FTasm"]() end, + [".*%.[sS]"] = function() vim.fn["dist#ft#FTasm"]() end, + [".*%.properties_.._.._.*"] = starsetf('jproperties'), + [".*%.vhdl_[0-9].*"] = starsetf('vhdl'), + [".*/%.fvwm/.*"] = starsetf('fvwm'), + [".*/%.gitconfig%.d/.*"] = starsetf('gitconfig'), + [".*/%.neomutt/neomuttrc.*"] = starsetf('neomuttrc'), + [".*/Xresources/.*"] = starsetf('xdefaults'), + [".*/app%-defaults/.*"] = starsetf('xdefaults'), + [".*/bind/db%..*"] = starsetf('bindzone'), + [".*/debian/patches/.*"] = function() vim.fn["dist#ft#Dep3patch"]() end, + [".*/etc/Muttrc%.d/.*"] = starsetf('muttrc'), + [".*/etc/apache2/.*%.conf.*"] = starsetf('apache'), + [".*/etc/apache2/conf%..*/.*"] = starsetf('apache'), + [".*/etc/apache2/mods%-.*/.*"] = starsetf('apache'), + [".*/etc/apache2/sites%-.*/.*"] = starsetf('apache'), + [".*/etc/cron%.d/.*"] = starsetf('crontab'), + [".*/etc/dnsmasq%.d/.*"] = starsetf('dnsmasq'), + [".*/etc/httpd/conf%..*/.*"] = starsetf('apache'), + [".*/etc/httpd/conf%.d/.*%.conf.*"] = starsetf('apache'), + [".*/etc/httpd/mods%-.*/.*"] = starsetf('apache'), + [".*/etc/httpd/sites%-.*/.*"] = starsetf('apache'), + [".*/etc/logcheck/.*%.d.*/.*"] = starsetf('logcheck'), + [".*/etc/modprobe%..*"] = starsetf('modconf'), + [".*/etc/pam%.d/.*"] = starsetf('pamconf'), + [".*/etc/profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end, + [".*/etc/proftpd/.*%.conf.*"] = starsetf('apachestyle'), + [".*/etc/proftpd/conf%..*/.*"] = starsetf('apachestyle'), + [".*/etc/sudoers%.d/.*"] = starsetf('sudoers'), + [".*/etc/xinetd%.d/.*"] = starsetf('xinetd'), + [".*/etc/yum%.repos%.d/.*"] = starsetf('dosini'), + [".*/gitolite%-admin/conf/.*"] = starsetf('gitolite'), + [".*/named/db%..*"] = starsetf('bindzone'), + [".*/tmp/lltmp.*"] = starsetf('gedcom'), + [".*asterisk.*/.*voicemail%.conf.*"] = starsetf('asteriskvm'), + [".*asterisk/.*%.conf.*"] = starsetf('asterisk'), + [".*vimrc.*"] = starsetf('vim'), + [".*xmodmap.*"] = starsetf('xmodmap'), + ["/etc/gitconfig%.d/.*"] = starsetf('gitconfig'), + ["/etc/hostname%..*"] = starsetf('config'), + ["Containerfile%..*"] = starsetf('dockerfile'), + ["Dockerfile%..*"] = starsetf('dockerfile'), + ["JAM.*%..*"] = starsetf('jam'), + ["Kconfig%..*"] = starsetf('kconfig'), + ["Neomuttrc.*"] = starsetf('neomuttrc'), + ["Prl.*%..*"] = starsetf('jam'), + ["Xresources.*"] = starsetf('xdefaults'), + ["[mM]akefile.*"] = starsetf('make'), + ["[rR]akefile.*"] = starsetf('ruby'), + ["access%.conf.*"] = starsetf('apache'), + ["apache%.conf.*"] = starsetf('apache'), + ["apache2%.conf.*"] = starsetf('apache'), + ["bash%-fc[-%.]"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, + ["cabal%.project%..*"] = starsetf('cabalproject'), + ["crontab%..*"] = starsetf('crontab'), + ["drac%..*"] = starsetf('dracula'), + ["gtkrc.*"] = starsetf('gtkrc'), + ["httpd%.conf.*"] = starsetf('apache'), + ["lilo%.conf.*"] = starsetf('lilo'), + ["neomuttrc.*"] = starsetf('neomuttrc'), + ["proftpd%.conf.*"] = starsetf('apachestyle'), + ["reportbug%-.*"] = starsetf('mail'), + ["sgml%.catalog.*"] = starsetf('catalog'), + ["srm%.conf.*"] = starsetf('apache'), + ["tmac%..*"] = starsetf('nroff'), + ["zlog.*"] = starsetf('zsh'), + ["zsh.*"] = starsetf('zsh'), + ["ae%d+%.txt"] = 'mail', + ["[a-zA-Z0-9].*Dict"] = function() vim.fn["dist#ft#FTfoam"]() end, + ["[a-zA-Z0-9].*Dict%..*"] = function() vim.fn["dist#ft#FTfoam"]() end, + ["[a-zA-Z].*Properties"] = function() vim.fn["dist#ft#FTfoam"]() end, + ["[a-zA-Z].*Properties%..*"] = function() vim.fn["dist#ft#FTfoam"]() end, + [".*Transport%..*"] = function() vim.fn["dist#ft#FTfoam"]() end, + [".*/constant/g"] = function() vim.fn["dist#ft#FTfoam"]() end, + [".*/0/.*"] = function() vim.fn["dist#ft#FTfoam"]() end, + [".*/0%.orig/.*"] = function() vim.fn["dist#ft#FTfoam"]() end, + [".*/etc/sensors%.d/[^.].*"] = starsetf('sensors'), + [".*%.git/.*"] = function(path, bufnr) + local firstline = getline(bufnr, 1) + if firstline:find("^" .. string.rep("%x", 40) .. "+ ") or firstline:sub(1, 5) == "ref: " then + return "git" + end + end, + -- END PATTERN +} +-- luacheck: pop + +---@private +local function sort_by_priority(t) + local sorted = {} + for k, v in pairs(t) do + local ft = type(v) == "table" and v[1] or v + assert(type(ft) == "string" or type(ft) == "function", "Expected string or function for filetype") + + local opts = (type(v) == "table" and type(v[2]) == "table") and v[2] or {} + if not opts.priority then + opts.priority = 0 + end + table.insert(sorted, { [k] = { ft, opts } }) + end + table.sort(sorted, function(a, b) + return a[next(a)][2].priority > b[next(b)][2].priority + end) + return sorted +end + +local pattern_sorted = sort_by_priority(pattern) + +---@private +local function normalize_path(path) + return (path:gsub("\\", "/"):gsub("^~", vim.env.HOME)) +end + +--- Add new filetype mappings. +--- +--- Filetype mappings can be added either by extension or by filename (either +--- the "tail" or the full file path). The full file path is checked first, +--- followed by the file name. If a match is not found using the filename, then +--- the filename is matched against the list of patterns (sorted by priority) +--- until a match is found. Lastly, if pattern matching does not find a +--- filetype, then the file extension is used. +--- +--- The filetype can be either a string (in which case it is used as the +--- filetype directly) or a function. If a function, it takes the full path and +--- buffer number of the file as arguments (along with captures from the matched +--- pattern, if any) and should return a string that will be used as the +--- buffer's filetype. +--- +--- Filename patterns can specify an optional priority to resolve cases when a +--- file path matches multiple patterns. Higher priorities are matched first. +--- When omitted, the priority defaults to 0. +--- +--- See $VIMRUNTIME/lua/vim/filetype.lua for more examples. +--- +--- Note that Lua filetype detection is only enabled when |g:do_filetype_lua| is +--- set to 1. +--- +--- Example: +--- <pre> +--- vim.filetype.add({ +--- extension = { +--- foo = "fooscript", +--- bar = function(path, bufnr) +--- if some_condition() then +--- return "barscript" +--- end +--- return "bar" +--- end, +--- }, +--- filename = { +--- [".foorc"] = "toml", +--- ["/etc/foo/config"] = "toml", +--- }, +--- pattern = { +--- [".*/etc/foo/.*"] = "fooscript", +--- -- Using an optional priority +--- [".*/etc/foo/.*%.conf"] = { "dosini", { priority = 10 } }, +--- ["README.(%a+)$"] = function(path, bufnr, ext) +--- if ext == "md" then +--- return "markdown" +--- elseif ext == "rst" then +--- return "rst" +--- end +--- end, +--- }, +--- }) +--- </pre> +--- +---@param filetypes table A table containing new filetype maps (see example). +function M.add(filetypes) + for k, v in pairs(filetypes.extension or {}) do + extension[k] = v + end + + for k, v in pairs(filetypes.filename or {}) do + filename[normalize_path(k)] = v + end + + for k, v in pairs(filetypes.pattern or {}) do + pattern[normalize_path(k)] = v + end + + if filetypes.pattern then + pattern_sorted = sort_by_priority(pattern) + end +end + +---@private +local function dispatch(ft, path, bufnr, ...) + if type(ft) == "function" then + ft = ft(path, bufnr, ...) + end + + if type(ft) == "string" then + api.nvim_buf_set_option(bufnr, "filetype", ft) + return true + end + + -- Any non-falsey value (that is, anything other than 'nil' or 'false') will + -- end filetype matching. This is useful for e.g. the dist#ft functions that + -- return 0, but set the buffer's filetype themselves + return ft +end + +---@private +local function match_pattern(name, path, tail, pat) + -- If the pattern contains a / match against the full path, otherwise just the tail + local fullpat = "^" .. pat .. "$" + local matches + if pat:find("/") then + -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against + -- both the short file name (as typed) and the full file name (after expanding to full path + -- and resolving symlinks) + matches = name:match(fullpat) or path:match(fullpat) + else + matches = tail:match(fullpat) + end + return matches +end + +--- Set the filetype for the given buffer from a file name. +--- +---@param name string File name (can be an absolute or relative path) +---@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer. +function M.match(name, bufnr) + -- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use + -- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers + -- wish to perform filetype detection on buffers other than the current one. + bufnr = bufnr or api.nvim_get_current_buf() + + name = normalize_path(name) + + -- First check for the simple case where the full path exists as a key + local path = vim.fn.resolve(vim.fn.fnamemodify(name, ":p")) + if dispatch(filename[path], path, bufnr) then + return + end + + -- Next check against just the file name + local tail = vim.fn.fnamemodify(name, ":t") + if dispatch(filename[tail], path, bufnr) then + return + end + + -- Next, check the file path against available patterns with non-negative priority + local j = 1 + for i, v in ipairs(pattern_sorted) do + local k = next(v) + local opts = v[k][2] + if opts.priority < 0 then + j = i + break + end + + local ft = v[k][1] + local matches = match_pattern(name, path, tail, k) + if matches then + if dispatch(ft, path, bufnr, matches) then + return + end + end + end + + -- Next, check file extension + local ext = vim.fn.fnamemodify(name, ":e") + if dispatch(extension[ext], path, bufnr) then + return + end + + -- Finally, check patterns with negative priority + for i = j, #pattern_sorted do + local v = pattern_sorted[i] + local k = next(v) + + local ft = v[k][1] + local matches = match_pattern(name, path, tail, k) + if matches then + if dispatch(ft, path, bufnr, matches) then + return + end + end + end +end + +return M diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index 236f3165f2..12faa0a6e1 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -25,16 +25,29 @@ end ---@param higroup highlight group to use for highlighting ---@param rtype type of range (:help setreg, default charwise) ---@param inclusive boolean indicating whether the range is end-inclusive (default false) -function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive) +---@param priority number indicating priority of highlight (default 50) +function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive, priority) rtype = rtype or 'v' inclusive = inclusive or false + priority = priority or 50 -- sanity check if start[2] < 0 or finish[1] < start[1] then return end local region = vim.region(bufnr, start, finish, rtype, inclusive) for linenr, cols in pairs(region) do - api.nvim_buf_add_highlight(bufnr, ns, higroup, linenr, cols[1], cols[2]) + local end_row + if cols[2] == -1 then + end_row = linenr + 1 + cols[2] = 0 + end + api.nvim_buf_set_extmark(bufnr, ns, linenr, cols[1], { + hl_group = higroup, + end_row = end_row, + end_col = cols[2], + priority = priority, + strict = false + }) end end @@ -82,7 +95,7 @@ function highlight.on_yank(opts) pos1 = {pos1[2] - 1, pos1[3] - 1 + pos1[4]} pos2 = {pos2[2] - 1, pos2[3] - 1 + pos2[4]} - highlight.range(bufnr, yank_ns, higroup, pos1, pos2, event.regtype, event.inclusive) + highlight.range(bufnr, yank_ns, higroup, pos1, pos2, event.regtype, event.inclusive, 200) vim.defer_fn( function() diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua new file mode 100644 index 0000000000..d53b790746 --- /dev/null +++ b/runtime/lua/vim/keymap.lua @@ -0,0 +1,135 @@ +local keymap = {} + +--- Add a new |mapping|. +--- Examples: +--- <pre> +--- -- Can add mapping to Lua functions +--- vim.keymap.set('n', 'lhs', function() print("real lua function") end) +--- +--- -- Can use it to map multiple modes +--- vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true }) +--- +--- -- Can add mapping for specific buffer +--- vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 }) +--- +--- -- Expr mappings +--- vim.keymap.set('i', '<Tab>', function() +--- return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>" +--- end, { expr = true }) +--- -- <Plug> mappings +--- vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)') +--- </pre> +--- +--- Note that in a mapping like: +--- <pre> +--- vim.keymap.set('n', 'asdf', require('jkl').my_fun) +--- </pre> +--- +--- the require('jkl') gets evaluated during this call in order to access the function. If you want to +--- avoid this cost at startup you can wrap it in a function, for example: +--- <pre> +--- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end) +--- </pre> +--- +---@param mode string|table Same mode short names as |nvim_set_keymap()|. +--- Can also be list of modes to create mapping on multiple modes. +---@param lhs string Left-hand side |{lhs}| of the mapping. +---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function. +-- +---@param opts table A table of |:map-arguments| such as "silent". In addition to the options +--- listed in |nvim_set_keymap()|, this table also accepts the following keys: +--- - replace_keycodes: (boolean, default true) When both this and expr is "true", +--- |nvim_replace_termcodes()| is applied to the result of Lua expr maps. +--- - remap: (boolean) Make the mapping recursive. This is the +--- inverse of the "noremap" option from |nvim_set_keymap()|. +--- Default `true` if `lhs` is a string starting with `<plug>` (case-insensitive), `false` otherwise. +---@see |nvim_set_keymap()| +function keymap.set(mode, lhs, rhs, opts) + vim.validate { + mode = {mode, {'s', 't'}}, + lhs = {lhs, 's'}, + rhs = {rhs, {'s', 'f'}}, + opts = {opts, 't', true} + } + + opts = vim.deepcopy(opts) or {} + local is_rhs_luaref = type(rhs) == "function" + mode = type(mode) == 'string' and {mode} or mode + + if is_rhs_luaref and opts.expr and opts.replace_keycodes ~= false then + local user_rhs = rhs + rhs = function () + return vim.api.nvim_replace_termcodes(user_rhs(), true, true, true) + end + end + -- clear replace_keycodes from opts table + opts.replace_keycodes = nil + + if opts.remap == nil then + -- remap by default on <plug> mappings and don't otherwise. + opts.noremap = is_rhs_luaref or rhs:lower():match("^<plug>") == nil + else + -- remaps behavior is opposite of noremap option. + opts.noremap = not opts.remap + opts.remap = nil + end + + if is_rhs_luaref then + opts.callback = rhs + rhs = '' + end + + if opts.buffer then + local bufnr = opts.buffer == true and 0 or opts.buffer + opts.buffer = nil + for _, m in ipairs(mode) do + vim.api.nvim_buf_set_keymap(bufnr, m, lhs, rhs, opts) + end + else + opts.buffer = nil + for _, m in ipairs(mode) do + vim.api.nvim_set_keymap(m, lhs, rhs, opts) + end + end +end + +--- Remove an existing mapping. +--- Examples: +--- <pre> +--- vim.keymap.del('n', 'lhs') +--- +--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 }) +--- </pre> +---@param opts table A table of optional arguments: +--- - buffer: (number or boolean) Remove a mapping from the given buffer. +--- When "true" or 0, use the current buffer. +---@see |vim.keymap.set()| +--- +function keymap.del(modes, lhs, opts) + vim.validate { + mode = {modes, {'s', 't'}}, + lhs = {lhs, 's'}, + opts = {opts, 't', true} + } + + opts = opts or {} + modes = type(modes) == 'string' and {modes} or modes + + local buffer = false + if opts.buffer ~= nil then + buffer = opts.buffer == true and 0 or opts.buffer + opts.buffer = nil + end + + if buffer == false then + for _, mode in ipairs(modes) do + vim.api.nvim_del_keymap(mode, lhs) + end + else + for _, mode in ipairs(modes) do + vim.api.nvim_buf_del_keymap(buffer, mode, lhs) + end + end +end + +return keymap diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 72a84dcc53..37e222a5ce 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -256,7 +256,7 @@ local function validate_client_config(config) (not config.flags or not config.flags.debounce_text_changes or type(config.flags.debounce_text_changes) == 'number'), - "flags.debounce_text_changes must be nil or a number with the debounce time in milliseconds" + "flags.debounce_text_changes must be a number with the debounce time in milliseconds" ) local cmd, cmd_args = lsp._cmd_parts(config.cmd) @@ -290,7 +290,7 @@ end --- Memoizes a function. On first run, the function return value is saved and --- immediately returned on subsequent runs. If the function returns a multival, --- only the first returned value will be memoized and returned. The function will only be run once, ---- even if it has side-effects. +--- even if it has side effects. --- ---@param fn (function) Function to run ---@returns (function) Memoized function @@ -306,70 +306,138 @@ local function once(fn) end end - local changetracking = {} do --@private --- client_id → state --- --- state + --- use_incremental_sync: bool + --- buffers: bufnr -> buffer_state + --- + --- buffer_state --- pending_change?: function that the timer starts to trigger didChange --- pending_changes: table (uri -> list of pending changeset tables)); - -- Only set if incremental_sync is used - --- use_incremental_sync: bool - --- buffers?: table (bufnr → lines); for incremental sync only + --- Only set if incremental_sync is used + --- --- timer?: uv_timer + --- lines: table local state_by_client = {} ---@private function changetracking.init(client, bufnr) + local use_incremental_sync = ( + if_nil(client.config.flags.allow_incremental_sync, true) + and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental + ) local state = state_by_client[client.id] if not state then state = { - pending_changes = {}; - use_incremental_sync = ( - if_nil(client.config.flags.allow_incremental_sync, true) - and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental - ); + buffers = {}; + debounce = client.config.flags.debounce_text_changes or 150, + use_incremental_sync = use_incremental_sync; } state_by_client[client.id] = state end - if not state.use_incremental_sync then - return - end - if not state.buffers then - state.buffers = {} + if not state.buffers[bufnr] then + local buf_state = {} + state.buffers[bufnr] = buf_state + if use_incremental_sync then + buf_state.lines = nvim_buf_get_lines(bufnr, 0, -1, true) + buf_state.lines_tmp = {} + buf_state.pending_changes = {} + end end - state.buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true) end ---@private function changetracking.reset_buf(client, bufnr) - changetracking.flush(client) + changetracking.flush(client, bufnr) local state = state_by_client[client.id] if state and state.buffers then + local buf_state = state.buffers[bufnr] state.buffers[bufnr] = nil + if buf_state and buf_state.timer then + buf_state.timer:stop() + buf_state.timer:close() + buf_state.timer = nil + end end end ---@private function changetracking.reset(client_id) local state = state_by_client[client_id] - if state then - state_by_client[client_id] = nil - changetracking._reset_timer(state) + if not state then + return end + for _, buf_state in pairs(state.buffers) do + if buf_state.timer then + buf_state.timer:stop() + buf_state.timer:close() + buf_state.timer = nil + end + end + state.buffers = {} + end + + ---@private + -- + -- Adjust debounce time by taking time of last didChange notification into + -- consideration. If the last didChange happened more than `debounce` time ago, + -- debounce can be skipped and otherwise maybe reduced. + -- + -- This turns the debounce into a kind of client rate limiting + local function next_debounce(debounce, buf_state) + if debounce == 0 then + return 0 + end + local ns_to_ms = 0.000001 + if not buf_state.last_flush then + return debounce + end + local now = uv.hrtime() + local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms + return math.max(debounce - ms_since_last_flush, 0) end ---@private function changetracking.prepare(bufnr, firstline, lastline, new_lastline) - local incremental_changes = function(client) - local cached_buffers = state_by_client[client.id].buffers - local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true) + local incremental_changes = function(client, buf_state) + + local prev_lines = buf_state.lines + local curr_lines = buf_state.lines_tmp + + local changed_lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true) + for i = 1, firstline do + curr_lines[i] = prev_lines[i] + end + for i = firstline + 1, new_lastline do + curr_lines[i] = changed_lines[i - firstline] + end + for i = lastline + 1, #prev_lines do + curr_lines[i - lastline + new_lastline] = prev_lines[i] + end + if tbl_isempty(curr_lines) then + -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259. + curr_lines[1] = '' + end + local line_ending = buf_get_line_ending(bufnr) local incremental_change = sync.compute_diff( - cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending) - cached_buffers[bufnr] = curr_lines + buf_state.lines, curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending) + + -- Double-buffering of lines tables is used to reduce the load on the garbage collector. + -- At this point the prev_lines table is useless, but its internal storage has already been allocated, + -- so let's keep it around for the next didChange event, in which it will become the next + -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the + -- internal storage - it merely marks them as free, for the GC to deallocate them. + for i in ipairs(prev_lines) do + prev_lines[i] = nil + end + buf_state.lines = curr_lines + buf_state.lines_tmp = prev_lines + return incremental_change end local full_changes = once(function() @@ -383,75 +451,68 @@ do return end local state = state_by_client[client.id] - local debounce = client.config.flags.debounce_text_changes - if not debounce then - local changes = state.use_incremental_sync and incremental_changes(client) or full_changes() - client.notify("textDocument/didChange", { - textDocument = { - uri = uri; - version = util.buf_versions[bufnr]; - }; - contentChanges = { changes, } - }) - return - end - changetracking._reset_timer(state) + local buf_state = state.buffers[bufnr] + changetracking._reset_timer(buf_state) + local debounce = next_debounce(state.debounce, buf_state) if state.use_incremental_sync then -- This must be done immediately and cannot be delayed -- The contents would further change and startline/endline may no longer fit - if not state.pending_changes[uri] then - state.pending_changes[uri] = {} - end - table.insert(state.pending_changes[uri], incremental_changes(client)) + table.insert(buf_state.pending_changes, incremental_changes(client, buf_state)) end - state.pending_change = function() - state.pending_change = nil + buf_state.pending_change = function() + buf_state.pending_change = nil + buf_state.last_flush = uv.hrtime() if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then return end - if state.use_incremental_sync then - for change_uri, content_changes in pairs(state.pending_changes) do - client.notify("textDocument/didChange", { - textDocument = { - uri = change_uri; - version = util.buf_versions[vim.uri_to_bufnr(change_uri)]; - }; - contentChanges = content_changes, - }) - end - state.pending_changes = {} - else - client.notify("textDocument/didChange", { - textDocument = { - uri = uri; - version = util.buf_versions[bufnr]; - }; - contentChanges = { full_changes() }, - }) - end + local changes = state.use_incremental_sync and buf_state.pending_changes or { full_changes() } + client.notify("textDocument/didChange", { + textDocument = { + uri = uri, + version = util.buf_versions[bufnr], + }, + contentChanges = changes, + }) + buf_state.pending_changes = {} + end + if debounce == 0 then + buf_state.pending_change() + else + local timer = vim.loop.new_timer() + buf_state.timer = timer + -- Must use schedule_wrap because `full_changes()` calls nvim_buf_get_lines + timer:start(debounce, 0, vim.schedule_wrap(buf_state.pending_change)) end - state.timer = vim.loop.new_timer() - -- Must use schedule_wrap because `full_changes()` calls nvim_buf_get_lines - state.timer:start(debounce, 0, vim.schedule_wrap(state.pending_change)) end end - function changetracking._reset_timer(state) - if state.timer then - state.timer:stop() - state.timer:close() - state.timer = nil + function changetracking._reset_timer(buf_state) + if buf_state.timer then + buf_state.timer:stop() + buf_state.timer:close() + buf_state.timer = nil end end --- Flushes any outstanding change notification. ---@private - function changetracking.flush(client) + function changetracking.flush(client, bufnr) local state = state_by_client[client.id] - if state then - changetracking._reset_timer(state) - if state.pending_change then - state.pending_change() + if not state then + return + end + if bufnr then + local buf_state = state.buffers[bufnr] or {} + changetracking._reset_timer(buf_state) + if buf_state.pending_change then + buf_state.pending_change() + end + else + for _, buf_state in pairs(state.buffers) do + changetracking._reset_timer(buf_state) + if buf_state.pending_change then + buf_state.pending_change() + end end end end @@ -645,8 +706,8 @@ end ---@param on_error Callback with parameters (code, ...), invoked --- when the client operation throws an error. `code` is a number describing --- the error. Other arguments may be passed depending on the error kind. See ---- |vim.lsp.client_errors| for possible errors. ---- Use `vim.lsp.client_errors[code]` to get human-friendly name. +--- |vim.lsp.rpc.client_errors| for possible errors. +--- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name. --- ---@param before_init Callback with parameters (initialize_params, config) --- invoked before the LSP "initialize" phase, where `params` contains the @@ -757,8 +818,8 @@ function lsp.start_client(config) --- ---@param code (number) Error code ---@param err (...) Other arguments may be passed depending on the error kind - ---@see |vim.lsp.client_errors| for possible errors. Use - ---`vim.lsp.client_errors[code]` to get a human-friendly name. + ---@see |vim.lsp.rpc.client_errors| for possible errors. Use + ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name. function dispatch.on_error(code, err) local _ = log.error() and log.error(log_prefix, "on_error", { code = lsp.client_errors[code], err = err }) err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) @@ -777,6 +838,10 @@ function lsp.start_client(config) ---@param code (number) exit code of the process ---@param signal (number) the signal used to terminate (if any) function dispatch.on_exit(code, signal) + if config.on_exit then + pcall(config.on_exit, code, signal, client_id) + end + active_clients[client_id] = nil uninitialized_clients[client_id] = nil @@ -792,10 +857,6 @@ function lsp.start_client(config) vim.notify(msg, vim.log.levels.WARN) end) end - - if config.on_exit then - pcall(config.on_exit, code, signal, client_id) - end end -- Start the RPC client. @@ -897,7 +958,7 @@ function lsp.start_client(config) client.initialized = true uninitialized_clients[client_id] = nil client.workspace_folders = workspace_folders - -- TODO(mjlbach): Backwards compatbility, to be removed in 0.7 + -- TODO(mjlbach): Backwards compatibility, to be removed in 0.7 client.workspaceFolders = client.workspace_folders client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities") -- These are the cleaned up capabilities we use for dynamically deciding @@ -957,7 +1018,7 @@ function lsp.start_client(config) or error(string.format("not found: %q request handler for client %q.", method, client.name)) end -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state - changetracking.flush(client) + changetracking.flush(client, bufnr) bufnr = resolve_bufnr(bufnr) local _ = log.debug() and log.debug(log_prefix, "client.request", client_id, method, params, handler, bufnr) local success, request_id = rpc.request(method, params, function(err, result) @@ -1014,14 +1075,16 @@ function lsp.start_client(config) ---@private --- Sends a notification to an LSP server. --- - ---@param method (string) LSP method name. - ---@param params (optional, table) LSP request params. - ---@param bufnr (number) Buffer handle, or 0 for current. + ---@param method string LSP method name. + ---@param params table|nil LSP request params. ---@returns {status} (bool) true if the notification was successful. ---If it is false, then it will always be false ---(the client has shutdown). - function client.notify(...) - return rpc.notify(...) + function client.notify(method, params) + if method ~= 'textDocument/didChange' then + changetracking.flush(client) + end + return rpc.notify(method, params) end ---@private @@ -1112,9 +1175,9 @@ local text_document_did_change_handler do text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline) - -- Don't do anything if there are no clients attached. + -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then - return + return true end util.buf_versions[bufnr] = changedtick local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline) @@ -1131,7 +1194,7 @@ function lsp._text_document_did_save_handler(bufnr) if client.resolved_capabilities.text_document_save then local included_text if client.resolved_capabilities.text_document_save_include_text then - included_text = text() + included_text = text(bufnr) end client.notify('textDocument/didSave', { textDocument = { @@ -1156,6 +1219,12 @@ function lsp.buf_attach_client(bufnr, client_id) client_id = {client_id, 'n'}; } bufnr = resolve_bufnr(bufnr) + if not vim.api.nvim_buf_is_loaded(bufnr) then + local _ = log.warn() and log.warn( + string.format("buf_attach_client called on unloaded buffer (id: %d): ", bufnr) + ) + return false + end local buffer_client_ids = all_buffer_active_clients[bufnr] -- This is our first time attaching to this buffer. if not buffer_client_ids then @@ -1214,6 +1283,50 @@ function lsp.buf_attach_client(bufnr, client_id) return true end +--- Detaches client from the specified buffer. +--- Note: While the server is notified that the text document (buffer) +--- was closed, it is still able to send notifications should it ignore this notification. +--- +---@param bufnr number Buffer handle, or 0 for current +---@param client_id number Client id +function lsp.buf_detach_client(bufnr, client_id) + validate { + bufnr = {bufnr, 'n', true}; + client_id = {client_id, 'n'}; + } + bufnr = resolve_bufnr(bufnr) + + local client = lsp.get_client_by_id(client_id) + if not client or not client.attached_buffers[bufnr] then + vim.notify( + string.format('Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', client_id, bufnr) + ) + return + end + + changetracking.reset_buf(client, bufnr) + + if client.resolved_capabilities.text_document_open_close then + local uri = vim.uri_from_bufnr(bufnr) + local params = { textDocument = { uri = uri; } } + client.notify('textDocument/didClose', params) + end + + client.attached_buffers[bufnr] = nil + util.buf_versions[bufnr] = nil + + all_buffer_active_clients[bufnr][client_id] = nil + if #vim.tbl_keys(all_buffer_active_clients[bufnr]) == 0 then + all_buffer_active_clients[bufnr] = nil + end + + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace, bufnr) + + vim.notify(string.format('Detached buffer (id: %d) from client (id: %d)', bufnr, client_id)) + +end + --- Checks if a buffer is attached for a particular client. --- ---@param bufnr (number) Buffer handle, or 0 for current @@ -1658,14 +1771,14 @@ end -- -- Can be used to lookup the number from the name or the -- name from the number. --- Levels by name: "trace", "debug", "info", "warn", "error" --- Level numbers begin with "trace" at 0 +-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR" +-- Level numbers begin with "TRACE" at 0 lsp.log_levels = log.levels --- Sets the global log level for LSP logging. --- ---- Levels by name: "trace", "debug", "info", "warn", "error" ---- Level numbers begin with "trace" at 0 +--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR" +--- Level numbers begin with "TRACE" at 0 --- --- Use `lsp.log_levels` for reverse lookup. --- diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 8e3ed9b002..eb7ec579f1 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -184,7 +184,7 @@ function M.formatting_sync(options, timeout_ms) local result, err = client.request_sync('textDocument/formatting', params, timeout_ms, bufnr) if result and result.result then - util.apply_text_edits(result.result, bufnr) + util.apply_text_edits(result.result, bufnr, client.offset_encoding) elseif err then vim.notify('vim.lsp.buf.formatting_sync: ' .. err, vim.log.levels.WARN) end @@ -228,7 +228,7 @@ function M.formatting_seq_sync(options, timeout_ms, order) local params = util.make_formatting_params(options) local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, vim.api.nvim_get_current_buf()) if result and result.result then - util.apply_text_edits(result.result, bufnr) + util.apply_text_edits(result.result, bufnr, client.offset_encoding) elseif err then vim.notify(string.format("vim.lsp.buf.formatting_seq_sync: (%s) %s", client.name, err), vim.log.levels.WARN) end @@ -447,13 +447,16 @@ end ---@param query (string, optional) function M.workspace_symbol(query) query = query or npcall(vfn.input, "Query: ") + if query == nil then + return + end local params = {query = query} request('workspace/symbol', params) end --- Send request to the server to resolve document highlights for the current --- text document position. This request can be triggered by a key mapping or ---- by events such as `CursorHold`, eg: +--- by events such as `CursorHold`, e.g.: --- --- <pre> --- autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight() @@ -503,7 +506,7 @@ local function on_code_action_results(results, ctx) ---@private local function apply_action(action, client) if action.edit then - util.apply_workspace_edit(action.edit) + util.apply_workspace_edit(action.edit, client.offset_encoding) end if action.command then local command = type(action.command) == 'table' and action.command or action @@ -627,14 +630,19 @@ end --- Executes an LSP server command. --- ----@param command A valid `ExecuteCommandParams` object +---@param command_params table A valid `ExecuteCommandParams` object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand -function M.execute_command(command) +function M.execute_command(command_params) validate { - command = { command.command, 's' }, - arguments = { command.arguments, 't', true } + command = { command_params.command, 's' }, + arguments = { command_params.arguments, 't', true } + } + command_params = { + command=command_params.command, + arguments=command_params.arguments, + workDoneToken=command_params.workDoneToken, } - request('workspace/executeCommand', command) + request('workspace/executeCommand', command_params ) end return M diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 8850d25233..68942ae11a 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -168,8 +168,8 @@ end --- }, --- -- Use a function to dynamically turn signs off --- -- and on, using buffer local variables ---- signs = function(bufnr, client_id) ---- return vim.bo[bufnr].show_signs == false +--- signs = function(namespace, bufnr) +--- return vim.b[bufnr].show_signs == true --- end, --- -- Disable a feature --- update_in_insert = false, @@ -243,7 +243,7 @@ end ---@param client_id number ---@private function M.save(diagnostics, bufnr, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.save is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.save is deprecated. See :h deprecated', vim.log.levels.WARN) local namespace = M.get_namespace(client_id) vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) end @@ -257,7 +257,7 @@ end --- If nil, diagnostics of all clients are included. ---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[]) function M.get_all(client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', vim.log.levels.WARN) local result = {} local namespace if client_id then @@ -279,7 +279,7 @@ end --- Else, return just the diagnostics associated with the client_id. ---@param predicate function|nil Optional function for filtering diagnostics function M.get(bufnr, client_id, predicate) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get is deprecated. See :h deprecated', vim.log.levels.WARN) predicate = predicate or function() return true end if client_id == nil then local all_diagnostics = {} @@ -341,7 +341,7 @@ end ---@param severity DiagnosticSeverity ---@param client_id number the client id function M.get_count(bufnr, severity, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', vim.log.levels.WARN) severity = severity_lsp_to_vim(severity) local opts = { severity = severity } if client_id ~= nil then @@ -358,7 +358,7 @@ end ---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Previous diagnostic function M.get_prev(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -376,7 +376,7 @@ end ---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Previous diagnostic position function M.get_prev_pos(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -393,7 +393,7 @@ end --- ---@param opts table See |vim.lsp.diagnostic.goto_next()| function M.goto_prev(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -411,7 +411,7 @@ end ---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Next diagnostic function M.get_next(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -429,7 +429,7 @@ end ---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Next diagnostic position function M.get_next_pos(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -444,7 +444,7 @@ end --- ---@deprecated Prefer |vim.diagnostic.goto_next()| function M.goto_next(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', vim.log.levels.WARN) if opts then if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -468,7 +468,7 @@ end --- - severity_limit (DiagnosticSeverity): --- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid. function M.set_signs(diagnostics, bufnr, client_id, _, opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', vim.log.levels.WARN) local namespace = M.get_namespace(client_id) if opts and not opts.severity and opts.severity_limit then opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)} @@ -489,7 +489,7 @@ end --- - severity_limit (DiagnosticSeverity): --- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid. function M.set_underline(diagnostics, bufnr, client_id, _, opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', vim.log.levels.WARN) local namespace = M.get_namespace(client_id) if opts and not opts.severity and opts.severity_limit then opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)} @@ -511,7 +511,7 @@ end --- - severity_limit (DiagnosticSeverity): --- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid. function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', vim.log.levels.WARN) local namespace = M.get_namespace(client_id) if opts and not opts.severity and opts.severity_limit then opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)} @@ -530,7 +530,7 @@ end ---@return an array of [text, hl_group] arrays. This can be passed directly to --- the {virt_text} option of |nvim_buf_set_extmark()|. function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', vim.log.levels.WARN) return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts) end @@ -548,7 +548,7 @@ end ---@param position table|nil The (0,0)-indexed position ---@return table {popup_bufnr, win_id} function M.show_position_diagnostics(opts, buf_nr, position) - vim.api.nvim_echo({{'vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN) opts = opts or {} opts.scope = "cursor" opts.pos = position @@ -572,7 +572,7 @@ end ---@param client_id number|nil the client id ---@return table {popup_bufnr, win_id} function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN) opts = opts or {} opts.scope = "line" opts.pos = line_nr @@ -596,7 +596,7 @@ end --- client. The default is to redraw diagnostics for all attached --- clients. function M.redraw(bufnr, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', vim.log.levels.WARN) bufnr = get_bufnr(bufnr) if not client_id then return vim.lsp.for_each_buffer_client(bufnr, function(client) @@ -624,7 +624,7 @@ end --- - {workspace}: (boolean, default true) --- - Set the list with workspace diagnostics function M.set_qflist(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', vim.log.levels.WARN) opts = opts or {} if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -656,7 +656,7 @@ end --- - {workspace}: (boolean, default false) --- - Set the list with workspace diagnostics function M.set_loclist(opts) - vim.api.nvim_echo({{'vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', vim.log.levels.WARN) opts = opts or {} if opts.severity then opts.severity = severity_lsp_to_vim(opts.severity) @@ -684,7 +684,7 @@ end -- send diagnostic information and the client will still process it. The -- diagnostics are simply not displayed to the user. function M.disable(bufnr, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.disable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.disable is deprecated. See :h deprecated', vim.log.levels.WARN) if not client_id then return vim.lsp.for_each_buffer_client(bufnr, function(client) M.disable(bufnr, client.id) @@ -705,7 +705,7 @@ end --- client. The default is to enable diagnostics for all attached --- clients. function M.enable(bufnr, client_id) - vim.api.nvim_echo({{'vim.lsp.diagnostic.enable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {}) + vim.notify_once('vim.lsp.diagnostic.enable is deprecated. See :h deprecated', vim.log.levels.WARN) if not client_id then return vim.lsp.for_each_buffer_client(bufnr, function(client) M.enable(bufnr, client.id) diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index c974d1a6b4..a997b887d9 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -111,13 +111,15 @@ M['client/registerCapability'] = function(_, _, ctx) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit -M['workspace/applyEdit'] = function(_, workspace_edit) +M['workspace/applyEdit'] = function(_, workspace_edit, ctx) if not workspace_edit then return end -- TODO(ashkan) Do something more with label? + local client_id = ctx.client_id + local client = vim.lsp.get_client_by_id(client_id) if workspace_edit.label then print("Workspace edit", workspace_edit.label) end - local status, result = pcall(util.apply_workspace_edit, workspace_edit.edit) + local status, result = pcall(util.apply_workspace_edit, workspace_edit.edit, client.offset_encoding) return { applied = status; failureReason = result; @@ -150,6 +152,17 @@ M['workspace/configuration'] = function(_, result, ctx) return response end +--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders +M['workspace/workspaceFolders'] = function(_, _, ctx) + local client_id = ctx.client_id + local client = vim.lsp.get_client_by_id(client_id) + if not client then + err_message("LSP[id=", client_id, "] client has shut down after sending the message") + return + end + return client.workspace_folders or vim.NIL +end + M['textDocument/publishDiagnostics'] = function(...) return require('vim.lsp.diagnostic').on_publish_diagnostics(...) end @@ -159,6 +172,31 @@ M['textDocument/codeLens'] = function(...) end +--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references +M['textDocument/references'] = function(_, result, ctx, config) + if not result or vim.tbl_isempty(result) then + vim.notify('No references found') + else + local client = vim.lsp.get_client_by_id(ctx.client_id) + config = config or {} + if config.loclist then + vim.fn.setloclist(0, {}, ' ', { + title = 'References'; + items = util.locations_to_items(result, client.offset_encoding); + context = ctx; + }) + api.nvim_command("lopen") + else + vim.fn.setqflist({}, ' ', { + title = 'References'; + items = util.locations_to_items(result, client.offset_encoding); + context = ctx; + }) + api.nvim_command("botright copen") + end + end +end + ---@private --- Return a function that converts LSP responses to list items and opens the list @@ -169,23 +207,26 @@ end --- loclist: (boolean) use the location list (default is to use the quickfix list) --- ---@param map_result function `((resp, bufnr) -> list)` to convert the response ----@param entity name of the resource used in a `not found` error message -local function response_to_list(map_result, entity) - return function(_,result, ctx, config) +---@param entity string name of the resource used in a `not found` error message +---@param title_fn function Function to call to generate list title +local function response_to_list(map_result, entity, title_fn) + return function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') else config = config or {} if config.loclist then vim.fn.setloclist(0, {}, ' ', { - title = 'Language Server'; + title = title_fn(ctx); items = map_result(result, ctx.bufnr); + context = ctx; }) api.nvim_command("lopen") else vim.fn.setqflist({}, ' ', { - title = 'Language Server'; + title = title_fn(ctx); items = map_result(result, ctx.bufnr); + context = ctx; }) api.nvim_command("botright copen") end @@ -194,31 +235,36 @@ local function response_to_list(map_result, entity) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references -M['textDocument/references'] = response_to_list(util.locations_to_items, 'references') - --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol -M['textDocument/documentSymbol'] = response_to_list(util.symbols_to_items, 'document symbols') +M['textDocument/documentSymbol'] = response_to_list(util.symbols_to_items, 'document symbols', function(ctx) + local fname = vim.fn.fnamemodify(vim.uri_to_fname(ctx.params.textDocument.uri), ":.") + return string.format('Symbols in %s', fname) +end) --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol -M['workspace/symbol'] = response_to_list(util.symbols_to_items, 'symbols') +M['workspace/symbol'] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) + return string.format("Symbols matching '%s'", ctx.params.query) +end) --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename -M['textDocument/rename'] = function(_, result, _) +M['textDocument/rename'] = function(_, result, ctx, _) if not result then return end - util.apply_workspace_edit(result) + local client = vim.lsp.get_client_by_id(ctx.client_id) + util.apply_workspace_edit(result, client.offset_encoding) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting M['textDocument/rangeFormatting'] = function(_, result, ctx, _) if not result then return end - util.apply_text_edits(result, ctx.bufnr) + local client = vim.lsp.get_client_by_id(ctx.client_id) + util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting M['textDocument/formatting'] = function(_, result, ctx, _) if not result then return end - util.apply_text_edits(result, ctx.bufnr) + local client = vim.lsp.get_client_by_id(ctx.client_id) + util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion @@ -246,7 +292,7 @@ end ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window ---- - See |vim.api.nvim_open_win()| +--- - See |nvim_open_win()| function M.hover(_, result, ctx, config) config = config or {} config.focus_id = ctx.method @@ -277,19 +323,23 @@ local function location_handler(_, result, ctx, _) local _ = log.info() and log.info(ctx.method, 'No location found') return nil end + local client = vim.lsp.get_client_by_id(ctx.client_id) -- textDocument/definition can return Location or Location[] -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition if vim.tbl_islist(result) then - util.jump_to_location(result[1]) + util.jump_to_location(result[1], client.offset_encoding) if #result > 1 then - vim.fn.setqflist({}, ' ', {title = 'LSP locations', items = util.locations_to_items(result)}) + vim.fn.setqflist({}, ' ', { + title = 'LSP locations', + items = util.locations_to_items(result, client.offset_encoding) + }) api.nvim_command("copen") end else - util.jump_to_location(result) + util.jump_to_location(result, client.offset_encoding) end end @@ -439,14 +489,20 @@ for k, fn in pairs(M) do }) if err then - local client = vim.lsp.get_client_by_id(ctx.client_id) - local client_name = client and client.name or string.format("client_id=%d", ctx.client_id) -- LSP spec: -- interface ResponseError: -- code: integer; -- message: string; -- data?: string | number | boolean | array | object | null; - return err_message(client_name .. ': ' .. tostring(err.code) .. ': ' .. err.message) + + -- Per LSP, don't show ContentModified error to the user. + if err.code ~= protocol.ErrorCodes.ContentModified then + local client = vim.lsp.get_client_by_id(ctx.client_id) + local client_name = client and client.name or string.format("client_id=%d", ctx.client_id) + + err_message(client_name .. ': ' .. tostring(err.code) .. ': ' .. err.message) + end + return end return fn(err, result, ctx, config) diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index dbc473b52c..e0b5653587 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -8,8 +8,8 @@ local log = {} -- Log level dictionary with reverse lookup as well. -- -- Can be used to lookup the number from the name or the name from the number. --- Levels by name: 'trace', 'debug', 'info', 'warn', 'error' --- Level numbers begin with 'trace' at 0 +-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR" +-- Level numbers begin with "TRACE" at 0 log.levels = vim.deepcopy(vim.log.levels) -- Default log level is warn. diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 1fb75ddeb7..1ecac50df4 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -133,7 +133,8 @@ local function request_parser_loop() end end -local client_errors = vim.tbl_add_reverse_lookup { +--- Mapping of error codes used by the client +local client_errors = { INVALID_SERVER_MESSAGE = 1; INVALID_SERVER_JSON = 2; NO_RESULT_CALLBACK_FOUND = 3; @@ -143,6 +144,8 @@ local client_errors = vim.tbl_add_reverse_lookup { SERVER_RESULT_CALLBACK_ERROR = 7; } +client_errors = vim.tbl_add_reverse_lookup(client_errors) + --- Constructs an error message from an LSP error object. --- ---@param err (table) The error object diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 5df2a4d144..0f4e5b572b 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -105,15 +105,16 @@ local function align_end_position(line, byte, offset_encoding) char = compute_line_length(line, offset_encoding) + 1 else -- Modifying line, find the nearest utf codepoint - local offset = str_utf_end(line, byte) + local offset = str_utf_start(line, byte) -- If the byte does not fall on the start of the character, then -- align to the start of the next character. - if offset > 0 then - char = byte_to_utf(line, byte, offset_encoding) + 1 - byte = byte + offset - else + if offset < 0 then + byte = byte + str_utf_end(line, byte) + 1 + end + if byte <= #line then char = byte_to_utf(line, byte, offset_encoding) - byte = byte + offset + else + char = compute_line_length(line, offset_encoding) + 1 end -- Extending line, find the nearest utf codepoint for the last valid character end @@ -167,7 +168,7 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline, char_idx = compute_line_length(prev_line, offset_encoding) + 1 else byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx) - char_idx = byte_to_utf(prev_line, start_byte_idx, offset_encoding) + char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding) end -- Return the start difference (shared for new and prev lines) @@ -297,7 +298,7 @@ end ---@private -- rangelength depends on the offset encoding --- bytes for utf-8 (clangd with extenion) +-- bytes for utf-8 (clangd with extension) -- codepoints for utf-16 -- codeunits for utf-32 -- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 68a030d50b..d22c00ae76 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -10,14 +10,6 @@ local uv = vim.loop local npcall = vim.F.npcall local split = vim.split -local _warned = {} -local warn_once = function(message) - if not _warned[message] then - vim.api.nvim_err_writeln(message) - _warned[message] = true - end -end - local M = {} local default_border = { @@ -97,15 +89,17 @@ end ---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 ---@return number `encoding` index of `index` in `line` function M._str_utfindex_enc(line, index, encoding) - if encoding ~= 'utf-8' then - local col32, col16 = vim.str_utfindex(line, index) - if encoding == 'utf-32' then - return col32 - else - return col16 - end + if not encoding then encoding = 'utf-16' end + if encoding == 'utf-8' then + if index then return index else return #line end + elseif encoding == 'utf-16' then + local _, col16 = vim.str_utfindex(line, index) + return col16 + elseif encoding == 'utf-32' then + local col32, _ = vim.str_utfindex(line, index) + return col32 else - return index + error("Invalid encoding: " .. vim.inspect(encoding)) end end @@ -117,10 +111,15 @@ end ---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 ---@return number byte (utf-8) index of `encoding` index `index` in `line` function M._str_byteindex_enc(line, index, encoding) - if encoding ~= 'utf-8' then - return vim.str_byteindex(line, index, not encoding or encoding ~= 'utf-32') + if not encoding then encoding = 'utf-16' end + if encoding == 'utf-8' then + if index then return index else return #line end + elseif encoding == 'utf-16' then + return vim.str_byteindex(line, index, true) + elseif encoding == 'utf-32' then + return vim.str_byteindex(line, index) else - return index + error("Invalid encoding: " .. vim.inspect(encoding)) end end @@ -194,6 +193,11 @@ end local function get_lines(bufnr, rows) rows = type(rows) == "table" and rows or { rows } + -- This is needed for bufload and bufloaded + if bufnr == 0 then + bufnr = vim.api.nvim_get_current_buf() + end + ---@private local function buf_lines() local lines = {} @@ -273,7 +277,7 @@ end ---@private --- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position --- Returns a zero-indexed column, since set_lines() does the conversion to ----@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 +---@param offset_encoding string utf-8|utf-16|utf-32 --- 1-indexed local function get_line_byte_from_position(bufnr, position, offset_encoding) -- LSP's line and characters are 0-indexed @@ -282,7 +286,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding) -- When on the first character, we can ignore the difference between byte and -- character if col > 0 then - local line = get_line(bufnr, position.line) + local line = get_line(bufnr, position.line) or '' local ok, result ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding) if ok then @@ -356,15 +360,14 @@ end --- Applies a list of text edits to a buffer. ---@param text_edits table list of `TextEdit` objects ---@param bufnr number Buffer id ----@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to encoding of first client of `bufnr` +---@param offset_encoding string utf-8|utf-16|utf-32 defaults to encoding of first client of `bufnr` ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit function M.apply_text_edits(text_edits, bufnr, offset_encoding) validate { text_edits = { text_edits, 't', false }; bufnr = { bufnr, 'number', false }; - offset_encoding = { offset_encoding, 'string', true }; + offset_encoding = { offset_encoding, 'string', false }; } - offset_encoding = offset_encoding or M._get_offset_encoding(bufnr) if not next(text_edits) then return end if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) @@ -398,25 +401,6 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) end end) - -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here. - local has_eol_text_edit = false - local max = vim.api.nvim_buf_line_count(bufnr) - local len = _str_utfindex_enc(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '', nil, offset_encoding) - text_edits = vim.tbl_map(function(text_edit) - if max <= text_edit.range.start.line then - text_edit.range.start.line = max - 1 - text_edit.range.start.character = len - text_edit.newText = '\n' .. text_edit.newText - has_eol_text_edit = true - end - if max <= text_edit.range['end'].line then - text_edit.range['end'].line = max - 1 - text_edit.range['end'].character = len - has_eol_text_edit = true - end - return text_edit - end, text_edits) - -- Some LSP servers are depending on the VSCode behavior. -- The VSCode will re-locate the cursor position after applying TextEdit so we also do it. local is_current_buf = vim.api.nvim_get_current_buf() == bufnr @@ -436,16 +420,38 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) -- Apply text edits. local is_cursor_fixed = false + local has_eol_text_edit = false for _, text_edit in ipairs(text_edits) do + -- Normalize line ending + text_edit.newText, _ = string.gsub(text_edit.newText, '\r\n?', '\n') + + -- Convert from LSP style ranges to Neovim style ranges. local e = { start_row = text_edit.range.start.line, - start_col = get_line_byte_from_position(bufnr, text_edit.range.start), + start_col = get_line_byte_from_position(bufnr, text_edit.range.start, offset_encoding), end_row = text_edit.range['end'].line, - end_col = get_line_byte_from_position(bufnr, text_edit.range['end']), + end_col = get_line_byte_from_position(bufnr, text_edit.range['end'], offset_encoding), text = vim.split(text_edit.newText, '\n', true), } + + -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here. + local max = vim.api.nvim_buf_line_count(bufnr) + if max <= e.start_row or max <= e.end_row then + local len = #(get_line(bufnr, max - 1) or '') + if max <= e.start_row then + e.start_row = max - 1 + e.start_col = len + table.insert(e.text, 1, '') + end + if max <= e.end_row then + e.end_row = max - 1 + e.end_col = len + end + has_eol_text_edit = true + end vim.api.nvim_buf_set_text(bufnr, e.start_row, e.start_col, e.end_row, e.end_col, e.text) + -- Fix cursor position. local row_count = (e.end_row - e.start_row) + 1 if e.end_row < cursor.row then cursor.row = cursor.row + (#e.text - row_count) @@ -460,10 +466,13 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) end end + local max = vim.api.nvim_buf_line_count(bufnr) + + -- Apply fixed cursor position. if is_cursor_fixed then local is_valid_cursor = true - is_valid_cursor = is_valid_cursor and cursor.row < vim.api.nvim_buf_line_count(bufnr) - is_valid_cursor = is_valid_cursor and cursor.col <= #(vim.api.nvim_buf_get_lines(bufnr, cursor.row, cursor.row + 1, false)[1] or '') + is_valid_cursor = is_valid_cursor and cursor.row < max + is_valid_cursor = is_valid_cursor and cursor.col <= #(get_line(bufnr, max - 1) or '') if is_valid_cursor then vim.api.nvim_win_set_cursor(0, { cursor.row + 1, cursor.col }) end @@ -472,7 +481,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) -- Remove final line if needed local fix_eol = has_eol_text_edit fix_eol = fix_eol and api.nvim_buf_get_option(bufnr, 'fixeol') - fix_eol = fix_eol and (vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '') == '' + fix_eol = fix_eol and get_line(bufnr, max - 1) == '' if fix_eol then vim.api.nvim_buf_set_lines(bufnr, -2, -1, false, {}) end @@ -510,9 +519,12 @@ end ---@param text_document_edit table: a `TextDocumentEdit` object ---@param index number: Optional index of the edit, if from a list of edits (or nil, if not from a list) ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit -function M.apply_text_document_edit(text_document_edit, index) +function M.apply_text_document_edit(text_document_edit, index, offset_encoding) local text_document = text_document_edit.textDocument local bufnr = vim.uri_to_bufnr(text_document.uri) + if offset_encoding == nil then + vim.notify_once("apply_text_document_edit must be called with valid offset encoding", vim.log.levels.WARN) + end -- For lists of text document edits, -- do not check the version after the first edit. @@ -531,7 +543,7 @@ function M.apply_text_document_edit(text_document_edit, index) return end - M.apply_text_edits(text_document_edit.edits, bufnr) + M.apply_text_edits(text_document_edit.edits, bufnr, offset_encoding) end --- Parses snippets in a completion entry. @@ -728,9 +740,13 @@ end --- Applies a `WorkspaceEdit`. --- ----@param workspace_edit (table) `WorkspaceEdit` +---@param workspace_edit table `WorkspaceEdit` +---@param offset_encoding string utf-8|utf-16|utf-32 (required) --see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit -function M.apply_workspace_edit(workspace_edit) +function M.apply_workspace_edit(workspace_edit, offset_encoding) + if offset_encoding == nil then + vim.notify_once("apply_workspace_edit must be called with valid offset encoding", vim.log.levels.WARN) + end if workspace_edit.documentChanges then for idx, change in ipairs(workspace_edit.documentChanges) do if change.kind == "rename" then @@ -746,7 +762,7 @@ function M.apply_workspace_edit(workspace_edit) elseif change.kind then error(string.format("Unsupported change: %q", vim.inspect(change))) else - M.apply_text_document_edit(change, idx) + M.apply_text_document_edit(change, idx, offset_encoding) end end return @@ -759,7 +775,7 @@ function M.apply_workspace_edit(workspace_edit) for uri, changes in pairs(all_changes) do local bufnr = vim.uri_to_bufnr(uri) - M.apply_text_edits(changes, bufnr) + M.apply_text_edits(changes, bufnr, offset_encoding) end end @@ -835,7 +851,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers local active_hl local active_signature = signature_help.activeSignature or 0 -- If the activeSignature is not inside the valid range, then clip it. - if active_signature >= #signature_help.signatures then + -- In 3.15 of the protocol, activeSignature was allowed to be negative + if active_signature >= #signature_help.signatures or active_signature < 0 then active_signature = 0 end local signature = signature_help.signatures[active_signature + 1] @@ -976,12 +993,16 @@ end --- Jumps to a location. --- ----@param location (`Location`|`LocationLink`) +---@param location table (`Location`|`LocationLink`) +---@param offset_encoding string utf-8|utf-16|utf-32 (required) ---@returns `true` if the jump succeeded -function M.jump_to_location(location) +function M.jump_to_location(location, offset_encoding) -- location may be Location or LocationLink local uri = location.uri or location.targetUri if uri == nil then return end + if offset_encoding == nil then + vim.notify_once("jump_to_location must be called with valid offset encoding", vim.log.levels.WARN) + end local bufnr = vim.uri_to_bufnr(uri) -- Save position in jumplist vim.cmd "normal! m'" @@ -993,10 +1014,10 @@ function M.jump_to_location(location) --- Jump to new location (adjusting for UTF-16 encoding of characters) api.nvim_set_current_buf(bufnr) - api.nvim_buf_set_option(0, 'buflisted', true) + api.nvim_buf_set_option(bufnr, 'buflisted', true) local range = location.range or location.targetSelectionRange local row = range.start.line - local col = get_line_byte_from_position(0, range.start) + local col = get_line_byte_from_position(bufnr, range.start, offset_encoding) api.nvim_win_set_cursor(0, {row + 1, col}) -- Open folds under the cursor vim.cmd("normal! zv") @@ -1498,18 +1519,20 @@ do --[[ References ]] ---@param bufnr number Buffer id function M.buf_clear_references(bufnr) validate { bufnr = {bufnr, 'n', true} } - api.nvim_buf_clear_namespace(bufnr, reference_ns, 0, -1) + api.nvim_buf_clear_namespace(bufnr or 0, reference_ns, 0, -1) end --- Shows a list of document highlights for a certain buffer. --- ---@param bufnr number Buffer id ---@param references table List of `DocumentHighlight` objects to highlight - ---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to `offset_encoding` of first client of `bufnr` + ---@param offset_encoding string One of "utf-8", "utf-16", "utf-32". ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight function M.buf_highlight_references(bufnr, references, offset_encoding) - validate { bufnr = {bufnr, 'n', true} } - offset_encoding = offset_encoding or M._get_offset_encoding(bufnr) + validate { + bufnr = {bufnr, 'n', true}, + offset_encoding = { offset_encoding, 'string', false }; + } for _, reference in ipairs(references) do local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"] local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"] @@ -1527,7 +1550,10 @@ do --[[ References ]] reference_ns, document_highlight_kind[kind], { start_line, start_idx }, - { end_line, end_idx }) + { end_line, end_idx }, + nil, + false, + 40) end end end @@ -1542,9 +1568,14 @@ end) --- The result can be passed to the {list} argument of |setqflist()| or --- |setloclist()|. --- ----@param locations (table) list of `Location`s or `LocationLink`s +---@param locations table list of `Location`s or `LocationLink`s +---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 ---@returns (table) list of items -function M.locations_to_items(locations) +function M.locations_to_items(locations, offset_encoding) + if offset_encoding == nil then + vim.notify_once("locations_to_items must be called with valid offset encoding", vim.log.levels.WARN) + end + local items = {} local grouped = setmetatable({}, { __index = function(t, k) @@ -1584,7 +1615,7 @@ function M.locations_to_items(locations) local pos = temp.start local row = pos.line local line = lines[row] or "" - local col = pos.character + local col = M._str_byteindex_enc(line, pos.character, offset_encoding) table.insert(items, { filename = filename, lnum = row + 1, @@ -1670,7 +1701,7 @@ function M.symbols_to_items(symbols, bufnr) end return _items end - return _symbols_to_items(symbols, {}, bufnr) + return _symbols_to_items(symbols, {}, bufnr or 0) end --- Removes empty lines from the beginning and end. @@ -1768,7 +1799,13 @@ function M._get_offset_encoding(bufnr) local offset_encoding for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do - local this_offset_encoding = client.offset_encoding or "utf-16" + if client.offset_encoding == nil then + vim.notify_once( + string.format("Client (id: %s) offset_encoding is nil. Do not unset offset_encoding.", client.id), + vim.log.levels.ERROR + ) + end + local this_offset_encoding = client.offset_encoding if not offset_encoding then offset_encoding = this_offset_encoding elseif offset_encoding ~= this_offset_encoding then @@ -1789,7 +1826,7 @@ end ---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---`current_position`, end = `current_position` } } function M.make_range_params(window, offset_encoding) - local buf = vim.api.nvim_win_get_buf(window) + local buf = vim.api.nvim_win_get_buf(window or 0) offset_encoding = offset_encoding or M._get_offset_encoding(buf) local position = make_position_param(window, offset_encoding) return { @@ -1815,7 +1852,7 @@ function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding) end_pos = {end_pos, 't', true}; offset_encoding = {offset_encoding, 's', true}; } - bufnr = bufnr or 0 + bufnr = bufnr or vim.api.nvim_get_current_buf() offset_encoding = offset_encoding or M._get_offset_encoding(bufnr) local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<')) local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>')) @@ -1897,7 +1934,9 @@ end ---@returns (number, number) `offset_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, offset_encoding) local line = get_line(buf, row) - offset_encoding = offset_encoding or M._get_offset_encoding(buf) + if offset_encoding == nil then + vim.notify_once("character_offset must be called with valid offset encoding", vim.log.levels.WARN) + end -- If the col is past the EOL, use the line length. if col > #line then return _str_utfindex_enc(line, nil, offset_encoding) @@ -1921,7 +1960,6 @@ function M.lookup_section(settings, section) end M._get_line_byte_from_position = get_line_byte_from_position -M._warn_once = warn_once M.buf_versions = {} diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 1cf618725d..e170befa4c 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -526,13 +526,23 @@ end --- => error('arg1: expected even number, got 3') --- </pre> --- ----@param opt Map of parameter names to validations. Each key is a parameter +--- If multiple types are valid they can be given as a list. +--- <pre> +--- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} +--- => NOP (success) +--- +--- vim.validate{arg1={1, {'string', table'}}} +--- => error('arg1: expected string|table, got number') +--- +--- </pre> +--- +---@param opt table of parameter names to validations. Each key is a parameter --- name; each value is a tuple in one of these forms: --- 1. (arg_value, type_name, optional) --- - arg_value: argument value ---- - type_name: string type name, one of: ("table", "t", "string", +--- - type_name: string|table type name, one of: ("table", "t", "string", --- "s", "number", "n", "boolean", "b", "function", "f", "nil", ---- "thread", "userdata") +--- "thread", "userdata") or list of them. --- - optional: (optional) boolean, if true, `nil` is valid --- 2. (arg_value, fn, msg) --- - arg_value: argument value @@ -571,31 +581,43 @@ do end local val = spec[1] -- Argument value. - local t = spec[2] -- Type name, or callable. + local types = spec[2] -- Type name, or callable. local optional = (true == spec[3]) - if type(t) == 'string' then - local t_name = type_names[t] - if not t_name then - return false, string.format('invalid type name: %s', t) - end + if type(types) == 'string' then + types = {types} + end - if (not optional or val ~= nil) and not _is_type(val, t_name) then - return false, string.format("%s: expected %s, got %s", param_name, t_name, type(val)) - end - elseif vim.is_callable(t) then + if vim.is_callable(types) then -- Check user-provided validation function. - local valid, optional_message = t(val) + local valid, optional_message = types(val) if not valid then - local error_message = string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), val) + local error_message = string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), tostring(val)) if optional_message ~= nil then error_message = error_message .. string.format(". Info: %s", optional_message) end return false, error_message end + elseif type(types) == 'table' then + local success = false + for i, t in ipairs(types) do + local t_name = type_names[t] + if not t_name then + return false, string.format('invalid type name: %s', t) + end + types[i] = t_name + + if (optional and val == nil) or _is_type(val, t_name) then + success = true + break + end + end + if not success then + return false, string.format("%s: expected %s, got %s", param_name, table.concat(types, '|'), type(val)) + end else - return false, string.format("invalid type name: %s", tostring(t)) + return false, string.format("invalid type name: %s", tostring(types)) end end diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 594765761d..85fd5cd8e0 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -77,7 +77,7 @@ end --- Determines whether this tree is valid. --- If the tree is invalid, `parse()` must be called ---- to get the an updated tree. +--- to get the updated tree. function LanguageTree:is_valid() return self._valid end diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index ebed502c92..b3036ea679 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -138,6 +138,13 @@ function M.get_query(lang, query_name) end end +local query_cache = setmetatable({}, { + __index = function(tbl, key) + rawset(tbl, key, {}) + return rawget(tbl, key) + end +}) + --- Parse {query} as a string. (If the query is in a file, the caller --- should read the contents into a string before calling). --- @@ -151,17 +158,23 @@ end --- -` info.captures` also points to `captures`. --- - `info.patterns` contains information about predicates. --- ----@param lang The language ----@param query A string containing the query (s-expr syntax) +---@param lang string The language +---@param query string A string containing the query (s-expr syntax) --- ---@returns The query function M.parse_query(lang, query) language.require_language(lang) - local self = setmetatable({}, Query) - self.query = vim._ts_parse_query(lang, query) - self.info = self.query:inspect() - self.captures = self.info.captures - return self + local cached = query_cache[lang][query] + if cached then + return cached + else + local self = setmetatable({}, Query) + self.query = vim._ts_parse_query(lang, query) + self.info = self.query:inspect() + self.captures = self.info.captures + query_cache[lang][query] = self + return self + end end --- Gets the text corresponding to a given node diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua index d08d2a3ee3..11b661cd1a 100644 --- a/runtime/lua/vim/uri.lua +++ b/runtime/lua/vim/uri.lua @@ -74,8 +74,8 @@ local function uri_from_fname(path) return table.concat(uri_parts) end -local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*' -local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):[a-zA-Z]:.*' +local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*' +local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*' --- Get a URI from a bufnr ---@param bufnr number diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml index 225dd79878..4ad656f1a3 100644 --- a/runtime/nvim.appdata.xml +++ b/runtime/nvim.appdata.xml @@ -26,7 +26,9 @@ </screenshots> <releases> + <release date="2021-12-31" version="0.6.1"/> <release date="2021-11-30" version="0.6.0"/> + <release date="2021-09-26" version="0.5.1"/> <release date="2021-07-02" version="0.5.0"/> <release date="2020-08-04" version="0.4.4"/> <release date="2019-11-06" version="0.4.3"/> diff --git a/runtime/optwin.vim b/runtime/optwin.vim index d4c10f7afa..c873252909 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2020 Oct 27 +" Last Change: 2021 Dec 12 " If there already is an option window, jump to that one. let buf = bufnr('option-window') @@ -261,6 +261,8 @@ call <SID>OptionG("sect", §) call append("$", "path\tlist of directory names used for file searching") call append("$", "\t(global or local to buffer)") call <SID>OptionG("pa", &pa) +call <SID>AddOption("cdhome", ":cd without argument goes to the home directory") +call <SID>BinOptionG("cdh", &cdh) call append("$", "cdpath\tlist of directory names used for :cd") call <SID>OptionG("cd", &cd) if exists("+autochdir") diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim index 4f3dd8ff9e..e8689980ae 100644 --- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim +++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim @@ -1,6 +1,11 @@ " matchit.vim: (global plugin) Extended "%" matching " autload script of matchit plugin, see ../plugin/matchit.vim -" Last Change: Mar 01, 2020 +" Last Change: Jun 10, 2021 + +" Neovim does not support scriptversion +if has("vimscript-4") + scriptversion 4 +endif let s:last_mps = "" let s:last_words = ":" @@ -30,11 +35,11 @@ function s:RestoreOptions() " In s:CleanUp(), :execute "set" restore_options . let restore_options = "" if get(b:, 'match_ignorecase', &ic) != &ic - let restore_options .= (&ic ? " " : " no") . "ignorecase" + let restore_options ..= (&ic ? " " : " no") .. "ignorecase" let &ignorecase = b:match_ignorecase endif if &ve != '' - let restore_options = " ve=" . &ve . restore_options + let restore_options = " ve=" .. &ve .. restore_options set ve= endif return restore_options @@ -42,22 +47,23 @@ endfunction function matchit#Match_wrapper(word, forward, mode) range let restore_options = s:RestoreOptions() - " If this function was called from Visual mode, make sure that the cursor - " is at the correct end of the Visual range: - if a:mode == "v" - execute "normal! gv\<Esc>" - elseif a:mode == "o" && mode(1) !~# '[vV]' - exe "norm! v" - elseif a:mode == "n" && mode(1) =~# 'ni' - exe "norm! v" - endif " In s:CleanUp(), we may need to check whether the cursor moved forward. let startpos = [line("."), col(".")] - " Use default behavior if called with a count. + " if a count has been applied, use the default [count]% mode (see :h N%) if v:count - exe "normal! " . v:count . "%" + exe "normal! " .. v:count .. "%" return s:CleanUp(restore_options, a:mode, startpos) end + if a:mode =~# "v" && mode(1) =~# 'ni' + exe "norm! gv" + elseif a:mode == "o" && mode(1) !~# '[vV]' + exe "norm! v" + " If this function was called from Visual mode, make sure that the cursor + " is at the correct end of the Visual range: + elseif a:mode == "v" + execute "normal! gv\<Esc>" + let startpos = [line("."), col(".")] + endif " First step: if not already done, set the script variables " s:do_BR flag for whether there are backrefs @@ -78,30 +84,30 @@ function matchit#Match_wrapper(word, forward, mode) range " quote the special chars in 'matchpairs', replace [,:] with \| and then " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif, " #endif) - let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . + let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' " s:all = pattern with all the keywords - let match_words = match_words . (strlen(match_words) ? "," : "") . default + let match_words = match_words .. (strlen(match_words) ? "," : "") .. default let s:last_words = match_words - if match_words !~ s:notslash . '\\\d' + if match_words !~ s:notslash .. '\\\d' let s:do_BR = 0 let s:pat = match_words else let s:do_BR = 1 let s:pat = s:ParseWords(match_words) endif - let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g') + let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g') " Just in case there are too many '\(...)' groups inside the pattern, make " sure to use \%(...) groups, so that error E872 can be avoided let s:all = substitute(s:all, '\\(', '\\%(', 'g') - let s:all = '\%(' . s:all . '\)' + let s:all = '\%(' .. s:all .. '\)' if exists("b:match_debug") let b:match_pat = s:pat endif " Reconstruct the version with unresolved backrefs. - let s:patBR = substitute(match_words.',', - \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') - let s:patBR = substitute(s:patBR, s:notslash.'\zs:\{2,}', ':', 'g') + let s:patBR = substitute(match_words .. ',', + \ s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') endif " Second step: set the following local variables: @@ -128,12 +134,15 @@ function matchit#Match_wrapper(word, forward, mode) range let curcol = match(matchline, regexp) " If there is no match, give up. if curcol == -1 + " Make sure macros abort properly + "exe "norm! \<esc>" + call feedkeys("\e", 'tni') return s:CleanUp(restore_options, a:mode, startpos) endif let endcol = matchend(matchline, regexp) let suf = strlen(matchline) - endcol - let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(') - let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$') + let prefix = (curcol ? '^.*\%' .. (curcol + 1) .. 'c\%(' : '^\%(') + let suffix = (suf ? '\)\%' .. (endcol + 1) .. 'c.*$' : '\)$') endif if exists("b:match_debug") let b:match_match = matchstr(matchline, regexp) @@ -150,7 +159,7 @@ function matchit#Match_wrapper(word, forward, mode) range " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns " group . "," . groupBR, and we pick it apart. let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, s:patBR) - let i = matchend(group, s:notslash . ",") + let i = matchend(group, s:notslash .. ",") let groupBR = strpart(group, i) let group = strpart(group, 0, i-1) " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix @@ -159,32 +168,32 @@ function matchit#Match_wrapper(word, forward, mode) range endif if exists("b:match_debug") let b:match_wholeBR = groupBR - let i = matchend(groupBR, s:notslash . ":") + let i = matchend(groupBR, s:notslash .. ":") let b:match_iniBR = strpart(groupBR, 0, i-1) endif " Fourth step: Set the arguments for searchpair(). - let i = matchend(group, s:notslash . ":") - let j = matchend(group, '.*' . s:notslash . ":") + let i = matchend(group, s:notslash .. ":") + let j = matchend(group, '.*' .. s:notslash .. ":") let ini = strpart(group, 0, i-1) - let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g') + let mid = substitute(strpart(group, i,j-i-1), s:notslash .. '\zs:', '\\|', 'g') let fin = strpart(group, j) "Un-escape the remaining , and : characters. - let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') - let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') - let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') + let ini = substitute(ini, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + let mid = substitute(mid, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + let fin = substitute(fin, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') " searchpair() requires that these patterns avoid \(\) groups. - let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g') - let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g') - let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g') + let ini = substitute(ini, s:notslash .. '\zs\\(', '\\%(', 'g') + let mid = substitute(mid, s:notslash .. '\zs\\(', '\\%(', 'g') + let fin = substitute(fin, s:notslash .. '\zs\\(', '\\%(', 'g') " Set mid. This is optimized for readability, not micro-efficiency! - if a:forward && matchline =~ prefix . fin . suffix - \ || !a:forward && matchline =~ prefix . ini . suffix + if a:forward && matchline =~ prefix .. fin .. suffix + \ || !a:forward && matchline =~ prefix .. ini .. suffix let mid = "" endif " Set flag. This is optimized for readability, not micro-efficiency! - if a:forward && matchline =~ prefix . fin . suffix - \ || !a:forward && matchline !~ prefix . ini . suffix + if a:forward && matchline =~ prefix .. fin .. suffix + \ || !a:forward && matchline !~ prefix .. ini .. suffix let flag = "bW" else let flag = "W" @@ -193,14 +202,14 @@ function matchit#Match_wrapper(word, forward, mode) range if exists("b:match_skip") let skip = b:match_skip elseif exists("b:match_comment") " backwards compatibility and testing! - let skip = "r:" . b:match_comment + let skip = "r:" .. b:match_comment else let skip = 's:comment\|string' endif let skip = s:ParseSkip(skip) if exists("b:match_debug") let b:match_ini = ini - let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin + let b:match_tail = (strlen(mid) ? mid .. '\|' : '') .. fin endif " Fifth step: actually start moving the cursor and call searchpair(). @@ -210,25 +219,29 @@ function matchit#Match_wrapper(word, forward, mode) range if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) let skip = "0" else - execute "if " . skip . "| let skip = '0' | endif" + execute "if " .. skip .. "| let skip = '0' | endif" endif let sp_return = searchpair(ini, mid, fin, flag, skip) if &selection isnot# 'inclusive' && a:mode == 'v' " move cursor one pos to the right, because selection is not inclusive - " add virtualedit=onemore, to make it work even when the match ends the " line + " add virtualedit=onemore, to make it work even when the match ends the + " line if !(col('.') < col('$')-1) - set ve=onemore + let eolmark=1 " flag to set a mark on eol (since we cannot move there) endif norm! l endif - let final_position = "call cursor(" . line(".") . "," . col(".") . ")" + let final_position = "call cursor(" .. line(".") .. "," .. col(".") .. ")" " Restore cursor position and original screen. call winrestview(view) normal! m' if sp_return > 0 execute final_position endif - return s:CleanUp(restore_options, a:mode, startpos, mid.'\|'.fin) + if exists('eolmark') && eolmark + call setpos("''", [0, line('.'), col('$'), 0]) " set mark on the eol + endif + return s:CleanUp(restore_options, a:mode, startpos, mid .. '\|' .. fin) endfun " Restore options and do some special handling for Operator-pending mode. @@ -270,16 +283,16 @@ endfun " a:matchline = "123<tag>12" or "123</tag>12" " then extract "tag" from a:matchline and return "<tag>:</tag>" . fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) - if a:matchline !~ a:prefix . - \ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix + if a:matchline !~ a:prefix .. + \ substitute(a:group, s:notslash .. '\zs:', '\\|', 'g') .. a:suffix return a:group endif - let i = matchend(a:groupBR, s:notslash . ':') + let i = matchend(a:groupBR, s:notslash .. ':') let ini = strpart(a:groupBR, 0, i-1) let tailBR = strpart(a:groupBR, i) let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix, \ a:groupBR) - let i = matchend(word, s:notslash . ":") + let i = matchend(word, s:notslash .. ":") let wordBR = strpart(word, i) let word = strpart(word, 0, i-1) " Now, a:matchline =~ a:prefix . word . a:suffix @@ -289,10 +302,10 @@ fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) let table = "" let d = 0 while d < 10 - if tailBR =~ s:notslash . '\\' . d - let table = table . d + if tailBR =~ s:notslash .. '\\' .. d + let table = table .. d else - let table = table . "-" + let table = table .. "-" endif let d = d + 1 endwhile @@ -300,13 +313,13 @@ fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) let d = 9 while d if table[d] != "-" - let backref = substitute(a:matchline, a:prefix.word.a:suffix, - \ '\'.table[d], "") + let backref = substitute(a:matchline, a:prefix .. word .. a:suffix, + \ '\' .. table[d], "") " Are there any other characters that should be escaped? let backref = escape(backref, '*,:') execute s:Ref(ini, d, "start", "len") - let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len) - let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d, + let ini = strpart(ini, 0, start) .. backref .. strpart(ini, start+len) + let tailBR = substitute(tailBR, s:notslash .. '\zs\\' .. d, \ escape(backref, '\\&'), 'g') endif let d = d-1 @@ -320,7 +333,7 @@ fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) let b:match_word = "" endif endif - return ini . ":" . tailBR + return ini .. ":" .. tailBR endfun " Input a comma-separated list of groups with backrefs, such as @@ -328,25 +341,25 @@ endfun " and return a comma-separated list of groups with backrefs replaced: " return '\(foo\):end\(foo\),\(bar\):end\(bar\)' fun! s:ParseWords(groups) - let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g') - let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g') + let groups = substitute(a:groups .. ",", s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let groups = substitute(groups, s:notslash .. '\zs:\{2,}', ':', 'g') let parsed = "" while groups =~ '[^,:]' - let i = matchend(groups, s:notslash . ':') - let j = matchend(groups, s:notslash . ',') + let i = matchend(groups, s:notslash .. ':') + let j = matchend(groups, s:notslash .. ',') let ini = strpart(groups, 0, i-1) - let tail = strpart(groups, i, j-i-1) . ":" + let tail = strpart(groups, i, j-i-1) .. ":" let groups = strpart(groups, j) - let parsed = parsed . ini - let i = matchend(tail, s:notslash . ':') + let parsed = parsed .. ini + let i = matchend(tail, s:notslash .. ':') while i != -1 " In 'if:else:endif', ini='if' and word='else' and then word='endif'. let word = strpart(tail, 0, i-1) let tail = strpart(tail, i) - let i = matchend(tail, s:notslash . ':') - let parsed = parsed . ":" . s:Resolve(ini, word, "word") + let i = matchend(tail, s:notslash .. ':') + let parsed = parsed .. ":" .. s:Resolve(ini, word, "word") endwhile " Now, tail has been used up. - let parsed = parsed . "," + let parsed = parsed .. "," endwhile " groups =~ '[^,:]' let parsed = substitute(parsed, ',$', '', '') return parsed @@ -364,14 +377,14 @@ endfun " let j = matchend(getline("."), regexp) " let match = matchstr(getline("."), regexp) fun! s:Wholematch(string, pat, start) - let group = '\%(' . a:pat . '\)' - let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^') + let group = '\%(' .. a:pat .. '\)' + let prefix = (a:start ? '\(^.*\%<' .. (a:start + 2) .. 'c\)\zs' : '^') let len = strlen(a:string) - let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$') - if a:string !~ prefix . group . suffix + let suffix = (a:start+1 < len ? '\(\%>' .. (a:start+1) .. 'c.*$\)\@=' : '$') + if a:string !~ prefix .. group .. suffix let prefix = '' endif - return prefix . group . suffix + return prefix .. group .. suffix endfun " No extra arguments: s:Ref(string, d) will @@ -392,7 +405,7 @@ fun! s:Ref(string, d, ...) let match = a:string while cnt let cnt = cnt - 1 - let index = matchend(match, s:notslash . '\\(') + let index = matchend(match, s:notslash .. '\\(') if index == -1 return "" endif @@ -404,7 +417,7 @@ fun! s:Ref(string, d, ...) endif let cnt = 1 while cnt - let index = matchend(match, s:notslash . '\\(\|\\)') - 1 + let index = matchend(match, s:notslash .. '\\(\|\\)') - 1 if index == -2 return "" endif @@ -418,7 +431,7 @@ fun! s:Ref(string, d, ...) if a:0 == 1 return len elseif a:0 == 2 - return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len + return "let " .. a:1 .. "=" .. start .. "| let " .. a:2 .. "=" .. len else return strpart(a:string, start, len) endif @@ -431,9 +444,9 @@ endfun fun! s:Count(string, pattern, ...) let pat = escape(a:pattern, '\\') if a:0 > 1 - let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g") + let foo = substitute(a:string, '[^' .. a:pattern .. ']', "a:1", "g") let foo = substitute(a:string, pat, a:2, "g") - let foo = substitute(foo, '[^' . a:2 . ']', "", "g") + let foo = substitute(foo, '[^' .. a:2 .. ']', "", "g") return strlen(foo) endif let result = 0 @@ -456,7 +469,7 @@ endfun " unless it is preceded by "\". fun! s:Resolve(source, target, output) let word = a:target - let i = matchend(word, s:notslash . '\\\d') - 1 + let i = matchend(word, s:notslash .. '\\\d') - 1 let table = "----------" while i != -2 " There are back references to be replaced. let d = word[i] @@ -477,28 +490,28 @@ fun! s:Resolve(source, target, output) if table[s] == "-" if w + b < 10 " let table[s] = w + b - let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1) + let table = strpart(table, 0, s) .. (w+b) .. strpart(table, s+1) endif let b = b + 1 let s = s + 1 else execute s:Ref(backref, b, "start", "len") let ref = strpart(backref, start, len) - let backref = strpart(backref, 0, start) . ":". table[s] - \ . strpart(backref, start+len) + let backref = strpart(backref, 0, start) .. ":" .. table[s] + \ .. strpart(backref, start+len) let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1') endif endwhile - let word = strpart(word, 0, i-1) . backref . strpart(word, i+1) - let i = matchend(word, s:notslash . '\\\d') - 1 + let word = strpart(word, 0, i-1) .. backref .. strpart(word, i+1) + let i = matchend(word, s:notslash .. '\\\d') - 1 endwhile - let word = substitute(word, s:notslash . '\zs:', '\\', 'g') + let word = substitute(word, s:notslash .. '\zs:', '\\', 'g') if a:output == "table" return table elseif a:output == "word" return word else - return table . word + return table .. word endif endfun @@ -508,21 +521,21 @@ endfun " If <patn> is the first pattern that matches a:string then return <patn> " if no optional arguments are given; return <patn>,<altn> if a:1 is given. fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) - let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma) - let i = matchend(tail, s:notslash . a:comma) + let tail = (a:patterns =~ a:comma .. "$" ? a:patterns : a:patterns .. a:comma) + let i = matchend(tail, s:notslash .. a:comma) if a:0 - let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma) - let j = matchend(alttail, s:notslash . a:comma) + let alttail = (a:1 =~ a:comma .. "$" ? a:1 : a:1 .. a:comma) + let j = matchend(alttail, s:notslash .. a:comma) endif let current = strpart(tail, 0, i-1) if a:branch == "" let currpat = current else - let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') + let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') endif - while a:string !~ a:prefix . currpat . a:suffix + while a:string !~ a:prefix .. currpat .. a:suffix let tail = strpart(tail, i) - let i = matchend(tail, s:notslash . a:comma) + let i = matchend(tail, s:notslash .. a:comma) if i == -1 return -1 endif @@ -530,15 +543,15 @@ fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) if a:branch == "" let currpat = current else - let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') + let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') endif if a:0 let alttail = strpart(alttail, j) - let j = matchend(alttail, s:notslash . a:comma) + let j = matchend(alttail, s:notslash .. a:comma) endif endwhile if a:0 - let current = current . a:comma . strpart(alttail, 0, j-1) + let current = current .. a:comma .. strpart(alttail, 0, j-1) endif return current endfun @@ -562,7 +575,7 @@ fun! matchit#Match_debug() " fin = 'endif' piece, with all backrefs resolved from match amenu &Matchit.&word :echo b:match_word<CR> " '\'.d in ini refers to the same thing as '\'.table[d] in word. - amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR> + amenu &Matchit.t&able :echo '0:' .. b:match_table .. ':9'<CR> endfun " Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW" @@ -598,26 +611,26 @@ fun! matchit#MultiMatch(spflag, mode) endif if (match_words != s:last_words) || (&mps != s:last_mps) || \ exists("b:match_debug") - let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . + let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' let s:last_mps = &mps - let match_words = match_words . (strlen(match_words) ? "," : "") . default + let match_words = match_words .. (strlen(match_words) ? "," : "") .. default let s:last_words = match_words - if match_words !~ s:notslash . '\\\d' + if match_words !~ s:notslash .. '\\\d' let s:do_BR = 0 let s:pat = match_words else let s:do_BR = 1 let s:pat = s:ParseWords(match_words) endif - let s:all = '\%(' . substitute(s:pat, '[,:]\+', '\\|', 'g') . '\)' + let s:all = '\%(' .. substitute(s:pat, '[,:]\+', '\\|', 'g') .. '\)' if exists("b:match_debug") let b:match_pat = s:pat endif " Reconstruct the version with unresolved backrefs. - let s:patBR = substitute(match_words.',', - \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') - let s:patBR = substitute(s:patBR, s:notslash.'\zs:\{2,}', ':', 'g') + let s:patBR = substitute(match_words .. ',', + \ s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') endif " Second step: figure out the patterns for searchpair() @@ -625,23 +638,23 @@ fun! matchit#MultiMatch(spflag, mode) " - TODO: A lot of this is copied from matchit#Match_wrapper(). " - maybe even more functionality should be split off " - into separate functions! - let openlist = split(s:pat . ',', s:notslash . '\zs:.\{-}' . s:notslash . ',') - let midclolist = split(',' . s:pat, s:notslash . '\zs,.\{-}' . s:notslash . ':') - call map(midclolist, {-> split(v:val, s:notslash . ':')}) + let openlist = split(s:pat .. ',', s:notslash .. '\zs:.\{-}' .. s:notslash .. ',') + let midclolist = split(',' .. s:pat, s:notslash .. '\zs,.\{-}' .. s:notslash .. ':') + call map(midclolist, {-> split(v:val, s:notslash .. ':')}) let closelist = [] let middlelist = [] call map(midclolist, {i,v -> [extend(closelist, v[-1 : -1]), \ extend(middlelist, v[0 : -2])]}) - call map(openlist, {i,v -> v =~# s:notslash . '\\|' ? '\%(' . v . '\)' : v}) - call map(middlelist, {i,v -> v =~# s:notslash . '\\|' ? '\%(' . v . '\)' : v}) - call map(closelist, {i,v -> v =~# s:notslash . '\\|' ? '\%(' . v . '\)' : v}) + call map(openlist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) + call map(middlelist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) + call map(closelist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) let open = join(openlist, ',') let middle = join(middlelist, ',') let close = join(closelist, ',') if exists("b:match_skip") let skip = b:match_skip elseif exists("b:match_comment") " backwards compatibility and testing! - let skip = "r:" . b:match_comment + let skip = "r:" .. b:match_comment else let skip = 's:comment\|string' endif @@ -650,18 +663,18 @@ fun! matchit#MultiMatch(spflag, mode) " Third step: call searchpair(). " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'. - let openpat = substitute(open, '\%(' . s:notslash . '\)\@<=\\(', '\\%(', 'g') + let openpat = substitute(open, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') let openpat = substitute(openpat, ',', '\\|', 'g') - let closepat = substitute(close, '\%(' . s:notslash . '\)\@<=\\(', '\\%(', 'g') + let closepat = substitute(close, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') let closepat = substitute(closepat, ',', '\\|', 'g') - let middlepat = substitute(middle, '\%(' . s:notslash . '\)\@<=\\(', '\\%(', 'g') + let middlepat = substitute(middle, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') let middlepat = substitute(middlepat, ',', '\\|', 'g') if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) let skip = '0' else try - execute "if " . skip . "| let skip = '0' | endif" + execute "if " .. skip .. "| let skip = '0' | endif" catch /^Vim\%((\a\+)\)\=:E363/ " We won't find anything, so skip searching, should keep Vim responsive. return {} @@ -744,11 +757,11 @@ fun! s:ParseSkip(str) let skip = a:str if skip[1] == ":" if skip[0] == "s" - let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . - \ strpart(skip,2) . "'" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .. + \ strpart(skip,2) .. "'" elseif skip[0] == "S" - let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" . - \ strpart(skip,2) . "'" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .. + \ strpart(skip,2) .. "'" elseif skip[0] == "r" let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'" elseif skip[0] == "R" diff --git a/runtime/pack/dist/opt/matchit/doc/matchit.txt b/runtime/pack/dist/opt/matchit/doc/matchit.txt index b719fae730..553359ffaf 100644 --- a/runtime/pack/dist/opt/matchit/doc/matchit.txt +++ b/runtime/pack/dist/opt/matchit/doc/matchit.txt @@ -4,7 +4,7 @@ For instructions on installing this file, type `:help matchit-install` inside Vim. -For Vim version 8.1. Last change: 2021 Nov 13 +For Vim version 8.2. Last change: 2021 Dec 24 VIM REFERENCE MANUAL by Benji Fisher et al @@ -150,6 +150,10 @@ To use the matchit plugin add this line to your |vimrc|: > The script should start working the next time you start Vim. +To use the matchit plugin after startup, you can use this command (note the +omitted '!'): > + packadd matchit + (Earlier versions of the script did nothing unless a |buffer-variable| named |b:match_words| was defined. Even earlier versions contained autocommands that set this variable for various file types. Now, |b:match_words| is @@ -378,8 +382,8 @@ The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in 5. Known Bugs and Limitations *matchit-bugs* Repository: https://github.com/chrisbra/matchit/ -Bugs can be reported at the repository (alternatively you can send me a mail). -The latest development snapshot can also be downloaded there. +Bugs can be reported at the repository and the latest development snapshot can +also be downloaded there. Just because I know about a bug does not mean that it is on my todo list. I try to respond to reports of bugs that cause real problems. If it does not diff --git a/runtime/pack/dist/opt/matchit/plugin/matchit.vim b/runtime/pack/dist/opt/matchit/plugin/matchit.vim index b62cc3913a..51ba3a7f51 100644 --- a/runtime/pack/dist/opt/matchit/plugin/matchit.vim +++ b/runtime/pack/dist/opt/matchit/plugin/matchit.vim @@ -1,7 +1,7 @@ " matchit.vim: (global plugin) Extended "%" matching " Maintainer: Christian Brabandt -" Version: 1.17 -" Last Change: 2019 Oct 24 +" Version: 1.18 +" Last Change: 2020 Dec 23 " Repository: https://github.com/chrisbra/matchit " Previous URL:http://www.vim.org/script.php?script_id=39 " Previous Maintainer: Benji Fisher PhD <benji@member.AMS.org> @@ -48,18 +48,12 @@ set cpo&vim nnoremap <silent> <Plug>(MatchitNormalForward) :<C-U>call matchit#Match_wrapper('',1,'n')<CR> nnoremap <silent> <Plug>(MatchitNormalBackward) :<C-U>call matchit#Match_wrapper('',0,'n')<CR> -xnoremap <silent> <Plug>(MatchitVisualForward) :<C-U>call matchit#Match_wrapper('',1,'v')<CR>m'gv`` +xnoremap <silent> <Plug>(MatchitVisualForward) :<C-U>call matchit#Match_wrapper('',1,'v')<CR> + \:if col("''") != col("$") \| exe ":normal! m'" \| endif<cr>gv`` xnoremap <silent> <Plug>(MatchitVisualBackward) :<C-U>call matchit#Match_wrapper('',0,'v')<CR>m'gv`` onoremap <silent> <Plug>(MatchitOperationForward) :<C-U>call matchit#Match_wrapper('',1,'o')<CR> onoremap <silent> <Plug>(MatchitOperationBackward) :<C-U>call matchit#Match_wrapper('',0,'o')<CR> -nmap <silent> % <Plug>(MatchitNormalForward) -nmap <silent> g% <Plug>(MatchitNormalBackward) -xmap <silent> % <Plug>(MatchitVisualForward) -xmap <silent> g% <Plug>(MatchitVisualBackward) -omap <silent> % <Plug>(MatchitOperationForward) -omap <silent> g% <Plug>(MatchitOperationBackward) - " Analogues of [{ and ]} using matching patterns: nnoremap <silent> <Plug>(MatchitNormalMultiBackward) :<C-U>call matchit#MultiMatch("bW", "n")<CR> nnoremap <silent> <Plug>(MatchitNormalMultiForward) :<C-U>call matchit#MultiMatch("W", "n")<CR> @@ -68,16 +62,28 @@ xnoremap <silent> <Plug>(MatchitVisualMultiForward) :<C-U>call matchit#Multi onoremap <silent> <Plug>(MatchitOperationMultiBackward) :<C-U>call matchit#MultiMatch("bW", "o")<CR> onoremap <silent> <Plug>(MatchitOperationMultiForward) :<C-U>call matchit#MultiMatch("W", "o")<CR> -nmap <silent> [% <Plug>(MatchitNormalMultiBackward) -nmap <silent> ]% <Plug>(MatchitNormalMultiForward) -xmap <silent> [% <Plug>(MatchitVisualMultiBackward) -xmap <silent> ]% <Plug>(MatchitVisualMultiForward) -omap <silent> [% <Plug>(MatchitOperationMultiBackward) -omap <silent> ]% <Plug>(MatchitOperationMultiForward) - " text object: xmap <silent> <Plug>(MatchitVisualTextObject) <Plug>(MatchitVisualMultiBackward)o<Plug>(MatchitVisualMultiForward) -xmap a% <Plug>(MatchitVisualTextObject) + +if !exists("g:no_plugin_maps") + nmap <silent> % <Plug>(MatchitNormalForward) + nmap <silent> g% <Plug>(MatchitNormalBackward) + xmap <silent> % <Plug>(MatchitVisualForward) + xmap <silent> g% <Plug>(MatchitVisualBackward) + omap <silent> % <Plug>(MatchitOperationForward) + omap <silent> g% <Plug>(MatchitOperationBackward) + + " Analogues of [{ and ]} using matching patterns: + nmap <silent> [% <Plug>(MatchitNormalMultiBackward) + nmap <silent> ]% <Plug>(MatchitNormalMultiForward) + xmap <silent> [% <Plug>(MatchitVisualMultiBackward) + xmap <silent> ]% <Plug>(MatchitVisualMultiForward) + omap <silent> [% <Plug>(MatchitOperationMultiBackward) + omap <silent> ]% <Plug>(MatchitOperationMultiForward) + + " Text object + xmap a% <Plug>(MatchitVisualTextObject) +endif " Call this function to turn on debugging information. Every time the main " script is run, buffer variables will be saved. These can be used directly diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 67d91360d8..49d9389773 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2021 Nov 29 +" Last Change: 2022 Jan 17 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with @@ -104,6 +104,10 @@ call s:Highlight(1, '', &background) hi default debugBreakpoint term=reverse ctermbg=red guibg=red hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray +func s:GetCommand() + return type(g:termdebugger) == v:t_list ? copy(g:termdebugger) : [g:termdebugger] +endfunc + func s:StartDebug(bang, ...) " First argument is the command to debug, second core file or process ID. call s:StartDebug_internal({'gdb_args': a:000, 'bang': a:bang}) @@ -119,8 +123,9 @@ func s:StartDebug_internal(dict) echoerr 'Terminal debugger already running, cannot run two' return endif - if !executable(g:termdebugger) - echoerr 'Cannot execute debugger program "' .. g:termdebugger .. '"' + let gdbcmd = s:GetCommand() + if !executable(gdbcmd[0]) + echoerr 'Cannot execute debugger program "' .. gdbcmd[0] .. '"' return endif @@ -148,7 +153,7 @@ func s:StartDebug_internal(dict) if &columns < g:termdebug_wide let s:save_columns = &columns let &columns = g:termdebug_wide - " If we make the Vim window wider, use the whole left halve for the debug + " If we make the Vim window wider, use the whole left half for the debug " windows. let s:allleft = 1 endif @@ -192,7 +197,7 @@ endfunc func s:CheckGdbRunning() if nvim_get_chan_info(s:gdb_job_id) == {} - echoerr string(g:termdebugger) . ' exited unexpectedly' + echoerr string(s:GetCommand()[0]) . ' exited unexpectedly' call s:CloseBuffers() return '' endif @@ -245,7 +250,7 @@ func s:StartDebug_term(dict) let gdb_args = get(a:dict, 'gdb_args', []) let proc_args = get(a:dict, 'proc_args', []) - let gdb_cmd = [g:termdebugger] + let gdb_cmd = s:GetCommand() " Add -quiet to avoid the intro message causing a hit-enter prompt. let gdb_cmd += ['-quiet'] " Disable pagination, it causes everything to stop at the gdb @@ -379,7 +384,7 @@ func s:StartDebug_prompt(dict) let gdb_args = get(a:dict, 'gdb_args', []) let proc_args = get(a:dict, 'proc_args', []) - let gdb_cmd = [g:termdebugger] + let gdb_cmd = s:GetCommand() " Add -quiet to avoid the intro message causing a hit-enter prompt. let gdb_cmd += ['-quiet'] " Disable pagination, it causes everything to stop at the gdb, needs to be run early @@ -609,7 +614,7 @@ endfunc " to the next ", unescaping characters: " - remove line breaks " - change \\t to \t -" - change \0xhh to \xhh +" - change \0xhh to \xhh (disabled for now) " - change \ooo to octal " - change \\ to \ func s:DecodeMessage(quotedText) @@ -618,12 +623,21 @@ func s:DecodeMessage(quotedText) return endif return a:quotedText - \->substitute('^"\|".*\|\\n', '', 'g') - \->substitute('\\t', "\t", 'g') - \->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') - \->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g') - \->substitute('\\\\', '\', 'g') + \ ->substitute('^"\|".*\|\\n', '', 'g') + \ ->substitute('\\t', "\t", 'g') + " multi-byte characters arrive in octal form + " NULL-values must be kept encoded as those break the string otherwise + \ ->substitute('\\000', s:NullRepl, 'g') + \ ->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g') + " Note: GDB docs also mention hex encodings - the translations below work + " but we keep them out for performance-reasons until we actually see + " those in mi-returns + " \ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') + " \ ->substitute('\\0x00', s:NullRepl, 'g') + \ ->substitute('\\\\', '\', 'g') + \ ->substitute(s:NullRepl, '\\000', 'g') endfunc +const s:NullRepl = 'XXXNULLXXX' " Extract the "name" value from a gdb message with fullname="name". func s:GetFullname(msg) @@ -1037,10 +1051,10 @@ func s:GetEvaluationExpression(range, arg) return expr endfunc -" clean up expression that may got in because of range +" clean up expression that may get in because of range " (newlines and surrounding whitespace) " As it can also be specified via ex-command for assignments this function -" may not change the "content" parts (like replacing contained spaces +" may not change the "content" parts (like replacing contained spaces) func s:CleanupExpr(expr) " replace all embedded newlines/tabs/... let expr = substitute(a:expr, '\_s', ' ', 'g') @@ -1066,11 +1080,20 @@ let s:evalFromBalloonExprResult = '' " Handle the result of data-evaluate-expression func s:HandleEvaluate(msg) - let value = substitute(a:msg, '.*value="\(.*\)"', '\1', '') - let value = substitute(value, '\\"', '"', 'g') - " multi-byte characters arrive in octal form - let value = substitute(value, '\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g') - let value = substitute(value, '
', '\1', '') + let value = a:msg + \ ->substitute('.*value="\(.*\)"', '\1', '') + \ ->substitute('\\"', '"', 'g') + \ ->substitute('\\\\', '\\', 'g') + "\ multi-byte characters arrive in octal form, replace everything but NULL values + \ ->substitute('\\000', s:NullRepl, 'g') + \ ->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g') + "\ Note: GDB docs also mention hex encodings - the translations below work + "\ but we keep them out for performance-reasons until we actually see + "\ those in mi-returns + "\ ->substitute('\\0x00', s:NullRep, 'g') + "\ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') + \ ->substitute(s:NullRepl, '\\000', 'g') + \ ->substitute('
', '\1', '') if s:evalFromBalloonExpr if s:evalFromBalloonExprResult == '' let s:evalFromBalloonExprResult = s:evalexpr . ': ' . value @@ -1321,6 +1344,16 @@ func s:HandleCursor(msg) if lnum =~ '^[0-9]*$' call s:GotoSourcewinOrCreateIt() if expand('%:p') != fnamemodify(fname, ':p') + echomsg 'different fname: "' .. expand('%:p') .. '" vs "' .. fnamemodify(fname, ':p') .. '"' + augroup Termdebug + " Always open a file read-only instead of showing the ATTENTION + " prompt, since we are unlikely to want to edit the file. + " The file may be changed but not saved, warn for that. + au SwapExists * echohl WarningMsg + \ | echo 'Warning: file is being edited elsewhere' + \ | echohl None + \ | let v:swapchoice = 'o' + augroup END if &modified " TODO: find existing window exe 'split ' . fnameescape(fname) @@ -1329,6 +1362,9 @@ func s:HandleCursor(msg) else exe 'edit ' . fnameescape(fname) endif + augroup Termdebug + au! SwapExists + augroup END endif exe lnum normal! zv diff --git a/runtime/scripts.vim b/runtime/scripts.vim index 3790b1c10f..dd47f65ba0 100644 --- a/runtime/scripts.vim +++ b/runtime/scripts.vim @@ -384,7 +384,7 @@ else set ft=scheme " Git output - elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$' + elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$' set ft=git " Gprof (gnu profiler) @@ -406,6 +406,12 @@ else elseif s:line1 =~# '^#.*by RouterOS.*$' set ft=routeros + " Sed scripts + " #ncomment is allowed but most likely a false positive so require a space + " before any trailing comment text + elseif s:line1 =~# '^#n\%($\|\s\)' + set ft=sed + " CVS diff else let s:lnum = 1 diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index 20f8632006..e86e1b8669 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: C " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2021 May 24 +" Last Change: 2021 Dec 07 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -196,7 +196,6 @@ syn match cNumber display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>" " Flag the first zero of an octal number as something special syn match cOctal display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=cOctalZero syn match cOctalZero display contained "\<0" -syn match cFloat display contained "\d\+f" "floating point number, with dot, optional exponent syn match cFloat display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\=" "floating point number, starting with a dot, optional exponent diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim new file mode 100644 index 0000000000..37f1822740 --- /dev/null +++ b/runtime/syntax/checkhealth.vim @@ -0,0 +1,30 @@ +" Vim syntax file +" Language: Neovim checkhealth buffer +" Last Change: 2021 Dec 15 + +if exists("b:current_syntax") + finish +endif + +runtime! syntax/markdown.vim +unlet! b:current_syntax + +syn case match + +" We do not care about markdown syntax errors +if hlexists('markdownError') + syn clear markdownError +endif + +syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine +syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine +syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine +syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar +syn match healthBar "|" contained conceal + +hi def link healthError Error +hi def link healthWarning WarningMsg +hi def healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232 +hi def link healthHelp Identifier + +let b:current_syntax = "checkhealth" diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim index 67ad1ea335..564dc151bc 100644 --- a/runtime/syntax/css.vim +++ b/runtime/syntax/css.vim @@ -7,7 +7,7 @@ " Nikolai Weibull (Add CSS2 support) " URL: https://github.com/vim-language-dept/css-syntax.vim " Maintainer: Jay Sitter <jay@jaysitter.com> -" Last Change: 2021 Oct 15 +" Last Change: 2021 Oct 20 " quit when a syntax file was already loaded if !exists("main_syntax") @@ -116,7 +116,7 @@ syn keyword cssColor contained ActiveBorder ActiveCaption AppWorkspace ButtonFac syn case ignore syn match cssImportant contained "!\s*important\>" -syn match cssCustomProp contained "--[a-zA-Z0-9-_]*" +syn match cssCustomProp contained "\<--[a-zA-Z0-9-_]*\>" syn match cssColor contained "\<transparent\>" syn match cssColor contained "\<currentColor\>" @@ -126,6 +126,7 @@ syn match cssColor contained "#\x\{6\}\>" contains=cssUnitDecorators syn match cssColor contained "#\x\{8\}\>" contains=cssUnitDecorators syn region cssURL contained matchgroup=cssFunctionName start="\<\(uri\|url\|local\|format\)\s*(" end=")" contains=cssStringQ,cssStringQQ oneline +syn region cssMathGroup contained matchgroup=cssMathParens start="(" end=")" containedin=cssFunction,cssMathGroup contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ oneline syn region cssFunction contained matchgroup=cssFunctionName start="\<\(var\|calc\)\s*(" end=")" contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ oneline syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\|cubic-bezier\|steps\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgba\|hsl\|hsla\|color-stop\|from\|to\)\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma,cssFunction @@ -395,9 +396,9 @@ syn match cssUIAttr contained '\<preserve-3d\>' syn match cssIEUIAttr contained '\<bicubic\>' " Webkit/iOS specific properties -syn match cssUIProp contained '\<tap-highlight-color\|user-select\|touch-callout\>' +syn match cssUIProp contained '\<\(tap-highlight-color\|user-select\|touch-callout\)\>' " IE specific properties -syn match cssIEUIProp contained '\<interpolation-mode\|zoom\|filter\>' +syn match cssIEUIProp contained '\<\(interpolation-mode\|zoom\|filter\)\>' " Webkit/Firebox specific properties/attributes syn keyword cssUIProp contained appearance @@ -423,11 +424,15 @@ syn keyword cssAuralAttr contained male female child code digits continuous syn match cssMobileTextProp contained "\<text-size-adjust\>" syn keyword cssMediaProp contained width height orientation scan -syn match cssMediaProp contained /\(\(max\|min\)-\)\=\(\(device\)-\)\=aspect-ratio/ -syn match cssMediaProp contained /\(\(max\|min\)-\)\=device-pixel-ratio/ -syn match cssMediaProp contained /\(\(max\|min\)-\)\=device-\(height\|width\)/ -syn match cssMediaProp contained /\(\(max\|min\)-\)\=\(height\|width\|resolution\|monochrome\|color\(-index\)\=\)/ +syn keyword cssMediaProp contained any-hover any-pointer color-gamut grid hover +syn keyword cssMediaProp contained overflow-block overflow-inline pointer update +syn match cssMediaProp contained /\<\(\(max\|min\)-\)\=\(\(device\)-\)\=aspect-ratio\>/ +syn match cssMediaProp contained /\<\(\(max\|min\)-\)\=device-pixel-ratio\>/ +syn match cssMediaProp contained /\<\(\(max\|min\)-\)\=device-\(height\|width\)\>/ +syn match cssMediaProp contained /\<\(\(max\|min\)-\)\=\(height\|width\|resolution\|monochrome\|color\(-index\)\=\)\>/ syn keyword cssMediaAttr contained portrait landscape progressive interlace +syn keyword cssMediaAttr contained coarse fast fine hover infinite p3 paged +syn keyword cssMediaAttr contained rec2020 scroll slow srgb syn match cssKeyFrameProp contained /\(\d\+\(\.\d\+\)\?%\|\(\<from\|to\>\)\)/ nextgroup=cssDefinition syn match cssPageMarginProp /@\(\(top\|left\|right\|bottom\)-\(left\|center\|right\|middle\|bottom\)\)\(-corner\)\=/ contained nextgroup=cssDefinition syn keyword cssPageProp contained content size @@ -445,17 +450,17 @@ syn match cssBraceError "}" syn match cssAttrComma "," " Pseudo class -" http://www.w3.org/TR/css3-selectors/ +" https://www.w3.org/TR/selectors-4/ syn match cssPseudoClass ":[A-Za-z0-9_-]*" contains=cssNoise,cssPseudoClassId,cssUnicodeEscape,cssVendor,cssPseudoClassFn syn keyword cssPseudoClassId contained link visited active hover before after left right -syn keyword cssPseudoClassId contained root empty target enable disabled checked invalid +syn keyword cssPseudoClassId contained root empty target enabled disabled checked invalid syn match cssPseudoClassId contained "\<first-\(line\|letter\)\>" syn match cssPseudoClassId contained "\<\(first\|last\|only\)-\(of-type\|child\)\>" -syn region cssPseudoClassFn contained matchgroup=cssFunctionName start="\<\(not\|lang\|\(nth\|nth-last\)-\(of-type\|child\)\)(" end=")" contains=cssStringQ,cssStringQQ +syn match cssPseudoClassId contained "\<focus\(-within\|-visible\)\=\>" +syn region cssPseudoClassFn contained matchgroup=cssFunctionName start="\<\(not\|is\|lang\|\(nth\|nth-last\)-\(of-type\|child\)\)(" end=")" contains=cssStringQ,cssStringQQ,cssTagName,cssAttributeSelector,cssClassName,cssIdentifier " ------------------------------------ " Vendor specific properties syn match cssPseudoClassId contained "\<selection\>" -syn match cssPseudoClassId contained "\<focus\(-inner\)\=\>" syn match cssPseudoClassId contained "\<\(input-\)\=placeholder\>" " Misc highlight groups diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim index 25fc252de6..8b65ece4ca 100644 --- a/runtime/syntax/debcontrol.vim +++ b/runtime/syntax/debcontrol.vim @@ -3,7 +3,7 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Gerfried Fuchs <alfie@ist.org> " Wichert Akkerman <wakkerma@debian.org> -" Last Change: 2020 Oct 26 +" Last Change: 2021 Nov 26 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debcontrol.vim " Standard syntax initialization @@ -91,6 +91,11 @@ syn case ignore " Handle all fields from deb-src-control(5) +" Catch-all for the legal fields +syn region debcontrolField matchgroup=debcontrolKey start="^\%(\%(XSBC-Original-\)\=Maintainer\|Standards-Version\|Bugs\|Origin\|X[SB]-Python-Version\|\%(XS-\)\=Vcs-Mtn\|\%(XS-\)\=Testsuite\%(-Triggers\)\=\|Build-Profiles\|Tag\|Subarchitecture\|Kernel-Version\|Installer-Menu-Item\): " end="$" contains=debcontrolVariable,debcontrolEmail oneline +syn region debcontrolMultiField matchgroup=debcontrolKey start="^\%(Build-\%(Conflicts\|Depends\)\%(-Arch\|-Indep\)\=\|\%(Pre-\)\=Depends\|Recommends\|Suggests\|Breaks\|Enhances\|Replaces\|Conflicts\|Provides\|Built-Using\|Uploaders\|X[SBC]\{0,3\}\%(Private-\)\=-[-a-zA-Z0-9]\+\): *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment +syn region debcontrolMultiFieldSpell matchgroup=debcontrolKey start="^Description: *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment,@Spell + " Fields for which we do strict syntax checking syn region debcontrolStrictField matchgroup=debcontrolKey start="^Architecture: *" end="$" contains=debcontrolArchitecture,debcontrolSpace oneline syn region debcontrolStrictField matchgroup=debcontrolKey start="^Multi-Arch: *" end="$" contains=debcontrolMultiArch oneline @@ -99,20 +104,15 @@ syn region debcontrolStrictField matchgroup=debcontrolKey start="^Priority: *" e syn region debcontrolStrictField matchgroup=debcontrolKey start="^Section: *" end="$" contains=debcontrolSection oneline syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XC-\)\=Package-Type: *" end="$" contains=debcontrolPackageType oneline syn region debcontrolStrictField matchgroup=debcontrolKey start="^Homepage: *" end="$" contains=debcontrolHTTPUrl oneline keepend -syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-\)\=Vcs-\%(Browser\|Arch\|Bzr\|Darcs\|Hg\): *" end="$" contains=debcontrolHTTPUrl oneline keepend -syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-\)\=Vcs-Svn: *" end="$" contains=debcontrolVcsSvn,debcontrolHTTPUrl oneline keepend -syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-\)\=Vcs-Cvs: *" end="$" contains=debcontrolVcsCvs oneline keepend -syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-\)\=Vcs-Git: *" end="$" contains=debcontrolVcsGit oneline keepend +syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-[-a-zA-Z0-9]\+-\)\=Vcs-\%(Browser\|Arch\|Bzr\|Darcs\|Hg\): *" end="$" contains=debcontrolHTTPUrl oneline keepend +syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-[-a-zA-Z0-9]\+-\)\=Vcs-Svn: *" end="$" contains=debcontrolVcsSvn,debcontrolHTTPUrl oneline keepend +syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-[-a-zA-Z0-9]\+-\)\=Vcs-Cvs: *" end="$" contains=debcontrolVcsCvs oneline keepend +syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(XS-[-a-zA-Z0-9]\+-\)\=Vcs-Git: *" end="$" contains=debcontrolVcsGit oneline keepend syn region debcontrolStrictField matchgroup=debcontrolKey start="^Rules-Requires-Root: *" end="$" contains=debcontrolR3 oneline syn region debcontrolStrictField matchgroup=debcontrolKey start="^\%(Build-\)\=Essential: *" end="$" contains=debcontrolYesNo oneline syn region debcontrolStrictField matchgroup=debcontrolDeprecatedKey start="^\%(XS-\)\=DM-Upload-Allowed: *" end="$" contains=debcontrolDmUpload oneline -" Catch-all for the other legal fields -syn region debcontrolField matchgroup=debcontrolKey start="^\%(\%(XSBC-Original-\)\=Maintainer\|Standards-Version\|Bugs\|Origin\|X[SB]-Python-Version\|\%(XS-\)\=Vcs-Mtn\|\%(XS-\)\=Testsuite\%(-Triggers\)\=\|Build-Profiles\|Tag\|Subarchitecture\|Kernel-Version\|Installer-Menu-Item\): " end="$" contains=debcontrolVariable,debcontrolEmail oneline -syn region debcontrolMultiField matchgroup=debcontrolKey start="^\%(Build-\%(Conflicts\|Depends\)\%(-Arch\|-Indep\)\=\|\%(Pre-\)\=Depends\|Recommends\|Suggests\|Breaks\|Enhances\|Replaces\|Conflicts\|Provides\|Built-Using\|Uploaders\|X[SBC]\{0,3\}\%(Private-\)\=-[-a-zA-Z0-9]\+\): *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment -syn region debcontrolMultiFieldSpell matchgroup=debcontrolKey start="^Description: *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment,@Spell - " Associate our matches and regions with pretty colours hi def link debcontrolKey Keyword hi def link debcontrolField Normal diff --git a/runtime/syntax/dep3patch.vim b/runtime/syntax/dep3patch.vim new file mode 100644 index 0000000000..8b2cee629c --- /dev/null +++ b/runtime/syntax/dep3patch.vim @@ -0,0 +1,57 @@ +" Vim syntax file +" Language: Debian DEP3 Patch headers +" Maintainer: Gabriel Filion <gabster@lelutin.ca> +" Last Change: 2021-01-09 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/dep3patch.vim +" +" Specification of the DEP3 patch header format is available at: +" https://dep-team.pages.debian.net/deps/dep3/ + +" Standard syntax initialization +if exists('b:current_syntax') + finish +endif + +runtime! syntax/diff.vim +unlet! b:current_syntax + +let s:cpo_save = &cpo +set cpo&vim + +syn region dep3patchHeaders start="\%^" end="^\%(---\)\@=" contains=dep3patchKey,dep3patchMultiField + +syn case ignore + +syn region dep3patchMultiField matchgroup=dep3patchKey start="^\%(Description\|Subject\)\ze: *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contained contains=@Spell +syn region dep3patchMultiField matchgroup=dep3patchKey start="^Origin\ze: *" end="$" contained contains=dep3patchHTTPUrl,dep3patchCommitID,dep3patchOriginCategory oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^Bug\%(-[[:graph:]]\+\)\?\ze: *" end="$" contained contains=dep3patchHTTPUrl oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^Forwarded\ze: *" end="$" contained contains=dep3patchHTTPUrl,dep3patchForwardedShort oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^\%(Author\|From\)\ze: *" end="$" contained contains=dep3patchEmail oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^\%(Reviewed-by\|Acked-by\)\ze: *" end="$" contained contains=dep3patchEmail oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^Last-Updated\ze: *" end="$" contained contains=dep3patchISODate oneline keepend +syn region dep3patchMultiField matchgroup=dep3patchKey start="^Applied-Upstream\ze: *" end="$" contained contains=dep3patchHTTPUrl,dep3patchCommitID oneline keepend + +syn match dep3patchHTTPUrl contained "\vhttps?://[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?(:\d+)?(/[^[:space:]]*)?$" +syn match dep3patchCommitID contained "commit:[[:alnum:]]\+" +syn match dep3patchOriginCategory contained "\%(upstream\|backport\|vendor\|other\), " +syn match dep3patchForwardedShort contained "\%(yes\|no\|not-needed\), " +syn match dep3patchEmail "[_=[:alnum:]\.+-]\+@[[:alnum:]\./\-]\+" +syn match dep3patchEmail "<.\{-}>" +syn match dep3patchISODate "[[:digit:]]\{4}-[[:digit:]]\{2}-[[:digit:]]\{2}" + +" Associate our matches and regions with pretty colours +hi def link dep3patchKey Keyword +hi def link dep3patchOriginCategory Keyword +hi def link dep3patchForwardedShort Keyword +hi def link dep3patchMultiField Normal +hi def link dep3patchHTTPUrl Identifier +hi def link dep3patchCommitID Identifier +hi def link dep3patchEmail Identifier +hi def link dep3patchISODate Identifier + +let b:current_syntax = 'dep3patch' + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: ts=8 sw=2 diff --git a/runtime/syntax/dtd.vim b/runtime/syntax/dtd.vim index ef0592e1d1..58f07c98dd 100644 --- a/runtime/syntax/dtd.vim +++ b/runtime/syntax/dtd.vim @@ -45,7 +45,7 @@ if !exists("dtd_no_tag_errors") syn region dtdError contained start=+<!+lc=2 end=+>+ endif -" if this is a html like comment hightlight also +" if this is a html like comment highlight also " the opening <! and the closing > as Comment. syn region dtdComment start=+<![ \t]*--+ end=+-->+ contains=dtdTodo,@Spell @@ -99,8 +99,8 @@ syn match dtdEntity "&[^; \t]*;" contains=dtdEntityPunct syn match dtdEntityPunct contained "[&.;]" " Strings are between quotes -syn region dtdString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=dtdAttrDef,dtdAttrType,dtdEnum,dtdParamEntityInst,dtdEntity,dtdCard -syn region dtdString start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=dtdAttrDef,dtdAttrType,dtdEnum,dtdParamEntityInst,dtdEntity,dtdCard +syn region dtdString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=dtdAttrDef,dtdAttrType,dtdParamEntityInst,dtdEntity,dtdCard +syn region dtdString start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=dtdAttrDef,dtdAttrType,dtdParamEntityInst,dtdEntity,dtdCard " Enumeration of elements or data between parenthesis " diff --git a/runtime/syntax/git.vim b/runtime/syntax/git.vim index a8467edd43..bf013ce195 100644 --- a/runtime/syntax/git.vim +++ b/runtime/syntax/git.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: generic git output " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2019 Dec 05 +" Last Change: 2022 Jan 05 if exists("b:current_syntax") finish @@ -12,12 +12,28 @@ syn sync minlines=50 syn include @gitDiff syntax/diff.vim -syn region gitHead start=/\%^/ end=/^$/ -syn region gitHead start=/\%(^commit\%( \x\{40\}\)\{1,\}\%(\s*(.*)\)\=$\)\@=/ end=/^$/ - -" For git reflog and git show ...^{tree}, avoid sync issues -syn match gitHead /^\d\{6\} \%(\w\{4} \)\=\x\{40\}\%( [0-3]\)\=\t.*/ -syn match gitHead /^\x\{40\} \x\{40}\t.*/ +syn region gitHead start=/\%^\%(tag \|tree \|object \)\@=/ end=/^$/ contains=@NoSpell +syn region gitHead start=/\%(^commit\%( \x\{4,\}\)\{1,\}\%(\s*(.*)\)\=$\)\@=/ end=/^$/ contains=@NoSpell +" git log --oneline +" minimize false positives by verifying contents of buffer +if getline(1) =~# '^\x\{7,\} ' && getline('$') =~# '^\x\{7,\} ' + syn match gitHashAbbrev /^\x\{7,\} \@=/ contains=@NoSpell +elseif getline(1) =~# '^[|\/\\_ ]\{-\}\*[|\/\\_ ]\{-\} \x\{7,\} ' + syn match gitHashAbbrev /^[|\/\\_ ]\{-\}\*[|\/\\_ ]\{-\} \zs\x\{7,\} \@=/ contains=@NoSpell +endif +" git log --graph +syn region gitGraph start=/\%(^[|\/\\_ ]*\*[|\/\\_ ]\{-\} commit\%( \x\{4,\}\)\{1,\}\%(\s*(.*)\)\=$\)\@=/ end=/^\%([|\/\\_ ]*$\)\@=/ contains=@NoSpell +" git blame --porcelain +syn region gitHead start=/\%(^\x\{40,\} \d\+ \d\+\%( \d\+\)\=$\)\@=/ end=/^\t\@=/ contains=@NoSpell +" git ls-tree +syn match gitMode /^\d\{6\}\%( \%(blob\|tree\) \x\{4,\}\t\)\@=/ nextgroup=gitType skipwhite contains=@NoSpell +" git ls-files --stage +syn match gitMode /^\d\{6\}\%( \x\{4,\} [0-3]\t\)\@=/ nextgroup=gitHashStage skipwhite contains=@NoSpell +" .git/HEAD, .git/refs/ +syn match gitKeyword /\%^ref: \@=/ nextgroup=gitReference skipwhite contains=@NoSpell +syn match gitHash /\%^\x\{40,}\%$/ skipwhite contains=@NoSpell +" .git/logs/ +syn match gitReflog /^\x\{40,\} \x\{40,\} .\{-\}\d\+\s-\d\{4\}\t.*/ skipwhite contains=@NoSpell,gitReflogOld syn region gitDiff start=/^\%(diff --git \)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff fold syn region gitDiff start=/^\%(@@ -\)\@=/ end=/^\%(diff --\%(git\|cc\|combined\) \|$\)\@=/ contains=@gitDiff @@ -25,35 +41,47 @@ syn region gitDiff start=/^\%(@@ -\)\@=/ end=/^\%(diff --\%(git\|cc\|combined\) syn region gitDiffMerge start=/^\%(diff --\%(cc\|combined\) \)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff syn region gitDiffMerge start=/^\%(@@@@* -\)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff syn match gitDiffAdded "^ \++.*" contained containedin=gitDiffMerge -syn match gitDiffAdded "{+.*+}" contained containedin=gitDiff +syn match gitDiffAdded "{+[^}]*+}" contained containedin=gitDiff syn match gitDiffRemoved "^ \+-.*" contained containedin=gitDiffMerge -syn match gitDiffRemoved "\[-.*-\]" contained containedin=gitDiff +syn match gitDiffRemoved "\[-[^]]*-\]" contained containedin=gitDiff + +syn match gitKeyword /^commit \@=/ contained containedin=gitHead nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitKeyword /^\%(object\|tree\|parent\|encoding\|gpgsig\%(-\w\+\)\=\|previous\) \@=/ contained containedin=gitHead nextgroup=gitHash skipwhite contains=@NoSpell +syn match gitKeyword /^Merge:/ contained containedin=gitHead nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitIdentityKeyword /^\%(author\|committer\|tagger\) \@=/ contained containedin=gitHead nextgroup=gitIdentity skipwhite contains=@NoSpell +syn match gitIdentityHeader /^\%(Author\|Commit\|Tagger\):/ contained containedin=gitHead nextgroup=gitIdentity skipwhite contains=@NoSpell +syn match gitDateHeader /^\%(AuthorDate\|CommitDate\|Date\):/ contained containedin=gitHead nextgroup=gitDate skipwhite contains=@NoSpell -syn match gitKeyword /^\%(object\|type\|tag\|commit\|tree\|parent\|encoding\)\>/ contained containedin=gitHead nextgroup=gitHash,gitType skipwhite -syn match gitKeyword /^\%(tag\>\|ref:\)/ contained containedin=gitHead nextgroup=gitReference skipwhite -syn match gitKeyword /^Merge:/ contained containedin=gitHead nextgroup=gitHashAbbrev skipwhite -syn match gitMode /^\d\{6\}\>/ contained containedin=gitHead nextgroup=gitType,gitHash skipwhite -syn match gitIdentityKeyword /^\%(author\|committer\|tagger\)\>/ contained containedin=gitHead nextgroup=gitIdentity skipwhite -syn match gitIdentityHeader /^\%(Author\|Commit\|Tagger\):/ contained containedin=gitHead nextgroup=gitIdentity skipwhite -syn match gitDateHeader /^\%(AuthorDate\|CommitDate\|Date\):/ contained containedin=gitHead nextgroup=gitDate skipwhite +syn match gitKeyword /^[*|\/\\_ ]\+\zscommit \@=/ contained containedin=gitGraph nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitKeyword /^[|\/\\_ ]\+\zs\%(object\|tree\|parent\|encoding\|gpgsig\%(-\w\+\)\=\|previous\) \@=/ contained containedin=gitGraph nextgroup=gitHash skipwhite contains=@NoSpell +syn match gitKeyword /^[|\/\\_ ]\+\zsMerge:/ contained containedin=gitGraph nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitIdentityKeyword /^[|\/\\_ ]\+\zs\%(author\|committer\|tagger\) \@=/ contained containedin=gitGraph nextgroup=gitIdentity skipwhite contains=@NoSpell +syn match gitIdentityHeader /^[|\/\\_ ]\+\zs\%(Author\|Commit\|Tagger\):/ contained containedin=gitGraph nextgroup=gitIdentity skipwhite contains=@NoSpell +syn match gitDateHeader /^[|\/\\_ ]\+\zs\%(AuthorDate\|CommitDate\|Date\):/ contained containedin=gitGraph nextgroup=gitDate skipwhite contains=@NoSpell -syn match gitReflogHeader /^Reflog:/ contained containedin=gitHead nextgroup=gitReflogMiddle skipwhite -syn match gitReflogHeader /^Reflog message:/ contained containedin=gitHead skipwhite -syn match gitReflogMiddle /\S\+@{\d\+} (/he=e-2 nextgroup=gitIdentity +syn match gitKeyword /^type \@=/ contained containedin=gitHead nextgroup=gitType skipwhite contains=@NoSpell +syn match gitKeyword /^\%(summary\|boundary\|filename\|\%(author\|committer\)-\%(time\|tz\)\) \@=/ contained containedin=gitHead skipwhite contains=@NoSpell +syn match gitKeyword /^tag \@=/ contained containedin=gitHead nextgroup=gitReference skipwhite contains=@NoSpell +syn match gitIdentityKeyword /^\%(author\|committer\)-mail \@=/ contained containedin=gitHead nextgroup=gitEmail skipwhite contains=@NoSpell +syn match gitReflogHeader /^Reflog:/ contained containedin=gitHead nextgroup=gitReflogMiddle skipwhite contains=@NoSpell +syn match gitReflogHeader /^Reflog message:/ contained containedin=gitHead skipwhite contains=@NoSpell +syn match gitReflogMiddle /\S\+@{\d\+} (/he=e-2 nextgroup=gitIdentity contains=@NoSpell -syn match gitDate /\<\u\l\l \u\l\l \d\=\d \d\d:\d\d:\d\d \d\d\d\d [+-]\d\d\d\d/ contained -syn match gitDate /-\=\d\+ [+-]\d\d\d\d\>/ contained -syn match gitDate /\<\d\+ \l\+ ago\>/ contained -syn match gitType /\<\%(tag\|commit\|tree\|blob\)\>/ contained nextgroup=gitHash skipwhite -syn match gitStage /\<\d\t\@=/ contained -syn match gitReference /\S\+\S\@!/ contained -syn match gitHash /\<\x\{40\}\>/ contained nextgroup=gitIdentity,gitStage,gitHash skipwhite -syn match gitHash /^\<\x\{40\}\>/ containedin=gitHead contained nextgroup=gitHash skipwhite -syn match gitHashAbbrev /\<\x\{4,40\}\>/ contained nextgroup=gitHashAbbrev skipwhite -syn match gitHashAbbrev /\<\x\{4,39\}\.\.\./he=e-3 contained nextgroup=gitHashAbbrev skipwhite +syn match gitIdentity /\S.\{-\} <[^>]*>/ contained nextgroup=gitDate skipwhite contains=@NoSpell +syn region gitEmail matchgroup=gitEmailDelimiter start=/</ end=/>/ keepend oneline contained containedin=gitIdentity contains=@NoSpell +syn match gitDate /\<\u\l\l \u\l\l \d\=\d \d\d:\d\d:\d\d \d\d\d\d [+-]\d\d\d\d/ contained contains=@NoSpell +syn match gitDate /-\=\d\+ [+-]\d\d\d\d\>/ contained contains=@NoSpell +syn match gitDate /\<\d\+ \l\+ ago\>/ contained contains=@NoSpell +syn match gitType /\<\%(tag\|commit\|tree\|blob\)\>/ contained nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitReference /\S\+\S\@!/ contained contains=@NoSpell +syn match gitHash /\<\x\{40,\}\>/ contained nextgroup=gitIdentity,gitHash skipwhite contains=@NoSpell +syn match gitReflogOld /^\x\{40,\} \@=/ contained nextgroup=gitReflogNew skipwhite contains=@NoSpell +syn match gitReflogNew /\<\x\{40,\} \@=/ contained nextgroup=gitIdentity skipwhite contains=@NoSpell +syn match gitHashAbbrev /\<\x\{4,\}\>/ contained nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitHashAbbrev /\<\x\{4,39\}\.\.\./he=e-3 contained nextgroup=gitHashAbbrev skipwhite contains=@NoSpell +syn match gitHashStage /\<\x\{4,\}\>/ contained nextgroup=gitStage skipwhite contains=@NoSpell +syn match gitStage /\<\d\t\@=/ contained contains=@NoSpell -syn match gitIdentity /\S.\{-\} <[^>]*>/ contained nextgroup=gitDate skipwhite -syn region gitEmail matchgroup=gitEmailDelimiter start=/</ end=/>/ keepend oneline contained containedin=gitIdentity syn match gitNotesHeader /^Notes:\ze\n / @@ -68,7 +96,10 @@ hi def link gitEmailDelimiter Delimiter hi def link gitEmail Special hi def link gitDate Number hi def link gitMode Number +hi def link gitHashStage gitHash hi def link gitHashAbbrev gitHash +hi def link gitReflogOld gitHash +hi def link gitReflogNew gitHash hi def link gitHash Identifier hi def link gitReflogMiddle gitReference hi def link gitReference Function diff --git a/runtime/syntax/gitcommit.vim b/runtime/syntax/gitcommit.vim index 63b1ce920f..42c8d4414f 100644 --- a/runtime/syntax/gitcommit.vim +++ b/runtime/syntax/gitcommit.vim @@ -2,71 +2,87 @@ " Language: git commit file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: *.git/COMMIT_EDITMSG -" Last Change: 2019 Dec 05 +" Last Change: 2022 Jan 05 if exists("b:current_syntax") finish endif +scriptencoding utf-8 + syn case match syn sync minlines=50 +syn sync linebreaks=1 if has("spell") syn spell toplevel endif syn include @gitcommitDiff syntax/diff.vim -syn region gitcommitDiff start=/\%(^diff --\%(git\|cc\|combined\) \)\@=/ end=/^\%(diff --\|$\|#\)\@=/ fold contains=@gitcommitDiff +syn region gitcommitDiff start=/\%(^diff --\%(git\|cc\|combined\) \)\@=/ end=/^\%(diff --\|$\|@@\@!\|[^[:alnum:]\ +-]\S\@!\)\@=/ fold contains=@gitcommitDiff syn match gitcommitSummary "^.*\%<51v." contained containedin=gitcommitFirstLine nextgroup=gitcommitOverflow contains=@Spell syn match gitcommitOverflow ".*" contained contains=@Spell -syn match gitcommitBlank "^[^#].*" contained contains=@Spell +syn match gitcommitBlank "^.\+" contained contains=@Spell +syn match gitcommitFirstLine "\%^.*" nextgroup=gitcommitBlank,gitcommitComment skipnl + +let s:scissors = 0 +let s:l = search('^[#;@!$%^&|:] -\{24,\} >8 -\{24,\}$', 'cnW', '', 100) +if s:l == 0 + let s:l = line('$') +elseif getline(s:l)[0] !=# getline(s:l - 1)[0] + let s:scissors = 1 +endif +let s:comment = escape((matchstr(getline(s:l), '^[#;@!$%^&|:]\S\@!') . '#')[0], '^$.*[]~\"/') -if get(g:, "gitcommit_cleanup") is# "scissors" - syn match gitcommitFirstLine "\%^.*" nextgroup=gitcommitBlank skipnl - syn region gitcommitComment start=/^# -\+ >8 -\+$/ end=/\%$/ contains=gitcommitDiff +if s:scissors + let s:comment .= ' -\{24,\} >8 -\{24,\}$' + exe 'syn region gitcommitComment start="^' . s:comment . '" end="\%$" contains=gitcommitDiff' else - syn match gitcommitFirstLine "\%^[^#].*" nextgroup=gitcommitBlank skipnl - syn match gitcommitComment "^#.*" + exe 'syn match gitcommitComment "^' . s:comment . '.*"' endif +exe 'syn match gitcommitTrailers "\n\@<=\n\%([[:alnum:]-]\+\s*:.*\|(cherry picked from commit .*\)\%(\n\s.*\|\n[[:alnum:]-]\+\s*:.*\|\n(cherry picked from commit .*\)*\%(\n\n*\%(' . s:comment . '\)\|\n*\%$\)\@="' -syn match gitcommitHead "^\%(# .*\n\)\+#$" contained transparent -syn match gitcommitOnBranch "\%(^# \)\@<=On branch" contained containedin=gitcommitComment nextgroup=gitcommitBranch skipwhite -syn match gitcommitOnBranch "\%(^# \)\@<=Your branch .\{-\} '" contained containedin=gitcommitComment nextgroup=gitcommitBranch skipwhite +unlet s:l s:comment s:scissors + +syn match gitcommitTrailerToken "^[[:alnum:]-]\+\s*:" contained containedin=gitcommitTrailers + +syn match gitcommitHash "\<\x\{40,}\>" contains=@NoSpell display +syn match gitcommitOnBranch "\%(^. \)\@<=On branch" contained containedin=gitcommitComment nextgroup=gitcommitBranch skipwhite +syn match gitcommitOnBranch "\%(^. \)\@<=Your branch .\{-\} '" contained containedin=gitcommitComment nextgroup=gitcommitBranch skipwhite syn match gitcommitBranch "[^ ']\+" contained -syn match gitcommitNoBranch "\%(^# \)\@<=Not currently on any branch." contained containedin=gitcommitComment -syn match gitcommitHeader "\%(^# \)\@<=.*:$" contained containedin=gitcommitComment -syn region gitcommitAuthor matchgroup=gitCommitHeader start=/\%(^# \)\@<=\%(Author\|Committer\):/ end=/$/ keepend oneline contained containedin=gitcommitComment transparent -syn match gitcommitNoChanges "\%(^# \)\@<=No changes$" contained containedin=gitcommitComment +syn match gitcommitNoBranch "\%(^. \)\@<=Not currently on any branch." contained containedin=gitcommitComment +syn match gitcommitHeader "\%(^. \)\@<=\S.*[::]\%(\n^$\)\@!$" contained containedin=gitcommitComment +syn region gitcommitAuthor matchgroup=gitCommitHeader start=/\%(^. \)\@<=\%(Author\|Committer\|Date\):/ end=/$/ keepend oneline contained containedin=gitcommitComment transparent +syn match gitcommitHeader "\%(^. \)\@<=commit\%( \x\{40,\}$\)\@=" contained containedin=gitcommitComment nextgroup=gitcommitHash skipwhite +syn match gitcommitNoChanges "\%(^. \)\@<=No changes$" contained containedin=gitcommitComment -syn region gitcommitUntracked start=/^# Untracked files:/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitUntrackedFile fold -syn match gitcommitUntrackedFile "\t\@<=.*" contained +syn match gitcommitType "\%(^.\t\)\@<=[^[:punct:][:space:]][^/::]*[^[:punct:][:space:]][::]\ze "he=e-1 contained containedin=gitcommitComment nextgroup=gitcommitFile skipwhite +syn match gitcommitFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitArrow +syn match gitcommitArrow " -> " contained nextgroup=gitcommitFile +syn match gitcommitUntrackedFile "\%(^.\t\)\@<=[^::/]*\%(/.*\)\=$" contained containedin=gitcommitComment -syn region gitcommitDiscarded start=/^# Change\%(s not staged for commit\|d but not updated\):/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitDiscardedType fold -syn region gitcommitSelected start=/^# Changes to be committed:/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitSelectedType fold -syn region gitcommitUnmerged start=/^# Unmerged paths:/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitUnmergedType fold +syn region gitcommitUntracked start=/^\z(.\) Untracked files:$/ end=/^\z1\=$\|^\z1\@!/ contains=gitcommitHeader containedin=gitcommitComment containedin=gitcommitComment contained transparent fold +syn region gitcommitDiscarded start=/^\z(.\) Change\%(s not staged for commit\|d but not updated\):$/ end=/^\z1\=$\|^\z1\@!/ contains=gitcommitHeader,gitcommitDiscardedType containedin=gitcommitComment containedin=gitcommitComment contained transparent fold +syn region gitcommitSelected start=/^\z(.\) Changes to be committed:$/ end=/^\z1$\|^\z1\@!/ contains=gitcommitHeader,gitcommitSelectedType containedin=gitcommitComment containedin=gitcommitComment contained transparent fold +syn region gitcommitUnmerged start=/^\z(.\) Unmerged paths:$/ end=/^\z1\=$\|^\z1\@!/ contains=gitcommitHeader,gitcommitUnmergedType containedin=gitcommitComment containedin=gitcommitComment contained transparent fold +syn match gitcommitUntrackedFile "\%(^.\t\)\@<=.*" contained containedin=gitcommitUntracked -syn match gitcommitDiscardedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitDiscardedFile skipwhite -syn match gitcommitSelectedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitSelectedFile skipwhite -syn match gitcommitUnmergedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitUnmergedFile skipwhite -syn match gitcommitDiscardedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitDiscardedArrow -syn match gitcommitSelectedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitSelectedArrow -syn match gitcommitUnmergedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitSelectedArrow +syn match gitcommitDiscardedType "\%(^.\t\)\@<=[^[:punct:][:space:]][^/::]*[^[:punct:][:space:]][::]\ze "he=e-1 contained nextgroup=gitcommitDiscardedFile skipwhite +syn match gitcommitSelectedType "\%(^.\t\)\@<=[^[:punct:][:space:]][^/::]*[^[:punct:][:space:]][::]\ze "he=e-1 contained nextgroup=gitcommitSelectedFile skipwhite +syn match gitcommitUnmergedType "\%(^.\t\)\@<=[^[:punct:][:space:]][^/::]*[^[:punct:][:space:]][::]\ze "he=e-1 contained nextgroup=gitcommitUnmergedFile skipwhite +syn match gitcommitDiscardedFile "\S.\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitDiscardedArrow +syn match gitcommitSelectedFile "\S.\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitSelectedArrow +syn match gitcommitUnmergedFile "\S.\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitUnmergedArrow syn match gitcommitDiscardedArrow " -> " contained nextgroup=gitcommitDiscardedFile syn match gitcommitSelectedArrow " -> " contained nextgroup=gitcommitSelectedFile -syn match gitcommitUnmergedArrow " -> " contained nextgroup=gitcommitSelectedFile - -syn match gitcommitWarning "\%^[^#].*: needs merge$" nextgroup=gitcommitWarning skipnl -syn match gitcommitWarning "^[^#].*: needs merge$" nextgroup=gitcommitWarning skipnl contained -syn match gitcommitWarning "^\%(no changes added to commit\|nothing \%(added \)\=to commit\)\>.*\%$" +syn match gitcommitUnmergedArrow " -> " contained nextgroup=gitcommitUnmergedFile hi def link gitcommitSummary Keyword +hi def link gitcommitTrailerToken Label hi def link gitcommitComment Comment -hi def link gitcommitUntracked gitcommitComment -hi def link gitcommitDiscarded gitcommitComment -hi def link gitcommitSelected gitcommitComment -hi def link gitcommitUnmerged gitcommitComment +hi def link gitcommitHash Identifier hi def link gitcommitOnBranch Comment hi def link gitcommitBranch Special hi def link gitcommitNoBranch gitCommitBranch diff --git a/runtime/syntax/gitrebase.vim b/runtime/syntax/gitrebase.vim index bc6f34d1a7..13f157b005 100644 --- a/runtime/syntax/gitrebase.vim +++ b/runtime/syntax/gitrebase.vim @@ -2,7 +2,7 @@ " Language: git rebase --interactive " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: git-rebase-todo -" Last Change: 2019 Dec 06 +" Last Change: 2022 Jan 05 if exists("b:current_syntax") finish @@ -10,8 +10,10 @@ endif syn case match -syn match gitrebaseHash "\v<\x{7,}>" contained -syn match gitrebaseCommit "\v<\x{7,}>" nextgroup=gitrebaseSummary skipwhite +let s:c = escape((matchstr(getline('$'), '^[#;@!$%^&|:]\S\@!') . '#')[0], '^$.*[]~\"/') + +syn match gitrebaseHash "\v<\x{7,}>" contained contains=@NoSpell +syn match gitrebaseCommit "\v<\x{7,}>" nextgroup=gitrebaseSummary skipwhite contains=@NoSpell syn match gitrebasePick "\v^p%(ick)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseReword "\v^r%(eword)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseEdit "\v^e%(dit)=>" nextgroup=gitrebaseCommit skipwhite @@ -26,12 +28,15 @@ syn match gitrebaseLabel "\v^l(abel)=>" nextgroup=gitrebaseName skipwhite syn match gitrebaseReset "\v^(t|reset)=>" nextgroup=gitrebaseName skipwhite syn match gitrebaseSummary ".*" contains=gitrebaseHash contained syn match gitrebaseCommand ".*" contained -syn match gitrebaseComment "^\s*#.*" contains=gitrebaseHash +exe 'syn match gitrebaseComment " \@<=' . s:c . ' empty$" containedin=gitrebaseSummary contained' +exe 'syn match gitrebaseComment "^\s*' . s:c . '.*" contains=gitrebaseHash' syn match gitrebaseSquashError "\v%^%(s%(quash)=>|f%(ixup)=>)" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseMergeOption "\v-[Cc]>" nextgroup=gitrebaseMergeCommit skipwhite contained syn match gitrebaseMergeCommit "\v<\x{7,}>" nextgroup=gitrebaseName skipwhite contained syn match gitrebaseName "\v[^[:space:].*?i:^~/-]\S+" nextgroup=gitrebaseMergeComment skipwhite contained -syn match gitrebaseMergeComment "#" nextgroup=gitrebaseSummary skipwhite contained +exe 'syn match gitrebaseMergeComment "' . s:c . '" nextgroup=gitrebaseSummary skipwhite contained' + +unlet s:c hi def link gitrebaseCommit gitrebaseHash hi def link gitrebaseHash Identifier diff --git a/runtime/syntax/i3config.vim b/runtime/syntax/i3config.vim new file mode 100644 index 0000000000..a2f50e50b8 --- /dev/null +++ b/runtime/syntax/i3config.vim @@ -0,0 +1,257 @@ +" Vim syntax file +" Language: i3 config file +" Original Author: Mohamed Boughaba <mohamed dot bgb at gmail dot com> +" Maintainer: Quentin Hibon (github user hiqua) +" Version: 0.4 +" Last Change: 2022 Jan 15 + +" References: +" http://i3wm.org/docs/userguide.html#configuring +" http://vimdoc.sourceforge.net/htmldoc/syntax.html +" +" +" Quit when a syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +scriptencoding utf-8 + +" Error +syn match i3ConfigError /.*/ + +" Todo +syn keyword i3ConfigTodo TODO FIXME XXX contained + +" Comment +" Comments are started with a # and can only be used at the beginning of a line +syn match i3ConfigComment /^\s*#.*$/ contains=i3ConfigTodo + +" Font +" A FreeType font description is composed by: +" a font family, a style, a weight, a variant, a stretch and a size. +syn match i3ConfigFontSeparator /,/ contained +syn match i3ConfigFontSeparator /:/ contained +syn keyword i3ConfigFontKeyword font contained +syn match i3ConfigFontNamespace /\w\+:/ contained contains=i3ConfigFontSeparator +syn match i3ConfigFontContent /-\?\w\+\(-\+\|\s\+\|,\)/ contained contains=i3ConfigFontNamespace,i3ConfigFontSeparator,i3ConfigFontKeyword +syn match i3ConfigFontSize /\s\=\d\+\(px\)\?\s\?$/ contained +syn match i3ConfigFont /^\s*font\s\+.*$/ contains=i3ConfigFontContent,i3ConfigFontSeparator,i3ConfigFontSize,i3ConfigFontNamespace +syn match i3ConfigFont /^\s*font\s\+.*\(\\\_.*\)\?$/ contains=i3ConfigFontContent,i3ConfigFontSeparator,i3ConfigFontSize,i3ConfigFontNamespace +syn match i3ConfigFont /^\s*font\s\+.*\(\\\_.*\)\?[^\\]\+$/ contains=i3ConfigFontContent,i3ConfigFontSeparator,i3ConfigFontSize,i3ConfigFontNamespace +syn match i3ConfigFont /^\s*font\s\+\(\(.*\\\_.*\)\|\(.*[^\\]\+$\)\)/ contains=i3ConfigFontContent,i3ConfigFontSeparator,i3ConfigFontSize,i3ConfigFontNamespace + +" variables +syn match i3ConfigString /\(['"]\)\(.\{-}\)\1/ contained +syn match i3ConfigColor /#\w\{6}/ contained +syn match i3ConfigVariableModifier /+/ contained +syn match i3ConfigVariableAndModifier /+\w\+/ contained contains=i3ConfigVariableModifier +syn match i3ConfigVariable /\$\w\+\(\(-\w\+\)\+\)\?\(\s\|+\)\?/ contains=i3ConfigVariableModifier,i3ConfigVariableAndModifier +syn keyword i3ConfigInitializeKeyword set contained +syn match i3ConfigInitialize /^\s*set\s\+.*$/ contains=i3ConfigVariable,i3ConfigInitializeKeyword,i3ConfigColor,i3ConfigString + +" Gaps +syn keyword i3ConfigGapStyleKeyword inner outer horizontal vertical top right bottom left current all set plus minus toggle up down contained +syn match i3ConfigGapStyle /^\s*\(gaps\)\s\+\(inner\|outer\|horizontal\|vertical\|left\|top\|right\|bottom\)\(\s\+\(current\|all\)\)\?\(\s\+\(set\|plus\|minus\|toggle\)\)\?\(\s\+\(-\?\d\+\|\$.*\)\)$/ contains=i3ConfigGapStyleKeyword,i3ConfigNumber,i3ConfigVariable +syn keyword i3ConfigSmartGapKeyword on inverse_outer contained +syn match i3ConfigSmartGap /^\s*smart_gaps\s\+\(on\|inverse_outer\)\s\?$/ contains=i3ConfigSmartGapKeyword +syn keyword i3ConfigSmartBorderKeyword on no_gaps contained +syn match i3ConfigSmartBorder /^\s*smart_borders\s\+\(on\|no_gaps\)\s\?$/ contains=i3ConfigSmartBorderKeyword + +" Keyboard bindings +syn keyword i3ConfigAction toggle fullscreen restart key import kill shrink grow contained +syn keyword i3ConfigAction focus move grow height width split layout resize restore reload mute unmute exit mode workspace container to contained +syn match i3ConfigModifier /\w\++\w\+\(\(+\w\+\)\+\)\?/ contained contains=i3ConfigVariableModifier +syn match i3ConfigNumber /\s\d\+/ contained +syn match i3ConfigUnit /\sp\(pt\|x\)/ contained +syn match i3ConfigUnitOr /\sor/ contained +syn keyword i3ConfigBindKeyword bindsym bindcode exec gaps border contained +syn match i3ConfigBindArgument /--\w\+\(\(-\w\+\)\+\)\?\s/ contained +syn match i3ConfigBind /^\s*\(bindsym\|bindcode\)\s\+.*$/ contains=i3ConfigVariable,i3ConfigBindKeyword,i3ConfigVariableAndModifier,i3ConfigNumber,i3ConfigUnit,i3ConfigUnitOr,i3ConfigBindArgument,i3ConfigModifier,i3ConfigAction,i3ConfigString,i3ConfigGapStyleKeyword,i3ConfigBorderStyleKeyword + +" Floating +syn keyword i3ConfigSizeSpecial x contained +syn match i3ConfigNegativeSize /-/ contained +syn match i3ConfigSize /-\?\d\+\s\?x\s\?-\?\d\+/ contained contains=i3ConfigSizeSpecial,i3ConfigNumber,i3ConfigNegativeSize +syn match i3ConfigFloating /^\s*floating_modifier\s\+\$\w\+\d\?/ contains=i3ConfigVariable +syn match i3ConfigFloating /^\s*floating_\(maximum\|minimum\)_size\s\+-\?\d\+\s\?x\s\?-\?\d\+/ contains=i3ConfigSize + +" Orientation +syn keyword i3ConfigOrientationKeyword vertical horizontal auto contained +syn match i3ConfigOrientation /^\s*default_orientation\s\+\(vertical\|horizontal\|auto\)\s\?$/ contains=i3ConfigOrientationKeyword + +" Layout +syn keyword i3ConfigLayoutKeyword default stacking tabbed contained +syn match i3ConfigLayout /^\s*workspace_layout\s\+\(default\|stacking\|tabbed\)\s\?$/ contains=i3ConfigLayoutKeyword + +" Border style +syn keyword i3ConfigBorderStyleKeyword none normal pixel contained +syn match i3ConfigBorderStyle /^\s*\(new_window\|new_float\|default_border\|default_floating_border\)\s\+\(none\|\(normal\|pixel\)\(\s\+\d\+\)\?\(\s\+\$\w\+\(\(-\w\+\)\+\)\?\(\s\|+\)\?\)\?\)\s\?$/ contains=i3ConfigBorderStyleKeyword,i3ConfigNumber,i3ConfigVariable + +" Hide borders and edges +syn keyword i3ConfigEdgeKeyword none vertical horizontal both smart smart_no_gaps contained +syn match i3ConfigEdge /^\s*hide_edge_borders\s\+\(none\|vertical\|horizontal\|both\|smart\|smart_no_gaps\)\s\?$/ contains=i3ConfigEdgeKeyword + +" Arbitrary commands for specific windows (for_window) +syn keyword i3ConfigCommandKeyword for_window contained +syn region i3ConfigWindowStringSpecial start=+"+ skip=+\\"+ end=+"+ contained contains=i3ConfigString +syn region i3ConfigWindowCommandSpecial start="\[" end="\]" contained contains=i3ConfigWindowStringSpacial,i3ConfigString +syn match i3ConfigArbitraryCommand /^\s*for_window\s\+.*$/ contains=i3ConfigWindowCommandSpecial,i3ConfigCommandKeyword,i3ConfigBorderStyleKeyword,i3ConfigLayoutKeyword,i3ConfigOrientationKeyword,Size,i3ConfigNumber + +" Disable focus open opening +syn keyword i3ConfigNoFocusKeyword no_focus contained +syn match i3ConfigDisableFocus /^\s*no_focus\s\+.*$/ contains=i3ConfigWindowCommandSpecial,i3ConfigNoFocusKeyword + +" Move client to specific workspace automatically +syn keyword i3ConfigAssignKeyword assign contained +syn match i3ConfigAssignSpecial /→/ contained +syn match i3ConfigAssign /^\s*assign\s\+.*$/ contains=i3ConfigAssignKeyword,i3ConfigWindowCommandSpecial,i3ConfigAssignSpecial + +" X resources +syn keyword i3ConfigResourceKeyword set_from_resource contained +syn match i3ConfigResource /^\s*set_from_resource\s\+.*$/ contains=i3ConfigResourceKeyword,i3ConfigWindowCommandSpecial,i3ConfigColor,i3ConfigVariable + +" Auto start applications +syn keyword i3ConfigExecKeyword exec exec_always contained +syn match i3ConfigNoStartupId /--no-startup-id/ contained " We are not using i3ConfigBindArgument as only no-startup-id is supported here +syn match i3ConfigExec /^\s*exec\(_always\)\?\s\+.*$/ contains=i3ConfigExecKeyword,i3ConfigNoStartupId,i3ConfigString + +" Automatically putting workspaces on specific screens +syn keyword i3ConfigWorkspaceKeyword workspace contained +syn keyword i3ConfigOutput output contained +syn match i3ConfigWorkspace /^\s*workspace\s\+.*$/ contains=i3ConfigWorkspaceKeyword,i3ConfigNumber,i3ConfigString,i3ConfigOutput + +" Changing colors +syn keyword i3ConfigClientColorKeyword client focused focused_inactive unfocused urgent placeholder background contained +syn match i3ConfigClientColor /^\s*client.\w\+\s\+.*$/ contains=i3ConfigClientColorKeyword,i3ConfigColor,i3ConfigVariable + +syn keyword i3ConfigTitleAlignKeyword left center right contained +syn match i3ConfigTitleAlign /^\s*title_align\s\+.*$/ contains=i3ConfigTitleAlignKeyword + +" Interprocess communication +syn match i3ConfigInterprocessKeyword /ipc-socket/ contained +syn match i3ConfigInterprocess /^\s*ipc-socket\s\+.*$/ contains=i3ConfigInterprocessKeyword + +" Mouse warping +syn keyword i3ConfigMouseWarpingKeyword mouse_warping contained +syn keyword i3ConfigMouseWarpingType output none contained +syn match i3ConfigMouseWarping /^\s*mouse_warping\s\+\(output\|none\)\s\?$/ contains=i3ConfigMouseWarpingKeyword,i3ConfigMouseWarpingType + +" Focus follows mouse +syn keyword i3ConfigFocusFollowsMouseKeyword focus_follows_mouse contained +syn keyword i3ConfigFocusFollowsMouseType yes no contained +syn match i3ConfigFocusFollowsMouse /^\s*focus_follows_mouse\s\+\(yes\|no\)\s\?$/ contains=i3ConfigFocusFollowsMouseKeyword,i3ConfigFocusFollowsMouseType + +" Popups during fullscreen mode +syn keyword i3ConfigPopupOnFullscreenKeyword popup_during_fullscreen contained +syn keyword i3ConfigPopuponFullscreenType smart ignore leave_fullscreen contained +syn match i3ConfigPopupOnFullscreen /^\s*popup_during_fullscreen\s\+\w\+\s\?$/ contains=i3ConfigPopupOnFullscreenKeyword,i3ConfigPopupOnFullscreenType + +" Focus wrapping +syn keyword i3ConfigFocusWrappingKeyword force_focus_wrapping focus_wrapping contained +syn keyword i3ConfigFocusWrappingType yes no contained +syn match i3ConfigFocusWrapping /^\s*\(force_\)\?focus_wrapping\s\+\(yes\|no\)\s\?$/ contains=i3ConfigFocusWrappingType,i3ConfigFocusWrappingKeyword + +" Forcing Xinerama +syn keyword i3ConfigForceXineramaKeyword force_xinerama contained +syn match i3ConfigForceXinerama /^\s*force_xinerama\s\+\(yes\|no\)\s\?$/ contains=i3ConfigFocusWrappingType,i3ConfigForceXineramaKeyword + +" Automatic back-and-forth when switching to the current workspace +syn keyword i3ConfigAutomaticSwitchKeyword workspace_auto_back_and_forth contained +syn match i3ConfigAutomaticSwitch /^\s*workspace_auto_back_and_forth\s\+\(yes\|no\)\s\?$/ contains=i3ConfigFocusWrappingType,i3ConfigAutomaticSwitchKeyword + +" Delay urgency hint +syn keyword i3ConfigTimeUnit ms contained +syn keyword i3ConfigDelayUrgencyKeyword force_display_urgency_hint contained +syn match i3ConfigDelayUrgency /^\s*force_display_urgency_hint\s\+\d\+\s\+ms\s\?$/ contains=i3ConfigFocusWrappingType,i3ConfigDelayUrgencyKeyword,i3ConfigNumber,i3ConfigTimeUnit + +" Focus on window activation +syn keyword i3ConfigFocusOnActivationKeyword focus_on_window_activation contained +syn keyword i3ConfigFocusOnActivationType smart urgent focus none contained +syn match i3ConfigFocusOnActivation /^\s*focus_on_window_activation\s\+\(smart\|urgent\|focus\|none\)\s\?$/ contains=i3ConfigFocusOnActivationKeyword,i3ConfigFocusOnActivationType + +" Automatic back-and-forth when switching to the current workspace +syn keyword i3ConfigDrawingMarksKeyword show_marks contained +syn match i3ConfigDrawingMarks /^\s*show_marks\s\+\(yes\|no\)\s\?$/ contains=i3ConfigFocusWrappingType,i3ConfigDrawingMarksKeyword + +" Group mode/bar +syn keyword i3ConfigBlockKeyword mode bar colors i3bar_command status_command position exec mode hidden_state modifier id position output background statusline tray_output tray_padding separator separator_symbol workspace_min_width workspace_buttons strip_workspace_numbers binding_mode_indicator focused_workspace active_workspace inactive_workspace urgent_workspace binding_mode contained +syn region i3ConfigBlock start=+.*s\?{$+ end=+^}$+ contains=i3ConfigBlockKeyword,i3ConfigString,i3ConfigBind,i3ConfigComment,i3ConfigFont,i3ConfigFocusWrappingType,i3ConfigColor,i3ConfigVariable transparent keepend extend + +" Line continuation +syn region i3ConfigLineCont start=/^.*\\$/ end=/^.*$/ contains=i3ConfigBlockKeyword,i3ConfigString,i3ConfigBind,i3ConfigComment,i3ConfigFont,i3ConfigFocusWrappingType,i3ConfigColor,i3ConfigVariable transparent keepend extend + +" Define the highlighting. +hi def link i3ConfigError Error +hi def link i3ConfigTodo Todo +hi def link i3ConfigComment Comment +hi def link i3ConfigFontContent Type +hi def link i3ConfigFocusOnActivationType Type +hi def link i3ConfigPopupOnFullscreenType Type +hi def link i3ConfigOrientationKeyword Type +hi def link i3ConfigMouseWarpingType Type +hi def link i3ConfigFocusFollowsMouseType Type +hi def link i3ConfigGapStyleKeyword Type +hi def link i3ConfigTitleAlignKeyword Type +hi def link i3ConfigSmartGapKeyword Type +hi def link i3ConfigSmartBorderKeyword Type +hi def link i3ConfigLayoutKeyword Type +hi def link i3ConfigBorderStyleKeyword Type +hi def link i3ConfigEdgeKeyword Type +hi def link i3ConfigAction Type +hi def link i3ConfigCommand Type +hi def link i3ConfigOutput Type +hi def link i3ConfigWindowCommandSpecial Type +hi def link i3ConfigFocusWrappingType Type +hi def link i3ConfigUnitOr Type +hi def link i3ConfigFontSize Constant +hi def link i3ConfigColor Constant +hi def link i3ConfigNumber Constant +hi def link i3ConfigUnit Constant +hi def link i3ConfigVariableAndModifier Constant +hi def link i3ConfigTimeUnit Constant +hi def link i3ConfigModifier Constant +hi def link i3ConfigString Constant +hi def link i3ConfigNegativeSize Constant +hi def link i3ConfigFontSeparator Special +hi def link i3ConfigVariableModifier Special +hi def link i3ConfigSizeSpecial Special +hi def link i3ConfigWindowSpecial Special +hi def link i3ConfigAssignSpecial Special +hi def link i3ConfigFontNamespace PreProc +hi def link i3ConfigBindArgument PreProc +hi def link i3ConfigNoStartupId PreProc +hi def link i3ConfigFontKeyword Identifier +hi def link i3ConfigBindKeyword Identifier +hi def link i3ConfigOrientation Identifier +hi def link i3ConfigGapStyle Identifier +hi def link i3ConfigTitleAlign Identifier +hi def link i3ConfigSmartGap Identifier +hi def link i3ConfigSmartBorder Identifier +hi def link i3ConfigLayout Identifier +hi def link i3ConfigBorderStyle Identifier +hi def link i3ConfigEdge Identifier +hi def link i3ConfigFloating Identifier +hi def link i3ConfigCommandKeyword Identifier +hi def link i3ConfigNoFocusKeyword Identifier +hi def link i3ConfigInitializeKeyword Identifier +hi def link i3ConfigAssignKeyword Identifier +hi def link i3ConfigResourceKeyword Identifier +hi def link i3ConfigExecKeyword Identifier +hi def link i3ConfigWorkspaceKeyword Identifier +hi def link i3ConfigClientColorKeyword Identifier +hi def link i3ConfigInterprocessKeyword Identifier +hi def link i3ConfigMouseWarpingKeyword Identifier +hi def link i3ConfigFocusFollowsMouseKeyword Identifier +hi def link i3ConfigPopupOnFullscreenKeyword Identifier +hi def link i3ConfigFocusWrappingKeyword Identifier +hi def link i3ConfigForceXineramaKeyword Identifier +hi def link i3ConfigAutomaticSwitchKeyword Identifier +hi def link i3ConfigDelayUrgencyKeyword Identifier +hi def link i3ConfigFocusOnActivationKeyword Identifier +hi def link i3ConfigDrawingMarksKeyword Identifier +hi def link i3ConfigBlockKeyword Identifier +hi def link i3ConfigVariable Statement +hi def link i3ConfigArbitraryCommand Type + +let b:current_syntax = "i3config" diff --git a/runtime/syntax/python.vim b/runtime/syntax/python.vim index 3427aa06c8..2293163a5b 100644 --- a/runtime/syntax/python.vim +++ b/runtime/syntax/python.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Python " Maintainer: Zvezdan Petkovic <zpetkovic@acm.org> -" Last Change: 2021 Feb 15 +" Last Change: 2021 Dec 10 " Credits: Neil Schemenauer <nas@python.ca> " Dmitry Vasiliev " @@ -77,13 +77,14 @@ endif " " The list can be checked using: " -" python3 -c 'import keyword, pprint; pprint.pprint(keyword.kwlist, compact=True)' +" python3 -c 'import keyword, pprint; pprint.pprint(keyword.kwlist + keyword.softkwlist, compact=True)' " syn keyword pythonStatement False None True syn keyword pythonStatement as assert break continue del global syn keyword pythonStatement lambda nonlocal pass return with yield syn keyword pythonStatement class def nextgroup=pythonFunction skipwhite syn keyword pythonConditional elif else if +syn keyword pythonConditional case match syn keyword pythonRepeat for while syn keyword pythonOperator and in is not or syn keyword pythonException except finally raise try diff --git a/runtime/syntax/rc.vim b/runtime/syntax/rc.vim index 4c6856bc83..d69edd00fd 100644 --- a/runtime/syntax/rc.vim +++ b/runtime/syntax/rc.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: M$ Resource files (*.rc) " Maintainer: Christian Brabandt -" Last Change: 2015-05-29 +" Last Change: 20220116 " Repository: https://github.com/chrisbra/vim-rc-syntax " License: Vim (see :h license) " Previous Maintainer: Heiko Erhardt <Heiko.Erhardt@munich.netsurf.de> @@ -173,16 +173,17 @@ hi def link rcAttribute rcCommonAttribute hi def link rcStdId rcStatement hi def link rcStatement Statement -" Default color overrides -hi def rcLanguage term=reverse ctermbg=Red ctermfg=Yellow guibg=Red guifg=Yellow -hi def rcMainObject term=underline ctermfg=Blue guifg=Blue -hi def rcSubObject ctermfg=Green guifg=Green -hi def rcCaptionParam term=underline ctermfg=DarkGreen guifg=Green -hi def rcParam ctermfg=DarkGreen guifg=DarkGreen -hi def rcStatement ctermfg=DarkGreen guifg=DarkGreen -hi def rcCommonAttribute ctermfg=Brown guifg=Brown +hi def link rcLanguage Constant +hi def link rcCaptionParam Constant +hi def link rcCommonAttribute Constant + +hi def link rcMainObject Identifier +hi def link rcSubObject Define +hi def link rcParam Constant +hi def link rcStatement Statement +" +"hi def link rcIdentifier Identifier -"hi def link rcIdentifier Identifier let b:current_syntax = "rc" diff --git a/runtime/syntax/scala.vim b/runtime/syntax/scala.vim index 16e114778d..c08e60e55a 100644 --- a/runtime/syntax/scala.vim +++ b/runtime/syntax/scala.vim @@ -3,7 +3,7 @@ " Maintainer: Derek Wyatt " URL: https://github.com/derekwyatt/vim-scala " License: Same as Vim -" Last Change: 23 August 2021 +" Last Change: 23 January 2022 " ---------------------------------------------------------------------------- if !exists('main_syntax') @@ -43,55 +43,55 @@ syn keyword scalaKeyword class trait object extends with nextgroup=scalaInstance syn keyword scalaKeyword case nextgroup=scalaKeyword,scalaCaseFollowing skipwhite syn keyword scalaKeyword val nextgroup=scalaNameDefinition,scalaQuasiQuotes skipwhite syn keyword scalaKeyword def var nextgroup=scalaNameDefinition skipwhite -hi link scalaKeyword Keyword +hi def link scalaKeyword Keyword exe 'syn region scalaBlock start=/{/ end=/}/ contains=' . s:ContainedGroup() . ' fold' syn keyword scalaAkkaSpecialWord when goto using startWith initialize onTransition stay become unbecome -hi link scalaAkkaSpecialWord PreProc +hi def link scalaAkkaSpecialWord PreProc syn keyword scalatestSpecialWord shouldBe syn match scalatestShouldDSLA /^\s\+\zsit should/ syn match scalatestShouldDSLB /\<should\>/ -hi link scalatestSpecialWord PreProc -hi link scalatestShouldDSLA PreProc -hi link scalatestShouldDSLB PreProc +hi def link scalatestSpecialWord PreProc +hi def link scalatestShouldDSLA PreProc +hi def link scalatestShouldDSLB PreProc syn match scalaSymbol /'[_A-Za-z0-9$]\+/ -hi link scalaSymbol Number +hi def link scalaSymbol Number syn match scalaChar /'.'/ syn match scalaChar /'\\[\\"'ntbrf]'/ contains=scalaEscapedChar syn match scalaChar /'\\u[A-Fa-f0-9]\{4}'/ contains=scalaUnicodeChar syn match scalaEscapedChar /\\[\\"'ntbrf]/ syn match scalaUnicodeChar /\\u[A-Fa-f0-9]\{4}/ -hi link scalaChar Character -hi link scalaEscapedChar Special -hi link scalaUnicodeChar Special +hi def link scalaChar Character +hi def link scalaEscapedChar Special +hi def link scalaUnicodeChar Special syn match scalaOperator "||" syn match scalaOperator "&&" syn match scalaOperator "|" syn match scalaOperator "&" -hi link scalaOperator Special +hi def link scalaOperator Special syn match scalaNameDefinition /\<[_A-Za-z0-9$]\+\>/ contained nextgroup=scalaPostNameDefinition,scalaVariableDeclarationList syn match scalaNameDefinition /`[^`]\+`/ contained nextgroup=scalaPostNameDefinition syn match scalaVariableDeclarationList /\s*,\s*/ contained nextgroup=scalaNameDefinition syn match scalaPostNameDefinition /\_s*:\_s*/ contained nextgroup=scalaTypeDeclaration -hi link scalaNameDefinition Function +hi def link scalaNameDefinition Function syn match scalaInstanceDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaInstanceHash syn match scalaInstanceDeclaration /`[^`]\+`/ contained syn match scalaInstanceHash /#/ contained nextgroup=scalaInstanceDeclaration -hi link scalaInstanceDeclaration Special -hi link scalaInstanceHash Type +hi def link scalaInstanceDeclaration Special +hi def link scalaInstanceHash Type syn match scalaUnimplemented /???/ -hi link scalaUnimplemented ERROR +hi def link scalaUnimplemented ERROR syn match scalaCapitalWord /\<[A-Z][A-Za-z0-9$]*\>/ -hi link scalaCapitalWord Special +hi def link scalaCapitalWord Special " Handle type declarations specially syn region scalaTypeStatement matchgroup=Keyword start=/\<type\_s\+\ze/ end=/$/ contains=scalaTypeTypeDeclaration,scalaSquareBrackets,scalaTypeTypeEquals,scalaTypeStatement @@ -105,18 +105,18 @@ syn match scalaTypeTypeEquals /=\ze[^>]/ contained nextgroup=scalaTypeTypePostDe syn match scalaTypeTypeExtension /)\?\_s*\zs\%(⇒\|=>\|<:\|:>\|=:=\|::\|#\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeTypeDeclaration skipwhite syn match scalaTypeTypePostDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeTypePostExtension skipwhite syn match scalaTypeTypePostExtension /\%(⇒\|=>\|<:\|:>\|=:=\|::\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeTypePostDeclaration skipwhite -hi link scalaTypeTypeDeclaration Type -hi link scalaTypeTypeExtension Keyword -hi link scalaTypeTypePostDeclaration Special -hi link scalaTypeTypePostExtension Keyword +hi def link scalaTypeTypeDeclaration Type +hi def link scalaTypeTypeExtension Keyword +hi def link scalaTypeTypePostDeclaration Special +hi def link scalaTypeTypePostExtension Keyword syn match scalaTypeDeclaration /(/ contained nextgroup=scalaTypeExtension contains=scalaRoundBrackets skipwhite syn match scalaTypeDeclaration /\%(⇒\|=>\)\ze/ contained nextgroup=scalaTypeDeclaration contains=scalaTypeExtension skipwhite syn match scalaTypeDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeExtension skipwhite syn match scalaTypeExtension /)\?\_s*\zs\%(⇒\|=>\|<:\|:>\|=:=\|::\|#\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeDeclaration skipwhite -hi link scalaTypeDeclaration Type -hi link scalaTypeExtension Keyword -hi link scalaTypePostExtension Keyword +hi def link scalaTypeDeclaration Type +hi def link scalaTypeExtension Keyword +hi def link scalaTypePostExtension Keyword syn match scalaTypeAnnotation /\%([_a-zA-Z0-9$\s]:\_s*\)\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration contains=scalaRoundBrackets syn match scalaTypeAnnotation /)\_s*:\_s*\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration @@ -124,51 +124,51 @@ hi clear scalaTypeAnnotation syn match scalaCaseFollowing /\<[_\.A-Za-z0-9$]\+\>/ contained contains=scalaCapitalWord syn match scalaCaseFollowing /`[^`]\+`/ contained contains=scalaCapitalWord -hi link scalaCaseFollowing Special +hi def link scalaCaseFollowing Special syn keyword scalaKeywordModifier abstract override final lazy implicit private protected sealed null super syn keyword scalaSpecialFunction implicitly require -hi link scalaKeywordModifier Function -hi link scalaSpecialFunction Function +hi def link scalaKeywordModifier Function +hi def link scalaSpecialFunction Function syn keyword scalaSpecial this true false ne eq syn keyword scalaSpecial new nextgroup=scalaInstanceDeclaration skipwhite syn match scalaSpecial "\%(=>\|⇒\|<-\|←\|->\|→\)" syn match scalaSpecial /`[^`]\+`/ " Backtick literals -hi link scalaSpecial PreProc +hi def link scalaSpecial PreProc syn keyword scalaExternal package import -hi link scalaExternal Include +hi def link scalaExternal Include syn match scalaStringEmbeddedQuote /\\"/ contained syn region scalaString start=/"/ end=/"/ contains=scalaStringEmbeddedQuote,scalaEscapedChar,scalaUnicodeChar -hi link scalaString String -hi link scalaStringEmbeddedQuote String +hi def link scalaString String +hi def link scalaStringEmbeddedQuote String syn region scalaIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"/ skip=/\\"/ end=/"/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar syn region scalaTripleIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"""/ end=/"""\ze\%([^"]\|$\)/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar -hi link scalaIString String -hi link scalaTripleIString String +hi def link scalaIString String +hi def link scalaTripleIString String syn match scalaInterpolation /\$[a-zA-Z0-9_$]\+/ contained exe 'syn region scalaInterpolationB matchgroup=scalaInterpolationBoundary start=/\${/ end=/}/ contained contains=' . s:ContainedGroup() -hi link scalaInterpolation Function +hi def link scalaInterpolation Function hi clear scalaInterpolationB syn region scalaFString matchgroup=scalaInterpolationBrackets start=/f"/ skip=/\\"/ end=/"/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar syn match scalaFInterpolation /\$[a-zA-Z0-9_$]\+\(%[-A-Za-z0-9\.]\+\)\?/ contained exe 'syn region scalaFInterpolationB matchgroup=scalaInterpolationBoundary start=/${/ end=/}\(%[-A-Za-z0-9\.]\+\)\?/ contained contains=' . s:ContainedGroup() -hi link scalaFString String -hi link scalaFInterpolation Function +hi def link scalaFString String +hi def link scalaFInterpolation Function hi clear scalaFInterpolationB syn region scalaTripleString start=/"""/ end=/"""\%([^"]\|$\)/ contains=scalaEscapedChar,scalaUnicodeChar syn region scalaTripleFString matchgroup=scalaInterpolationBrackets start=/f"""/ end=/"""\%([^"]\|$\)/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar -hi link scalaTripleString String -hi link scalaTripleFString String +hi def link scalaTripleString String +hi def link scalaTripleFString String -hi link scalaInterpolationBrackets Special -hi link scalaInterpolationBoundary Function +hi def link scalaInterpolationBrackets Special +hi def link scalaInterpolationBoundary Function syn match scalaNumber /\<0[dDfFlL]\?\>/ " Just a bare 0 syn match scalaNumber /\<[1-9]\d*[dDfFlL]\?\>/ " A multi-digit number - octal numbers with leading 0's are deprecated in Scala @@ -176,16 +176,16 @@ syn match scalaNumber /\<0[xX][0-9a-fA-F]\+[dDfFlL]\?\>/ " Hex number syn match scalaNumber /\%(\<\d\+\.\d*\|\.\d\+\)\%([eE][-+]\=\d\+\)\=[fFdD]\=/ " exponential notation 1 syn match scalaNumber /\<\d\+[eE][-+]\=\d\+[fFdD]\=\>/ " exponential notation 2 syn match scalaNumber /\<\d\+\%([eE][-+]\=\d\+\)\=[fFdD]\>/ " exponential notation 3 -hi link scalaNumber Number +hi def link scalaNumber Number syn region scalaRoundBrackets start="(" end=")" skipwhite contained contains=scalaTypeDeclaration,scalaSquareBrackets,scalaRoundBrackets syn region scalaSquareBrackets matchgroup=scalaSquareBracketsBrackets start="\[" end="\]" skipwhite nextgroup=scalaTypeExtension contains=scalaTypeDeclaration,scalaSquareBrackets,scalaTypeOperator,scalaTypeAnnotationParameter syn match scalaTypeOperator /[-+=:<>]\+/ contained syn match scalaTypeAnnotationParameter /@\<[`_A-Za-z0-9$]\+\>/ contained -hi link scalaSquareBracketsBrackets Type -hi link scalaTypeOperator Keyword -hi link scalaTypeAnnotationParameter Function +hi def link scalaSquareBracketsBrackets Type +hi def link scalaTypeOperator Keyword +hi def link scalaTypeAnnotationParameter Function syn match scalaShebang "\%^#!.*" display syn region scalaMultilineComment start="/\*" end="\*/" contains=scalaMultilineComment,scalaDocLinks,scalaParameterAnnotation,scalaCommentAnnotation,scalaTodo,scalaCommentCodeBlock,@Spell keepend fold @@ -195,20 +195,20 @@ syn match scalaParamAnnotationValue /[.`_A-Za-z0-9$]\+/ contained syn region scalaDocLinks start="\[\[" end="\]\]" contained syn region scalaCommentCodeBlock matchgroup=Keyword start="{{{" end="}}}" contained syn match scalaTodo "\vTODO|FIXME|XXX" contained -hi link scalaShebang Comment -hi link scalaMultilineComment Comment -hi link scalaDocLinks Function -hi link scalaParameterAnnotation Function -hi link scalaParamAnnotationValue Keyword -hi link scalaCommentAnnotation Function -hi link scalaCommentCodeBlock String -hi link scalaTodo Todo +hi def link scalaShebang Comment +hi def link scalaMultilineComment Comment +hi def link scalaDocLinks Function +hi def link scalaParameterAnnotation Function +hi def link scalaParamAnnotationValue Keyword +hi def link scalaCommentAnnotation Function +hi def link scalaCommentCodeBlock String +hi def link scalaTodo Todo syn match scalaAnnotation /@\<[`_A-Za-z0-9$]\+\>/ -hi link scalaAnnotation PreProc +hi def link scalaAnnotation PreProc syn match scalaTrailingComment "//.*$" contains=scalaTodo,@Spell -hi link scalaTrailingComment Comment +hi def link scalaTrailingComment Comment syn match scalaAkkaFSM /goto([^)]*)\_s\+\<using\>/ contains=scalaAkkaFSMGotoUsing syn match scalaAkkaFSM /stay\_s\+using/ @@ -221,8 +221,8 @@ syn match scalaAkkaFSM /onTermination/ syn match scalaAkkaFSM /whenUnhandled/ syn match scalaAkkaFSMGotoUsing /\<using\>/ syn match scalaAkkaFSMGotoUsing /\<goto\>/ -hi link scalaAkkaFSM PreProc -hi link scalaAkkaFSMGotoUsing PreProc +hi def link scalaAkkaFSM PreProc +hi def link scalaAkkaFSMGotoUsing PreProc let b:current_syntax = 'scala' diff --git a/runtime/syntax/texinfo.vim b/runtime/syntax/texinfo.vim index a4b7689707..79a4dfe821 100644 --- a/runtime/syntax/texinfo.vim +++ b/runtime/syntax/texinfo.vim @@ -1,396 +1,46 @@ " Vim syntax file -" Language: Texinfo (macro package for TeX) -" Maintainer: Sandor Kopanyi <sandor.kopanyi@mailbox.hu> -" URL: <-> -" Last Change: 2004 Jun 23 -" -" the file follows the Texinfo manual structure; this file is based -" on manual for Texinfo version 4.0, 28 September 1999 -" since @ can have special meanings, everything is 'match'-ed and 'region'-ed -" (including @ in 'iskeyword' option has unexpected effects) +" Language: Texinfo (documentation format) +" Maintainer: Robert Dodier <robert.dodier@gmail.com> +" Latest Revision: 2021-12-15 -" quit when a syntax file was already loaded if exists("b:current_syntax") finish endif -if !exists("main_syntax") - let main_syntax = 'texinfo' -endif - -"in Texinfo can be real big things, like tables; sync for that -syn sync lines=200 - -"some general stuff -"syn match texinfoError "\S" contained TODO -syn match texinfoIdent "\k\+" contained "IDENTifier -syn match texinfoAssignment "\k\+\s*=\s*\k\+\s*$" contained "assigment statement ( var = val ) -syn match texinfoSinglePar "\k\+\s*$" contained "single parameter (used for several @-commands) -syn match texinfoIndexPar "\k\k\s*$" contained "param. used for different *index commands (+ @documentlanguage command) - - -"marking words and phrases (chap. 9 in Texinfo manual) -"(almost) everything appears as 'contained' too; is for tables (@table) - -"this chapter is at the beginning of this file to avoid overwritings - -syn match texinfoSpecialChar "@acronym" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@acronym{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@b" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@b{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@cite" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@cite{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@code" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@code{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@command" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@command{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@dfn" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@dfn{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@email" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@email{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@emph" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@emph{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@env" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@env{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@file" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@file{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@i" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@i{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@kbd" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@kbd{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@key" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@key{" end="}" contains=texinfoSpecialChar -syn match texinfoSpecialChar "@option" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@option{" end="}" contains=texinfoSpecialChar -syn match texinfoSpecialChar "@r" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@r{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@samp" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@samp{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@sc" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@sc{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@strong" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@strong{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@t" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@t{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@url" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@url{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoSpecialChar "@var" contained -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@var{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn match texinfoAtCmd "^@kbdinputstyle" nextgroup=texinfoSinglePar skipwhite - - -"overview of Texinfo (chap. 1 in Texinfo manual) -syn match texinfoComment "@c .*" -syn match texinfoComment "@c$" -syn match texinfoComment "@comment .*" -syn region texinfoMltlnAtCmd matchgroup=texinfoComment start="^@ignore\s*$" end="^@end ignore\s*$" contains=ALL - - -"beginning a Texinfo file (chap. 3 in Texinfo manual) -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="@center " skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd oneline -syn region texinfoMltlnDMAtCmd matchgroup=texinfoAtCmd start="^@detailmenu\s*$" end="^@end detailmenu\s*$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@setfilename " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@settitle " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@shorttitlepage " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@title " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@titlefont{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@titlepage\s*$" end="^@end titlepage\s*$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoMltlnDMAtCmd,texinfoAtCmd,texinfoPrmAtCmd,texinfoMltlnAtCmd -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@vskip " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn match texinfoAtCmd "^@exampleindent" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "^@headings" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "^\\input" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "^@paragraphindent" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "^@setchapternewpage" nextgroup=texinfoSinglePar skipwhite - - -"ending a Texinfo file (chap. 4 in Texinfo manual) -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="@author " skip="\\$" end="$" contains=texinfoSpecialChar oneline -"all below @bye should be comment TODO -syn match texinfoAtCmd "^@bye\s*$" -syn match texinfoAtCmd "^@contents\s*$" -syn match texinfoAtCmd "^@printindex" nextgroup=texinfoIndexPar skipwhite -syn match texinfoAtCmd "^@setcontentsaftertitlepage\s*$" -syn match texinfoAtCmd "^@setshortcontentsaftertitlepage\s*$" -syn match texinfoAtCmd "^@shortcontents\s*$" -syn match texinfoAtCmd "^@summarycontents\s*$" - - -"chapter structuring (chap. 5 in Texinfo manual) -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@appendix" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@appendixsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@appendixsection" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@appendixsubsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@appendixsubsubsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@centerchap" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@chapheading" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@chapter" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@heading" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@majorheading" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@section" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@subheading " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@subsection" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@subsubheading" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@subsubsection" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@subtitle" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@unnumbered" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@unnumberedsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@unnumberedsubsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@unnumberedsubsubsec" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn match texinfoAtCmd "^@lowersections\s*$" -syn match texinfoAtCmd "^@raisesections\s*$" - - -"nodes (chap. 6 in Texinfo manual) -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@anchor{" end="}" -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@top" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@node" skip="\\$" end="$" contains=texinfoSpecialChar oneline - - -"menus (chap. 7 in Texinfo manual) -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@menu\s*$" end="^@end menu\s*$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoMltlnDMAtCmd - - -"cross references (chap. 8 in Texinfo manual) -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@inforef{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@pxref{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@ref{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@uref{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@xref{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd - - -"marking words and phrases (chap. 9 in Texinfo manual) -"(almost) everything appears as 'contained' too; is for tables (@table) - -"this chapter is at the beginning of this file to avoid overwritings - - -"quotations and examples (chap. 10 in Texinfo manual) -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@cartouche\s*$" end="^@end cartouche\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@display\s*$" end="^@end display\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@example\s*$" end="^@end example\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@flushleft\s*$" end="^@end flushleft\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@flushright\s*$" end="^@end flushright\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@format\s*$" end="^@end format\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@lisp\s*$" end="^@end lisp\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@quotation\s*$" end="^@end quotation\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@smalldisplay\s*$" end="^@end smalldisplay\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@smallexample\s*$" end="^@end smallexample\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@smallformat\s*$" end="^@end smallformat\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@smalllisp\s*$" end="^@end smalllisp\s*$" contains=ALL -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@exdent" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn match texinfoAtCmd "^@noindent\s*$" -syn match texinfoAtCmd "^@smallbook\s*$" - - -"lists and tables (chap. 11 in Texinfo manual) -syn match texinfoAtCmd "@asis" contained -syn match texinfoAtCmd "@columnfractions" contained -syn match texinfoAtCmd "@item" contained -syn match texinfoAtCmd "@itemx" contained -syn match texinfoAtCmd "@tab" contained -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@enumerate" end="^@end enumerate\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ftable" end="^@end ftable\s*$" contains=ALL -syn region texinfoMltlnNAtCmd matchgroup=texinfoAtCmd start="^@itemize" end="^@end itemize\s*$" contains=ALL -syn region texinfoMltlnNAtCmd matchgroup=texinfoAtCmd start="^@multitable" end="^@end multitable\s*$" contains=ALL -syn region texinfoMltlnNAtCmd matchgroup=texinfoAtCmd start="^@table" end="^@end table\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@vtable" end="^@end vtable\s*$" contains=ALL +let s:cpo_save = &cpo +set cpo&vim +syn match texinfoControlSequence display '\(@end [a-zA-Z@]\+\|@[a-zA-Z@]\+\)' -"indices (chap. 12 in Texinfo manual) -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@\(c\|f\|k\|p\|t\|v\)index" skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@..index" skip="\\$" end="$" contains=texinfoSpecialChar oneline -"@defcodeindex and @defindex is defined after chap. 15's @def* commands (otherwise those ones will overwrite these ones) -syn match texinfoSIPar "\k\k\s*\k\k\s*$" contained -syn match texinfoAtCmd "^@syncodeindex" nextgroup=texinfoSIPar skipwhite -syn match texinfoAtCmd "^@synindex" nextgroup=texinfoSIPar skipwhite +syn match texinfoComment display '^\s*\(@comment\|@c\)\>.*$' -"special insertions (chap. 13 in Texinfo manual) -syn match texinfoSpecialChar "@\(!\|?\|@\|\s\)" -syn match texinfoSpecialChar "@{" -syn match texinfoSpecialChar "@}" -"accents -syn match texinfoSpecialChar "@=." -syn match texinfoSpecialChar "@\('\|\"\|\^\|`\)[aeiouyAEIOUY]" -syn match texinfoSpecialChar "@\~[aeinouyAEINOUY]" -syn match texinfoSpecialChar "@dotaccent{.}" -syn match texinfoSpecialChar "@H{.}" -syn match texinfoSpecialChar "@,{[cC]}" -syn match texinfoSpecialChar "@AA{}" -syn match texinfoSpecialChar "@aa{}" -syn match texinfoSpecialChar "@L{}" -syn match texinfoSpecialChar "@l{}" -syn match texinfoSpecialChar "@O{}" -syn match texinfoSpecialChar "@o{}" -syn match texinfoSpecialChar "@ringaccent{.}" -syn match texinfoSpecialChar "@tieaccent{..}" -syn match texinfoSpecialChar "@u{.}" -syn match texinfoSpecialChar "@ubaraccent{.}" -syn match texinfoSpecialChar "@udotaccent{.}" -syn match texinfoSpecialChar "@v{.}" -"ligatures -syn match texinfoSpecialChar "@AE{}" -syn match texinfoSpecialChar "@ae{}" -syn match texinfoSpecialChar "@copyright{}" -syn match texinfoSpecialChar "@bullet" contained "for tables and lists -syn match texinfoSpecialChar "@bullet{}" -syn match texinfoSpecialChar "@dotless{i}" -syn match texinfoSpecialChar "@dotless{j}" -syn match texinfoSpecialChar "@dots{}" -syn match texinfoSpecialChar "@enddots{}" -syn match texinfoSpecialChar "@equiv" contained "for tables and lists -syn match texinfoSpecialChar "@equiv{}" -syn match texinfoSpecialChar "@error{}" -syn match texinfoSpecialChar "@exclamdown{}" -syn match texinfoSpecialChar "@expansion{}" -syn match texinfoSpecialChar "@minus" contained "for tables and lists -syn match texinfoSpecialChar "@minus{}" -syn match texinfoSpecialChar "@OE{}" -syn match texinfoSpecialChar "@oe{}" -syn match texinfoSpecialChar "@point" contained "for tables and lists -syn match texinfoSpecialChar "@point{}" -syn match texinfoSpecialChar "@pounds{}" -syn match texinfoSpecialChar "@print{}" -syn match texinfoSpecialChar "@questiondown{}" -syn match texinfoSpecialChar "@result" contained "for tables and lists -syn match texinfoSpecialChar "@result{}" -syn match texinfoSpecialChar "@ss{}" -syn match texinfoSpecialChar "@TeX{}" -"other -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@dmn{" end="}" -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@footnote{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@image{" end="}" -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@math{" end="}" -syn match texinfoAtCmd "@footnotestyle" nextgroup=texinfoSinglePar skipwhite +syn region texinfoCode matchgroup=texinfoControlSequence start="@code{" end="}" contains=ALL +syn region texinfoVerb matchgroup=texinfoControlSequence start="@verb{" end="}" contains=ALL +syn region texinfoArgument matchgroup=texinfoBrace start="{" end="}" contains=ALLBUT -"making and preventing breaks (chap. 14 in Texinfo manual) -syn match texinfoSpecialChar "@\(\*\|-\|\.\)" -syn match texinfoAtCmd "^@need" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "^@page\s*$" -syn match texinfoAtCmd "^@sp" nextgroup=texinfoSinglePar skipwhite -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@group\s*$" end="^@end group\s*$" contains=ALL -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@hyphenation{" end="}" -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@w{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd +syn region texinfoExample matchgroup=texinfoControlSequence start="^@example\s*$" end="^@end example\s*$" contains=ALL +syn region texinfoVerbatim matchgroup=texinfoControlSequence start="^@verbatim\s*$" end="^@end verbatim\s*$" -"definition commands (chap. 15 in Texinfo manual) -syn match texinfoMltlnAtCmdFLine "^@def\k\+" contained -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@def\k\+" end="^@end def\k\+$" contains=ALL - -"next 2 commands are from chap. 12; must be defined after @def* commands above to overwrite them -syn match texinfoAtCmd "@defcodeindex" nextgroup=texinfoIndexPar skipwhite -syn match texinfoAtCmd "@defindex" nextgroup=texinfoIndexPar skipwhite - - -"conditionally visible text (chap. 16 in Texinfo manual) -syn match texinfoAtCmd "^@clear" nextgroup=texinfoSinglePar skipwhite -syn region texinfoMltln2AtCmd matchgroup=texinfoAtCmd start="^@html\s*$" end="^@end html\s*$" -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifclear" end="^@end ifclear\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifhtml" end="^@end ifhtml\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifinfo" end="^@end ifinfo\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifnothtml" end="^@end ifnothtml\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifnotinfo" end="^@end ifnotinfo\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifnottex" end="^@end ifnottex\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@ifset" end="^@end ifset\s*$" contains=ALL -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@iftex" end="^@end iftex\s*$" contains=ALL -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@set " skip="\\$" end="$" contains=texinfoSpecialChar oneline -syn region texinfoTexCmd start="\$\$" end="\$\$" contained -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@tex" end="^@end tex\s*$" contains=texinfoTexCmd -syn region texinfoBrcPrmAtCmd matchgroup=texinfoAtCmd start="@value{" end="}" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd - - -"internationalization (chap. 17 in Texinfo manual) -syn match texinfoAtCmd "@documentencoding" nextgroup=texinfoSinglePar skipwhite -syn match texinfoAtCmd "@documentlanguage" nextgroup=texinfoIndexPar skipwhite - - -"defining new texinfo commands (chap. 18 in Texinfo manual) -syn match texinfoAtCmd "@alias" nextgroup=texinfoAssignment skipwhite -syn match texinfoDIEPar "\S*\s*,\s*\S*\s*,\s*\S*\s*$" contained -syn match texinfoAtCmd "@definfoenclose" nextgroup=texinfoDIEPar skipwhite -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@macro" end="^@end macro\s*$" contains=ALL - - -"formatting hardcopy (chap. 19 in Texinfo manual) -syn match texinfoAtCmd "^@afourlatex\s*$" -syn match texinfoAtCmd "^@afourpaper\s*$" -syn match texinfoAtCmd "^@afourwide\s*$" -syn match texinfoAtCmd "^@finalout\s*$" -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@pagesizes" end="$" oneline - - -"creating and installing Info Files (chap. 20 in Texinfo manual) -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@dircategory" skip="\\$" end="$" oneline -syn region texinfoMltlnAtCmd matchgroup=texinfoAtCmd start="^@direntry\s*$" end="^@end direntry\s*$" contains=texinfoSpecialChar -syn match texinfoAtCmd "^@novalidate\s*$" - - -"include files (appendix E in Texinfo manual) -syn match texinfoAtCmd "^@include" nextgroup=texinfoSinglePar skipwhite - - -"page headings (appendix F in Texinfo manual) -syn match texinfoHFSpecialChar "@|" contained -syn match texinfoThisAtCmd "@thischapter" contained -syn match texinfoThisAtCmd "@thischaptername" contained -syn match texinfoThisAtCmd "@thisfile" contained -syn match texinfoThisAtCmd "@thispage" contained -syn match texinfoThisAtCmd "@thistitle" contained -syn match texinfoThisAtCmd "@today{}" contained -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@evenfooting" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@evenheading" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@everyfooting" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@everyheading" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@oddfooting" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline -syn region texinfoPrmAtCmd matchgroup=texinfoAtCmd start="^@oddheading" skip="\\$" end="$" contains=texinfoSpecialChar,texinfoBrcPrmAtCmd,texinfoThisAtCmd,texinfoHFSpecialChar oneline - - -"refilling paragraphs (appendix H in Texinfo manual) -syn match texinfoAtCmd "@refill" - - -syn cluster texinfoAll contains=ALLBUT,texinfoThisAtCmd,texinfoHFSpecialChar -syn cluster texinfoReducedAll contains=texinfoSpecialChar,texinfoBrcPrmAtCmd -"============================================================================== -" highlighting - -" Only when an item doesn't have highlighting yet - -hi def link texinfoSpecialChar Special -hi def link texinfoHFSpecialChar Special - -hi def link texinfoError Error -hi def link texinfoIdent Identifier -hi def link texinfoAssignment Identifier -hi def link texinfoSinglePar Identifier -hi def link texinfoIndexPar Identifier -hi def link texinfoSIPar Identifier -hi def link texinfoDIEPar Identifier -hi def link texinfoTexCmd PreProc - - -hi def link texinfoAtCmd Statement "@-command -hi def link texinfoPrmAtCmd String "@-command in one line with unknown nr. of parameters - "is String because is found as a region and is 'matchgroup'-ed - "to texinfoAtCmd -hi def link texinfoBrcPrmAtCmd String "@-command with parameter(s) in braces ({}) - "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd -hi def link texinfoMltlnAtCmdFLine texinfoAtCmd "repeated embedded First lines in @-commands -hi def link texinfoMltlnAtCmd String "@-command in multiple lines - "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd -hi def link texinfoMltln2AtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) -hi def link texinfoMltlnDMAtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors; used for @detailmenu, which can be included in @menu) -hi def link texinfoMltlnNAtCmd Normal "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) -hi def link texinfoThisAtCmd Statement "@-command used in headers and footers (@this... series) - -hi def link texinfoComment Comment +syn region texinfoMenu matchgroup=texinfoControlSequence start="^@menu\s*$" end="^@end menu\s*$" +if exists("g:texinfo_delimiters") + syn match texinfoDelimiter display '[][{}]' +endif +hi def link texinfoDelimiter Delimiter +hi def link texinfoComment Comment +hi def link texinfoControlSequence Identifier +hi def link texinfoBrace Operator +hi def link texinfoArgument Special +hi def link texinfoExample String +hi def link texinfoVerbatim String +hi def link texinfoVerb String +hi def link texinfoCode String +hi def link texinfoMenu String let b:current_syntax = "texinfo" -if main_syntax == 'texinfo' - unlet main_syntax -endif - -" vim: ts=8 +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/xml.vim b/runtime/syntax/xml.vim index 7c9791a7cc..d99f8b467a 100644 --- a/runtime/syntax/xml.vim +++ b/runtime/syntax/xml.vim @@ -10,6 +10,7 @@ " 20190923 - Fix xmlEndTag to match xmlTag (vim/vim#884) " 20190924 - Fix xmlAttribute property (amadeus/vim-xml@d8ce1c946) " 20191103 - Enable spell checking globally +" 20210428 - Improve syntax synchronizing " CONFIGURATION: " syntax folding can be turned on by @@ -302,9 +303,12 @@ unlet b:current_syntax " synchronizing -" TODO !!! to be improved !!! -syn sync match xmlSyncDT grouphere xmlDocType +\_.\(<!DOCTYPE\)\@=+ +syn sync match xmlSyncComment grouphere xmlComment +<!--+ +syn sync match xmlSyncComment groupthere NONE +-->+ + +" The following is slow on large documents (and the doctype is optional +" syn sync match xmlSyncDT grouphere xmlDocType +\_.\(<!DOCTYPE\)\@=+ " syn sync match xmlSyncDT groupthere NONE +]>+ if exists('g:xml_syntax_folding') @@ -313,7 +317,7 @@ if exists('g:xml_syntax_folding') syn sync match xmlSync groupthere xmlRegion +</[^ /!?<>"']\+>+ endif -syn sync minlines=100 +syn sync minlines=100 maxlines=200 " The default highlighting. @@ -354,4 +358,4 @@ let b:current_syntax = "xml" let &cpo = s:xml_cpo_save unlet s:xml_cpo_save -" vim: ts=8 +" vim: ts=4 diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim index 819c419228..bab89b916e 100644 --- a/runtime/syntax/zsh.vim +++ b/runtime/syntax/zsh.vim @@ -41,11 +41,12 @@ if get(g:, 'zsh_fold_enable', 0) setlocal foldmethod=syntax endif +syn match zshQuoted '\\.' syn match zshPOSIXQuoted '\\[xX][0-9a-fA-F]\{1,2}' syn match zshPOSIXQuoted '\\[0-7]\{1,3}' syn match zshPOSIXQuoted '\\u[0-9a-fA-F]\{1,4}' syn match zshPOSIXQuoted '\\U[1-9a-fA-F]\{1,8}' -syn match zshQuoted '\\.' + syn region zshString matchgroup=zshStringDelimiter start=+"+ end=+"+ \ contains=zshQuoted,@zshDerefs,@zshSubst fold syn region zshString matchgroup=zshStringDelimiter start=+'+ end=+'+ fold @@ -133,217 +134,15 @@ syn keyword zshCommands alias autoload bg bindkey break bye cap cd \ zmodload zparseopts zprof zpty zrecompile \ zregexparse zsocket zstyle ztcp -" Options, generated by: echo ${(j:\n:)options[(I)*]} | sort -" Create a list of option names from zsh source dir: -" #!/bin/zsh -" topdir=/path/to/zsh-xxx -" grep '^pindex([A-Za-z_]*)$' $topdir/Doc/Zsh/options.yo | -" while read opt -" do -" echo ${${(L)opt#pindex\(}%\)} -" done - +" Options, generated by from the zsh source with the make-options.zsh script. syn case ignore - -syn match zshOptStart /^\s*\%(\%(\%(un\)\?setopt\)\|set\s+[-+]o\)/ nextgroup=zshOption skipwhite -syn match zshOption / - \ \%(\%(\<no_\?\)\?aliases\>\)\| - \ \%(\%(\<no_\?\)\?aliasfuncdef\>\)\|\%(\%(no_\?\)\?alias_func_def\>\)\| - \ \%(\%(\<no_\?\)\?allexport\>\)\|\%(\%(no_\?\)\?all_export\>\)\| - \ \%(\%(\<no_\?\)\?alwayslastprompt\>\)\|\%(\%(no_\?\)\?always_last_prompt\>\)\|\%(\%(no_\?\)\?always_lastprompt\>\)\| - \ \%(\%(\<no_\?\)\?alwaystoend\>\)\|\%(\%(no_\?\)\?always_to_end\>\)\| - \ \%(\%(\<no_\?\)\?appendcreate\>\)\|\%(\%(no_\?\)\?append_create\>\)\| - \ \%(\%(\<no_\?\)\?appendhistory\>\)\|\%(\%(no_\?\)\?append_history\>\)\| - \ \%(\%(\<no_\?\)\?autocd\>\)\|\%(\%(no_\?\)\?auto_cd\>\)\| - \ \%(\%(\<no_\?\)\?autocontinue\>\)\|\%(\%(no_\?\)\?auto_continue\>\)\| - \ \%(\%(\<no_\?\)\?autolist\>\)\|\%(\%(no_\?\)\?auto_list\>\)\| - \ \%(\%(\<no_\?\)\?automenu\>\)\|\%(\%(no_\?\)\?auto_menu\>\)\| - \ \%(\%(\<no_\?\)\?autonamedirs\>\)\|\%(\%(no_\?\)\?auto_name_dirs\>\)\| - \ \%(\%(\<no_\?\)\?autoparamkeys\>\)\|\%(\%(no_\?\)\?auto_param_keys\>\)\| - \ \%(\%(\<no_\?\)\?autoparamslash\>\)\|\%(\%(no_\?\)\?auto_param_slash\>\)\| - \ \%(\%(\<no_\?\)\?autopushd\>\)\|\%(\%(no_\?\)\?auto_pushd\>\)\| - \ \%(\%(\<no_\?\)\?autoremoveslash\>\)\|\%(\%(no_\?\)\?auto_remove_slash\>\)\| - \ \%(\%(\<no_\?\)\?autoresume\>\)\|\%(\%(no_\?\)\?auto_resume\>\)\| - \ \%(\%(\<no_\?\)\?badpattern\>\)\|\%(\%(no_\?\)\?bad_pattern\>\)\| - \ \%(\%(\<no_\?\)\?banghist\>\)\|\%(\%(no_\?\)\?bang_hist\>\)\| - \ \%(\%(\<no_\?\)\?bareglobqual\>\)\|\%(\%(no_\?\)\?bare_glob_qual\>\)\| - \ \%(\%(\<no_\?\)\?bashautolist\>\)\|\%(\%(no_\?\)\?bash_auto_list\>\)\| - \ \%(\%(\<no_\?\)\?bashrematch\>\)\|\%(\%(no_\?\)\?bash_rematch\>\)\| - \ \%(\%(\<no_\?\)\?beep\>\)\| - \ \%(\%(\<no_\?\)\?bgnice\>\)\|\%(\%(no_\?\)\?bg_nice\>\)\| - \ \%(\%(\<no_\?\)\?braceccl\>\)\|\%(\%(no_\?\)\?brace_ccl\>\)\| - \ \%(\%(\<no_\?\)\?braceexpand\>\)\|\%(\%(no_\?\)\?brace_expand\>\)\| - \ \%(\%(\<no_\?\)\?bsdecho\>\)\|\%(\%(no_\?\)\?bsd_echo\>\)\| - \ \%(\%(\<no_\?\)\?caseglob\>\)\|\%(\%(no_\?\)\?case_glob\>\)\| - \ \%(\%(\<no_\?\)\?casematch\>\)\|\%(\%(no_\?\)\?case_match\>\)\| - \ \%(\%(\<no_\?\)\?cbases\>\)\|\%(\%(no_\?\)\?c_bases\>\)\| - \ \%(\%(\<no_\?\)\?cdablevars\>\)\|\%(\%(no_\?\)\?cdable_vars\>\)\|\%(\%(no_\?\)\?cd_able_vars\>\)\| - \ \%(\%(\<no_\?\)\?cdsilent\>\)\|\%(\%(no_\?\)\?cd_silent\>\)\|\%(\%(no_\?\)\?cd_silent\>\)\| - \ \%(\%(\<no_\?\)\?chasedots\>\)\|\%(\%(no_\?\)\?chase_dots\>\)\| - \ \%(\%(\<no_\?\)\?chaselinks\>\)\|\%(\%(no_\?\)\?chase_links\>\)\| - \ \%(\%(\<no_\?\)\?checkjobs\>\)\|\%(\%(no_\?\)\?check_jobs\>\)\| - \ \%(\%(\<no_\?\)\?checkrunningjobs\>\)\|\%(\%(no_\?\)\?check_running_jobs\>\)\| - \ \%(\%(\<no_\?\)\?clobber\>\)\| - \ \%(\%(\<no_\?\)\?clobberempty\>\)\|\%(\%(no_\?\)\?clobber_empty\>\)\| - \ \%(\%(\<no_\?\)\?combiningchars\>\)\|\%(\%(no_\?\)\?combining_chars\>\)\| - \ \%(\%(\<no_\?\)\?completealiases\>\)\|\%(\%(no_\?\)\?complete_aliases\>\)\| - \ \%(\%(\<no_\?\)\?completeinword\>\)\|\%(\%(no_\?\)\?complete_in_word\>\)\| - \ \%(\%(\<no_\?\)\?continueonerror\>\)\|\%(\%(no_\?\)\?continue_on_error\>\)\| - \ \%(\%(\<no_\?\)\?correct\>\)\| - \ \%(\%(\<no_\?\)\?correctall\>\)\|\%(\%(no_\?\)\?correct_all\>\)\| - \ \%(\%(\<no_\?\)\?cprecedences\>\)\|\%(\%(no_\?\)\?c_precedences\>\)\| - \ \%(\%(\<no_\?\)\?cshjunkiehistory\>\)\|\%(\%(no_\?\)\?csh_junkie_history\>\)\| - \ \%(\%(\<no_\?\)\?cshjunkieloops\>\)\|\%(\%(no_\?\)\?csh_junkie_loops\>\)\| - \ \%(\%(\<no_\?\)\?cshjunkiequotes\>\)\|\%(\%(no_\?\)\?csh_junkie_quotes\>\)\| - \ \%(\%(\<no_\?\)\?csh_nullcmd\>\)\|\%(\%(no_\?\)\?csh_null_cmd\>\)\|\%(\%(no_\?\)\?cshnullcmd\>\)\|\%(\%(no_\?\)\?csh_null_cmd\>\)\| - \ \%(\%(\<no_\?\)\?cshnullglob\>\)\|\%(\%(no_\?\)\?csh_null_glob\>\)\| - \ \%(\%(\<no_\?\)\?debugbeforecmd\>\)\|\%(\%(no_\?\)\?debug_before_cmd\>\)\| - \ \%(\%(\<no_\?\)\?dotglob\>\)\|\%(\%(no_\?\)\?dot_glob\>\)\| - \ \%(\%(\<no_\?\)\?dvorak\>\)\| - \ \%(\%(\<no_\?\)\?emacs\>\)\| - \ \%(\%(\<no_\?\)\?equals\>\)\| - \ \%(\%(\<no_\?\)\?errexit\>\)\|\%(\%(no_\?\)\?err_exit\>\)\| - \ \%(\%(\<no_\?\)\?errreturn\>\)\|\%(\%(no_\?\)\?err_return\>\)\| - \ \%(\%(\<no_\?\)\?evallineno\>\)\|\%(\%(no_\?\)\?eval_lineno\>\)\| - \ \%(\%(\<no_\?\)\?exec\>\)\| - \ \%(\%(\<no_\?\)\?extendedglob\>\)\|\%(\%(no_\?\)\?extended_glob\>\)\| - \ \%(\%(\<no_\?\)\?extendedhistory\>\)\|\%(\%(no_\?\)\?extended_history\>\)\| - \ \%(\%(\<no_\?\)\?flowcontrol\>\)\|\%(\%(no_\?\)\?flow_control\>\)\| - \ \%(\%(\<no_\?\)\?forcefloat\>\)\|\%(\%(no_\?\)\?force_float\>\)\| - \ \%(\%(\<no_\?\)\?functionargzero\>\)\|\%(\%(no_\?\)\?function_argzero\>\)\|\%(\%(no_\?\)\?function_arg_zero\>\)\| - \ \%(\%(\<no_\?\)\?glob\>\)\| - \ \%(\%(\<no_\?\)\?globalexport\>\)\|\%(\%(no_\?\)\?global_export\>\)\| - \ \%(\%(\<no_\?\)\?globalrcs\>\)\|\%(\%(no_\?\)\?global_rcs\>\)\| - \ \%(\%(\<no_\?\)\?globassign\>\)\|\%(\%(no_\?\)\?glob_assign\>\)\| - \ \%(\%(\<no_\?\)\?globcomplete\>\)\|\%(\%(no_\?\)\?glob_complete\>\)\| - \ \%(\%(\<no_\?\)\?globdots\>\)\|\%(\%(no_\?\)\?glob_dots\>\)\| - \ \%(\%(\<no_\?\)\?glob_subst\>\)\|\%(\%(no_\?\)\?globsubst\>\)\| - \ \%(\%(\<no_\?\)\?globstarshort\>\)\|\%(\%(no_\?\)\?glob_star_short\>\)\| - \ \%(\%(\<no_\?\)\?hashall\>\)\|\%(\%(no_\?\)\?hash_all\>\)\| - \ \%(\%(\<no_\?\)\?hashcmds\>\)\|\%(\%(no_\?\)\?hash_cmds\>\)\| - \ \%(\%(\<no_\?\)\?hashdirs\>\)\|\%(\%(no_\?\)\?hash_dirs\>\)\| - \ \%(\%(\<no_\?\)\?hashexecutablesonly\>\)\|\%(\%(no_\?\)\?hash_executables_only\>\)\| - \ \%(\%(\<no_\?\)\?hashlistall\>\)\|\%(\%(no_\?\)\?hash_list_all\>\)\| - \ \%(\%(\<no_\?\)\?histallowclobber\>\)\|\%(\%(no_\?\)\?hist_allow_clobber\>\)\| - \ \%(\%(\<no_\?\)\?histappend\>\)\|\%(\%(no_\?\)\?hist_append\>\)\| - \ \%(\%(\<no_\?\)\?histbeep\>\)\|\%(\%(no_\?\)\?hist_beep\>\)\| - \ \%(\%(\<no_\?\)\?hist_expand\>\)\|\%(\%(no_\?\)\?histexpand\>\)\| - \ \%(\%(\<no_\?\)\?hist_expire_dups_first\>\)\|\%(\%(no_\?\)\?histexpiredupsfirst\>\)\| - \ \%(\%(\<no_\?\)\?histfcntllock\>\)\|\%(\%(no_\?\)\?hist_fcntl_lock\>\)\| - \ \%(\%(\<no_\?\)\?histfindnodups\>\)\|\%(\%(no_\?\)\?hist_find_no_dups\>\)\| - \ \%(\%(\<no_\?\)\?histignorealldups\>\)\|\%(\%(no_\?\)\?hist_ignore_all_dups\>\)\| - \ \%(\%(\<no_\?\)\?histignoredups\>\)\|\%(\%(no_\?\)\?hist_ignore_dups\>\)\| - \ \%(\%(\<no_\?\)\?histignorespace\>\)\|\%(\%(no_\?\)\?hist_ignore_space\>\)\| - \ \%(\%(\<no_\?\)\?histlexwords\>\)\|\%(\%(no_\?\)\?hist_lex_words\>\)\| - \ \%(\%(\<no_\?\)\?histnofunctions\>\)\|\%(\%(no_\?\)\?hist_no_functions\>\)\| - \ \%(\%(\<no_\?\)\?histnostore\>\)\|\%(\%(no_\?\)\?hist_no_store\>\)\| - \ \%(\%(\<no_\?\)\?histreduceblanks\>\)\|\%(\%(no_\?\)\?hist_reduce_blanks\>\)\| - \ \%(\%(\<no_\?\)\?histsavebycopy\>\)\|\%(\%(no_\?\)\?hist_save_by_copy\>\)\| - \ \%(\%(\<no_\?\)\?histsavenodups\>\)\|\%(\%(no_\?\)\?hist_save_no_dups\>\)\| - \ \%(\%(\<no_\?\)\?histsubstpattern\>\)\|\%(\%(no_\?\)\?hist_subst_pattern\>\)\| - \ \%(\%(\<no_\?\)\?histverify\>\)\|\%(\%(no_\?\)\?hist_verify\>\)\| - \ \%(\%(\<no_\?\)\?hup\>\)\| - \ \%(\%(\<no_\?\)\?ignorebraces\>\)\|\%(\%(no_\?\)\?ignore_braces\>\)\| - \ \%(\%(\<no_\?\)\?ignoreclosebraces\>\)\|\%(\%(no_\?\)\?ignore_close_braces\>\)\| - \ \%(\%(\<no_\?\)\?ignoreeof\>\)\|\%(\%(no_\?\)\?ignore_eof\>\)\| - \ \%(\%(\<no_\?\)\?incappendhistory\>\)\|\%(\%(no_\?\)\?inc_append_history\>\)\| - \ \%(\%(\<no_\?\)\?incappendhistorytime\>\)\|\%(\%(no_\?\)\?inc_append_history_time\>\)\| - \ \%(\%(\<no_\?\)\?interactive\>\)\| - \ \%(\%(\<no_\?\)\?interactivecomments\>\)\|\%(\%(no_\?\)\?interactive_comments\>\)\| - \ \%(\%(\<no_\?\)\?ksharrays\>\)\|\%(\%(no_\?\)\?ksh_arrays\>\)\| - \ \%(\%(\<no_\?\)\?kshautoload\>\)\|\%(\%(no_\?\)\?ksh_autoload\>\)\| - \ \%(\%(\<no_\?\)\?kshglob\>\)\|\%(\%(no_\?\)\?ksh_glob\>\)\| - \ \%(\%(\<no_\?\)\?kshoptionprint\>\)\|\%(\%(no_\?\)\?ksh_option_print\>\)\| - \ \%(\%(\<no_\?\)\?kshtypeset\>\)\|\%(\%(no_\?\)\?ksh_typeset\>\)\| - \ \%(\%(\<no_\?\)\?kshzerosubscript\>\)\|\%(\%(no_\?\)\?ksh_zero_subscript\>\)\| - \ \%(\%(\<no_\?\)\?listambiguous\>\)\|\%(\%(no_\?\)\?list_ambiguous\>\)\| - \ \%(\%(\<no_\?\)\?listbeep\>\)\|\%(\%(no_\?\)\?list_beep\>\)\| - \ \%(\%(\<no_\?\)\?listpacked\>\)\|\%(\%(no_\?\)\?list_packed\>\)\| - \ \%(\%(\<no_\?\)\?listrowsfirst\>\)\|\%(\%(no_\?\)\?list_rows_first\>\)\| - \ \%(\%(\<no_\?\)\?listtypes\>\)\|\%(\%(no_\?\)\?list_types\>\)\| - \ \%(\%(\<no_\?\)\?localloops\>\)\|\%(\%(no_\?\)\?local_loops\>\)\| - \ \%(\%(\<no_\?\)\?localoptions\>\)\|\%(\%(no_\?\)\?local_options\>\)\| - \ \%(\%(\<no_\?\)\?localpatterns\>\)\|\%(\%(no_\?\)\?local_patterns\>\)\| - \ \%(\%(\<no_\?\)\?localtraps\>\)\|\%(\%(no_\?\)\?local_traps\>\)\| - \ \%(\%(\<no_\?\)\?log\>\)\| - \ \%(\%(\<no_\?\)\?login\>\)\| - \ \%(\%(\<no_\?\)\?longlistjobs\>\)\|\%(\%(no_\?\)\?long_list_jobs\>\)\| - \ \%(\%(\<no_\?\)\?magicequalsubst\>\)\|\%(\%(no_\?\)\?magic_equal_subst\>\)\| - \ \%(\%(\<no_\?\)\?mark_dirs\>\)\| - \ \%(\%(\<no_\?\)\?mailwarn\>\)\|\%(\%(no_\?\)\?mail_warn\>\)\| - \ \%(\%(\<no_\?\)\?mailwarning\>\)\|\%(\%(no_\?\)\?mail_warning\>\)\| - \ \%(\%(\<no_\?\)\?markdirs\>\)\| - \ \%(\%(\<no_\?\)\?menucomplete\>\)\|\%(\%(no_\?\)\?menu_complete\>\)\| - \ \%(\%(\<no_\?\)\?monitor\>\)\| - \ \%(\%(\<no_\?\)\?multibyte\>\)\|\%(\%(no_\?\)\?multi_byte\>\)\| - \ \%(\%(\<no_\?\)\?multifuncdef\>\)\|\%(\%(no_\?\)\?multi_func_def\>\)\| - \ \%(\%(\<no_\?\)\?multios\>\)\|\%(\%(no_\?\)\?multi_os\>\)\| - \ \%(\%(\<no_\?\)\?nomatch\>\)\|\%(\%(no_\?\)\?no_match\>\)\| - \ \%(\%(\<no_\?\)\?notify\>\)\| - \ \%(\%(\<no_\?\)\?nullglob\>\)\|\%(\%(no_\?\)\?null_glob\>\)\| - \ \%(\%(\<no_\?\)\?numericglobsort\>\)\|\%(\%(no_\?\)\?numeric_glob_sort\>\)\| - \ \%(\%(\<no_\?\)\?octalzeroes\>\)\|\%(\%(no_\?\)\?octal_zeroes\>\)\| - \ \%(\%(\<no_\?\)\?onecmd\>\)\|\%(\%(no_\?\)\?one_cmd\>\)\| - \ \%(\%(\<no_\?\)\?overstrike\>\)\|\%(\%(no_\?\)\?over_strike\>\)\| - \ \%(\%(\<no_\?\)\?pathdirs\>\)\|\%(\%(no_\?\)\?path_dirs\>\)\| - \ \%(\%(\<no_\?\)\?pathscript\>\)\|\%(\%(no_\?\)\?path_script\>\)\| - \ \%(\%(\<no_\?\)\?physical\>\)\| - \ \%(\%(\<no_\?\)\?pipefail\>\)\|\%(\%(no_\?\)\?pipe_fail\>\)\| - \ \%(\%(\<no_\?\)\?posixaliases\>\)\|\%(\%(no_\?\)\?posix_aliases\>\)\| - \ \%(\%(\<no_\?\)\?posixargzero\>\)\|\%(\%(no_\?\)\?posix_arg_zero\>\)\|\%(\%(no_\?\)\?posix_argzero\>\)\| - \ \%(\%(\<no_\?\)\?posixbuiltins\>\)\|\%(\%(no_\?\)\?posix_builtins\>\)\| - \ \%(\%(\<no_\?\)\?posixcd\>\)\|\%(\%(no_\?\)\?posix_cd\>\)\| - \ \%(\%(\<no_\?\)\?posixidentifiers\>\)\|\%(\%(no_\?\)\?posix_identifiers\>\)\| - \ \%(\%(\<no_\?\)\?posixjobs\>\)\|\%(\%(no_\?\)\?posix_jobs\>\)\| - \ \%(\%(\<no_\?\)\?posixstrings\>\)\|\%(\%(no_\?\)\?posix_strings\>\)\| - \ \%(\%(\<no_\?\)\?posixtraps\>\)\|\%(\%(no_\?\)\?posix_traps\>\)\| - \ \%(\%(\<no_\?\)\?printeightbit\>\)\|\%(\%(no_\?\)\?print_eight_bit\>\)\| - \ \%(\%(\<no_\?\)\?printexitvalue\>\)\|\%(\%(no_\?\)\?print_exit_value\>\)\| - \ \%(\%(\<no_\?\)\?privileged\>\)\| - \ \%(\%(\<no_\?\)\?promptbang\>\)\|\%(\%(no_\?\)\?prompt_bang\>\)\| - \ \%(\%(\<no_\?\)\?promptcr\>\)\|\%(\%(no_\?\)\?prompt_cr\>\)\| - \ \%(\%(\<no_\?\)\?promptpercent\>\)\|\%(\%(no_\?\)\?prompt_percent\>\)\| - \ \%(\%(\<no_\?\)\?promptsp\>\)\|\%(\%(no_\?\)\?prompt_sp\>\)\| - \ \%(\%(\<no_\?\)\?promptsubst\>\)\|\%(\%(no_\?\)\?prompt_subst\>\)\| - \ \%(\%(\<no_\?\)\?promptvars\>\)\|\%(\%(no_\?\)\?prompt_vars\>\)\| - \ \%(\%(\<no_\?\)\?pushdignoredups\>\)\|\%(\%(no_\?\)\?pushd_ignore_dups\>\)\| - \ \%(\%(\<no_\?\)\?pushdminus\>\)\|\%(\%(no_\?\)\?pushd_minus\>\)\| - \ \%(\%(\<no_\?\)\?pushdsilent\>\)\|\%(\%(no_\?\)\?pushd_silent\>\)\| - \ \%(\%(\<no_\?\)\?pushdtohome\>\)\|\%(\%(no_\?\)\?pushd_to_home\>\)\| - \ \%(\%(\<no_\?\)\?rcexpandparam\>\)\|\%(\%(no_\?\)\?rc_expandparam\>\)\|\%(\%(no_\?\)\?rc_expand_param\>\)\| - \ \%(\%(\<no_\?\)\?rcquotes\>\)\|\%(\%(no_\?\)\?rc_quotes\>\)\| - \ \%(\%(\<no_\?\)\?rcs\>\)\| - \ \%(\%(\<no_\?\)\?recexact\>\)\|\%(\%(no_\?\)\?rec_exact\>\)\| - \ \%(\%(\<no_\?\)\?rematchpcre\>\)\|\%(\%(no_\?\)\?re_match_pcre\>\)\|\%(\%(no_\?\)\?rematch_pcre\>\)\| - \ \%(\%(\<no_\?\)\?restricted\>\)\| - \ \%(\%(\<no_\?\)\?rmstarsilent\>\)\|\%(\%(no_\?\)\?rm_star_silent\>\)\| - \ \%(\%(\<no_\?\)\?rmstarwait\>\)\|\%(\%(no_\?\)\?rm_star_wait\>\)\| - \ \%(\%(\<no_\?\)\?sharehistory\>\)\|\%(\%(no_\?\)\?share_history\>\)\| - \ \%(\%(\<no_\?\)\?shfileexpansion\>\)\|\%(\%(no_\?\)\?sh_file_expansion\>\)\| - \ \%(\%(\<no_\?\)\?shglob\>\)\|\%(\%(no_\?\)\?sh_glob\>\)\| - \ \%(\%(\<no_\?\)\?shinstdin\>\)\|\%(\%(no_\?\)\?shin_stdin\>\)\| - \ \%(\%(\<no_\?\)\?shnullcmd\>\)\|\%(\%(no_\?\)\?sh_nullcmd\>\)\| - \ \%(\%(\<no_\?\)\?shoptionletters\>\)\|\%(\%(no_\?\)\?sh_option_letters\>\)\| - \ \%(\%(\<no_\?\)\?shortloops\>\)\|\%(\%(no_\?\)\?short_loops\>\)\| - \ \%(\%(\<no_\?\)\?shortrepeat\>\)\|\%(\%(no_\?\)\?short_repeat\>\)\| - \ \%(\%(\<no_\?\)\?shwordsplit\>\)\|\%(\%(no_\?\)\?sh_word_split\>\)\| - \ \%(\%(\<no_\?\)\?singlecommand\>\)\|\%(\%(no_\?\)\?single_command\>\)\| - \ \%(\%(\<no_\?\)\?singlelinezle\>\)\|\%(\%(no_\?\)\?single_line_zle\>\)\| - \ \%(\%(\<no_\?\)\?sourcetrace\>\)\|\%(\%(no_\?\)\?source_trace\>\)\| - \ \%(\%(\<no_\?\)\?stdin\>\)\| - \ \%(\%(\<no_\?\)\?sunkeyboardhack\>\)\|\%(\%(no_\?\)\?sun_keyboard_hack\>\)\| - \ \%(\%(\<no_\?\)\?trackall\>\)\|\%(\%(no_\?\)\?track_all\>\)\| - \ \%(\%(\<no_\?\)\?transientrprompt\>\)\|\%(\%(no_\?\)\?transient_rprompt\>\)\| - \ \%(\%(\<no_\?\)\?trapsasync\>\)\|\%(\%(no_\?\)\?traps_async\>\)\| - \ \%(\%(\<no_\?\)\?typesetsilent\>\)\|\%(\%(no_\?\)\?type_set_silent\>\)\|\%(\%(no_\?\)\?typeset_silent\>\)\| - \ \%(\%(\<no_\?\)\?unset\>\)\| - \ \%(\%(\<no_\?\)\?verbose\>\)\| - \ \%(\%(\<no_\?\)\?vi\>\)\| - \ \%(\%(\<no_\?\)\?warnnestedvar\>\)\|\%(\%(no_\?\)\?warn_nested_var\>\)\| - \ \%(\%(\<no_\?\)\?warncreateglobal\>\)\|\%(\%(no_\?\)\?warn_create_global\>\)\| - \ \%(\%(\<no_\?\)\?xtrace\>\)\| - \ \%(\%(\<no_\?\)\?zle\>\)/ nextgroup=zshOption,zshComment skipwhite contained - +syn match zshOptStart + \ /\v^\s*%(%(un)?setopt|set\s+[-+]o)/ + \ nextgroup=zshOption skipwhite +syn match zshOption nextgroup=zshOption,zshComment skipwhite contained /\v + \ <%(no_?)?%( + \ auto_?cd|auto_?pushd|cdable_?vars|cd_?silent|chase_?dots|chase_?links|posix_?cd|pushd_?ignore_?dups|pushd_?minus|pushd_?silent|pushd_?to_?home|always_?last_?prompt|always_?to_?end|auto_?list|auto_?menu|auto_?name_?dirs|auto_?param_?keys|auto_?param_?slash|auto_?remove_?slash|bash_?auto_?list|complete_?aliases|complete_?in_?word|glob_?complete|hash_?list_?all|list_?ambiguous|list_?beep|list_?packed|list_?rows_?first|list_?types|menu_?complete|rec_?exact|bad_?pattern|bare_?glob_?qual|brace_?ccl|case_?glob|case_?match|case_?paths|csh_?null_?glob|equals|extended_?glob|force_?float|glob|glob_?assign|glob_?dots|glob_?star_?short|glob_?subst|hist_?subst_?pattern|ignore_?braces|ignore_?close_?braces|ksh_?glob|magic_?equal_?subst|mark_?dirs|multibyte|nomatch|null_?glob|numeric_?glob_?sort|rc_?expand_?param|rematch_?pcre|sh_?glob|unset|warn_?create_?global|warn_?nested_?var|warnnestedvar|append_?history|bang_?hist|extended_?history|hist_?allow_?clobber|hist_?beep|hist_?expire_?dups_?first|hist_?fcntl_?lock|hist_?find_?no_?dups|hist_?ignore_?all_?dups|hist_?ignore_?dups|hist_?ignore_?space|hist_?lex_?words|hist_?no_?functions|hist_?no_?store|hist_?reduce_?blanks|hist_?save_?by_?copy|hist_?save_?no_?dups|hist_?verify|inc_?append_?history|inc_?append_?history_?time|share_?history|all_?export|global_?export|global_?rcs|rcs|aliases|clobber|clobber_?empty|correct|correct_?all|dvorak|flow_?control|ignore_?eof|interactive_?comments|hash_?cmds|hash_?dirs|hash_?executables_?only|mail_?warning|path_?dirs|path_?script|print_?eight_?bit|print_?exit_?value|rc_?quotes|rm_?star_?silent|rm_?star_?wait|short_?loops|short_?repeat|sun_?keyboard_?hack|auto_?continue|auto_?resume|bg_?nice|check_?jobs|check_?running_?jobs|hup|long_?list_?jobs|monitor|notify|posix_?jobs|prompt_?bang|prompt_?cr|prompt_?sp|prompt_?percent|prompt_?subst|transient_?rprompt|alias_?func_?def|c_?bases|c_?precedences|debug_?before_?cmd|err_?exit|err_?return|eval_?lineno|exec|function_?argzero|local_?loops|local_?options|local_?patterns|local_?traps|multi_?func_?def|multios|octal_?zeroes|pipe_?fail|source_?trace|typeset_?silent|typeset_?to_?unset|verbose|xtrace|append_?create|bash_?rematch|bsd_?echo|continue_?on_?error|csh_?junkie_?history|csh_?junkie_?loops|csh_?junkie_?quotes|csh_?nullcmd|ksh_?arrays|ksh_?autoload|ksh_?option_?print|ksh_?typeset|ksh_?zero_?subscript|posix_?aliases|posix_?argzero|posix_?builtins|posix_?identifiers|posix_?strings|posix_?traps|sh_?file_?expansion|sh_?nullcmd|sh_?option_?letters|sh_?word_?split|traps_?async|interactive|login|privileged|restricted|shin_?stdin|single_?command|beep|combining_?chars|emacs|overstrike|single_?line_?zle|vi|zle|brace_?expand|dot_?glob|hash_?all|hist_?append|hist_?expand|log|mail_?warn|one_?cmd|physical|prompt_?vars|stdin|track_?all|no_?match + \)>/ syn case match syn keyword zshTypes float integer local typeset declare private readonly @@ -365,7 +164,7 @@ syn region zshGlob start='(#' end=')' syn region zshMathSubst matchgroup=zshSubstDelim transparent \ start='\%(\$\?\)[<=>]\@<!((' skip='\\)' end='))' \ contains=zshParentheses,@zshSubst,zshNumber, - \ @zshDerefs,zshString keepend fold + \ @zshDerefs,zshString fold " The ms=s+1 prevents matching zshBrackets several times on opening brackets " (see https://github.com/chrisbra/vim-zsh/issues/21#issuecomment-576330348) syn region zshBrackets contained transparent start='{'ms=s+1 skip='\\}' |