diff options
67 files changed, 718 insertions, 411 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 123014908b..e96fd5286f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,5 @@ updates: directory: "/" schedule: interval: "daily" + commit-message: + prefix: "ci" diff --git a/.github/labeler.yml b/.github/labeler.yml index ad48287246..111fc5f373 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,10 +2,6 @@ - runtime/lua/vim/lsp.lua - runtime/lua/vim/lsp/* -"lua": - - runtime/lua/**/* - - src/nvim/lua/* - "tui": - src/nvim/tui/tui.* diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c1d3ee3ff3..74661e686e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v7 + - uses: actions/stale@v8 with: days-before-close: 30 days-before-stale: -1 diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 48a96b1bd8..665503aded 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -14,6 +14,7 @@ include(Util) set(DEPS_CMAKE_ARGS -D CMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -D CMAKE_C_STANDARD=99 -D CMAKE_GENERATOR=${CMAKE_GENERATOR} -D CMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM} -D CMAKE_POSITION_INDEPENDENT_CODE=ON) diff --git a/cmake.deps/cmake/LibvtermCMakeLists.txt b/cmake.deps/cmake/LibvtermCMakeLists.txt index 0fb3227117..7b1d95f531 100644 --- a/cmake.deps/cmake/LibvtermCMakeLists.txt +++ b/cmake.deps/cmake/LibvtermCMakeLists.txt @@ -5,8 +5,6 @@ include(GNUInstallDirs) if(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) -else() - add_compile_options(-std=c99) endif() include_directories(${CMAKE_SOURCE_DIR}/include) diff --git a/cmake.deps/cmake/TreesitterCMakeLists.txt b/cmake.deps/cmake/TreesitterCMakeLists.txt index 759fa93bb0..9017436ef5 100644 --- a/cmake.deps/cmake/TreesitterCMakeLists.txt +++ b/cmake.deps/cmake/TreesitterCMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) project(tree-sitter C) -set(CMAKE_C_STANDARD 99) + add_library(tree-sitter lib/src/lib.c) target_include_directories(tree-sitter PRIVATE lib/src lib/include) diff --git a/cmake.deps/cmake/TreesitterParserCMakeLists.txt b/cmake.deps/cmake/TreesitterParserCMakeLists.txt index 9bdf500aa7..42386185e7 100644 --- a/cmake.deps/cmake/TreesitterParserCMakeLists.txt +++ b/cmake.deps/cmake/TreesitterParserCMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.10) project(parser C) -set(CMAKE_C_STANDARD 99) file(GLOB source_files src/*.c) add_library(parser diff --git a/cmake.deps/cmake/libtermkeyCMakeLists.txt b/cmake.deps/cmake/libtermkeyCMakeLists.txt index 95d4a54549..cefe14e515 100644 --- a/cmake.deps/cmake/libtermkeyCMakeLists.txt +++ b/cmake.deps/cmake/libtermkeyCMakeLists.txt @@ -3,9 +3,6 @@ project(libtermkey C) add_definitions(-D _CRT_SECURE_NO_WARNINGS) add_definitions(-DHAVE_UNIBILIUM) -if(NOT MSVC) - add_compile_options(-std=c99) -endif() include_directories(${PROJECT_BINARY_DIR}/t) include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS}) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 197edf2e81..ea57db22e0 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1549,11 +1549,11 @@ nvim_command({command}) *nvim_command()* On execution error: fails with VimL error, updates v:errmsg. - Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple - lines of Vim script or an Ex command directly, use |nvim_exec()|. To - construct an Ex command using a structured format and then execute it, use - |nvim_cmd()|. To modify an Ex command before evaluating it, use - |nvim_parse_cmd()| in conjunction with |nvim_cmd()|. + Prefer using |nvim_cmd()| or |nvim_exec2()| over this. To evaluate + multiple lines of Vim script or an Ex command directly, use + |nvim_exec2()|. To construct an Ex command using a structured format and + then execute it, use |nvim_cmd()|. To modify an Ex command before + evaluating it, use |nvim_parse_cmd()| in conjunction with |nvim_cmd()|. Parameters: ~ • {command} Ex command string @@ -1570,7 +1570,7 @@ nvim_eval({expr}) *nvim_eval()* Return: ~ Evaluation result or expanded object -nvim_exec({src}, {output}) *nvim_exec()* +nvim_exec2({src}, {*opts}) *nvim_exec2()* Executes Vimscript (multiline block of Ex commands), like anonymous |:source|. @@ -1580,12 +1580,14 @@ nvim_exec({src}, {output}) *nvim_exec()* On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ - • {src} Vimscript code - • {output} Capture and return all (non-error, non-shell |:!|) output + • {src} Vimscript code + • {opts} Optional parameters. + • output: (boolean, default false) Whether to capture and + return all (non-error, non-shell |:!|) output. Return: ~ - Output (non-error, non-shell |:!|) if `output` is true, else empty - string. + Dictionary containing information about execution, with these keys: + • output: (string|nil) Output if `opts.output` is true. See also: ~ • |execute()| @@ -1738,7 +1740,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* empty string. See also: ~ - • |nvim_exec()| + • |nvim_exec2()| • |nvim_command()| *nvim_create_user_command()* diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 50f5b95ab5..69cec8da53 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -15,10 +15,11 @@ Deprecated features API - *nvim_buf_clear_highlight()* Use |nvim_buf_clear_namespace()| instead. - *nvim_buf_set_virtual_text()* Use |nvim_buf_set_extmark()| instead. -- *nvim_command_output()* Use |nvim_exec()| instead. +- *nvim_command_output()* Use |nvim_exec2()| instead. - *nvim_execute_lua()* Use |nvim_exec_lua()| instead. - *nvim_get_hl_by_name()* Use |nvim_get_hl()| instead. - *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead. +- *nvim_exec()* Use |nvim_exec2()| instead. COMMANDS - *:rv* *:rviminfo* Deprecated alias to |:rshada| command. @@ -122,7 +123,7 @@ LSP FUNCTIONS or |vim.lsp.buf.format()| instead. TREESITTER FUNCTIONS -- *vim.treesitter.language.require_language()* Use |vim.treesitter.add()| +- *vim.treesitter.language.require_language()* Use |vim.treesitter.language.add()| instead. - *vim.treesitter.get_node_at_pos()* Use |vim.treesitter.get_node()| instead. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 2baae3a123..0bea2819c9 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1355,9 +1355,9 @@ cmd({command}) *vim.cmd()* Parameters: ~ • {command} string|table Command(s) to execute. If a string, executes multiple lines of Vim script at once. In this case, it is - an alias to |nvim_exec()|, where `output` is set to false. - Thus it works identical to |:source|. If a table, executes - a single command. In this case, it is an alias to + an alias to |nvim_exec2()|, where `opts.output` is set to + false. Thus it works identical to |:source|. If a table, + executes a single command. In this case, it is an alias to |nvim_cmd()| where `opts` is empty. See also: ~ @@ -1510,7 +1510,8 @@ print({...}) *vim.print()* region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()* Get a table of lines with start, end columns for a region marked by two - points + points. Input and output positions are (0,0)-indexed and indicate byte + positions. Parameters: ~ • {bufnr} (integer) number of buffer @@ -1518,11 +1519,12 @@ region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()* region • {pos2} integer[] (line, column) tuple marking end of region • {regtype} (string) type of selection, see |setreg()| - • {inclusive} (boolean) indicating whether the selection is - end-inclusive + • {inclusive} (boolean) indicating whether column of pos2 is inclusive Return: ~ - (table) region Table of the form `{linenr = {startcol,endcol}}` + (table) region Table of the form `{linenr = {startcol,endcol}}`. + `endcol` is exclusive, and whole lines are marked with + `{startcol,endcol} = {0,-1}`. schedule_wrap({cb}) *vim.schedule_wrap()* Defers callback `cb` until the Nvim API is safe to call. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index a03bd705a9..20af29430a 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -60,6 +60,8 @@ The following changes may require adaptations in user config or plugins. • Renamed vim.pretty_print to vim.print. |deprecated| +• |nvim_exec()| is now deprecated in favor of |nvim_exec2()|. + ============================================================================== NEW FEATURES *news-features* @@ -180,9 +182,9 @@ The following new APIs or features were added. more complicated dynamic language injections. • |vim.treesitter.get_node_text()| now accepts a `metadata` option for - writing custom directives using |vim.treesitter.add_directive()|. + writing custom directives using |vim.treesitter.query.add_directive()|. -• |vim.treesitter.add()| replaces `vim.treesitter.language.require_language`. +• |vim.treesitter.language.add()| replaces `vim.treesitter.language.require_language`. • `require'bit'` is now always available |lua-bit| @@ -217,7 +219,7 @@ The following new APIs or features were added. • |vim.filetype.get_option()| to get the default option value for a specific filetype. This is a wrapper around |nvim_get_option_value()| with caching. - + • Added |nvim_get_hl()| for getting highlight group definitions in a format compatible with |nvim_set_hl()|. ============================================================================== @@ -275,11 +277,27 @@ DEPRECATIONS *news-deprecations* The following functions are now deprecated and will be removed in the next release. -• |vim.treesitter.add()| replaces `vim.treesitter.language.require_language()` +• |vim.treesitter.language.add()| replaces `vim.treesitter.language.require_language()` • |vim.treesitter.get_node_at_pos()| and |vim.treesitter.get_node_at_cursor()| are both deprecated in favor of |vim.treesitter.get_node()|. • `vim.api.nvim_get_hl_by_name()`, `vim.api.nvim_get_hl_by_id()` were deprecated, use |nvim_get_hl()| instead. +• The following top level Treesitter functions have been moved: + `vim.treesitter.inspect_language()` -> `vim.treesitter.language.inspect()` + `vim.treesitter.get_query_files()` -> `vim.treesitter.query.get_files()` + `vim.treesitter.set_query()` -> `vim.treesitter.query.set()` + `vim.treesitter.query.set_query()` -> `vim.treesitter.query.set()` + `vim.treesitter.get_query()` -> `vim.treesitter.query.get()` + `vim.treesitter.query.get_query()` -> `vim.treesitter.query.get()` + `vim.treesitter.parse_query()` -> `vim.treesitter.query.parse()` + `vim.treesitter.query.parse_query()` -> `vim.treesitter.query.parse()` + `vim.treesitter.add_predicate()` -> `vim.treesitter.query.add_predicate()` + `vim.treesitter.add_directive()` -> `vim.treesitter.query.add_directive()` + `vim.treesitter.list_predicates()` -> `vim.treesitter.query.list_predicates()` + `vim.treesitter.list_directives()` -> `vim.treesitter.query.list_directives()` + `vim.treesitter.query.get_range()` -> `vim.treesitter.get_range()` + `vim.treesitter.query.get_node_text()` -> `vim.treesitter.get_node_text()` + vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 46f414d905..d7e005ae51 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -26,7 +26,7 @@ If multiple parsers for the same language are found, the first one is used. (This typically implies the priority "user config > plugins > bundled". A parser can also be loaded manually using a full path: >lua - vim.treesitter.require_language("python", "/path/to/python.so") + vim.treesitter.language.add('python', { path = "/path/to/python.so" }) < ============================================================================== TREESITTER TREES *treesitter-tree* @@ -236,8 +236,8 @@ The following predicates are built in: Each predicate has a `not-` prefixed predicate that is just the negation of the predicate. -Further predicates can be added via |vim.treesitter.add_predicate()|. -Use |vim.treesitter.list_predicates()| to list all available predicates. +Further predicates can be added via |vim.treesitter.query.add_predicate()|. +Use |vim.treesitter.query.list_predicates()| to list all available predicates. TREESITTER QUERY DIRECTIVES *treesitter-directives* @@ -279,8 +279,8 @@ The following directives are built in: ((identifier) @constant (#offset! @constant 0 1 0 -1)) < -Further directives can be added via |vim.treesitter.add_directive()|. -Use |vim.treesitter.list_directives()| to list all available directives. +Further directives can be added via |vim.treesitter.query.add_directive()|. +Use |vim.treesitter.query.list_directives()| to list all available directives. TREESITTER QUERY MODELINES *treesitter-query-modeline* @@ -575,6 +575,22 @@ get_node_range({node_or_range}) *vim.treesitter.get_node_range()* (integer) end_row (integer) end_col + *vim.treesitter.get_node_text()* +get_node_text({node}, {source}, {opts}) + Gets the text corresponding to a given node + + Parameters: ~ + • {node} |TSNode| + • {source} (integer|string) Buffer or string from which the {node} is + extracted + • {opts} (table|nil) Optional parameters. + • metadata (table) Metadata of a specific capture. This + would be set to `metadata[capture_id]` when using + |vim.treesitter.query.add_directive()|. + + Return: ~ + (string) + get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()* Returns the parser for a specific buffer and filetype and attaches it to the buffer @@ -591,6 +607,19 @@ get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()* Return: ~ |LanguageTree| object to use for parsing +get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()* + Get the range of a |TSNode|. Can also supply {source} and {metadata} to + get the range with directives applied. + + Parameters: ~ + • {node} |TSNode| + • {source} integer|string|nil Buffer or string from which the {node} + is extracted + • {metadata} TSMetadata|nil + + Return: ~ + (table) + *vim.treesitter.get_string_parser()* get_string_parser({str}, {lang}, {opts}) Returns a string parser @@ -698,7 +727,7 @@ stop({bufnr}) *vim.treesitter.stop()* ============================================================================== Lua module: vim.treesitter.language *lua-treesitter-language* -add({lang}, {opts}) *vim.treesitter.add()* +add({lang}, {opts}) *vim.treesitter.language.add()* Asserts that a parser for the language {lang} is installed. Parsers are searched in the `parser` runtime directory, or the provided @@ -716,14 +745,14 @@ add({lang}, {opts}) *vim.treesitter.add()* • symbol_name (string|nil) Internal symbol name for the language to load -get_lang({filetype}) *vim.treesitter.get_lang()* +get_lang({filetype}) *vim.treesitter.language.get_lang()* Parameters: ~ • {filetype} (string) Return: ~ (string|nil) -inspect_language({lang}) *vim.treesitter.inspect_language()* +inspect({lang}) *vim.treesitter.language.inspect()* Inspects the provided language. Inspecting provides some useful information on the language like node @@ -735,7 +764,7 @@ inspect_language({lang}) *vim.treesitter.inspect_language()* Return: ~ (table) -register({lang}, {filetype}) *vim.treesitter.register()* +register({lang}, {filetype}) *vim.treesitter.language.register()* Register a lang to be used for a filetype (or list of filetypes). Parameters: ~ @@ -746,7 +775,7 @@ register({lang}, {filetype}) *vim.treesitter.register()* ============================================================================== Lua module: vim.treesitter.query *lua-treesitter-query* - *vim.treesitter.add_directive()* + *vim.treesitter.query.add_directive()* add_directive({name}, {handler}, {force}) Adds a new directive to be used in queries @@ -768,7 +797,7 @@ add_directive({name}, {handler}, {force}) the predicate `{ "#set!", "conceal", "-" }` • {force} (boolean|nil) - *vim.treesitter.add_predicate()* + *vim.treesitter.query.add_predicate()* add_predicate({name}, {handler}, {force}) Adds a new predicate to be used in queries @@ -776,27 +805,11 @@ add_predicate({name}, {handler}, {force}) • {name} (string) Name of the predicate, without leading # • {handler} function(match:table<string,|TSNode|>, pattern:string, bufnr:integer, predicate:string[]) - • see |vim.treesitter.add_directive()| for argument + • see |vim.treesitter.query.add_directive()| for argument meanings • {force} (boolean|nil) - *vim.treesitter.get_node_text()* -get_node_text({node}, {source}, {opts}) - Gets the text corresponding to a given node - - Parameters: ~ - • {node} |TSNode| - • {source} (integer|string) Buffer or string from which the {node} is - extracted - • {opts} (table|nil) Optional parameters. - • metadata (table) Metadata of a specific capture. This - would be set to `metadata[capture_id]` when using - |vim.treesitter.add_directive()|. - - Return: ~ - (string) - -get_query({lang}, {query_name}) *vim.treesitter.get_query()* +get({lang}, {query_name}) *vim.treesitter.query.get()* Returns the runtime query {query_name} for {lang}. Parameters: ~ @@ -806,8 +819,8 @@ get_query({lang}, {query_name}) *vim.treesitter.get_query()* Return: ~ Query|nil Parsed query - *vim.treesitter.get_query_files()* -get_query_files({lang}, {query_name}, {is_included}) + *vim.treesitter.query.get_files()* +get_files({lang}, {query_name}, {is_included}) Gets the list of files used to make up a query Parameters: ~ @@ -820,32 +833,19 @@ get_query_files({lang}, {query_name}, {is_included}) string[] query_files List of files to load for given query and language -get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()* - Get the range of a |TSNode|. Can also supply {source} and {metadata} to - get the range with directives applied. - - Parameters: ~ - • {node} |TSNode| - • {source} integer|string|nil Buffer or string from which the {node} - is extracted - • {metadata} TSMetadata|nil - - Return: ~ - (table) - -list_directives() *vim.treesitter.list_directives()* +list_directives() *vim.treesitter.query.list_directives()* Lists the currently available directives to use in queries. Return: ~ string[] List of supported directives. -list_predicates() *vim.treesitter.list_predicates()* +list_predicates() *vim.treesitter.query.list_predicates()* Lists the currently available predicates to use in queries. Return: ~ string[] List of supported predicates. -parse_query({lang}, {query}) *vim.treesitter.parse_query()* +parse({lang}, {query}) *vim.treesitter.query.parse()* Parse {query} as a string. (If the query is in a file, the caller should read the contents into a string before calling). @@ -935,7 +935,7 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) (fun(): integer, table<integer,TSNode>, table): pattern id, match, metadata -set_query({lang}, {query_name}, {text}) *vim.treesitter.set_query()* +set({lang}, {query_name}, {text}) *vim.treesitter.query.set()* Sets the runtime query named {query_name} for {lang} This allows users to override any runtime files and/or configuration set diff --git a/runtime/lua/_vim9script.lua b/runtime/lua/_vim9script.lua index 363d061451..76e427b748 100644 --- a/runtime/lua/_vim9script.lua +++ b/runtime/lua/_vim9script.lua @@ -162,7 +162,7 @@ local vim9 = (function() end end - vim.api.nvim_exec(table.concat(file, '\n'), false) + vim.api.nvim_exec2(table.concat(file, '\n'), { output = false }) end, }) end diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index f2875e5646..db7a6c1d17 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -322,8 +322,8 @@ end --- ---@param command string|table Command(s) to execute. --- If a string, executes multiple lines of Vim script at once. In this ---- case, it is an alias to |nvim_exec()|, where `output` is set to ---- false. Thus it works identical to |:source|. +--- case, it is an alias to |nvim_exec2()|, where `opts.output` is set +--- to false. Thus it works identical to |:source|. --- If a table, executes a single command. In this case, it is an alias --- to |nvim_cmd()| where `opts` is empty. ---@see |ex-cmd-index| @@ -338,7 +338,7 @@ vim.cmd = setmetatable({}, { if type(command) == 'table' then return vim.api.nvim_cmd(command, {}) else - return vim.api.nvim_exec(command, false) + return vim.api.nvim_exec2(command, { output = false }).output end end, __index = function(t, command) @@ -397,14 +397,17 @@ do vim.t = make_dict_accessor('t') end ---- Get a table of lines with start, end columns for a region marked by two points +--- Get a table of lines with start, end columns for a region marked by two points. +--- Input and output positions are (0,0)-indexed and indicate byte positions. --- ---@param bufnr integer number of buffer ---@param pos1 integer[] (line, column) tuple marking beginning of region ---@param pos2 integer[] (line, column) tuple marking end of region ---@param regtype string type of selection, see |setreg()| ----@param inclusive boolean indicating whether the selection is end-inclusive ----@return table region Table of the form `{linenr = {startcol,endcol}}` +---@param inclusive boolean indicating whether column of pos2 is inclusive +---@return table region Table of the form `{linenr = {startcol,endcol}}`. +--- `endcol` is exclusive, and whole lines are marked with +--- `{startcol,endcol} = {0,-1}`. function vim.region(bufnr, pos1, pos2, regtype, inclusive) if not vim.api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fa4208e2a4..740304df15 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1103,8 +1103,8 @@ local extension = { wrl = 'vrml', vroom = 'vroom', vue = 'vue', - wat = 'wast', wast = 'wast', + wat = 'wat', wdl = 'wdl', wm = 'webmacro', wbt = 'winbatch', diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index ee5b63d260..d01f8e6159 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -364,7 +364,9 @@ function M.hover(_, result, ctx, config) local markdown_lines = util.convert_input_to_markdown_lines(result.contents) markdown_lines = util.trim_empty_lines(markdown_lines) if vim.tbl_isempty(markdown_lines) then - vim.notify('No information available') + if config.silent ~= true then + vim.notify('No information available') + end return end return util.open_floating_preview(markdown_lines, 'markdown', config) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 48faddfce1..ebde7af16c 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1378,6 +1378,20 @@ function M.stylize_markdown(bufnr, contents, opts) end end + -- Handle some common html escape sequences + stripped = vim.tbl_map(function(line) + local escapes = { + ['>'] = '>', + ['<'] = '<', + ['"'] = '"', + ['''] = "'", + [' '] = ' ', + [' '] = ' ', + ['&'] = '&', + } + return (string.gsub(line, '&[^ ;]+;', escapes)) + end, stripped) + -- Compute size of float needed to show (wrapped) lines opts.wrap_at = opts.wrap_at or (vim.wo['wrap'] and api.nvim_win_get_width(0)) local width = M._make_floating_popup_size(stripped, opts) diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 43b8c11b80..4c3b17daa4 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -1,6 +1,4 @@ local a = vim.api -local query = require('vim.treesitter.query') -local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') local Range = require('vim.treesitter._range') @@ -9,12 +7,9 @@ local parsers = setmetatable({}, { __mode = 'v' }) ---@class TreesitterModule ---@field highlighter TSHighlighter -local M = vim.tbl_extend('error', query, language) - -M.language_version = vim._ts_get_language_version() -M.minimum_language_version = vim._ts_get_minimum_language_version() - -setmetatable(M, { +---@field query TSQueryModule +---@field language TSLanguageModule +local M = setmetatable({}, { __index = function(t, k) ---@diagnostic disable:no-unknown if k == 'highlighter' then @@ -27,10 +22,25 @@ setmetatable(M, { t[k] = require('vim.treesitter.query') return t[k] end + + local query = require('vim.treesitter.query') + if query[k] then + vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.query.' .. k .. '()', '0.10') + t[k] = query[k] + return t[k] + end + + local language = require('vim.treesitter.language') + if language[k] then + vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.language.' .. k .. '()', '0.10') + t[k] = language[k] + return t[k] + end end, }) ----@diagnostic disable:invisible +M.language_version = vim._ts_get_language_version() +M.minimum_language_version = vim._ts_get_minimum_language_version() --- Creates a new parser --- @@ -49,7 +59,7 @@ function M._create_parser(bufnr, lang, opts) vim.fn.bufload(bufnr) local ft = vim.bo[bufnr].filetype - language.add(lang, { filetype = ft ~= '' and ft or nil }) + M.language.add(lang, { filetype = ft ~= '' and ft or nil }) local self = LanguageTree.new(bufnr, lang, opts) @@ -103,7 +113,7 @@ function M.get_parser(bufnr, lang, opts) if lang == nil then local ft = vim.bo[bufnr].filetype if ft ~= '' then - lang = language.get_lang(ft) or ft + lang = M.language.get_lang(ft) or ft -- TODO(lewis6991): we should error here and not default to ft -- if not lang then -- error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr)) @@ -132,7 +142,7 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end ----@private +---@package ---@param bufnr (integer|nil) Buffer number ---@return boolean function M._has_parser(bufnr) @@ -154,7 +164,7 @@ function M.get_string_parser(str, lang, opts) str = { str, 'string' }, lang = { lang, 'string' }, }) - language.add(lang) + M.language.add(lang) return LanguageTree.new(str, lang, opts) end @@ -198,6 +208,61 @@ function M.get_node_range(node_or_range) end end +---Get the range of a |TSNode|. Can also supply {source} and {metadata} +---to get the range with directives applied. +---@param node TSNode +---@param source integer|string|nil Buffer or string from which the {node} is extracted +---@param metadata TSMetadata|nil +---@return Range6 +function M.get_range(node, source, metadata) + if metadata and metadata.range then + assert(source) + return Range.add_bytes(source, metadata.range) + end + return { node:range(true) } +end + +---@private +---@param buf integer +---@param range Range +---@returns string +local function buf_range_get_text(buf, range) + local start_row, start_col, end_row, end_col = Range.unpack4(range) + if end_col == 0 then + if start_row == end_row then + start_col = -1 + start_row = start_row - 1 + end + end_col = -1 + end_row = end_row - 1 + end + local lines = a.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {}) + return table.concat(lines, '\n') +end + +--- Gets the text corresponding to a given node +--- +---@param node TSNode +---@param source (integer|string) Buffer or string from which the {node} is extracted +---@param opts (table|nil) Optional parameters. +--- - metadata (table) Metadata of a specific capture. This would be +--- set to `metadata[capture_id]` when using |vim.treesitter.query.add_directive()|. +---@return string +function M.get_node_text(node, source, opts) + opts = opts or {} + local metadata = opts.metadata or {} + + if metadata.text then + return metadata.text + elseif type(source) == 'number' then + local range = vim.treesitter.get_range(node, source, metadata) + return buf_range_get_text(source, range) + end + + ---@cast source string + return source:sub(select(3, node:start()) + 1, select(3, node:end_())) +end + --- Determines whether (line, col) position is in node range --- ---@param node TSNode defining the range @@ -276,7 +341,7 @@ function M.get_captures_at_pos(bufnr, row, col) end end end - end, true) + end) return matches end diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index 90f4394fcc..6547ab936e 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -1,9 +1,8 @@ local Range = require('vim.treesitter._range') -local Query = require('vim.treesitter.query') local api = vim.api ----@class FoldInfo +---@class TS.FoldInfo ---@field levels table<integer,string> ---@field levels0 table<integer,integer> ---@field private start_counts table<integer,integer> @@ -11,6 +10,7 @@ local api = vim.api local FoldInfo = {} FoldInfo.__index = FoldInfo +---@private function FoldInfo.new() return setmetatable({ start_counts = {}, @@ -20,6 +20,7 @@ function FoldInfo.new() }, FoldInfo) end +---@package ---@param srow integer ---@param erow integer function FoldInfo:invalidate_range(srow, erow) @@ -31,6 +32,7 @@ function FoldInfo:invalidate_range(srow, erow) end end +---@package ---@param srow integer ---@param erow integer function FoldInfo:remove_range(srow, erow) @@ -42,6 +44,7 @@ function FoldInfo:remove_range(srow, erow) end end +---@package ---@param srow integer ---@param erow integer function FoldInfo:add_range(srow, erow) @@ -53,22 +56,26 @@ function FoldInfo:add_range(srow, erow) end end +---@package ---@param lnum integer function FoldInfo:add_start(lnum) self.start_counts[lnum] = (self.start_counts[lnum] or 0) + 1 end +---@package ---@param lnum integer function FoldInfo:add_stop(lnum) self.stop_counts[lnum] = (self.stop_counts[lnum] or 0) + 1 end +---@packag ---@param lnum integer ---@return integer function FoldInfo:get_start(lnum) return self.start_counts[lnum] or 0 end +---@package ---@param lnum integer ---@return integer function FoldInfo:get_stop(lnum) @@ -84,7 +91,7 @@ local function trim_level(level) end ---@param bufnr integer ----@param info FoldInfo +---@param info TS.FoldInfo ---@param srow integer? ---@param erow integer? local function get_folds_levels(bufnr, info, srow, erow) @@ -97,7 +104,7 @@ local function get_folds_levels(bufnr, info, srow, erow) local prev_stop = -1 vim.treesitter.get_parser(bufnr):for_each_tree(function(tree, ltree) - local query = vim.treesitter.query.get_query(ltree:lang(), 'folds') + local query = vim.treesitter.query.get(ltree:lang(), 'folds') if not query then return end @@ -107,7 +114,7 @@ local function get_folds_levels(bufnr, info, srow, erow) for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow or 0, q_erow) do if query.captures[id] == 'fold' then - local range = Query.get_range(node, bufnr, metadata[id]) + local range = vim.treesitter.get_range(node, bufnr, metadata[id]) local start, _, stop, stop_col = Range.unpack4(range) if stop_col == 0 then @@ -161,7 +168,7 @@ end local M = {} ----@type table<integer,FoldInfo> +---@type table<integer,TS.FoldInfo> local foldinfos = {} local function recompute_folds() @@ -178,7 +185,7 @@ local function recompute_folds() end ---@param bufnr integer ----@param foldinfo FoldInfo +---@param foldinfo TS.FoldInfo ---@param tree_changes Range4[] local function on_changedtree(bufnr, foldinfo, tree_changes) -- For some reason, queries seem to use the old buffer state in on_bytes. @@ -193,7 +200,7 @@ local function on_changedtree(bufnr, foldinfo, tree_changes) end ---@param bufnr integer ----@param foldinfo FoldInfo +---@param foldinfo TS.FoldInfo ---@param start_row integer ---@param old_row integer ---@param new_row integer @@ -212,13 +219,13 @@ local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row) end end +---@package ---@param lnum integer|nil ---@return string function M.foldexpr(lnum) lnum = lnum or vim.v.lnum local bufnr = api.nvim_get_current_buf() - ---@diagnostic disable-next-line:invisible if not vim.treesitter._has_parser(bufnr) or not lnum then return '0' end diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 72823ccf26..4d0f43d030 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -3,7 +3,8 @@ ---@class TSNode ---@field id fun(self: TSNode): integer ---@field tree fun(self: TSNode): TSTree ----@field range fun(self: TSNode, include_bytes: boolean?): integer, integer, integer, integer, integer, integer +---@field range fun(self: TSNode, include_bytes: false?): integer, integer, integer, integer +---@field range fun(self: TSNode, include_bytes: true): integer, integer, integer, integer, integer, integer ---@field start fun(self: TSNode): integer, integer, integer ---@field end_ fun(self: TSNode): integer, integer, integer ---@field type fun(self: TSNode): string diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index e3deaf6ba6..729cd34090 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -1,5 +1,5 @@ local a = vim.api -local query = require('vim.treesitter.query') +local query = vim.treesitter.query ---@alias TSHlIter fun(): integer, TSNode, TSMetadata @@ -45,20 +45,20 @@ function TSHighlighterQuery.new(lang, query_string) }) if query_string then - self._query = query.parse_query(lang, query_string) + self._query = query.parse(lang, query_string) else - self._query = query.get_query(lang, 'highlights') + self._query = query.get(lang, 'highlights') end return self end ----@private +---@package function TSHighlighterQuery:query() return self._query end ----@private +---@package --- --- Creates a highlighter for `tree`. --- @@ -76,16 +76,14 @@ function TSHighlighter.new(tree, opts) opts = opts or {} ---@type { queries: table<string,string> } self.tree = tree tree:register_cbs({ - ---@diagnostic disable:invisible on_changedtree = function(...) self:on_changedtree(...) end, on_bytes = function(...) self:on_bytes(...) end, - on_detach = function(...) - ---@diagnostic disable-next-line:redundant-parameter - self:on_detach(...) + on_detach = function() + self:on_detach() end, }) @@ -147,7 +145,7 @@ function TSHighlighter:destroy() end end ----@private +---@package ---@param tstree TSTree ---@return TSHighlightState function TSHighlighter:get_highlight_state(tstree) @@ -166,19 +164,19 @@ function TSHighlighter:reset_highlight_state() self._highlight_states = {} end ----@private +---@package ---@param start_row integer ---@param new_end integer function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) a.nvim__buf_redraw_range(self.bufnr, start_row, start_row + new_end + 1) end ----@private +---@package function TSHighlighter:on_detach() self:destroy() end ----@private +---@package ---@param changes integer[][]? function TSHighlighter:on_changedtree(changes) for _, ch in ipairs(changes or {}) do @@ -188,7 +186,7 @@ end --- Gets the query used for @param lang -- ----@private +---@package ---@param lang string Language used by the highlighter. ---@return TSHighlighterQuery function TSHighlighter:get_query(lang) @@ -205,7 +203,6 @@ end ---@param line integer ---@param is_spell_nav boolean local function on_line_impl(self, buf, line, is_spell_nav) - ---@diagnostic disable:invisible self.tree:for_each_tree(function(tstree, tree) if not tstree then return @@ -268,7 +265,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) state.next_row = start_row end end - end, true) + end) end ---@private diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 47375fd5e6..974d66ec05 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -1,5 +1,6 @@ local a = vim.api +---@class TSLanguageModule local M = {} ---@type table<string,string> @@ -111,9 +112,19 @@ end --- ---@param lang string Language ---@return table -function M.inspect_language(lang) +function M.inspect(lang) M.add(lang) return vim._ts_inspect_language(lang) end +---@deprecated +function M.inspect_language(...) + vim.deprecate( + 'vim.treesitter.language.inspect_language()', + 'vim.treesitter.language.inspect()', + '0.10' + ) + return M.inspect(...) +end + return M diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index bdfe281a5b..82e507551d 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -70,7 +70,7 @@ local LanguageTree = {} LanguageTree.__index = LanguageTree ---- @private +--- @package --- --- |LanguageTree| contains a tree of parsers: the root treesitter parser for {lang} and any --- "injected" language parsers, which themselves may inject other languages, recursively. @@ -99,8 +99,8 @@ function LanguageTree.new(source, lang, opts) _regions = {}, _trees = {}, _opts = opts, - _injection_query = injections[lang] and query.parse_query(lang, injections[lang]) - or query.get_query(lang, 'injections'), + _injection_query = injections[lang] and query.parse(lang, injections[lang]) + or query.get(lang, 'injections'), _valid = false, _parser = vim._create_ts_parser(lang), _callbacks = { @@ -482,7 +482,7 @@ end ---@param metadata TSMetadata ---@return Range6[] local function get_node_ranges(node, source, metadata, include_children) - local range = query.get_range(node, source, metadata) + local range = vim.treesitter.get_range(node, source, metadata) if include_children then return { range } @@ -562,7 +562,7 @@ function LanguageTree:_get_injection(match, metadata) -- Lang should override any other language tag if name == 'injection.language' then - lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) + lang = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'injection.content' then ranges = get_node_ranges(node, self._source, metadata[id], include_children) end @@ -609,11 +609,11 @@ function LanguageTree:_get_injection_deprecated(match, metadata) -- Lang should override any other language tag if name == 'language' and not lang then - lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) + lang = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'combined' then combined = true elseif name == 'content' and #ranges == 0 then - ranges[#ranges + 1] = query.get_range(node, self._source, metadata[id]) + ranges[#ranges + 1] = vim.treesitter.get_range(node, self._source, metadata[id]) -- Ignore any tags that start with "_" -- Allows for other tags to be used in matches elseif string.sub(name, 1, 1) ~= '_' then @@ -622,7 +622,7 @@ function LanguageTree:_get_injection_deprecated(match, metadata) end if #ranges == 0 then - ranges[#ranges + 1] = query.get_range(node, self._source, metadata[id]) + ranges[#ranges + 1] = vim.treesitter.get_range(node, self._source, metadata[id]) end end end @@ -700,7 +700,7 @@ function LanguageTree:_do_callback(cb_name, ...) end end ----@private +---@package function LanguageTree:_edit( start_byte, end_byte_old, @@ -776,7 +776,7 @@ function LanguageTree:_edit( end) end ----@private +---@package ---@param bufnr integer ---@param changed_tick integer ---@param start_row integer @@ -822,7 +822,6 @@ function LanguageTree:_on_bytes( -- Edit trees together BEFORE emitting a bytes callback. ---@private self:for_each_child(function(child) - ---@diagnostic disable-next-line:invisible child:_edit( start_byte, start_byte + old_byte, @@ -852,12 +851,12 @@ function LanguageTree:_on_bytes( ) end ----@private +---@package function LanguageTree:_on_reload() self:invalidate(true) end ----@private +---@package function LanguageTree:_on_detach(...) self:invalidate(true) self:_do_callback('detach', ...) diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua index 7f181c23fd..35f06f5caf 100644 --- a/runtime/lua/vim/treesitter/playground.lua +++ b/runtime/lua/vim/treesitter/playground.lua @@ -5,11 +5,11 @@ local api = vim.api ---@field opts table Options table with the following keys: --- - anon (boolean): If true, display anonymous nodes --- - lang (boolean): If true, display the language alongside each node ----@field nodes Node[] ----@field named Node[] +---@field nodes TSP.Node[] +---@field named TSP.Node[] local TSPlayground = {} ---- ----@class Node + +---@class TSP.Node ---@field id integer Node id ---@field text string Node text ---@field named boolean True if this is a named (non-anonymous) node @@ -36,9 +36,9 @@ local TSPlayground = {} ---@param node TSNode Starting node to begin traversal |tsnode| ---@param depth integer Current recursion depth ---@param lang string Language of the tree currently being traversed ----@param injections table<integer,Node> Mapping of node ids to root nodes of injected language trees (see +---@param injections table<integer,TSP.Node> Mapping of node ids to root nodes of injected language trees (see --- explanation above) ----@param tree Node[] Output table containing a list of tables each representing a node in the tree +---@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree ---@private local function traverse(node, depth, lang, injections, tree) local injection = injections[node:id()] @@ -87,7 +87,7 @@ end ---@return TSPlayground|nil ---@return string|nil Error message, if any --- ----@private +---@package function TSPlayground:new(bufnr, lang) local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang) if not ok then @@ -114,7 +114,7 @@ function TSPlayground:new(bufnr, lang) local nodes = traverse(root, 0, parser:lang(), injections, {}) - local named = {} ---@type Node[] + local named = {} ---@type TSP.Node[] for _, v in ipairs(nodes) do if v.named then named[#named + 1] = v @@ -154,7 +154,7 @@ end --- Write the contents of this Playground into {bufnr}. --- ---@param bufnr integer Buffer number to write into. ----@private +---@package function TSPlayground:draw(bufnr) vim.bo[bufnr].modifiable = true local lines = {} ---@type string[] @@ -195,8 +195,8 @@ end --- The node number is dependent on whether or not anonymous nodes are displayed. --- ---@param i integer Node number to get ----@return Node ----@private +---@return TSP.Node +---@package function TSPlayground:get(i) local t = self.opts.anon and self.nodes or self.named return t[i] @@ -204,10 +204,10 @@ end --- Iterate over all of the nodes in this Playground object. --- ----@return (fun(): integer, Node) Iterator over all nodes in this Playground +---@return (fun(): integer, TSP.Node) Iterator over all nodes in this Playground ---@return table ---@return integer ----@private +---@package function TSPlayground:iter() return ipairs(self.opts.anon and self.nodes or self.named) end diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index f4e038b2d8..25623c1498 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -1,8 +1,6 @@ local a = vim.api local language = require('vim.treesitter.language') -local Range = require('vim.treesitter._range') - ---@class Query ---@field captures string[] List of captures used in query ---@field info TSQueryInfo Contains used queries, predicates, directives @@ -14,6 +12,7 @@ Query.__index = Query ---@field captures table ---@field patterns table<string,any[][]> +---@class TSQueryModule local M = {} ---@private @@ -57,22 +56,14 @@ local function add_included_lang(base_langs, lang, ilang) return false end ----@private ----@param buf integer ----@param range Range ----@returns string -local function buf_range_get_text(buf, range) - local start_row, start_col, end_row, end_col = Range.unpack4(range) - if end_col == 0 then - if start_row == end_row then - start_col = -1 - start_row = start_row - 1 - end - end_col = -1 - end_row = end_row - 1 - end - local lines = a.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {}) - return table.concat(lines, '\n') +---@deprecated +function M.get_query_files(...) + vim.deprecate( + 'vim.treesitter.query.get_query_files()', + 'vim.treesitter.query.get_files()', + '0.10' + ) + return M.get_files(...) end --- Gets the list of files used to make up a query @@ -81,7 +72,7 @@ end ---@param query_name string Name of the query to load (e.g., "highlights") ---@param is_included (boolean|nil) Internal parameter, most of the time left as `nil` ---@return string[] query_files List of files to load for given query and language -function M.get_query_files(lang, query_name, is_included) +function M.get_files(lang, query_name, is_included) local query_path = string.format('queries/%s/%s.scm', lang, query_name) local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true)) @@ -153,7 +144,7 @@ function M.get_query_files(lang, query_name, is_included) local query_files = {} for _, base_lang in ipairs(base_langs) do - local base_files = M.get_query_files(base_lang, query_name, true) + local base_files = M.get_files(base_lang, query_name, true) vim.list_extend(query_files, base_files) end vim.list_extend(query_files, { base_query }) @@ -175,7 +166,7 @@ local function read_query_files(filenames) return table.concat(contents, '') end --- The explicitly set queries from |vim.treesitter.query.set_query()| +-- The explicitly set queries from |vim.treesitter.query.set()| ---@type table<string,table<string,Query>> local explicit_queries = setmetatable({}, { __index = function(t, k) @@ -186,6 +177,12 @@ local explicit_queries = setmetatable({}, { end, }) +---@deprecated +function M.set_query(...) + vim.deprecate('vim.treesitter.query.set_query()', 'vim.treesitter.query.set()', '0.10') + M.set(...) +end + --- Sets the runtime query named {query_name} for {lang} --- --- This allows users to override any runtime files and/or configuration @@ -194,8 +191,14 @@ local explicit_queries = setmetatable({}, { ---@param lang string Language to use for the query ---@param query_name string Name of the query (e.g., "highlights") ---@param text string Query text (unparsed). -function M.set_query(lang, query_name, text) - explicit_queries[lang][query_name] = M.parse_query(lang, text) +function M.set(lang, query_name, text) + explicit_queries[lang][query_name] = M.parse(lang, text) +end + +---@deprecated +function M.get_query(...) + vim.deprecate('vim.treesitter.query.get_query()', 'vim.treesitter.query.get()', '0.10') + return M.get(...) end --- Returns the runtime query {query_name} for {lang}. @@ -204,16 +207,16 @@ end ---@param query_name string Name of the query (e.g. "highlights") --- ---@return Query|nil Parsed query -function M.get_query(lang, query_name) +function M.get(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_files = M.get_files(lang, query_name) local query_string = read_query_files(query_files) if #query_string > 0 then - return M.parse_query(lang, query_string) + return M.parse(lang, query_string) end end @@ -222,6 +225,12 @@ local query_cache = vim.defaulttable(function() return setmetatable({}, { __mode = 'v' }) end) +---@deprecated +function M.parse_query(...) + vim.deprecate('vim.treesitter.query.parse_query()', 'vim.treesitter.query.parse()', '0.10') + return M.parse(...) +end + --- Parse {query} as a string. (If the query is in a file, the caller --- should read the contents into a string before calling). --- @@ -239,7 +248,7 @@ end) ---@param query string Query in s-expr syntax --- ---@return Query Parsed query -function M.parse_query(lang, query) +function M.parse(lang, query) language.add(lang) local cached = query_cache[lang][query] if cached then @@ -254,41 +263,16 @@ function M.parse_query(lang, query) return self end ----Get the range of a |TSNode|. Can also supply {source} and {metadata} ----to get the range with directives applied. ----@param node TSNode ----@param source integer|string|nil Buffer or string from which the {node} is extracted ----@param metadata TSMetadata|nil ----@return Range6 -function M.get_range(node, source, metadata) - if metadata and metadata.range then - assert(source) - return Range.add_bytes(source, metadata.range) - end - return { node:range(true) } +---@deprecated +function M.get_range(...) + vim.deprecate('vim.treesitter.query.get_range()', 'vim.treesitter.get_range()', '0.10') + return vim.treesitter.get_range(...) end ---- Gets the text corresponding to a given node ---- ----@param node TSNode ----@param source (integer|string) Buffer or string from which the {node} is extracted ----@param opts (table|nil) Optional parameters. ---- - metadata (table) Metadata of a specific capture. This would be ---- set to `metadata[capture_id]` when using |vim.treesitter.add_directive()|. ----@return string -function M.get_node_text(node, source, opts) - opts = opts or {} - local metadata = opts.metadata or {} - - if metadata.text then - return metadata.text - elseif type(source) == 'number' then - local range = M.get_range(node, source, metadata) - return buf_range_get_text(source, range) - end - - ---@cast source string - return source:sub(select(3, node:start()) + 1, select(3, node:end_())) +---@deprecated +function M.get_node_text(...) + vim.deprecate('vim.treesitter.query.get_node_text()', 'vim.treesitter.get_node_text()', '0.10') + return vim.treesitter.get_node_text(...) end ---@alias TSMatch table<integer,TSNode> @@ -304,7 +288,7 @@ local predicate_handlers = { if not node then return true end - local node_text = M.get_node_text(node, source) + local node_text = vim.treesitter.get_node_text(node, source) local str ---@type string if type(predicate[3]) == 'string' then @@ -312,7 +296,7 @@ local predicate_handlers = { str = predicate[3] else -- (#eq? @aa @bb) - str = M.get_node_text(match[predicate[3]], source) + str = vim.treesitter.get_node_text(match[predicate[3]], source) end if node_text ~= str or str == nil then @@ -328,7 +312,7 @@ local predicate_handlers = { return true end local regex = predicate[3] - return string.find(M.get_node_text(node, source), regex) ~= nil + return string.find(vim.treesitter.get_node_text(node, source), regex) ~= nil end, ['match?'] = (function() @@ -357,7 +341,7 @@ local predicate_handlers = { end ---@diagnostic disable-next-line no-unknown local regex = compiled_vim_regexes[pred[3]] - return regex:match_str(M.get_node_text(node, source)) + return regex:match_str(vim.treesitter.get_node_text(node, source)) end end)(), @@ -366,7 +350,7 @@ local predicate_handlers = { if not node then return true end - local node_text = M.get_node_text(node, source) + local node_text = vim.treesitter.get_node_text(node, source) for i = 3, #predicate do if string.find(node_text, predicate[i], 1, true) then @@ -382,7 +366,7 @@ local predicate_handlers = { if not node then return true end - local node_text = M.get_node_text(node, source) + local node_text = vim.treesitter.get_node_text(node, source) -- Since 'predicate' will not be used by callers of this function, use it -- to store a string set built from the list of words to check against. @@ -468,7 +452,7 @@ local directive_handlers = { assert(type(id) == 'number') local node = match[id] - local text = M.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' + local text = vim.treesitter.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' if not metadata[id] then metadata[id] = {} @@ -486,7 +470,7 @@ local directive_handlers = { --- ---@param name string Name of the predicate, without leading # ---@param handler function(match:table<string,TSNode>, pattern:string, bufnr:integer, predicate:string[]) ---- - see |vim.treesitter.add_directive()| for argument meanings +--- - see |vim.treesitter.query.add_directive()| for argument meanings ---@param force boolean|nil function M.add_predicate(name, handler, force) if predicate_handlers[name] and not force then diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 72f9df325b..de95caf376 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -290,7 +290,7 @@ CONFIG = { if fstem == 'treesitter' else f'*{name}()*' if name[0].isupper() - else f'*vim.treesitter.{name}()*'), + else f'*vim.treesitter.{fstem}.{name}()*'), 'module_override': {}, 'append_only': [], } diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index de9f2926f2..014934aebe 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -336,6 +336,8 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) offset = 1 end + line = line:gsub('@package', '@private') + if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') or vim.startswith(line, '---@type') then diff --git a/src/nvim/README.md b/src/nvim/README.md index 69d5939c70..cbd5daba4e 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -198,6 +198,34 @@ possible to see exactly what terminfo values Nvim is using on any system. nvim -V3log +### TUI Debugging with gdb/lldb + +Launching the nvim TUI involves two processes, one for main editor state and one +for rendering the TUI. Both of these processes use the nvim binary, so somewhat +confusingly setting a breakpoint in either will generally succeed but may not be +hit depending on which process the breakpoints were set in. + +To debug the main process, you can debug the nvim binary with the `--headless` +flag which does not launch the TUI and will allow you to set breakpoints in code +not related to TUI rendering like so: + +``` +lldb -- ./build/bin/nvim --headless --listen ~/.cache/nvim/debug-server.pipe +``` + +You can then attach to the headless process to interact with the editor like so: + +``` +./build/bin/nvim --remote-ui --server ~/.cache/nvim/debug-server.pipe +``` + +Conversely for debugging TUI rendering, you can start a headless process and +debug the remote-ui process multiple times without losing editor state. + +For details on using nvim-dap and automatically debugging the child (main) +process, see +[here](https://zignar.net/2023/02/17/debugging-neovim-with-neovim-and-nvim-dap/) + ### TUI trace The ancient `script` command is still the "state of the art" for tracing diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 1455f28050..26ee9205b2 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -307,7 +307,7 @@ end: /// /// On execution error: fails with VimL error, updates v:errmsg. /// -/// @see |nvim_exec()| +/// @see |nvim_exec2()| /// @see |nvim_command()| /// /// @param cmd Command to execute. Must be a Dictionary that can contain the same values as diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index b1e2e6811e..6a12cfe2da 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -27,13 +27,26 @@ # include "api/deprecated.c.generated.h" #endif +/// @deprecated Use nvim_exec2() instead. +/// @see nvim_exec2 +String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err) + FUNC_API_SINCE(7) + FUNC_API_DEPRECATED_SINCE(11) +{ + Dict(exec_opts) opts = { 0 }; + opts.output = BOOLEAN_OBJ(output); + return exec_impl(channel_id, src, &opts, err); +} + /// @deprecated -/// @see nvim_exec +/// @see nvim_exec2 String nvim_command_output(uint64_t channel_id, String command, Error *err) FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(7) { - return nvim_exec(channel_id, command, true, err); + Dict(exec_opts) opts = { 0 }; + opts.output = BOOLEAN_OBJ(true); + return exec_impl(channel_id, command, &opts, err); } /// @deprecated Use nvim_exec_lua() instead. diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index b2b327d73e..ce29001787 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -232,4 +232,7 @@ return { { 'echo_opts', { "verbose"; }}; + { 'exec_opts', { + "output"; + }}; } diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 32dcbdec3f..2438a5cf1d 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -45,13 +45,33 @@ /// @see |nvim_cmd()| /// /// @param src Vimscript code -/// @param output Capture and return all (non-error, non-shell |:!|) output +/// @param opts Optional parameters. +/// - output: (boolean, default false) Whether to capture and return +/// all (non-error, non-shell |:!|) output. /// @param[out] err Error details (Vim error), if any -/// @return Output (non-error, non-shell |:!|) if `output` is true, -/// else empty string. -String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err) - FUNC_API_SINCE(7) +/// @return Dictionary containing information about execution, with these keys: +/// - output: (string|nil) Output if `opts.output` is true. +Dictionary nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err) + FUNC_API_SINCE(11) { + Dictionary result = ARRAY_DICT_INIT; + + String output = exec_impl(channel_id, src, opts, err); + if (ERROR_SET(err)) { + return result; + } + + if (HAS_KEY(opts->output) && api_object_to_bool(opts->output, "opts.output", false, err)) { + PUT(result, "output", STRING_OBJ(output)); + } + + return result; +} + +String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err) +{ + Boolean output = api_object_to_bool(opts->output, "opts.output", false, err); + const int save_msg_silent = msg_silent; garray_T *const save_capture_ga = capture_ga; const int save_msg_col = msg_col; @@ -69,7 +89,7 @@ String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err) const sctx_T save_current_sctx = api_set_sctx(channel_id); - do_source_str(src.data, "nvim_exec()"); + do_source_str(src.data, "nvim_exec2()"); if (output) { capture_ga = save_capture_ga; msg_silent = save_msg_silent; @@ -108,8 +128,8 @@ theend: /// /// On execution error: fails with VimL error, updates v:errmsg. /// -/// Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script -/// or an Ex command directly, use |nvim_exec()|. To construct an Ex command using a structured +/// Prefer using |nvim_cmd()| or |nvim_exec2()| over this. To evaluate multiple lines of Vim script +/// or an Ex command directly, use |nvim_exec2()|. To construct an Ex command using a structured /// format and then execute it, use |nvim_cmd()|. To modify an Ex command before evaluating it, use /// |nvim_parse_cmd()| in conjunction with |nvim_cmd()|. /// diff --git a/src/nvim/context.c b/src/nvim/context.c index 9de6c16536..b13a331eff 100644 --- a/src/nvim/context.c +++ b/src/nvim/context.c @@ -10,6 +10,7 @@ #include <string.h> #include "nvim/api/private/converter.h" +#include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vimscript.h" #include "nvim/context.h" @@ -271,8 +272,10 @@ static inline void ctx_save_funcs(Context *ctx, bool scriptonly) size_t cmd_len = sizeof("func! ") + strlen(name); char *cmd = xmalloc(cmd_len); snprintf(cmd, cmd_len, "func! %s", name); - String func_body = nvim_exec(VIML_INTERNAL_CALL, cstr_as_string(cmd), - true, &err); + Dict(exec_opts) opts = { 0 }; + opts.output = BOOLEAN_OBJ(true); + String func_body = exec_impl(VIML_INTERNAL_CALL, cstr_as_string(cmd), + &opts, &err); xfree(cmd); if (!ERROR_SET(&err)) { ADD(ctx->funcs, STRING_OBJ(func_body)); diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3a7da21606..df8004dc73 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7581,7 +7581,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // third argument: action - 'a' for append and 'r' for replace. // default is to replace the stack. if (argvars[2].v_type == VAR_UNKNOWN) { - action = 'r'; + // action = 'r'; } else if (argvars[2].v_type == VAR_STRING) { const char *actstr; actstr = tv_get_string_chk(&argvars[2]); diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 3e7f640326..f7bf9c46a4 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -525,7 +525,9 @@ static bool cin_is_cpp_namespace(const char *s) s = cin_skipcomment(s); - if (strncmp(s, "inline", 6) == 0 && (s[6] == NUL || !vim_iswordc((uint8_t)s[6]))) { + // skip over "inline" and "export" in any order + while ((strncmp(s, "inline", 6) == 0 || strncmp(s, "export", 6) == 0) + && (s[6] == NUL || !vim_iswordc((uint8_t)s[6]))) { s = cin_skipcomment(skipwhite(s + 6)); } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index c61c74c607..7100146245 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2890,7 +2890,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar status = INS_COMPL_CPT_END; } else { if (ctrl_x_mode_line_or_eval()) { - compl_type = -1; + // compl_type = -1; } else if (*st->e_cpt == 'k' || *st->e_cpt == 's') { if (*st->e_cpt == 'k') { compl_type = CTRL_X_DICTIONARY; @@ -2912,8 +2912,6 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar vim_snprintf(IObuff, IOSIZE, "%s", _("Scanning tags.")); (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); } - } else { - compl_type = -1; } // in any case e_cpt is advanced to the next entry diff --git a/src/nvim/main.c b/src/nvim/main.c index ea5f511fc6..a16badc1a0 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1,7 +1,12 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#define EXTERN +// Make sure extern symbols are exported on Windows +#ifdef WIN32 +# define EXTERN __declspec(dllexport) +#else +# define EXTERN +#endif #include <assert.h> #include <limits.h> #include <msgpack/pack.h> diff --git a/src/nvim/path.c b/src/nvim/path.c index 9bbf56276e..973e5eaec4 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -2375,7 +2375,6 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force) end_of_path = p + 1; } else { relative_directory[0] = NUL; - end_of_path = (char *)fname; } if (FAIL == path_full_dir_name(relative_directory, buf, len)) { diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index ea59e7d464..950814880b 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -2238,7 +2238,6 @@ collection: } // Failed to recognize a character class. Use the simple // version that turns [abc] into 'a' OR 'b' OR 'c' - startc = -1; negated = false; if (*regparse == '^') { // negated range negated = true; diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 98f10c0082..3f816d0172 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -3602,7 +3602,6 @@ shada_read_next_item_start: ret = spm_ret; goto shada_read_next_item_error; } - ret = kSDReadStatusMalformed; entry->data = sd_default_values[type_u64].data; switch ((ShadaEntryType)type_u64) { case kSDItemHeader: diff --git a/test/README.md b/test/README.md index d8d918eb61..65a5ae7912 100644 --- a/test/README.md +++ b/test/README.md @@ -149,14 +149,26 @@ To run a *specific* unit test: TEST_FILE=test/unit/foo.lua make unittest +or + + cmake -E env "TEST_FILE=test/unit/foo.lua" cmake --build build --target unittest + To run a *specific* functional test: TEST_FILE=test/functional/foo.lua make functionaltest +or + + cmake -E env "TEST_FILE=test/functional/foo.lua" cmake --build build --target functionaltest + To *repeat* a test: BUSTED_ARGS="--repeat=100 --no-keep-going" TEST_FILE=test/functional/foo_spec.lua make functionaltest +or + + cmake -E env "TEST_FILE=test/functional/foo_spec.lua" cmake -E env BUSTED_ARGS="--repeat=100 --no-keep-going" cmake --build build --target functionaltest + ### Filter by tag Tests can be "tagged" by adding `#` before a token in the test description. diff --git a/test/deprecated.lua b/test/deprecated.lua index b162c8fc93..e30dfcf3ab 100644 --- a/test/deprecated.lua +++ b/test/deprecated.lua @@ -3,7 +3,7 @@ local M = {} function M.redir_exec() - error('redir_exec is deprecated, use nvim_exec() or pcall_err()') + error('redir_exec is deprecated, use nvim_exec2() or pcall_err()') end return M diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 30e75b8061..e9a175625b 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -1413,12 +1413,12 @@ describe('API/extmarks', function() end) it('does not crash with append/delete/undo sequence', function() - meths.exec([[ + meths.exec2([[ let ns = nvim_create_namespace('myplugin') call nvim_buf_set_extmark(0, ns, 0, 0, {}) call append(0, '') %delete - undo]],false) + undo]], { output = false }) assert_alive() end) @@ -1450,7 +1450,7 @@ describe('API/extmarks', function() feed('u') -- handles pasting - meths.exec([[let @a='asdfasdf']], false) + meths.exec2([[let @a='asdfasdf']], { output = false }) feed([["ap]]) eq({ {1, 0, 0}, {2, 0, 8} }, meths.buf_get_extmarks(0, ns, 0, -1, {})) diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index 5be4425162..78281be195 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -681,13 +681,13 @@ describe('nvim_set_keymap, nvim_del_keymap', function() end) it('can set <expr> mappings whose RHS change dynamically', function() - meths.exec([[ + meths.exec2([[ function! FlipFlop() abort if !exists('g:flip') | let g:flip = 0 | endif let g:flip = !g:flip return g:flip endfunction - ]], true) + ]], { output = false }) eq(1, meths.call_function('FlipFlop', {})) eq(0, meths.call_function('FlipFlop', {})) eq(1, meths.call_function('FlipFlop', {})) @@ -827,8 +827,12 @@ describe('nvim_set_keymap, nvim_del_keymap', function() exec_lua [[ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end }) ]] - assert.truthy(string.match(exec_lua[[return vim.api.nvim_exec(':nmap asdf', true)]], - "^\nn asdf <Lua %d+>")) + assert.truthy( + string.match( + exec_lua[[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]], + "^\nn asdf <Lua %d+>" + ) + ) end) it ('mapcheck() returns lua mapping correctly', function() diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index ff1bfef591..162735dbd7 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -89,132 +89,145 @@ describe('API', function() eq({mode='i', blocking=false}, nvim("get_mode")) end) - describe('nvim_exec', function() + describe('nvim_exec2', function() + it('always returns table', function() + -- In built version this results into `vim.empty_dict()` + eq({}, nvim('exec2', 'echo "Hello"', {})) + eq({}, nvim('exec2', 'echo "Hello"', { output = false })) + eq({ output = 'Hello' }, nvim('exec2', 'echo "Hello"', { output = true })) + end) + + it('default options', function() + -- Should be equivalent to { output = false } + nvim('exec2', "let x0 = 'a'", {}) + eq('a', nvim('get_var', 'x0')) + end) + it('one-line input', function() - nvim('exec', "let x1 = 'a'", false) + nvim('exec2', "let x1 = 'a'", { output = false }) eq('a', nvim('get_var', 'x1')) end) it(':verbose set {option}?', function() - nvim('exec', 'set nowrap', false) - eq('nowrap\n\tLast set from anonymous :source', - nvim('exec', 'verbose set wrap?', true)) + nvim('exec2', 'set nowrap', { output = false }) + eq({ output = 'nowrap\n\tLast set from anonymous :source' }, + nvim('exec2', 'verbose set wrap?', { output = true })) -- Using script var to force creation of a script item - nvim('exec', [[ + nvim('exec2', [[ let s:a = 1 set nowrap - ]], false) - eq('nowrap\n\tLast set from anonymous :source (script id 1)', - nvim('exec', 'verbose set wrap?', true)) + ]], { output = false }) + eq({ output = 'nowrap\n\tLast set from anonymous :source (script id 1)' }, + nvim('exec2', 'verbose set wrap?', { output = true })) end) it('multiline input', function() -- Heredoc + empty lines. - nvim('exec', "let x2 = 'a'\n", false) + nvim('exec2', "let x2 = 'a'\n", { output = false }) eq('a', nvim('get_var', 'x2')) - nvim('exec','lua <<EOF\n\n\n\ny=3\n\n\nEOF', false) + nvim('exec2','lua <<EOF\n\n\n\ny=3\n\n\nEOF', { output = false }) eq(3, nvim('eval', "luaeval('y')")) - eq('', nvim('exec', 'lua <<EOF\ny=3\nEOF', false)) + eq({}, nvim('exec2', 'lua <<EOF\ny=3\nEOF', { output = false })) eq(3, nvim('eval', "luaeval('y')")) -- Multiple statements - nvim('exec', 'let x1=1\nlet x2=2\nlet x3=3\n', false) + nvim('exec2', 'let x1=1\nlet x2=2\nlet x3=3\n', { output = false }) eq(1, nvim('eval', 'x1')) eq(2, nvim('eval', 'x2')) eq(3, nvim('eval', 'x3')) -- Functions - nvim('exec', 'function Foo()\ncall setline(1,["xxx"])\nendfunction', false) + nvim('exec2', 'function Foo()\ncall setline(1,["xxx"])\nendfunction', { output = false }) eq('', nvim('get_current_line')) - nvim('exec', 'call Foo()', false) + nvim('exec2', 'call Foo()', { output = false }) eq('xxx', nvim('get_current_line')) -- Autocmds - nvim('exec','autocmd BufAdd * :let x1 = "Hello"', false) + nvim('exec2','autocmd BufAdd * :let x1 = "Hello"', { output = false }) nvim('command', 'new foo') eq('Hello', request('nvim_eval', 'g:x1')) -- Line continuations - nvim('exec', [[ + nvim('exec2', [[ let abc = #{ \ a: 1, "\ b: 2, \ c: 3 - \ }]], false) + \ }]], { output = false }) eq({a = 1, c = 3}, request('nvim_eval', 'g:abc')) -- try no spaces before continuations to catch off-by-one error - nvim('exec', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', false) + nvim('exec2', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', { output = false }) eq({a = 98}, request('nvim_eval', 'g:ab')) -- Script scope (s:) - eq('ahoy! script-scoped varrrrr', nvim('exec', [[ + eq({ output = 'ahoy! script-scoped varrrrr' }, nvim('exec2', [[ let s:pirate = 'script-scoped varrrrr' function! s:avast_ye_hades(s) abort return a:s .. ' ' .. s:pirate endfunction echo <sid>avast_ye_hades('ahoy!') - ]], true)) + ]], { output = true })) - eq('ahoy! script-scoped varrrrr', nvim('exec', [[ + eq({ output = "{'output': 'ahoy! script-scoped varrrrr'}" }, nvim('exec2', [[ let s:pirate = 'script-scoped varrrrr' function! Avast_ye_hades(s) abort return a:s .. ' ' .. s:pirate endfunction - echo nvim_exec('echo Avast_ye_hades(''ahoy!'')', 1) - ]], true)) + echo nvim_exec2('echo Avast_ye_hades(''ahoy!'')', {'output': v:true}) + ]], { output = true })) matches('Vim%(echo%):E121: Undefined variable: s:pirate$', - pcall_err(request, 'nvim_exec', [[ + pcall_err(request, 'nvim_exec2', [[ let s:pirate = 'script-scoped varrrrr' - call nvim_exec('echo s:pirate', 1) - ]], false)) + call nvim_exec2('echo s:pirate', {'output': v:true}) + ]], { output = false })) -- Script items are created only on script var access - eq('1\n0', nvim('exec', [[ + eq({ output = '1\n0' }, nvim('exec2', [[ echo expand("<SID>")->empty() let s:a = 123 echo expand("<SID>")->empty() - ]], true)) + ]], { output = true })) - eq('1\n0', nvim('exec', [[ + eq({ output = '1\n0' }, nvim('exec2', [[ echo expand("<SID>")->empty() function s:a() abort endfunction echo expand("<SID>")->empty() - ]], true)) + ]], { output = true })) end) it('non-ASCII input', function() - nvim('exec', [=[ + nvim('exec2', [=[ new exe "normal! i ax \n Ax " :%s/ax/--a1234--/g | :%s/Ax/--A1234--/g - ]=], false) + ]=], { output = false }) nvim('command', '1') eq(' --a1234-- ', nvim('get_current_line')) nvim('command', '2') eq(' --A1234-- ', nvim('get_current_line')) - nvim('exec', [[ + nvim('exec2', [[ new call setline(1,['xxx']) call feedkeys('r') call feedkeys('ñ', 'xt') - ]], false) + ]], { output = false }) eq('ñxx', nvim('get_current_line')) end) it('execution error', function() - eq('nvim_exec(): Vim:E492: Not an editor command: bogus_command', - pcall_err(request, 'nvim_exec', 'bogus_command', false)) + eq('nvim_exec2(): Vim:E492: Not an editor command: bogus_command', + pcall_err(request, 'nvim_exec2', 'bogus_command', {})) eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) - eq('nvim_exec(): Vim(buffer):E86: Buffer 23487 does not exist', - pcall_err(request, 'nvim_exec', 'buffer 23487', false)) + eq('nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist', + pcall_err(request, 'nvim_exec2', 'buffer 23487', {})) eq('', eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) @@ -222,17 +235,17 @@ describe('API', function() it('recursion', function() local fname = tmpname() write_file(fname, 'let x1 = "set from :source file"\n') - -- nvim_exec + -- nvim_exec2 -- :source - -- nvim_exec - request('nvim_exec', [[ + -- nvim_exec2 + request('nvim_exec2', [[ let x2 = substitute('foo','o','X','g') let x4 = 'should be overwritten' - call nvim_exec("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec','g')\nlet x5='overwritten'\nlet x4=x5\n", v:false) - ]], false) + call nvim_exec2("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false}) + ]], { output = false }) eq('set from :source file', request('nvim_get_var', 'x1')) eq('fXX', request('nvim_get_var', 'x2')) - eq('set by recursive nvim_exec', request('nvim_get_var', 'x3')) + eq('set by recursive nvim_exec2', request('nvim_get_var', 'x3')) eq('overwritten', request('nvim_get_var', 'x4')) eq('overwritten', request('nvim_get_var', 'x5')) os.remove(fname) @@ -242,35 +255,35 @@ describe('API', function() local fname = tmpname() write_file(fname, 'echo "hello"\n') local sourcing_fname = tmpname() - write_file(sourcing_fname, 'call nvim_exec("source '..fname..'", v:false)\n') - meths.exec('set verbose=2', false) + write_file(sourcing_fname, 'call nvim_exec2("source '..fname..'", {"output": v:false})\n') + meths.exec2('set verbose=2', { output = false }) local traceback_output = 'line 0: sourcing "'..sourcing_fname..'"\n'.. 'line 0: sourcing "'..fname..'"\n'.. 'hello\n'.. 'finished sourcing '..fname..'\n'.. - 'continuing in nvim_exec() called at '..sourcing_fname..':1\n'.. + 'continuing in nvim_exec2() called at '..sourcing_fname..':1\n'.. 'finished sourcing '..sourcing_fname..'\n'.. - 'continuing in nvim_exec() called at nvim_exec():0' - eq(traceback_output, - meths.exec('call nvim_exec("source '..sourcing_fname..'", v:false)', true)) + 'continuing in nvim_exec2() called at nvim_exec2():0' + eq({ output = traceback_output }, + meths.exec2('call nvim_exec2("source '..sourcing_fname..'", {"output": v:false})', { output = true })) os.remove(fname) os.remove(sourcing_fname) end) it('returns output', function() - eq('this is spinal tap', - nvim('exec', 'lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', true)) - eq('', nvim('exec', 'echo', true)) - eq('foo 42', nvim('exec', 'echo "foo" 42', true)) + eq({ output = 'this is spinal tap' }, + nvim('exec2', 'lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', { output = true })) + eq({ output = '' }, nvim('exec2', 'echo', { output = true })) + eq({ output = 'foo 42' }, nvim('exec2', 'echo "foo" 42', { output = true })) end) - it('displays messages when output=false', function() + it('displays messages when opts.output=false', function() local screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ [0] = {bold=true, foreground=Screen.colors.Blue}, }) - meths.exec("echo 'hello'", false) + meths.exec2("echo 'hello'", { output = false }) screen:expect{grid=[[ ^ | {0:~ }| @@ -289,7 +302,7 @@ describe('API', function() screen:set_default_attr_ids({ [0] = {bold=true, foreground=Screen.colors.Blue}, }) - meths.exec("echo 'hello'", true) + meths.exec2("echo 'hello'", { output = true }) screen:expect{grid=[[ ^ | {0:~ }| @@ -300,7 +313,7 @@ describe('API', function() ]]} exec([[ func Print() - call nvim_exec('echo "hello"', v:true) + call nvim_exec2('echo "hello"', { 'output': v:true }) endfunc ]]) feed([[:echon 1 | call Print() | echon 5<CR>]]) @@ -575,7 +588,7 @@ describe('API', function() it('sets previous directory', function() meths.set_current_dir("Xtestdir") - meths.exec('cd -', false) + meths.exec2('cd -', { output = false }) eq(funcs.getcwd(), start_dir) end) end) @@ -2674,7 +2687,7 @@ describe('API', function() eq(' 1 %a "[No Name]" line 1\n'.. ' 3 h "[Scratch]" line 0\n'.. ' 4 h "[Scratch]" line 0', - meths.exec('ls', true)) + meths.exec2('ls', { output = true }).output) -- current buffer didn't change eq({id=1}, meths.get_current_buf()) @@ -2788,7 +2801,7 @@ describe('API', function() end) it('should not crash when echoed', function() - meths.exec("echo nvim_get_all_options_info()", true) + meths.exec2("echo nvim_get_all_options_info()", { output = true }) end) end) @@ -2941,13 +2954,13 @@ describe('API', function() it('can save message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {}) - eq("msg\nmsgmsg", meths.exec('messages', true)) + eq("msg\nmsgmsg", meths.exec2('messages', { output = true }).output) end) it('can disable saving message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {}) - eq("", meths.exec("messages", true)) + eq("", meths.exec2("messages", { output = true }).output) end) end) @@ -3936,7 +3949,7 @@ describe('API', function() it('sets correct script context', function() meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) - local str = meths.exec([[verbose set cursorline?]], true) + local str = meths.exec2([[verbose set cursorline?]], { output = true }).output neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)")) end) @@ -3986,7 +3999,7 @@ describe('API', function() line6 ]] meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {}) - meths.exec("1put a", false) + meths.exec2("1put a", { output = false }) expect [[ line1 line2 @@ -4051,11 +4064,11 @@ describe('API', function() { output = true })) end) it('splits arguments correctly', function() - meths.exec([[ + meths.exec2([[ function! FooFunc(...) echo a:000 endfunction - ]], false) + ]], { output = false }) meths.create_user_command("Foo", "call FooFunc(<f-args>)", { nargs = '+' }) eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=], meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}}, diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua index ad3687d7b0..7d475e5015 100644 --- a/test/functional/autocmd/autocmd_oldtest_spec.lua +++ b/test/functional/autocmd/autocmd_oldtest_spec.lua @@ -6,7 +6,7 @@ local meths = helpers.meths local funcs = helpers.funcs local exec = function(str) - meths.exec(str, false) + meths.exec2(str, { output = false }) end describe('oldtests', function() diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua index dc4b45b4d9..d474b77806 100644 --- a/test/functional/core/exit_spec.lua +++ b/test/functional/core/exit_spec.lua @@ -93,14 +93,14 @@ describe(':cquit', function() end) it('exits with redir msg for multiple exit codes after :cquit 1 2', function() - test_cq('cquit 1 2', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: 2: cquit 1 2') + test_cq('cquit 1 2', nil, 'nvim_exec2(): Vim(cquit):E488: Trailing characters: 2: cquit 1 2') end) it('exits with redir msg for non-number exit code after :cquit X', function() - test_cq('cquit X', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: X: cquit X') + test_cq('cquit X', nil, 'nvim_exec2(): Vim(cquit):E488: Trailing characters: X: cquit X') end) it('exits with redir msg for negative exit code after :cquit -1', function() - test_cq('cquit -1', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: -1: cquit -1') + test_cq('cquit -1', nil, 'nvim_exec2(): Vim(cquit):E488: Trailing characters: -1: cquit -1') end) end) diff --git a/test/functional/core/remote_spec.lua b/test/functional/core/remote_spec.lua index 846d79abf3..b2a1679023 100644 --- a/test/functional/core/remote_spec.lua +++ b/test/functional/core/remote_spec.lua @@ -101,7 +101,7 @@ describe('Remote', function() expect(contents) eq(1, #funcs.getbufinfo()) -- Since we didn't pass silent, we should get a complaint - neq(nil, string.find(meths.exec('messages', true), 'E247')) + neq(nil, string.find(meths.exec2('messages', { output = true }).output, 'E247')) end) it('creates server if not found with tabs', function() @@ -110,7 +110,7 @@ describe('Remote', function() eq(2, #funcs.gettabinfo()) eq(2, #funcs.getbufinfo()) -- We passed silent, so no message should be issued about the server not being found - eq(nil, string.find(meths.exec('messages', true), 'E247')) + eq(nil, string.find(meths.exec2('messages', { output = true }).output, 'E247')) end) pending('exits with error on', function() diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index e9b47a0251..4ae8b1c95e 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -58,7 +58,7 @@ describe('startup', function() ^ | | Entering Debug mode. Type "cont" to continue. | - nvim_exec() | + nvim_exec2() | cmd: aunmenu * | > | | @@ -691,7 +691,6 @@ describe('sysinit', function() eq('loaded 1 xdg 0 vim 1', eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')) end) - end) describe('user config init', function() @@ -824,7 +823,7 @@ describe('user config init', function() clear{ args_rm={'-u'}, env=xenv } feed('<cr><c-c>') -- Dismiss "Conflicting config …" message. eq(1, eval('g:lua_rc')) - matches('^E5422: Conflicting configs', meths.exec('messages', true)) + matches('^E5422: Conflicting configs', meths.exec2('messages', { output = true }).output) end) end) end) @@ -873,7 +872,7 @@ describe('runtime:', function() eq(2, eval('g:lua_plugin')) -- Check if plugin_file_path is listed in :scriptname - local scripts = meths.exec(':scriptnames', true) + local scripts = meths.exec2(':scriptnames', { output = true }).output assert(scripts:find(plugin_file_path)) -- Check if plugin_file_path is listed in startup profile diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua index 0670176719..365f8527a0 100644 --- a/test/functional/editor/mark_spec.lua +++ b/test/functional/editor/mark_spec.lua @@ -40,59 +40,59 @@ describe('named marks', function() it("errors when set out of range with :mark", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "1000mark x") - eq("nvim_exec(): Vim(mark):E16: Invalid range: 1000mark x", err) + eq("nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x", err) end) it("errors when set out of range with :k", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "1000kx") - eq("nvim_exec(): Vim(k):E16: Invalid range: 1000kx", err) + eq("nvim_exec2(): Vim(k):E16: Invalid range: 1000kx", err) end) it("errors on unknown mark name with :mark", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "mark #") - eq("nvim_exec(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err) + eq("nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err) end) it("errors on unknown mark name with '", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! '#") - eq("nvim_exec(): Vim(normal):E78: Unknown mark", err) + eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err) end) it("errors on unknown mark name with `", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! `#") - eq("nvim_exec(): Vim(normal):E78: Unknown mark", err) + eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err) end) it("errors when moving to a mark that is not set with '", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! 'z") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) err = pcall_err(helpers.exec_capture, "normal! '.") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) end) it("errors when moving to a mark that is not set with `", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! `z") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) err = pcall_err(helpers.exec_capture, "normal! `>") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) end) it("errors when moving to a global mark that is not set with '", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! 'Z") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) end) it("errors when moving to a global mark that is not set with `", function() command("edit " .. file1) local err = pcall_err(helpers.exec_capture, "normal! `Z") - eq("nvim_exec(): Vim(normal):E20: Mark not set", err) + eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) end) it("can move to them using '", function() @@ -153,7 +153,7 @@ describe('named marks', function() command("next") command("bw! " .. file1 ) local err = pcall_err(helpers.exec_capture, "normal! 'A") - eq("nvim_exec(): Vim(normal):E92: Buffer 1 not found", err) + eq("nvim_exec2(): Vim(normal):E92: Buffer 1 not found", err) os.remove(file1) end) diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua index bf69ada820..d13268c97c 100644 --- a/test/functional/ex_cmds/script_spec.lua +++ b/test/functional/ex_cmds/script_spec.lua @@ -34,7 +34,7 @@ describe('script_get-based command', function() %s %s endif ]])):format(cmd, garbage))) - eq('', meths.exec('messages', true)) + eq('', meths.exec2('messages', { output = true }).output) if check_neq then neq(0, exc_exec(dedent([[ %s %s @@ -49,7 +49,7 @@ describe('script_get-based command', function() EOF endif ]])):format(cmd, garbage))) - eq('', meths.exec('messages', true)) + eq('', meths.exec2('messages', { output = true }).output) if check_neq then eq(true, pcall(source, (dedent([[ let g:exc = 0 diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua index 64c3464be7..e12ead240d 100644 --- a/test/functional/ex_cmds/source_spec.lua +++ b/test/functional/ex_cmds/source_spec.lua @@ -96,12 +96,12 @@ describe(':source', function() let d = s:s]]) command('source') - eq('2', meths.exec('echo a', true)) - eq("{'k': 'v'}", meths.exec('echo b', true)) + eq('2', meths.exec2('echo a', { output = true }).output) + eq("{'k': 'v'}", meths.exec2('echo b', { output = true }).output) -- Script items are created only on script var access - eq("1", meths.exec('echo c', true)) - eq("0zBEEFCAFE", meths.exec('echo d', true)) + eq("1", meths.exec2('echo c', { output = true }).output) + eq("0zBEEFCAFE", meths.exec2('echo d', { output = true }).output) exec('set cpoptions+=C') eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec('source')) @@ -124,14 +124,14 @@ describe(':source', function() -- Source the 2nd line only feed('ggjV') feed_command(':source') - eq('3', meths.exec('echo a', true)) + eq('3', meths.exec2('echo a', { output = true }).output) -- Source from 2nd line to end of file feed('ggjVG') feed_command(':source') - eq('4', meths.exec('echo a', true)) - eq("{'K': 'V'}", meths.exec('echo b', true)) - eq("<SNR>1_C()", meths.exec('echo D()', true)) + eq('4', meths.exec2('echo a', { output = true }).output) + eq("{'K': 'V'}", meths.exec2('echo b', { output = true }).output) + eq("<SNR>1_C()", meths.exec2('echo D()', { output = true }).output) -- Source last line only feed_command(':$source') @@ -147,7 +147,7 @@ describe(':source', function() let a = 123 ]] command('source') - eq('123', meths.exec('echo a', true)) + eq('123', meths.exec2('echo a', { output = true }).output) end) it('multiline heredoc command', function() @@ -157,7 +157,7 @@ describe(':source', function() EOF]]) command('source') - eq('4', meths.exec('echo luaeval("y")', true)) + eq('4', meths.exec2('echo luaeval("y")', { output = true }).output) end) it('can source lua files', function() diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua index e55372e993..2482fd912f 100644 --- a/test/functional/ex_cmds/verbose_spec.lua +++ b/test/functional/ex_cmds/verbose_spec.lua @@ -24,11 +24,11 @@ vim.opt.number = true vim.api.nvim_set_keymap('n', '<leader>key1', ':echo "test"<cr>', {noremap = true}) vim.keymap.set('n', '<leader>key2', ':echo "test"<cr>') -vim.api.nvim_exec("augroup test_group\ +vim.api.nvim_exec2("augroup test_group\ autocmd!\ autocmd FileType c setl cindent\ augroup END\ - ", false) + ", { output = false }) vim.api.nvim_command("command Bdelete :bd") vim.api.nvim_create_user_command("TestCommand", ":echo 'Hello'", {}) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index b485352c94..de5fe96934 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -533,7 +533,7 @@ function module.feed_command(...) end end --- @deprecated use nvim_exec() +-- @deprecated use nvim_exec2() function module.source(code) module.exec(dedent(code)) end @@ -826,11 +826,11 @@ function module.skip_fragile(pending_fn, cond) end function module.exec(code) - return module.meths.exec(code, false) + module.meths.exec2(code, { output = false }) end function module.exec_capture(code) - return module.meths.exec(code, true) + return module.meths.exec2(code, { output = true }).output end function module.exec_lua(code, ...) diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 4829a0bbe1..d49d7d665a 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -145,10 +145,10 @@ describe('assert function:', function() call assert_true('', 'file two') ]]) expected_errors({ - "nvim_exec(): equal assertion failed: Expected 1 but got 100", - "nvim_exec(): true assertion failed: Expected False but got 'true'", - "nvim_exec(): false assertion failed: Expected True but got 'false'", - "nvim_exec(): file two: Expected True but got ''", + "nvim_exec2(): equal assertion failed: Expected 1 but got 100", + "nvim_exec2(): true assertion failed: Expected False but got 'true'", + "nvim_exec2(): false assertion failed: Expected True but got 'false'", + "nvim_exec2(): file two: Expected True but got ''", }) end) end) diff --git a/test/functional/lua/ffi_spec.lua b/test/functional/lua/ffi_spec.lua index 18b13a8959..c492c1e765 100644 --- a/test/functional/lua/ffi_spec.lua +++ b/test/functional/lua/ffi_spec.lua @@ -63,5 +63,14 @@ describe('ffi.cdef', function() nil ) ]=]) + + -- Check that extern symbols are exported and accessible + eq(true, exec_lua[[ + local ffi = require('ffi') + + ffi.cdef('uint64_t display_tick;') + + return ffi.C.display_tick >= 0 + ]]) end) end) diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua index 4fdc6ef4be..7ff86438b2 100644 --- a/test/functional/options/keymap_spec.lua +++ b/test/functional/options/keymap_spec.lua @@ -30,7 +30,7 @@ describe("'keymap' / :lmap", function() command('lmapclear <buffer>') command('set keymap=dvorak') command('set nomore') - local bindings = funcs.nvim_exec('lmap', true) + local bindings = funcs.nvim_exec2('lmap', { output = true }).output eq(dedent([[ l " @_ diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua new file mode 100644 index 0000000000..3e53b6d574 --- /dev/null +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -0,0 +1,75 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local exec_lua = helpers.exec_lua + +describe('vim.lsp.util', function() + before_each(helpers.clear) + + describe('stylize_markdown', function() + local stylize_markdown = function(content, opts) + return exec_lua([[ + local bufnr = vim.uri_to_bufnr("file:///fake/uri") + vim.fn.bufload(bufnr) + + local args = { ... } + local content = args[1] + local opts = args[2] + local stripped_content = vim.lsp.util.stylize_markdown(bufnr, content, opts) + + return stripped_content + ]], content, opts) + end + + it('code fences', function() + local lines = { + "```lua", + "local hello = 'world'", + "```", + } + local expected = { + "local hello = 'world'", + } + local opts = {} + eq(expected, stylize_markdown(lines, opts)) + end) + + it('adds separator after code block', function() + local lines = { + "```lua", + "local hello = 'world'", + "```", + "", + "something", + } + local expected = { + "local hello = 'world'", + "─────────────────────", + "something", + } + local opts = { separator = true } + eq(expected, stylize_markdown(lines, opts)) + end) + + it('replaces supported HTML entities', function() + local lines = { + "1 < 2", + "3 > 2", + ""quoted"", + "'apos'", + "   ", + "&", + } + local expected = { + "1 < 2", + "3 > 2", + '"quoted"', + "'apos'", + " ", + "&", + } + local opts = {} + eq(expected, stylize_markdown(lines, opts)) + end) + end) +end) diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 2a2311c0fa..44e6500008 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -376,7 +376,7 @@ describe('treesitter highlighting', function() exec_lua [[ parser = vim.treesitter.get_parser(0, "c") - query = vim.treesitter.parse_query("c", "(declaration) @decl") + query = vim.treesitter.query.parse("c", "(declaration) @decl") local nodes = {} for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do @@ -481,8 +481,8 @@ describe('treesitter highlighting', function() exec_lua [[ local injection_query = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)" - require('vim.treesitter.query').set_query("c", "highlights", hl_query) - require('vim.treesitter.query').set_query("c", "injections", injection_query) + vim.treesitter.query.set("c", "highlights", hl_query) + vim.treesitter.query.set("c", "injections", injection_query) vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, "c")) ]] diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua index 48e7b4b018..9b871a72fb 100644 --- a/test/functional/treesitter/language_spec.lua +++ b/test/functional/treesitter/language_spec.lua @@ -18,27 +18,27 @@ describe('treesitter language API', function() -- actual message depends on platform matches("Failed to load parser for language 'borklang': uv_dlopen: .+", - pcall_err(exec_lua, "parser = vim.treesitter.add('borklang', { path = 'borkbork.so' })")) + pcall_err(exec_lua, "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })")) - eq(false, exec_lua("return pcall(vim.treesitter.add, 'borklang')")) + eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang')")) - eq(false, exec_lua("return pcall(vim.treesitter.add, 'borklang', { path = 'borkbork.so' })")) + eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })")) eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", - pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')")) + pcall_err(exec_lua, "parser = vim.treesitter.language.inspect('borklang')")) matches("Failed to load parser: uv_dlsym: .+", - pcall_err(exec_lua, 'vim.treesitter.add("c", { symbol_name = "borklang" })')) + pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })')) end) it('shows error for invalid language name', function() eq(".../language.lua:0: '/foo/' is not a valid language name", - pcall_err(exec_lua, 'vim.treesitter.add("/foo/")')) + pcall_err(exec_lua, 'vim.treesitter.language.add("/foo/")')) end) it('inspects language', function() local keys, fields, symbols = unpack(exec_lua([[ - local lang = vim.treesitter.inspect_language('c') + local lang = vim.treesitter.language.inspect('c') local keys, symbols = {}, {} for k,_ in pairs(lang) do keys[k] = true diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua index a82dce47b7..5ff73d3a8d 100644 --- a/test/functional/treesitter/node_spec.lua +++ b/test/functional/treesitter/node_spec.lua @@ -26,7 +26,7 @@ describe('treesitter node API', function() parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] root = tree:root() - lang = vim.treesitter.inspect_language('c') + lang = vim.treesitter.language.inspect('c') function node_text(node) return query.get_node_text(node, 0) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index e872861d2a..72a8cd9e9b 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -23,7 +23,7 @@ describe('treesitter parser API', function() parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] root = tree:root() - lang = vim.treesitter.inspect_language('c') + lang = vim.treesitter.language.inspect('c') ]]) eq("<tree>", exec_lua("return tostring(tree)")) @@ -171,7 +171,7 @@ void ui_refresh(void) it("supports runtime queries", function() local ret = exec_lua [[ - return require"vim.treesitter.query".get_query("c", "highlights").captures[1] + return vim.treesitter.query.get("c", "highlights").captures[1] ]] eq('variable', ret) @@ -184,7 +184,7 @@ void ui_refresh(void) local query, n = ... local before = vim.loop.hrtime() for i=1,n,1 do - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) end local after = vim.loop.hrtime() return after - before @@ -203,7 +203,7 @@ void ui_refresh(void) insert(test_text) local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -232,7 +232,7 @@ void ui_refresh(void) insert(test_text) local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -326,7 +326,7 @@ end]] insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. + cquery = vim.treesitter.query.parse("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. '([_] @times (#vim-match? @times "^\\\\*$"))'.. '([_] @paren (#vim-match? @paren "^\\\\($"))'.. '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'.. @@ -376,7 +376,7 @@ end]] ]]) exec_lua([[ function get_query_result(query_text) - cquery = vim.treesitter.parse_query("c", query_text) + cquery = vim.treesitter.query.parse("c", query_text) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -416,7 +416,7 @@ end]] insert('char* astring = "Hello World!";') local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') + cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -449,7 +449,7 @@ end]] local custom_query = "((identifier) @main (#is-main? @main))" local res = exec_lua([[ - local query = require"vim.treesitter.query" + local query = vim.treesitter.query local function is_main(match, pattern, bufnr, predicate) local node = match[ predicate[2] ] @@ -461,7 +461,7 @@ end]] query.add_predicate("is-main?", is_main) - local query = query.parse_query("c", ...) + local query = query.parse("c", ...) local nodes = {} for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do @@ -474,7 +474,7 @@ end]] eq({{0, 4, 0, 8}}, res) local res_list = exec_lua[[ - local query = require'vim.treesitter.query' + local query = vim.treesitter.query local list = query.list_predicates() @@ -533,7 +533,7 @@ end]] local res = exec_lua [[ parser = vim.treesitter.get_parser(0, "c") - query = vim.treesitter.parse_query("c", "(declaration) @decl") + query = vim.treesitter.query.parse("c", "(declaration) @decl") local nodes = {} for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do @@ -581,7 +581,7 @@ end]] local parser = vim.treesitter.get_string_parser(str, "c") local nodes = {} - local query = vim.treesitter.parse_query("c", '((identifier) @id (eq? @id "foo"))') + local query = vim.treesitter.query.parse("c", '((identifier) @id (eq? @id "foo"))') for _, node in query:iter_captures(parser:parse()[1]:root(), str) do table.insert(nodes, { node:range() }) @@ -603,7 +603,7 @@ end]] local parser = vim.treesitter.get_string_parser(str, "c") local nodes = {} - local query = vim.treesitter.parse_query("c", '((identifier) @foo)') + local query = vim.treesitter.query.parse("c", '((identifier) @foo)') local first_child = parser:parse()[1]:root():child(1) for _, node in query:iter_captures(first_child, str) do @@ -703,7 +703,7 @@ int x = INT_MAX; describe("when providing parsing information through a directive", function() it("should inject a language", function() exec_lua([=[ - vim.treesitter.add_directive("inject-clang!", function(match, _, _, pred, metadata) + vim.treesitter.query.add_directive("inject-clang!", function(match, _, _, pred, metadata) metadata.language = "c" metadata.combined = true metadata.content = pred[2] @@ -741,7 +741,7 @@ int x = INT_MAX; it("should not inject bad languages", function() exec_lua([=[ - vim.treesitter.add_directive("inject-bad!", function(match, _, _, pred, metadata) + vim.treesitter.query.add_directive("inject-bad!", function(match, _, _, pred, metadata) metadata.language = "{" metadata.combined = true metadata.content = pred[2] @@ -774,7 +774,7 @@ int x = INT_MAX; end) it("should list all directives", function() local res_list = exec_lua[[ - local query = require'vim.treesitter.query' + local query = vim.treesitter.query local list = query.list_directives() @@ -820,7 +820,7 @@ int x = INT_MAX; local result = exec_lua([[ local result - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! "key" "value"))') + query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! "key" "value"))') parser = vim.treesitter.get_parser(0, "c") for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do @@ -840,10 +840,10 @@ int x = INT_MAX; ]]) local result = exec_lua([[ - local query = require("vim.treesitter.query") + local query = vim.treesitter.query local value - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))') + query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value"))') parser = vim.treesitter.get_parser(0, "c") for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do @@ -862,10 +862,10 @@ int x = INT_MAX; ]]) local result = exec_lua([[ - local query = require("vim.treesitter.query") + local query = vim.treesitter.query local result - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))') + query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))') parser = vim.treesitter.get_parser(0, "c") for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua index eb5de693bd..d6c8408f04 100644 --- a/test/functional/ui/cmdline_highlight_spec.lua +++ b/test/functional/ui/cmdline_highlight_spec.lua @@ -362,7 +362,7 @@ describe('Command-line coloring', function() {EOB:~ }| :e^ | ]]) - eq('', meths.exec('messages', true)) + eq('', meths.exec2('messages', { output = true }).output) end) it('silences :echon', function() set_color_cb('Echoning') @@ -377,7 +377,7 @@ describe('Command-line coloring', function() {EOB:~ }| :e^ | ]]) - eq('', meths.exec('messages', true)) + eq('', meths.exec2('messages', { output = true }).output) end) it('silences :echomsg', function() set_color_cb('Echomsging') @@ -392,7 +392,7 @@ describe('Command-line coloring', function() {EOB:~ }| :e^ | ]]) - eq('', meths.exec('messages', true)) + eq('', meths.exec2('messages', { output = true }).output) end) it('does the right thing when throwing', function() set_color_cb('Throwing') @@ -858,7 +858,7 @@ describe('Ex commands coloring', function() ]]) feed('<CR>') eq('Error detected while processing :\nE605: Exception not caught: 42\nE749: empty buffer', - meths.exec('messages', true)) + meths.exec2('messages', { output = true }).output) end) it('errors out when failing to get callback', function() meths.set_var('Nvim_color_cmdline', 42) diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index a92b55ae5d..81602ef92e 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -986,7 +986,7 @@ describe('ui/builtin messages', function() -- screen size doesn't affect internal output #10285 eq('ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red', - meths.exec("hi ErrorMsg", true)) + meths.exec2("hi ErrorMsg", { output = true }).output) end) it(':syntax list langGroup output', function() @@ -1025,7 +1025,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim match /\<endif\s\+".*$/ms=s+5,lc=5 contains=@vimCommentGroup,vimCommentString match /\<else\s\+".*$/ms=s+4,lc=4 contains=@vimCommentGroup,vimCommentString links to Comment]], - meths.exec('syntax list vimComment', true)) + meths.exec2('syntax list vimComment', { output = true }).output) -- luacheck: pop end) diff --git a/test/old/testdir/test_cindent.vim b/test/old/testdir/test_cindent.vim index ccc8168c09..d9702f57d2 100644 --- a/test/old/testdir/test_cindent.vim +++ b/test/old/testdir/test_cindent.vim @@ -4392,6 +4392,18 @@ func Test_cindent_47() inline/* test */namespace { 111111111111111111; } + export namespace { + 111111111111111111; + } + export inline namespace { + 111111111111111111; + } + export/* test */inline namespace { + 111111111111111111; + } + inline export namespace { + 111111111111111111; + } /* invalid namespaces use block indent */ namespace test test2 { @@ -4495,6 +4507,18 @@ func Test_cindent_47() inline/* test */namespace { 111111111111111111; } + export namespace { + 111111111111111111; + } + export inline namespace { + 111111111111111111; + } + export/* test */inline namespace { + 111111111111111111; + } + inline export namespace { + 111111111111111111; + } /* invalid namespaces use block indent */ namespace test test2 { diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index 3c47c7eefa..29eb0c599d 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -658,7 +658,8 @@ let s:filename_checks = { \ 'vrml': ['file.wrl'], \ 'vroom': ['file.vroom'], \ 'vue': ['file.vue'], - \ 'wast': ['file.wast', 'file.wat'], + \ 'wat': ['file.wat'], + \ 'wast': ['file.wast'], \ 'wdl': ['file.wdl'], \ 'webmacro': ['file.wm'], \ 'wget': ['.wgetrc', 'wgetrc'], |