diff options
Diffstat (limited to 'runtime')
41 files changed, 1107 insertions, 211 deletions
diff --git a/runtime/autoload/haskellcomplete.vim b/runtime/autoload/haskellcomplete.vim index 520ab93700..48fbac7f9f 100644 --- a/runtime/autoload/haskellcomplete.vim +++ b/runtime/autoload/haskellcomplete.vim @@ -2,7 +2,7 @@ " Language: Haskell " Maintainer: Daniel Campoverde <alx@sillybytes.net> " URL: https://github.com/alx741/haskellcomplete.vim -" Last Change: 2018 Aug 26 +" Last Change: 2019 May 14 " Usage: setlocal omnifunc=haskellcomplete#Complete @@ -63,6 +63,7 @@ function! haskellcomplete#Complete(findstart, base) call add(l:matches, extension) endif endfor + let b:completingLangExtension = 0 return l:matches endif @@ -78,6 +79,7 @@ function! haskellcomplete#Complete(findstart, base) call add(l:matches, flag) endif endfor + let b:completingOptionsGHC = 0 return l:matches endif @@ -93,6 +95,7 @@ function! haskellcomplete#Complete(findstart, base) call add(l:matches, module) endif endfor + let b:completingModule = 0 return l:matches endif diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index c2195fa02d..07f37d604f 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -132,6 +132,12 @@ function! provider#clipboard#Executable() abort let s:copy['*'] = s:copy['+'] let s:paste['*'] = s:paste['+'] return 'win32yank' + elseif executable('termux-clipboard-set') + let s:copy['+'] = ['termux-clipboard-set'] + let s:paste['+'] = ['termux-clipboard-get'] + let s:copy['*'] = s:copy['+'] + let s:paste['*'] = s:paste['+'] + return 'termux-clipboard' elseif !empty($TMUX) && executable('tmux') let s:copy['+'] = ['tmux', 'load-buffer', '-'] let s:paste['+'] = ['tmux', 'save-buffer', '-'] diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index fdc41af1d5..1e287281cf 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -538,6 +538,21 @@ nvim__screenshot({path}) *nvim__screenshot()* Attributes: ~ {fast} +nvim__set_hl_ns({ns_id}) *nvim__set_hl_ns()* + Set active namespace for highlights. + + NB: this function can be called from async contexts, but the + semantics are not yet well-defined. To start with + |nvim_set_decoration_provider| on_win and on_line callbacks + are explicitly allowed to change the namespace during a redraw + cycle. + + Attributes: ~ + {fast} + + Parameters: ~ + {ns_id} the namespace to activate + nvim__stats() *nvim__stats()* Gets internal stats. @@ -599,6 +614,22 @@ nvim_call_function({fn}, {args}) *nvim_call_function()* Return: ~ Result of the function call +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. + + This function writes raw data, not RPC messages. If the + channel was created with `rpc=true` then the channel expects + RPC messages, use |vim.rpcnotify()| and |vim.rpcrequest()| + instead. + + Parameters: ~ + {chan} id of the channel + {data} data to write. 8-bit clean: can contain NUL bytes. + nvim_command({command}) *nvim_command()* Executes an ex-command. @@ -1160,6 +1191,27 @@ nvim_notify({msg}, {log_level}, {opts}) *nvim_notify()* {log_level} The log level {opts} Reserved for future use. +nvim_open_term({buffer}, {opts}) *nvim_open_term()* + Open a terminal instance in a buffer + + By default (and currently the only option) the terminal will + not be connected to an external process. Instead, input send + on the channel will be echoed directly by the terminal. This + is useful to disply ANSI terminal sequences returned as part + of a rpc message, or similar. + + Note: to directly initiate the terminal using the right size, + display the buffer in a configured window before calling this. + For instance, for a floating display, first create an empty + buffer using |nvim_create_buf()|, then display it using + |nvim_open_win()|, and then call this function. Then + |nvim_chan_send()| cal be called immediately to process + sequences in a virtual terminal having the intended size. + + Parameters: ~ + {buffer} the buffer to use (expected to be empty) + {opts} Optional parameters. Reserved for future use. + nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* Open a new window. @@ -1415,9 +1467,9 @@ nvim_put({lines}, {type}, {after}, {follow}) *nvim_put()* • "c" |charwise| mode • "l" |linewise| mode • "" guess by contents, see |setreg()| - {after} Insert after cursor (like |p|), or before (like - |P|). - {follow} Place cursor at end of inserted text. + {after} If true insert after cursor (like |p|), or + before (like |P|). + {follow} If true place cursor at end of inserted text. *nvim_replace_termcodes()* nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) @@ -1623,21 +1675,6 @@ nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()* keys are also recognized: `default` : don't override existing definition, like `hi default` -nvim_set_hl_ns({ns_id}) *nvim_set_hl_ns()* - Set active namespace for highlights. - - NB: this function can be called from async contexts, but the - semantics are not yet well-defined. To start with - |nvim_set_decoration_provider| on_win and on_line callbacks - are explicitly allowed to change the namespace during a redraw - cycle. - - Attributes: ~ - {fast} - - Parameters: ~ - {ns_id} the namespace to activate - nvim_set_keymap({mode}, {lhs}, {rhs}, {opts}) *nvim_set_keymap()* Sets a global |mapping| for the given mode. @@ -1737,7 +1774,7 @@ nvim__buf_stats({buffer}) *nvim__buf_stats()* TODO: Documentation *nvim_buf_add_highlight()* -nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, {col_start}, +nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start}, {col_end}) Adds a highlight to buffer. @@ -2202,6 +2239,19 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts}) column, without shifting the underlying text. + • virt_text_hide : hide the virtual text when + the background text is selected or hidden due + to horizontal scroll 'nowrap' + • hl_mode : control how highlights are combined + with the highlights of the text. Currently + only affects virt_text highlights, but might + affect`hl_group`in later versions. + • "replace": only show the virt_text color. + This is the default + • "combine": combine with background text + color + • "blend": blend with background text color. + • ephemeral : for use with |nvim_set_decoration_provider| callbacks. The mark will only be used for the current redraw @@ -2468,6 +2518,21 @@ nvim_win_get_width({window}) *nvim_win_get_width()* Return: ~ Width as a count of columns +nvim_win_hide({window}) *nvim_win_hide()* + Closes the window and hide the buffer it contains (like + |:hide| with a |window-ID|). + + Like |:hide| the buffer becomes hidden unless another window + is editing it, or 'bufhidden' is `unload` , `delete` or `wipe` + as opposed to |:close| or |nvim_win_close|, which will close + the buffer. + + Attributes: ~ + not allowed when |textlock| is active + + Parameters: ~ + {window} Window handle, or 0 for current window + nvim_win_is_valid({window}) *nvim_win_is_valid()* Checks if a window is valid diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index f3ed086933..310d244fbc 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -445,6 +445,9 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right* *<* <{motion} Shift {motion} lines one 'shiftwidth' leftwards. + If the 'shiftwidth' option is set to zero, the amount + of indent is calculated at the first non-blank + character in the line. *<<* << Shift [count] lines one 'shiftwidth' leftwards. @@ -455,6 +458,9 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right* *>* >{motion} Shift {motion} lines one 'shiftwidth' rightwards. + If the 'shiftwidth' option is set to zero, the amount + of indent is calculated at the first non-blank + character in the line. *>>* >> Shift [count] lines one 'shiftwidth' rightwards. @@ -934,6 +940,10 @@ This replaces each 'E' character with a euro sign. Read more in |<Char->|. this (that's a good habit anyway). `:retab!` may also change a sequence of spaces by <Tab> characters, which can mess up a printf(). + A list of tab widths separated by commas may be used + in place of a single tabstop. Each value in the list + represents the width of one tabstop, except the final + value which applies to all following tabstops. *retab-example* Example for using autocommands and ":retab" to edit a file which is stored diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index ac398ec494..aa964a521f 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -90,7 +90,7 @@ g CTRL-G Prints the current position of the cursor in five :buffers :files :ls List all the currently known file names. See - 'windows.txt' |:files| |:buffers| |:ls|. + |windows.txt| |:files| |:buffers| |:ls|. Vim will remember the full path name of a file name that you enter. In most cases when the file name is displayed only the name you typed is shown, but @@ -1190,7 +1190,7 @@ The syntax is best shown via some examples: > < Open the browser in the C:/bar directory, with the current buffer filename as default, and save the buffer under the filename chosen. -Also see the |'browsedir'| option. +Also see the 'browsedir' option. For versions of Vim where browsing is not supported, the command is executed unmodified. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index be7c026f5a..2911224de5 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -444,7 +444,7 @@ as a key. To avoid having to put quotes around every key the #{} form can be used. This does require the key to consist only of ASCII letters, digits, '-' and '_'. Example: > - let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3} + :let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3} Note that 333 here is the string "333". Empty keys are not possible with #{}. A value can be any expression. Using a Dictionary for a value creates a @@ -2308,7 +2308,6 @@ perleval({expr}) any evaluate |perl| expression pow({x}, {y}) Float {x} to the power of {y} prevnonblank({lnum}) Number line nr of non-blank line <= {lnum} printf({fmt}, {expr1}...) String format text -prompt_addtext({buf}, {expr}) none add text to a prompt buffer prompt_setcallback({buf}, {expr}) none set prompt callback function prompt_setinterrupt({buf}, {text}) none set prompt interrupt function prompt_setprompt({buf}, {text}) none set prompt text @@ -2393,7 +2392,7 @@ sha256({string}) String SHA256 checksum of {string} shellescape({string} [, {special}]) String escape {string} for use as shell command argument -shiftwidth() Number effective value of 'shiftwidth' +shiftwidth([{col}]) Number effective value of 'shiftwidth' sign_define({name} [, {dict}]) Number define or update a sign sign_getdefined([{name}]) List get a list of defined signs sign_getplaced([{expr} [, {dict}]]) @@ -2430,7 +2429,7 @@ strcharpart({str}, {start} [, {len}]) String {len} characters of {str} at character {start} strdisplaywidth({expr} [, {col}]) Number display length of the String {expr} -strftime({format} [, {time}]) String time in specified format +strftime({format} [, {time}]) String format time with a specified format strgetchar({str}, {index}) Number get char {index} from {str} stridx({haystack}, {needle} [, {start}]) Number index of {needle} in {haystack} @@ -2439,6 +2438,8 @@ strlen({expr}) Number length of the String {expr} strpart({str}, {start} [, {len} [, {chars}]]) String {len} bytes/chars of {str} at byte {start} +strptime({format}, {timestring}) + Number Convert {timestring} to unix timestamp strridx({haystack}, {needle} [, {start}]) Number last index of {needle} in {haystack} strtrans({expr}) String translate string to make it printable @@ -2498,6 +2499,8 @@ win_gotoid({expr}) Number go to |window-ID| {expr} win_id2tabwin({expr}) List get tab and window nr from |window-ID| win_id2win({expr}) Number get window nr from |window-ID| win_screenpos({nr}) List get screen position of window {nr} +win_splitmove({nr}, {target} [, {options}]) + none move window {nr} to split of {target} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} @@ -4981,7 +4984,7 @@ getwininfo([{winid}]) *getwininfo()* getwinpos([{timeout}]) *getwinpos()* The result is a list with two numbers, the result of - getwinposx() and getwinposy() combined: + |getwinposx()| and |getwinposy()| combined: [x-pos, y-pos] {timeout} can be used to specify how long to wait in msec for a response from the terminal. When omitted 100 msec is used. @@ -5851,7 +5854,7 @@ list2str({list} [, {utf8}]) *list2str()* < localtime() *localtime()* Return the current time, measured as seconds since 1st Jan - 1970. See also |strftime()| and |getftime()|. + 1970. See also |strftime()|, |strptime()| and |getftime()|. log({expr}) *log()* @@ -7895,7 +7898,7 @@ shellescape({string} [, {special}]) *shellescape()* < See also |::S|. -shiftwidth() *shiftwidth()* +shiftwidth([{col}]) *shiftwidth()* Returns the effective value of 'shiftwidth'. This is the 'shiftwidth' value unless it is zero, in which case it is the 'tabstop' value. To be backwards compatible in indent @@ -7911,6 +7914,11 @@ shiftwidth() *shiftwidth()* endif < And then use s:sw() instead of &sw. + When there is one argument {col} this is used as column number + for which to return the 'shiftwidth' value. This matters for the + 'vartabstop' feature. If no {col} argument is given, column 1 + will be assumed. + sign_define({name} [, {dict}]) *sign_define()* Define a new sign named {name} or modify the attributes of an existing sign. This is similar to the |:sign-define| command. @@ -8486,7 +8494,7 @@ strftime({format} [, {time}]) *strftime()* {format} depends on your system, thus this is not portable! See the manual page of the C function strftime() for the format. The maximum length of the result is 80 characters. - See also |localtime()| and |getftime()|. + See also |localtime()|, |getftime()| and |strptime()|. The language can be changed with the |:language| command. Examples: > :echo strftime("%c") Sun Apr 27 11:49:23 1997 @@ -8576,6 +8584,31 @@ strpart({src}, {start} [, {len} [, {chars}]]) *strpart()* example, to get the character under the cursor: > strpart(getline("."), col(".") - 1, 1, v:true) < +strptime({format}, {timestring}) *strptime()* + The result is a Number, which is a unix timestamp representing + the date and time in {timestring}, which is expected to match + the format specified in {format}. + + The accepted {format} depends on your system, thus this is not + portable! See the manual page of the C function strptime() + for the format. Especially avoid "%c". The value of $TZ also + matters. + + If the {timestring} cannot be parsed with {format} zero is + returned. If you do not know the format of {timestring} you + can try different {format} values until you get a non-zero + result. + + See also |strftime()|. + Examples: > + :echo strptime("%Y %b %d %X", "1997 Apr 27 11:49:23") +< 862156163 > + :echo strftime("%c", strptime("%y%m%d %T", "970427 11:53:55")) +< Sun Apr 27 11:53:55 1997 > + :echo strftime("%c", strptime("%Y%m%d%H%M%S", "19970427115355") + 3600) +< Sun Apr 27 12:53:55 1997 + + strridx({haystack}, {needle} [, {start}]) *strridx()* The result is a Number, which gives the byte index in {haystack} of the last occurrence of the String {needle}. @@ -9370,6 +9403,25 @@ win_screenpos({nr}) *win_screenpos()* Return [0, 0] if the window cannot be found in the current tabpage. +win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* + Move the window {nr} to a new split of the window {target}. + This is similar to moving to {target}, creating a new window + using |:split| but having the same contents as window {nr}, and + then closing {nr}. + + Both {nr} and {target} can be window numbers or |window-ID|s. + + Returns zero for success, non-zero for failure. + + {options} is a Dictionary with the following optional entries: + "vertical" When TRUE, the split is created vertically, + like with |:vsplit|. + "rightbelow" When TRUE, the split is made below or to the + right (if vertical). When FALSE, it is done + above or to the left (if vertical). When not + present, the values of 'splitbelow' and + 'splitright' are used. + *winbufnr()* winbufnr({nr}) The result is a Number, which is the number of the buffer associated with window {nr}. {nr} can be the window number or diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index c4b93a2a27..6902ed5fd4 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -287,8 +287,7 @@ character is written at the end of each line. Thus if you want to insert a *i_CTRL-X* *insert_expand* CTRL-X enters a sub-mode where several commands can be used. Most of these -commands do keyword completion; see |ins-completion|. These are not available -when Vim was compiled without the |+insert_expand| feature. +commands do keyword completion; see |ins-completion|. Two commands can be used to scroll the window up or down, without exiting insert mode: @@ -592,9 +591,6 @@ In Insert and Replace mode, there are several commands to complete part of a keyword or line that has been typed. This is useful if you are using complicated keywords (e.g., function names with capitals and underscores). -These commands are not available when the |+insert_expand| feature was -disabled at compile time. - Completion can be done for: 1. Whole lines |i_CTRL-X_CTRL-L| diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index d2d88fb9ba..67a10c7efb 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -749,15 +749,6 @@ start_client({config}) *vim.lsp.start_client()* The following parameters describe fields in the {config} table. -> - - -- In attach function for the client, you can do: - local custom_attach = function(client) - if client.config.flags then - client.config.flags.allow_incremental_sync = true - end - end -< Parameters: ~ {root_dir} (required, string) Directory where the @@ -799,6 +790,8 @@ start_client({config}) *vim.lsp.start_client()* See `initialize` in the LSP spec. {name} (string, default=client-id) Name in log messages. + {get_language_id} function(bufnr, filetype) -> language + ID as string. Defaults to the filetype. {offset_encoding} (default="utf-16") One of "utf-8", "utf-16", or "utf-32" which is the encoding that the LSP server expects. @@ -854,8 +847,8 @@ start_client({config}) *vim.lsp.start_client()* {flags} A table with flags for the client. The current (experimental) flags are: • allow_incremental_sync (bool, default - false): Allow using on_line callbacks - for lsp + true): Allow using incremental sync + for buffer edits Return: ~ Client id. |vim.lsp.get_client_by_id()| Note: client may @@ -1469,8 +1462,8 @@ show_line_diagnostics({opts}, {bufnr}, {line_nr}, {client_id}) ============================================================================== Lua module: vim.lsp.handlers *lsp-handlers* - *vim.lsp.handlers.progress_callback()* -progress_callback({_}, {_}, {params}, {client_id}) + *vim.lsp.handlers.progress_handler()* +progress_handler({_}, {_}, {params}, {client_id}) See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand @@ -1547,6 +1540,18 @@ close_preview_autocmd({events}, {winnr}) See also: ~ |autocmd-events| + *vim.lsp.util.compute_diff()* +compute_diff({old_lines}, {new_lines}, {start_line_idx}, {end_line_idx}) + Returns the range table for the difference between old and new + lines + + Parameters: ~ + {old_lines} table list of lines + {new_lines} table list of lines + + Return: ~ + table start_line_idx and start_col_idx of range + *vim.lsp.util.convert_input_to_markdown_lines()* convert_input_to_markdown_lines({input}, {contents}) Converts any of `MarkedString` | `MarkedString[]` | @@ -1581,6 +1586,12 @@ convert_signature_help_to_markdown_lines({signature_help}) See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp +create_file({change}) *vim.lsp.util.create_file()* + TODO: Documentation + +delete_file({change}) *vim.lsp.util.delete_file()* + TODO: Documentation + *vim.lsp.util.extract_completion_items()* extract_completion_items({result}) Can be used to extract the completion items from a `textDocument/completion` request, which may return one of `CompletionItem[]` , `CompletionList` or null. @@ -1788,12 +1799,12 @@ make_workspace_params({added}, {removed}) {removed} *vim.lsp.util.open_floating_preview()* -open_floating_preview({contents}, {filetype}, {opts}) +open_floating_preview({contents}, {syntax}, {opts}) Shows contents in a floating window. Parameters: ~ {contents} table of lines to show in window - {filetype} string of filetype to set for opened buffer + {syntax} string of syntax to set for opened buffer {opts} dictionary with optional fields Return: ~ @@ -1824,6 +1835,10 @@ preview_location({location}) *vim.lsp.util.preview_location()* (bufnr,winnr) buffer and window number of floating window or nil +rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()* + Parameters: ~ + {opts} (table) + set_lines({lines}, {A}, {B}, {new_lines}) *vim.lsp.util.set_lines()* Replaces text in a range with new text. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 0bbed56662..c2fc25431c 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1055,6 +1055,18 @@ list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()* See also: ~ |vim.tbl_extend()| +list_slice({list}, {start}, {finish}) *vim.list_slice()* + Creates a copy of a table containing only elements from start + to end (inclusive) + + Parameters: ~ + {list} table table + {start} integer Start range of slice + {finish} integer End range of slice + + Return: ~ + Copy of table sliced from start to finish (inclusive) + pesc({s}) *vim.pesc()* Escapes magic chars in a Lua pattern. diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index edec4a8de7..73ac3763d0 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -224,6 +224,20 @@ text before the cursor and start omni completion when some condition is met. For abbreviations |v:char| is set to the character that was typed to trigger the abbreviation. You can use this to decide how to expand the {lhs}. You should not either insert or change the v:char. + +Also, 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('.') + return 'x' + endfunc + nnoremap <expr> x StoreColumn() + nmap ! f!x +You will notice that g:column has the value from before executing "fx", +because "z" is evaluated before "fx" is executed. +This can be solved by inserting <Ignore> before the character that is +expression-mapped: > + nmap ! f!<Ignore>x Be very careful about side effects! The expression is evaluated while obtaining characters, you may very well make the command dysfunctional. @@ -276,7 +290,7 @@ as a special key. *<Cmd>* *:map-cmd* The <Cmd> pseudokey begins a "command mapping", which executes the command directly (without changing modes). Where you might use ":...<CR>" in the -{lhs} of a mapping, you can instead use "<Cmd>...<CR>". +{rhs} of a mapping, you can instead use "<Cmd>...<CR>". Example: > noremap x <Cmd>echo mode(1)<cr> < @@ -300,7 +314,7 @@ Note: *E5520* <Cmd> commands must terminate, that is, they must be followed by <CR> in the -{lhs} of the mapping definition. |Command-line| mode is never entered. +{rhs} of the mapping definition. |Command-line| mode is never entered. 1.3 MAPPING AND MODES *:map-modes* diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index bec2b362ea..5885b20ab7 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -312,6 +312,8 @@ Other commands ~ *:Program* jump to the window with the running program *:Source* jump to the window with the source code, create it if there isn't one + *:Asm* jump to the window with the disassembly, create it if there + isn't one Prompt mode ~ @@ -330,6 +332,12 @@ This works slightly differently: Prompt mode can be used even when the |+terminal| feature is present with: > let g:termdebug_use_prompt = 1 +< + *termdebug_disasm_window* +If you want the Asm window shown by default, set this to 1. Setting to +any value greater than 1 will set the Asm window height to that value: > + let g:termdebug_disasm_window = 15 +< Communication ~ *termdebug-communication* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index ce3788e0fc..04310ca8d4 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3716,6 +3716,10 @@ A jump table for the options with a short description can be found at |Q_op|. *lcs-space* space:c Character to show for a space. When omitted, spaces are left blank. + *lcs-lead* + lead:c Character to show for leading spaces. When omitted, + leading spaces are blank. Overrides the "space" + setting for leading spaces. *lcs-trail* trail:c Character to show for trailing spaces. When omitted, trailing spaces are blank. Overrides the "space" @@ -4090,8 +4094,6 @@ A jump table for the options with a short description can be found at |Q_op|. In the "popup" model the right mouse button produces a pop-up menu. You need to define this first, see |popup-menu|. - In a terminal the popup menu works if Vim is compiled with the - |+insert_expand| option. Note that you can further refine the meaning of buttons with mappings. See |mouse-overview|. But mappings are NOT used for modeless selection. @@ -4858,7 +4860,9 @@ A jump table for the options with a short description can be found at |Q_op|. local to window Number of lines to scroll with CTRL-U and CTRL-D commands. Will be set to half the number of lines in the window when the window size - changes. If you give a count to the CTRL-U or CTRL-D command it will + changes. This may happen when enabling the |status-line| or + 'tabline' option after setting the 'scroll' option. + If you give a count to the CTRL-U or CTRL-D command it will be used as the new value for 'scroll'. Reset to half the window height with ":set scroll=0". @@ -5621,6 +5625,9 @@ A jump table for the options with a short description can be found at |Q_op|. The 'L' flag in 'cpoptions' changes how tabs are used when 'list' is set. + The value of 'softtabstop' will be ignored if |'varsofttabstop'| is set + to anything other than an empty string. + *'spell'* *'nospell'* 'spell' boolean (default off) local to window @@ -6158,6 +6165,9 @@ A jump table for the options with a short description can be found at |Q_op|. though. Otherwise aligned comments will be wrong when 'tabstop' is changed. + The value of 'tabstop' will be ignored if |'vartabstop'| is set to + anything other than an empty string. + *'tagbsearch'* *'tbs'* *'notagbsearch'* *'notbs'* 'tagbsearch' 'tbs' boolean (default on) global @@ -6542,6 +6552,38 @@ A jump table for the options with a short description can be found at |Q_op|. written to disk (see |crash-recovery|). Also used for the |CursorHold| autocommand event. + *'varsofttabstop'* *'vsts'* +'varsofttabstop' 'vsts' string (default "") + local to buffer + A list of the number of spaces that a <Tab> counts for while editing, + such as inserting a <Tab> or using <BS>. It "feels" like variable- + width <Tab>s are being inserted, while in fact a mixture of spaces + and <Tab>s is used. Tab widths are separated with commas, with the + final value applying to all subsequent tabs. + + For example, when editing assembly language files where statements + start in the 8th column and comments in the 40th, it may be useful + to use the following: > + :set varsofttabstop=8,32,8 +< This will set soft tabstops at the 8th and 40th columns, and at every + 8th column thereafter. + + Note that the value of |'softtabstop'| will be ignored while + 'varsofttabstop' is set. + + *'vartabstop'* *'vts'* +'vartabstop' 'vts' string (default "") + local to buffer + A list of the number of spaces that a <Tab> in the file counts for, + separated by commas. Each value corresponds to one tab, with the + final value applying to all subsequent tabs. For example: > + :set vartabstop=4,20,10,8 +< This will make the first tab 4 spaces wide, the second 20 spaces, + the third 10 spaces, and all following tabs 8 spaces. + + Note that the value of |'tabstop'| will be ignored while 'vartabstop' + is set. + *'verbose'* *'vbs'* 'verbose' 'vbs' number (default 0) global diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 4a99aa47bf..d3647246fa 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -106,8 +106,6 @@ argument. This can be used to find out where time is spent while loading your |config|, plugins and opening the first file. When {fname} already exists new messages are appended. - (Only available when compiled with the |+startuptime| - feature). *-+* +[num] The cursor will be positioned on line "num" for the first diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 7da886dabd..aeee02a1e0 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1715,7 +1715,7 @@ There are several html preprocessor languages out there. html.vim has been written such that it should be trivial to include it. To do so add the following two lines to the syntax coloring file for that language (the example comes from the asp.vim file): - +> runtime! syntax/html.vim syn cluster htmlPreproc add=asp @@ -4689,6 +4689,7 @@ in their own color. highlighting for groups added by the user! Uses the current value of 'background' to decide which default colors to use. + If there was a default link, restore it. |:hi-link| :hi[ghlight] clear {group-name} :hi[ghlight] {group-name} NONE diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 23db809543..7d09ca86ac 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -337,11 +337,11 @@ the same as above, with a "p" prepended. A static tag is a tag that is defined for a specific file. In a C program this could be a static function. -In Vi jumping to a tag sets the current search pattern. This means that -the "n" command after jumping to a tag does not search for the same pattern -that it did before jumping to the tag. Vim does not do this as we consider it -to be a bug. You can still find the tag search pattern in the search history. -If you really want the old Vi behavior, set the 't' flag in 'cpoptions'. +In Vi jumping to a tag sets the current search pattern. This means that the +"n" command after jumping to a tag does not search for the same pattern that +it did before jumping to the tag. Vim does not do this as we consider it to +be a bug. If you really want the old Vi behavior, set the 't' flag in +'cpoptions'. *tag-binary-search* Vim uses binary searching in the tags file to find the desired tag quickly @@ -419,8 +419,7 @@ would otherwise go unnoticed. Example: > In Vi the ":tag" command sets the last search pattern when the tag is searched for. In Vim this is not done, the previous search pattern is still remembered, -unless the 't' flag is present in 'cpoptions'. The search pattern is always -put in the search history, so you can modify it if searching fails. +unless the 't' flag is present in 'cpoptions'. *tags-option* The 'tags' option is a list of file names. Each of these files is searched @@ -847,19 +846,25 @@ like |CTRL-]|. The function used for generating the taglist is specified by setting the 'tagfunc' option. The function will be called with three arguments: - a:pattern The tag identifier used during the tag search. - a:flags List of flags to control the function behavior. + a:pattern The tag identifier or pattern used during the tag search. + a:flags String containing flags to control the function behavior. a:info Dict containing the following entries: buf_ffname Full filename which can be used for priority. user_data Custom data String, if stored in the tag stack previously by tagfunc. -Currently two flags may be passed to the tag function: +Currently up to three flags may be passed to the tag function: 'c' The function was invoked by a normal command being processed (mnemonic: the tag function may use the context around the cursor to perform a better job of generating the tag list.) 'i' In Insert mode, the user was completing a tag (with - |i_CTRL-X_CTRL-]|). + |i_CTRL-X_CTRL-]| or 'completeopt' contains `t`). + 'r' The first argument to tagfunc should be interpreted as a + |pattern| (see |tag-regexp|), such as when using: > + :tag /pat +< It is also given when completing in insert mode. + If this flag is not present, the argument is usually taken + literally as the full tag name. Note that when 'tagfunc' is set, the priority of the tags described in |tag-priority| does not apply. Instead, the priority is exactly as the diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 1696d3b9ba..343f4a62c2 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -32,6 +32,12 @@ retained for the lifetime of a buffer but this is subject to change. A plugin should keep a reference to the parser object as long as it wants incremental updates. + *vim.treesitter.language_version* +To check which language version is compiled with neovim, the number is stored +within `vim.treesitter.language_version`. This number is not too helpful +unless you are wondering about compatibility between different versions of +compiled grammars. + Parser files *treesitter-parsers* Parsers are the heart of tree-sitter. They are libraries that tree-sitter will diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 63c899da0c..97aacc1403 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -788,6 +788,7 @@ Date and Time: *date-functions* *time-functions* getftime() get last modification time of a file localtime() get current time in seconds strftime() convert time to a string + strptime() convert a date/time string to time reltime() get the current or elapsed time accurately reltimestr() convert reltime() result to a string reltimefloat() convert reltime() result to a Float diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 0c1e216164..eadc1c04a0 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -70,6 +70,8 @@ the differences. - |matchit| plugin is enabled. To disable it in your config: > :let loaded_matchit = 1 +- |g:vimsyn_embed| defaults to "l" to enable Lua highlighting + ============================================================================== 3. New Features *nvim-features* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 6a13e67ac5..52cd2dcbfd 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -164,6 +164,9 @@ au BufNewFile,BufRead *.mar setf vmasm " Atlas au BufNewFile,BufRead *.atl,*.as setf atlas +" Atom is based on XML +au BufNewFile,BufRead *.atom setf xml + " Autoit v3 au BufNewFile,BufRead *.au3 setf autoit @@ -1272,6 +1275,11 @@ au BufNewFile,BufRead .povrayrc setf povini " Povray, Pascal, PHP or assembly au BufNewFile,BufRead *.inc call dist#ft#FTinc() +" PowerShell +au BufNewFile,BufRead *.ps1,*.psd1,*.psm1,*.pssc setf ps1 +au BufNewFile,BufRead *.ps1xml setf ps1xml +au BufNewFile,BufRead *.cdxml,*.psc1 setf xml + " Printcap and Termcap au BufNewFile,BufRead *printcap \ let b:ptcap_type = "print" | setf ptcap @@ -1330,6 +1338,9 @@ au BufNewFile,BufRead *.pml setf promela au BufNewFile,BufRead *.proto setf proto au BufNewFile,BufRead *.pbtxt setf pbtxt +" Poke +au BufNewFile,BufRead *.pk setf poke + " Protocols au BufNewFile,BufRead */etc/protocols setf protocols @@ -1394,6 +1405,9 @@ else au BufNewFile,BufRead *.rmd,*.smd setf rmd endif +" RSS looks like XML +au BufNewFile,BufRead *.rss setf xml + " R reStructuredText file if has("fname_case") au BufNewFile,BufRead *.Rrst,*.rrst,*.Srst,*.srst setf rrst diff --git a/runtime/indent/tcl.vim b/runtime/indent/tcl.vim index d77081841d..eafb8dd568 100644 --- a/runtime/indent/tcl.vim +++ b/runtime/indent/tcl.vim @@ -1,8 +1,8 @@ " Vim indent file " Language: Tcl -" Previous Maintainer: Nikolai Weibull <now@bitwi.se> " Latest Update: Chris Heithoff <chrisheithoff@gmail.com> -" Latest Revision: 2018-12-05 +" Previous Maintainer: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2018-12-05 if exists("b:did_indent") finish diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 143909fe41..563ffc479e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -38,11 +38,13 @@ lsp._request_name_to_capability = { ['textDocument/declaration'] = 'declaration'; ['textDocument/typeDefinition'] = 'type_definition'; ['textDocument/documentSymbol'] = 'document_symbol'; - ['textDocument/workspaceSymbol'] = 'workspace_symbol'; ['textDocument/prepareCallHierarchy'] = 'call_hierarchy'; ['textDocument/rename'] = 'rename'; ['textDocument/codeAction'] = 'code_action'; + ['textDocument/codeLens'] = 'code_lens'; + ['codeLens/resolve'] = 'code_lens_resolve'; ['workspace/executeCommand'] = 'execute_command'; + ['workspace/symbol'] = 'workspace_symbol'; ['textDocument/references'] = 'find_references'; ['textDocument/rangeFormatting'] = 'document_range_formatting'; ['textDocument/formatting'] = 'document_formatting'; @@ -228,6 +230,7 @@ local function validate_client_config(config) before_init = { config.before_init, "f", true }; offset_encoding = { config.offset_encoding, "s", true }; flags = { config.flags, "t", true }; + get_language_id = { config.get_language_id, "f", true }; } local cmd, cmd_args = lsp._cmd_parts(config.cmd) @@ -262,23 +265,47 @@ end --@param bufnr (Number) Number of the buffer, or 0 for current --@param client Client object local function text_document_did_open_handler(bufnr, client) + local use_incremental_sync = ( + if_nil(client.config.flags.allow_incremental_sync, true) + and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental + ) + if use_incremental_sync then + if not client._cached_buffers then + client._cached_buffers = {} + end + client._cached_buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true) + end if not client.resolved_capabilities.text_document_open_close then return end if not vim.api.nvim_buf_is_loaded(bufnr) then return end + local filetype = nvim_buf_get_option(bufnr, 'filetype') + local params = { textDocument = { version = 0; uri = vim.uri_from_bufnr(bufnr); - -- TODO make sure our filetypes are compatible with languageId names. - languageId = nvim_buf_get_option(bufnr, 'filetype'); + languageId = client.config.get_language_id(bufnr, filetype); text = buf_get_full_text(bufnr); } } client.notify('textDocument/didOpen', params) util.buf_versions[bufnr] = params.textDocument.version + + -- Next chance we get, we should re-do the diagnostics + vim.schedule(function() + vim.lsp.handlers["textDocument/publishDiagnostics"]( + nil, + "textDocument/publishDiagnostics", + { + diagnostics = vim.lsp.diagnostic.get(bufnr, client.id), + uri = vim.uri_from_bufnr(bufnr), + }, + client.id + ) + end) end -- FIXME: DOC: Shouldn't need to use a dummy function @@ -400,6 +427,9 @@ end --- --@param name (string, default=client-id) Name in log messages. --- +--@param get_language_id function(bufnr, filetype) -> language ID as string. +--- Defaults to the filetype. +--- --@param offset_encoding (default="utf-16") One of "utf-8", "utf-16", --- or "utf-32" which is the encoding that the LSP server expects. Client does --- not verify this is correct. @@ -438,16 +468,7 @@ end --@param trace: "off" | "messages" | "verbose" | nil passed directly to the language --- server in the initialize request. Invalid/empty values will default to "off" --@param flags: A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default false): Allow using on_line callbacks for lsp ---- ---- <pre> ---- -- In attach function for the client, you can do: ---- local custom_attach = function(client) ---- if client.config.flags then ---- client.config.flags.allow_incremental_sync = true ---- end ---- end ---- </pre> +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits --- --@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once @@ -459,6 +480,11 @@ function lsp.start_client(config) config.flags = config.flags or {} config.settings = config.settings or {} + -- By default, get_language_id just returns the exact filetype it is passed. + -- It is possible to pass in something that will calculate a different filetype, + -- to be sent by the client. + config.get_language_id = config.get_language_id or function(_, filetype) return filetype end + local client_id = next_client_id() local handlers = config.handlers or {} @@ -542,6 +568,13 @@ function lsp.start_client(config) client_ids[client_id] = nil end + if code ~= 0 or (signal ~= 0 and signal ~= 15) then + local msg = string.format("Client %s quit with exit code %s and signal %s", client_id, code, signal) + vim.schedule(function() + vim.notify(msg, vim.log.levels.WARN) + end) + end + if config.on_exit then pcall(config.on_exit, code, signal, client_id) end @@ -801,7 +834,6 @@ end --- Notify all attached clients that a buffer has changed. local text_document_did_change_handler do - local encoding_index = { ["utf-8"] = 1; ["utf-16"] = 2; ["utf-32"] = 3; } text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size) @@ -818,45 +850,30 @@ do end util.buf_versions[bufnr] = changedtick - -- Lazy initialize these because clients may not even need them. - local incremental_changes = once(function(client) - local size_index = encoding_index[client.offset_encoding] - local length = select(size_index, old_byte_size, old_utf16_size, old_utf32_size) - local lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true) - - -- This is necessary because we are specifying the full line including the - -- newline in range. Therefore, we must replace the newline as well. - if #lines > 0 then - table.insert(lines, '') - end - return { - range = { - start = { line = firstline, character = 0 }; - ["end"] = { line = lastline, character = 0 }; - }; - rangeLength = length; - text = table.concat(lines, '\n'); - }; - end) + + local incremental_changes = function(client) + local lines = nvim_buf_get_lines(bufnr, 0, -1, true) + local startline = math.min(firstline + 1, math.min(#client._cached_buffers[bufnr], #lines)) + local endline = math.min(-(#lines - new_lastline), -1) + local incremental_change = vim.lsp.util.compute_diff( + client._cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or "utf-16") + client._cached_buffers[bufnr] = lines + return incremental_change + end + local full_changes = once(function() return { text = buf_get_full_text(bufnr); }; end) - local uri = vim.uri_from_bufnr(bufnr) - for_each_buffer_client(bufnr, function(client, _client_id) - local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, false) + local uri = vim.uri_from_bufnr(bufnr) + for_each_buffer_client(bufnr, function(client) + local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, true) local text_document_did_change = client.resolved_capabilities.text_document_did_change local changes if text_document_did_change == protocol.TextDocumentSyncKind.None then return - --[=[ TODO(ashkan) there seem to be problems with the byte_sizes sent by - -- neovim right now so only send the full content for now. In general, we - -- can assume that servers *will* support both versions anyway, as there - -- is no way to specify the sync capability by the client. - -- See https://github.com/palantir/python-language-server/commit/cfd6675bc10d5e8dbc50fc50f90e4a37b7178821#diff-f68667852a14e9f761f6ebf07ba02fc8 for an example of pyls handling both. - --]=] elseif not allow_incremental_sync or text_document_did_change == protocol.TextDocumentSyncKind.Full then changes = full_changes(client) elseif text_document_did_change == protocol.TextDocumentSyncKind.Incremental then @@ -914,16 +931,34 @@ function lsp.buf_attach_client(bufnr, client_id) all_buffer_active_clients[bufnr] = buffer_client_ids local uri = vim.uri_from_bufnr(bufnr) - nvim_command(string.format("autocmd BufWritePost <buffer=%d> lua vim.lsp._text_document_did_save_handler(0)", bufnr)) + local buf_did_save_autocommand = [=[ + augroup lsp_c_%d_b_%d_did_save + au! + au BufWritePost <buffer=%d> lua vim.lsp._text_document_did_save_handler(0) + augroup END + ]=] + vim.api.nvim_exec(string.format(buf_did_save_autocommand, client_id, bufnr, bufnr), false) -- First time, so attach and set up stuff. vim.api.nvim_buf_attach(bufnr, false, { on_lines = text_document_did_change_handler; + on_reload = function() + local params = { textDocument = { uri = uri; } } + for_each_buffer_client(bufnr, function(client, _) + if client.resolved_capabilities.text_document_open_close then + client.notify('textDocument/didClose', params) + end + text_document_did_open_handler(bufnr, client) + end) + end; on_detach = function() local params = { textDocument = { uri = uri; } } for_each_buffer_client(bufnr, function(client, _) if client.resolved_capabilities.text_document_open_close then client.notify('textDocument/didClose', params) end + if client._cached_buffers then + client._cached_buffers[bufnr] = nil + end end) util.buf_versions[bufnr] = nil all_buffer_active_clients[bufnr] = nil diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index df25943ecd..4e82c46fef 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -264,10 +264,16 @@ local function set_diagnostic_cache(diagnostics, bufnr, client_id) -- The diagnostic's severity. Can be omitted. If omitted it is up to the -- client to interpret diagnostics as error, warning, info or hint. -- TODO: Replace this with server-specific heuristics to infer severity. + local buf_line_count = vim.api.nvim_buf_line_count(bufnr) for _, diagnostic in ipairs(diagnostics) do if diagnostic.severity == nil then diagnostic.severity = DiagnosticSeverity.Error end + -- Account for servers that place diagnostics on terminating newline + if buf_line_count > 0 then + local start = diagnostic.range.start + start.line = math.min(start.line, buf_line_count - 1) + end end diagnostic_cache[bufnr][client_id] = diagnostics diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 7819bddcb9..eacbd90077 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -26,7 +26,7 @@ end -- @msg of type ProgressParams -- Basically a token of type number/string -local function progress_callback(_, _, params, client_id) +local function progress_handler(_, _, params, client_id) local client = vim.lsp.get_client_by_id(client_id) local client_name = client and client.name or string.format("id=%d", client_id) if not client then @@ -62,7 +62,7 @@ local function progress_callback(_, _, params, client_id) end --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress -M['$/progress'] = progress_callback +M['$/progress'] = progress_handler --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create M['window/workDoneProgress/create'] = function(_, _, params, client_id) @@ -304,7 +304,7 @@ M['textDocument/typeDefinition'] = location_handler M['textDocument/implementation'] = location_handler --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp -M['textDocument/signatureHelp'] = function(_, method, result) +M['textDocument/signatureHelp'] = function(_, method, result, _, bufnr) -- When use `autocmd CompleteDone <silent><buffer> lua vim.lsp.buf.signature_help()` to call signatureHelp handler -- If the completion item doesn't have signatures It will make noise. Change to use `print` that can use `<silent>` to ignore if not (result and result.signatures and result.signatures[1]) then @@ -317,9 +317,11 @@ M['textDocument/signatureHelp'] = function(_, method, result) print('No signature help available') return end - util.focusable_preview(method, function() + local syntax = api.nvim_buf_get_option(bufnr, 'syntax') + local p_bufnr, _ = util.focusable_preview(method, function() return lines, util.try_trim_markdown_code_blocks(lines) end) + api.nvim_buf_set_option(p_bufnr, 'syntax', syntax) end --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 4e8d2d4202..331e980e67 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -32,6 +32,8 @@ do vim.fn.mkdir(vim.fn.stdpath('cache'), "p") local logfile = assert(io.open(logfilename, "a+")) + -- Start message for logging + logfile:write(string.format("[ START ] %s ] LSP logging initiated\n", os.date(log_date_format))) for level, levelnr in pairs(log.levels) do -- Also export the log level on the root object. log[level] = levelnr @@ -68,8 +70,6 @@ do logfile:flush() end end - -- Add some space to make it easier to distinguish different neovim runs. - logfile:write("\n") end -- This is put here on purpose after the loop above so that it doesn't diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 388f65c180..7e43eb84de 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -749,6 +749,9 @@ function protocol.make_client_capabilities() }; workspaceFolders = true; applyEdit = true; + workspaceEdit = { + resourceOperations = {'rename', 'create', 'delete',}, + }; }; callHierarchy = { dynamicRegistration = false; @@ -975,6 +978,16 @@ function protocol.resolve_capabilities(server_capabilities) general_properties.rename = true end + if server_capabilities.codeLensProvider == nil then + general_properties.code_lens = false + general_properties.code_lens_resolve = false + elseif type(server_capabilities.codeLensProvider) == 'table' then + general_properties.code_lens = true + general_properties.code_lens_resolve = server_capabilities.codeLensProvider.resolveProvider or false + else + error("The server sent invalid codeLensProvider") + end + if server_capabilities.codeActionProvider == nil then general_properties.code_action = false elseif type(server_capabilities.codeActionProvider) == 'boolean' diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 4e2dd7c8e8..1aa8326514 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -315,8 +315,10 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) dispatchers = { dispatchers, 't', true }; } - if not (vim.fn.executable(cmd) == 1) then - error(string.format("The given command %q is not executable.", cmd)) + if extra_spawn_params and extra_spawn_params.cwd then + assert(is_dir(extra_spawn_params.cwd), "cwd must be a directory") + elseif not (vim.fn.executable(cmd) == 1) then + error(string.format("The given command %q is not executable.", cmd)) end if dispatchers then local user_dispatchers = dispatchers @@ -370,9 +372,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) } if extra_spawn_params then spawn_params.cwd = extra_spawn_params.cwd - if spawn_params.cwd then - assert(is_dir(spawn_params.cwd), "cwd must be a directory") - end spawn_params.env = env_merge(extra_spawn_params.env) end handle, pid = uv.spawn(cmd, spawn_params, onexit) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 6fb9f09c99..ec1131ae1f 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -226,6 +226,177 @@ end -- function M.glob_to_regex(glob) -- end +--@private +--- Finds the first line and column of the difference between old and new lines +--@param old_lines table list of lines +--@param new_lines table list of lines +--@returns (int, int) start_line_idx and start_col_idx of range +local function first_difference(old_lines, new_lines, start_line_idx) + local line_count = math.min(#old_lines, #new_lines) + if line_count == 0 then return 1, 1 end + if not start_line_idx then + for i = 1, line_count do + start_line_idx = i + if old_lines[start_line_idx] ~= new_lines[start_line_idx] then + break + end + end + end + local old_line = old_lines[start_line_idx] + local new_line = new_lines[start_line_idx] + local length = math.min(#old_line, #new_line) + local start_col_idx = 1 + while start_col_idx <= length do + if string.sub(old_line, start_col_idx, start_col_idx) ~= string.sub(new_line, start_col_idx, start_col_idx) then + break + end + start_col_idx = start_col_idx + 1 + end + return start_line_idx, start_col_idx +end + + +--@private +--- Finds the last line and column of the differences between old and new lines +--@param old_lines table list of lines +--@param new_lines table list of lines +--@param start_char integer First different character idx of range +--@returns (int, int) end_line_idx and end_col_idx of range +local function last_difference(old_lines, new_lines, start_char, end_line_idx) + local line_count = math.min(#old_lines, #new_lines) + if line_count == 0 then return 0,0 end + if not end_line_idx then + end_line_idx = -1 + end + for i = end_line_idx, -line_count, -1 do + if old_lines[#old_lines + i + 1] ~= new_lines[#new_lines + i + 1] then + end_line_idx = i + break + end + end + local old_line + local new_line + if end_line_idx <= -line_count then + end_line_idx = -line_count + old_line = string.sub(old_lines[#old_lines + end_line_idx + 1], start_char) + new_line = string.sub(new_lines[#new_lines + end_line_idx + 1], start_char) + else + old_line = old_lines[#old_lines + end_line_idx + 1] + new_line = new_lines[#new_lines + end_line_idx + 1] + end + local old_line_length = #old_line + local new_line_length = #new_line + local length = math.min(old_line_length, new_line_length) + local end_col_idx = -1 + while end_col_idx >= -length do + local old_char = string.sub(old_line, old_line_length + end_col_idx + 1, old_line_length + end_col_idx + 1) + local new_char = string.sub(new_line, new_line_length + end_col_idx + 1, new_line_length + end_col_idx + 1) + if old_char ~= new_char then + break + end + end_col_idx = end_col_idx - 1 + end + return end_line_idx, end_col_idx + +end + +--@private +--- Get the text of the range defined by start and end line/column +--@param lines table list of lines +--@param start_char integer First different character idx of range +--@param end_char integer Last different character idx of range +--@param start_line integer First different line idx of range +--@param end_line integer Last different line idx of range +--@returns string text extracted from defined region +local function extract_text(lines, start_line, start_char, end_line, end_char) + if start_line == #lines + end_line + 1 then + if end_line == 0 then return '' end + local line = lines[start_line] + local length = #line + end_char - start_char + return string.sub(line, start_char, start_char + length + 1) + end + local result = string.sub(lines[start_line], start_char) .. '\n' + for line_idx = start_line + 1, #lines + end_line do + result = result .. lines[line_idx] .. '\n' + end + if end_line ~= 0 then + local line = lines[#lines + end_line + 1] + local length = #line + end_char + 1 + result = result .. string.sub(line, 1, length) + end + return result +end + +--@private +--- Compute the length of the substituted range +--@param lines table list of lines +--@param start_char integer First different character idx of range +--@param end_char integer Last different character idx of range +--@param start_line integer First different line idx of range +--@param end_line integer Last different line idx of range +--@returns (int, int) end_line_idx and end_col_idx of range +local function compute_length(lines, start_line, start_char, end_line, end_char) + local adj_end_line = #lines + end_line + 1 + local adj_end_char + if adj_end_line > #lines then + adj_end_char = end_char - 1 + else + adj_end_char = #lines[adj_end_line] + end_char + end + if start_line == adj_end_line then + return adj_end_char - start_char + 1 + end + local result = #lines[start_line] - start_char + 1 + for line = start_line + 1, adj_end_line -1 do + result = result + #lines[line] + 1 + end + result = result + adj_end_char + 1 + return result +end + +--- Returns the range table for the difference between old and new lines +--@param old_lines table list of lines +--@param new_lines table list of lines +--@param start_line_idx int line to begin search for first difference +--@param end_line_idx int line to begin search for last difference +--@param offset_encoding string encoding requested by language server +--@returns table start_line_idx and start_col_idx of range +function M.compute_diff(old_lines, new_lines, start_line_idx, end_line_idx, offset_encoding) + local start_line, start_char = first_difference(old_lines, new_lines, start_line_idx) + local end_line, end_char = last_difference(vim.list_slice(old_lines, start_line, #old_lines), + vim.list_slice(new_lines, start_line, #new_lines), start_char, end_line_idx) + local text = extract_text(new_lines, start_line, start_char, end_line, end_char) + local length = compute_length(old_lines, start_line, start_char, end_line, end_char) + + local adj_end_line = #old_lines + end_line + local adj_end_char + if end_line == 0 then + adj_end_char = 0 + else + adj_end_char = #old_lines[#old_lines + end_line + 1] + end_char + 1 + end + + local _ + if offset_encoding == "utf-16" then + _, start_char = vim.str_utfindex(old_lines[start_line], start_char - 1) + _, end_char = vim.str_utfindex(old_lines[#old_lines + end_line + 1], adj_end_char) + else + start_char = start_char - 1 + end_char = adj_end_char + end + + local result = { + range = { + start = { line = start_line - 1, character = start_char}, + ["end"] = { line = adj_end_line, character = end_char} + }, + text = text, + rangeLength = length + 1, + } + + return result +end + --- Can be used to extract the completion items from a --- `textDocument/completion` request, which may return one of --- `CompletionItem[]`, `CompletionList` or null. @@ -359,13 +530,13 @@ end --- precedence is as follows: textEdit.newText > insertText > label --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion local function get_completion_word(item) - if item.textEdit ~= nil and item.textEdit.newText ~= nil then + if item.textEdit ~= nil and item.textEdit.newText ~= nil and item.textEdit.newText ~= "" then if protocol.InsertTextFormat[item.insertTextFormat] == "PlainText" then return item.textEdit.newText else return M.parse_snippet(item.textEdit.newText) end - elseif item.insertText ~= nil then + elseif item.insertText ~= nil and item.insertText ~= "" then if protocol.InsertTextFormat[item.insertTextFormat] == "PlainText" then return item.insertText else @@ -453,6 +624,62 @@ function M.text_document_completion_list_to_complete_items(result, prefix) return matches end + +--- Rename old_fname to new_fname +-- +--@param opts (table) +-- overwrite? bool +-- ignoreIfExists? bool +function M.rename(old_fname, new_fname, opts) + opts = opts or {} + local bufnr = vim.fn.bufadd(old_fname) + vim.fn.bufload(bufnr) + local target_exists = vim.loop.fs_stat(new_fname) ~= nil + if target_exists and not opts.overwrite or opts.ignoreIfExists then + vim.notify('Rename target already exists. Skipping rename.') + return + end + local ok, err = os.rename(old_fname, new_fname) + assert(ok, err) + api.nvim_buf_call(bufnr, function() + vim.cmd('saveas! ' .. vim.fn.fnameescape(new_fname)) + end) +end + + +local function create_file(change) + local opts = change.options or {} + -- from spec: Overwrite wins over `ignoreIfExists` + local fname = vim.uri_to_fname(change.uri) + if not opts.ignoreIfExists or opts.overwrite then + local file = io.open(fname, 'w') + file:close() + end + vim.fn.bufadd(fname) +end + + +local function delete_file(change) + local opts = change.options or {} + local fname = vim.uri_to_fname(change.uri) + local stat = vim.loop.fs_stat(fname) + if opts.ignoreIfNotExists and not stat then + return + end + assert(stat, "Cannot delete not existing file or folder " .. fname) + local flags + if stat and stat.type == 'directory' then + flags = opts.recursive and 'rf' or 'd' + else + flags = '' + end + local bufnr = vim.fn.bufadd(fname) + local result = tonumber(vim.fn.delete(fname, flags)) + assert(result == 0, 'Could not delete file: ' .. fname .. ', stat: ' .. vim.inspect(stat)) + api.nvim_buf_delete(bufnr, { force = true }) +end + + --- Applies a `WorkspaceEdit`. --- --@param workspace_edit (table) `WorkspaceEdit` @@ -460,8 +687,17 @@ end function M.apply_workspace_edit(workspace_edit) if workspace_edit.documentChanges then for idx, change in ipairs(workspace_edit.documentChanges) do - if change.kind then - -- TODO(ashkan) handle CreateFile/RenameFile/DeleteFile + if change.kind == "rename" then + M.rename( + vim.uri_to_fname(change.oldUri), + vim.uri_to_fname(change.newUri), + change.options + ) + elseif change.kind == 'create' then + create_file(change) + elseif change.kind == 'delete' then + delete_file(change) + elseif change.kind then error(string.format("Unsupported change: %q", vim.inspect(change))) else M.apply_text_document_edit(change, idx) @@ -687,8 +923,8 @@ function M.preview_location(location) end local range = location.targetRange or location.range local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range["end"].line+1, false) - local filetype = api.nvim_buf_get_option(bufnr, 'filetype') - return M.open_floating_preview(contents, filetype) + local syntax = api.nvim_buf_get_option(bufnr, 'syntax') + return M.open_floating_preview(contents, syntax) end --@private @@ -873,8 +1109,10 @@ function M.fancy_floating_markdown(contents, opts) -- This is because the syntax command doesn't accept a target. local cwin = vim.api.nvim_get_current_win() vim.api.nvim_set_current_win(winnr) + api.nvim_win_set_option(winnr, 'conceallevel', 2) + api.nvim_win_set_option(winnr, 'concealcursor', 'n') - vim.cmd("ownsyntax markdown") + vim.cmd("ownsyntax lsp_markdown") local idx = 1 --@private local function apply_syntax_to_region(ft, start, finish) @@ -975,7 +1213,7 @@ end --- Shows contents in a floating window. --- --@param contents table of lines to show in window ---@param filetype string of filetype to set for opened buffer +--@param syntax string of syntax to set for opened buffer --@param opts dictionary with optional fields -- - height of floating window -- - width of floating window @@ -988,10 +1226,10 @@ end -- - pad_bottom number of lines to pad contents at bottom --@returns bufnr,winnr buffer and window number of the newly created floating ---preview window -function M.open_floating_preview(contents, filetype, opts) +function M.open_floating_preview(contents, syntax, opts) validate { contents = { contents, 't' }; - filetype = { filetype, 's', true }; + syntax = { syntax, 's', true }; opts = { opts, 't', true }; } opts = opts or {} @@ -1004,12 +1242,12 @@ function M.open_floating_preview(contents, filetype, opts) local width, height = M._make_floating_popup_size(contents, opts) local floating_bufnr = api.nvim_create_buf(false, true) - if filetype then - api.nvim_buf_set_option(floating_bufnr, 'filetype', filetype) + if syntax then + api.nvim_buf_set_option(floating_bufnr, 'syntax', syntax) end local float_option = M.make_floating_popup_options(width, height, opts) local floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option) - if filetype == 'markdown' then + if syntax == 'markdown' then api.nvim_win_set_option(floating_winnr, 'conceallevel', 2) end api.nvim_buf_set_lines(floating_bufnr, 0, -1, true, contents) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 998e04f568..0a663628a5 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -400,6 +400,20 @@ function vim.tbl_count(t) return count end +--- Creates a copy of a table containing only elements from start to end (inclusive) +--- +--@param list table table +--@param start integer Start range of slice +--@param finish integer End range of slice +--@returns Copy of table sliced from start to finish (inclusive) +function vim.list_slice(list, start, finish) + local new_list = {} + for i = start or 1, finish or #list do + new_list[#new_list+1] = list[i] + end + return new_list +end + --- Trim whitespace (Lua pattern "%s") from both sides of a string. --- --@see https://www.lua.org/pil/20.2.html diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 3af66b134c..cac0ab864b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -10,13 +10,11 @@ local parsers = {} local M = vim.tbl_extend("error", query, language) +M.language_version = vim._ts_get_language_version() + setmetatable(M, { __index = function (t, k) - if k == "TSHighlighter" then - a.nvim_err_writeln("vim.TSHighlighter is deprecated, please use vim.treesitter.highlighter") - t[k] = require'vim.treesitter.highlighter' - return t[k] - elseif k == "highlighter" then + if k == "highlighter" then t[k] = require'vim.treesitter.highlighter' return t[k] end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 6b833c6d35..fe7e1052c9 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -12,6 +12,16 @@ TSHighlighterQuery.__index = TSHighlighterQuery local ns = a.nvim_create_namespace("treesitter/highlighter") +local _default_highlights = {} +local _link_default_highlight_once = function(from, to) + if not _default_highlights[from] then + _default_highlights[from] = true + vim.cmd(string.format("highlight default link %s %s", from, to)) + end + + return from +end + -- These are conventions defined by nvim-treesitter, though it -- needs to be user extensible also. TSHighlighter.hl_map = { @@ -70,9 +80,12 @@ function TSHighlighterQuery.new(lang, query_string) self.hl_cache = setmetatable({}, { __index = function(table, capture) - local hl = self:get_hl_from_capture(capture) - rawset(table, capture, hl) + local hl, is_vim_highlight = self:_get_hl_from_capture(capture) + if not is_vim_highlight then + hl = _link_default_highlight_once(lang .. hl, hl) + end + rawset(table, capture, hl) return hl end }) @@ -90,16 +103,16 @@ function TSHighlighterQuery:query() return self._query end -function TSHighlighterQuery:get_hl_from_capture(capture) +--- Get the hl from capture. +--- Returns a tuple { highlight_name: string, is_builtin: bool } +function TSHighlighterQuery:_get_hl_from_capture(capture) local name = self._query.captures[capture] if is_highlight_name(name) then -- From "Normal.left" only keep "Normal" - return vim.split(name, '.', true)[1] + return vim.split(name, '.', true)[1], true else - -- Default to false to avoid recomputing - local hl = TSHighlighter.hl_map[name] - return hl and a.nvim_get_hl_id_by_name(hl) or 0 + return TSHighlighter.hl_map[name] or name, false end end @@ -208,6 +221,9 @@ local function on_line_impl(self, buf, line) local state = self:get_highlight_state(tstree) local highlighter_query = self:get_query(tree:lang()) + -- Some injected languages may not have highlight queries. + if not highlighter_query:query() then return end + if state.iter == nil then state.iter = highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1) end diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 8b94348994..f40e1d5294 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -8,10 +8,33 @@ Query.__index = Query local M = {} +local function dedupe_files(files) + local result = {} + local seen = {} + + for _, path in ipairs(files) do + if not seen[path] then + table.insert(result, path) + seen[path] = true + end + end + + return result +end + +local function safe_read(filename, read_quantifier) + local file, err = io.open(filename, 'r') + if not file then + error(err) + end + local content = file:read(read_quantifier) + io.close(file) + return content +end function M.get_query_files(lang, query_name, is_included) local query_path = string.format('queries/%s/%s.scm', lang, query_name) - local lang_files = a.nvim_get_runtime_file(query_path, true) + local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true)) if #lang_files == 0 then return {} end @@ -25,7 +48,7 @@ function M.get_query_files(lang, query_name, is_included) local MODELINE_FORMAT = "^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$" for _, file in ipairs(lang_files) do - local modeline = io.open(file, 'r'):read('*l') + local modeline = safe_read(file, '*l') if modeline then local langlist = modeline:match(MODELINE_FORMAT) @@ -60,7 +83,7 @@ local function read_query_files(filenames) local contents = {} for _,filename in ipairs(filenames) do - table.insert(contents, io.open(filename, 'r'):read('*a')) + table.insert(contents, safe_read(filename, '*a')) end return table.concat(contents, '') @@ -77,6 +100,27 @@ local function new_match_metadata() return setmetatable({}, match_metatable) end +--- The explicitly set queries from |vim.treesitter.query.set_query()| +local explicit_queries = setmetatable({}, { + __index = function(t, k) + local lang_queries = {} + rawset(t, k, lang_queries) + + return lang_queries + end, +}) + +--- Sets the runtime query {query_name} for {lang} +--- +--- This allows users to override any runtime files and/or configuration +--- set by plugins. +---@param lang string: The language to use for the query +---@param query_name string: The name of the query (i.e. "highlights") +---@param text string: The query text (unparsed). +function M.set_query(lang, query_name, text) + explicit_queries[lang][query_name] = M.parse_query(lang, text) +end + --- Returns the runtime query {query_name} for {lang}. -- -- @param lang The language to use for the query @@ -84,6 +128,10 @@ end -- -- @return The corresponding query, parsed. function M.get_query(lang, query_name) + if explicit_queries[lang][query_name] then + return explicit_queries[lang][query_name] + end + local query_files = M.get_query_files(lang, query_name) local query_string = read_query_files(query_files) diff --git a/runtime/menu.vim b/runtime/menu.vim index 3756787e7f..cd56eb5583 100644 --- a/runtime/menu.vim +++ b/runtime/menu.vim @@ -356,8 +356,8 @@ func! s:SetupColorSchemes() abort let s:did_setup_color_schemes = 1 let n = globpath(&runtimepath, "colors/*.vim", 1, 1) - let n += globpath(&runtimepath, "pack/*/start/*/colors/*.vim", 1, 1) - let n += globpath(&runtimepath, "pack/*/opt/*/colors/*.vim", 1, 1) + let n += globpath(&packpath, "pack/*/start/*/colors/*.vim", 1, 1) + let n += globpath(&packpath, "pack/*/opt/*/colors/*.vim", 1, 1) " Ignore case for VMS and windows, sort on name let names = sort(map(n, 'substitute(v:val, "\\c.*[/\\\\:\\]]\\([^/\\\\:]*\\)\\.vim", "\\1", "")'), 1) diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 6b3328a5d4..60dc6fdd31 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -810,6 +810,14 @@ call <SID>OptionL("ts") call append("$", "shiftwidth\tnumber of spaces used for each step of (auto)indent") call append("$", "\t(local to buffer)") call <SID>OptionL("sw") +if has("vartabs") + call append("$", "vartabstop\tlist of number of spaces a tab counts for") + call append("$", "\t(local to buffer)") + call <SID>OptionL("vts") + call append("$", "varsofttabstop\tlist of number of spaces a soft tabsstop counts for") + call append("$", "\t(local to buffer)") + call <SID>OptionL("vsts") +endif call append("$", "smarttab\ta <Tab> in an indent inserts 'shiftwidth' spaces") call <SID>BinOptionG("sta", &sta) call append("$", "softtabstop\tif non-zero, number of spaces to insert for a <Tab>") diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 6870bcec75..fa5d064048 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -43,7 +43,7 @@ " balloon -> nvim floating window " " The code for opening the floating window was taken from the beautiful -" implementation of LanguageClient-Neovim: +" implementation of LanguageClient-Neovim: " https://github.com/autozimu/LanguageClient-neovim/blob/0ed9b69dca49c415390a8317b19149f97ae093fa/autoload/LanguageClient.vim#L304 " " Neovim terminal also works seamlessly on windows, which is why the ability @@ -76,9 +76,14 @@ if !exists('g:termdebugger') endif let s:pc_id = 12 -let s:break_id = 13 " breakpoint number is added to this +let s:asm_id = 13 +let s:break_id = 14 " breakpoint number is added to this let s:stopped = 1 +let s:parsing_disasm_msg = 0 +let s:asm_lines = [] +let s:asm_addr = '' + " Take a breakpoint number as used by GDB and turn it into an integer. " The breakpoint may contain a dot: 123.4 -> 123004 " The main breakpoint has a zero subid. @@ -120,6 +125,7 @@ func s:StartDebug_internal(dict) let s:ptywin = 0 let s:pid = 0 + let s:asmwin = 0 " Uncomment this line to write logging in "debuglog". " call ch_logfile('debuglog', 'w') @@ -155,6 +161,14 @@ func s:StartDebug_internal(dict) else call s:StartDebug_term(a:dict) endif + + if exists('g:termdebug_disasm_window') + if g:termdebug_disasm_window + let curwinid = win_getid(winnr()) + call s:GotoAsmwinOrCreateIt() + call win_gotoid(curwinid) + endif + endif endfunc " Use when debugger didn't start or ended. @@ -321,9 +335,9 @@ func s:StartDebug_prompt(dict) "call ch_log('executing "' . join(cmd) . '"') let s:gdbjob = jobstart(cmd, { - \ 'on_exit': function('s:EndPromptDebug'), - \ 'on_stdout': function('s:GdbOutCallback'), - \ }) + \ 'on_exit': function('s:EndPromptDebug'), + \ 'on_stdout': function('s:GdbOutCallback'), + \ }) if s:gdbjob == 0 echoerr 'invalid argument (or job table is full) while starting gdb job' exe 'bwipe! ' . s:ptybuf @@ -562,6 +576,15 @@ func s:GetFullname(msg) return name endfunc +" Extract the "addr" value from a gdb message with addr="0x0001234". +func s:GetAsmAddr(msg) + if a:msg !~ 'addr=' + return '' + endif + let addr = s:DecodeMessage(substitute(a:msg, '.*addr=', '', '')) + return addr +endfunc + function s:EndTermDebug(job_id, exit_code, event) unlet s:gdbwin @@ -601,6 +624,66 @@ func s:EndPromptDebug(job_id, exit_code, event) "call ch_log("Returning from EndPromptDebug()") endfunc +" - CommOutput: disassemble $pc +" - CommOutput: &"disassemble $pc\n" +" - CommOutput: ~"Dump of assembler code for function main(int, char**):\n" +" - CommOutput: ~" 0x0000555556466f69 <+0>:\tpush rbp\n" +" ... +" - CommOutput: ~" 0x0000555556467cd0:\tpop rbp\n" +" - CommOutput: ~" 0x0000555556467cd1:\tret \n" +" - CommOutput: ~"End of assembler dump.\n" +" - CommOutput: ^done + +" - CommOutput: disassemble $pc +" - CommOutput: &"disassemble $pc\n" +" - CommOutput: &"No function contains specified address.\n" +" - CommOutput: ^error,msg="No function contains specified address." +func s:HandleDisasmMsg(msg) + if a:msg =~ '^\^done' + let curwinid = win_getid(winnr()) + if win_gotoid(s:asmwin) + silent normal! gg0"_dG + call setline(1, s:asm_lines) + set nomodified + set filetype=asm + + let lnum = search('^' . s:asm_addr) + if lnum != 0 + exe 'sign unplace ' . s:asm_id + exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC' + endif + + call win_gotoid(curwinid) + endif + + let s:parsing_disasm_msg = 0 + let s:asm_lines = [] + elseif a:msg =~ '^\^error,msg=' + if s:parsing_disasm_msg == 1 + " Disassemble call ran into an error. This can happen when gdb can't + " find the function frame address, so let's try to disassemble starting + " at current PC + call s:SendCommand('disassemble $pc,+100') + endif + let s:parsing_disasm_msg = 0 + elseif a:msg =~ '\&\"disassemble \$pc' + if a:msg =~ '+100' + " This is our second disasm attempt + let s:parsing_disasm_msg = 2 + endif + else + let value = substitute(a:msg, '^\~\"[ ]*', '', '') + let value = substitute(value, '^=>[ ]*', '', '') + let value = substitute(value, '\\n\"
$', '', '') + let value = substitute(value, '
', '', '') + let value = substitute(value, '\\t', ' ', 'g') + + if value != '' || !empty(s:asm_lines) + call add(s:asm_lines, value) + endif + endif +endfunc + func s:CommOutput(job_id, msgs, event) for msg in a:msgs @@ -608,7 +691,10 @@ func s:CommOutput(job_id, msgs, event) if msg[0] == "\n" let msg = msg[1:] endif - if msg != '' + + if s:parsing_disasm_msg + call s:HandleDisasmMsg(msg) + elseif msg != '' if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)' call s:HandleCursor(msg) elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,' @@ -621,6 +707,9 @@ func s:CommOutput(job_id, msgs, event) call s:HandleEvaluate(msg) elseif msg =~ '^\^error,msg=' call s:HandleError(msg) + elseif msg =~ '^disassemble' + let s:parsing_disasm_msg = 1 + let s:asm_lines = [] endif endif endfor @@ -651,6 +740,7 @@ func s:InstallCommands() command Gdb call win_gotoid(s:gdbwin) command Program call win_gotoid(s:ptywin) command Source call s:GotoSourcewinOrCreateIt() + command Asm call s:GotoAsmwinOrCreateIt() command Winbar call s:InstallWinbar() " TODO: can the K mapping be restored? @@ -689,6 +779,7 @@ func s:DeleteCommands() delcommand Gdb delcommand Program delcommand Source + delcommand Asm delcommand Winbar nunmap K @@ -963,6 +1054,48 @@ func s:GotoSourcewinOrCreateIt() endif endfunc +func s:GotoAsmwinOrCreateIt() + if !win_gotoid(s:asmwin) + if win_gotoid(s:sourcewin) + exe 'rightbelow new' + else + exe 'new' + endif + + let s:asmwin = win_getid(winnr()) + + setlocal nowrap + setlocal number + setlocal noswapfile + setlocal buftype=nofile + + let asmbuf = bufnr('Termdebug-asm-listing') + if asmbuf > 0 + exe 'buffer' . asmbuf + else + exe 'file Termdebug-asm-listing' + endif + + if exists('g:termdebug_disasm_window') + if g:termdebug_disasm_window > 1 + exe 'resize ' . g:termdebug_disasm_window + endif + endif + endif + + if s:asm_addr != '' + let lnum = search('^' . s:asm_addr) + if lnum == 0 + if s:stopped + call s:SendCommand('disassemble $pc') + endif + else + exe 'sign unplace ' . s:asm_id + exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC' + endif + endif +endfunc + " Handle stopping and running message from gdb. " Will update the sign that shows the current position. func s:HandleCursor(msg) @@ -981,10 +1114,31 @@ func s:HandleCursor(msg) else let fname = '' endif + + if a:msg =~ 'addr=' + let asm_addr = s:GetAsmAddr(a:msg) + if asm_addr != '' + let s:asm_addr = asm_addr + + let curwinid = win_getid(winnr()) + if win_gotoid(s:asmwin) + let lnum = search('^' . s:asm_addr) + if lnum == 0 + call s:SendCommand('disassemble $pc') + else + exe 'sign unplace ' . s:asm_id + exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC' + endif + + call win_gotoid(curwinid) + endif + endif + endif + if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname) let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '') if lnum =~ '^[0-9]*$' - call s:GotoSourcewinOrCreateIt() + call s:GotoSourcewinOrCreateIt() if expand('%:p') != fnamemodify(fname, ':p') if &modified " TODO: find existing window diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm index 96b43cf0d0..260750a85b 100644 --- a/runtime/queries/c/highlights.scm +++ b/runtime/queries/c/highlights.scm @@ -14,6 +14,7 @@ "union" "volatile" "goto" + "register" ] @keyword [ @@ -81,6 +82,8 @@ "|=" "&=" "^=" + ">>=" + "<<=" "--" "++" ] @operator @@ -117,7 +120,6 @@ (preproc_arg) (preproc_defined) ] @function.macro -; TODO (preproc_arg) @embedded (field_identifier) @property (statement_identifier) @label @@ -129,13 +131,22 @@ (type_descriptor) ] @type -(declaration type: [(identifier) (type_identifier)] @type) -(cast_expression type: [(identifier) (type_identifier)] @type) +(declaration (type_qualifier) @type) +(cast_expression type: (type_descriptor) @type) (sizeof_expression value: (parenthesized_expression (identifier) @type)) ((identifier) @constant (#match? @constant "^[A-Z][A-Z0-9_]+$")) +;; Preproc def / undef +(preproc_def + name: (_) @constant) +(preproc_call + directive: (preproc_directive) @_u + argument: (_) @constant + (#eq? @_u "#undef")) + + (comment) @comment ;; Parameters diff --git a/runtime/syntax/cabal.vim b/runtime/syntax/cabal.vim index 8af47d4042..92e6b8331e 100644 --- a/runtime/syntax/cabal.vim +++ b/runtime/syntax/cabal.vim @@ -4,7 +4,7 @@ " Maintainer: Marcin Szamotulski <profunctor@pm.me> " Previous Maintainer: Vincent Berthoux <twinside@gmail.com> " File Types: .cabal -" Last Change: 15 May 2018 +" Last Change: 21 Nov 2020 " v1.5: Incorporated changes from " https://github.com/sdiehl/haskell-vim-proto/blob/master/vim/syntax/cabal.vim " Use `syn keyword` instead of `syn match`. @@ -62,11 +62,12 @@ syn keyword cabalCategory contained \ source-repository \ flag \ custom-setup + \ common syn match cabalCategoryTitle contained /[^{]*\ze{\?/ syn match cabalCategoryRegion \ contains=cabalCategory,cabalCategoryTitle \ nextgroup=cabalCategory skipwhite - \ /^\c\s*\(contained\|executable\|library\|benchmark\|test-suite\|source-repository\|flag\|custom-setup\)\+\s*\%(.*$\|$\)/ + \ /^\c\s*\(contained\|executable\|library\|benchmark\|test-suite\|source-repository\|flag\|custom-setup\|common\)\+\s*\%(.*$\|$\)/ syn keyword cabalTruth true false " cabalStatementRegion which limits the scope of cabalStatement keywords, this @@ -76,10 +77,14 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion \ default-language \ default-extensions \ author + \ autogen-modules + \ asm-sources + \ asm-options \ branch \ bug-reports \ build-depends \ build-tools + \ build-tools-depends \ build-type \ buildable \ c-sources @@ -87,32 +92,46 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion \ category \ cc-options \ copyright + \ cmm-sources + \ cmm-options \ cpp-options + \ cxx-sources \ data-dir \ data-files \ default + \ default-extensions \ description \ executable \ exposed-modules \ exposed \ extensions - \ extra-tmp-files + \ extra-bundled-libraries \ extra-doc-files + \ extra-dynamic-library-flavours + \ extra-framework-dirs + \ extra-ghci-libraries \ extra-lib-dirs \ extra-libraries + \ extra-library-flavours \ extra-source-files - \ exta-tmp-files + \ extra-tmp-files \ for example \ frameworks \ ghc-options \ ghc-prof-options \ ghc-shared-options + \ ghcjs-options + \ ghcjs-prof-options + \ ghcjs-shared-options \ homepage + \ hs-source-dir \ hs-source-dirs \ hugs-options + \ import \ include-dirs \ includes \ install-includes + \ js-sources \ ld-options \ license \ license-file @@ -120,10 +139,13 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion \ main-is \ maintainer \ manual + \ mixins \ module \ name \ nhc98-options \ other-extensions + \ other-language + \ other-languages \ other-modules \ package-url \ pkgconfig-depends diff --git a/runtime/syntax/cabalconfig.vim b/runtime/syntax/cabalconfig.vim new file mode 100644 index 0000000000..0165725c06 --- /dev/null +++ b/runtime/syntax/cabalconfig.vim @@ -0,0 +1,30 @@ +" Vim syntax file +" Language: Cabal Config +" Maintainer: profunctor@pm.me +" Last Change: Marcin Szamotulski +" Original Author: Marcin Szamotulski + +if exists("b:current_syntax") + finish +endif + +syn match CabalConfigSection /^\S[[:alpha:]]\+\%(-[[:alpha:]]\+\)*[^:]*$/ +syn region CabalConfigRegion matchgroup=CabalConfigKey start=/^\s*[[:alpha:]]\+\%(-[[:alpha:]]\+\)*:/ matchgroup=NONE end=/$/ contains=CabalConfigSeparator,CabalConfigKeyword,CabalConfigPath keepend +syn match CabalConfigComment /^\s*--.*$/ +syn match CabalConfigValue /.*$/ contained +syn match CabalConfigKey /[[:alpha:]]\+\%(-[[:alpha:]]\+\)*\ze:/ +syn keyword CabalConfigSeparator : contained +syn match CabalConfigVariable /\$[[:alpha:]]\+/ +syn keyword CabalConfigKeyword True False ghc +syn match CabalConfigPath /\%([[:alpha:]]\+:\)\?\%(\/[[:print:]]\+\)\+/ + +hi def link CabalConfigComment Comment +hi def link CabalConfigSection Title +hi def link CabalConfigKey Statement +hi def link CabalConfigSeparator NonText +hi def link CabalConfigValue Normal +hi def link CabalConfigVariable Identifier +hi def link CabalConfigKeyword Keyword +hi def link CabalConfigPath Directory + +let b:current_syntax = "cabal.config" diff --git a/runtime/syntax/cabalproject.vim b/runtime/syntax/cabalproject.vim new file mode 100644 index 0000000000..12143b9ee9 --- /dev/null +++ b/runtime/syntax/cabalproject.vim @@ -0,0 +1,28 @@ +" Vim syntax file +" Language: Cabal Project +" Maintainer: profunctor@pm.me +" Last Change: Marcin Szamotulski +" Original Author: Marcin Szamotulski + +if exists("b:current_syntax") + finish +endif + +syn match CabalProjectComment /^\s*--.*/ contains=@Spell +syn match CabalProjectField /^\w\%(\w\|-\)\+/ contains=@NoSpell + +syn keyword CabalProjectBoolean true false True False +syn keyword CabalProjectCompiler ghc ghcjs jhc lhc uhc haskell-suite +syn match CabalProjectNat /\<\d\+\>/ +syn keyword CabalProjectJobs $ncpus +syn keyword CabalProjectProfilingLevel default none exported-functions toplevel-functions all-functions + +hi def link CabalProjectComment Comment +hi def link CabalProjectField Statement +hi def link CabalProjectBoolean Boolean +hi def link CabalProjectCompiler Identifier +hi def link CabalProjectNat Number +hi def link CabalProjectJobs Number +hi def link CabalProjectProfilingLevel Statement + +let b:current_syntax = "cabal.project" diff --git a/runtime/syntax/haskell.vim b/runtime/syntax/haskell.vim index e5128a12ab..1b70b9344a 100644 --- a/runtime/syntax/haskell.vim +++ b/runtime/syntax/haskell.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Haskell " Maintainer: Haskell Cafe mailinglist <haskell-cafe@haskell.org> -" Last Change: 2018 Mar 29 by Marcin Szamotulski +" Last Change: 2020 Oct 4 by Marcin Szamotulski <profunctor@pm.me> " Original Author: John Williams <jrw@pobox.com> " " Thanks to Ryan Crumley for suggestions and John Meacham for @@ -38,8 +38,8 @@ if exists("b:current_syntax") endif " (Qualified) identifiers (no default highlighting) -syn match ConId "\(\<[A-Z][a-zA-Z0-9_']*\.\)\=\<[A-Z][a-zA-Z0-9_']*\>" contains=@NoSpell -syn match VarId "\(\<[A-Z][a-zA-Z0-9_']*\.\)\=\<[a-z][a-zA-Z0-9_']*\>" contains=@NoSpell +syn match ConId "\(\<[A-Z][a-zA-Z0-9_']*\.\)*\<[A-Z][a-zA-Z0-9_']*\>" contains=@NoSpell +syn match VarId "\(\<[A-Z][a-zA-Z0-9_']*\.\)*\<[a-z][a-zA-Z0-9_']*\>" contains=@NoSpell " Infix operators--most punctuation characters and any (qualified) identifier " enclosed in `backquotes`. An operator starting with : is a constructor, @@ -49,8 +49,11 @@ syn match hsConSym "\(\<[A-Z][a-zA-Z0-9_']*\.\)\=:[-!#$%&\*\+./<=>\?@\\^|~:]*" syn match hsVarSym "`\(\<[A-Z][a-zA-Z0-9_']*\.\)\=[a-z][a-zA-Z0-9_']*`" syn match hsConSym "`\(\<[A-Z][a-zA-Z0-9_']*\.\)\=[A-Z][a-zA-Z0-9_']*`" +" (Non-qualified) identifiers which start with # are labels +syn match hsLabel "#[a-z][a-zA-Z0-9_']*\>" + " Reserved symbols--cannot be overloaded. -syn match hsDelimiter "(\|)\|\[\|\]\|,\|;\|_\|{\|}" +syn match hsDelimiter "(\|)\|\[\|\]\|,\|;\|{\|}" " Strings and constants syn match hsSpecialChar contained "\\\([0-9]\+\|o[0-7]\+\|x[0-9a-fA-F]\+\|[\"\\'&\\abfnrtv]\|^[A-Z^_\[\\\]]\)" @@ -62,37 +65,41 @@ syn match hsCharacter "^'\([^\\]\|\\[^']\+\|\\'\)'" contains=hsSpecialChar,hs syn match hsNumber "\v<[0-9]%(_*[0-9])*>|<0[xX]_*[0-9a-fA-F]%(_*[0-9a-fA-F])*>|<0[oO]_*%(_*[0-7])*>|<0[bB]_*[01]%(_*[01])*>" syn match hsFloat "\v<[0-9]%(_*[0-9])*\.[0-9]%(_*[0-9])*%(_*[eE][-+]?[0-9]%(_*[0-9])*)?>|<[0-9]%(_*[0-9])*_*[eE][-+]?[0-9]%(_*[0-9])*>|<0[xX]_*[0-9a-fA-F]%(_*[0-9a-fA-F])*\.[0-9a-fA-F]%(_*[0-9a-fA-F])*%(_*[pP][-+]?[0-9]%(_*[0-9])*)?>|<0[xX]_*[0-9a-fA-F]%(_*[0-9a-fA-F])*_*[pP][-+]?[0-9]%(_*[0-9])*>" -" Keyword definitions. These must be patterns instead of keywords -" because otherwise they would match as keywords at the start of a -" "literate" comment (see lhs.vim). -syn match hsModule "\<module\>" -syn match hsImport "\<import\>.*"he=s+6 contains=hsImportMod,hsLineComment,hsBlockComment,@NoSpell -syn match hsImportMod contained "\<\(as\|qualified\|hiding\)\>" contains=@NoSpell -syn match hsInfix "\<\(infix\|infixl\|infixr\)\>" -syn match hsStructure "\<\(class\|data\|deriving\|instance\|default\|where\)\>" -syn match hsTypedef "\<\(type\|newtype\)\>" -syn match hsStatement "\<\(do\|case\|of\|let\|in\)\>" -syn match hsConditional "\<\(if\|then\|else\)\>" +" Keyword definitions. +syn keyword hsModule module +syn match hsImportGroup "\<import\>.*" contains=hsImport,hsImportModuleName,hsImportMod,hsLineComment,hsBlockComment,hsImportList,@NoSpell nextgroup=hsImport +syn keyword hsImport import contained nextgroup=hsImportModuleName +syn match hsImportModuleName '\<[A-Z][A-Za-z.]*' contained +syn region hsImportList start='(' skip='([^)]\{-})' end=')' keepend contained contains=ConId,VarId,hsDelimiter,hsBlockComment,hsTypedef,@NoSpell + +syn keyword hsImportMod contained as qualified hiding +syn keyword hsInfix infix infixl infixr +syn keyword hsStructure class data deriving instance default where +syn keyword hsTypedef type +syn keyword hsNewtypedef newtype +syn keyword hsTypeFam family +syn keyword hsStatement mdo do case of let in +syn keyword hsConditional if then else " Not real keywords, but close. if exists("hs_highlight_boolean") " Boolean constants from the standard prelude. - syn match hsBoolean "\<\(True\|False\)\>" + syn keyword hsBoolean True False endif if exists("hs_highlight_types") " Primitive types from the standard prelude and libraries. - syn match hsType "\<\(Int\|Integer\|Char\|Bool\|Float\|Double\|IO\|Void\|Addr\|Array\|String\)\>" + syn keyword hsType Int Integer Char Bool Float Double IO Void Addr Array String endif if exists("hs_highlight_more_types") " Types from the standard prelude libraries. - syn match hsType "\<\(Maybe\|Either\|Ratio\|Complex\|Ordering\|IOError\|IOResult\|ExitCode\)\>" - syn match hsMaybe "\<Nothing\>" - syn match hsExitCode "\<\(ExitSuccess\)\>" - syn match hsOrdering "\<\(GT\|LT\|EQ\)\>" + syn keyword hsType Maybe Either Ratio Complex Ordering IOError IOResult ExitCode + syn keyword hsMaybe Nothing + syn keyword hsExitCode ExitSuccess + syn keyword hsOrdering GT LT EQ endif if exists("hs_highlight_debug") " Debugging functions from the standard prelude. - syn match hsDebug "\<\(undefined\|error\|trace\)\>" + syn keyword hsDebug undefined error trace endif @@ -133,12 +140,14 @@ hi def link hsImportMod hsImport hi def link hsInfix PreProc hi def link hsStructure Structure hi def link hsStatement Statement -hi def link hsConditional Conditional -hi def link hsSpecialChar SpecialChar +hi def link hsConditional Conditional +hi def link hsSpecialChar SpecialChar hi def link hsTypedef Typedef +hi def link hsNewtypedef Typedef hi def link hsVarSym hsOperator hi def link hsConSym hsOperator hi def link hsOperator Operator +hi def link hsTypeFam Structure if exists("hs_highlight_delimiters") " Some people find this highlighting distracting. hi def link hsDelimiter Delimiter @@ -160,22 +169,22 @@ hi def link hsMaybe hsEnumConst hi def link hsOrdering hsEnumConst hi def link hsEnumConst Constant hi def link hsDebug Debug - -hi def link cCppString hsString -hi def link cCommentStart hsComment -hi def link cCommentError hsError -hi def link cCommentStartError hsError -hi def link cInclude Include -hi def link cPreProc PreProc -hi def link cDefine Macro -hi def link cIncluded hsString -hi def link cError Error -hi def link cPreCondit PreCondit -hi def link cComment Comment -hi def link cCppSkip cCppOut -hi def link cCppOut2 cCppOut -hi def link cCppOut Comment - +hi def link hsLabel Special + +hi def link cCppString hsString +hi def link cCommentStart hsComment +hi def link cCommentError hsError +hi def link cCommentStartError hsError +hi def link cInclude Include +hi def link cPreProc PreProc +hi def link cDefine Macro +hi def link cIncluded hsString +hi def link cError Error +hi def link cPreCondit PreCondit +hi def link cComment Comment +hi def link cCppSkip cCppOut +hi def link cCppOut2 cCppOut +hi def link cCppOut Comment let b:current_syntax = "haskell" diff --git a/runtime/syntax/lsp_markdown.vim b/runtime/syntax/lsp_markdown.vim new file mode 100644 index 0000000000..d5c1414f01 --- /dev/null +++ b/runtime/syntax/lsp_markdown.vim @@ -0,0 +1,15 @@ +" Vim syntax file +" Language: lsp_markdown +" Maintainer: Michael Lingelbach <m.j.lbach@gmail.com +" URL: http://neovim.io +" Remark: Uses markdown syntax file + +runtime! syntax/markdown.vim + +syn cluster mkdNonListItem add=mkdEscape,mkdNbsp + +syntax region mkdEscape matchgroup=mkdEscape start=/\\\ze[\\\x60*{}\[\]()#+\-,.!_>~|"$%&'\/:;<=?@^ ]/ end=/.\zs/ keepend contains=mkdEscapeCh oneline concealends +syntax match mkdEscapeCh /./ contained +syntax match mkdNbsp / / conceal cchar= + +hi def link mkdEscape special diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 1a37af1c8a..92348d57ec 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -616,7 +616,7 @@ syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/' skip='\\.' e " g:vimsyn_embed =~# 'r' : embed ruby " g:vimsyn_embed =~# 't' : embed tcl if !exists("g:vimsyn_embed") - let g:vimsyn_embed= 0 + let g:vimsyn_embed = 'l' endif " [-- lua --] {{{3 |