aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/lua.txt14
-rw-r--r--runtime/doc/news.txt8
-rw-r--r--runtime/doc/repeat.txt8
-rw-r--r--runtime/doc/treesitter.txt10
-rw-r--r--runtime/ftplugin/hurl.vim11
-rw-r--r--runtime/lua/vim/treesitter.lua12
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua93
-rw-r--r--runtime/syntax/ant.vim94
-rw-r--r--src/nvim/api/private/helpers.c2
-rw-r--r--src/nvim/decoration.c6
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/ex_docmd.c47
-rw-r--r--src/nvim/lua/executor.c37
-rw-r--r--src/nvim/runtime.c9
-rw-r--r--src/nvim/terminal.c3
-rw-r--r--src/nvim/window.c2
-rw-r--r--test/functional/api/vim_spec.lua50
-rw-r--r--test/functional/autocmd/win_scrolled_resized_spec.lua17
-rw-r--r--test/functional/lua/commands_spec.lua41
-rw-r--r--test/functional/terminal/tui_spec.lua58
-rw-r--r--test/functional/treesitter/fold_spec.lua123
21 files changed, 275 insertions, 372 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 433a9fc266..7aa2fd5a6f 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -254,6 +254,14 @@ arguments separated by " " (space) instead of "\t" (tab).
< To see the LuaJIT version: >vim
:lua =jit.version
<
+:{range}lua
+ Executes buffer lines in {range} as Lua code. Unlike |:source|, this
+ always treats the lines as Lua code.
+
+ Example: select the following code and type ":lua<Enter>" to execute it: >lua
+ print(string.format(
+ 'unix time: %s', os.time()))
+<
*:lua-heredoc*
:lua << [trim] [{endmarker}]
{script}
@@ -266,10 +274,8 @@ arguments separated by " " (space) instead of "\t" (tab).
function! CurrentLineInfo()
lua << EOF
local linenr = vim.api.nvim_win_get_cursor(0)[1]
- local curline = vim.api.nvim_buf_get_lines(
- 0, linenr - 1, linenr, false)[1]
- print(string.format("Current line [%d] has %d bytes",
- linenr, #curline))
+ local curline = vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1]
+ print(string.format('Line [%d] has %d bytes', linenr, #curline))
EOF
endfunction
<
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index a7c4e8147c..40717f8ecf 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -123,7 +123,8 @@ BREAKING CHANGES IN HEAD *news-breaking-dev*
The following breaking changes were made during the development cycle to
unreleased features on Nvim HEAD.
-• ...
+• Removed `vim.treesitter.foldtext` as transparent foldtext is now supported
+ https://github.com/neovim/neovim/pull/20750
• ...
==============================================================================
@@ -223,8 +224,6 @@ The following new APIs and features were added.
• |vim.treesitter.query.edit()| allows live editing of treesitter
queries.
• Improved error messages for query parsing.
- • |vim.treesitter.foldtext()| applies treesitter highlighting to
- foldtext.
• |vim.ui.open()| opens URIs using the system default handler (macOS `open`,
Windows `explorer`, Linux `xdg-open`, etc.)
@@ -341,6 +340,9 @@ The following changes to existing APIs or features add new behavior.
• |:source| without arguments treats a buffer with its 'filetype' set to "lua"
as Lua code regardless of its extension.
+• |:lua| with a |[range]| executes that range in the current buffer as Lua code
+ regardless of its extension.
+
• |:checkhealth| buffer now implements |folding|. The initial folding status is
defined by the 'foldenable' option.
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 726d7a9591..ae827fa06f 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -192,11 +192,11 @@ Using Vim scripts *using-scripts*
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:so* *:source* *load-vim-script*
-:[range]so[urce] [file] Runs |Ex| commands or Lua code (".lua" files) from
+:[range]so[urce] [file] Runs |Ex-commands| or Lua code (".lua" files) from
[file].
- If no [file], the current buffer is used, and it is
- treated as Lua code if its 'filetype' is "lua" or its
- file name ends with ".lua".
+ If no [file], the current buffer is used and treated
+ as Lua code if 'filetype' is "lua" or its filename
+ ends with ".lua".
Triggers the |SourcePre| autocommand.
*:source!*
:[range]so[urce]! {file}
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 956b7d6ae5..0f4462b109 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -652,16 +652,6 @@ foldexpr({lnum}) *vim.treesitter.foldexpr()*
Return: ~
(`string`)
-foldtext() *vim.treesitter.foldtext()*
- Returns the highlighted content of the first line of the fold or falls
- back to |foldtext()| if no treesitter parser is found. Can be set directly
- to 'foldtext': >lua
- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
-<
-
- Return: ~
- (`{ [1]: string, [2]: string[] }[]|string`)
-
*vim.treesitter.get_captures_at_cursor()*
get_captures_at_cursor({winnr})
Returns a list of highlight capture names under the cursor
diff --git a/runtime/ftplugin/hurl.vim b/runtime/ftplugin/hurl.vim
new file mode 100644
index 0000000000..10a3131d3a
--- /dev/null
+++ b/runtime/ftplugin/hurl.vim
@@ -0,0 +1,11 @@
+" Vim filetype plugin file
+" Language: hurl
+" Maintainer: Melker Ulander <melker.ulander@pm.me>
+" Last Changed: 2024 01 26
+
+if exists("b:did_ftplugin") | finish | endif
+
+let b:did_ftplugin = 1
+setlocal commentstring=#\ %s
+
+let b:undo_ftplugin = "setlocal commentstring<"
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 3c91be7acf..9d96ab33fa 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -517,16 +517,4 @@ function M.foldexpr(lnum)
return require('vim.treesitter._fold').foldexpr(lnum)
end
---- Returns the highlighted content of the first line of the fold or falls back to |foldtext()|
---- if no treesitter parser is found. Can be set directly to 'foldtext':
----
---- ```lua
---- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
---- ```
----
----@return { [1]: string, [2]: string[] }[] | string
-function M.foldtext()
- return require('vim.treesitter._fold').foldtext()
-end
-
return M
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index 735627d29f..d96cc966de 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -397,97 +397,4 @@ api.nvim_create_autocmd('OptionSet', {
end
end,
})
-
----@package
----@return { [1]: string, [2]: string[] }[]|string
-function M.foldtext()
- local foldstart = vim.v.foldstart
- local bufnr = api.nvim_get_current_buf()
-
- ---@type boolean, LanguageTree
- local ok, parser = pcall(ts.get_parser, bufnr)
- if not ok then
- return vim.fn.foldtext()
- end
-
- local query = ts.query.get(parser:lang(), 'highlights')
- if not query then
- return vim.fn.foldtext()
- end
-
- local tree = parser:parse({ foldstart - 1, foldstart })[1]
-
- local line = api.nvim_buf_get_lines(bufnr, foldstart - 1, foldstart, false)[1]
- if not line then
- return vim.fn.foldtext()
- end
-
- ---@type { [1]: string, [2]: string[], range: { [1]: integer, [2]: integer } }[] | { [1]: string, [2]: string[] }[]
- local result = {}
-
- local line_pos = 0
-
- for id, node, metadata in query:iter_captures(tree:root(), 0, foldstart - 1, foldstart) do
- local name = query.captures[id]
- local start_row, start_col, end_row, end_col = node:range()
-
- local priority = tonumber(metadata.priority or vim.highlight.priorities.treesitter)
-
- if start_row == foldstart - 1 and end_row == foldstart - 1 then
- -- check for characters ignored by treesitter
- if start_col > line_pos then
- table.insert(result, {
- line:sub(line_pos + 1, start_col),
- {},
- range = { line_pos, start_col },
- })
- end
- line_pos = end_col
-
- local text = line:sub(start_col + 1, end_col)
- table.insert(result, { text, { { '@' .. name, priority } }, range = { start_col, end_col } })
- end
- end
-
- local i = 1
- while i <= #result do
- -- find first capture that is not in current range and apply highlights on the way
- local j = i + 1
- while
- j <= #result
- and result[j].range[1] >= result[i].range[1]
- and result[j].range[2] <= result[i].range[2]
- do
- for k, v in ipairs(result[i][2]) do
- if not vim.tbl_contains(result[j][2], v) then
- table.insert(result[j][2], k, v)
- end
- end
- j = j + 1
- end
-
- -- remove the parent capture if it is split into children
- if j > i + 1 then
- table.remove(result, i)
- else
- -- highlights need to be sorted by priority, on equal prio, the deeper nested capture (earlier
- -- in list) should be considered higher prio
- if #result[i][2] > 1 then
- table.sort(result[i][2], function(a, b)
- return a[2] < b[2]
- end)
- end
-
- result[i][2] = vim.tbl_map(function(tbl)
- return tbl[1]
- end, result[i][2])
- result[i] = { result[i][1], result[i][2] }
-
- i = i + 1
- end
- end
-
- return result
-end
-
return M
diff --git a/runtime/syntax/ant.vim b/runtime/syntax/ant.vim
index 6696f96eb1..b0231236dd 100644
--- a/runtime/syntax/ant.vim
+++ b/runtime/syntax/ant.vim
@@ -1,9 +1,9 @@
" Vim syntax file
-" Language: ANT build file (xml)
-" Maintainer: Johannes Zellner <johannes@zellner.org>
-" Last Change: Tue Apr 27 13:05:59 CEST 2004
-" Filenames: build.xml
-" $Id: ant.vim,v 1.1 2004/06/13 18:13:18 vimboss Exp $
+" Language: ANT build file (xml)
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
+" Last Change: 2024 Jan 27
+" Filenames: build.xml
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -44,48 +44,48 @@ call AntSyntaxScript('jpython', 'python.vim')
syn cluster xmlTagHook add=antElement
-syn keyword antElement display WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
-syn keyword antElement display assertions attrib attribute available basename bcc blgenclient bootclasspath
-syn keyword antElement display borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
-syn keyword antElement display catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
-syn keyword antElement display ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
-syn keyword antElement display ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
-syn keyword antElement display chown classconstants classes classfileset classpath commandline comment
-syn keyword antElement display compilerarg compilerclasspath concat concatfilter condition copy copydir
-syn keyword antElement display copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
-syn keyword antElement display daemons date defaultexcludes define delete deletecharacters deltree depend
-syn keyword antElement display depends dependset depth description different dirname dirset disable dname
-syn keyword antElement display doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
-syn keyword antElement display env equals escapeunicode exclude excludepackage excludesfile exec execon
-syn keyword antElement display existing expandproperties extdirs extension extensionSet extensionset factory
-syn keyword antElement display fail filelist filename filepath fileset filesmatch filetokenizer filter
-syn keyword antElement display filterchain filterreader filters filterset filtersfile fixcrlf footer format
-syn keyword antElement display from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
-syn keyword antElement display ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
-syn keyword antElement display iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
-syn keyword antElement display jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
-syn keyword antElement display jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
-syn keyword antElement display junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
-syn keyword antElement display location macrodef mail majority manifest map mapper marker mergefiles message
-syn keyword antElement display metainf method mimemail mkdir mmetrics modified move mparse none not options or
-syn keyword antElement display os outputproperty package packageset parallel param patch path pathconvert
-syn keyword antElement display pathelement patternset permissions prefixlines present presetdef project
-syn keyword antElement display property propertyfile propertyref propertyset pvcs pvcsproject record reference
-syn keyword antElement display regexp rename renameext replace replacefilter replaceregex replaceregexp
-syn keyword antElement display replacestring replacetoken replacetokens replacevalue replyto report resource
-syn keyword antElement display revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
-syn keyword antElement display setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
-syn keyword antElement display sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
-syn keyword antElement display stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
-syn keyword antElement display striplinecomments style subant substitution support symlink sync sysproperty
-syn keyword antElement display syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
-syn keyword antElement display targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
-syn keyword antElement display to token tokenfilter touch transaction translate triggers trim tstamp type
-syn keyword antElement display typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
-syn keyword antElement display vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
-syn keyword antElement display webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
-syn keyword antElement display wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
-syn keyword antElement display zipgroupfileset
+syn keyword antElement WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
+syn keyword antElement assertions attrib attribute available basename bcc blgenclient bootclasspath
+syn keyword antElement borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
+syn keyword antElement catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
+syn keyword antElement ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
+syn keyword antElement ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
+syn keyword antElement chown classconstants classes classfileset classpath commandline comment
+syn keyword antElement compilerarg compilerclasspath concat concatfilter condition copy copydir
+syn keyword antElement copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
+syn keyword antElement daemons date defaultexcludes define delete deletecharacters deltree depend
+syn keyword antElement depends dependset depth description different dirname dirset disable dname
+syn keyword antElement doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
+syn keyword antElement env equals escapeunicode exclude excludepackage excludesfile exec execon
+syn keyword antElement existing expandproperties extdirs extension extensionSet extensionset factory
+syn keyword antElement fail filelist filename filepath fileset filesmatch filetokenizer filter
+syn keyword antElement filterchain filterreader filters filterset filtersfile fixcrlf footer format
+syn keyword antElement from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
+syn keyword antElement ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
+syn keyword antElement iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
+syn keyword antElement jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
+syn keyword antElement jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
+syn keyword antElement junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
+syn keyword antElement location macrodef mail majority manifest map mapper marker mergefiles message
+syn keyword antElement metainf method mimemail mkdir mmetrics modified move mparse none not options or
+syn keyword antElement os outputproperty package packageset parallel param patch path pathconvert
+syn keyword antElement pathelement patternset permissions prefixlines present presetdef project
+syn keyword antElement property propertyfile propertyref propertyset pvcs pvcsproject record reference
+syn keyword antElement regexp rename renameext replace replacefilter replaceregex replaceregexp
+syn keyword antElement replacestring replacetoken replacetokens replacevalue replyto report resource
+syn keyword antElement revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
+syn keyword antElement setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
+syn keyword antElement sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
+syn keyword antElement stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
+syn keyword antElement striplinecomments style subant substitution support symlink sync sysproperty
+syn keyword antElement syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
+syn keyword antElement targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
+syn keyword antElement to token tokenfilter touch transaction translate triggers trim tstamp type
+syn keyword antElement typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
+syn keyword antElement vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
+syn keyword antElement webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
+syn keyword antElement wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
+syn keyword antElement zipgroupfileset
hi def link antElement Statement
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 8f30ac7c8f..9ce1786fa0 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -151,7 +151,7 @@ bool try_end(Error *err)
if (should_free) {
xfree(msg);
}
- } else if (did_throw) {
+ } else if (did_throw || need_rethrow) {
if (*current_exception->throw_name != NUL) {
if (current_exception->throw_lnum != 0) {
api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 8d9b234bbc..755655856d 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -629,9 +629,9 @@ next_mark:
} else if (item.data.sh.flags & kSHSpellOff) {
spell = kFalse;
}
- }
- if (active && item.data.sh.url != NULL) {
- attr = hl_add_url(attr, item.data.sh.url);
+ if (item.data.sh.url != NULL) {
+ attr = hl_add_url(attr, item.data.sh.url);
+ }
}
if (item.start_row == state->row && item.start_col <= col
&& decor_virt_pos(&item) && item.draw_col == -10) {
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 551d228862..1318eda5eb 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -1612,7 +1612,7 @@ module.cmds = {
},
{
command = 'lua',
- flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK),
addr_type = 'ADDR_LINES',
func = 'ex_lua',
},
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 7c3eb47247..12e746d49e 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -309,6 +309,33 @@ static void msg_verbose_cmd(linenr_T lnum, char *cmd)
no_wait_return--;
}
+static int cmdline_call_depth = 0; ///< recursiveness
+
+/// Start executing an Ex command line.
+///
+/// @return FAIL if too recursive, OK otherwise.
+static int do_cmdline_start(void)
+{
+ assert(cmdline_call_depth >= 0);
+ // It's possible to create an endless loop with ":execute", catch that
+ // here. The value of 200 allows nested function calls, ":source", etc.
+ // Allow 200 or 'maxfuncdepth', whatever is larger.
+ if (cmdline_call_depth >= 200 && cmdline_call_depth >= p_mfd) {
+ return FAIL;
+ }
+ cmdline_call_depth++;
+ start_batch_changes();
+ return OK;
+}
+
+/// End executing an Ex command line.
+static void do_cmdline_end(void)
+{
+ cmdline_call_depth--;
+ assert(cmdline_call_depth >= 0);
+ end_batch_changes();
+}
+
/// Execute a simple command line. Used for translated commands like "*".
int do_cmdline_cmd(const char *cmd)
{
@@ -359,7 +386,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
char *(*cmd_getline)(int, void *, int, bool);
void *cmd_cookie;
struct loop_cookie cmd_loop_cookie;
- static int call_depth = 0; // recursiveness
// For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
// location for storing error messages to be converted to an exception.
@@ -371,10 +397,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
msg_list = &private_msg_list;
private_msg_list = NULL;
- // It's possible to create an endless loop with ":execute", catch that
- // here. The value of 200 allows nested function calls, ":source", etc.
- // Allow 200 or 'maxfuncdepth', whatever is larger.
- if (call_depth >= 200 && call_depth >= p_mfd) {
+ if (do_cmdline_start() == FAIL) {
emsg(_(e_command_too_recursive));
// When converting to an exception, we do not include the command name
// since this is not an error of the specific command.
@@ -382,8 +405,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
msg_list = saved_msg_list;
return FAIL;
}
- call_depth++;
- start_batch_changes();
ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
@@ -884,8 +905,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
did_endif = false; // in case do_cmdline used recursively
- call_depth--;
- end_batch_changes();
+ do_cmdline_end();
return retval;
}
@@ -1669,9 +1689,13 @@ static int execute_cmd0(int *retv, exarg_T *eap, const char **errormsg, bool pre
/// @param preview Execute command preview callback instead of actual command
int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
{
- const char *errormsg = NULL;
int retv = 0;
+ if (do_cmdline_start() == FAIL) {
+ emsg(_(e_command_too_recursive));
+ return retv;
+ }
+ const char *errormsg = NULL;
#undef ERROR
#define ERROR(msg) \
do { \
@@ -1738,9 +1762,12 @@ end:
if (errormsg != NULL && *errormsg != NUL) {
emsg(errormsg);
}
+
// Undo command modifiers
undo_cmdmod(&cmdmod);
cmdmod = save_cmdmod;
+
+ do_cmdline_end();
return retv;
#undef ERROR
}
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index f48cab6739..62e82175c3 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1641,27 +1641,38 @@ bool nlua_is_deferred_safe(void)
return in_fast_callback == 0;
}
-/// Run lua string
+/// Executes Lua code.
///
-/// Used for :lua.
+/// Implements `:lua` and `:lua ={expr}`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:lua {code}`, `:{range}lua`, or `:lua ={expr}` command.
void ex_lua(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
+ // ":{range}lua"
+ if (eap->addr_count > 0 || *eap->arg == NUL) {
+ if (eap->addr_count > 0 && *eap->arg == NUL) {
+ cmd_source_buffer(eap, true);
+ } else {
+ semsg(_(e_invarg2), "exactly one of {chunk} or {range} required");
+ }
+ return;
+ }
+
size_t len;
char *code = script_get(eap, &len);
if (eap->skip || code == NULL) {
xfree(code);
return;
}
- // When =expr is used transform it to vim.print(expr)
+
+ // ":lua {code}", ":={expr}" or ":lua ={expr}"
+ //
+ // When "=expr" is used transform it to "vim.print(expr)".
if (eap->cmdidx == CMD_equal || code[0] == '=') {
size_t off = (eap->cmdidx == CMD_equal) ? 0 : 1;
len += sizeof("vim.print()") - 1 - off;
- // code_buf needs to be 1 char larger then len for null byte in the end.
- // lua nlua_typval_exec doesn't expect null terminated string so len
- // needs to end before null byte.
+ // `nlua_typval_exec` doesn't expect NUL-terminated string so `len` must end before NUL byte.
char *code_buf = xmallocz(len);
vim_snprintf(code_buf, len + 1, "vim.print(%s)", code + off);
xfree(code);
@@ -1673,11 +1684,11 @@ void ex_lua(exarg_T *const eap)
xfree(code);
}
-/// Run lua string for each line in range
+/// Executes Lua code for-each line in a buffer range.
///
-/// Used for :luado.
+/// Implements `:luado`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:luado {code}` command.
void ex_luado(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
@@ -1754,11 +1765,11 @@ void ex_luado(exarg_T *const eap)
redraw_curbuf_later(UPD_NOT_VALID);
}
-/// Run lua file
+/// Executes Lua code from a file location.
///
-/// Used for :luafile.
+/// Implements `:luafile`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:luafile {file}` command.
void ex_luafile(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 3f8e467118..98e9d6c9e6 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -1779,7 +1779,7 @@ freeall:
static void cmd_source(char *fname, exarg_T *eap)
{
if (eap != NULL && *fname == NUL) {
- cmd_source_buffer(eap);
+ cmd_source_buffer(eap, false);
} else if (eap != NULL && eap->forceit) {
// ":source!": read Normal mode commands
// Need to execute the commands directly. This is required at least
@@ -1989,7 +1989,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
return retval;
}
-static void cmd_source_buffer(const exarg_T *const eap)
+void cmd_source_buffer(const exarg_T *const eap, bool ex_lua)
FUNC_ATTR_NONNULL_ALL
{
if (curbuf == NULL) {
@@ -2012,9 +2012,10 @@ static void cmd_source_buffer(const exarg_T *const eap)
.buf = ga.ga_data,
.offset = 0,
};
- if (strequal(curbuf->b_p_ft, "lua")
+ if (ex_lua || strequal(curbuf->b_p_ft, "lua")
|| (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua"))) {
- nlua_source_using_linegetter(get_str_line, (void *)&cookie, ":source (no file)");
+ char *name = ex_lua ? ":{range}lua" : ":source (no file)";
+ nlua_source_using_linegetter(get_str_line, (void *)&cookie, name);
} else {
source_using_linegetter((void *)&cookie, get_str_line, ":source (no file)");
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 00acbfb602..499f31454e 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -93,6 +93,7 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/vim_defs.h"
+#include "nvim/window.h"
typedef struct {
VimState state;
@@ -615,6 +616,8 @@ static int terminal_check(VimState *state)
curbuf->b_locked--;
}
+ may_trigger_win_scrolled_resized();
+
if (need_maketitle) { // Update title in terminal-mode. #7248
maketitle();
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 66d090b0c8..23779d1e7b 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5367,7 +5367,7 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
// Skip floating windows that do not have a snapshot (usually because they are newly-created),
- // as unlike split windows, creating floating windows do not cause other windows to resize.
+ // as unlike split windows, creating floating windows doesn't cause other windows to resize.
if (wp->w_floating && wp->w_last_topline == 0) {
wp->w_last_topline = wp->w_topline;
wp->w_last_topfill = wp->w_topfill;
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 91f61b5053..5cf48412a8 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -399,6 +399,19 @@ describe('API', function()
]],
}
end)
+
+ it('errors properly when command too recursive', function()
+ exec_lua([[
+ _G.success = false
+ vim.api.nvim_create_user_command('Test', function()
+ vim.api.nvim_exec2('Test', {})
+ _G.success = true
+ end, {})
+ ]])
+ pcall_err(command, 'Test')
+ assert_alive()
+ eq(false, exec_lua('return _G.success'))
+ end)
end)
describe('nvim_command', function()
@@ -4560,6 +4573,7 @@ describe('API', function()
line6
]]
end)
+
it('works with count', function()
insert [[
line1
@@ -4577,6 +4591,7 @@ describe('API', function()
line6
]]
end)
+
it('works with register', function()
insert [[
line1
@@ -4599,11 +4614,13 @@ describe('API', function()
line6
]]
end)
+
it('works with bang', function()
api.nvim_create_user_command('Foo', 'echo "<bang>"', { bang = true })
eq('!', api.nvim_cmd({ cmd = 'Foo', bang = true }, { output = true }))
eq('', api.nvim_cmd({ cmd = 'Foo', bang = false }, { output = true }))
end)
+
it('works with modifiers', function()
-- with silent = true output is still captured
eq(
@@ -4659,6 +4676,7 @@ describe('API', function()
feed(':call<CR><CR>')
eq('E471: Argument required', api.nvim_cmd({ cmd = 'messages' }, { output = true }))
end)
+
it('works with magic.file', function()
exec_lua([[
vim.api.nvim_create_user_command("Foo", function(opts)
@@ -4673,6 +4691,7 @@ describe('API', function()
)
)
end)
+
it('splits arguments correctly', function()
exec([[
function! FooFunc(...)
@@ -4695,6 +4714,7 @@ describe('API', function()
)
)
end)
+
it('splits arguments correctly for Lua callback', function()
api.nvim_exec_lua(
[[
@@ -4721,6 +4741,7 @@ describe('API', function()
)
)
end)
+
it('works with buffer names', function()
command('edit foo.txt | edit bar.txt')
api.nvim_cmd({ cmd = 'buffer', args = { 'foo.txt' } }, {})
@@ -4728,6 +4749,7 @@ describe('API', function()
api.nvim_cmd({ cmd = 'buffer', args = { 'bar.txt' } }, {})
eq('bar.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
+
it('triggers CmdUndefined event if command is not found', function()
api.nvim_exec_lua(
[[
@@ -4742,13 +4764,16 @@ describe('API', function()
)
eq('foo', api.nvim_cmd({ cmd = 'Foo' }, { output = true }))
end)
+
it('errors if command is not implemented', function()
eq('Command not implemented: winpos', pcall_err(api.nvim_cmd, { cmd = 'winpos' }, {}))
end)
+
it('works with empty arguments list', function()
api.nvim_cmd({ cmd = 'update' }, {})
api.nvim_cmd({ cmd = 'buffer', count = 0 }, {})
end)
+
it("doesn't suppress errors when used in keymapping", function()
api.nvim_exec_lua(
[[
@@ -4760,6 +4785,7 @@ describe('API', function()
feed('[l')
neq(nil, string.find(eval('v:errmsg'), 'E5108:'))
end)
+
it('handles 0 range #19608', function()
api.nvim_buf_set_lines(0, 0, -1, false, { 'aa' })
api.nvim_cmd({ cmd = 'delete', range = { 0 } }, {})
@@ -4767,12 +4793,14 @@ describe('API', function()
eq({ 'aa' }, api.nvim_buf_get_lines(0, 0, 1, false))
assert_alive()
end)
+
it('supports filename expansion', function()
api.nvim_cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {})
local arg = fn.expand('%:p:h:t')
eq({ arg, arg }, fn.argv())
end)
- it("'make' command works when argument count isn't 1 #19696", function()
+
+ it(":make command works when argument count isn't 1 #19696", function()
command('set makeprg=echo')
command('set shellquote=')
matches('^:!echo ', api.nvim_cmd({ cmd = 'make' }, { output = true }))
@@ -4789,6 +4817,7 @@ describe('API', function()
)
assert_alive()
end)
+
it("doesn't display messages when output=true", function()
local screen = Screen.new(40, 6)
screen:attach()
@@ -4817,31 +4846,37 @@ describe('API', function()
]],
}
end)
+
it('works with non-String args', function()
eq('2', api.nvim_cmd({ cmd = 'echo', args = { 2 } }, { output = true }))
eq('1', api.nvim_cmd({ cmd = 'echo', args = { true } }, { output = true }))
end)
+
describe('first argument as count', function()
it('works', function()
command('vsplit | enew')
api.nvim_cmd({ cmd = 'bdelete', args = { api.nvim_get_current_buf() } }, {})
eq(1, api.nvim_get_current_buf())
end)
+
it('works with :sleep using milliseconds', function()
local start = uv.now()
api.nvim_cmd({ cmd = 'sleep', args = { '100m' } }, {})
ok(uv.now() - start <= 300)
end)
end)
+
it(':call with unknown function does not crash #26289', function()
eq(
'Vim:E117: Unknown function: UnknownFunc',
pcall_err(api.nvim_cmd, { cmd = 'call', args = { 'UnknownFunc()' } }, {})
)
end)
+
it(':throw does not crash #24556', function()
eq('42', pcall_err(api.nvim_cmd, { cmd = 'throw', args = { '42' } }, {}))
end)
+
it('can use :return #24556', function()
exec([[
func Foo()
@@ -4854,5 +4889,18 @@ describe('API', function()
eq('before', api.nvim_get_var('pos'))
eq({ 1, 2, 3 }, api.nvim_get_var('result'))
end)
+
+ it('errors properly when command too recursive #27210', function()
+ exec_lua([[
+ _G.success = false
+ vim.api.nvim_create_user_command('Test', function()
+ vim.api.nvim_cmd({ cmd = 'Test' }, {})
+ _G.success = true
+ end, {})
+ ]])
+ pcall_err(command, 'Test')
+ assert_alive()
+ eq(false, exec_lua('return _G.success'))
+ end)
end)
end)
diff --git a/test/functional/autocmd/win_scrolled_resized_spec.lua b/test/functional/autocmd/win_scrolled_resized_spec.lua
index c2a534ab27..d40dc37103 100644
--- a/test/functional/autocmd/win_scrolled_resized_spec.lua
+++ b/test/functional/autocmd/win_scrolled_resized_spec.lua
@@ -39,6 +39,23 @@ describe('WinResized', function()
eq(2, eval('g:resized'))
eq({ windows = { 1002, 1001, 1000 } }, eval('g:v_event'))
end)
+
+ it('is triggered in terminal mode #21197 #27207', function()
+ exec([[
+ autocmd TermOpen * startinsert
+ let g:resized = 0
+ autocmd WinResized * let g:resized += 1
+ ]])
+ eq(0, eval('g:resized'))
+
+ command('vsplit term://')
+ eq({ mode = 't', blocking = false }, api.nvim_get_mode())
+ eq(1, eval('g:resized'))
+
+ command('split')
+ eq({ mode = 't', blocking = false }, api.nvim_get_mode())
+ eq(2, eval('g:resized'))
+ end)
end)
describe('WinScrolled', function()
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index 28a99a86f8..b759d0e2c4 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -22,7 +22,7 @@ local remove_trace = helpers.remove_trace
before_each(clear)
-describe(':lua command', function()
+describe(':lua', function()
it('works', function()
eq('', exec_capture('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})'))
eq({ '', 'TEST' }, api.nvim_buf_get_lines(0, 0, 100, false))
@@ -54,7 +54,14 @@ describe(':lua command', function()
)
)
end)
+
it('throws catchable errors', function()
+ for _, cmd in ipairs({ 'lua', '1lua chunk' }) do
+ eq(
+ 'Vim(lua):E475: Invalid argument: exactly one of {chunk} or {range} required',
+ pcall_err(command, cmd)
+ )
+ end
eq(
[[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']],
pcall_err(command, 'lua ()')
@@ -69,9 +76,11 @@ describe(':lua command', function()
)
eq({ '' }, api.nvim_buf_get_lines(0, 0, 100, false))
end)
+
it('works with NULL errors', function()
eq([=[Vim(lua):E5108: Error executing lua [NULL]]=], exc_exec('lua error(nil)'))
end)
+
it('accepts embedded NLs without heredoc', function()
-- Such code is usually used for `:execute 'lua' {generated_string}`:
-- heredocs do not work in this case.
@@ -83,12 +92,14 @@ describe(':lua command', function()
]])
eq({ '', 'ETTS', 'TTSE', 'STTE' }, api.nvim_buf_get_lines(0, 0, 100, false))
end)
+
it('preserves global and not preserves local variables', function()
eq('', exec_capture('lua gvar = 42'))
eq('', exec_capture('lua local lvar = 100500'))
eq(NIL, fn.luaeval('lvar'))
eq(42, fn.luaeval('gvar'))
end)
+
it('works with long strings', function()
local s = ('x'):rep(100500)
@@ -192,6 +203,34 @@ describe(':lua command', function()
exec_capture('=x(false)')
)
end)
+
+ it('with range', function()
+ local screen = Screen.new(40, 10)
+ screen:attach()
+ api.nvim_buf_set_lines(0, 0, 0, 0, { 'nonsense', 'function x() print "hello" end', 'x()' })
+
+ -- ":{range}lua" fails on invalid Lua code.
+ eq(
+ [[:{range}lua: Vim(lua):E5107: Error loading lua [string ":{range}lua"]:0: '=' expected near '<eof>']],
+ pcall_err(command, '1lua')
+ )
+
+ -- ":{range}lua" executes valid Lua code.
+ feed(':2,3lua<CR>')
+ screen:expect {
+ grid = [[
+ nonsense |
+ function x() print "hello" end |
+ x() |
+ ^ |
+ {1:~ }|*5
+ hello |
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ },
+ }
+ end)
end)
describe(':luado command', function()
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 5bfc7efbb3..06285d91b5 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -8,7 +8,6 @@ local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
-local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
local clear = helpers.clear
local command = helpers.command
@@ -2810,17 +2809,13 @@ end)
describe('TUI bg color', function()
before_each(clear)
- local attr_ids = {
- [1] = { reverse = true },
- [2] = { bold = true },
- [3] = { reverse = true, bold = true },
- [4] = { foreground = tonumber('0x00000a') },
- }
-
it('is properly set in a nested Nvim instance when background=dark', function()
command('highlight clear Normal')
command('set background=dark') -- set outer Nvim background
+ local child_server = new_pipename()
local screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
'-u',
'NONE',
'-i',
@@ -2830,26 +2825,20 @@ describe('TUI bg color', function()
'--cmd',
'set noswapfile',
})
- screen:set_default_attr_ids(attr_ids)
- retry(nil, 30000, function() -- wait for automatic background processing
- screen:sleep(20)
- feed_command('set background?') -- check nested Nvim background
- screen:expect([[
- {1: } |
- {2:~} |
- {2:~} |
- {2:~} |
- {3:[No Name] 0,0-1 All}|
- background=dark |
- {4:-- TERMINAL --} |
- ]])
+ screen:expect({ any = '%[No Name%]' })
+ local child_session = helpers.connect(child_server)
+ retry(nil, nil, function()
+ eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') })
end)
end)
it('is properly set in a nested Nvim instance when background=light', function()
command('highlight clear Normal')
command('set background=light') -- set outer Nvim background
+ local child_server = new_pipename()
local screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
'-u',
'NONE',
'-i',
@@ -2859,18 +2848,10 @@ describe('TUI bg color', function()
'--cmd',
'set noswapfile',
})
- retry(nil, 30000, function() -- wait for automatic background processing
- screen:sleep(20)
- feed_command('set background?') -- check nested Nvim background
- screen:expect([[
- {1: } |
- {3:~} |
- {3:~} |
- {3:~} |
- {5:[No Name] 0,0-1 All}|
- background=light |
- {3:-- TERMINAL --} |
- ]])
+ screen:expect({ any = '%[No Name%]' })
+ local child_session = helpers.connect(child_server)
+ retry(nil, nil, function()
+ eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') })
end)
end)
@@ -2914,18 +2895,13 @@ describe('TUI bg color', function()
'-c',
'autocmd OptionSet background echo "did OptionSet, yay!"',
})
- retry(nil, 30000, function() -- wait for automatic background processing
- screen:sleep(20)
- screen:expect([[
+ screen:expect([[
{1: } |
- {3:~} |
- {3:~} |
- {3:~} |
+ {3:~} |*3
{5:[No Name] 0,0-1 All}|
did OptionSet, yay! |
{3:-- TERMINAL --} |
- ]])
- end)
+ ]])
end)
end)
diff --git a/test/functional/treesitter/fold_spec.lua b/test/functional/treesitter/fold_spec.lua
index ac9d227bb6..9428432f66 100644
--- a/test/functional/treesitter/fold_spec.lua
+++ b/test/functional/treesitter/fold_spec.lua
@@ -675,126 +675,3 @@ t2]])
}
end)
end)
-
-describe('treesitter foldtext', function()
- local test_text = [[
-void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
-{
- int width = INT_MAX, height = INT_MAX;
- bool ext_widgets[kUIExtCount];
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
- ext_widgets[i] = true;
- }
-
- bool inclusive = ui_override();
- for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
- width = MIN(ui->width, width);
- height = MIN(ui->height, height);
- foo = BAR(ui->bazaar, bazaar);
- for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
- }
- }
-}]]
- local screen
-
- before_each(function()
- screen = Screen.new(60, 5)
- screen:set_default_attr_ids({
- [0] = { foreground = Screen.colors.Blue, bold = true },
- [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
- [2] = {
- bold = true,
- background = Screen.colors.LightGray,
- foreground = Screen.colors.SeaGreen,
- },
- [3] = { foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGray },
- [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGray },
- [5] = { bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.Brown },
- [6] = { background = Screen.colors.Red1 },
- [7] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Red },
- [8] = { foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red },
- [9] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Red },
- [10] = { bold = true },
- })
- screen:attach()
- end)
-
- it('displays highlighted content', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
- insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
-
- feed('ggVGzf')
- screen:expect {
- grid = [[
- {4:^void}{1: }{3:qsort}{4:(void}{1: }{5:*}{3:base}{4:,}{1: }{4:size_t}{1: }{3:nel}{4:,}{1: }{4:size_t}{1: }{3:width}{4:,}{1: }{4:int}{1: }{4:(}{5:*}{3:compa}|
- {0:~ }|*3
- |
- ]],
- }
- end)
-
- it('handles deep nested captures', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
- insert([[
-function FoldInfo.new()
- return setmetatable({
- start_counts = {},
- stop_counts = {},
- levels0 = {},
- levels = {},
- }, FoldInfo)
-end]])
- exec_lua([[vim.treesitter.get_parser(0, "lua")]])
-
- feed('ggjVGkzfgg')
- screen:expect {
- grid = [[
- ^function FoldInfo.new() |
- {1: }{5:return}{1: }{4:setmetatable({}{1:·····································}|
- end |
- {0:~ }|
- |
- ]],
- }
-
- command('hi! Visual guibg=Red')
- feed('GVgg')
- screen:expect {
- grid = [[
- ^f{6:unction FoldInfo.new()} |
- {7: }{8:return}{7: }{9:setmetatable({}{7:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL LINE --} |
- ]],
- }
-
- feed('10l<C-V>')
- screen:expect {
- grid = [[
- {6:function F}^oldInfo.new() |
- {7: }{8:return}{7: }{9:se}{4:tmetatable({}{1:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL BLOCK --} |
- ]],
- }
- end)
-
- it('falls back to default', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext()]])
- insert(test_text)
-
- feed('ggVGzf')
- screen:expect {
- grid = [[
- {1:^+-- 19 lines: void qsort(void *base, size_t nel, size_t widt}|
- {0:~ }|*3
- |
- ]],
- }
- end)
-end)