aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--runtime/doc/api.txt110
-rw-r--r--runtime/doc/eval.txt2
-rw-r--r--runtime/doc/lsp.txt282
-rw-r--r--runtime/doc/lua.txt88
-rw-r--r--runtime/lua/vim/lsp.lua10
-rw-r--r--runtime/lua/vim/lsp/buf.lua34
-rw-r--r--runtime/lua/vim/lsp/rpc.lua6
-rw-r--r--runtime/lua/vim/lsp/util.lua106
-rw-r--r--runtime/lua/vim/shared.lua22
-rw-r--r--runtime/lua/vim/treesitter.lua6
-rwxr-xr-xscripts/gen_vimdoc.py66
-rwxr-xr-xscripts/lua2dox_filter11
-rw-r--r--src/nvim/api/buffer.c2
-rw-r--r--src/nvim/api/vim.c10
-rw-r--r--src/nvim/lua/executor.c12
-rw-r--r--src/nvim/lua/treesitter.c102
-rw-r--r--src/nvim/lua/vim.lua2
-rw-r--r--src/nvim/version.c4
-rw-r--r--test/functional/lua/treesitter_spec.lua61
-rw-r--r--test/functional/plugin/lsp_spec.lua73
21 files changed, 787 insertions, 224 deletions
diff --git a/.gitignore b/.gitignore
index f4037c718a..699d493b59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,8 @@ local.mk
/runtime/doc/*.html
/runtime/doc/tags.ref
/runtime/doc/errors.log
+# Don't include the mpack files.
+/runtime/doc/*.mpack
# CLion
/.idea/
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index fdabb0da50..ea3a8242ae 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -475,6 +475,9 @@ created for extmark changes.
==============================================================================
Global Functions *api-global*
+nvim__get_lib_dir() *nvim__get_lib_dir()*
+ TODO: Documentation
+
nvim__id({obj}) *nvim__id()*
Returns object given as argument.
@@ -526,7 +529,8 @@ nvim__id_float({flt}) *nvim__id_float()*
nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()*
TODO: Documentation
-nvim__put_attr({id}, {c0}, {c1}) *nvim__put_attr()*
+ *nvim__put_attr()*
+nvim__put_attr({id}, {start_row}, {start_col}, {end_row}, {end_col})
Set attrs in nvim__buf_set_lua_hl callbacks
TODO(bfredl): This is rather pedestrian. The final interface
@@ -612,7 +616,8 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
Parameters: ~
{listed} Sets 'buflisted'
{scratch} Creates a "throwaway" |scratch-buffer| for
- temporary work (always 'nomodified')
+ temporary work (always 'nomodified'). Also sets
+ 'nomodeline' on the buffer.
Return: ~
Buffer handle, or 0 on error
@@ -729,6 +734,15 @@ nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()*
On execution error: does not fail, but updates v:errmsg.
+ If you need to input sequences like <C-o> use nvim_replace_termcodes
+ to replace the termcodes and then pass the resulting string to
+ nvim_feedkeys. You'll also want to enable escape_csi.
+
+ Example: >
+ :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true)
+ :call nvim_feedkeys(key, 'n', v:true)
+<
+
Parameters: ~
{keys} to be typed
{mode} behavior flags, see |feedkeys()|
@@ -929,6 +943,23 @@ nvim_get_proc_children({pid}) *nvim_get_proc_children()*
Return: ~
Array of child process ids, empty if process not found.
+nvim_get_runtime_file({name}, {all}) *nvim_get_runtime_file()*
+ Find files in runtime directories
+
+ 'name' can contain wildcards. For example
+ nvim_get_runtime_file("colors/*.vim", true) will return all
+ color scheme files.
+
+ It is not an error to not find any files. An empty array is
+ returned then.
+
+ Parameters: ~
+ {name} pattern of files to search for
+ {all} whether to return all matches or only the first
+
+ Return: ~
+ list of absolute paths to the found files
+
nvim_get_var({name}) *nvim_get_var()*
Gets a global (g:) variable.
@@ -1517,6 +1548,9 @@ nvim_unsubscribe({event}) *nvim_unsubscribe()*
==============================================================================
Buffer Functions *api-buffer*
+
+For more information on buffers, see |buffers|.
+
Unloaded Buffers:~
Buffers may be unloaded by the |:bunload| command or the
@@ -1530,6 +1564,12 @@ affected.
You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()|
to check whether a buffer is loaded.
+ *nvim__buf_add_decoration()*
+nvim__buf_add_decoration({buffer}, {ns_id}, {hl_group}, {start_row},
+ {start_col}, {end_row}, {end_col},
+ {virt_text})
+ TODO: Documentation
+
*nvim__buf_redraw_range()*
nvim__buf_redraw_range({buffer}, {first}, {last})
TODO: Documentation
@@ -1550,7 +1590,7 @@ nvim__buf_stats({buffer}) *nvim__buf_stats()*
TODO: Documentation
*nvim_buf_add_highlight()*
-nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line},
+nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line},
{col_start}, {col_end})
Adds a highlight to buffer.
@@ -1747,8 +1787,8 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
as (0,0) and (-1,-1) respectively, thus the following are
equivalent:
>
- nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
- nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
+ nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
+ nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
<
If `end` is less than `start` , traversal works backwards.
@@ -1757,18 +1797,18 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
Example:
>
- local a = vim.api
- local pos = a.nvim_win_get_cursor(0)
- local ns = a.nvim_create_namespace('my-plugin')
- -- Create new extmark at line 1, column 1.
- local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
- -- Create new extmark at line 3, column 1.
- local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {})
- -- Get extmarks only from line 3.
- local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
- -- Get all marks in this buffer + namespace.
- local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {})
- print(vim.inspect(ms))
+ local a = vim.api
+ local pos = a.nvim_win_get_cursor(0)
+ local ns = a.nvim_create_namespace('my-plugin')
+ -- Create new extmark at line 1, column 1.
+ local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
+ -- Create new extmark at line 3, column 1.
+ local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {})
+ -- Get extmarks only from line 3.
+ local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
+ -- Get all marks in this buffer + namespace.
+ local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {})
+ print(vim.inspect(ms))
<
Parameters: ~
@@ -1879,7 +1919,7 @@ nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()*
Variable value
*nvim_buf_get_virtual_text()*
-nvim_buf_get_virtual_text({buffer}, {lnum})
+nvim_buf_get_virtual_text({buffer}, {line})
Get the virtual text (annotation) for a buffer line.
The virtual text is returned as list of lists, whereas the
@@ -2013,7 +2053,8 @@ nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
{value} Variable value
*nvim_buf_set_virtual_text()*
-nvim_buf_set_virtual_text({buffer}, {ns_id}, {line}, {chunks}, {opts})
+nvim_buf_set_virtual_text({buffer}, {src_id}, {line}, {chunks},
+ {opts})
Set the virtual text (annotation) for a buffer line.
By default (and currently the only option) the text will be
@@ -2337,28 +2378,31 @@ nvim_ui_detach() *nvim_ui_detach()*
Removes the client from the list of UIs. |nvim_list_uis()|
-nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()*
- Tells Nvim the number of elements displaying in the popumenu,
- to decide <PageUp> and <PageDown> movement.
-
- Parameters: ~
- {height} Popupmenu height, must be greater than zero.
-
*nvim_ui_pum_set_bounds()*
nvim_ui_pum_set_bounds({width}, {height}, {row}, {col})
+ Tells Nvim the geometry of the popumenu, to align floating
+ windows with an external popup menu.
- Tells Nvim the geometry of the popumenu, to align floating
- windows with an external popup menu. Note that this method
- is not to be confused with |nvim_ui_pum_set_height()|, which
- sets the number of visible items in the popup menu, while
- this function sets the bounding box of the popup menu,
- including visual decorations such as boarders and sliders.
+ Note that this method is not to be confused with
+ |nvim_ui_pum_set_height()|, which sets the number of visible
+ items in the popup menu, while this function sets the bounding
+ box of the popup menu, including visual decorations such as
+ boarders and sliders. Floats need not use the same font size,
+ nor be anchored to exact grid corners, so one can set
+ floating-point numbers to the popup menu geometry.
Parameters: ~
{width} Popupmenu width.
{height} Popupmenu height.
{row} Popupmenu row.
- {height} Popupmenu height.
+ {col} Popupmenu height.
+
+nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()*
+ Tells Nvim the number of elements displaying in the popumenu,
+ to decide <PageUp> and <PageDown> movement.
+
+ Parameters: ~
+ {height} Popupmenu height, must be greater than zero.
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
TODO: Documentation
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 92f703a8a3..1c1baa943a 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -9367,7 +9367,7 @@ wordcount() *wordcount()*
(only in Visual mode)
visual_chars Number of chars visually selected
(only in Visual mode)
- visual_words Number of chars visually selected
+ visual_words Number of words visually selected
(only in Visual mode)
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index f81265c2c8..15587955de 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -58,6 +58,11 @@ Nvim provides the |vim.lsp.omnifunc| 'omnifunc' handler which allows
" Use LSP omni-completion in Python files.
autocmd Filetype python setlocal omnifunc=v:lua.vim.lsp.omnifunc
+If a function has a `*_sync` variant, it's primarily intended for being run
+automatically on file save. E.g. code formatting: >
+
+ " Auto-format *.rs files prior to saving them
+ autocmd BufWritePre *.rs lua vim.lsp.buf.formatting_sync(nil, 1000)
================================================================================
FAQ *lsp-faq*
@@ -359,13 +364,12 @@ buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()*
{client_id} (number) the client id
buf_notify({bufnr}, {method}, {params}) *vim.lsp.buf_notify()*
- Sends a notification to all servers attached to the buffer.
+ Send a notification to a server
Parameters: ~
- {bufnr} (optional, number) Buffer handle, or 0 for
- current
- {method} (string) LSP method name
- {params} (string) Parameters to send to the server
+ {bufnr} [number] (optional): The number of the buffer
+ {method} [string]: Name of the request method
+ {params} [string]: Arguments to send to the server
Return: ~
true if any client returns true; false otherwise
@@ -467,6 +471,10 @@ client() *vim.lsp.client*
client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
TODO: Documentation
+ *vim.lsp.define_default_sign()*
+define_default_sign({name}, {properties})
+ TODO: Documentation
+
err_message({...}) *vim.lsp.err_message()*
TODO: Documentation
@@ -542,7 +550,7 @@ once({fn}) *vim.lsp.once()*
optional_validator({fn}) *vim.lsp.optional_validator()*
TODO: Documentation
-request({method}, {params}, {callback}) *vim.lsp.request()*
+request({method}, {params}, {callback}, {bufnr}) *vim.lsp.request()*
TODO: Documentation
resolve_bufnr({bufnr}) *vim.lsp.resolve_bufnr()*
@@ -578,7 +586,7 @@ start_client({config}) *vim.lsp.start_client()*
{root_dir} (required, string) Directory where the
LSP server will base its rootUri on
initialization.
- {cmd} (required, list treated like
+ {cmd} (required, string or list treated like
|jobstart()|) Base command that
initiates the LSP client.
{cmd_cwd} (string, default=|getcwd()|) Directory
@@ -682,7 +690,7 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()*
object. To stop all clients:
>
- vim.lsp.stop_client(lsp.get_active_clients())
+ vim.lsp.stop_client(lsp.get_active_clients())
<
By default asks the server to shutdown, unless stop was
@@ -704,9 +712,6 @@ unsupported_method({method}) *vim.lsp.unsupported_method()*
validate_client_config({config}) *vim.lsp.validate_client_config()*
TODO: Documentation
-validate_command({input}) *vim.lsp.validate_command()*
- TODO: Documentation
-
validate_encoding({encoding}) *vim.lsp.validate_encoding()*
TODO: Documentation
@@ -746,6 +751,9 @@ transform_schema_to_table()
==============================================================================
Lua module: vim.lsp.buf *lsp-buf*
+clear_references() *vim.lsp.buf.clear_references()*
+ TODO: Documentation
+
code_action({context}) *vim.lsp.buf.code_action()*
TODO: Documentation
@@ -759,14 +767,32 @@ definition() *vim.lsp.buf.definition()*
TODO: Documentation
document_highlight() *vim.lsp.buf.document_highlight()*
- TODO: Documentation
+ Send request to server to resolve document highlights for the
+ current text document position. This request can be associated
+ to key mapping or to events such as `CursorHold` , eg:
+>
+ vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
+ vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
+ vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
+<
document_symbol() *vim.lsp.buf.document_symbol()*
TODO: Documentation
+execute_command({command}) *vim.lsp.buf.execute_command()*
+ TODO: Documentation
+
formatting({options}) *vim.lsp.buf.formatting()*
TODO: Documentation
+ *vim.lsp.buf.formatting_sync()*
+formatting_sync({options}, {timeout_ms})
+ Perform |vim.lsp.buf.formatting()| synchronously.
+
+ Useful for running on save, to make sure buffer is formatted
+ prior to being saved. {timeout_ms} is passed on to
+ |vim.lsp.buf_request_sync()|.
+
hover() *vim.lsp.buf.hover()*
TODO: Documentation
@@ -793,8 +819,8 @@ request({method}, {params}, {callback}) *vim.lsp.buf.request()*
TODO: Documentation
server_ready() *vim.lsp.buf.server_ready()*
- Sends a notification through all clients associated with current
- buffer and returns `true` if server responds.
+ Return: ~
+ `true` if server responds.
signature_help() *vim.lsp.buf.signature_help()*
TODO: Documentation
@@ -804,10 +830,12 @@ type_definition() *vim.lsp.buf.type_definition()*
workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()*
Lists all symbols in the current workspace in the quickfix
- window. The list is filtered against the optional argument
- {query}; if the argument is omitted from the call, the user
- is prompted to enter a string on the command line. An empty
- string means no filtering is done.
+ window.
+
+ The list is filtered against the optional argument {query}; if
+ the argument is omitted from the call, the user is prompted to
+ enter a string on the command line. An empty string means no
+ filtering is done.
==============================================================================
@@ -820,14 +848,6 @@ err_message({...}) *vim.lsp.callbacks.err_message()*
location_callback({_}, {method}, {result})
TODO: Documentation
- *vim.lsp.callbacks.log_message()*
-log_message({_}, {_}, {result}, {client_id})
- TODO: Documentation
-
- *vim.lsp.callbacks.signature_help_to_preview_contents()*
-signature_help_to_preview_contents({input})
- TODO: Documentation
-
==============================================================================
Lua module: vim.lsp.log *lsp-log*
@@ -859,8 +879,17 @@ create_and_start_client({cmd}, {cmd_args}, {handlers},
encode_and_send({payload}) *vim.lsp.rpc.encode_and_send()*
TODO: Documentation
-force_env_list({final_env}) *vim.lsp.rpc.force_env_list()*
- TODO: Documentation
+env_merge({env}) *vim.lsp.rpc.env_merge()*
+ Merges current process env with the given env and returns the
+ result as a list of "k=v" strings.
+>
+
+ Example:
+<
+
+ > in: { PRODUCTION="false", PATH="/usr/bin/", PORT=123, HOST="0.0.0.0", }
+ out: { "PRODUCTION=false", "PATH=/usr/bin/", "PORT=123", "HOST=0.0.0.0", }
+<
*vim.lsp.rpc.format_message_with_content_length()*
format_message_with_content_length({encoded_message})
@@ -934,6 +963,10 @@ try_call({errkind}, {fn}, {...}) *vim.lsp.rpc.try_call()*
==============================================================================
Lua module: vim.lsp.util *lsp-util*
+ *vim.lsp.util.apply_syntax_to_region()*
+apply_syntax_to_region({ft}, {start}, {finish})
+ TODO: Documentation
+
*vim.lsp.util.apply_text_document_edit()*
apply_text_document_edit({text_document_edit})
TODO: Documentation
@@ -946,59 +979,61 @@ apply_text_edits({text_edits}, {bufnr})
apply_workspace_edit({workspace_edit})
TODO: Documentation
- *vim.lsp.util.diagnostics_by_buf*
-diagnostics_by_buf
- A table containing diagnostics grouped by buf.
-
- {<bufnr>: {diagnostics}}
-
- {diagnostics} is an array of diagnostics.
-
- By default this is populated by the
- `textDocument/publishDiagnostics` callback via
- |vim.lsp.util.buf_diagnostics_save_positions|.
-
- It contains entries for active buffers. Once a buffer is
- detached the entries for it are discarded.
-
buf_clear_diagnostics({bufnr}) *vim.lsp.util.buf_clear_diagnostics()*
TODO: Documentation
-
- *vim.lsp.util.buf_diagnostics_count()*
-buf_diagnostics_count({kind})
- Returns the number of diagnostics of given kind for current buffer.
- Useful for showing diagnostics counts in statusline. eg:
+buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
+ TODO: Documentation
+
+buf_diagnostics_count({kind}) *vim.lsp.util.buf_diagnostics_count()*
+ Returns the number of diagnostics of given kind for current
+ buffer.
+
+ Useful for showing diagnostic counts in statusline. eg:
>
+
function! LspStatus() abort
let sl = ''
- if luaeval('vim.lsp.buf.server_ready()')
+ if luaeval('not vim.tbl_isempty(vim.lsp.buf_get_clients(0))')
let sl.='%#MyStatuslineLSP#E:'
- let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.util.buf_diagnostics_count(\"Error\")")}'
+ let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.util.buf_diagnostics_count([[Error]])")}'
let sl.='%#MyStatuslineLSP# W:'
- let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.util.buf_diagnostics_count(\"Warning\")")}'
+ let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.util.buf_diagnostics_count([[Warning]])")}'
else
let sl.='%#MyStatuslineLSPErrors#off'
endif
return sl
endfunction
- let &l:statusline = '%#MyStatuslineLSP#LSP '.LspStatus()
+ let &l:statusline = '%#MyStatuslineLSP#LSP '.LspStatus()
<
Parameters: ~
- {kind} Diagnostic severity kind: Error, Warning, Information or Hint.
+ {kind} Diagnostic severity kind: See
+ |vim.lsp.protocol.DiagnosticSeverity|
-buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
- TODO: Documentation
+ Return: ~
+ Count of diagnostics
- *vim.lsp.util.buf_diagnostics_save()*
+ *vim.lsp.util.buf_diagnostics_save_positions()*
buf_diagnostics_save_positions({bufnr}, {diagnostics})
- Stores the diagnostics into |vim.lsp.util.diagnostics_by_buf|
+ Saves the diagnostics (Diagnostic[]) into diagnostics_by_buf
Parameters: ~
- {bufr} bufnr for which the diagnostics are for.
- {diagnostics} Diagnostics[] received from the
- langauge server.
+ {bufnr} bufnr for which the diagnostics are for.
+ {diagnostics} Diagnostics[] received from the language
+ server.
+
+ *vim.lsp.util.buf_diagnostics_signs()*
+buf_diagnostics_signs({bufnr}, {diagnostics})
+ Place signs for each diagnostic in the sign column.
+
+ Sign characters can be customized with the following commands:
+>
+ sign define LspDiagnosticsErrorSign text=E texthl=LspDiagnosticsError linehl= numhl=
+ sign define LspDiagnosticsWarningSign text=W texthl=LspDiagnosticsWarning linehl= numhl=
+ sign define LspDiagnosticsInformationSign text=I texthl=LspDiagnosticsInformation linehl= numhl=
+ sign define LspDiagnosticsHintSign text=H texthl=LspDiagnosticsHint linehl= numhl=
+<
*vim.lsp.util.buf_diagnostics_underline()*
buf_diagnostics_underline({bufnr}, {diagnostics})
@@ -1008,17 +1043,9 @@ buf_diagnostics_underline({bufnr}, {diagnostics})
buf_diagnostics_virtual_text({bufnr}, {diagnostics})
TODO: Documentation
- *vim.lsp.util.buf_diagnostics_signs()*
-buf_diagnostics_signs({bufnr}, {diagnostics})
- Place signs for each diagnostic in the sign column.
- Sign characters can be customized with the following commands:
->
-sign define LspDiagnosticsErrorSign text=E texthl=LspDiagnosticsError linehl= numhl=
-sign define LspDiagnosticsWarningSign text=W texthl=LspDiagnosticsWarning linehl= numhl=
-sign define LspDiagnosticsInformationSign text=I texthl=LspDiagnosticsInformation linehl= numhl=
-sign define LspDiagnosticsHintSign text=H texthl=LspDiagnosticsHint linehl= numhl=
-<
-
+ *vim.lsp.util.buf_highlight_references()*
+buf_highlight_references({bufnr}, {references})
+ TODO: Documentation
character_offset({buf}, {row}, {col}) *vim.lsp.util.character_offset()*
TODO: Documentation
@@ -1031,13 +1058,33 @@ close_preview_autocmd({events}, {winnr})
convert_input_to_markdown_lines({input}, {contents})
TODO: Documentation
+ *vim.lsp.util.convert_signature_help_to_markdown_lines()*
+convert_signature_help_to_markdown_lines({signature_help})
+ TODO: Documentation
+
+ *vim.lsp.util.diagnostics_group_by_line()*
+diagnostics_group_by_line({diagnostics})
+ TODO: Documentation
+
*vim.lsp.util.extract_completion_items()*
extract_completion_items({result})
TODO: Documentation
*vim.lsp.util.fancy_floating_markdown()*
fancy_floating_markdown({contents}, {opts})
- TODO: Documentation
+ Convert markdown into syntax highlighted regions by stripping
+ the code blocks and converting them into highlighted code.
+ This will by default insert a blank line separator after those
+ code block regions to improve readability. The result is shown
+ in a floating preview TODO: refactor to separate
+ stripping/converting and make use of open_floating_preview
+
+ Parameters: ~
+ {contents} table of lines to show in window
+ {opts} dictionary with optional fields
+
+ Return: ~
+ width,height size of float
find_window_by_var({name}, {value}) *vim.lsp.util.find_window_by_var()*
TODO: Documentation
@@ -1049,10 +1096,33 @@ focusable_float({unique_name}, {fn}) *vim.lsp.util.focusable_float()*
focusable_preview({unique_name}, {fn})
TODO: Documentation
+get_completion_word({item}) *vim.lsp.util.get_completion_word()*
+ TODO: Documentation
+
*vim.lsp.util.get_current_line_to_cursor()*
get_current_line_to_cursor()
TODO: Documentation
+get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
+ Get visual width of tabstop.
+
+ Parameters: ~
+ {bufnr} (optional, number): Buffer handle, defaults to
+ current
+
+ Return: ~
+ (number) tabstop visual width
+
+ See also: ~
+ |softtabstop|
+
+ *vim.lsp.util.get_line_byte_from_position()*
+get_line_byte_from_position({bufnr}, {position})
+ TODO: Documentation
+
+get_line_diagnostics() *vim.lsp.util.get_line_diagnostics()*
+ TODO: Documentation
+
*vim.lsp.util.get_severity_highlight_name()*
get_severity_highlight_name({severity})
TODO: Documentation
@@ -1060,9 +1130,6 @@ get_severity_highlight_name({severity})
jump_to_location({location}) *vim.lsp.util.jump_to_location()*
TODO: Documentation
-preview_location({location}) *vim.lsp.util.preview_location()*
- TODO: Documentation
-
locations_to_items({locations}) *vim.lsp.util.locations_to_items()*
TODO: Documentation
@@ -1070,9 +1137,22 @@ locations_to_items({locations}) *vim.lsp.util.locations_to_items()*
make_floating_popup_options({width}, {height}, {opts})
TODO: Documentation
+ *vim.lsp.util.make_formatting_params()*
+make_formatting_params({options})
+ TODO: Documentation
+
+make_position_param() *vim.lsp.util.make_position_param()*
+ TODO: Documentation
+
make_position_params() *vim.lsp.util.make_position_params()*
TODO: Documentation
+make_range_params() *vim.lsp.util.make_range_params()*
+ TODO: Documentation
+
+make_text_document_params() *vim.lsp.util.make_text_document_params()*
+ TODO: Documentation
+
npcall({fn}, {...}) *vim.lsp.util.npcall()*
TODO: Documentation
@@ -1081,15 +1161,49 @@ ok_or_nil({status}, {...}) *vim.lsp.util.ok_or_nil()*
*vim.lsp.util.open_floating_preview()*
open_floating_preview({contents}, {filetype}, {opts})
+ Show contents in a floating window
+
+ Parameters: ~
+ {contents} table of lines to show in window
+ {filetype} string of filetype to set for opened buffer
+ {opts} dictionary with optional fields
+
+ Return: ~
+ bufnr,winnr buffer and window number of floating window or
+ nil
+
+parse_snippet({input}) *vim.lsp.util.parse_snippet()*
+ TODO: Documentation
+
+parse_snippet_rec({input}, {inner}) *vim.lsp.util.parse_snippet_rec()*
+ TODO: Documentation
+
+preview_location({location}) *vim.lsp.util.preview_location()*
+ Preview a location in a floating windows
+
+ behavior depends on type of location:
+ • for Location, range is shown (e.g., function definition)
+ • for LocationLink, targetRange is shown (e.g., body of
+ function definition)
+
+ Parameters: ~
+ {location} a single Location or LocationLink
+
+ Return: ~
+ bufnr,winnr buffer and window number of floating window or
+ nil
+
+ *vim.lsp.util.remove_unmatch_completion_items()*
+remove_unmatch_completion_items({items}, {prefix})
TODO: Documentation
set_lines({lines}, {A}, {B}, {new_lines}) *vim.lsp.util.set_lines()*
TODO: Documentation
-set_loclist({locations}) *vim.lsp.util.set_loclist()*
+set_loclist({items}) *vim.lsp.util.set_loclist()*
TODO: Documentation
-set_qflist({locations}) *vim.lsp.util.set_qflist()*
+set_qflist({items}) *vim.lsp.util.set_qflist()*
TODO: Documentation
show_line_diagnostics() *vim.lsp.util.show_line_diagnostics()*
@@ -1098,11 +1212,20 @@ show_line_diagnostics() *vim.lsp.util.show_line_diagnostics()*
sort_by_key({fn}) *vim.lsp.util.sort_by_key()*
TODO: Documentation
+sort_completion_items({items}) *vim.lsp.util.sort_completion_items()*
+ TODO: Documentation
+
split_lines({value}) *vim.lsp.util.split_lines()*
TODO: Documentation
+symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()*
+ Convert symbols to quickfix list items
+
+ Parameters: ~
+ {symbols} DocumentSymbol[] or SymbolInformation[]
+
*vim.lsp.util.text_document_completion_list_to_complete_items()*
-text_document_completion_list_to_complete_items({result})
+text_document_completion_list_to_complete_items({result}, {prefix})
TODO: Documentation
trim_empty_lines({lines}) *vim.lsp.util.trim_empty_lines()*
@@ -1112,7 +1235,4 @@ trim_empty_lines({lines}) *vim.lsp.util.trim_empty_lines()*
try_trim_markdown_code_blocks({lines})
TODO: Documentation
-validate_lsp_position({pos}) *vim.lsp.util.validate_lsp_position()*
- TODO: Documentation
-
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 5a49d36503..002fc523a1 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -512,6 +512,9 @@ 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.
+Parser methods *lua-treesitter-parser*
+
+tsparser:parse() *tsparser:parse()*
Whenever you need to access the current syntax tree, parse the buffer: >
tstree = parser:parse()
@@ -528,6 +531,16 @@ shouldn't be done directly in the change callback anyway as they will be very
frequent. Rather a plugin that does any kind of analysis on a tree should use
a timer to throttle too frequent updates.
+tsparser:set_included_ranges(ranges) *tsparser:set_included_ranges()*
+ Changes the ranges the parser should consider. This is used for
+ language injection. `ranges` should be of the form (all zero-based): >
+ {
+ {start_node, end_node},
+ ...
+ }
+<
+ NOTE: `start_node` and `end_node` are both inclusive.
+
Tree methods *lua-treesitter-tree*
tstree:root() *tstree:root()*
@@ -1018,6 +1031,9 @@ inspect({object}, {options}) *vim.inspect()*
https://github.com/kikito/inspect.lua
https://github.com/mpeterv/vinspect
+make_meta_accessor({get}, {set}, {del}) *vim.make_meta_accessor()*
+ TODO: Documentation
+
paste({lines}, {phase}) *vim.paste()*
Paste handler, invoked by |nvim_paste()| when a conforming UI
(such as the |TUI|) pastes text into the editor.
@@ -1133,7 +1149,7 @@ list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
|vim.tbl_extend()|
pesc({s}) *vim.pesc()*
- Escapes magic chars in a Lua pattern string.
+ Escapes magic chars in a Lua pattern.
Parameters: ~
{s} String to escape
@@ -1177,8 +1193,7 @@ startswith({s}, {prefix}) *vim.startswith()*
tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
Add the reverse lookup values to an existing table. For
- example: `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A =
- 1 }`
+ example: tbl_add_reverse_lookup { A = 1 } == { [1] = 'A , A = 1 }`
Parameters: ~
{o} table The table to add the reverse to.
@@ -1193,6 +1208,37 @@ tbl_contains({t}, {value}) *vim.tbl_contains()*
Return: ~
true if `t` contains `value`
+tbl_count({t}) *vim.tbl_count()*
+ Counts the number of non-nil values in table `t` .
+>
+
+ vim.tbl_count({ a=1, b=2 }) => 2
+ vim.tbl_count({ 1, 2 }) => 2
+<
+
+ Parameters: ~
+ {t} Table
+
+ Return: ~
+ Number that is the number of the value in table
+
+ See also: ~
+ https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
+
+tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
+ Merges recursively two or more map-like tables.
+
+ Parameters: ~
+ {behavior} Decides what to do if a key is found in more
+ than one map:
+ • "error": raise an error
+ • "keep": use value from the leftmost map
+ • "force": use value from the rightmost map
+ {...} Two or more map-like tables.
+
+ See also: ~
+ |tbl_extend()|
+
tbl_extend({behavior}, {...}) *vim.tbl_extend()*
Merges two or more map-like tables.
@@ -1207,6 +1253,13 @@ tbl_extend({behavior}, {...}) *vim.tbl_extend()*
See also: ~
|extend()|
+tbl_filter({func}, {t}) *vim.tbl_filter()*
+ Filter a table using a predicate function
+
+ Parameters: ~
+ {func} function or callable table
+ {t} table
+
tbl_flatten({t}) *vim.tbl_flatten()*
Creates a copy of a list-like table such that any nested
tables are "unrolled" and appended to the result.
@@ -1225,11 +1278,19 @@ tbl_isempty({t}) *vim.tbl_isempty()*
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua@paramt Table to check
tbl_islist({t}) *vim.tbl_islist()*
- Table
+ Determine whether a Lua table can be treated as an array.
+
+ An empty table `{}` will default to being treated as an array.
+ Use `vim.emtpy_dict()` to create a table treated as an empty
+ dict. Empty tables returned by `rpcrequest()` and `vim.fn`
+ functions can be checked using this function whether they
+ represent empty API arrays and vimL lists.
+
+ Parameters: ~
+ {t} Table
Return: ~
- true: A non-empty array, false: A non-empty table, nil: An
- empty table
+ `true` if array-like table, else `false` .
tbl_keys({t}) *vim.tbl_keys()*
Return a list of all keys used in a table. However, the order
@@ -1244,6 +1305,13 @@ tbl_keys({t}) *vim.tbl_keys()*
See also: ~
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua
+tbl_map({func}, {t}) *vim.tbl_map()*
+ Apply a function to all values of a table.
+
+ Parameters: ~
+ {func} function or callable table
+ {t} table
+
tbl_values({t}) *vim.tbl_values()*
Return a list of all values used in a table. However, the
order of the return table of values is not guaranteed.
@@ -1288,12 +1356,12 @@ validate({opt}) *vim.validate()*
=> NOP (success)
<
>
- vim.validate{arg1={1, 'table'}}
- => error('arg1: expected table, got number')
+ vim.validate{arg1={1, 'table'}}
+ => error('arg1: expected table, got number')
<
>
- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- => error('arg1: expected even number, got 3')
+ vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ => error('arg1: expected even number, got 3')
<
Parameters: ~
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index e759511347..7442f0c0b5 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -877,11 +877,11 @@ function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
end
--- Send a notification to a server
--- @param bufnr [number] (optional): The number of the buffer
--- @param method [string]: Name of the request method
--- @param params [string]: Arguments to send to the server
---
--- @returns true if any client returns true; false otherwise
+--@param bufnr [number] (optional): The number of the buffer
+--@param method [string]: Name of the request method
+--@param params [string]: Arguments to send to the server
+---
+--@returns true if any client returns true; false otherwise
function lsp.buf_notify(bufnr, method, params)
validate {
bufnr = { bufnr, 'n', true };
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 7a819f3c3d..839e00c67d 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -23,6 +23,9 @@ local function request(method, params, callback)
return vim.lsp.buf_request(0, method, params, callback)
end
+--- Sends a notification through all clients associated with current buffer.
+--
+--@return `true` if server responds.
function M.server_ready()
return not not vim.lsp.buf_notify(0, "window/progress", {})
end
@@ -65,19 +68,22 @@ function M.completion(context)
end
function M.formatting(options)
- validate { options = {options, 't', true} }
- local sts = vim.bo.softtabstop;
- options = vim.tbl_extend('keep', options or {}, {
- tabSize = (sts > 0 and sts) or (sts < 0 and vim.bo.shiftwidth) or vim.bo.tabstop;
- insertSpaces = vim.bo.expandtab;
- })
- local params = {
- textDocument = { uri = vim.uri_from_bufnr(0) };
- options = options;
- }
+ local params = util.make_formatting_params(options)
return request('textDocument/formatting', params)
end
+--- Perform |vim.lsp.buf.formatting()| synchronously.
+---
+--- Useful for running on save, to make sure buffer is formatted prior to being
+--- saved. {timeout_ms} is passed on to |vim.lsp.buf_request_sync()|.
+function M.formatting_sync(options, timeout_ms)
+ local params = util.make_formatting_params(options)
+ local result = vim.lsp.buf_request_sync(0, "textDocument/formatting", params, timeout_ms)
+ if not result then return end
+ result = result[1].result
+ vim.lsp.util.apply_text_edits(result)
+end
+
function M.range_formatting(options, start_pos, end_pos)
validate {
options = {options, 't', true};
@@ -116,7 +122,7 @@ function M.rename(new_name)
-- TODO(ashkan) use prepareRename
-- * result: [`Range`](#range) \| `{ range: Range, placeholder: string }` \| `null` describing the range of the string to rename and optionally a placeholder text of the string content to be renamed. If `null` is returned then it is deemed that a 'textDocument/rename' request is not valid at the given position.
local params = util.make_position_params()
- new_name = new_name or npcall(vfn.input, "New Name: ")
+ new_name = new_name or npcall(vfn.input, "New Name: ", vfn.expand('<cword>'))
if not (new_name and #new_name > 0) then return end
params.newName = new_name
request('textDocument/rename', params)
@@ -137,6 +143,12 @@ function M.document_symbol()
request('textDocument/documentSymbol', params)
end
+
+--- Lists all symbols in the current workspace in the quickfix window.
+---
+--- The list is filtered against the optional argument {query};
+--- if the argument is omitted from the call, the user is prompted to enter a string on the command line.
+--- An empty string means no filtering is done.
function M.workspace_symbol(query)
query = query or npcall(vfn.input, "Query: ")
local params = {query = query}
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index dad1dc11f1..81c92bfe05 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -36,10 +36,12 @@ end
--- Merges current process env with the given env and returns the result as
--- a list of "k=v" strings.
---
+--- <pre>
--- Example:
---
---- { PRODUCTION="false", PATH="/usr/bin/", PORT=123, HOST="0.0.0.0", }
---- => { "PRODUCTION=false", "PATH=/usr/bin/", "PORT=123", "HOST=0.0.0.0", }
+--- in: { PRODUCTION="false", PATH="/usr/bin/", PORT=123, HOST="0.0.0.0", }
+--- out: { "PRODUCTION=false", "PATH=/usr/bin/", "PORT=123", "HOST=0.0.0.0", }
+--- </pre>
local function env_merge(env)
if env == nil then
return env
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 0f366c2b57..6b19d3ecd6 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -952,7 +952,9 @@ do
end
--- Saves the diagnostics (Diagnostic[]) into diagnostics_by_buf
- --
+ ---
+ --@param bufnr bufnr for which the diagnostics are for.
+ --@param diagnostics Diagnostics[] received from the language server.
function M.buf_diagnostics_save_positions(bufnr, diagnostics)
validate {
bufnr = {bufnr, 'n', true};
@@ -1044,6 +1046,29 @@ do
end
end
+ --- Returns the number of diagnostics of given kind for current buffer.
+ ---
+ --- Useful for showing diagnostic counts in statusline. eg:
+ ---
+ --- <pre>
+ --- function! LspStatus() abort
+ --- let sl = ''
+ --- if luaeval('not vim.tbl_isempty(vim.lsp.buf_get_clients(0))')
+ --- let sl.='%#MyStatuslineLSP#E:'
+ --- let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.util.buf_diagnostics_count([[Error]])")}'
+ --- let sl.='%#MyStatuslineLSP# W:'
+ --- let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.util.buf_diagnostics_count([[Warning]])")}'
+ --- else
+ --- let sl.='%#MyStatuslineLSPErrors#off'
+ --- endif
+ --- return sl
+ --- endfunction
+ --- let &l:statusline = '%#MyStatuslineLSP#LSP '.LspStatus()
+ --- </pre>
+ ---
+ --@param kind Diagnostic severity kind: See |vim.lsp.protocol.DiagnosticSeverity|
+ ---
+ --@return Count of diagnostics
function M.buf_diagnostics_count(kind)
local bufnr = vim.api.nvim_get_current_buf()
local diagnostics = M.diagnostics_by_buf[bufnr]
@@ -1064,6 +1089,16 @@ do
[protocol.DiagnosticSeverity.Hint] = "LspDiagnosticsHintSign";
}
+ --- Place signs for each diagnostic in the sign column.
+ ---
+ --- Sign characters can be customized with the following commands:
+ ---
+ --- <pre>
+ --- sign define LspDiagnosticsErrorSign text=E texthl=LspDiagnosticsError linehl= numhl=
+ --- sign define LspDiagnosticsWarningSign text=W texthl=LspDiagnosticsWarning linehl= numhl=
+ --- sign define LspDiagnosticsInformationSign text=I texthl=LspDiagnosticsInformation linehl= numhl=
+ --- sign define LspDiagnosticsHintSign text=H texthl=LspDiagnosticsHint linehl= numhl=
+ --- </pre>
function M.buf_diagnostics_signs(bufnr, diagnostics)
for _, diagnostic in ipairs(diagnostics) do
vim.fn.sign_place(0, sign_ns, diagnostic_severity_map[diagnostic.severity], bufnr, {lnum=(diagnostic.range.start.line+1)})
@@ -1089,40 +1124,31 @@ function M.locations_to_items(locations)
for _, d in ipairs(locations) do
-- locations may be Location or LocationLink
local uri = d.uri or d.targetUri
- local fname = assert(vim.uri_to_fname(uri))
local range = d.range or d.targetSelectionRange
- table.insert(grouped[fname], {start = range.start})
+ table.insert(grouped[uri], {start = range.start})
end
local keys = vim.tbl_keys(grouped)
table.sort(keys)
-- TODO(ashkan) I wish we could do this lazily.
- for _, fname in ipairs(keys) do
- local rows = grouped[fname]
-
+ for _, uri in ipairs(keys) do
+ local rows = grouped[uri]
table.sort(rows, position_sort)
- local i = 0
- for line in io.lines(fname) do
- for _, temp in ipairs(rows) do
- local pos = temp.start
- local row = pos.line
- if i == row then
- local col
- if pos.character > #line then
- col = #line
- else
- col = vim.str_byteindex(line, pos.character)
- end
- table.insert(items, {
- filename = fname,
- lnum = row + 1,
- col = col + 1;
- text = line;
- })
- end
- end
- i = i + 1
+ local bufnr = vim.uri_to_bufnr(uri)
+ vim.fn.bufload(bufnr)
+ local filename = vim.uri_to_fname(uri)
+ for _, temp in ipairs(rows) do
+ local pos = temp.start
+ local row = pos.line
+ local line = (api.nvim_buf_get_lines(bufnr, row, row + 1, false) or {""})[1]
+ local col = M.character_offset(bufnr, row, pos.character)
+ table.insert(items, {
+ filename = filename,
+ lnum = row + 1,
+ col = col + 1;
+ text = line;
+ })
end
end
return items
@@ -1151,7 +1177,7 @@ end
--- Convert symbols to quickfix list items
---
---@symbols DocumentSymbol[] or SymbolInformation[]
+--@param symbols DocumentSymbol[] or SymbolInformation[]
function M.symbols_to_items(symbols, bufnr)
local function _symbols_to_items(_symbols, _items, _bufnr)
for _, symbol in ipairs(_symbols) do
@@ -1260,6 +1286,30 @@ function M.make_text_document_params()
return { uri = vim.uri_from_bufnr(0) }
end
+--- Get visual width of tabstop.
+---
+--@see |softtabstop|
+--@param bufnr (optional, number): Buffer handle, defaults to current
+--@returns (number) tabstop visual width
+function M.get_effective_tabstop(bufnr)
+ validate { bufnr = {bufnr, 'n', true} }
+ local bo = bufnr and vim.bo[bufnr] or vim.bo
+ local sts = bo.softtabstop
+ return (sts > 0 and sts) or (sts < 0 and bo.shiftwidth) or bo.tabstop
+end
+
+function M.make_formatting_params(options)
+ validate { options = {options, 't', true} }
+ options = vim.tbl_extend('keep', options or {}, {
+ tabSize = M.get_effective_tabstop();
+ insertSpaces = vim.bo.expandtab;
+ })
+ return {
+ textDocument = { uri = vim.uri_from_bufnr(0) };
+ options = options;
+ }
+end
+
-- @param buf buffer handle or 0 for current.
-- @param row 0-indexed line
-- @param col 0-indexed byte offset in line
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 384d22cb89..6e427665f2 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -347,16 +347,16 @@ function vim.tbl_flatten(t)
return result
end
--- Determine whether a Lua table can be treated as an array.
---
--- An empty table `{}` will default to being treated as an array.
--- Use `vim.emtpy_dict()` to create a table treated as an
--- empty dict. Empty tables returned by `rpcrequest()` and
--- `vim.fn` functions can be checked using this function
--- whether they represent empty API arrays and vimL lists.
----
---@params Table
---@returns true: An array-like table, false: A dict-like or mixed table
+--- Determine whether a Lua table can be treated as an array.
+---
+--- An empty table `{}` will default to being treated as an array.
+--- Use `vim.emtpy_dict()` to create a table treated as an
+--- empty dict. Empty tables returned by `rpcrequest()` and
+--- `vim.fn` functions can be checked using this function
+--- whether they represent empty API arrays and vimL lists.
+---
+--@param t Table
+--@returns `true` if array-like table, else `false`.
function vim.tbl_islist(t)
if type(t) ~= 'table' then
return false
@@ -392,7 +392,7 @@ end
--- </pre>
---
--@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
---@param Table
+--@param t Table
--@returns Number that is the number of the value in table
function vim.tbl_count(t)
vim.validate{t={t,'t'}}
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index c502e45bd0..f356673839 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -30,6 +30,12 @@ function Parser:_on_lines(bufnr, _, start_row, old_stop_row, stop_row, old_byte_
self.valid = false
end
+function Parser:set_included_ranges(ranges)
+ self._parser:set_included_ranges(ranges)
+ -- The buffer will need to be parsed again later
+ self.valid = false
+end
+
local M = {
parse_query = vim._ts_parse_query,
}
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 3c51b2aa81..328a903b46 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -374,6 +374,7 @@ def update_params_map(parent, ret_map, width=62):
def render_node(n, text, prefix='', indent='', width=62):
"""Renders a node as Vim help text, recursively traversing all descendants."""
global fmt_vimhelp
+ global has_seen_preformatted
def ind(s):
return s if fmt_vimhelp else ''
@@ -386,6 +387,7 @@ def render_node(n, text, prefix='', indent='', width=62):
o = get_text(n, preformatted=True)
ensure_nl = '' if o[-1] == '\n' else '\n'
text += '>{}{}\n<'.format(ensure_nl, o)
+
elif is_inline(n):
text = doc_wrap(get_text(n), indent=indent, width=width)
elif n.nodeName == 'verbatim':
@@ -394,11 +396,17 @@ def render_node(n, text, prefix='', indent='', width=62):
text += ' [verbatim] {}'.format(get_text(n))
elif n.nodeName == 'listitem':
for c in n.childNodes:
- text += (
- indent
- + prefix
- + render_node(c, text, indent=indent + (' ' * len(prefix)), width=width)
+ result = render_node(
+ c,
+ text,
+ indent=indent + (' ' * len(prefix)),
+ width=width
)
+
+ if is_blank(result):
+ continue
+
+ text += indent + prefix + result
elif n.nodeName in ('para', 'heading'):
for c in n.childNodes:
text += render_node(c, text, indent=indent, width=width)
@@ -433,6 +441,7 @@ def render_node(n, text, prefix='', indent='', width=62):
else:
raise RuntimeError('unhandled node type: {}\n{}'.format(
n.nodeName, n.toprettyxml(indent=' ', newl='\n')))
+
return text
@@ -496,6 +505,7 @@ def para_as_map(parent, indent='', width=62):
and '' != get_text(self_or_child(child)).strip()
and ' ' != text[-1]):
text += ' '
+
text += render_node(child, text, indent=indent, width=width)
prev = child
@@ -566,6 +576,7 @@ def fmt_node_as_vimhelp(parent, width=62, indent=''):
rendered_blocks.append(clean_lines('\n'.join(chunks).strip()))
rendered_blocks.append('')
+
return clean_lines('\n'.join(rendered_blocks).strip())
@@ -678,6 +689,11 @@ def extract_from_xml(filename, target, width):
signature += vimtag.rjust(width - len(signature))
paras = []
+ brief_desc = find_first(member, 'briefdescription')
+ if brief_desc:
+ for child in brief_desc.childNodes:
+ paras.append(para_as_map(child))
+
desc = find_first(member, 'detaileddescription')
if desc:
for child in desc.childNodes:
@@ -763,8 +779,36 @@ def fmt_doxygen_xml_as_vimhelp(filename, target):
func_doc = fn['signature'] + '\n'
func_doc += textwrap.indent(clean_lines(doc), ' ' * 16)
+
+ # Verbatim handling.
func_doc = re.sub(r'^\s+([<>])$', r'\1', func_doc, flags=re.M)
+ split_lines = func_doc.split('\n')
+ start = 0
+ while True:
+ try:
+ start = split_lines.index('>', start)
+ except ValueError:
+ break
+
+ try:
+ end = split_lines.index('<', start)
+ except ValueError:
+ break
+
+ split_lines[start + 1:end] = [
+ (' ' + x).rstrip()
+ for x in textwrap.dedent(
+ "\n".join(
+ split_lines[start+1:end]
+ )
+ ).split("\n")
+ ]
+
+ start = end
+
+ func_doc = "\n".join(split_lines)
+
if 'Deprecated' in xrefs:
deprecated_fns_txt[name] = func_doc
elif name.startswith(CONFIG[target]['fn_name_prefix']):
@@ -847,11 +891,21 @@ def main(config):
groupxml = os.path.join(base, '%s.xml' %
compound.getAttribute('refid'))
- desc = find_first(minidom.parse(groupxml), 'detaileddescription')
+ group_parsed = minidom.parse(groupxml)
+ doc_list = []
+ brief_desc = find_first(group_parsed, 'briefdescription')
+ if brief_desc:
+ for child in brief_desc.childNodes:
+ doc_list.append(fmt_node_as_vimhelp(child))
+
+ desc = find_first(group_parsed, 'detaileddescription')
if desc:
doc = fmt_node_as_vimhelp(desc)
+
if doc:
- intros[groupname] = doc
+ doc_list.append(doc)
+
+ intros[groupname] = "\n".join(doc_list)
for compound in dom.getElementsByTagName('compound'):
if compound.getAttribute('kind') != 'file':
diff --git a/scripts/lua2dox_filter b/scripts/lua2dox_filter
index 6cb16ef060..61577527c4 100755
--- a/scripts/lua2dox_filter
+++ b/scripts/lua2dox_filter
@@ -36,7 +36,16 @@ test_executable(){
##! \brief sets the lua interpreter
set_lua(){
- test_executable 'texlua'
+ if test -z "${EXE}"
+ then
+ test_executable 'luajit'
+ fi
+
+ if test -z "${EXE}"
+ then
+ test_executable 'texlua'
+ fi
+
if test -z "${EXE}"
then
test_executable 'lua'
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 18474c6588..8e61976c4b 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -42,6 +42,8 @@
/// \defgroup api-buffer
///
+/// \brief For more information on buffers, see |buffers|
+///
/// Unloaded Buffers:~
///
/// Buffers may be unloaded by the |:bunload| command or the buffer's
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 40cef87cf0..d6f95c7a5f 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -203,6 +203,16 @@ Integer nvim_get_hl_id_by_name(String name)
/// flags. This is a blocking call, unlike |nvim_input()|.
///
/// On execution error: does not fail, but updates v:errmsg.
+//
+// If you need to input sequences like <C-o> use nvim_replace_termcodes
+// to replace the termcodes and then pass the resulting string to
+// nvim_feedkeys. You'll also want to enable escape_csi.
+///
+/// Example:
+/// <pre>
+/// :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true)
+/// :call nvim_feedkeys(key, 'n', v:true)
+/// </pre>
///
/// @param keys to be typed
/// @param mode behavior flags, see |feedkeys()|
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 327ed6d6b7..4b47b34d8a 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1128,21 +1128,11 @@ void ex_luafile(exarg_T *const eap)
}
}
-static int create_tslua_parser(lua_State *L)
-{
- if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) {
- return luaL_error(L, "string expected");
- }
-
- const char *lang_name = lua_tostring(L, 1);
- return tslua_push_parser(L, lang_name);
-}
-
static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
{
tslua_init(lstate);
- lua_pushcfunction(lstate, create_tslua_parser);
+ lua_pushcfunction(lstate, tslua_push_parser);
lua_setfield(lstate, -2, "_create_ts_parser");
lua_pushcfunction(lstate, tslua_add_language);
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 51d9549033..ddf54720a7 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -20,6 +20,7 @@
#include "nvim/lua/treesitter.h"
#include "nvim/api/private/handle.h"
#include "nvim/memline.h"
+#include "nvim/buffer.h"
typedef struct {
TSParser *parser;
@@ -41,6 +42,7 @@ static struct luaL_Reg parser_meta[] = {
{ "parse_buf", parser_parse_buf },
{ "edit", parser_edit },
{ "tree", parser_tree },
+ { "set_included_ranges", parser_set_ranges },
{ NULL, NULL }
};
@@ -214,8 +216,13 @@ int tslua_inspect_lang(lua_State *L)
return 1;
}
-int tslua_push_parser(lua_State *L, const char *lang_name)
+int tslua_push_parser(lua_State *L)
{
+ // Gather language
+ if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) {
+ return luaL_error(L, "string expected");
+ }
+ const char *lang_name = lua_tostring(L, 1);
TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
if (!lang) {
return luaL_error(L, "no such language: %s", lang_name);
@@ -377,6 +384,57 @@ static int parser_edit(lua_State *L)
return 0;
}
+static int parser_set_ranges(lua_State *L)
+{
+ if (lua_gettop(L) < 2) {
+ return luaL_error(
+ L,
+ "not enough args to parser:set_included_ranges()");
+ }
+
+ TSLua_parser *p = parser_check(L);
+ if (!p || !p->tree) {
+ return 0;
+ }
+
+ if (!lua_istable(L, 2)) {
+ return luaL_error(
+ L,
+ "argument for parser:set_included_ranges() should be a table.");
+ }
+
+ size_t tbl_len = lua_objlen(L, 2);
+ TSRange *ranges = xmalloc(sizeof(TSRange) * tbl_len);
+
+
+ // [ parser, ranges ]
+ for (size_t index = 0; index < tbl_len; index++) {
+ lua_rawgeti(L, 2, index + 1); // [ parser, ranges, range ]
+
+ TSNode node;
+ if (!node_check(L, -1, &node)) {
+ xfree(ranges);
+ return luaL_error(
+ L,
+ "ranges should be tables of nodes.");
+ }
+ lua_pop(L, 1); // [ parser, ranges ]
+
+ ranges[index] = (TSRange) {
+ .start_point = ts_node_start_point(node),
+ .end_point = ts_node_end_point(node),
+ .start_byte = ts_node_start_byte(node),
+ .end_byte = ts_node_end_byte(node)
+ };
+ }
+
+ // This memcpies ranges, thus we can free it afterwards
+ ts_parser_set_included_ranges(p->parser, ranges, tbl_len);
+ xfree(ranges);
+
+ return 0;
+}
+
// Tree methods
@@ -459,9 +517,9 @@ static void push_node(lua_State *L, TSNode node, int uindex)
lua_setfenv(L, -2); // [udata]
}
-static bool node_check(lua_State *L, TSNode *res)
+static bool node_check(lua_State *L, int index, TSNode *res)
{
- TSNode *ud = luaL_checkudata(L, 1, "treesitter_node");
+ TSNode *ud = luaL_checkudata(L, index, "treesitter_node");
if (ud) {
*res = *ud;
return true;
@@ -473,7 +531,7 @@ static bool node_check(lua_State *L, TSNode *res)
static int node_tostring(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
lua_pushstring(L, "<node ");
@@ -486,7 +544,7 @@ static int node_tostring(lua_State *L)
static int node_eq(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
// This should only be called if both x and y in "x == y" has the
@@ -503,7 +561,7 @@ static int node_eq(lua_State *L)
static int node_range(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSPoint start = ts_node_start_point(node);
@@ -518,7 +576,7 @@ static int node_range(lua_State *L)
static int node_start(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSPoint start = ts_node_start_point(node);
@@ -532,7 +590,7 @@ static int node_start(lua_State *L)
static int node_end(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSPoint end = ts_node_end_point(node);
@@ -546,7 +604,7 @@ static int node_end(lua_State *L)
static int node_child_count(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
uint32_t count = ts_node_child_count(node);
@@ -557,7 +615,7 @@ static int node_child_count(lua_State *L)
static int node_named_child_count(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
uint32_t count = ts_node_named_child_count(node);
@@ -568,7 +626,7 @@ static int node_named_child_count(lua_State *L)
static int node_type(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
lua_pushstring(L, ts_node_type(node));
@@ -578,7 +636,7 @@ static int node_type(lua_State *L)
static int node_symbol(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSSymbol symbol = ts_node_symbol(node);
@@ -589,7 +647,7 @@ static int node_symbol(lua_State *L)
static int node_named(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
lua_pushboolean(L, ts_node_is_named(node));
@@ -599,7 +657,7 @@ static int node_named(lua_State *L)
static int node_sexpr(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
char *allocated = ts_node_string(node);
@@ -611,7 +669,7 @@ static int node_sexpr(lua_State *L)
static int node_missing(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
lua_pushboolean(L, ts_node_is_missing(node));
@@ -621,7 +679,7 @@ static int node_missing(lua_State *L)
static int node_has_error(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
lua_pushboolean(L, ts_node_has_error(node));
@@ -631,7 +689,7 @@ static int node_has_error(lua_State *L)
static int node_child(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
long num = lua_tointeger(L, 2);
@@ -644,7 +702,7 @@ static int node_child(lua_State *L)
static int node_named_child(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
long num = lua_tointeger(L, 2);
@@ -657,7 +715,7 @@ static int node_named_child(lua_State *L)
static int node_descendant_for_range(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSPoint start = { (uint32_t)lua_tointeger(L, 2),
@@ -673,7 +731,7 @@ static int node_descendant_for_range(lua_State *L)
static int node_named_descendant_for_range(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSPoint start = { (uint32_t)lua_tointeger(L, 2),
@@ -689,7 +747,7 @@ static int node_named_descendant_for_range(lua_State *L)
static int node_parent(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSNode parent = ts_node_parent(node);
@@ -771,7 +829,7 @@ static int query_next_capture(lua_State *L)
static int node_rawquery(lua_State *L)
{
TSNode node;
- if (!node_check(L, &node)) {
+ if (!node_check(L, 1, &node)) {
return 0;
}
TSQuery *query = query_check(L, 2);
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 523d23ec12..047ce1ad43 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -255,6 +255,8 @@ function vim.schedule_wrap(cb)
end)
end
+--- <Docs described in |vim.empty_dict()| >
+--@private
function vim.empty_dict()
return setmetatable({}, vim._empty_dict_mt)
end
diff --git a/src/nvim/version.c b/src/nvim/version.c
index f3a584d15b..190f13e74b 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -364,7 +364,7 @@ static const int included_patches[] = {
1557,
1556,
1555,
- // 1554,
+ 1554,
1553,
1552,
1551,
@@ -375,7 +375,7 @@ static const int included_patches[] = {
1546,
1545,
// 1544,
- // 1543,
+ 1543,
1542,
1541,
1540,
diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua
index ecee471386..ab0224a911 100644
--- a/test/functional/lua/treesitter_spec.lua
+++ b/test/functional/lua/treesitter_spec.lua
@@ -404,4 +404,65 @@ static int nlua_schedule(lua_State *const lstate)
end
eq({true,true}, {has_named,has_anonymous})
end)
+ it('allows to set simple ranges', function()
+ if not check_parser() then return end
+
+ insert(test_text)
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ return { parser:parse():root():range() }
+ ]])
+
+ eq({0, 0, 19, 0}, res)
+
+ -- The following sets the included ranges for the current parser
+ -- As stated here, this only includes the function (thus the whole buffer, without the last line)
+ local res2 = exec_lua([[
+ local root = parser:parse():root()
+ parser:set_included_ranges({root:child(0)})
+ parser.valid = false
+ return { parser:parse():root():range() }
+ ]])
+
+ eq({0, 0, 18, 1}, res2)
+ end)
+ it("allows to set complex ranges", function()
+ if not check_parser() then return end
+
+ insert(test_text)
+
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ query = vim.treesitter.parse_query("c", "(declaration) @decl")
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do
+ table.insert(nodes, node)
+ end
+
+ parser:set_included_ranges(nodes)
+
+ local root = parser:parse():root()
+
+ local res = {}
+ for i=0,(root:named_child_count() - 1) do
+ table.insert(res, { root:named_child(i):range() })
+ end
+ return res
+ ]])
+
+ eq({
+ { 2, 2, 2, 40 },
+ { 3, 3, 3, 32 },
+ { 4, 7, 4, 8 },
+ { 4, 8, 4, 25 },
+ { 8, 2, 8, 6 },
+ { 8, 7, 8, 33 },
+ { 9, 8, 9, 20 },
+ { 10, 4, 10, 5 },
+ { 10, 5, 10, 20 },
+ { 14, 9, 14, 27 } }, res)
+ end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index c74ed6bf3b..1b022f50df 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -1070,6 +1070,64 @@ describe('LSP', function()
]])
end)
end)
+ describe('lsp.util.locations_to_items', function()
+ it('Convert Location[] to items', function()
+ local expected = {
+ {
+ filename = 'fake/uri',
+ lnum = 1,
+ col = 3,
+ text = 'testing'
+ },
+ }
+ local actual = exec_lua [[
+ local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local lines = {"testing", "123"}
+ vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
+ local locations = {
+ {
+ uri = 'file://fake/uri',
+ range = {
+ start = { line = 0, character = 2 },
+ ['end'] = { line = 0, character = 3 },
+ }
+ },
+ }
+ return vim.lsp.util.locations_to_items(locations)
+ ]]
+ eq(expected, actual)
+ end)
+ it('Convert LocationLink[] to items', function()
+ local expected = {
+ {
+ filename = 'fake/uri',
+ lnum = 1,
+ col = 3,
+ text = 'testing'
+ },
+ }
+ local actual = exec_lua [[
+ local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local lines = {"testing", "123"}
+ vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
+ local locations = {
+ {
+ targetUri = vim.uri_from_bufnr(bufnr),
+ targetRange = {
+ start = { line = 0, character = 2 },
+ ['end'] = { line = 0, character = 3 },
+ },
+ targetSelectionRange = {
+ start = { line = 0, character = 2 },
+ ['end'] = { line = 0, character = 3 },
+ }
+ },
+ }
+ return vim.lsp.util.locations_to_items(locations)
+ ]]
+ eq(expected, actual)
+ end)
+ end)
describe('lsp.util.symbols_to_items', function()
describe('convert DocumentSymbol[] to items', function()
it('DocumentSymbol has children', function()
@@ -1424,4 +1482,19 @@ describe('LSP', function()
eq({15,5}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]])
end)
end)
+
+ describe('lsp.util.get_effective_tabstop', function()
+ local function test_tabstop(tabsize, softtabstop)
+ exec_lua(string.format([[
+ vim.api.nvim_buf_set_option(0, 'softtabstop', %d)
+ vim.api.nvim_buf_set_option(0, 'tabstop', 2)
+ vim.api.nvim_buf_set_option(0, 'shiftwidth', 3)
+ ]], softtabstop))
+ eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()'))
+ end
+
+ it('with softtabstop = 1', function() test_tabstop(1, 1) end)
+ it('with softtabstop = 0', function() test_tabstop(2, 0) end)
+ it('with softtabstop = -1', function() test_tabstop(3, -1) end)
+ end)
end)