aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/autoload/haskellcomplete.vim5
-rw-r--r--runtime/autoload/provider/clipboard.vim6
-rw-r--r--runtime/doc/api.txt103
-rw-r--r--runtime/doc/change.txt10
-rw-r--r--runtime/doc/editing.txt4
-rw-r--r--runtime/doc/eval.txt68
-rw-r--r--runtime/doc/insert.txt6
-rw-r--r--runtime/doc/lsp.txt45
-rw-r--r--runtime/doc/lua.txt12
-rw-r--r--runtime/doc/map.txt18
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt8
-rw-r--r--runtime/doc/options.txt48
-rw-r--r--runtime/doc/starting.txt2
-rw-r--r--runtime/doc/syntax.txt3
-rw-r--r--runtime/doc/tagsrch.txt27
-rw-r--r--runtime/doc/treesitter.txt6
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/filetype.vim14
-rw-r--r--runtime/indent/tcl.vim4
-rw-r--r--runtime/lua/vim/lsp.lua123
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua6
-rw-r--r--runtime/lua/vim/lsp/handlers.lua10
-rw-r--r--runtime/lua/vim/lsp/log.lua4
-rw-r--r--runtime/lua/vim/lsp/protocol.lua13
-rw-r--r--runtime/lua/vim/lsp/rpc.lua9
-rw-r--r--runtime/lua/vim/lsp/util.lua264
-rw-r--r--runtime/lua/vim/shared.lua14
-rw-r--r--runtime/lua/vim/treesitter.lua8
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua30
-rw-r--r--runtime/lua/vim/treesitter/query.lua54
-rw-r--r--runtime/menu.vim4
-rw-r--r--runtime/optwin.vim8
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim168
-rw-r--r--runtime/queries/c/highlights.scm17
-rw-r--r--runtime/syntax/cabal.vim30
-rw-r--r--runtime/syntax/cabalconfig.vim30
-rw-r--r--runtime/syntax/cabalproject.vim28
-rw-r--r--runtime/syntax/haskell.vim89
-rw-r--r--runtime/syntax/lsp_markdown.vim15
-rw-r--r--runtime/syntax/vim.vim2
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 /&nbsp;/ 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