Compare commits

..

22 Commits

Author SHA1 Message Date
marvim
d2f00055be docs: update version.c 2025-09-08 03:25:39 +00:00
zeertzjq
da78772328 test(lsp): fix flakiness in inline completion test (#35676)
The flakiness happens because get() uses vim.schedule(), and a following
key may be processed before the scheduled event. Use poke_eventloop() to
ensure that the scheduled event is processed.
2025-09-08 02:54:57 +00:00
zeertzjq
f0bf6d7647 Merge pull request #35673 from zeertzjq/vim-9.1.1676
vim-patch: cmdline completion fixes
2025-09-08 10:38:37 +08:00
zeertzjq
bea87b4a9e test: add tests for #20348 2025-09-08 09:24:13 +08:00
zeertzjq
18f24b85c3 vim-patch:9.1.1740: Memory leak with wildmode=longest,full and wildoptions=pum
Problem:  Memory leak with wildmode=longest,full and wildoptions=pum
          (after 9.1.1737).
Solution: Avoid using showmatches() and WILD_NEXT together.  Also fix
          wildmode=longest,noselect:full selecting wrong item
          (zeertzjq).

fixes: vim/vim#18228
closes: vim/vim#18229

c7f235bd43
2025-09-08 09:02:37 +08:00
zeertzjq
d784ed7013 vim-patch:9.1.1739: Matches may be listed twice with wildmode=longest,list
Problem:  Matches may be listed twice with wildmode=longest,list when
          "longest" doesn't change command line (after 9.1.1737).
Solution: Set did_wild_list when trying "list" after "longest"
          (zeertzjq).

closes: vim/vim#18227

a28a2eb9d9
2025-09-08 09:02:37 +08:00
zeertzjq
f2bda1effc vim-patch:9.1.1737: Patch v9.1.1714 introduce a regression for wildmenu
Problem:  Patch v9.1.1714 introduce a regression for wildmenu (zeertzjq)
Solution: Restore behavior of "longest" in 'wildmode' (Girish Palya)

- Fixed a regression caused by PR vim/vim#18125 selecting wrong item
- Fixed another regression where the first pasted text did not appear on
  the command-line after starting Vim.

closes: vim/vim#18212

8fec92d631

Co-authored-by: Girish Palya <girishji@gmail.com>
2025-09-08 09:02:37 +08:00
zeertzjq
1359578abb vim-patch:9.1.1714: completion: wildmode=longest:full selects wrong item
Problem:  completion: wildmode=longest:full selects wrong item
          (zeertzjq)
Solution: Fix issue, refactor ex_getln.c slightly
          (Girish Palya)

fixes: vim/vim#18102
closes: vim/vim#18125

2eccb4d0be

Co-authored-by: Girish Palya <girishji@gmail.com>
2025-09-08 09:02:37 +08:00
zeertzjq
3b5337ab6c vim-patch:9.1.1676: completion: long line shown twice
Problem:  completion: long line shown twice
          (Maxim Kim)
Solution: Fix the issue, disable an incorrect test.
          (Girish Palya)

fixes: vim/vim#18035
closes: vim/vim#18088

57379302aa

Omit removal of blank line in Test_noselect_expand_env_var() as it's
added again in patch 9.1.1682.
Cherry-pick two blank lines in Test_long_line_noselect() from patch
9.1.1682.

Co-authored-by: Girish Palya <girishji@gmail.com>
2025-09-08 09:02:37 +08:00
zeertzjq
a16064ff29 vim-patch:partial:9.1.1639: completion: popup may be misplaced
Problem:  During commandline completiom, popup window placement can be
          incorrect when 'noselect' is present in 'wildmode'
          (Shane-XB-Qian)
Solution: Disable "showtail" feature when 'noselect' is present.

fixes: vim/vim#17969
closes: vim/vim#18001

1e38198a41

Partial port excluding the showtail change and the test.

Co-authored-by: Girish Palya <girishji@gmail.com>
2025-09-08 09:02:36 +08:00
skewb1k
ad22d0ace9 fix(cjson): fix strbuf_set_length incorrectness #35565
`strbuf_set_length` was incorrectly updating
length with `+=` instead of assignment.

Also syncs minor updates with upstream.
2025-09-07 15:45:34 -07:00
Evgeni Chasnovski
0c49167490 docs: adjust *lua-plugin-init* wording #35600
Problem: Unnecessarily anecdotal wording.

Solution: Adjust wording while delivering the same message.
2025-09-07 15:04:09 -07:00
Evgeni Chasnovski
fa3920282d fix(pack): handle Git environment variables #35626
Problem: Some environment variables which are useful when working inside
  a bare repository can affect any Git operation.

Solution: Explicitly unset problematic environment variables.
2025-09-07 14:42:09 -07:00
skewb1k
448f15ca39 feat(json): pretty-format (indent) with vim.json.encode() #35424
Problem:
There is no straightforward way to pretty-print objects as JSON.
The existing `vim.inspect` outputs LON.

Solution:
Introduce an `indent` option for `vim.json.encode()` which enables
human-readable output with configurable indentation.

Adapts PR to upstream: openresty/lua-cjson#114
2025-09-07 14:38:27 -07:00
glepnir
2b156be19c refactor(api): redundant w_pos_changed assignment #35663
Problem: w_pos_changed flag was being set redundantly after win_config_float call

Solution: remove duplicate assignment since win_config_float already sets this flag internally
2025-09-07 10:11:32 -07:00
Evgeni Chasnovski
7853cde29a feat(pack): vim.pack.get() gets VCS info #35631
Problem:
Force resolve `spec.version` overrides the information about whether
a user supplied `version` or not. Knowing it might be useful in some use
cases (like comparing to previously set `spec` to detect if it has
changed).

Solution:
Do not resolve `spec.version`. This also improves speed when triggering
events and calling `get()`.
- Place default branch first when listing all branches.
- Use correct terminology in `get_hash` helper.
- Do not return `{ '' }` if there are no tags.

Problem:
There is no way to get more information about installed plugins, like
current revision or default branch (necessary if resolving default
`spec.version` manually). As computing Git data migth take some time,
also allow `get()` to limit output to only necessary set of plugins.

Solution:
- introduce arguments to `get(names, opts)`, which follows other
  `vim.pack` functions. Plugin extra info is returned by default and
  should be opt-out via `opts.info = false`.
  - Examples:
    - Get current revision: `get({ 'plug-name' })[1].rev`
    - Get default branch: `get({ 'plug_name' })[1].branches[1]`
- `update()` and `del()` act on plugins in the same order their names
  are supplied. This is less surprising.
- default `opts.info` to `true` since this simplifies logic for the
  common user, while still leaving the door open for a faster `get()` if
  needed.
2025-09-07 09:59:31 -07:00
github-actions[bot]
fd59e72b47 docs: update version.c #35576
vim-patch:8.1.1919: using window options when passing a buffer to popup_create()
vim-patch:8.1.1954: more functions can be used as a method
vim-patch:8.1.1982: more functions can be used as methods
vim-patch:8.1.1986: more functions can be used as methods
vim-patch:8.1.1987: more functions can be used as methods
vim-patch:8.1.1993: more functions can be used as methods
vim-patch:8.1.1996: more functions can be used as methods
vim-patch:8.1.2004: more functions can be used as methods
vim-patch:8.1.2295: if buffer of popup is in another window cursorline sign shows

vim-patch:8.2.0568: the man filetype plugin overwrites the unnamed register
vim-patch:8.2.1186: with SGR mouse codes balloon doesn't show up after click
vim-patch:8.2.3539: GTK3: with 'rightleft' set scrollbar may move unintentionally
vim-patch:8.2.3681: cannot drag popup window after click on a status line
vim-patch:8.2.4561: build failure with some combination of features
vim-patch:8.2.4984: dragging statusline fails for window with winbar

vim-patch:9.0.0136: after CTRL-Left-mouse click a mouse scroll also has CTRL
vim-patch:9.0.0696: it is unclear if the +rightleft and +arabic features are used
vim-patch:9.0.0931: MS-Windows: mouse column limited to 223
vim-patch:9.0.1896: "below" virtual text doesn't work with 'rightleft'
2025-09-07 09:36:52 -07:00
zeertzjq
5f23ce732d Merge pull request #35664 from zeertzjq/vim-efb913a
vim-patch: runtime file updates
2025-09-07 22:00:54 +08:00
zeertzjq
4521f6da7d vim-patch:1ed2ff7: runtime(m4): Remove m4Type and leftover m4Function in syntax script
closes: vim/vim#18223

1ed2ff77d8

Co-authored-by: Damien Lejay <damien@lejay.be>
2025-09-07 21:22:52 +08:00
zeertzjq
91fa613fad vim-patch:6505dc6: runtime(nu): Add new Nushell runtime files
See: https://github.com/elkasztano/nushell-syntax-vim

Thanks to Pete Cruz (@Petesta) for promoting this addition.

closes: vim/vim#18208

6505dc69d3

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2025-09-07 21:22:12 +08:00
zeertzjq
30dc9934a6 vim-patch:efb913a: runtime(m4): Remove m4Function
closes: vim/vim#18211

efb913a4f5

Co-authored-by: Damien Lejay <damien@lejay.be>
2025-09-07 21:21:33 +08:00
Christian Clason
13b04207f1 build(deps): bump tree-sitter-query to v0.7.0 2025-09-07 12:51:46 +02:00
29 changed files with 1662 additions and 346 deletions

View File

@@ -61,8 +61,8 @@
.hash = "N-V-__8AAI4YCgD7OqxCEAmz2RqT_ohl6eA4F0fGMtLIe7nb", .hash = "N-V-__8AAI4YCgD7OqxCEAmz2RqT_ohl6eA4F0fGMtLIe7nb",
}, },
.treesitter_query = .{ .treesitter_query = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.6.2#8a43889f89fd0667289936341bff3a77bafade17", .url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.7.0#60e253d3c9d6b1131a0f75c85e4bdcc9a48d5b42",
.hash = "N-V-__8AAARLBACBLGiXGFTijEzLv8AwiqT_kJpmVjir1BgX", .hash = "N-V-__8AAGNUBAAvnkA99VqpVeC-dHymIp78MhFEixP8w7Tj",
}, },
}, },
.paths = .{ .paths = .{

View File

@@ -42,8 +42,8 @@ TREESITTER_VIM_URL https://github.com/tree-sitter-grammars/tree-sitter-vim/archi
TREESITTER_VIM_SHA256 44eabc31127c4feacda19f2a05a5788272128ff561ce01093a8b7a53aadcc7b2 TREESITTER_VIM_SHA256 44eabc31127c4feacda19f2a05a5788272128ff561ce01093a8b7a53aadcc7b2
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v4.0.0.tar.gz TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v4.0.0.tar.gz
TREESITTER_VIMDOC_SHA256 8096794c0f090b2d74b7bff94548ac1be3285b929ec74f839bd9b3ff4f4c6a0b TREESITTER_VIMDOC_SHA256 8096794c0f090b2d74b7bff94548ac1be3285b929ec74f839bd9b3ff4f4c6a0b
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.6.2.tar.gz TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.7.0.tar.gz
TREESITTER_QUERY_SHA256 90682e128d048fbf2a2a17edca947db71e326fa0b3dba4136e041e096538b4eb TREESITTER_QUERY_SHA256 79285847e8350ee9fe1f6f6c9eb64bc14320f70f7b9b65037193fc58f2638613
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.5.0.tar.gz TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.5.0.tar.gz
TREESITTER_MARKDOWN_SHA256 14c2c948ccf0e9b606eec39b09286c59dddf28307849f71b7ce2b1d1ef06937e TREESITTER_MARKDOWN_SHA256 14c2c948ccf0e9b606eec39b09286c59dddf28307849f71b7ce2b1d1ef06937e
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.9.tar.gz TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.9.tar.gz

View File

@@ -121,18 +121,8 @@ In the user's config:
============================================================================== ==============================================================================
Initialization *lua-plugin-init* Initialization *lua-plugin-init*
Newcomers to Lua plugin development will often put all initialization logic in
a single `setup` function, which takes a table of options.
If you do this, users will be forced to call this function in order to use
your plugin, even if they are happy with the default configuration.
Strictly separated configuration and smart initialization allow your plugin to Strictly separated configuration and smart initialization allow your plugin to
work out of the box. work out of the box. Common approaches are:
NOTE: A well designed plugin has minimal impact on startup time. See also
|lua-plugin-lazy|.
Common approaches to a strictly separated configuration are:
- A Lua function, e.g. `setup(opts)` or `configure(opts)`, which only overrides the - A Lua function, e.g. `setup(opts)` or `configure(opts)`, which only overrides the
default configuration and does not contain any initialization logic. default configuration and does not contain any initialization logic.
@@ -143,6 +133,22 @@ Common approaches to a strictly separated configuration are:
Typically, automatic initialization logic is done in a |plugin| or |ftplugin| Typically, automatic initialization logic is done in a |plugin| or |ftplugin|
script. See also |'runtimepath'|. script. See also |'runtimepath'|.
On the other hand, a single `setup(opts)` that combines configuration and
initialization may be useful in specific cases:
- Customizing complex initialization, where there is a significant risk of
misconfiguration.
- Requiring users to opt in for plugin functionality that should not be
initialized automatically.
Keep in mind that this approach requires users to call `setup` in order to
use your plugin, even if the default configuration is enough for them.
Consider carefully whether your plugin benefits from combined `setup()` pattern
before adopting it.
NOTE: A well designed plugin has minimal impact on startup time. See also
|lua-plugin-lazy|.
============================================================================== ==============================================================================
Lazy loading *lua-plugin-lazy* Lazy loading *lua-plugin-lazy*

View File

@@ -3372,6 +3372,9 @@ vim.json.encode({obj}, {opts}) *vim.json.encode()*
• {opts} (`table<string,any>?`) Options table with keys: • {opts} (`table<string,any>?`) Options table with keys:
• escape_slash: (boolean) (default false) Escape slash • escape_slash: (boolean) (default false) Escape slash
characters "/" in string values. characters "/" in string values.
• indent: (string) (default "") String used for indentation at
each nesting level. If non-empty enables newlines and a
space after colons.
Return: ~ Return: ~
(`string`) (`string`)

View File

@@ -262,6 +262,7 @@ LUA
• |vim.list.unique()| to deduplicate lists. • |vim.list.unique()| to deduplicate lists.
• |vim.list.bisect()| for binary search. • |vim.list.bisect()| for binary search.
• Experimental `vim.pos` and `vim.range` for Position/Range abstraction. • Experimental `vim.pos` and `vim.range` for Position/Range abstraction.
• |vim.json.encode()| has an `indent` option for pretty-formatting.
OPTIONS OPTIONS

View File

@@ -271,9 +271,8 @@ Switch plugin's version:
run |vim.pack.update()|. run |vim.pack.update()|.
Freeze plugin from being updated: Freeze plugin from being updated:
• Update 'init.lua' for plugin to have `version` set to current commit hash. • Update 'init.lua' for plugin to have `version` set to current revision. Get
You can get it by running `vim.pack.update({ 'plugin-name' })` and yanking it with `:=vim.pack.get({ 'plug-name' })[1].rev` (looks like `abc12345`).
the word describing current state (looks like `abc12345`).
• |:restart|. • |:restart|.
Unfreeze plugin to start receiving updates: Unfreeze plugin to start receiving updates:
@@ -355,16 +354,27 @@ del({names}) *vim.pack.del()*
be managed by |vim.pack|, not necessarily already added to be managed by |vim.pack|, not necessarily already added to
current session. current session.
get() *vim.pack.get()* get({names}, {opts}) *vim.pack.get()*
Get data about all plugins managed by |vim.pack| Gets |vim.pack| plugin info, optionally filtered by `names`.
Parameters: ~
• {names} (`string[]?`) List of plugin names. Default: all plugins
managed by |vim.pack|.
• {opts} (`table?`) A table with the following fields:
• {info} (`boolean`) Whether to include extra plugin info.
Default `true`.
Return: ~ Return: ~
(`table[]`) A list of objects with the following fields: (`table[]`) A list of objects with the following fields:
• {spec} (`vim.pack.SpecResolved`) A |vim.pack.Spec| with defaults
made explicit.
• {path} (`string`) Plugin's path on disk.
• {active} (`boolean`) Whether plugin was added via |vim.pack.add()| • {active} (`boolean`) Whether plugin was added via |vim.pack.add()|
to current session. to current session.
• {branches}? (`string[]`) Available Git branches (first is default).
Missing if `info=false`.
• {path} (`string`) Plugin's path on disk.
• {rev}? (`string`) Current Git revision. Missing if `info=false`.
• {spec} (`vim.pack.SpecResolved`) A |vim.pack.Spec| with resolved
`name`.
• {tags}? (`string[]`) Available Git tags. Missing if `info=false`.
update({names}, {opts}) *vim.pack.update()* update({names}, {opts}) *vim.pack.update()*
Update plugins Update plugins

View File

@@ -1,13 +1,17 @@
" Vim filetype plugin " Vim filetype plugin
" Language: Nu " Language: Nushell
" Maintainer: Marc Jakobi <marc@jakobi.dev> " Maintainer: El Kasztano
" Last Change: 2024 Aug 31 " URL: https://github.com/elkasztano/nushell-syntax-vim
" License: MIT <https://opensource.org/license/mit>
" Last Change: 2025 Sep 05
if exists('b:did_ftplugin') if exists("b:did_ftplugin")
finish finish
endif endif
let b:did_ftplugin = 1 let b:did_ftplugin = 1
setlocal commentstring=#\ %s setlocal commentstring=#\ %s
setlocal comments-=://
setlocal formatoptions=tcroql
let b:undo_ftplugin = 'setl com<' let b:undo_ftplugin = "setl fo< cms< com<"

54
runtime/indent/nu.vim Normal file
View File

@@ -0,0 +1,54 @@
" Vim indent file
" Language: Nushell
" Maintainer: El Kasztano
" URL: https://github.com/elkasztano/nushell-syntax-vim
" License: MIT <https://opensource.org/license/mit>
" Last Change: 2025 Sep 05
" Only load if no other indent file is loaded
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal cindent
setlocal cinoptions=L0,(s,Ws,J1,j1,+0,f5,m1,i0
setlocal cinkeys=0{,0},!^F,o,O,0[,0],0),0#
setlocal autoindent
setlocal indentkeys=0{,0},!^F,o,O,0[,0],0),0#
setlocal shiftwidth=2
setlocal softtabstop=2
setlocal expandtab
setlocal indentexpr=GetNuIndent(v:lnum)
let b:undo_indent = "setl ai< cin< cink< cino< et< inde< indk< sts< sw<"
" only define once
if exists("*GetNuIndent")
finish
endif
let s:save_cpo = &cpo
set cpo&vim
function GetNuIndent(lnum)
let prevlnum = prevnonblank(v:lnum - 1) "get number of last non blank line
let line = getline(a:lnum)
let synname = synIDattr(synID(a:lnum, 1, 1), "name")
if (synname == "nuString") || (synname == "nuComment")
return -1
endif
if getline(prevlnum) =~ '\%(^.*[$\|^.*[\s*#.*$\)'
return (prevlnum > 0) * indent(prevlnum) + shiftwidth()
endif
if getline(v:lnum) =~ "^\s*]\>"
return (prevlnum > 0) * indent(prevlnum) - shiftwidth()
endif
return cindent(a:lnum)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -38,5 +38,7 @@ function vim.json.decode(str, opts) end
---@param opts? table<string,any> Options table with keys: ---@param opts? table<string,any> Options table with keys:
--- - escape_slash: (boolean) (default false) Escape slash --- - escape_slash: (boolean) (default false) Escape slash
--- characters "/" in string values. --- characters "/" in string values.
--- - indent: (string) (default "") String used for indentation at each nesting level.
--- If non-empty enables newlines and a space after colons.
---@return string ---@return string
function vim.json.encode(obj, opts) end function vim.json.encode(obj, opts) end

View File

@@ -68,9 +68,8 @@
---you run |vim.pack.update()|. ---you run |vim.pack.update()|.
--- ---
---Freeze plugin from being updated: ---Freeze plugin from being updated:
---- Update 'init.lua' for plugin to have `version` set to current commit hash. ---- Update 'init.lua' for plugin to have `version` set to current revision.
---You can get it by running `vim.pack.update({ 'plugin-name' })` and yanking ---Get it with `:=vim.pack.get({ 'plug-name' })[1].rev` (looks like `abc12345`).
---the word describing current state (looks like `abc12345`).
---- |:restart|. ---- |:restart|.
--- ---
---Unfreeze plugin to start receiving updates: ---Unfreeze plugin to start receiving updates:
@@ -108,7 +107,9 @@ local M = {}
local function git_cmd(cmd, cwd) local function git_cmd(cmd, cwd)
-- Use '-c gc.auto=0' to disable `stderr` "Auto packing..." messages -- Use '-c gc.auto=0' to disable `stderr` "Auto packing..." messages
cmd = vim.list_extend({ 'git', '-c', 'gc.auto=0' }, cmd) cmd = vim.list_extend({ 'git', '-c', 'gc.auto=0' }, cmd)
local sys_opts = { cwd = cwd, text = true, clear_env = true } local env = vim.fn.environ() --- @type table<string,string>
env.GIT_DIR, env.GIT_WORK_TREE = nil, nil
local sys_opts = { cwd = cwd, text = true, env = env, clear_env = true }
local out = async.await(3, vim.system, cmd, sys_opts) --- @type vim.SystemCompleted local out = async.await(3, vim.system, cmd, sys_opts) --- @type vim.SystemCompleted
async.await(1, vim.schedule) async.await(1, vim.schedule)
if out.code ~= 0 then if out.code ~= 0 then
@@ -148,13 +149,13 @@ local function git_clone(url, path)
end end
--- @async --- @async
--- @param rev string --- @param ref string
--- @param cwd string --- @param cwd string
--- @return string --- @return string
local function git_get_hash(rev, cwd) local function git_get_hash(ref, cwd)
-- Using `rev-list -1` shows a commit of revision, while `rev-parse` shows -- Using `rev-list -1` shows a commit of reference, while `rev-parse` shows
-- hash of revision. Those are different for annotated tags. -- hash of reference. Those are different for annotated tags.
return git_cmd({ 'rev-list', '-1', '--abbrev-commit', rev }, cwd) return git_cmd({ 'rev-list', '-1', '--abbrev-commit', ref }, cwd)
end end
--- @async --- @async
@@ -169,11 +170,14 @@ end
--- @param cwd string --- @param cwd string
--- @return string[] --- @return string[]
local function git_get_branches(cwd) local function git_get_branches(cwd)
local def_branch = git_get_default_branch(cwd)
local cmd = { 'branch', '--remote', '--list', '--format=%(refname:short)', '--', 'origin/**' } local cmd = { 'branch', '--remote', '--list', '--format=%(refname:short)', '--', 'origin/**' }
local stdout = git_cmd(cmd, cwd) local stdout = git_cmd(cmd, cwd)
local res = {} --- @type string[] local res = {} --- @type string[]
for l in vim.gsplit(stdout, '\n') do for l in vim.gsplit(stdout, '\n') do
res[#res + 1] = l:match('^origin/(.+)$') local branch = l:match('^origin/(.+)$')
local pos = branch == def_branch and 1 or (#res + 1)
table.insert(res, pos, branch)
end end
return res return res
end end
@@ -182,8 +186,8 @@ end
--- @param cwd string --- @param cwd string
--- @return string[] --- @return string[]
local function git_get_tags(cwd) local function git_get_tags(cwd)
local cmd = { 'tag', '--list', '--sort=-v:refname' } local tags = git_cmd({ 'tag', '--list', '--sort=-v:refname' }, cwd)
return vim.split(git_cmd(cmd, cwd), '\n') return tags == '' and {} or vim.split(tags, '\n')
end end
-- Plugin operations ---------------------------------------------------------- -- Plugin operations ----------------------------------------------------------
@@ -323,34 +327,22 @@ local function normalize_plugs(plugs)
return res return res
end end
--- @param names string[]? --- @param names? string[]
--- @return vim.pack.Plug[] --- @return vim.pack.Plug[]
local function plug_list_from_names(names) local function plug_list_from_names(names)
local all_plugins = M.get() local p_data_list = M.get(names, { info = false })
local plug_dir = get_plug_dir() local plug_dir = get_plug_dir()
local plugs = {} --- @type vim.pack.Plug[] local plugs = {} --- @type vim.pack.Plug[]
local used_names = {} --- @type table<string,boolean> for _, p_data in ipairs(p_data_list) do
-- Preserve plugin order; might be important during checkout or event trigger
for _, p_data in ipairs(all_plugins) do
-- NOTE: By default include only active plugins (and not all on disk). Using -- NOTE: By default include only active plugins (and not all on disk). Using
-- not active plugins might lead to a confusion as default `version` and -- not active plugins might lead to a confusion as default `version` and
-- user's desired one might mismatch. -- user's desired one might mismatch.
-- TODO(echasnovski): Consider changing this if/when there is lockfile. -- TODO(echasnovski): Change this when there is lockfile.
--- @cast names string[] if names ~= nil or p_data.active then
if (not names and p_data.active) or vim.tbl_contains(names or {}, p_data.spec.name) then
plugs[#plugs + 1] = new_plug(p_data.spec, plug_dir) plugs[#plugs + 1] = new_plug(p_data.spec, plug_dir)
used_names[p_data.spec.name] = true
end end
end end
if vim.islist(names) and #plugs ~= #names then
--- @param n string
local unused = vim.tbl_filter(function(n)
return not used_names[n]
end, names)
error('The following plugins are not installed: ' .. table.concat(unused, ', '))
end
return plugs return plugs
end end
@@ -358,13 +350,7 @@ end
--- @param event_name 'PackChangedPre'|'PackChanged' --- @param event_name 'PackChangedPre'|'PackChanged'
--- @param kind 'install'|'update'|'delete' --- @param kind 'install'|'update'|'delete'
local function trigger_event(p, event_name, kind) local function trigger_event(p, event_name, kind)
local spec = vim.deepcopy(p.spec) local data = { kind = kind, spec = vim.deepcopy(p.spec), path = p.path }
-- Infer default branch for fuller `event-data` (if possible)
-- Doing it only on event trigger level allows keeping `spec` close to what
-- user supplied without performance issues during startup.
spec.version = spec.version or (uv.fs_stat(p.path) and git_get_default_branch(p.path))
local data = { kind = kind, spec = spec, path = p.path }
api.nvim_exec_autocmds(event_name, { pattern = p.path, data = data }) api.nvim_exec_autocmds(event_name, { pattern = p.path, data = data })
end end
@@ -463,7 +449,7 @@ end
--- @param p vim.pack.Plug --- @param p vim.pack.Plug
local function resolve_version(p) local function resolve_version(p)
local function list_in_line(name, list) local function list_in_line(name, list)
return #list == 0 and '' or ('\n' .. name .. ': ' .. table.concat(list, ', ')) return ('\n%s: %s'):format(name, table.concat(list, ', '))
end end
-- Resolve only once -- Resolve only once
@@ -987,13 +973,44 @@ end
--- @inlinedoc --- @inlinedoc
--- @class vim.pack.PlugData --- @class vim.pack.PlugData
--- @field spec vim.pack.SpecResolved A |vim.pack.Spec| with defaults made explicit.
--- @field path string Plugin's path on disk.
--- @field active boolean Whether plugin was added via |vim.pack.add()| to current session. --- @field active boolean Whether plugin was added via |vim.pack.add()| to current session.
--- @field branches? string[] Available Git branches (first is default). Missing if `info=false`.
--- @field path string Plugin's path on disk.
--- @field rev? string Current Git revision. Missing if `info=false`.
--- @field spec vim.pack.SpecResolved A |vim.pack.Spec| with resolved `name`.
--- @field tags? string[] Available Git tags. Missing if `info=false`.
--- Get data about all plugins managed by |vim.pack| --- @class vim.pack.keyset.get
--- @inlinedoc
--- @field info boolean Whether to include extra plugin info. Default `true`.
--- @param p_data_list vim.pack.PlugData[]
local function add_p_data_info(p_data_list)
local funs = {} --- @type (async fun())[]
for i, p_data in ipairs(p_data_list) do
local path = p_data.path
--- @async
funs[i] = function()
p_data.branches = git_get_branches(path)
p_data.rev = git_get_hash('HEAD', path)
p_data.tags = git_get_tags(path)
end
end
--- @async
local function joined_f()
async.join(n_threads, funs)
end
async.run(joined_f):wait()
end
--- Gets |vim.pack| plugin info, optionally filtered by `names`.
--- @param names? string[] List of plugin names. Default: all plugins managed by |vim.pack|.
--- @param opts? vim.pack.keyset.get
--- @return vim.pack.PlugData[] --- @return vim.pack.PlugData[]
function M.get() function M.get(names, opts)
vim.validate('names', names, vim.islist, true, 'list')
opts = vim.tbl_extend('force', { info = true }, opts or {})
-- Process active plugins in order they were added. Take into account that -- Process active plugins in order they were added. Take into account that
-- there might be "holes" after `vim.pack.del()`. -- there might be "holes" after `vim.pack.del()`.
local active = {} --- @type table<integer,vim.pack.Plug?> local active = {} --- @type table<integer,vim.pack.Plug?>
@@ -1001,11 +1018,12 @@ function M.get()
active[p_active.id] = p_active.plug active[p_active.id] = p_active.plug
end end
--- @type vim.pack.PlugData[] local res = {} --- @type vim.pack.PlugData[]
local res = {} local used_names = {} --- @type table<string,boolean>
for i = 1, n_active_plugins do for i = 1, n_active_plugins do
if active[i] then if active[i] and (not names or vim.tbl_contains(names, active[i].spec.name)) then
res[#res + 1] = { spec = vim.deepcopy(active[i].spec), path = active[i].path, active = true } res[#res + 1] = { spec = vim.deepcopy(active[i].spec), path = active[i].path, active = true }
used_names[active[i].spec.name] = true
end end
end end
@@ -1015,21 +1033,34 @@ function M.get()
local plug_dir = get_plug_dir() local plug_dir = get_plug_dir()
for n, t in vim.fs.dir(plug_dir, { depth = 1 }) do for n, t in vim.fs.dir(plug_dir, { depth = 1 }) do
local path = vim.fs.joinpath(plug_dir, n) local path = vim.fs.joinpath(plug_dir, n)
if t == 'directory' and not active_plugins[path] then local is_in_names = not names or vim.tbl_contains(names, n)
if t == 'directory' and not active_plugins[path] and is_in_names then
local spec = { name = n, src = git_cmd({ 'remote', 'get-url', 'origin' }, path) } local spec = { name = n, src = git_cmd({ 'remote', 'get-url', 'origin' }, path) }
res[#res + 1] = { spec = spec, path = path, active = false } res[#res + 1] = { spec = spec, path = path, active = false }
end used_names[n] = true
end
-- Make default `version` explicit
for _, p_data in ipairs(res) do
if not p_data.spec.version then
p_data.spec.version = git_get_default_branch(p_data.path)
end end
end end
end end
async.run(do_get):wait() async.run(do_get):wait()
if names ~= nil then
-- Align result with input
local names_order = {} --- @type table<string,integer>
for i, n in ipairs(names) do
if not used_names[n] then
error(('Plugin `%s` is not installed'):format(tostring(n)))
end
names_order[n] = i
end
table.sort(res, function(a, b)
return names_order[a.spec.name] < names_order[b.spec.name]
end)
end
if opts.info then
add_p_data_info(res)
end
return res return res
end end

View File

@@ -4,10 +4,8 @@
" Last Change: 2022 Jun 12 " Last Change: 2022 Jun 12
" 2025 Sep 2 by Vim project: fix a few syntax issues #18192 " 2025 Sep 2 by Vim project: fix a few syntax issues #18192
" 2025 Sep 5 by Vim project: introduce m4Disabled region #18200 " 2025 Sep 5 by Vim project: introduce m4Disabled region #18200
" 2025 Sep 6 by Vim project: remove m4Function heuristics #18211
" This file will highlight user function calls if they use only " 2025 Sep 6 by Vim project: remove m4Type and m4Function #18223
" capital letters and have at least one argument (i.e. the '('
" must be there). Let me know if this is a problem.
" quit when a syntax file was already loaded " quit when a syntax file was already loaded
if !exists("main_syntax") if !exists("main_syntax")
@@ -45,6 +43,13 @@ syn region m4Quoted
" Comments themselves are disabled when quoted. " Comments themselves are disabled when quoted.
syn region m4Disabled start=+#+ end=+$+ containedin=ALLBUT,m4Quoted syn region m4Disabled start=+#+ end=+$+ containedin=ALLBUT,m4Quoted
" Macros in M4:
" Name tokens consist of the longest possible sequence of letters, digits,
" and underscores, where the first character is not a digit.
" In GNU M4, this can be altered with changeword().
" Any name token may be defined as a macro and quoting prevents expansion.
" Thus correct highlighting requires running M4.
" define the m4 syntax " define the m4 syntax
syn match m4Variable contained "\$\d\+" syn match m4Variable contained "\$\d\+"
syn match m4Special contained "$[@*#]" syn match m4Special contained "$[@*#]"
@@ -53,26 +58,24 @@ syn match m4Constants "\<\(m4_\)\=__file__"
syn match m4Constants "\<\(m4_\)\=__line__" syn match m4Constants "\<\(m4_\)\=__line__"
syn keyword m4Constants divnum sysval m4_divnum m4_sysval syn keyword m4Constants divnum sysval m4_divnum m4_sysval
syn region m4Paren matchgroup=m4Delimiter start="(" end=")" contained contains=@m4Top syn region m4Paren matchgroup=m4Delimiter start="(" end=")" contained contains=@m4Top
syn region m4Command matchgroup=m4Function start="\<\(m4_\)\=\(define\|defn\|pushdef\)(" end=")" contains=@m4Top syn region m4Command matchgroup=m4Define start="\<\(m4_\)\=\(define\|defn\|pushdef\)(" end=")" contains=@m4Top
syn region m4Command matchgroup=m4Preproc start="\<\(m4_\)\=\(include\|sinclude\)("he=e-1 end=")" contains=@m4Top syn region m4Command matchgroup=m4Preproc start="\<\(m4_\)\=\(include\|sinclude\)("he=e-1 end=")" contains=@m4Top
syn region m4Command matchgroup=m4Statement start="\<\(m4_\)\=\(syscmd\|esyscmd\|ifdef\|ifelse\|indir\|builtin\|shift\|errprint\|m4exit\|changecom\|changequote\|changeword\|m4wrap\|debugfile\|divert\|undivert\)("he=e-1 end=")" contains=@m4Top syn region m4Command matchgroup=m4Statement start="\<\(m4_\)\=\(syscmd\|esyscmd\|ifdef\|ifelse\|indir\|builtin\|shift\|errprint\|m4exit\|changecom\|changequote\|changeword\|m4wrap\|debugfile\|divert\|undivert\)("he=e-1 end=")" contains=@m4Top
syn region m4Command matchgroup=m4Builtin start="\<\(m4_\)\=\(len\|index\|regexp\|substr\|translit\|patsubst\|format\|incr\|decr\|eval\|maketemp\)("he=e-1 end=")" contains=@m4Top syn region m4Command matchgroup=m4Builtin start="\<\(m4_\)\=\(len\|index\|regexp\|substr\|translit\|patsubst\|format\|incr\|decr\|eval\|maketemp\)("he=e-1 end=")" contains=@m4Top
syn keyword m4Statement divert undivert syn keyword m4Statement divert undivert
syn region m4Command matchgroup=m4Type start="\<\(m4_\)\=\(undefine\|popdef\)("he=e-1 end=")" contains=@m4Top syn region m4Command matchgroup=m4Define start="\<\(m4_\)\=\(undefine\|popdef\)("he=e-1 end=")" contains=@m4Top
syn region m4Function matchgroup=m4Type start="\<[_A-Z][_A-Z0-9]*("he=e-1 end=")" contains=@m4Top syn cluster m4Top contains=m4Comment,m4Constants,m4Special,m4Variable,m4Paren,m4Command,m4Statement,m4Quoted
syn cluster m4Top contains=m4Comment,m4Constants,m4Special,m4Variable,m4Paren,m4Command,m4Statement,m4Function,m4Quoted
" Define the default highlighting. " Define the default highlighting.
" Only when an item doesn't have highlighting yet " Only when an item doesn't have highlighting yet
hi def link m4QuoteDelim Delimiter hi def link m4QuoteDelim Delimiter
hi def link m4Delimiter Delimiter hi def link m4Delimiter Delimiter
hi def link m4Comment Comment hi def link m4Comment Comment
hi def link m4Function Function
hi def link m4Keyword Keyword hi def link m4Keyword Keyword
hi def link m4Define Define
hi def link m4Special Special hi def link m4Special Special
hi def link m4Statement Statement hi def link m4Statement Statement
hi def link m4Preproc PreProc hi def link m4Preproc PreProc
hi def link m4Type Type
hi def link m4Variable Special hi def link m4Variable Special
hi def link m4Constants Constant hi def link m4Constants Constant
hi def link m4Builtin Statement hi def link m4Builtin Statement

720
runtime/syntax/nu.vim Normal file
View File

@@ -0,0 +1,720 @@
" Vim syntax file
" Language: Nushell
" Maintainer: El Kasztano
" URL: https://github.com/elkasztano/nushell-syntax-vim
" License: MIT <https://opensource.org/license/mit>
" Last Change: 2025 Sep 05
if exists("b:current_syntax")
finish
endif
syn iskeyword @,192-255,-,_
syn match nuCmd "\<alias\>" display
syn match nuCmd "\<all\>" display
syn match nuCmd "\<ansi\>" display
syn match nuCmd "\<ansi gradient\>" display
syn match nuCmd "\<ansi link\>" display
syn match nuCmd "\<ansi strip\>" display
syn match nuCmd "\<any\>" display
syn match nuCmd "\<append\>" display
syn match nuCmd "\<ast\>" display
syn match nuCmd "\<banner\>" display
syn match nuCmd "\<bits\>" display
syn match nuCmd "\<bits and\>" display
syn match nuCmd "\<bits not\>" display
syn match nuCmd "\<bits or\>" display
syn match nuCmd "\<bits rol\>" display
syn match nuCmd "\<bits ror\>" display
syn match nuCmd "\<bits shl\>" display
syn match nuCmd "\<bits shr\>" display
syn match nuCmd "\<bits xor\>" display
syn match nuCmd "\<break\>" display
syn match nuCmd "\<bytes\>" display
syn match nuCmd "\<bytes add\>" display
syn match nuCmd "\<bytes at\>" display
syn match nuCmd "\<bytes build\>" display
syn match nuCmd "\<bytes collect\>" display
syn match nuCmd "\<bytes ends-with\>" display
syn match nuCmd "\<bytes index-of\>" display
syn match nuCmd "\<bytes length\>" display
syn match nuCmd "\<bytes remove\>" display
syn match nuCmd "\<bytes replace\>" display
syn match nuCmd "\<bytes reverse\>" display
syn match nuCmd "\<bytes starts-with\>" display
syn match nuCmd "\<cal\>" display
syn match nuCmd "\<cd\>" display
syn match nuCmd "\<char\>" display
syn match nuCmd "\<clear\>" display
syn match nuCmd "\<collect\>" display
syn match nuCmd "\<columns\>" display
syn match nuCmd "\<commandline\>" display
syn match nuCmd "\<compact\>" display
syn match nuCmd "\<complete\>" display
syn match nuCmd "\<config\>" display
syn match nuCmd "\<config env\>" display
syn match nuCmd "\<config nu\>" display
syn match nuCmd "\<config reset\>" display
syn match nuCmd "\<const\>" nextgroup=nuIdtfr,nuSubCmd,nuDefflag skipwhite display
syn match nuCmd "\<continue\>" display
syn match nuCmd "\<cp\>" display
syn match nuCmd "\<cp-old\>" display
syn match nuCmd "\<create_left_prompt\>" display
syn match nuCmd "\<create_right_prompt\>" display
syn match nuCmd "\<date\>" display
syn match nuCmd "\<date format\>" display
syn match nuCmd "\<date humanize\>" display
syn match nuCmd "\<date list-timezone\>" display
syn match nuCmd "\<date now\>" display
syn match nuCmd "\<date to-record\>" display
syn match nuCmd "\<date to-table\>" display
syn match nuCmd "\<date to-timezone\>" display
syn match nuCmd "\<debug\>" display
syn match nuCmd "\<debug info\>" display
syn match nuCmd "\<decode\>" display
syn match nuCmd "\<decode base64\>" display
syn match nuCmd "\<decode hex\>" display
syn match nuCmd "\<def\>" nextgroup=nuIdtfr,nuSubCmd,nuDefflag skipwhite display
syn match nuCmd "\<def-env\>" nextgroup=nuIdtfr,nuSubCmd,nuDefflag skipwhite display
syn match nuCmd "\<default\>" display
syn match nuCmd "\<describe\>" display
syn match nuCmd "\<detect columns\>" display
syn match nuCmd "\<drop\>" display
syn match nuCmd "\<dfr\>" display
syn match nuCmd "\<dfr agg\>" display
syn match nuCmd "\<dfr agg-groups\>" display
syn match nuCmd "\<dfr all-false\>" display
syn match nuCmd "\<dfr all-true\>" display
syn match nuCmd "\<dfr append\>" display
syn match nuCmd "\<dfr arg-max\>" display
syn match nuCmd "\<dfr arg-min\>" display
syn match nuCmd "\<dfr arg-sort\>" display
syn match nuCmd "\<dfr arg-true\>" display
syn match nuCmd "\<dfr arg-unique\>" display
syn match nuCmd "\<dfr arg-where\>" display
syn match nuCmd "\<dfr as\>" display
syn match nuCmd "\<dfr as-date\>" display
syn match nuCmd "\<dfr as-datetime\>" display
syn match nuCmd "\<dfr cache\>" display
syn match nuCmd "\<dfr col\>" display
syn match nuCmd "\<dfr collect\>" display
syn match nuCmd "\<dfr columns\>" display
syn match nuCmd "\<dfr concat-str\>" display
syn match nuCmd "\<dfr concatenate\>" display
syn match nuCmd "\<dfr contains\>" display
syn match nuCmd "\<dfr count\>" display
syn match nuCmd "\<dfr count-null\>" display
syn match nuCmd "\<dfr cumulative\>" display
syn match nuCmd "\<dfr datepart\>" display
syn match nuCmd "\<dfr drop\>" display
syn match nuCmd "\<dfr drop-duplicates\>" display
syn match nuCmd "\<dfr drop-nulls\>" display
syn match nuCmd "\<dfr dtypes\>" display
syn match nuCmd "\<dfr dummies\>" display
syn match nuCmd "\<dfr explode\>" display
syn match nuCmd "\<dfr expr-not\>" display
syn match nuCmd "\<dfr fetch\>" display
syn match nuCmd "\<dfr fill-nan\>" display
syn match nuCmd "\<dfr fill-null\>" display
syn match nuCmd "\<dfr filter\>" display
syn match nuCmd "\<dfr filter-with\>" display
syn match nuCmd "\<dfr first\>" display
syn match nuCmd "\<dfr flatten\>" display
syn match nuCmd "\<dfr get\>" display
syn match nuCmd "\<dfr get-day\>" display
syn match nuCmd "\<dfr get-hour\>" display
syn match nuCmd "\<dfr get-minute\>" display
syn match nuCmd "\<dfr get-month\>" display
syn match nuCmd "\<dfr get-nanosecond\>" display
syn match nuCmd "\<dfr get-ordinal\>" display
syn match nuCmd "\<dfr get-second\>" display
syn match nuCmd "\<dfr get-week\>" display
syn match nuCmd "\<dfr get-weekday\>" display
syn match nuCmd "\<dfr get-year\>" display
syn match nuCmd "\<dfr group-by\>" display
syn match nuCmd "\<dfr implode\>" display
syn match nuCmd "\<dfr into-df\>" display
syn match nuCmd "\<dfr into-lazy\>" display
syn match nuCmd "\<dfr into-nu\>" display
syn match nuCmd "\<dfr is-duplicated\>" display
syn match nuCmd "\<dfr is-in\>" display
syn match nuCmd "\<dfr is-not-null\>" display
syn match nuCmd "\<dfr is-null\>" display
syn match nuCmd "\<dfr is-unique\>" display
syn match nuCmd "\<dfr join\>" display
syn match nuCmd "\<dfr last\>" display
syn match nuCmd "\<dfr lit\>" display
syn match nuCmd "\<dfr lowercase\>" display
syn match nuCmd "\<dfr ls\>" display
syn match nuCmd "\<dfr max\>" display
syn match nuCmd "\<dfr mean\>" display
syn match nuCmd "\<dfr median\>" display
syn match nuCmd "\<dfr melt\>" display
syn match nuCmd "\<dfr min\>" display
syn match nuCmd "\<dfr n-unique\>" display
syn match nuCmd "\<dfr not\>" display
syn match nuCmd "\<dfr open\>" display
syn match nuCmd "\<dfr otherwise\>" display
syn match nuCmd "\<dfr quantile\>" display
syn match nuCmd "\<dfr query\>" display
syn match nuCmd "\<dfr rename\>" display
syn match nuCmd "\<dfr replace\>" display
syn match nuCmd "\<dfr replace-all\>" display
syn match nuCmd "\<dfr reverse\>" display
syn match nuCmd "\<dfr rolling\>" display
syn match nuCmd "\<dfr sample\>" display
syn match nuCmd "\<dfr select\>" display
syn match nuCmd "\<dfr set\>" display
syn match nuCmd "\<dfr set-with-idx\>" display
syn match nuCmd "\<dfr shape\>" display
syn match nuCmd "\<dfr shift\>" display
syn match nuCmd "\<dfr slice\>" display
syn match nuCmd "\<dfr sort-by\>" display
syn match nuCmd "\<dfr std\>" display
syn match nuCmd "\<dfr str-lengths\>" display
syn match nuCmd "\<dfr str-slice\>" display
syn match nuCmd "\<dfr strftime\>" display
syn match nuCmd "\<dfr sum\>" display
syn match nuCmd "\<dfr summary\>" display
syn match nuCmd "\<dfr take\>" display
syn match nuCmd "\<dfr to-arrow\>" display
syn match nuCmd "\<dfr to-avro\>" display
syn match nuCmd "\<dfr to-csv\>" display
syn match nuCmd "\<dfr to-jsonl\>" display
syn match nuCmd "\<dfr to-parquet\>" display
syn match nuCmd "\<dfr unique\>" display
syn match nuCmd "\<dfr uppercase\>" display
syn match nuCmd "\<dfr value-counts\>" display
syn match nuCmd "\<dfr var\>" display
syn match nuCmd "\<dfr when\>" display
syn match nuCmd "\<dfr with-column\>" display
syn match nuCmd "\<do\>" display
syn match nuCmd "\<drop\>" display
syn match nuCmd "\<drop column\>" display
syn match nuCmd "\<drop nth\>" display
syn match nuCmd "\<du\>" display
syn match nuCmd "\<each\>" display
syn match nuCmd "\<each while\>" display
syn match nuCmd "\<echo\>" display
syn match nuCmd "\<encode\>" display
syn match nuCmd "\<encode base64\>" display
syn match nuCmd "\<encode hex\>" display
syn match nuCmd "\<add\>" display
syn match nuCmd "\<enumerate\>" display
syn match nuCmd "\<error make\>" display
syn match nuCmd "\<every\>" display
syn match nuCmd "\<exec\>" display
syn match nuCmd "\<exit\>" display
syn match nuCmd "\<explain\>" display
syn match nuCmd "\<explore\>" display
syn match nuCmd "\<export\>" display
syn match nuCmd "\<export alias\>" display
syn match nuCmd "\<export const\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export def\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export def-env\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export extern\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export extern-wrapped\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export module\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<export use\>" display
syn match nuCmd "\<export-env\>" display
syn match nuCmd "\<extern\>" display
syn match nuCmd "\<extern-wrapped\>" display
syn match nuCmd "\<fill\>" display
syn match nuCmd "\<filter\>" display
syn match nuCmd "\<find\>" display
syn match nuCmd "\<first\>" display
syn match nuCmd "\<flatten\>" display
syn match nuCmd "\<fmt\>" display
syn match nuCmd "\<for\>" display
syn match nuCmd "\<format\>" display
syn match nuCmd "\<format date\>" display
syn match nuCmd "\<format duration\>" display
syn match nuCmd "\<format filesize\>" display
syn match nuCmd "\<from\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<from csv\>" display
syn match nuCmd "\<from json\>" display
syn match nuCmd "\<from nuon\>" display
syn match nuCmd "\<from ods\>" display
syn match nuCmd "\<from ssv\>" display
syn match nuCmd "\<from toml\>" display
syn match nuCmd "\<from tsv\>" display
syn match nuCmd "\<from url\>" display
syn match nuCmd "\<from xlsx\>" display
syn match nuCmd "\<from xml\>" display
syn match nuCmd "\<from yaml\>" display
syn match nuCmd "\<from yml\>" display
syn match nuCmd "\<goto\>" display
syn match nuCmd "\<get\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<glob\>" display
syn match nuCmd "\<grid\>" display
syn match nuCmd "\<group\>" display
syn match nuCmd "\<group-by\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<hash\>" display
syn match nuCmd "\<hash md5\>" display
syn match nuCmd "\<hash sha256\>" display
syn match nuCmd "\<headers\>" display
syn match nuCmd "\<help\>" display
syn match nuCmd "\<help aliases\>" display
syn match nuCmd "\<help commands\>" display
syn match nuCmd "\<help escapes\>" display
syn match nuCmd "\<help externs\>" display
syn match nuCmd "\<help modules\>" display
syn match nuCmd "\<help operators\>" display
syn match nuCmd "\<hide\>" display
syn match nuCmd "\<hide-env\>" display
syn match nuCmd "\<histogram\>" display
syn match nuCmd "\<history\>" display
syn match nuCmd "\<history session\>" display
syn match nuCmd "\<http\> " display
syn match nuCmd "\<http delete\>" display
syn match nuCmd "\<http get\>" display
syn match nuCmd "\<http head\>" display
syn match nuCmd "\<http options\>" display
syn match nuCmd "\<http patch\>" display
syn match nuCmd "\<http post\>" display
syn match nuCmd "\<http put\>" display
syn match nuCmd "\<if\>" display
syn match nuCmd "\<ignore\>" display
syn match nuCmd "\<input\>" display
syn match nuCmd "\<input list\>" display
syn match nuCmd "\<input listen\>" display
syn match nuCmd "\<insert\>" display
syn match nuCmd "\<inspect\>" display
syn match nuCmd "\<into\>" display
syn match nuCmd "\<into binary\>" display
syn match nuCmd "\<into bits\>" display
syn match nuCmd "\<into bool\>" display
syn match nuCmd "\<into datetime\>" display
syn match nuCmd "\<into duration\>" display
syn match nuCmd "\<into filesize\>" display
syn match nuCmd "\<into float\>" display
syn match nuCmd "\<into int\>" display
syn match nuCmd "\<into record\>" display
syn match nuCmd "\<into sqlite\>" display
syn match nuCmd "\<into string\>" display
syn match nuCmd "\<into value\>" display
syn match nuCmd "\<is-admin\>" display
syn match nuCmd "\<is-empty\>" display
syn match nuCmd "\<items\>" display
syn match nuCmd "\<join\>" display
syn match nuCmd "\<keybindings\>" display
syn match nuCmd "\<keybindings default\>" display
syn match nuCmd "\<keybindings list\>" display
syn match nuCmd "\<keybindings listen\>" display
syn match nuCmd "\<kill\>" display
syn match nuCmd "\<last\>" display
syn match nuCmd "\<lazy make\>" display
syn match nuCmd "\<length\>" display
syn match nuCmd "\<let\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<let-env\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<lines\>" display
syn match nuCmd "\<load-env\>" display
syn match nuCmd "\<loop\>" display
syn match nuCmd "\<ls\>" display
syn match nuCmd "\<match\>" display
syn match nuCmd "\<math\>" display
syn match nuCmd "\<math abs\>" display
syn match nuCmd "\<math arccos\>" display
syn match nuCmd "\<math arccosh\>" display
syn match nuCmd "\<math arcsin\>" display
syn match nuCmd "\<math arcsinh\>" display
syn match nuCmd "\<math arctan\>" display
syn match nuCmd "\<math arctanh\>" display
syn match nuCmd "\<math avg\>" display
syn match nuCmd "\<math ceil\>" display
syn match nuCmd "\<math cos\>" display
syn match nuCmd "\<math cosh\>" display
syn match nuCmd "\<math exp\>" display
syn match nuCmd "\<math floor\>" display
syn match nuCmd "\<math ln\>" display
syn match nuCmd "\<math log\>" display
syn match nuCmd "\<math max\>" display
syn match nuCmd "\<math median\>" display
syn match nuCmd "\<math min\>" display
syn match nuCmd "\<math mode\>" display
syn match nuCmd "\<math product\>" display
syn match nuCmd "\<math round\>" display
syn match nuCmd "\<math sin\>" display
syn match nuCmd "\<math sinh\>" display
syn match nuCmd "\<math sqrt\>" display
syn match nuCmd "\<math stddev\>" display
syn match nuCmd "\<math sum\>" display
syn match nuCmd "\<math tan\>" display
syn match nuCmd "\<math tanh\>" display
syn match nuCmd "\<math variance\>" display
syn match nuCmd "\<merge\>" display
syn match nuCmd "\<metadata\>" display
syn match nuCmd "\<mkdir\>" display
syn match nuCmd "\<module\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<move\>" display
syn match nuCmd "\<mut\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<mv\>" display
syn match nuCmd "\<next\>" display
syn match nuCmd "\<nu-check\>" display
syn match nuCmd "\<nu-highlight\>" display
syn match nuCmd "\<open\>" display
syn match nuCmd "\<overlay\>" display
syn match nuCmd "\<overlay hide\>" display
syn match nuCmd "\<overlay list\>" display
syn match nuCmd "\<overlay new\>" display
syn match nuCmd "\<overlay use\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<prev\>" display
syn match nuCmd "\<par-each\>" display
syn match nuCmd "\<parse\>" display
syn match nuCmd "\<path\>" display
syn match nuCmd "\<path basename\>" display
syn match nuCmd "\<path dirname\>" display
syn match nuCmd "\<path exists\>" display
syn match nuCmd "\<path expand\>" display
syn match nuCmd "\<path join\>" display
syn match nuCmd "\<path parse\>" display
syn match nuCmd "\<path relative-to\>" display
syn match nuCmd "\<path split\>" display
syn match nuCmd "\<path type\>" display
syn match nuCmd "\<port\>" display
syn match nuCmd "\<prepend\>" display
syn match nuCmd "\<print\>" display
syn match nuCmd "\<profile\>" display
syn match nuCmd "\<ps\>" display
syn match nuCmd "\<pwd\>" display
syn match nuCmd "\<query db\>" display
syn match nuCmd "\<random\>" display
syn match nuCmd "\<random bool\>" display
syn match nuCmd "\<random chars\>" display
syn match nuCmd "\<random dice\>" display
syn match nuCmd "\<random float\>" display
syn match nuCmd "\<random int\>" display
syn match nuCmd "\<random integer\>" display
syn match nuCmd "\<random uuid\>" display
syn match nuCmd "\<range\>" display
syn match nuCmd "\<reduce\>" display
syn match nuCmd "\<register\>" display
syn match nuCmd "\<reject\>" display
syn match nuCmd "\<rename\>" display
syn match nuCmd "\<return\>" display
syn match nuCmd "\<reverse\>" display
syn match nuCmd "\<rm\>" display
syn match nuCmd "\<roll\>" display
syn match nuCmd "\<roll down\>" display
syn match nuCmd "\<roll left\>" display
syn match nuCmd "\<roll right\>" display
syn match nuCmd "\<roll up\>" display
syn match nuCmd "\<rotate\>" display
syn match nuCmd "\<run-external\>" display
syn match nuCmd "\<save\>" display
syn match nuCmd "\<schema\>" display
syn match nuCmd "\<scope\>" display
syn match nuCmd "\<scope aliases\>" display
syn match nuCmd "\<scope commands\>" display
syn match nuCmd "\<scope engine-stats\>" display
syn match nuCmd "\<scope externs\>" display
syn match nuCmd "\<scope modules\>" display
syn match nuCmd "\<scope variables\>" display
syn match nuCmd "\<select\>" display
syn match nuCmd "\<seq\>" display
syn match nuCmd "\<seq char\>" display
syn match nuCmd "\<seq date\>" display
syn match nuCmd "\<show\>" display
syn match nuCmd "\<shuffle\>" display
syn match nuCmd "\<size\>" display
syn match nuCmd "\<skip\>" display
syn match nuCmd "\<skip until\>" display
syn match nuCmd "\<skip while\>" display
syn match nuCmd "\<sleep\>" display
syn match nuCmd "\<sort\>" display
syn match nuCmd "\<sort-by\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<source\>" display
syn match nuCmd "\<source-env\>" display
syn match nuCmd "\<split\>" display
syn match nuCmd "\<split chars\>" display
syn match nuCmd "\<split column\>" display
syn match nuCmd "\<split list\>" display
syn match nuCmd "\<split row\>" display
syn match nuCmd "\<split words\>" display
syn match nuCmd "\<split-by\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<start\>" display
syn match nuCmd "\<str\>" display
syn match nuCmd "\<str camel-case\>" display
syn match nuCmd "\<str capitalize\>" display
syn match nuCmd "\<str contains\>" display
syn match nuCmd "\<str distance\>" display
syn match nuCmd "\<str downcase\>" display
syn match nuCmd "\<str ends-with\>" display
syn match nuCmd "\<str expand\>" display
syn match nuCmd "\<str index-of\>" display
syn match nuCmd "\<str join\>" display
syn match nuCmd "\<str kebab-case\>" display
syn match nuCmd "\<str length\>" display
syn match nuCmd "\<str pascal-case\>" display
syn match nuCmd "\<str replace\>" display
syn match nuCmd "\<str reverse\>" display
syn match nuCmd "\<str screaming-snake-case\>" display
syn match nuCmd "\<str snake-case\>" display
syn match nuCmd "\<str starts-with\>" display
syn match nuCmd "\<str substring\>" display
syn match nuCmd "\<str title-case\>" display
syn match nuCmd "\<str trim\>" display
syn match nuCmd "\<str upcase\>" display
syn match nuCmd "\<sys\>" display
syn match nuCmd "\<sys cpu\>" display
syn match nuCmd "\<sys disks\>" display
syn match nuCmd "\<sys host\>" display
syn match nuCmd "\<sys mem\>" display
syn match nuCmd "\<sys net\>" display
syn match nuCmd "\<sys temp\>" display
syn match nuCmd "\<sys users\>" display
syn match nuCmd "\<table\>" display
syn match nuCmd "\<take\>" display
syn match nuCmd "\<take until\>" display
syn match nuCmd "\<take while\>" display
syn match nuCmd "\<term size\>" display
syn match nuCmd "\<timeit\>" display
syn match nuCmd "\<to\>" display
syn match nuCmd "\<to csv\>" display
syn match nuCmd "\<to html\>" display
syn match nuCmd "\<to json\>" display
syn match nuCmd "\<to md\>" display
syn match nuCmd "\<to nuon\>" display
syn match nuCmd "\<to text\>" display
syn match nuCmd "\<to toml\>" display
syn match nuCmd "\<to tsv\>" display
syn match nuCmd "\<to xml\>" display
syn match nuCmd "\<to yaml\>" display
syn match nuCmd "\<touch\>" display
syn match nuCmd "\<transpose\>" display
syn match nuCmd "\<try\>" display
syn match nuCmd "\<tutor\>" display
syn match nuCmd "\<unfold\>" display
syn match nuCmd "\<uniq\>" display
syn match nuCmd "\<uniq-by\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<update\>" display
syn match nuCmd "\<update cells\>" display
syn match nuCmd "\<upsert\>" display
syn match nuCmd "\<url\>" display
syn match nuCmd "\<url build-query\>" display
syn match nuCmd "\<url decode\>" display
syn match nuCmd "\<url encode\>" display
syn match nuCmd "\<url join\>" display
syn match nuCmd "\<url parse\>" display
syn match nuCmd "\<use\>" nextgroup=nuIdtfr skipwhite display
syn match nuCmd "\<values\>" display
syn match nuCmd "\<version\>" display
syn match nuCmd "\<view\>" display
syn match nuCmd "\<view files\>" display
syn match nuCmd "\<view source\>" display
syn match nuCmd "\<view span\>" display
syn match nuCmd "\<watch\>" display
syn match nuCmd "\<where\>" nextgroup=nuPrpty skipwhite display
syn match nuCmd "\<which\>" display
syn match nuCmd "\<while\>" display
syn match nuCmd "\<whoami\>" display
syn match nuCmd "\<window\>" display
syn match nuCmd "\<with-env\>" display
syn match nuCmd "\<wrap\>" display
syn match nuCmd "\<zip\>" display
syn match nuCmd "\<exists\>" display
syn match nuCmd "\<attr category\>" display
syn match nuCmd "\<attr example\>" display
syn match nuCmd "\<attr search-terms\>" display
syn match nuCmd "\<bytes split\>" display
syn match nuCmd "\<chunk-by\>" display
syn match nuCmd "\<chunks\>" display
syn match nuCmd "\<commandline edit\>" display
syn match nuCmd "\<commandline get-cursor\>" display
syn match nuCmd "\<commandline set-cursor\>" display
syn match nuCmd "\<config flatten\>" display
syn match nuCmd "\<config use-colors\>" display
syn match nuCmd "\<date from-human\>" display
syn match nuCmd "\<debug profile\>" display
syn match nuCmd "\<decode base32\>" display
syn match nuCmd "\<decode base32hex\>" display
syn match nuCmd "\<encode base32\>" display
syn match nuCmd "\<encode base32hex\>" display
syn match nuCmd "\<format bits\>" display
syn match nuCmd "\<format number\>" display
syn match nuCmd "\<format pattern\>" display
syn match nuCmd "\<from msgpack\>" display
syn match nuCmd "\<from msgpackz\>" display
syn match nuCmd "\<generate\>" display
syn match nuCmd "\<help pipe-and-redirect\>" display
syn match nuCmd "\<history import\>" display
syn match nuCmd "\<interleave\>" display
syn match nuCmd "\<into cell-path\>" display
syn match nuCmd "\<into glob\>" display
syn match nuCmd "\<is-not-empty\>" display
syn match nuCmd "\<is-terminal\>" display
syn match nuCmd "\<job\>" display
syn match nuCmd "\<job flush\>" display
syn match nuCmd "\<job id\>" display
syn match nuCmd "\<job kill\>" display
syn match nuCmd "\<job list\>" display
syn match nuCmd "\<job recv\>" display
syn match nuCmd "\<job send\>" display
syn match nuCmd "\<job spawn\>" display
syn match nuCmd "\<job tag\>" display
syn match nuCmd "\<job unfreeze\>" display
syn match nuCmd "\<merge deep\>" display
syn match nuCmd "\<metadata access\>" display
syn match nuCmd "\<metadata set\>" display
syn match nuCmd "\<mktemp\>" display
syn match nuCmd "\<panic\>" display
syn match nuCmd "\<path self\>" display
syn match nuCmd "\<plugin\>" display
syn match nuCmd "\<plugin add\>" display
syn match nuCmd "\<plugin list\>" display
syn match nuCmd "\<plugin rm\>" display
syn match nuCmd "\<plugin stop\>" display
syn match nuCmd "\<plugin use\>" display
syn match nuCmd "\<random binary\>" display
syn match nuCmd "\<split cell-path\>" display
syn match nuCmd "\<stor create\>" display
syn match nuCmd "\<stor delete\>" display
syn match nuCmd "\<stor export\>" display
syn match nuCmd "\<stor import\>" display
syn match nuCmd "\<stor insert\>" display
syn match nuCmd "\<stor open\>" display
syn match nuCmd "\<stor reset\>" display
syn match nuCmd "\<stor update\>" display
syn match nuCmd "\<str stats\>" display
syn match nuCmd "\<tee\>" display
syn match nuCmd "\<term query\>" display
syn match nuCmd "\<to msgpack\>" display
syn match nuCmd "\<to msgpackz\>" display
syn match nuCmd "\<to yml\>" display
syn match nuCmd "\<ulimit\>" display
syn match nuCmd "\<uname\>" display
syn match nuCmd "\<url split-query\>" display
syn match nuCmd "\<version check\>" display
syn match nuCmd "\<view blocks\>" display
syn match nuCmd "\<view ir\>" display
syn match nuNumber "\([a-zA-Z_\.]\+\d*\)\@<!\d\+" nextgroup=nuUnit,nuDur
syn match nuNumber "\([a-zA-Z]\)\@<!\.\d\+" nextgroup=nuUnit,nuDur
syn match nuNumber "\([a-zA-Z]\)\@<!_\d\+" nextgroup=nuUnit,nuDur,nuNumber
syn match nuNumber "\d\+[eE][+-]\?\d\+" nextgroup=nuUnit,nuDur
syn match nuNumber "\d\+\.\d\+[eE]\?[+-]\d\+" nextgroup=nuUnit,nuDur
syn keyword nuTodo contained TODO FIXME NOTE
syn match nuComment "#.*$" contains=nuTodo
syn match nuOp "=" display
syn match nuOp "-" display
syn match nuOp "?" display
syn match nuOp "<" display
syn match nuOp ">" display
syn match nuOp "+" display
syn match nuOp "/" display
syn match nuOp "\*" display
syn match nuOp "!=" display
syn match nuOp "=\~" display
syn match nuOp "\!\~" display
syn match nuOp "\<in\>" nextgroup=nuPrpty skipwhite display
syn match nuOp "\<not-in\>" nextgroup=nuPrpty skipwhite display
syn match nuOp "\<not\>" display
syn match nuOp "\<and\>" nextgroup=nuPrpty skipwhite display
syn match nuOp "\<or\>" nextgroup=nuPrpty skipwhite display
syn match nuOp "\<xor\>" nextgroup=nuPrpty skipwhite display
syn match nuOp "\<bit-or\>" display
syn match nuOp "\<bit-xor\>" display
syn match nuOp "\<bit-and\>" display
syn match nuOp "\<bit-shl\>" display
syn match nuOp "\<bit-shr\>" display
syn match nuOp "\<starts-with\>" display
syn match nuOp "\<ends-with\>" display
syn match nuOp "\.\.\." display
syn match nuVar "\$[^?\])} \t]\+"
syn match nuIdtfr :\(-\+\)\@![^? \t"=]\+: contained
syn region nuSubCmd start=/"/ skip=/\\./ end=/"/ contained
syn match nuPrpty '\w\+' contained
syn keyword nuType any binary bool cell-path closure datetime directory duration error filesize float glob int list nothing number path range record string table true false null
syn keyword nuCondi if then else
syn match nuUnit "b\>" contained
syn match nuUnit "kb\>" contained
syn match nuUnit "mb\>" contained
syn match nuUnit "gb\>" contained
syn match nuUnit "tb\>" contained
syn match nuUnit "pb\>" contained
syn match nuUnit "eb\>" contained
syn match nuUnit "kib\>" contained
syn match nuUnit "mib\>" contained
syn match nuUnit "gib\>" contained
syn match nuUnit "tib\>" contained
syn match nuUnit "pib\>" contained
syn match nuUnit "eib\>" contained
syn match nuDur "ns\>" contained
syn match nuDur "us\>" contained
syn match nuDur "ms\>" contained
syn match nuDur "sec\>" contained
syn match nuDur "min\>" contained
syn match nuDur "hr\>" contained
syn match nuDur "day\>" contained
syn match nuDur "wk\>" contained
syn match nuFlag "\<-\k\+"
syn match nuDefflag "\<--env\>" display contained nextgroup=nuIdtfr skipwhite
syn match nuDefflag "\<--wrapped\>" display contained nextgroup=nuIdtfr skipwhite
syn match nuSysEsc "\^\k\+" display
syn match nuSqrbr "\[" display
syn match nuSqrbr "\]" display
syn match nuSqrbr ":" display
syn region nuString start=/\v"/ skip=/\v\\./ end=/\v"/ contains=nuEscaped
syn region nuString start='\'' end='\''
syn region nuString start='`' end='`'
syn region nuString start=/r#\+'/ end=/#\+/ contains=nuString
syn region nuStrInt start=/$'/ end=/'/ contains=nuNested
syn region nuStrInt start=/$"/ skip=/\\./ end=/"/ contains=nuNested,nuEscaped
syn region nuNested start="("hs=s+1 end=")"he=e-1 contained contains=nuAnsi
syn match nuAnsi "ansi[a-zA-Z0-9;' -]\+)"me=e-1 contained
syn match nuClosure "|\(\w\|, \)\+|"
syn match nuDot ")\.\(\k\|\.\)\+"ms=s+1 display
syn match nuEscaped "\\\\" display
syn match nuEscaped :\\": display
syn match nuEscaped "\\n" display
syn match nuEscaped "\\t" display
syn match nuEscaped "\\r" display
hi def link nuCmd Keyword
hi def link nuComment Comment
hi def link nuTodo Todo
hi def link nuString Constant
hi def link nuChar Constant
hi def link nuOp Operator
hi def link nuVar PreProc
hi def link nuSqrBr Special
hi def link nuIdtfr Identifier
hi def link nuType Type
hi def link nuUnit Type
hi def link nuDur Type
hi def link nuPrpty Special
hi def link nuSubCmd Identifier
hi def link nuStrInt Constant
hi def link nuNested PreProc
hi def link nuFlag Special
hi def link nuEscaped Special
hi def link nuCondi Type
hi def link nuClosure Type
hi def link nuNumber Number
hi def link nuDot Special
hi def link nuSysEsc PreProc
hi def link nuAnsi Special
hi def link nuDefflag Special
let b:current_syntax = "nu"

2
src/cjson/fpconv.c vendored
View File

@@ -130,7 +130,7 @@ double fpconv_strtod(const char *nptr, char **endptr)
/* Duplicate number into buffer */ /* Duplicate number into buffer */
if (buflen >= FPCONV_G_FMT_BUFSIZE) { if (buflen >= FPCONV_G_FMT_BUFSIZE) {
/* Handle unusually large numbers */ /* Handle unusually large numbers */
buf = malloc(buflen + 1); buf = (char *)malloc(buflen + 1);
if (!buf) { if (!buf) {
fprintf(stderr, "Out of memory"); fprintf(stderr, "Out of memory");
abort(); abort();

87
src/cjson/lua_cjson.c vendored
View File

@@ -87,6 +87,7 @@
#define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0 #define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0
#define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1 #define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1
#define DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES 0 #define DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES 0
#define DEFAULT_ENCODE_INDENT NULL
#ifdef DISABLE_INVALID_NUMBERS #ifdef DISABLE_INVALID_NUMBERS
#undef DEFAULT_DECODE_INVALID_NUMBERS #undef DEFAULT_DECODE_INVALID_NUMBERS
@@ -168,6 +169,7 @@ typedef struct {
int encode_keep_buffer; int encode_keep_buffer;
int encode_empty_table_as_object; int encode_empty_table_as_object;
int encode_escape_forward_slash; int encode_escape_forward_slash;
const char *encode_indent;
int decode_invalid_numbers; int decode_invalid_numbers;
int decode_max_depth; int decode_max_depth;
@@ -177,6 +179,7 @@ typedef struct {
typedef struct { typedef struct {
const char **char2escape[256]; const char **char2escape[256];
const char *indent;
} json_encode_options_t; } json_encode_options_t;
typedef struct { typedef struct {
@@ -330,6 +333,20 @@ static int json_enum_option(lua_State *l, int optindex, int *setting,
} }
*/ */
/* Process string option for a configuration function */
/*
static int json_string_option(lua_State *l, int optindex, const char **setting)
{
if (!lua_isnil(l, optindex)) {
const char *value = luaL_checkstring(l, optindex);
*setting = value;
}
lua_pushstring(l, *setting ? *setting : "");
return 1;
}
*/
/* Configures handling of extremely sparse arrays: /* Configures handling of extremely sparse arrays:
* convert: Convert extremely sparse arrays into objects? Otherwise error. * convert: Convert extremely sparse arrays into objects? Otherwise error.
* ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio
@@ -436,6 +453,20 @@ static int json_cfg_encode_keep_buffer(lua_State *l)
} }
*/ */
/* Configure how to indent output */
/*
static int json_cfg_encode_indent(lua_State *l)
{
json_config_t *cfg = json_arg_init(l, 1);
json_string_option(l, 1, &cfg->encode_indent);
// simplify further checking
if (cfg->encode_indent[0] == '\0') cfg->encode_indent = NULL;
return 1;
}
*/
#if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV) #if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)
void json_verify_invalid_number_setting(lua_State *l, int *setting) void json_verify_invalid_number_setting(lua_State *l, int *setting)
{ {
@@ -533,6 +564,7 @@ static void json_create_config(lua_State *l)
cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT; cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT;
cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH; cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH;
cfg->encode_skip_unsupported_value_types = DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES; cfg->encode_skip_unsupported_value_types = DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES;
cfg->encode_indent = DEFAULT_ENCODE_INDENT;
#if DEFAULT_ENCODE_KEEP_BUFFER > 0 #if DEFAULT_ENCODE_KEEP_BUFFER > 0
strbuf_init(&cfg->encode_buf, 0); strbuf_init(&cfg->encode_buf, 0);
@@ -704,6 +736,13 @@ static void json_check_encode_depth(lua_State *l, json_config_t *cfg,
static int json_append_data(lua_State *l, json_encode_t *cfg, static int json_append_data(lua_State *l, json_encode_t *cfg,
int current_depth); int current_depth);
static void json_append_newline_and_indent(strbuf_t *json, json_encode_t *ctx, int depth)
{
strbuf_append_char(json, '\n');
for (int i = 0; i < depth; i++)
strbuf_append_string(json, ctx->options->indent);
}
/* json_append_array args: /* json_append_array args:
* - lua_State * - lua_State
* - JSON strbuf * - JSON strbuf
@@ -712,15 +751,22 @@ static void json_append_array(lua_State *l, json_encode_t *ctx, int current_dept
int array_length, int raw) int array_length, int raw)
{ {
int comma, i, json_pos, err; int comma, i, json_pos, err;
int has_items = 0;
strbuf_t *json = ctx->json; strbuf_t *json = ctx->json;
strbuf_append_char(json, '['); strbuf_append_char(json, '[');
comma = 0; comma = 0;
for (i = 1; i <= array_length; i++) { for (i = 1; i <= array_length; i++) {
has_items = 1;
json_pos = strbuf_length(json); json_pos = strbuf_length(json);
if (comma++ > 0) if (comma++ > 0)
strbuf_append_char(json, ','); strbuf_append_char(json, ',');
if (ctx->options->indent)
json_append_newline_and_indent(json, ctx, current_depth);
if (raw) { if (raw) {
lua_rawgeti(l, -1, i); lua_rawgeti(l, -1, i);
} else { } else {
@@ -742,6 +788,9 @@ static void json_append_array(lua_State *l, json_encode_t *ctx, int current_dept
lua_pop(l, 1); lua_pop(l, 1);
} }
if (has_items && ctx->options->indent)
json_append_newline_and_indent(json, ctx, current_depth-1);
strbuf_append_char(json, ']'); strbuf_append_char(json, ']');
} }
@@ -798,6 +847,7 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
int current_depth) int current_depth)
{ {
int comma, keytype, json_pos, err; int comma, keytype, json_pos, err;
int has_items = 0;
strbuf_t *json = ctx->json; strbuf_t *json = ctx->json;
/* Object */ /* Object */
@@ -807,12 +857,17 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
/* table, startkey */ /* table, startkey */
comma = 0; comma = 0;
while (lua_next(l, -2) != 0) { while (lua_next(l, -2) != 0) {
has_items = 1;
json_pos = strbuf_length(json); json_pos = strbuf_length(json);
if (comma++ > 0) if (comma++ > 0)
strbuf_append_char(json, ','); strbuf_append_char(json, ',');
else else
comma = 1; comma = 1;
if (ctx->options->indent)
json_append_newline_and_indent(json, ctx, current_depth);
/* table, key, value */ /* table, key, value */
keytype = lua_type(l, -2); keytype = lua_type(l, -2);
if (keytype == LUA_TNUMBER) { if (keytype == LUA_TNUMBER) {
@@ -827,6 +882,8 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
"table key must be a number or string"); "table key must be a number or string");
/* never returns */ /* never returns */
} }
if (ctx->options->indent)
strbuf_append_char(json, ' ');
/* table, key, value */ /* table, key, value */
err = json_append_data(l, ctx, current_depth); err = json_append_data(l, ctx, current_depth);
@@ -841,6 +898,9 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
/* table, key */ /* table, key */
} }
if (has_items && ctx->options->indent)
json_append_newline_and_indent(json, ctx, current_depth-1);
strbuf_append_char(json, '}'); strbuf_append_char(json, '}');
} }
@@ -966,7 +1026,10 @@ static int json_append_data(lua_State *l, json_encode_t *ctx,
static int json_encode(lua_State *l) static int json_encode(lua_State *l)
{ {
json_config_t *cfg = json_fetch_config(l); json_config_t *cfg = json_fetch_config(l);
json_encode_options_t options = { .char2escape = { char2escape } }; json_encode_options_t options = {
.char2escape = { char2escape },
.indent = DEFAULT_ENCODE_INDENT,
};
json_encode_t ctx = { .options = &options, .cfg = cfg }; json_encode_t ctx = { .options = &options, .cfg = cfg };
strbuf_t local_encode_buf; strbuf_t local_encode_buf;
strbuf_t *encode_buf; strbuf_t *encode_buf;
@@ -979,26 +1042,29 @@ static int json_encode(lua_State *l)
break; break;
case 2: case 2:
luaL_checktype(l, 2, LUA_TTABLE); luaL_checktype(l, 2, LUA_TTABLE);
lua_getfield(l, 2, "escape_slash"); lua_getfield(l, 2, "escape_slash");
if (!lua_isnil(l, -1)) {
/* We only handle the escape_slash option for now */
if (lua_isnil(l, -1)) {
lua_pop(l, 2);
break;
}
luaL_checktype(l, -1, LUA_TBOOLEAN); luaL_checktype(l, -1, LUA_TBOOLEAN);
int escape_slash = lua_toboolean(l, -1); int escape_slash = lua_toboolean(l, -1);
if (escape_slash) { if (escape_slash) {
/* This can be optimised by adding a new hard-coded escape table for this case, /* This can be optimised by adding a new hard-coded escape table for this case,
* but this path will rarely if ever be used, so let's just memcpy.*/ * but this path will rarely if ever be used, so let's just memcpy. */
memcpy(customChar2escape, char2escape, sizeof(char2escape)); memcpy(customChar2escape, char2escape, sizeof(char2escape));
customChar2escape['/'] = "\\/"; customChar2escape['/'] = "\\/";
*ctx.options->char2escape = customChar2escape; *ctx.options->char2escape = customChar2escape;
} }
}
lua_pop(l, 1);
lua_getfield(l, 2, "indent");
if (!lua_isnil(l, -1)) {
options.indent = luaL_checkstring(l, -1);
if (options.indent[0] == '\0') options.indent = NULL;
}
/* Also pop the opts table */
lua_pop(l, 2); lua_pop(l, 2);
break; break;
default: default:
@@ -1710,6 +1776,7 @@ int lua_cjson_new(lua_State *l)
{ "decode_invalid_numbers", json_cfg_decode_invalid_numbers }, { "decode_invalid_numbers", json_cfg_decode_invalid_numbers },
{ "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash }, { "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash },
{ "encode_skip_unsupported_value_types", json_cfg_encode_skip_unsupported_value_types }, { "encode_skip_unsupported_value_types", json_cfg_encode_skip_unsupported_value_types },
{ "encode_indent", json_cfg_encode_indent },
*/ */
{ "new", lua_cjson_new }, { "new", lua_cjson_new },
{ NULL, NULL } { NULL, NULL }

7
src/cjson/strbuf.c vendored
View File

@@ -39,7 +39,7 @@ static void die(const char *fmt, ...)
va_end(arg); va_end(arg);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
exit(-1); abort();
} }
void strbuf_init(strbuf_t *s, size_t len) void strbuf_init(strbuf_t *s, size_t len)
@@ -51,7 +51,7 @@ void strbuf_init(strbuf_t *s, size_t len)
else else
size = len + 1; /* \0 terminator */ size = len + 1; /* \0 terminator */
if (size < len) if (size < len)
die("Overflow, len %zu", len); die("Overflow, len: %zu", len);
s->buf = NULL; s->buf = NULL;
s->size = size; s->size = size;
s->length = 0; s->length = 0;
@@ -132,7 +132,7 @@ static size_t calculate_new_size(strbuf_t *s, size_t len)
/* Ensure there is room for optional NULL termination */ /* Ensure there is room for optional NULL termination */
reqsize = len + 1; reqsize = len + 1;
if (reqsize < len) if (reqsize < len)
die("Overflow, len %zu", len); die("Overflow, len: %zu", len);
/* If the user has requested to shrink the buffer, do it exactly */ /* If the user has requested to shrink the buffer, do it exactly */
if (s->size > reqsize) if (s->size > reqsize)
@@ -194,5 +194,6 @@ void strbuf_append_string(strbuf_t *s, const char *str)
} }
} }
/* vi:ai et sw=4 ts=4: /* vi:ai et sw=4 ts=4:
*/ */

2
src/cjson/strbuf.h vendored
View File

@@ -103,7 +103,7 @@ static inline char *strbuf_empty_ptr(strbuf_t *s)
static inline void strbuf_set_length(strbuf_t *s, int len) static inline void strbuf_set_length(strbuf_t *s, int len)
{ {
s->length += len; s->length = len;
} }
static inline void strbuf_extend_length(strbuf_t *s, size_t len) static inline void strbuf_extend_length(strbuf_t *s, size_t len)

View File

@@ -633,7 +633,6 @@ restore_curwin:
} }
} else { } else {
win_config_float(win, fconfig); win_config_float(win, fconfig);
win->w_pos_changed = true;
} }
if (HAS_KEY_X(config, style)) { if (HAS_KEY_X(config, style)) {
if (fconfig.style == kWinStyleMinimal) { if (fconfig.style == kWinStyleMinimal) {

View File

@@ -254,6 +254,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
CmdlineInfo *const ccline = get_cmdline_info(); CmdlineInfo *const ccline = get_cmdline_info();
char *p; char *p;
bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER; bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
bool wild_navigate = (type == WILD_NEXT || type == WILD_PREV
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
|| type == WILD_PUM_WANT);
if (xp->xp_numfiles == -1) { if (xp->xp_numfiles == -1) {
pre_incsearch_pos = xp->xp_pre_incsearch_pos; pre_incsearch_pos = xp->xp_pre_incsearch_pos;
@@ -292,15 +295,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
// If cmd_silent is set then don't show the dots, because redrawcmd() below // If cmd_silent is set then don't show the dots, because redrawcmd() below
// won't remove them. // won't remove them.
if (!cmd_silent && !from_wildtrigger_func if (!cmd_silent && !from_wildtrigger_func && !wild_navigate
&& !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) { && !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) {
msg_puts("..."); // show that we are busy msg_puts("..."); // show that we are busy
ui_flush(); ui_flush();
} }
if (type == WILD_NEXT || type == WILD_PREV if (wild_navigate) {
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
|| type == WILD_PUM_WANT) {
// Get next/previous match for a previous expanded pattern. // Get next/previous match for a previous expanded pattern.
p = ExpandOne(xp, NULL, NULL, 0, type); p = ExpandOne(xp, NULL, NULL, 0, type);
} else { } else {
@@ -313,7 +314,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
tmp = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context); tmp = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
} }
// Translate string into pattern and expand it. // Translate string into pattern and expand it.
const int use_options = ((options & ~WILD_KEEP_SOLE_ITEM) const int use_options = (options
| WILD_HOME_REPLACE | WILD_HOME_REPLACE
| WILD_ADD_SLASH | WILD_ADD_SLASH
| WILD_SILENT | WILD_SILENT
@@ -337,7 +338,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
} }
} }
if (p != NULL && !got_int) { // Save cmdline before inserting selected item
if (!wild_navigate && ccline->cmdbuff != NULL) {
xfree(cmdline_orig);
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
}
if (p != NULL && !got_int && !(options & WILD_NOSELECT)) {
size_t plen = strlen(p); size_t plen = strlen(p);
int difflen = (int)plen - (int)(xp->xp_pattern_len); int difflen = (int)plen - (int)(xp->xp_pattern_len);
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) { if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) {
@@ -364,7 +371,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
if (xp->xp_numfiles <= 0 && p == NULL) { if (xp->xp_numfiles <= 0 && p == NULL) {
beep_flush(); beep_flush();
} else if (xp->xp_numfiles == 1 && !(options & WILD_KEEP_SOLE_ITEM)) { } else if (xp->xp_numfiles == 1 && !(options & WILD_NOSELECT) && !wild_navigate) {
// free expanded pattern // free expanded pattern
ExpandOne(xp, NULL, NULL, 0, WILD_FREE); ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
} }
@@ -374,10 +381,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
return OK; return OK;
} }
/// Create and display a cmdline completion popup menu with items from /// Create completion popup menu with items from "matches".
/// "matches".
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches, static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
bool showtail) bool showtail, bool noselect)
{ {
assert(numMatches >= 0); assert(numMatches >= 0);
// Add all the completion matches // Add all the completion matches
@@ -395,19 +401,13 @@ static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches,
} }
// Compute the popup menu starting column // Compute the popup menu starting column
char *endpos = showtail ? showmatches_gettail(xp->xp_pattern, true) : xp->xp_pattern; char *endpos = showtail ? showmatches_gettail(xp->xp_pattern, noselect) : xp->xp_pattern;
if (ui_has(kUICmdline) && cmdline_win == NULL) { if (ui_has(kUICmdline) && cmdline_win == NULL) {
compl_startcol = (int)(endpos - ccline->cmdbuff); compl_startcol = (int)(endpos - ccline->cmdbuff);
} else { } else {
compl_startcol = cmd_screencol((int)(endpos - ccline->cmdbuff)); compl_startcol = cmd_screencol((int)(endpos - ccline->cmdbuff));
} }
// no default selection
compl_selected = -1;
pum_clear();
cmdline_pum_display(true);
return EXPAND_OK; return EXPAND_OK;
} }
@@ -420,8 +420,7 @@ void cmdline_pum_display(bool changed_array)
/// Returns true if the cmdline completion popup menu is being displayed. /// Returns true if the cmdline completion popup menu is being displayed.
bool cmdline_pum_active(void) bool cmdline_pum_active(void)
{ {
// compl_match_array != NULL should already imply pum_visible() in Nvim. return pum_visible() && compl_match_array != NULL;
return compl_match_array != NULL;
} }
/// Remove the cmdline completion popup menu (if present), free the list of items. /// Remove the cmdline completion popup menu (if present), free the list of items.
@@ -745,12 +744,21 @@ static char *get_next_or_prev_match(int mode, expand_T *xp)
} }
// Display matches on screen // Display matches on screen
if (p_wmnu) {
if (compl_match_array) { if (compl_match_array) {
compl_selected = findex; compl_selected = findex;
cmdline_pum_display(false); cmdline_pum_display(false);
} else if (p_wmnu) { } else if (wop_flags & kOptWopFlagPum) {
if (cmdline_pum_create(get_cmdline_info(), xp, xp->xp_files,
xp->xp_numfiles, cmd_showtail, false) == EXPAND_OK) {
compl_selected = findex;
pum_clear();
cmdline_pum_display(true);
}
} else {
redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail); redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail);
} }
}
xp->xp_selected = findex; xp->xp_selected = findex;
// Return the original text or the selected match // Return the original text or the selected match
@@ -925,7 +933,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
cmdline_pum_remove(); cmdline_pum_remove();
} }
} }
xp->xp_selected = 0; xp->xp_selected = (options & WILD_NOSELECT) ? -1 : 0;
if (mode == WILD_FREE) { // only release file name if (mode == WILD_FREE) { // only release file name
return NULL; return NULL;
@@ -1084,49 +1092,49 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
} }
} }
/// Show all matches for completion on the command line. /// Display completion matches.
/// Returns EXPAND_NOTHING when the character that triggered expansion should /// Returns EXPAND_NOTHING when the character that triggered expansion should be
/// be inserted like a normal character. /// inserted as a normal character.
int showmatches(expand_T *xp, bool wildmenu) int showmatches(expand_T *xp, bool display_wildmenu, bool display_list, bool noselect)
{ {
CmdlineInfo *const ccline = get_cmdline_info(); CmdlineInfo *const ccline = get_cmdline_info();
int numMatches; int numMatches;
char **matches; char **matches;
int j;
int maxlen; int maxlen;
int lines; int lines;
int columns; int columns;
bool showtail; bool showtail;
// Save cmdline before expansion
if (ccline->cmdbuff != NULL) {
xfree(cmdline_orig);
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
}
if (xp->xp_numfiles == -1) { if (xp->xp_numfiles == -1) {
set_expand_context(xp); set_expand_context(xp);
if (xp->xp_context == EXPAND_LUA) { if (xp->xp_context == EXPAND_LUA) {
nlua_expand_pat(xp); nlua_expand_pat(xp);
} }
int i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos, int retval = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
&numMatches, &matches); &numMatches, &matches);
showtail = expand_showtail(xp); if (retval != EXPAND_OK) {
if (i != EXPAND_OK) { return retval;
return i;
} }
showtail = expand_showtail(xp);
} else { } else {
numMatches = xp->xp_numfiles; numMatches = xp->xp_numfiles;
matches = xp->xp_files; matches = xp->xp_files;
showtail = cmd_showtail; showtail = cmd_showtail;
} }
if (((!ui_has(kUICmdline) || cmdline_win != NULL) && wildmenu && (wop_flags & kOptWopFlagPum)) if (((!ui_has(kUICmdline) || cmdline_win != NULL) && display_wildmenu && !display_list
&& (wop_flags & kOptWopFlagPum))
|| ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) { || ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) {
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail); int retval = cmdline_pum_create(ccline, xp, matches, numMatches, showtail, noselect);
if (retval == EXPAND_OK) {
compl_selected = noselect ? -1 : 0;
pum_clear();
cmdline_pum_display(true);
}
return retval;
} }
if (!wildmenu) { if (display_list) {
msg_didany = false; // lines_left will be set msg_didany = false; // lines_left will be set
msg_start(); // prepare for paging msg_start(); // prepare for paging
msg_putchar('\n'); msg_putchar('\n');
@@ -1138,22 +1146,24 @@ int showmatches(expand_T *xp, bool wildmenu)
} }
if (got_int) { if (got_int) {
got_int = false; // only int. the completion, not the cmd line got_int = false; // only interrupt the completion, not the cmd line
} else if (wildmenu) { } else if (display_wildmenu && !display_list) {
redraw_wildmenu(xp, numMatches, matches, -1, showtail); redraw_wildmenu(xp, numMatches, matches, noselect ? -1 : 0,
} else { showtail); // display statusbar menu
} else if (display_list) {
// find the length of the longest file name // find the length of the longest file name
maxlen = 0; maxlen = 0;
for (int i = 0; i < numMatches; i++) { for (int i = 0; i < numMatches; i++) {
int len;
if (!showtail && (xp->xp_context == EXPAND_FILES if (!showtail && (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_SHELLCMD
|| xp->xp_context == EXPAND_BUFFERS)) { || xp->xp_context == EXPAND_BUFFERS)) {
home_replace(NULL, matches[i], NameBuff, MAXPATHL, true); home_replace(NULL, matches[i], NameBuff, MAXPATHL, true);
j = vim_strsize(NameBuff); len = vim_strsize(NameBuff);
} else { } else {
j = vim_strsize(SHOW_MATCH(i)); len = vim_strsize(SHOW_MATCH(i));
} }
maxlen = MAX(maxlen, j); maxlen = MAX(maxlen, len);
} }
if (xp->xp_context == EXPAND_TAGS_LISTFILES) { if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
@@ -3569,7 +3579,7 @@ int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, bool did_wi
{ {
int c = key; int c = key;
if (did_wild_list) { if (cmdline_pum_active() || did_wild_list || wild_menu_showing) {
if (c == K_LEFT) { if (c == K_LEFT) {
c = Ctrl_P; c = Ctrl_P;
} else if (c == K_RIGHT) { } else if (c == K_RIGHT) {

View File

@@ -40,7 +40,7 @@ enum {
WILD_NOERROR = 0x800, ///< sets EW_NOERROR WILD_NOERROR = 0x800, ///< sets EW_NOERROR
WILD_BUFLASTUSED = 0x1000, WILD_BUFLASTUSED = 0x1000,
BUF_DIFF_FILTER = 0x2000, BUF_DIFF_FILTER = 0x2000,
WILD_KEEP_SOLE_ITEM = 0x4000, WILD_NOSELECT = 0x4000,
WILD_MAY_EXPAND_PATTERN = 0x8000, WILD_MAY_EXPAND_PATTERN = 0x8000,
WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger() WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger()
}; };

View File

@@ -1120,31 +1120,34 @@ static int command_line_wildchar_complete(CommandLineState *s)
{ {
int res; int res;
int options = WILD_NO_BEEP; int options = WILD_NO_BEEP;
bool escape = s->firstc != '@';
bool wim_noselect = p_wmnu && (wim_flags[0] & kOptWimFlagNoselect) != 0;
if (wim_flags[s->wim_index] & kOptWimFlagLastused) { if (wim_flags[s->wim_index] & kOptWimFlagLastused) {
options |= WILD_BUFLASTUSED; options |= WILD_BUFLASTUSED;
} }
if (wim_flags[0] & kOptWimFlagNoselect) {
options |= WILD_KEEP_SOLE_ITEM;
}
if (s->xpc.xp_numfiles > 0) { // typed p_wc at least twice if (s->xpc.xp_numfiles > 0) { // typed p_wc at least twice
// if 'wildmode' contains "list" may still need to list // If "list" is present, list matches unless already listed
if (s->xpc.xp_numfiles > 1 if (s->xpc.xp_numfiles > 1
&& !s->did_wild_list && !s->did_wild_list
&& ((wim_flags[s->wim_index] & kOptWimFlagList) && (wim_flags[s->wim_index] & kOptWimFlagList)) {
|| (p_wmnu && (wim_flags[s->wim_index] & kOptWimFlagFull) != 0))) { showmatches(&s->xpc, false, true, wim_noselect);
showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0));
redrawcmd(); redrawcmd();
s->did_wild_list = true; s->did_wild_list = true;
} }
if (wim_flags[s->wim_index] & kOptWimFlagLongest) { if (wim_flags[s->wim_index] & kOptWimFlagLongest) {
res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@'); res = nextwild(&s->xpc, WILD_LONGEST, options, escape);
} else if (wim_flags[s->wim_index] & kOptWimFlagFull) { } else if (wim_flags[s->wim_index] & kOptWimFlagFull) {
res = nextwild(&s->xpc, WILD_NEXT, options, s->firstc != '@'); res = nextwild(&s->xpc, WILD_NEXT, options, escape);
} else { } else {
res = OK; // don't insert 'wildchar' now res = OK; // don't insert 'wildchar' now
} }
} else { // typed p_wc first time } else { // typed p_wc first time
bool wim_longest = (wim_flags[0] & kOptWimFlagLongest);
bool wim_list = (wim_flags[0] & kOptWimFlagList);
bool wim_full = (wim_flags[0] & kOptWimFlagFull);
s->wim_index = 0;
if (s->c == p_wc || s->c == p_wcm || s->c == K_WILD || s->c == Ctrl_Z) { if (s->c == p_wc || s->c == p_wcm || s->c == K_WILD || s->c == Ctrl_Z) {
options |= WILD_MAY_EXPAND_PATTERN; options |= WILD_MAY_EXPAND_PATTERN;
if (s->c == K_WILD) { if (s->c == K_WILD) {
@@ -1152,15 +1155,17 @@ static int command_line_wildchar_complete(CommandLineState *s)
} }
s->xpc.xp_pre_incsearch_pos = s->is_state.search_start; s->xpc.xp_pre_incsearch_pos = s->is_state.search_start;
} }
s->wim_index = 0; int cmdpos_before = ccline.cmdpos;
int j = ccline.cmdpos;
// if 'wildmode' first contains "longest", get longest // if 'wildmode' first contains "longest", get longest
// common part // common part
if (wim_flags[0] & kOptWimFlagLongest) { if (wim_longest) {
res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@'); res = nextwild(&s->xpc, WILD_LONGEST, options, escape);
} else { } else {
res = nextwild(&s->xpc, WILD_EXPAND_KEEP, options, s->firstc != '@'); if (wim_noselect || wim_list) {
options |= WILD_NOSELECT;
}
res = nextwild(&s->xpc, WILD_EXPAND_KEEP, options, escape);
} }
// if interrupted while completing, behave like it failed // if interrupted while completing, behave like it failed
@@ -1172,39 +1177,39 @@ static int command_line_wildchar_complete(CommandLineState *s)
return CMDLINE_CHANGED; return CMDLINE_CHANGED;
} }
// when more than one match, and 'wildmode' first contains // Display matches
// "list", or no change and 'wildmode' contains "longest,list", if (res == OK && s->xpc.xp_numfiles > (wim_noselect ? 0 : 1)) {
// list all matches if (wim_longest) {
if (res == OK bool found_longest_prefix = (ccline.cmdpos != cmdpos_before);
&& s->xpc.xp_numfiles > ((wim_flags[s->wim_index] & kOptWimFlagNoselect) ? 0 : 1)) { if (wim_list || (p_wmnu && wim_full)) {
// a "longest" that didn't do anything is skipped (but not showmatches(&s->xpc, p_wmnu, wim_list, true);
// "list:longest") } else if (!found_longest_prefix) {
if (wim_flags[0] == kOptWimFlagLongest && ccline.cmdpos == j) { bool wim_list_next = (wim_flags[1] & kOptWimFlagList);
s->wim_index = 1; bool wim_full_next = (wim_flags[1] & kOptWimFlagFull);
bool wim_noselect_next = (wim_flags[1] & kOptWimFlagNoselect);
if (wim_list_next || (p_wmnu && (wim_full_next || wim_noselect_next))) {
if (wim_full_next && !wim_noselect_next) {
nextwild(&s->xpc, WILD_NEXT, options, escape);
} else {
showmatches(&s->xpc, p_wmnu, wim_list_next, wim_noselect_next);
} }
if ((wim_flags[s->wim_index] & kOptWimFlagList) if (wim_list_next) {
|| (p_wmnu && (wim_flags[s->wim_index] & (kOptWimFlagFull|kOptWimFlagNoselect)))) {
if (!(wim_flags[0] & kOptWimFlagLongest)) {
int p_wmnu_save = p_wmnu;
p_wmnu = 0;
// remove match
nextwild(&s->xpc, WILD_PREV, options, s->firstc != '@');
p_wmnu = p_wmnu_save;
}
showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0));
redrawcmd();
s->did_wild_list = true; s->did_wild_list = true;
}
if (wim_flags[s->wim_index] & kOptWimFlagLongest) { }
nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@');
} else if ((wim_flags[s->wim_index] & kOptWimFlagFull)
&& !(wim_flags[s->wim_index] & kOptWimFlagNoselect)) {
nextwild(&s->xpc, WILD_NEXT, options, s->firstc != '@');
} }
} else {
if (wim_list || (p_wmnu && (wim_full || wim_noselect))) {
showmatches(&s->xpc, p_wmnu, wim_list, wim_noselect);
} else { } else {
vim_beep(kOptBoFlagWildmode); vim_beep(kOptBoFlagWildmode);
} }
}
redrawcmd();
if (wim_list) {
s->did_wild_list = true;
}
} else if (s->xpc.xp_numfiles == -1) { } else if (s->xpc.xp_numfiles == -1) {
s->xpc.xp_context = EXPAND_NOTHING; s->xpc.xp_context = EXPAND_NOTHING;
} }
@@ -1344,7 +1349,7 @@ static int command_line_execute(VimState *state, int key)
int wild_type = 0; int wild_type = 0;
const bool key_is_wc = (s->c == p_wc && KeyTyped) || s->c == p_wcm; const bool key_is_wc = (s->c == p_wc && KeyTyped) || s->c == p_wcm;
if ((cmdline_pum_active() || s->did_wild_list) && !key_is_wc) { if ((cmdline_pum_active() || wild_menu_showing || s->did_wild_list) && !key_is_wc) {
// Ctrl-Y: Accept the current selection and close the popup menu. // Ctrl-Y: Accept the current selection and close the popup menu.
// Ctrl-E: cancel the cmdline popup menu and return the original text. // Ctrl-E: cancel the cmdline popup menu and return the original text.
if (s->c == Ctrl_E || s->c == Ctrl_Y) { if (s->c == Ctrl_E || s->c == Ctrl_Y) {
@@ -1469,7 +1474,8 @@ static int command_line_execute(VimState *state, int key)
if (s->xpc.xp_numfiles > 1 if (s->xpc.xp_numfiles > 1
&& ((!s->did_wild_list && (wim_flags[s->wim_index] & kOptWimFlagList)) || p_wmnu)) { && ((!s->did_wild_list && (wim_flags[s->wim_index] & kOptWimFlagList)) || p_wmnu)) {
// Trigger the popup menu when wildoptions=pum // Trigger the popup menu when wildoptions=pum
showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0)); showmatches(&s->xpc, p_wmnu, wim_flags[s->wim_index] & kOptWimFlagList,
wim_flags[0] & kOptWimFlagNoselect);
} }
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
@@ -2036,7 +2042,8 @@ static int command_line_handle_key(CommandLineState *s)
} }
case Ctrl_D: case Ctrl_D:
if (showmatches(&s->xpc, false) == EXPAND_NOTHING) { if (showmatches(&s->xpc, false, true, wim_flags[0] & kOptWimFlagNoselect)
== EXPAND_NOTHING) {
break; // Use ^D as normal char instead break; // Use ^D as normal char instead
} }

View File

@@ -61,7 +61,7 @@ static const int included_patches[] = {
2423, 2423,
2422, 2422,
2421, 2421,
// 2420, 2420,
2419, 2419,
// 2418, // 2418,
2417, 2417,
@@ -147,7 +147,7 @@ static const int included_patches[] = {
2337, 2337,
2336, 2336,
2335, 2335,
// 2334, 2334,
2333, 2333,
2332, 2332,
2331, 2331,
@@ -174,28 +174,28 @@ static const int included_patches[] = {
2310, 2310,
2309, 2309,
2308, 2308,
// 2307, 2307,
2306, 2306,
2305, 2305,
2304, 2304,
2303, 2303,
2302, 2302,
2301, 2301,
// 2300, 2300,
2299, 2299,
2298, 2298,
2297, 2297,
2296, 2296,
// 2295, 2295,
2294, 2294,
2293, 2293,
// 2292, // 2292,
2291, 2291,
2290, 2290,
2289, 2289,
// 2288, 2288,
// 2287, 2287,
// 2286, 2286,
2285, 2285,
2284, 2284,
2283, 2283,
@@ -204,7 +204,7 @@ static const int included_patches[] = {
2280, 2280,
// 2279, // 2279,
2278, 2278,
// 2277, 2277,
2276, 2276,
2275, 2275,
2274, 2274,
@@ -241,7 +241,7 @@ static const int included_patches[] = {
2243, 2243,
2242, 2242,
// 2241, // 2241,
// 2240, 2240,
2239, 2239,
2238, 2238,
2237, 2237,
@@ -268,10 +268,10 @@ static const int included_patches[] = {
2216, 2216,
2215, 2215,
2214, 2214,
// 2213, 2213,
2212, 2212,
2211, 2211,
// 2210, 2210,
2209, 2209,
// 2208, // 2208,
2207, 2207,
@@ -317,7 +317,7 @@ static const int included_patches[] = {
2167, 2167,
2166, 2166,
2165, 2165,
// 2164, 2164,
2163, 2163,
2162, 2162,
2161, 2161,
@@ -367,12 +367,12 @@ static const int included_patches[] = {
2117, 2117,
2116, 2116,
2115, 2115,
// 2114, 2114,
2113, 2113,
2112, 2112,
2111, 2111,
// 2110, 2110,
// 2109, 2109,
2108, 2108,
2107, 2107,
2106, 2106,
@@ -449,7 +449,7 @@ static const int included_patches[] = {
2035, 2035,
2034, 2034,
2033, 2033,
// 2032, 2032,
2031, 2031,
2030, 2030,
2029, 2029,
@@ -472,34 +472,34 @@ static const int included_patches[] = {
2012, 2012,
2011, 2011,
2010, 2010,
// 2009, 2009,
2008, 2008,
2007, 2007,
2006, 2006,
2005, 2005,
// 2004, 2004,
2003, 2003,
2002, 2002,
2001, 2001,
2000, 2000,
// 1999, // 1999,
// 1998, 1998,
// 1997, 1997,
// 1996, 1996,
1995, 1995,
1994, 1994,
// 1993, 1993,
1992, 1992,
1991, 1991,
1990, 1990,
// 1989, // 1989,
1988, 1988,
// 1987, 1987,
// 1986, 1986,
// 1985, // 1985,
1984, 1984,
1983, 1983,
// 1982, 1982,
// 1981, // 1981,
1980, 1980,
// 1979, // 1979,
@@ -518,16 +518,16 @@ static const int included_patches[] = {
1966, 1966,
1965, 1965,
// 1964, // 1964,
// 1963, 1963,
1962, 1962,
1961, 1961,
1960, 1960,
// 1959, 1959,
1958, 1958,
// 1957, // 1957,
1956, 1956,
1955, 1955,
// 1954, 1954,
1953, 1953,
1952, 1952,
1951, 1951,
@@ -536,7 +536,7 @@ static const int included_patches[] = {
1948, 1948,
1947, 1947,
1946, 1946,
// 1945, 1945,
// 1944, // 1944,
// 1943, // 1943,
1942, 1942,
@@ -545,14 +545,14 @@ static const int included_patches[] = {
// 1939, // 1939,
1938, 1938,
1937, 1937,
// 1936, 1936,
1935, 1935,
// 1934, 1934,
1933, 1933,
1932, 1932,
1931, 1931,
1930, 1930,
// 1929, 1929,
// 1928, // 1928,
1927, 1927,
1926, 1926,
@@ -562,9 +562,9 @@ static const int included_patches[] = {
1922, 1922,
1921, 1921,
// 1920, // 1920,
// 1919, 1919,
// 1918, 1918,
// 1917, 1917,
1916, 1916,
1915, 1915,
1914, 1914,
@@ -574,12 +574,12 @@ static const int included_patches[] = {
1910, 1910,
1909, 1909,
// 1908, // 1908,
// 1907, 1907,
// 1906, // 1906,
// 1905, // 1905,
// 1904, // 1904,
1903, 1903,
// 1902, 1902,
1901, 1901,
1900, 1900,
1899, 1899,
@@ -607,7 +607,7 @@ static const int included_patches[] = {
1877, 1877,
1876, 1876,
1875, 1875,
// 1874, 1874,
1873, 1873,
1872, 1872,
1871, 1871,
@@ -631,12 +631,12 @@ static const int included_patches[] = {
1853, 1853,
1852, 1852,
// 1851, // 1851,
// 1850, 1850,
1849, 1849,
1848, 1848,
1847, 1847,
1846, 1846,
// 1845, 1845,
1844, 1844,
1843, 1843,
1842, 1842,
@@ -667,7 +667,7 @@ static const int included_patches[] = {
1817, 1817,
1816, 1816,
1815, 1815,
// 1814, 1814,
// 1813, // 1813,
1812, 1812,
// 1811, // 1811,
@@ -692,28 +692,28 @@ static const int included_patches[] = {
1792, 1792,
1791, 1791,
1790, 1790,
// 1789, 1789,
1788, 1788,
// 1787, // 1787,
// 1786, 1786,
1785, 1785,
// 1784, // 1784,
1783, 1783,
1782, 1782,
1781, 1781,
1780, 1780,
// 1779, 1779,
// 1778, 1778,
1777, 1777,
1776, 1776,
1775, 1775,
1774, 1774,
// 1773, 1773,
1772, 1772,
1771, 1771,
// 1770, // 1770,
1769, 1769,
// 1768, 1768,
1767, 1767,
1766, 1766,
1765, 1765,
@@ -726,10 +726,10 @@ static const int included_patches[] = {
1758, 1758,
1757, 1757,
1756, 1756,
// 1755, 1755,
// 1754, 1754,
// 1753, 1753,
// 1752, 1752,
// 1751, // 1751,
1750, 1750,
1749, 1749,
@@ -748,7 +748,7 @@ static const int included_patches[] = {
1736, 1736,
1735, 1735,
1734, 1734,
// 1733, 1733,
1732, 1732,
1731, 1731,
1730, 1730,
@@ -762,7 +762,7 @@ static const int included_patches[] = {
1722, 1722,
1721, 1721,
1720, 1720,
// 1719, 1719,
// 1718, // 1718,
1717, 1717,
1716, 1716,
@@ -772,9 +772,9 @@ static const int included_patches[] = {
1712, 1712,
1711, 1711,
1710, 1710,
// 1709, 1709,
1708, 1708,
// 1707, 1707,
1706, 1706,
1705, 1705,
1704, 1704,
@@ -803,9 +803,9 @@ static const int included_patches[] = {
1681, 1681,
1680, 1680,
1679, 1679,
// 1678, 1678,
1677, 1677,
// 1676, 1676,
1675, 1675,
1674, 1674,
// 1673, // 1673,
@@ -815,8 +815,8 @@ static const int included_patches[] = {
1669, 1669,
1668, 1668,
1667, 1667,
// 1666, 1666,
// 1665, 1665,
1664, 1664,
1663, 1663,
1662, 1662,
@@ -825,17 +825,17 @@ static const int included_patches[] = {
// 1659, // 1659,
1658, 1658,
1657, 1657,
// 1656, 1656,
1655, 1655,
1654, 1654,
1653, 1653,
1652, 1652,
1651, 1651,
1650, 1650,
// 1649, 1649,
1648, 1648,
1647, 1647,
// 1646, 1646,
1645, 1645,
1644, 1644,
1643, 1643,
@@ -845,7 +845,7 @@ static const int included_patches[] = {
1639, 1639,
1638, 1638,
1637, 1637,
// 1636, 1636,
1635, 1635,
1634, 1634,
1633, 1633,
@@ -859,14 +859,14 @@ static const int included_patches[] = {
1625, 1625,
1624, 1624,
1623, 1623,
// 1622, 1622,
1621, 1621,
// 1620, 1620,
1619, 1619,
1618, 1618,
// 1617, 1617,
1616, 1616,
// 1615, 1615,
1614, 1614,
1613, 1613,
// 1612, // 1612,
@@ -879,13 +879,13 @@ static const int included_patches[] = {
1605, 1605,
1604, 1604,
1603, 1603,
// 1602, 1602,
1601, 1601,
// 1600, // 1600,
1599, 1599,
1598, 1598,
// 1597, // 1597,
// 1596, 1596,
1595, 1595,
1594, 1594,
1593, 1593,
@@ -919,7 +919,7 @@ static const int included_patches[] = {
1565, 1565,
1564, 1564,
1563, 1563,
// 1562, 1562,
// 1561, // 1561,
// 1560, // 1560,
// 1559, // 1559,
@@ -931,7 +931,7 @@ static const int included_patches[] = {
// 1553, // 1553,
1552, 1552,
1551, 1551,
// 1550, 1550,
1549, 1549,
// 1548, // 1548,
1547, 1547,
@@ -954,7 +954,7 @@ static const int included_patches[] = {
1530, 1530,
1529, 1529,
1528, 1528,
// 1527, 1527,
1526, 1526,
// 1525, // 1525,
1524, 1524,
@@ -1398,7 +1398,7 @@ static const int included_patches[] = {
1086, 1086,
1085, 1085,
1084, 1084,
// 1083, 1083,
1082, 1082,
1081, 1081,
1080, 1080,

View File

@@ -530,6 +530,47 @@ describe('cmdline', function()
/global^ | /global^ |
]]) ]])
end) end)
-- oldtest: Test_long_line_noselect()
it("long line is shown properly with noselect in 'wildmode'", function()
local screen = Screen.new(60, 8)
exec([[
set wildmenu wildoptions=pum wildmode=noselect,full
command -nargs=1 -complete=custom,Entries DoubleEntry echo
func Entries(a, b, c)
return 'loooooooooooooooong quite loooooooooooong, really loooooooooooong, probably too looooooooooooooooooooooooooong entry'
endfunc
]])
feed(':DoubleEntry <Tab>')
screen:expect([[
|
{1:~ }|*5
{1:~ }{4: loooooooooooooooong quite loooooooooooong, real}|
:DoubleEntry ^ |
]])
feed('<C-N>')
screen:expect([[
|
{1:~ }|*3
{3: }|
:DoubleEntry loooooooooooooooong quite loooooooooooong, real|
ly loooooooo{12: loooooooooooooooong quite loooooooooooong, real}|
ong entry^ |
]])
feed('<C-N>')
screen:expect([[
|
{1:~ }|*3
{3: }{4: loooooooooooooooong quite loooooooooooong, real}|
:DoubleEntry ^ |
|*2
]])
feed('<Esc>')
end)
end) end)
describe('cmdwin', function() describe('cmdwin', function()

View File

@@ -192,6 +192,41 @@ describe('vim.json.encode()', function()
) )
end) end)
it('indent', function()
eq('"Test"', exec_lua([[return vim.json.encode('Test', { indent = " " })]]))
eq('[]', exec_lua([[return vim.json.encode({}, { indent = " " })]]))
eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict(), { indent = " " })]]))
eq(
'[\n {\n "a": "a"\n },\n {\n "b": "b"\n }\n]',
exec_lua([[return vim.json.encode({ { a = "a" }, { b = "b" } }, { indent = " " })]])
)
eq(
'{\n "a": {\n "b": 1\n }\n}',
exec_lua([[return vim.json.encode({ a = { b = 1 } }, { indent = " " })]])
)
eq(
'[{"a":"a"},{"b":"b"}]',
exec_lua([[return vim.json.encode({ { a = "a" }, { b = "b" } }, { indent = "" })]])
)
eq(
'[\n [\n 1,\n 2\n ],\n [\n 3,\n 4\n ]\n]',
exec_lua([[return vim.json.encode({ { 1, 2 }, { 3, 4 } }, { indent = " " })]])
)
eq(
'{\nabc"a": {\nabcabc"b": 1\nabc}\n}',
exec_lua([[return vim.json.encode({ a = { b = 1 } }, { indent = "abc" })]])
)
-- Checks for for global side-effects
eq(
'[{"a":"a"},{"b":"b"}]',
exec_lua([[
vim.json.encode('', { indent = " " })
return vim.json.encode({ { a = "a" }, { b = "b" } })
]])
)
end)
it('dumps strings', function() it('dumps strings', function()
eq('"Test"', exec_lua([[return vim.json.encode('Test')]])) eq('"Test"', exec_lua([[return vim.json.encode('Test')]]))
eq('""', exec_lua([[return vim.json.encode('')]])) eq('""', exec_lua([[return vim.json.encode('')]]))

View File

@@ -181,6 +181,7 @@ describe('vim.lsp.inline_completion', function()
exec_lua(function() exec_lua(function()
vim.lsp.inline_completion.get() vim.lsp.inline_completion.get()
end) end)
n.poke_eventloop()
feed('<Esc>') feed('<Esc>')
screen:expect({ grid = grid_applied_candidates }) screen:expect({ grid = grid_applied_candidates })
end) end)
@@ -267,6 +268,7 @@ describe('vim.lsp.inline_completion', function()
exec_lua(function() exec_lua(function()
vim.lsp.inline_completion.get() vim.lsp.inline_completion.get()
end) end)
n.poke_eventloop()
feed('<Esc>') feed('<Esc>')
screen:expect([[ screen:expect([[
function fibonacci(n) { | function fibonacci(n) { |

View File

@@ -465,7 +465,7 @@ describe('vim.pack', function()
watch_events({ 'PackChangedPre', 'PackChanged' }) watch_events({ 'PackChangedPre', 'PackChanged' })
exec_lua(function() exec_lua(function()
-- Should provide event-data respecting manual and inferred default `version` -- Should provide event-data respecting manual `version` without inferring default
vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' }, repos_src.defbranch }) vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' }, repos_src.defbranch })
end) end)
@@ -473,11 +473,11 @@ describe('vim.pack', function()
local installpre_basic = find_in_log(log, 'PackChangedPre', 'install', 'basic', 'feat-branch') local installpre_basic = find_in_log(log, 'PackChangedPre', 'install', 'basic', 'feat-branch')
local installpre_defbranch = find_in_log(log, 'PackChangedPre', 'install', 'defbranch', nil) local installpre_defbranch = find_in_log(log, 'PackChangedPre', 'install', 'defbranch', nil)
local updatepre_basic = find_in_log(log, 'PackChangedPre', 'update', 'basic', 'feat-branch') local updatepre_basic = find_in_log(log, 'PackChangedPre', 'update', 'basic', 'feat-branch')
local updatepre_defbranch = find_in_log(log, 'PackChangedPre', 'update', 'defbranch', 'dev') local updatepre_defbranch = find_in_log(log, 'PackChangedPre', 'update', 'defbranch', nil)
local update_basic = find_in_log(log, 'PackChanged', 'update', 'basic', 'feat-branch') local update_basic = find_in_log(log, 'PackChanged', 'update', 'basic', 'feat-branch')
local update_defbranch = find_in_log(log, 'PackChanged', 'update', 'defbranch', 'dev') local update_defbranch = find_in_log(log, 'PackChanged', 'update', 'defbranch', nil)
local install_basic = find_in_log(log, 'PackChanged', 'install', 'basic', 'feat-branch') local install_basic = find_in_log(log, 'PackChanged', 'install', 'basic', 'feat-branch')
local install_defbranch = find_in_log(log, 'PackChanged', 'install', 'defbranch', 'dev') local install_defbranch = find_in_log(log, 'PackChanged', 'install', 'defbranch', nil)
eq(8, #log) eq(8, #log)
-- NOTE: There is no guaranteed installation order among separate plugins (as it is async) -- NOTE: There is no guaranteed installation order among separate plugins (as it is async)
@@ -571,11 +571,9 @@ describe('vim.pack', function()
eq({}, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }')) eq({}, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }'))
-- Plugins should still be marked as "active", since they were added -- Plugins should still be marked as "active", since they were added
plugindirs_data.spec.version = 'main'
plugindirs_data.active = true plugindirs_data.active = true
basic_data.spec.version = 'main'
basic_data.active = true basic_data.active = true
eq({ plugindirs_data, basic_data }, n.exec_lua('return vim.pack.get()')) eq({ plugindirs_data, basic_data }, exec_lua('return vim.pack.get(nil, { info = false })'))
end end
-- Works on initial install -- Works on initial install
@@ -623,7 +621,8 @@ describe('vim.pack', function()
'`basic`:\n', '`basic`:\n',
-- Should report available branches and tags if revision is absent -- Should report available branches and tags if revision is absent
'`wrong%-version`', '`wrong%-version`',
'Available:\nTags: some%-tag\nBranches: feat%-branch, main', -- Should list default branch first
'Available:\nTags: some%-tag\nBranches: main, feat%-branch',
-- Should report available branches and versions if no constraint match -- Should report available branches and versions if no constraint match
'`semver`', '`semver`',
'Available:\nVersions: v1%.0%.0, v0%.4, 0%.3%.1, v0%.3%.0.*\nBranches: main\n', 'Available:\nVersions: v1%.0%.0, v0%.4, 0%.3%.1, v0%.3%.0.*\nBranches: main\n',
@@ -665,6 +664,19 @@ describe('vim.pack', function()
eq('basic main', exec_lua('return require("basic")')) eq('basic main', exec_lua('return require("basic")'))
end) end)
it('is not affected by special environment variables', function()
fn.setenv('GIT_WORK_TREE', fn.getcwd())
fn.setenv('GIT_DIR', vim.fs.joinpath(fn.getcwd(), '.git'))
local ref_environ = fn.environ()
exec_lua(function()
vim.pack.add({ repos_src.basic })
end)
eq('basic main', exec_lua('return require("basic")'))
eq(ref_environ, fn.environ())
end)
it('validates input', function() it('validates input', function()
local validate = function(err_pat, input) local validate = function(err_pat, input)
local add_input = function() local add_input = function()
@@ -1143,8 +1155,8 @@ describe('vim.pack', function()
-- Should trigger relevant events only for actually updated plugins -- Should trigger relevant events only for actually updated plugins
n.exec('write') n.exec('write')
local log = exec_lua('return _G.event_log') local log = exec_lua('return _G.event_log')
eq(1, find_in_log(log, 'PackChangedPre', 'update', 'fetch', 'main')) eq(1, find_in_log(log, 'PackChangedPre', 'update', 'fetch', nil))
eq(2, find_in_log(log, 'PackChanged', 'update', 'fetch', 'main')) eq(2, find_in_log(log, 'PackChanged', 'update', 'fetch', nil))
eq(2, #log) eq(2, #log)
end) end)
@@ -1164,6 +1176,20 @@ describe('vim.pack', function()
eq({ 'return "fetch new 2"' }, fn.readfile(fetch_lua_file)) eq({ 'return "fetch new 2"' }, fn.readfile(fetch_lua_file))
end) end)
it('is not affected by special environment variables', function()
fn.setenv('GIT_WORK_TREE', fn.getcwd())
fn.setenv('GIT_DIR', vim.fs.joinpath(fn.getcwd(), '.git'))
local ref_environ = fn.environ()
exec_lua(function()
vim.pack.add({ repos_src.fetch })
vim.pack.update({ 'fetch' }, { force = true })
end)
eq({ 'return "fetch new 2"' }, fn.readfile(fetch_lua_file))
eq(ref_environ, fn.environ())
end)
it('validates input', function() it('validates input', function()
local validate = function(err_pat, input) local validate = function(err_pat, input)
local update_input = function() local update_input = function()
@@ -1180,7 +1206,7 @@ describe('vim.pack', function()
vim.pack.add({ repos_src.basic }) vim.pack.add({ repos_src.basic })
end) end)
validate('The following plugins are not installed: aaa, ccc', { 'aaa', 'basic', 'ccc' }) validate('Plugin `ccc` is not installed', { 'ccc', 'basic', 'aaa' })
-- Empty list is allowed with warning -- Empty list is allowed with warning
n.exec('messages clear') n.exec('messages clear')
@@ -1192,39 +1218,73 @@ describe('vim.pack', function()
end) end)
describe('get()', function() describe('get()', function()
local basic_spec = { name = 'basic', src = repos_src.basic, version = 'main' } local make_basic_data = function(active, info)
local basic_path = pack_get_plug_path('basic') local spec = { name = 'basic', src = repos_src.basic, version = 'feat-branch' }
local defbranch_spec = { name = 'defbranch', src = repos_src.defbranch, version = 'dev' } local path = pack_get_plug_path('basic')
local defbranch_path = pack_get_plug_path('defbranch') local res = { active = active, path = path, spec = spec }
if info then
res.branches = { 'main', 'feat-branch' }
res.rev = git_get_hash('feat-branch', 'basic')
res.tags = { 'some-tag' }
end
return res
end
local make_defbranch_data = function(active, info)
local spec = { name = 'defbranch', src = repos_src.defbranch }
local path = pack_get_plug_path('defbranch')
local res = { active = active, path = path, spec = spec }
if info then
res.branches = { 'dev', 'main' }
res.rev = git_get_hash('dev', 'defbranch')
res.tags = {}
end
return res
end
it('returns list with necessary data', function()
local basic_data, defbranch_data
it('returns list of available plugins', function()
-- Should work just after installation -- Should work just after installation
exec_lua(function() exec_lua(function()
vim.pack.add({ repos_src.defbranch, repos_src.basic }) vim.pack.add({ repos_src.defbranch, { src = repos_src.basic, version = 'feat-branch' } })
end) end)
eq({ defbranch_data = make_defbranch_data(true, true)
basic_data = make_basic_data(true, true)
-- Should preserve order in which plugins were `vim.pack.add()`ed -- Should preserve order in which plugins were `vim.pack.add()`ed
{ active = true, path = defbranch_path, spec = defbranch_spec }, eq({ defbranch_data, basic_data }, exec_lua('return vim.pack.get()'))
{ active = true, path = basic_path, spec = basic_spec },
}, exec_lua('return vim.pack.get()'))
-- Should also list non-active plugins -- Should also list non-active plugins
n.clear() n.clear()
exec_lua(function() exec_lua(function()
vim.pack.add({ repos_src.basic }) vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' } })
end) end)
eq({ defbranch_data = make_defbranch_data(false, true)
basic_data = make_basic_data(true, true)
-- Should first list active, then non-active -- Should first list active, then non-active
{ active = true, path = basic_path, spec = basic_spec }, eq({ basic_data, defbranch_data }, exec_lua('return vim.pack.get()'))
{ active = false, path = defbranch_path, spec = defbranch_spec },
}, exec_lua('return vim.pack.get()')) -- Should respect `names` for both active and not active plugins
eq({ basic_data }, exec_lua('return vim.pack.get({ "basic" })'))
eq({ defbranch_data }, exec_lua('return vim.pack.get({ "defbranch" })'))
eq({ defbranch_data, basic_data }, exec_lua('return vim.pack.get({ "defbranch", "basic" })'))
local bad_get_cmd = 'return vim.pack.get({ "ccc", "basic", "aaa" })'
matches('Plugin `ccc` is not installed', pcall_err(exec_lua, bad_get_cmd))
-- Should respect `opts.info`
defbranch_data = make_defbranch_data(false, false)
basic_data = make_basic_data(true, false)
eq({ basic_data, defbranch_data }, exec_lua('return vim.pack.get(nil, { info = false })'))
eq({ basic_data }, exec_lua('return vim.pack.get({ "basic" }, { info = false })'))
eq({ defbranch_data }, exec_lua('return vim.pack.get({ "defbranch" }, { info = false })'))
end) end)
it('respects `data` field', function() it('respects `data` field', function()
local out = exec_lua(function() local out = exec_lua(function()
vim.pack.add({ vim.pack.add({
{ src = repos_src.basic, data = { test = 'value' } }, { src = repos_src.basic, version = 'feat-branch', data = { test = 'value' } },
{ src = repos_src.defbranch, data = 'value' }, { src = repos_src.defbranch, data = 'value' },
}) })
local plugs = vim.pack.get() local plugs = vim.pack.get()
@@ -1236,7 +1296,7 @@ describe('vim.pack', function()
it('works with `del()`', function() it('works with `del()`', function()
exec_lua(function() exec_lua(function()
vim.pack.add({ repos_src.defbranch, repos_src.basic }) vim.pack.add({ repos_src.defbranch, { src = repos_src.basic, version = 'feat-branch' } })
end) end)
exec_lua(function() exec_lua(function()
@@ -1251,15 +1311,9 @@ describe('vim.pack', function()
-- Should not include removed plugins immediately after they are removed, -- Should not include removed plugins immediately after they are removed,
-- while still returning list without holes -- while still returning list without holes
exec_lua('vim.pack.del({ "defbranch" })') exec_lua('vim.pack.del({ "defbranch" })')
eq({ local defbranch_data = make_defbranch_data(true, true)
{ local basic_data = make_basic_data(true, true)
{ active = true, path = defbranch_path, spec = defbranch_spec }, eq({ { defbranch_data, basic_data }, { basic_data } }, exec_lua('return _G.get_log'))
{ active = true, path = basic_path, spec = basic_spec },
},
{
{ active = true, path = basic_path, spec = basic_spec },
},
}, exec_lua('return _G.get_log'))
end) end)
end) end)
@@ -1281,16 +1335,16 @@ describe('vim.pack', function()
eq(false, pack_exists('plugindirs')) eq(false, pack_exists('plugindirs'))
eq( eq(
"vim.pack: Removed plugin 'plugindirs'\nvim.pack: Removed plugin 'basic'", "vim.pack: Removed plugin 'basic'\nvim.pack: Removed plugin 'plugindirs'",
n.exec_capture('messages') n.exec_capture('messages')
) )
-- Should trigger relevant events in order as specified in `vim.pack.add()` -- Should trigger relevant events in order as specified in `vim.pack.add()`
local log = exec_lua('return _G.event_log') local log = exec_lua('return _G.event_log')
eq(1, find_in_log(log, 'PackChangedPre', 'delete', 'plugindirs', 'main')) eq(1, find_in_log(log, 'PackChangedPre', 'delete', 'basic', 'feat-branch'))
eq(2, find_in_log(log, 'PackChanged', 'delete', 'plugindirs', 'main')) eq(2, find_in_log(log, 'PackChanged', 'delete', 'basic', 'feat-branch'))
eq(3, find_in_log(log, 'PackChangedPre', 'delete', 'basic', 'feat-branch')) eq(3, find_in_log(log, 'PackChangedPre', 'delete', 'plugindirs', nil))
eq(4, find_in_log(log, 'PackChanged', 'delete', 'basic', 'feat-branch')) eq(4, find_in_log(log, 'PackChanged', 'delete', 'plugindirs', nil))
eq(4, #log) eq(4, #log)
end) end)
@@ -1310,7 +1364,7 @@ describe('vim.pack', function()
vim.pack.add({ repos_src.basic }) vim.pack.add({ repos_src.basic })
end) end)
validate('The following plugins are not installed: aaa, ccc', { 'aaa', 'basic', 'ccc' }) validate('Plugin `ccc` is not installed', { 'ccc', 'basic', 'aaa' })
eq(true, pack_exists('basic')) eq(true, pack_exists('basic'))
-- Empty list is allowed with warning -- Empty list is allowed with warning

View File

@@ -535,12 +535,40 @@ local function test_cmdline(linegrid)
{2:långfile1 }| {2:långfile1 }|
| |
]], ]],
cmdline = { { content = { { 'b långfile1' } }, firstc = ':', pos = 12 } },
popupmenu = { popupmenu = {
anchor = { -1, 0, 2 }, anchor = { -1, 0, 2 },
items = { { 'långfile1', '', '', '' }, { 'långfile2', '', '', '' } }, items = { { 'långfile1', '', '', '' }, { 'långfile2', '', '', '' } },
pos = 0, pos = 0,
}, },
cmdline = { { content = { { 'b långfile1' } }, firstc = ':', pos = 12 } }, }
feed('<Esc>')
command('silent %bwipe')
command('set shellslash')
-- position is correct when expanding environment variable #20348
command('silent cd test/functional/fixtures')
n.fn.setenv('XNDIR', 'wildpum/Xnamedir')
feed(':e $XNDIR/<Tab>')
screen:expect {
grid = [[
^ |
{1:~ }|*3
|
]],
cmdline = {
{
content = { { 'e wildpum/Xnamedir/XdirA/' } },
firstc = ':',
pos = 25,
},
},
popupmenu = {
anchor = { -1, 0, 19 },
items = { { 'XdirA/', '', '', '' }, { 'XfileA', '', '', '' } },
pos = 0,
},
} }
end) end)

View File

@@ -1060,6 +1060,7 @@ describe('builtin popupmenu', function()
[110] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkYellow }, [110] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkYellow },
[111] = { background = Screen.colors.Plum1, foreground = Screen.colors.DarkBlue }, [111] = { background = Screen.colors.Plum1, foreground = Screen.colors.DarkBlue },
[112] = { background = Screen.colors.Plum1, foreground = Screen.colors.DarkGreen }, [112] = { background = Screen.colors.Plum1, foreground = Screen.colors.DarkGreen },
[113] = { background = Screen.colors.Yellow, foreground = Screen.colors.Black },
-- popup non-selected item -- popup non-selected item
n = { background = Screen.colors.Plum1 }, n = { background = Screen.colors.Plum1 },
-- popup scrollbar knob -- popup scrollbar knob
@@ -4516,7 +4517,7 @@ describe('builtin popupmenu', function()
feed('<esc>') feed('<esc>')
-- Check "list" still works -- Check that when "longest" produces no result, "list" works
command('set wildmode=longest,list') command('set wildmode=longest,list')
feed(':cn<Tab>') feed(':cn<Tab>')
screen:expect([[ screen:expect([[
@@ -4529,6 +4530,8 @@ describe('builtin popupmenu', function()
cnfile cnoremenu | cnfile cnoremenu |
:cn^ | :cn^ |
]]) ]])
feed('<Tab>')
screen:expect_unchanged()
feed('s') feed('s')
screen:expect([[ screen:expect([[
| |
@@ -4694,6 +4697,108 @@ describe('builtin popupmenu', function()
feed('<Esc>') feed('<Esc>')
-- "longest:list" shows list whether it finds a candidate or not
command('set wildmode=longest:list,full wildoptions=')
feed(':cn<Tab>')
screen:expect([[
|
{1:~ }|*3
{3: }|
:cn |
cnewer cnoreabbrev |
cnext cnoremap |
cnfile cnoremenu |
:cn^ |
]])
feed('<Tab>')
screen:expect([[
|
{1:~ }|*2
{3: }|
:cn |
cnewer cnoreabbrev |
cnext cnoremap |
cnfile cnoremenu |
{113:cnewer}{3: cnext cnfile > }|
:cnewer^ |
]])
feed('<Esc>:sign u<Tab>')
screen:expect([[
|
{1:~ }|*5
{3: }|
:sign un |
undefine unplace |
:sign un^ |
]])
-- "longest:full" shows wildmenu whether it finds a candidate or not;
-- item not selected
feed('<Esc>')
command('set wildmode=longest:full,full')
feed(':sign u<Tab>')
screen:expect([[
|
{1:~ }|*7
{3:undefine unplace }|
:sign un^ |
]])
feed('<Tab>')
screen:expect([[
|
{1:~ }|*7
{113:undefine}{3: unplace }|
:sign undefine^ |
]])
feed('<Esc>:cn<Tab>')
screen:expect([[
|
{1:~ }|*7
{3:cnewer cnext cnfile > }|
:cn^ |
]])
feed('<Tab>')
screen:expect([[
|
{1:~ }|*7
{113:cnewer}{3: cnext cnfile > }|
:cnewer^ |
]])
-- If "longest,full" finds a candidate, wildmenu is not shown
feed('<Esc>')
command('set wildmode=longest,full')
feed(':sign u<Tab>')
screen:expect([[
|
{1:~ }|*8
:sign un^ |
]])
-- Subsequent wildchar shows wildmenu
feed('<Tab>')
screen:expect([[
|
{1:~ }|*7
{113:undefine}{3: unplace }|
:sign undefine^ |
]])
-- 'longest' does not find candidate, and displays menu without selecting item
feed('<Esc>')
command('set wildmode=longest,noselect')
feed(':cn<Tab>')
screen:expect([[
|
{1:~ }|*7
{3:cnewer cnext cnfile > }|
:cn^ |
]])
command('set wildmode& wildoptions=pum')
feed('<C-U><Esc>')
-- check positioning with multibyte char in pattern -- check positioning with multibyte char in pattern
command('e långfile1') command('e långfile1')
command('sp långfile2') command('sp långfile2')
@@ -4748,7 +4853,7 @@ describe('builtin popupmenu', function()
]]) ]])
feed('<esc>') feed('<esc>')
command('close') command('%bwipe')
command('set wildmode=full') command('set wildmode=full')
-- special case: when patterns ends with "/", show menu items aligned -- special case: when patterns ends with "/", show menu items aligned
@@ -4761,6 +4866,18 @@ describe('builtin popupmenu', function()
{1:~ }{n: file2 }{1: }| {1:~ }{n: file2 }{1: }|
:e compdir/file1^ | :e compdir/file1^ |
]]) ]])
-- position is correct when expanding environment variable #20348
command('cd ..')
fn.setenv('XNDIR', 'wildpum/Xnamedir')
feed('<C-U>e $XNDIR/<Tab>')
screen:expect([[
|
{1:~ }|*11
{1:~ }{12: XdirA/ }{1: }|
{1:~ }{n: XfileA }{1: }|
:e wildpum/Xnamedir/XdirA/^ |
]])
end) end)
end end
@@ -4877,24 +4994,52 @@ describe('builtin popupmenu', function()
-- pressing <Tab> should display the wildmenu -- pressing <Tab> should display the wildmenu
feed('<Tab>') feed('<Tab>')
screen:expect([[ local s1 = [[
| |
{1:~ }|*4 {1:~ }|*4
{1:~ }{12: undefine }{1: }| {1:~ }{12: undefine }{1: }|
{1:~ }{n: unplace }{1: }| {1:~ }{n: unplace }{1: }|
:sign undefine^ | :sign undefine^ |
]]) ]]
screen:expect(s1)
eq(1, fn.wildmenumode()) eq(1, fn.wildmenumode())
-- pressing <Tab> second time should select the next entry in the menu -- pressing <Tab> second time should select the next entry in the menu
feed('<Tab>') feed('<Tab>')
screen:expect([[ local s2 = [[
| |
{1:~ }|*4 {1:~ }|*4
{1:~ }{n: undefine }{1: }| {1:~ }{n: undefine }{1: }|
{1:~ }{12: unplace }{1: }| {1:~ }{12: unplace }{1: }|
:sign unplace^ | :sign unplace^ |
]]
screen:expect(s2)
eq(1, fn.wildmenumode())
-- If "longest" finds no candidate in "longest,full", "full" is used
feed('<Esc>')
command('set wildmode=longest,full')
command('set wildoptions=pum')
feed(':sign un<Tab>')
screen:expect(s1)
feed('<Tab>')
screen:expect(s2)
-- Similarly for "longest,noselect:full"
feed('<Esc>')
command('set wildmode=longest,noselect:full')
feed(':sign un<Tab>')
screen:expect([[
|
{1:~ }|*4
{1:~ }{n: undefine }{1: }|
{1:~ }{n: unplace }{1: }|
:sign un^ |
]]) ]])
feed('<Tab>')
screen:expect(s1)
feed('<Tab>')
screen:expect(s2)
end) end)
it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function() it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function()

View File

@@ -2286,8 +2286,11 @@ func Wildmode_tests()
" when using longest completion match, matches shorter than the argument " when using longest completion match, matches shorter than the argument
" should be ignored (happens with :help) " should be ignored (happens with :help)
set wildmode=longest,full set wildmode=longest,full
call feedkeys(":help a*\t\<C-B>\"\<CR>", 'xt') " XXX: This test is incorrect. ':help a*' will never yield 'help a'
call assert_equal('"help a', @:) " because '`a' exists as a menu item. The intent was to test a case
" handled by nextwild().
" call feedkeys(":help a*\t\<C-B>\"\<CR>", 'xt')
" call assert_equal('"help a', @:)
" non existing file " non existing file
call feedkeys(":e a1b2y3z4\t\<C-B>\"\<CR>", 'xt') call feedkeys(":e a1b2y3z4\t\<C-B>\"\<CR>", 'xt')
call assert_equal('"e a1b2y3z4', @:) call assert_equal('"e a1b2y3z4', @:)
@@ -2893,10 +2896,12 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "sign xyz\<Esc>:sign \<Tab>\<C-E>\<Up>") call term_sendkeys(buf, "sign xyz\<Esc>:sign \<Tab>\<C-E>\<Up>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_29', {}) call VerifyScreenDump(buf, 'Test_wildmenu_pum_29', {})
" Check "list" still works " Check that when "longest" produces no result, "list" works
call term_sendkeys(buf, "\<C-U>set wildmode=longest,list\<CR>") call term_sendkeys(buf, "\<C-U>set wildmode=longest,list\<CR>")
call term_sendkeys(buf, ":cn\<Tab>") call term_sendkeys(buf, ":cn\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_30', {}) call VerifyScreenDump(buf, 'Test_wildmenu_pum_30', {})
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_30', {})
call term_sendkeys(buf, "s") call term_sendkeys(buf, "s")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_31', {}) call VerifyScreenDump(buf, 'Test_wildmenu_pum_31', {})
@@ -2997,7 +3002,66 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "\<Esc>:set wildchazz\<Left>\<Left>\<Tab>\<C-Y>") call term_sendkeys(buf, "\<Esc>:set wildchazz\<Left>\<Left>\<Tab>\<C-Y>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_53', {}) call VerifyScreenDump(buf, 'Test_wildmenu_pum_53', {})
call term_sendkeys(buf, "\<C-U>\<CR>") call term_sendkeys(buf, "\<Esc>:set showtabline& laststatus& lazyredraw&\<CR>")
" "longest:list" shows list whether it finds a candidate or not
call term_sendkeys(buf, ":set wildmode=longest:list,full wildoptions&\<CR>")
call term_sendkeys(buf, ":cn\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_55', {})
call term_sendkeys(buf, "\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_56', {})
call term_sendkeys(buf, "\<Esc>:sign u\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_57', {})
" "longest:full" shows wildmenu whether it finds a candidate or not; item not selected
call term_sendkeys(buf, "\<Esc>:set wildmode=longest:full,full\<CR>")
call term_sendkeys(buf, ":sign u\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_58', {})
call term_sendkeys(buf, "\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_59', {})
call term_sendkeys(buf, "\<Esc>:cn\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_60', {})
call term_sendkeys(buf, "\<Tab>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_wildmenu_pum_61', {})
" If "longest,full" finds a candidate, wildmenu is not shown
call term_sendkeys(buf, "\<Esc>:set wildmode=longest,full\<CR>")
call term_sendkeys(buf, ":sign u\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_62', {})
" Subsequent wildchar shows wildmenu
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_63', {})
" 'longest' does not find candidate, and displays menu without selecting item
call term_sendkeys(buf, "\<Esc>:set wildmode=longest,noselect\<CR>")
call term_sendkeys(buf, ":cn\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_64', {})
" If "longest" finds no candidate in "longest,full", "full" is used
call term_sendkeys(buf, "\<Esc>:set wildmode=longest,full\<CR>")
call term_sendkeys(buf, ":set wildoptions=pum\<CR>")
call term_sendkeys(buf, ":sign un\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_09', {})
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_10', {})
" Similarly for "longest,noselect:full"
call term_sendkeys(buf, "\<Esc>:set wildmode=longest,noselect:full\<CR>")
call term_sendkeys(buf, ":sign un\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_65', {})
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_09', {})
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_10', {})
call term_sendkeys(buf, "\<C-U>\<Esc>")
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc
@@ -4406,7 +4470,7 @@ func Test_cmdcomplete_info()
call feedkeys(":h echom\<cr>", "tx") " No expansion call feedkeys(":h echom\<cr>", "tx") " No expansion
call assert_equal('{}', g:cmdcomplete_info) call assert_equal('{}', g:cmdcomplete_info)
call feedkeys($":h echoms{trig}\<cr>", "tx") call feedkeys($":h echoms{trig}\<cr>", "tx")
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
call feedkeys($":h echom{trig}\<cr>", "tx") call feedkeys($":h echom{trig}\<cr>", "tx")
call assert_equal( call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}', \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
@@ -4422,7 +4486,7 @@ func Test_cmdcomplete_info()
set wildoptions=pum set wildoptions=pum
call feedkeys($":h echoms{trig}\<cr>", "tx") call feedkeys($":h echoms{trig}\<cr>", "tx")
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
call feedkeys($":h echom{trig}\<cr>", "tx") call feedkeys($":h echom{trig}\<cr>", "tx")
call assert_equal( call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}', \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
@@ -4874,4 +4938,33 @@ func Test_cmdline_changed()
call Ntest_override("char_avail", 0) call Ntest_override("char_avail", 0)
endfunc endfunc
" Issue #18035: long lines should not get listed twice in the menu when
" 'wildmode' contains 'noselect'
func Test_long_line_noselect()
CheckScreendump
let lines =<< trim [SCRIPT]
set wildmenu wildoptions=pum wildmode=noselect,full
command -nargs=1 -complete=custom,Entries DoubleEntry echo
func Entries(a, b, c)
return 'loooooooooooooooong quite loooooooooooong, really loooooooooooong, probably too looooooooooooooooooooooooooong entry'
endfunc
[SCRIPT]
call writefile(lines, 'XTest_wildmenu', 'D')
let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8, 'cols': 60})
call term_sendkeys(buf, ":DoubleEntry \<Tab>")
call VerifyScreenDump(buf, 'Test_long_line_noselect_1', {})
call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>")
call VerifyScreenDump(buf, 'Test_long_line_noselect_2', {})
call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>\<C-N>")
call VerifyScreenDump(buf, 'Test_long_line_noselect_3', {})
" clean up
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -5620,7 +5620,7 @@ func Test_completetimeout_autocompletetimeout()
set completetimeout=1 set completetimeout=1
call feedkeys("Gof\<C-N>\<F2>\<Esc>0", 'xt!') call feedkeys("Gof\<C-N>\<F2>\<Esc>0", 'xt!')
let match_count = len(b:matches->mapnew('v:val.word')) let match_count = len(b:matches->mapnew('v:val.word'))
call assert_true(match_count < 2000) call assert_true(match_count < 4000)
set completetimeout=1000 set completetimeout=1000
call feedkeys("\<Esc>Sf\<C-N>\<F2>\<Esc>0", 'xt!') call feedkeys("\<Esc>Sf\<C-N>\<F2>\<Esc>0", 'xt!')