Compare commits

..

91 Commits

Author SHA1 Message Date
Justin M. Keyes
a9a3981669 NVIM v0.11.1
For notable changes, see runtime/doc/news.txt (or `:help news` in Nvim).

Following is a list of fixes/features commits.

BREAKING
--------------------------------------------------------------------------------
- bbf912d72f provider: drop Python 3.7, 3.8 support #33088

FEATURES
--------------------------------------------------------------------------------
- 66953b16a2 lsp: workspace_required (#33608)
- 7efb3ba6f7 checkhealth: use emoji for OK/WARN/ERROR (#33195)
- 91d11c8bc1 clipboard: g:clipboard="foo" forces the "foo" clipboard tool #33235
- 12da443930 float: 'winborder' "bold" style #33189
- 5829b5de0a vim.hl: allow multiple timed highlights simultaneously #33283

FIXES
--------------------------------------------------------------------------------
- 91481ae7d5 bug in stylize_markdown
- 5fc6bd6454 api: nvim_set_keymap() throws error even in pcall() #33228
- 2b2a90051e api: use E226 instead of E227 for duplicate abbreviation (#33159)
- 056dbf3ea7 api: use original LHS in keymap error message #33135
- fb71d631a5 api: wrong return value with reverse range + overlap #32956
- fcee5df0fc checkhealth: check g:loaded_xx_provider for all providers #33168
- 89e0ea1788 checkhealth: check outdated pynvim version properly #33175
- adfd4b9f4f checkhealth: don't override user "q" keymap #33132
- 06df3e0c0d cmdline: avoid empty @: register after :<CR> (#33126)
- 53def2a877 cmdline: empty ext_cmdline block events for :<CR> #33118
- b8e5fd51fd column: don't count signs on lines beyond eob #33410
- e4007551c4 completion: avoid freeing uninitialized value (#33459)
- 6e51d39696 decor: enable decoration provider in on_start #33337
- 837c9d0409 defaults: enable :terminal [[,]] motion in operator-pending mode #33217
- 2182272139 defaults: keywordprg=:help on Windows #33336
- 7e884b78bf defaults: visual-mode [[,]] for :terminal shell prompts #33203
- 2a04161a35 desktop: cannot open filename with spaces using OS file manager #33161
- 2cd735d159 display: scroll logic does not take into account concealed topline (#33054)
- c4a19bff4e display: scroll redrawing doesn't account for virt_lines above fold #33374
- 02123bac0d display: wrong cursor column with 'concealcursor' = "n" and virt_text (#33218)
- 837faf7065 editor: respect [+cmd] when executing :drop #33339
- 155529b91a events: avoid superfluous CursorMovedI on first autocmd (#33588)
- c158d41cec health: expecting nonexistent "inotifywait" function #33312
- 06c2886569 health: message should mention "vim.provider" #33095
- 279a0e78c9 highlight: no match highlight during :substitute prompt #33262
- b5158e8e92 lsp: "bold" border for vim.lsp.buf.hover #33395
- 1e8e74dbff lsp: better handling of "*" configs
- 478f5d0070 lsp: cycling signatures with the default `config.focusable`
- 2435d72283 lsp: opts.reuse_win does not jump if buf is already open #33476
- 95f96a3d1b lsp: prioritize showing active signature
- a9afa6b152 lsp: warn on missing config in :checkhealth #33087
- 2b14447803 man.lua: noisy "ENOENT" error on Windows #33435
- 8aa49a8e9b man.lua: useless executability check #33438
- 4d87229789 marks: clamp conceal_lines corrected line number #33464
- 9da90af0f7 marks: wrong display after inserting/deleting lines #33389
- 3b0c88a537 messages: single msg_show event for multiple :set options #33555
- 3df9db58dc messages: verbose message emitted without kind #33305
- c61e8c6e70 mouse: crash with click on win-separator in statusline (#33091)
- dcd5e4574a mouse: do not fetch clipboard twice when pasting with middle button #33494
- 526444c4ff mouse: mouseclick after conceal_lines is miscalculated #33451
- 326eacef93 move: adjust for concealed lines above topline after scrolling up (#33211)
- 649bce6e73 provider: misleading :checkhealth if user sets g:loaded_python3_provider=1 #32696
- c57a36cd59 pum: fix heap-buffer-overflow with 'rightleft' (#33146)
- c1d3777db2 snippet: use <cmd>call cursor() for visual range
- 70f3e15298 treesitter: don't memoize modified headings (#33186)
- e342b9a25a treesitter: fix `:InspectTree` incorrect injections
- 4c1121bd33 treesitter: not refreshing virtualtext contents #33361
- 646a8f663e tui: ensure all pending escape sequences are processed before exiting #32151
- 9909580df2 ui: exclude unfocusable windows from 'complete' "w" completion
- ccb078bbb0 ui: wincmd _ should not increase 'cmdheight' above 0 (#33056)
- 29011e4d45 vim.hl: nvim_buf_del_extmark on invalid buffer #33331
- 9056c01a95 vim.lsp.inlay_hint: requesting inlay_hints even when disabled #32999
- 4422b9bbd0 vim.system: unclear non-executable message #33455
- a4b6705e87 window: crash on negative window height with 'winbar' #33250

PERFORMANCE
--------------------------------------------------------------------------------
- b9c9b15ad7 snippet: use "[count]|" to move cursor #33571

VIM PATCHES
--------------------------------------------------------------------------------
- a97713485d 9.0.1653: Amiga: default 'viewdir' may not work
- cdd3f2a2e6 9.0.1654: MS-Windows: test for default 'viewdir' fails
- b7de104d86 9.1.0721: tests: test_mksession does not consider XDG_CONFIG_HOME
- 6514e2c7ba 9.1.1247: fragile setup to get (preferred) keys from key_name_entry (#33102)
- 2084cda6f9 9.1.1260: Hang when filtering buffer with NUL bytes (#33192)
- 02bf23b4bf 9.1.1269: completion: compl_shown_match is updated when starting keyword completion
- e3506ede27 9.1.1272: completion: in keyword completion Ctrl_P cannot go back after Ctrl_N
- a92155b86b 9.1.1286: filetype: help files not detected when 'iskeyword' includes ":" (#33377)
- b694131c3b 9.1.1303: missing out-of-memory check in linematch.c (#33487)
- 0c315feddf 9.1.1305: completion menu active after switching windows/tabs (#33488)
- 12298be0fe 9.1.1310: completion: redundant check for preinsert effect (#33505)
- 4205fdee1d 9.1.1314: max allowed string width too small
- 248528c907 9.1.1317: noisy error when restoring folds from session fails
- 1a6ddeee41 9.1.1318: tests: test_format fails
- 448c2cec9d 9.1.1337: Undo corrupted with 'completeopt' "preinsert" when switching buffer (#33600)
2025-04-26 16:29:18 +02:00
Yi Ming
478f5d0070 fix(lsp): cycling signatures with the default config.focusable
(cherry picked from commit 342974773c)
2025-04-26 13:55:12 +00:00
Yi Ming
95f96a3d1b fix(lsp): prioritize showing active signature
(cherry picked from commit 9e93bfdb5f)
2025-04-26 13:55:12 +00:00
Luuk van Baal
9909580df2 fix(ui): exclude unfocusable windows from 'complete' "w" completion
Problem:  As in f85bc41, assume unfocusable windows to be UI windows
          whose buffer content is unexpectedly included in 'complete'
          "w" completion.
Solution: Exclude unfocusable windows when looping over windows.
(cherry picked from commit d01b2611a6)
2025-04-25 23:19:28 +00:00
Justin M. Keyes
66953b16a2 feat(lsp): workspace_required (#33608)
Problem:
Some language servers do not work properly without a workspace folder.

Solution:
Add `workspace_required`, which skips starting the lsp client if no
workspace folder is found.

Co-authored-by: Michael Strobel <71396679+Kibadda@users.noreply.github.com>
2025-04-24 07:06:30 -07:00
zeertzjq
448c2cec9d vim-patch:9.1.1337: Undo corrupted with 'completeopt' "preinsert" when switching buffer (#33600)
Problem:  Undo corrupted with 'completeopt' "preinsert" when switching
          buffer or window.
Solution: Do not delete preinsert text when switching buffer or window.
          (zeertzjq)

related: neovim/neovim#33581
closes: vim/vim#17193

1343681aba
(cherry picked from commit 63689deb45)
2025-04-24 00:45:04 +00:00
Luuk van Baal
c1d3777db2 fix(snippet): use <cmd>call cursor() for visual range
Problem:  Change applied in d3e495ce uses a byte-offset where a virtual
          column is expected.
Solution: Set the cursor directly through a <Cmd> mapping, while making
          sure the commands are ordered correctly by adding them to the
          type-ahead buffer.
(cherry picked from commit 019b2050e1)
2025-04-23 09:24:54 +00:00
zeertzjq
155529b91a fix(events): avoid superfluous CursorMovedI on first autocmd (#33588)
(cherry picked from commit 1dbede5b93)
2025-04-23 03:47:35 +00:00
zeertzjq
c633250cc0 Merge pull request #33589 from zeertzjq/backport
vim-patch:9.1.1305: completion menu active after switching windows/tabs (#33488)
2025-04-23 11:42:36 +08:00
zeertzjq
0c315feddf vim-patch:9.1.1305: completion menu active after switching windows/tabs (#33488)
Problem:  When switching to another window or tab page while the
          completion menu is active, the menu stays visible, although it
          belongs to the previous window/tab page context (Evgeni
          Chasnovski).
Solution: Track the window and tab page where completion started. Detect
          changes in the main editing loop and cancel completion mode if
          the current window or tab page differs from where completion
          started.

fixes: vim/vim#17090
closes: vim/vim#17101

cf7f01252f

Co-authored-by: glepnir <glephunter@gmail.com>
2025-04-23 11:09:01 +08:00
Gregory Anders
646a8f663e fix(tui): ensure all pending escape sequences are processed before exiting #32151
Problem:
Neovim disables a number of terminal modes when it exits, some of which
cause the terminal to send asynchronous events to Neovim. It's possible
that Neovim exits before the terminal has received and processed all of
the sequences to disable these modes, causing the terminal to emit one
of these asynchronous sequences after Neovim has already exited. If this
happens, then the sequence is received by the user's shell (or some
other program that is not Neovim).

Solution:
When Neovim exits, it now emits a Device Attributes request (DA1)
after disabling all of the different modes. When the terminal responds
to this request we know that it has already received all of our other
sequences disabling the other modes. At that point, it should not be
emitting any further asynchronous sequences. This means the process of
exiting Neovim is now asynchronous as well since it depends on receiving
the DA1 response from the terminal.

(cherry picked from commit 82f08f33c1)
2025-04-22 12:51:47 +00:00
luukvbaal
b9c9b15ad7 perf(snippet): use "[count]|" to move cursor #33571
Problem:
Flicker when using vim.snippet.jump().

Solution:
Pass count instead of multiple <right> keys.

(cherry picked from commit d3e495ce03)
2025-04-22 12:21:35 +00:00
luukvbaal
fb71d631a5 fix(api): wrong return value with reverse range + overlap #32956
Problem:  When iterating in reverse with {start} > {end} in
          `nvim_buf_get_extmarks()`, marks that overlap {start} and are
          greater than {end} are included in the return value twice.
          Marks that overlap {end} and do not overlap {start} are not
          not included in the return value at all. Marks are not
          actually returned in a meaningful "traversal order".

Solution: Rather than actually iterating in reverse, (also possible but
          requires convoluted conditions and would require fetching
          overlapping marks for both the {start} and {end} position,
          while still ending up with non-traversal ordered marks),
          iterate normally and reverse the return value.
(cherry picked from commit 65170e8dad)
2025-04-21 23:49:27 +00:00
luukvbaal
3b0c88a537 fix(messages): single msg_show event for multiple :set options #33555
Problem:  :set opt1 opt2... emits a separate event for each option.

Solution: Only set the kind for the first printed option value.
(cherry picked from commit 986b92eb07)
2025-04-21 16:23:38 +00:00
zeertzjq
1a6ddeee41 vim-patch:9.1.1318: tests: test_format fails
Problem:  tests: test_format fails (after 9.1.1314).
Solution: Increase the string size.  Add missing test_format.res in
          NEW_TESTS_RES (zeertzjq).

closes: vim/vim#17144

e9a27ef373
(cherry picked from commit 0251a25541)
2025-04-19 00:12:55 +00:00
zeertzjq
4205fdee1d vim-patch:9.1.1314: max allowed string width too small
Problem:  max allowed string width too small
Solution: increased MAX_ALLOWED_STRING_WIDTH from 6400 to 1MiB
          (Hirohito Higashi)

closes: vim/vim#17138

06fdfa11c5

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: John Marriott <basilisk@internode.on.net>
(cherry picked from commit ccdb37b075)
2025-04-19 00:12:55 +00:00
zeertzjq
248528c907 vim-patch:9.1.1317: noisy error when restoring folds from session fails
Problem:  noisy error when restoring folds from session fails
Solution: ignore errors silently when sourcing session file.
          (Igor Lacerda)

fixes: vim/vim#15813
closes: vim/vim#17127

cca5dea76e

Co-authored-by: Igor Lacerda <igorlfs@ufmg.br>
(cherry picked from commit e2e6c159d3)
2025-04-18 01:04:01 +00:00
zeertzjq
b7de104d86 vim-patch:9.1.0721: tests: test_mksession does not consider XDG_CONFIG_HOME
Problem:  tests: test_mksession does not consider XDG_CONFIG_HOME
Solution: allow to match $HOME/.vim/ and $HOME/.config/vim for &viewdir
          (John M Devin)

closes: vim/vim#15639

5b9237c2e7

Co-authored-by: John M Devin <john.m.devin@gmail.com>
(cherry picked from commit 0eb708aa8a)
2025-04-18 01:04:01 +00:00
zeertzjq
cdd3f2a2e6 vim-patch:9.0.1654: MS-Windows: test for default 'viewdir' fails
Problem:    MS-Windows: test for default 'viewdir' fails.
Solution:   Escape the pattern.

813b7a85f2

Co-authored-by: Bram Moolenaar <Bram@vim.org>
(cherry picked from commit bd0555ecd4)
2025-04-18 01:04:01 +00:00
zeertzjq
a97713485d vim-patch:9.0.1653: Amiga: default 'viewdir' may not work
Problem:    Amiga: default 'viewdir' may not work.
Solution:   Use "home:" instead of "$VIM". Add a test. (Christian Brabandt,
            closes vim/vim#12576)

b8b1c8ebd4

Cherry-pick Test_mkview_manual_fold() changes from 9.0.{0363,0626}.

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 827cfe4a76)
2025-04-18 01:04:01 +00:00
zeertzjq
12298be0fe vim-patch:9.1.1310: completion: redundant check for preinsert effect (#33505)
Problem:  Duplicate check for preinsert effect, particularly for Ctrl_w
          and Ctrl_U.
Solution: Remove the specific check for Ctrl_w and Ctrl_U to eliminate
          redundancy (glepnir).

closes: vim/vim#17129

1c2b258250

Co-authored-by: glepnir <glephunter@gmail.com>
(cherry picked from commit f9f6dc4262)
2025-04-17 23:25:23 +00:00
Au.
2435d72283 fix(lsp): opts.reuse_win does not jump if buf is already open #33476
Problem:
`vim.lsp.buf.[implementation|definition|...]({ reuse_win = true })` does not
jump cursor to existing window if buffer is already open.

Steps to reproduce:
1. `nvim repro.lua`
2. Insert anything that lsp can read to open the library definition/implementation, e.g., `vim.keymap.set`
3. open `repro.lua` buffer and the library buffer side by side.
4. type `gd` over `set` to jump to the library definition.

The open buffer is scrolled to the target line, but cursor does not jump.

Solution:
Call nvim_set_current_win if necessary.

(cherry picked from commit 6926fc1615)
2025-04-17 15:12:46 +00:00
yuukibarns
e342b9a25a fix(treesitter): fix :InspectTree incorrect injections
(cherry picked from commit 284b0e4fa2)
2025-04-16 14:31:32 +00:00
Justin M. Keyes
4422b9bbd0 fix(vim.system): unclear non-executable message #33455
Problem:
When a command is not found or not executable, the error message gives
no indication about what command was actually tried.

Solution:
Always append the command name to the error message.

BEFORE:

    E5108: Error executing lua …/_system.lua:248: ENOENT: no such file or directory

AFTER:

    E5108: Error executing lua …/_system.lua:249: ENOENT: no such file or directory: "foo"

fix #33445

(cherry picked from commit 223ac7782e)
2025-04-16 12:38:46 +00:00
Dmitry Torokhov
dcd5e4574a fix(mouse): do not fetch clipboard twice when pasting with middle button #33494
Problem:
When doing paste operation mouse code tries to figure out it it is
dealing with a multi-line register by calling yank_register_mline(),
which fetches register data and checks its type. Later the code calls
either do_put() or insert_reg() which fetch register data again. This is
unnoticeable when working with internal neovim registers, but starts
hurting when dealing with clipboards, especially remote one (forwarded X
or socket tunnel or similar).

Solution:
Change yank_register_mline() to also return pointer to the
register structure prepared for pasting, and insert_reg() to accept
such register pointer and use it if it is supplied. do_put() already
has support for accepting a register structure to be used for pasting.

Fixes #33493

(cherry picked from commit 7432781e71)
2025-04-16 10:50:01 +00:00
zeertzjq
b694131c3b vim-patch:9.1.1303: missing out-of-memory check in linematch.c (#33487)
Problem:  missing out-of-memory check in linematch.c
Solution: return early in case of memory allocation failure, move the
          pow() calculation ouside of the for() loop
          (John Marriott)

closes: vim/vim#17118

2137710b43

Co-authored-by: John Marriott <basilisk@internode.on.net>
(cherry picked from commit d2d1b5e944)
2025-04-15 23:37:37 +00:00
luukvbaal
4d87229789 fix(marks): clamp conceal_lines corrected line number #33464
Problem:  Line number corrected for conceal_lines may be set beyond eob
          when the last buffer line is concealed, causing ml_get errors.

Solution: Avoid setting line number beyond eob.
(cherry picked from commit 3341ab0776)
2025-04-14 11:38:29 +00:00
zeertzjq
e4007551c4 fix(completion): avoid freeing uninitialized value (#33459)
(cherry picked from commit 51caf0a3af)
2025-04-14 05:31:00 +00:00
luukvbaal
526444c4ff fix(mouse): mouseclick after conceal_lines is miscalculated #33451
Problem:  Computed buffer line for mouse position does not take into
          account concealed lines on the reached row.

Solution: Adjust for concealed lines at the end of the loop computing
          the buffer position.
(cherry picked from commit 2f8fb4f28a)
2025-04-13 21:57:00 +00:00
Emanuel Krollmann
8aa49a8e9b fix(man.lua): useless executability check #33438
Problem:
executability check using `uv.fs_access`
doesn't work currently and can't work on windows

Solution:
only check for executable with `vim.fn.executable`

(cherry picked from commit b8763cb215)
2025-04-12 23:53:54 +00:00
neovim-backports[bot]
2b14447803 fix(man.lua): noisy "ENOENT" error on Windows #33435
Problem:
:Man shows noisy "ENOENT: no such file or directory" error on Windows.

Solution:
Do some checks before calling `vim.system`.

(cherry picked from commit a8dd5c7e41)

Co-authored-by: Emanuel Krollmann <115734183+Sodastream11@users.noreply.github.com>
2025-04-12 15:53:32 -07:00
Justin M. Keyes
7384983721 docs: clipboard, eval #33328 2025-04-12 10:56:28 -07:00
luukvbaal
b8e5fd51fd fix(column): don't count signs on lines beyond eob #33410
Problem:  Computed previous buffer line count may be beyond end of
          buffer. This results in signs being removed from `b_signcols`
          that were never included in it, tripping an assertion.

Solution: Store the previous line count as it was before appending or
          deleting lines. Use it to clamp the edited region when
          clearing signs before a splice, after which it is reset.
(cherry picked from commit 4a706a7092)
2025-04-11 12:28:22 +00:00
luukvbaal
9da90af0f7 fix(marks): wrong display after inserting/deleting lines #33389
Problem:  Lines to/from which virt_lines or inline virt_text may have
          moved are left valid. Similarly the modified region may be
          too small to account for moved decorations after inserting
          or deleting lines. `redrawOneLine()` can be replaced with
          a call to `changed_lines_redraw_buf()`.

Solution: Invalidate the line after a change if there is virt_lines, or
          inline virt_text in the buffer with 'wrap' enabled. Extend the
          modified region for inserted or deleted lines if there may be
          decorations in the buffer. Remove `redrawOneLine()`.
          Simplify the logic for `changed_lines_invalidate_win()`.

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
(cherry picked from commit 064ff74cdb)
2025-04-11 12:03:53 +00:00
Siddhant Agarwal
b5158e8e92 fix(lsp): "bold" border for vim.lsp.buf.hover #33395
Problem: vim.lsp.buf.hover allows a bold border size which hasn't been
defined

Solution: Define the bold border size for vim.lsp.buf.hover
(cherry picked from commit f068386c9f)
2025-04-09 11:57:22 +00:00
jyn
837faf7065 fix(editor): respect [+cmd] when executing :drop #33339
Problem:
Normally, `:drop +41 foo.txt` will open foo.txt with the cursor on line
41. But if foo.txt is already open, it instead is a no-op, even if the
cursor is on a different line.

Steps to reproduce:

    nvim --clean foo.txt
    :drop +30 foo.txt

Solution:
Handle +cmd in ex_drop().

(cherry picked from commit 3647b821ea)
2025-04-08 13:47:08 +00:00
luukvbaal
c4a19bff4e fix(display): scroll redrawing doesn't account for virt_lines above fold #33374
Problem:  Logic computing the new height of the modified area does not
          take into account virtual lines attached to a folded line.

Solution: Remove `hasFolding()` branch and let `plines_win_full()` do its job.
(cherry picked from commit 5b1561bb71)
2025-04-08 13:20:27 +00:00
zeertzjq
a92155b86b vim-patch:9.1.1286: filetype: help files not detected when 'iskeyword' includes ":" (#33377)
Problem:  Help files not detected when 'iskeyword' includes ":".
Solution: Do not use \< and \> in the pattern (zeertzjq).

fixes: vim/vim#17069
closes: vim/vim#17071

e370141bf4
(cherry picked from commit 8af9f8ab5e)
2025-04-08 00:52:17 +00:00
luukvbaal
6e51d39696 fix(decor): enable decoration provider in on_start #33337
Problem:  An on_win-disabled decoration provider is left disabled for
          the on_buf callback during the next redraw (if the provider
          does not subscribe to on_end).

Solution: Move re-activation of the provider from after the on_end
          callback to before the on_start callback.
(cherry picked from commit ca16b54c86)
2025-04-07 11:33:43 +00:00
Dmitry Zolotukhin
4c1121bd33 fix(treesitter): not refreshing virtualtext contents #33361
Problem: In some cases, when treesitter is enabled, deleting a
line below virtualtext will not refresh all updated lines.
https://github.com/neovim/neovim/issues/33358

Solution: Revert a part of https://github.com/neovim/neovim/pull/31324
to ensure that the full range (with virtual lines) is refreshed.

(cherry picked from commit cf59631f65)
2025-04-07 11:30:12 +00:00
Felipe Lema
c158d41cec fix(health): expecting nonexistent "inotifywait" function #33312
Problem:
55e4301036 changed the program name but not the function name.

Solution:
Fix the healthcheck.

(cherry picked from commit bd37348939)
2025-04-07 09:40:09 +00:00
Emanuel Krollmann
2182272139 fix(defaults): keywordprg=:help on Windows #33336
Problem:
As `:h kp` says, the default value for keywordprg
should be ':help' on Windows. It is currently
always ':Man'.

Solution:
Add condition to options.lua which sets keywordprg
to ':help' if running on windows.

(cherry picked from commit 3ebde5ea14)
2025-04-07 09:35:36 +00:00
phanium
29011e4d45 fix(vim.hl): nvim_buf_del_extmark on invalid buffer #33331
Problem:
nvim_buf_del_extmark error if buffer is destroyed before timer stops

Solution:
check nvim_buf_is_valid.

(cherry picked from commit 28e8190185)
2025-04-05 23:19:19 +00:00
Lewis Russell
91481ae7d5 fix: bug in stylize_markdown
`stripped` and `markdown_lines` are iterated together so must have the same length.

(cherry picked from commit 379c37fa0b)
2025-04-04 14:08:52 +00:00
luukvbaal
3df9db58dc fix(messages): verbose message emitted without kind #33305
Problem:  Successive autocmd verbose messages may be emitted without a kind.

Solution: Always set the kind when preparing to emit a verbose message.
(cherry picked from commit 98f5aa2564)
2025-04-04 12:53:23 +00:00
glepnir
e3506ede27 vim-patch:9.1.1272: completion: in keyword completion Ctrl_P cannot go back after Ctrl_N
Problem:  completion: in keyword completion Ctrl_P cannot go back after
          Ctrl_N
Solution: in find_compl_when_fuzzy() always return first match of array, after Ctrl_P
          use compl_shown_match->cp_next instead of compl_first_match.
          (glepnir)

closes: vim/vim#17043

3e50a28a03

Co-authored-by: glepnir <glephunter@gmail.com>
(cherry picked from commit b01921cb55)
2025-04-04 06:40:34 +00:00
glepnir
02bf23b4bf vim-patch:9.1.1269: completion: compl_shown_match is updated when starting keyword completion
Problem:  compl_shown_match is updated when starting keyword completion
          and does not include fuzzy matching.
Solution: Do not update compl_shown_match when starting keyword
          completion, since it is the one already selected by the
          keyword completion direction. (glepnir)

closes: vim/vim#17033

e4e4d1c381

Co-authored-by: glepnir <glephunter@gmail.com>
(cherry picked from commit 8cf413e450)
2025-04-04 06:40:34 +00:00
tstsrt
cbf4906c11 test(plugin/shada_spec): failure if timezone isn't a whole hour ahead of UTC (#33257)
Problem: When running functional tests locally, test `syntax/shada.vim works`
fails if the local timezone is not a whole number of hours ahead of UTC.

Solution: Use '!%M' for minute format so that UTC is used in the expected
timestamp instead of the local timezone, just like '%H' for hours.

(cherry picked from commit d9405c7935)
2025-04-04 04:24:11 +00:00
zeertzjq
4cc97cf009 Merge pull request #33295 from siddhantdev/backport-33283-to-release-0.11
feat(vim.hl): allow multiple timed highlights simultaneously #33283
2025-04-04 09:50:29 +08:00
zeertzjq
c6ef13dc45 test(lua/hl_spec): fix hang on exit with ASAN (#33298) 2025-04-04 09:25:39 +08:00
zeertzjq
1a2d0484ac docs: news.txt 2025-04-04 09:25:14 +08:00
Siddhant Agarwal
5829b5de0a feat(vim.hl): allow multiple timed highlights simultaneously #33283
Problem: Currently vim.hl.range only allows one timed highlight.
Creating another one, removes the old one.

Solution: vim.hl.range now returns a timer and a function. The timer
keeps track of how much time is left in the highlight and the function
allows you to clear it, letting the user decide what to do with old
highlights.

(cherry picked from commit eae2d3b145)
2025-04-04 00:14:43 +05:30
Evgeni Chasnovski
dd547ef1ea docs(diagnostic): mention severity in Opts.VirtualLines (#33293)
Problem: `severity` field is recognized by
  `vim.diagnostic.Opts.VirtualLines`, but it is not explicitly
  documented.

Solution: document it.
(cherry picked from commit 71e133e5e6)
2025-04-03 16:49:58 +00:00
Deveshi Dwivedi
91d11c8bc1 feat(clipboard): g:clipboard="foo" forces the "foo" clipboard tool #33235
(cherry picked from commit 9722bd7b1b)
2025-04-03 14:26:45 +00:00
zeertzjq
1daea6e1fd test(lua/secure_spec): fix failure with long path (#33280)
Ref #33278

(cherry picked from commit 974a3aa2c4)
2025-04-03 13:56:49 +00:00
luukvbaal
279a0e78c9 fix(highlight): no match highlight during :substitute prompt #33262
Problem:  Redrawing during a substitute confirm prompt causes the match
          highlight to disappear.
Solution: Unset `highlight_match` after the prompt has returned.
          Use global highlight definitions in searchhl_spec.lua.
(cherry picked from commit 3af43cffa0)
2025-04-02 12:48:35 +00:00
tstsrt
5fc6bd6454 fix(api): nvim_set_keymap() throws error even in pcall() #33228
Problem: When `nvim_set_keymap` tries to overwrite a `<unique>` mapping,
it throws an error even when called in `pcall`.

Solution: src/nvim/mapping.c:buf_do_map no longer calls `semsg`. Its
callers now decide whether to ignore the error, or use
`semsg` (not caught)/`api_set_error` (caught by `pcall`).

(cherry picked from commit ec18ebcb41)
2025-04-01 15:50:54 +00:00
zeertzjq
2b2a90051e fix(api): use E226 instead of E227 for duplicate abbreviation (#33159)
(cherry picked from commit 99529577cc)
2025-04-01 15:04:03 +00:00
Lewis Russell
1e8e74dbff fix(lsp): better handling of "*" configs
Problem:

If a config name contains "*" it causes rtp discovery of `lsp/` to
consider the `*` as a wildcard and could lead to strange and unintended
behaviour. For example, accessing the `'*'` config from a `lsp/` file
would cause an infinite loop.

Solution:

- Explicitly disallow a config name from containing wildcards, with the
  exception of `'*'`.
- When Resolving `'*'` config, skip the rtp step.

(cherry picked from commit 2ee896201c)
2025-04-01 13:54:47 +01:00
luukvbaal
a4b6705e87 fix(window): crash on negative window height with 'winbar' #33250
Problem:  Negative window and grid height with 'winbar'.
Solution: Clamp the height when subtracting the 'winbar' height.
(cherry picked from commit 0e7479bb76)
2025-04-01 12:28:28 +00:00
Sean Dewar
f68e0fed26 docs(eval): fix dict param type of mapset
Match maparg's return type.

(cherry picked from commit ec6670080a)
2025-04-01 10:21:42 +00:00
Sean Dewar
09fd22d5d7 docs(eval): fix lnum type for functions using tv_get_lnum
These occurrences also accept string, which is used like in getline.

Also make the lnum field of vim.fn.sign_placelist.list.item optional, as it can
be omitted like vim.fn.sign_place.dict's.

(cherry picked from commit 4a36f234ac)
2025-04-01 10:21:42 +00:00
luukvbaal
326eacef93 fix(move): adjust for concealed lines above topline after scrolling up (#33211)
Problem:  Scrolling up does not adjust `w_topline` for concealed lines
          directly above it, resulting in (non-visual) asymmetry when
          scrolling up/down.
Solution: Adjust `w_topline` for concealed lines after scrolling up.
(cherry picked from commit 32325a66ca)
2025-04-01 06:34:00 +00:00
luukvbaal
02123bac0d fix(display): wrong cursor column with 'concealcursor' = "n" and virt_text (#33218)
Problem:  Inline virtual text placed in a decor provider callback
          invalidates `w_virtcol`, which must be valid for `win_line()`.
Solution: Call `validate_virtcol()` after "line" decor provider callbacks.
(cherry picked from commit 7e8b7bba21)
2025-04-01 06:31:29 +00:00
zeertzjq
8d9b4d8c14 test(float): restore border tests (#33222)
(cherry picked from commit 04901f4ee7)
2025-04-01 00:01:17 +00:00
zeertzjq
55be20316a docs: remove duplicate news file (#33227) 2025-03-31 15:16:51 +00:00
glepnir
12da443930 feat(float): 'winborder' "bold" style #33189
(cherry picked from commit 216cc893bf)
2025-03-31 14:06:11 +00:00
Ghjuvan Lacambre
837c9d0409 fix(defaults): enable :terminal [[,]] motion in operator-pending mode #33217
This enables y]] to copy a command and its output.

(cherry picked from commit 57b4fb5c53)
2025-03-31 13:42:29 +00:00
Tan, Long
70f3e15298 fix(treesitter): don't memoize modified headings (#33186)
Problem: repeated gO in markdown etc. adds extra toc indentation

Solution: don't memoize heading table which gets modified
(cherry picked from commit 28eaec5e15)
2025-03-31 09:49:39 +00:00
neovim-backports[bot]
7e884b78bf fix(defaults): visual-mode [[,]] for :terminal shell prompts #33203
Problem:
:terminal shell prompt jump mappings ]]/[[ don't work in visual mode.

Solution:
Also define them for in visual mode.

(cherry picked from commit cb247e06f0)

Co-authored-by: msaher <77233589+msaher@users.noreply.github.com>
2025-03-30 13:17:46 -07:00
zeertzjq
89e0ea1788 fix(checkhealth): check outdated pynvim version properly #33175
Fixes #33174, a regression from #22962.

(cherry picked from commit e87d2ae383)
2025-03-30 17:01:35 +00:00
Bartłomiej Maryńczak
9056c01a95 fix(vim.lsp.inlay_hint): requesting inlay_hints even when disabled #32999
Problem:
Nvim needlessly requests inlay_hints even if they are disabled for a given buffer.

Solution:
Add the missing `enabled` check in `on_refresh`.
Rest of the code has this check already so that's the only needed one to fix this.

(cherry picked from commit 49756ebc70)
2025-03-30 16:07:09 +00:00
Phạm Bình An
d2dd403693 docs: faq, lua packages #33183
Problem:
- `health#check()` seems to have been removed for a while, but `:h faq`
  still refers to it.
- `news-0.11.txt` doesn't mention #33044
2025-03-30 17:22:52 +02:00
zeertzjq
2084cda6f9 vim-patch:9.1.1260: Hang when filtering buffer with NUL bytes (#33192)
Problem:  Hang when filtering buffer with NUL bytes (after 9.1.1050).
Solution: Don't subtract "written" from "lplen" repeatedly (zeertzjq).

related: neovim/neovim#33173
closes: vim/vim#17011

53fed23cb7
(cherry picked from commit 431c037709)
2025-03-30 14:34:33 +00:00
neovim-backports[bot]
7efb3ba6f7 feat(checkhealth): use emoji for OK/WARN/ERROR (#33195)
Problem:
Health status can be much more visually distinct.

Solution:
Use emoji next to each status.

(cherry picked from commit 75fe540500)

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2025-03-30 07:04:01 -07:00
neovim-backports[bot]
649bce6e73 fix(provider): misleading :checkhealth if user sets g:loaded_python3_provider=1 #32696
Problem:
:checkhealth shows a confusing message if user sets
g:loaded_python3_provider=1.

Solution:
- Show a warning if that var is set to 1.
- Update provider modules to default to 0. Any user code that is
  checking for 1, is like already broken because these may be set to 2.

(cherry picked from commit b4906577c9)

Co-authored-by: Sathya Pramodh <94102031+sathya-pramodh@users.noreply.github.com>
2025-03-30 08:09:07 +08:00
Justin M. Keyes
fcee5df0fc fix(checkhealth): check g:loaded_xx_provider for all providers #33168
(cherry picked from commit 5f9f5bc04d)
2025-03-29 21:09:55 +00:00
Daniel Kusai
2a04161a35 fix(desktop): cannot open filename with spaces using OS file manager #33161
Problem:
When activated from OS "filetype handling", Nvim cannot handle filenames containing spaces.

Solution:
Quote the filename in the .desktop config.

(cherry picked from commit 6e12ef4a7b)
2025-03-29 16:17:04 +00:00
phanium
adfd4b9f4f fix(checkhealth): don't override user "q" keymap #33132
(cherry picked from commit 78d2e0b43e)
2025-03-29 13:58:03 +00:00
Gregory Anders
056dbf3ea7 fix(api): use original LHS in keymap error message #33135
When setting a keymap with "unique" that already exists the error
message contains the LHS of the keymap with termcodes replaced. In
particular this means that keys like <Tab> show as an actual tab
character, meaning the error message displays as "Mapping already exists
for ", which is hard to debug for users.

Instead, display the original LHS (without any simplification or parsed
termcodes). This rperesents exactly what the user passed to the `lhs`
argument of `nvim_set_keymap`, which makes it easier to find where the
offending keymap is.

(cherry picked from commit 0d73ec5834)
2025-03-29 13:48:06 +00:00
zeertzjq
c57a36cd59 fix(pum): fix heap-buffer-overflow with 'rightleft' (#33146)
(cherry picked from commit 2681e1fce3)
2025-03-29 02:58:38 +00:00
luukvbaal
06df3e0c0d fix(cmdline): avoid empty @: register after :<CR> (#33126)
Fix https://github.com/neovim/neovim/issues/33125

(cherry picked from commit f4ee0ab2f1)
2025-03-28 21:57:24 +00:00
Micah Halter
a9afa6b152 fix(lsp): warn on missing config in :checkhealth #33087
Problem
When calling `:checkhealth vim.lsp` after the user has enabled a language
server with `vim.lsp.enable` that has no configuration a runtime error
is hit because the code expects for a configuration to exist.

Solution:
Check if a configuration was returned before parsing it, if it isn't
returned then warn the user that the server has been enabled but a
configuration was not found.

(cherry picked from commit 5554fcc286)
2025-03-28 13:17:38 +00:00
v1nh1shungry
bbf912d72f fix(provider)!: drop Python 3.7, 3.8 support #33088
Problem: #33022 didn't update `min_version` to 3.9, therefore Python 3.7
and 3.8 are still available.

Solution: Update `min_version` to 3.9.
(cherry picked from commit ade58885c4)
2025-03-28 12:36:02 +00:00
luukvbaal
53def2a877 fix(cmdline): empty ext_cmdline block events for :<CR> #33118
Problem:  An ext_cmdline block event that should be empty after :<CR>
          re-emits the previous cmdline.
Solution: Clear `last_cmdline` even when `new_last_cmdline == NULL`.
(cherry picked from commit 95ab723995)
2025-03-28 12:11:56 +00:00
Shadman
c61e8c6e70 fix(mouse): crash with click on win-separator in statusline (#33091)
Problem: Clicking on window separator in statusline crashes Nvim due
to out of bound memory access

Solution: Check if the click location is within clicking range before
applying it.

(cherry picked from commit 18fa61049a)
2025-03-28 07:32:24 +00:00
zeertzjq
6514e2c7ba vim-patch:9.1.1247: fragile setup to get (preferred) keys from key_name_entry (#33102)
Problem:  fragile setup to get (preferred) keys from key_name_entry
          (after v9.1.1179)
Solution: refactor the code further, fix a bug with "pref_name" key
          entry introduced in v9.1.1180 (Yee Cheng Chin)

The optimization introduced for using bsearch() with key_name_entry
in vim/vim#16788 was fragile as it required synchronizing a non-obvious index
(e.g. IDX_KEYNAME_SWU) with the array that could be accidentally changed
by any one adding a key to it. Furthermore, the "pref_name" that was
introduced in that change was unnecessary, and in fact introduced a bug,
as we don't always want to use the canonical name.

The bug is triggered when the user triggers auto-complete using a
keycode, such as `:set <Scroll<Tab>`. The bug would end up showing two
copies of `<ScrollWheelUp>` because both entries end up using the
canonical name.

In this change, remove `pref_name`, and simply use a boolean to track
whether an entry is an alt name or not and modify logic to respect that.

Add test to make sure auto-complete works with alt names

closes: vim/vim#16987

7d8e7df551

In Nvim there is no `enabled` field, so put `is_alt` before `name` to
reduce the size of the struct.

Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
(cherry picked from commit ae98d0a560)
2025-03-28 00:28:03 +00:00
Eisuke Kawashima
06c2886569 fix(health): message should mention "vim.provider" #33095
(cherry picked from commit 07f048a8d7)
2025-03-27 23:49:03 +00:00
luukvbaal
2cd735d159 fix(display): scroll logic does not take into account concealed topline (#33054)
(cherry picked from commit ce0c0c31a0)
2025-03-27 13:55:34 +00:00
luukvbaal
ccb078bbb0 fix(ui): wincmd _ should not increase 'cmdheight' above 0 (#33056)
(cherry picked from commit 703f4037c4)
2025-03-27 13:08:16 +00:00
Justin M. Keyes
5e4365b83d version bump 2025-03-26 15:13:05 +01:00
1136 changed files with 37209 additions and 90993 deletions

View File

@@ -18,7 +18,6 @@ Checks: >
-bugprone-not-null-terminated-result,
-bugprone-suspicious-memory-comparison,
-bugprone-switch-missing-default-case,
-bugprone-tagged-union-member-count,
-cert-env33-c,
-cert-err33-c,
-cert-err34-c,
@@ -64,7 +63,6 @@ Checks: >
Aliases. These are just duplicates of other warnings and should always be ignored,
-bugprone-narrowing-conversions,
-cert-arr39-c,
-cert-dcl37-c,
-cert-dcl51-cpp,
-cert-exp42-c,

View File

@@ -1,25 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
"format": {
"externalTool": {
"program": "stylua",
"args": [
"-",
"--stdin-filepath",
"${file}"
]
}
},
"diagnostics": {
"disable": [
"unnecessary-if"
]
},
"codeAction": {
"insertSpace": true
},
"strict": {
"typeCall": true,
"arrayIndex": true
}
}

0
.gitattributes vendored Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
<!--
Thank you for contributing to Neovim!
If this is your first time, check out https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#pull-requests-prs
for our PR guidelines.
-->

View File

@@ -1,16 +1,8 @@
# This script enables Developer Command Prompt
# See https://github.com/microsoft/vswhere/wiki/Start-Developer-Command-Prompt#using-powershell
if ($env:BUILD_ARCH -eq "arm64") {
$arch = "arm64"
$installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.arm64 -property installationPath
} else {
$arch = "x64"
$installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
}
if ($installationPath) {
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=$arch -no_logo && set" |
ForEach-Object {
if ($installationPath -and (Test-Path "$installationPath\Common7\Tools\vsdevcmd.bat")) {
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=x64 -no_logo && set" | ForEach-Object {
$name, $value = $_ -split '=', 2
"$name=$value" >> $env:GITHUB_ENV
}

View File

@@ -57,7 +57,6 @@ module.exports = async ({ github, context }) => {
if (labels.includes("lsp")) {
reviewers.add("MariaSolOs");
reviewers.add("ribru17");
}
if (labels.includes("netrw")) {
@@ -90,7 +89,6 @@ module.exports = async ({ github, context }) => {
reviewers.add("clason");
reviewers.add("lewis6991");
reviewers.add("wookayin");
reviewers.add("ribru17");
}
if (labels.includes("tui")) {

View File

@@ -11,9 +11,9 @@ jobs:
if: github.event.pull_request.merged
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/create-github-app-token@v2
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.BACKPORT_APP }}
@@ -29,7 +29,7 @@ jobs:
- name: Create failed backport label
if: ${{ steps.backport.outputs.was_successful == 'false' }}
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({

View File

@@ -28,7 +28,7 @@ jobs:
test: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.test }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: |
cmake -S cmake.deps --preset ci -D ENABLE_WASMTIME=ON
@@ -44,7 +44,7 @@ jobs:
CMAKE_URL: 'https://cmake.org/files/v3.16/cmake-3.16.0-Linux-x86_64.sh'
CMAKE_VERSION: '3.16.0'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Install minimum required version of cmake
@@ -73,7 +73,7 @@ jobs:
name: Test USE_EXISTING_SRC_DIR=ON builds with no network access
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Build bundled dependencies

View File

@@ -22,7 +22,7 @@ jobs:
security-events: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Initialize CodeQL

View File

@@ -8,7 +8,7 @@ jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Download Coverity

View File

@@ -10,7 +10,7 @@ jobs:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Generate docs

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: check issue title
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
const title = context.payload.issue.title;

View File

@@ -9,8 +9,8 @@ jobs:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/labeler@v6
- uses: actions/checkout@v4
- uses: actions/labeler@v5
with:
configuration-path: .github/scripts/labeler_configuration.yml
@@ -40,7 +40,7 @@ jobs:
pull-requests: write
steps:
- if: startsWith(github.base_ref, 'release')
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci:skip-news')
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -2,26 +2,21 @@
${NVIM_VERSION}
```
## Release notes
- [Changelog](https://github.com/neovim/neovim/commit/${NVIM_COMMIT}) (fixes + features)
- [News](./runtime/doc/news.txt) (`:help news` in Nvim)
## Install
### Windows
#### Zip
1. Download **nvim-win64.zip** (or **nvim-win-arm64.zip** for ARM)
1. Download **nvim-win64.zip**
2. Extract the zip
3. Run `nvim.exe` in your terminal
3. Run `nvim.exe` on your CLI of choice
#### MSI
1. Download **nvim-win64.msi** (or **nvim-win-arm64.msi** for ARM)
1. Download **nvim-win64.msi**
2. Run the MSI
3. Run `nvim.exe` in your terminal
3. Run `nvim.exe` on your CLI of choice
Note: On Windows "Server" you may need to [install vcruntime140.dll](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170).
@@ -41,7 +36,7 @@ Note: On Windows "Server" you may need to [install vcruntime140.dll](https://lea
### Linux (x86_64)
If your system does not have the required glibc version, try the (unsupported) [builds for older glibc](https://github.com/neovim/neovim-releases).
If your system does not have the [required glibc version](https://neovim.io/doc/user/support.html#supported-platforms), try the (unsupported) [builds for older glibc](https://github.com/neovim/neovim-releases).
#### AppImage
@@ -59,7 +54,7 @@ If your system does not have the required glibc version, try the (unsupported) [
2. Extract: `tar xzvf nvim-linux-x86_64.tar.gz`
3. Run `./nvim-linux-x86_64/bin/nvim`
### Linux (arm64)
### Linux (arm64) - Untested
#### AppImage
@@ -80,3 +75,5 @@ If your system does not have the required glibc version, try the (unsupported) [
### Other
- Install by [package manager](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package)
## SHA256 Checksums

View File

@@ -55,7 +55,7 @@ jobs:
outputs:
version: ${{ steps.build.outputs.version }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
# Perform a full checkout #13471
fetch-depth: 0
@@ -101,7 +101,7 @@ jobs:
env:
MACOSX_DEPLOYMENT_TARGET: 11.0
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
# Perform a full checkout #13471
fetch-depth: 0
@@ -132,44 +132,27 @@ jobs:
windows:
needs: setup
strategy:
matrix:
include:
- runner: windows-2022
arch: x86_64
archive_name: nvim-win64
- runner: windows-11-arm
arch: arm64
archive_name: nvim-win-arm64
runs-on: ${{ matrix.runner }}
runs-on: windows-2019
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
# Perform a full checkout #13471
fetch-depth: 0
- run: .github/scripts/env.ps1
env:
BUILD_ARCH: ${{ matrix.arch }}
- name: Install Wix
run: |
Invoke-WebRequest -Uri "https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip" -OutFile "wix314-binaries.zip"
Expand-Archive -Path "wix314-binaries.zip" -DestinationPath "C:/wix"
echo "C:\wix" >> $env:GITHUB_PATH
- name: Build deps
run: |
cmake -S cmake.deps -B .deps -G Ninja -DCMAKE_BUILD_TYPE=${{ needs.setup.outputs.build_type }}
cmake --build .deps
- name: Build package
- name: build package
run: |
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ needs.setup.outputs.build_type }}
cmake --build build --target package
- name: Upload artifact
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
with:
name: nvim-win-${{ matrix.arch }}
name: nvim-win64
path: |
build/${{ matrix.archive_name }}.zip
build/${{ matrix.archive_name }}.msi
build/nvim-win64.msi
build/nvim-win64.zip
retention-days: 1
publish:
@@ -183,9 +166,9 @@ jobs:
steps:
# Must perform checkout first, since it deletes the target directory
# before running, and would therefore delete the downloaded artifacts
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y gettext-base
@@ -210,14 +193,25 @@ jobs:
echo 'PRERELEASE=') >> $GITHUB_ENV
gh release delete stable --yes || true
git push origin :stable || true
# `sha256sum` outputs <sha> <path>, so we cd into each dir to drop the
# containing folder from the output.
- run: |
for i in nvim-*; do
(
cd $i || exit
sha256sum * >> $GITHUB_WORKSPACE/shasum.txt
)
done
- name: Publish release
env:
NVIM_VERSION: ${{ needs.linux.outputs.version }}
NVIM_COMMIT: ${{ github.sha }}
DEBUG: api
run: |
envsubst < "$GITHUB_WORKSPACE/.github/workflows/notes.md" > "$RUNNER_TEMP/notes.md"
echo '```' >> "$RUNNER_TEMP/notes.md"
cat shasum.txt >> "$RUNNER_TEMP/notes.md"
echo '```' >> "$RUNNER_TEMP/notes.md"
if [ "$TAG_NAME" != "nightly" ]; then
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win-x86_64/* nvim-win-arm64/*
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/* shasum.txt
fi
gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win-x86_64/* nvim-win-arm64/*
gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/* shasum.txt

View File

@@ -13,8 +13,8 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/github-script@v8
- uses: actions/checkout@v4
- uses: actions/github-script@v7
with:
script: |
const script = require('./.github/scripts/close_unresponsive.js')
@@ -27,8 +27,8 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/github-script@v8
- uses: actions/checkout@v4
- uses: actions/github-script@v7
with:
script: |
const script = require('./.github/scripts/remove_response_label.js')

View File

@@ -10,9 +10,9 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: 'Request reviewers'
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
const script = require('./.github/scripts/reviewers_add.js')

View File

@@ -8,9 +8,9 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: 'Remove reviewers'
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
const script = require('./.github/scripts/reviewers_remove.js')

View File

@@ -28,17 +28,17 @@ env:
jobs:
lint:
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-24.04
timeout-minutes: 10
env:
CC: clang
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Install stylua
run: |
wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-aarch64.zip
wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-x86_64.zip
(cd "$BIN_DIR"; unzip stylua*.zip)
- name: Build third-party deps
@@ -82,12 +82,12 @@ jobs:
run: cmake --build build --target lintc-uncrustify
clang-analyzer:
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
CC: clang
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Build third-party deps
run: |
@@ -111,7 +111,7 @@ jobs:
{ runner: ubuntu-24.04, os: ubuntu, flavor: asan, cc: clang, flags: -D ENABLE_ASAN_UBSAN=ON },
{ runner: ubuntu-24.04, os: ubuntu, flavor: tsan, cc: clang, flags: -D ENABLE_TSAN=ON },
{ runner: ubuntu-24.04, os: ubuntu, flavor: release, cc: gcc, flags: -D CMAKE_BUILD_TYPE=Release -D ENABLE_TRANSLATIONS=ON },
{ runner: ubuntu-24.04-arm, os: ubuntu, flavor: arm, cc: clang, flags: -D CMAKE_BUILD_TYPE=RelWithDebInfo },
# { runner: ubuntu-24.04-arm, os: ubuntu, flavor: arm, cc: gcc, flags: -D CMAKE_BUILD_TYPE=RelWithDebInfo },
{ runner: macos-13, os: macos, flavor: intel, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
{ runner: macos-15, os: macos, flavor: arm, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
{ runner: ubuntu-24.04, os: ubuntu, flavor: puc-lua, cc: gcc, deps_flags: -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON, flags: -D PREFER_LUA=ON },
@@ -124,17 +124,12 @@ jobs:
build: { flavor: puc-lua }
- test: oldtest
build: { flavor: tsan }
- test: unittest
build: { runner: ubuntu-24.04-arm }
- test: oldtest
build: { runner: ubuntu-24.04-arm }
runs-on: ${{ matrix.build.runner }}
timeout-minutes: 45
env:
CC: ${{ matrix.build.cc }}
NVIM_TEST_INTEG: ${{ matrix.build.flavor == 'release' && '1' || '0' }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
with:
install_flags: "--test"
@@ -206,35 +201,16 @@ jobs:
name: Show logs
run: cat $(find "$LOG_DIR" -type f)
zig-build:
runs-on: ubuntu-24.04
timeout-minutes: 45
name: build using zig build (linux)
steps:
- uses: actions/checkout@v5
- uses: mlugg/setup-zig@v2
with:
version: 0.14.1
- run: sudo apt-get install -y inotify-tools
- run: zig build test_nlua0
- run: zig build nvim && ./zig-out/bin/nvim --version
- run: zig build unittest
- run: zig build functionaltest
# `zig build nvim` uses a lua script for doctags in order to support cross-compiling
# compare with the builtin generator that they match
- run: cd runtime; ../zig-out/bin/nvim -u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
- run: diff -u runtime/doc/tags zig-out/runtime/doc/tags
windows:
uses: ./.github/workflows/test_windows.yml
with-external-deps:
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-24.04
timeout-minutes: 10
env:
CC: gcc
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Install dependencies

View File

@@ -18,7 +18,7 @@ jobs:
matrix:
test: [functional, old]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Build deps

View File

@@ -15,11 +15,11 @@ jobs:
VERSION_BRANCH: marvim/ci-version-update
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
repository: vim/vim
path: ${{ env.VIM_SOURCE_DIR }}

3
.gitignore vendored
View File

@@ -10,8 +10,7 @@ compile_commands.json
/.idea/
# Build/deps dir
/.zig-cache/
/zig-out/
/build/
/.deps/
/tmp/
/.clangd/

View File

@@ -49,7 +49,6 @@ exclude_files = {
'runtime/lua/vim/_meta/vimfn.lua',
'runtime/lua/vim/_meta/api.lua',
'runtime/lua/vim/re.lua',
'runtime/lua/uv/_meta.lua',
'runtime/lua/coxpcall.lua',
'src/nvim/eval.lua',
}

View File

@@ -5,12 +5,13 @@
},
"workspace": {
"library": [
"${3rd}/busted/library"
"runtime/lua",
"${3rd}/busted/library",
"${3rd}/luv/library"
],
"ignoreDir": [
".deps",
"build",
"test"
"test",
"_vim9script.lua"
],
"checkThirdParty": "Disable"
},

View File

@@ -1,8 +0,0 @@
# Alternative settings for special snowflakes like: decorations_spec.lua, multigrid_spec.lua, etc.
column_width = 140
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
call_parentheses = "Input"

View File

@@ -1,15 +1,14 @@
build/
.deps/
runtime/lua/coxpcall.lua
runtime/lua/uv/_meta.lua
runtime/lua/vim/_meta
runtime/lua/vim/re.lua
/build/
/.deps/
/runtime/lua/coxpcall.lua
/runtime/lua/vim/_meta
/runtime/lua/vim/re.lua
# These are formatted explicitly by the "formatlua2" build task.
test/functional/ui/decorations_spec.lua
test/functional/ui/float_spec.lua
test/functional/ui/multigrid_spec.lua
test/functional/fixtures/lua/syntax_error.lua
test/functional/legacy/030_fileformats_spec.lua
test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
/test/functional/fixtures/lua/syntax_error.lua
/test/functional/legacy/030_fileformats_spec.lua
/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
/test/functional/lua/luaeval_spec.lua

View File

@@ -165,40 +165,11 @@ https://github.com/cascent/neovim-cygwin was built on Cygwin 2.9.0. Newer `libuv
mingw32-make install
```
### Windows WSL
Build Ubuntu/Debian linux binary on [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows Subsystem for Linux).
```bash
# Install build prerequisites
sudo apt-get install ninja-build gettext cmake build-essential
# Build the linux binary in WSL
make CMAKE_BUILD_TYPE=RelWithDebInfo
# Install the linux binary in WSL (with `<arch>` either `x86_64` or `arm64`)
cd build && cpack -G DEB && sudo dpkg -i nvim-linux-<arch>.deb
# Verify the installation
nvim --version && which nvim # should be debug build in /usr/bin/nvim
```
**Note**: If you encounter linker errors or segfaults during the build, Windows libraries in your PATH may be interfering. Use a clean PATH to avoid conflicts:
```bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" make CMAKE_BUILD_TYPE=RelWithDebInfo
```
## Localization
### Localization build
Translations are turned off by default. Enable by building Nvim with the CMake flag `ENABLE_TRANSLATIONS=ON`.
Doing this will create `.mo` files in `build/src/nvim/po`. Example:
```
make CMAKE_EXTRA_FLAGS="-DENABLE_TRANSLATIONS=ON"
```
A normal build will create `.mo` files in `build/src/nvim/po`.
* If you see `msgfmt: command not found`, you need to install [`gettext`](http://en.wikipedia.org/wiki/Gettext). On most systems, the package is just called `gettext`.
@@ -252,7 +223,7 @@ rebuild:
## Third-party dependencies
Reference the [Debian package](https://packages.debian.org/sid/source/neovim) (or alternatively, the [Homebrew formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/n/neovim.rb)) for the precise list of dependencies/versions.
Reference the [Debian package](https://packages.debian.org/sid/source/neovim) (or alternatively, the [Homebrew formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/neovim.rb)) for the precise list of dependencies/versions.
To build the bundled dependencies using CMake:
@@ -288,29 +259,6 @@ cmake --build build
- Using `ninja` is strongly recommended.
4. If treesitter parsers are not bundled, they need to be available in a `parser/` runtime directory (e.g. `/usr/share/nvim/runtime/parser/`).
### How to build static binary (on Linux)
1. Use a linux distribution which uses musl C. We will use Alpine Linux but any distro with musl should work. (glibc does not support static linking)
2. Run make passing the `STATIC_BUILD` variable: `make CMAKE_EXTRA_FLAGS="-DSTATIC_BUILD=1"`
In case you are not using Alpine Linux you can use a container to do the build the binary:
```bash
podman run \
--rm \
-it \
-v "$PWD:/workdir" \
-w /workdir \
alpine:latest \
bash -c 'apk add build-base cmake coreutils curl gettext-tiny-dev git && make CMAKE_EXTRA_FLAGS="-DSTATIC_BUILD=1"'
```
The resulting binary in `build/bin/nvim` will have all the dependencies statically linked:
```
build/bin/nvim: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=b93fa8e678d508ac0a76a2e3da20b119105f1b2d, with debug_info, not stripped
```
#### Debian 10 (Buster) example:
```sh
@@ -346,31 +294,31 @@ Platform-specific requirements are listed below.
### Ubuntu / Debian
```sh
sudo apt-get install ninja-build gettext cmake curl build-essential git
sudo apt-get install ninja-build gettext cmake curl build-essential
```
### RHEL / Fedora
```
sudo dnf -y install ninja-build cmake gcc make gettext curl glibc-gconv-extra git
sudo dnf -y install ninja-build cmake gcc make gettext curl glibc-gconv-extra
```
### openSUSE
```
sudo zypper install ninja cmake gcc-c++ gettext-tools curl git
sudo zypper install ninja cmake gcc-c++ gettext-tools curl
```
### Arch Linux
```
sudo pacman -S base-devel cmake ninja curl git
sudo pacman -S base-devel cmake ninja curl
```
### Alpine Linux
```
apk add build-base cmake coreutils curl gettext-tiny-dev git
apk add build-base cmake coreutils curl gettext-tiny-dev
```
### Void Linux
@@ -434,7 +382,7 @@ or a specific SHA1 like `--override-input neovim-src github:neovim/neovim/89dc8f
### FreeBSD
```
sudo pkg install cmake gmake sha wget gettext curl git
sudo pkg install cmake gmake sha wget gettext curl
```
If you get an error regarding a `sha256sum` mismatch, where the actual SHA-256 hash is `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, then this is your issue (that's the `sha256sum` of an empty file).
@@ -442,7 +390,7 @@ If you get an error regarding a `sha256sum` mismatch, where the actual SHA-256 h
### OpenBSD
```sh
doas pkg_add gmake cmake curl gettext-tools git
doas pkg_add gmake cmake curl gettext-tools
```
Build can sometimes fail when using the top level `Makefile`, apparently due to some third-party component (see [#2445-comment](https://github.com/neovim/neovim/issues/2445#issuecomment-108124236)). The following instructions use CMake:
@@ -467,7 +415,7 @@ gmake
2. Install [Homebrew](http://brew.sh)
3. Install Neovim build dependencies:
```
brew install ninja cmake gettext curl git
brew install ninja cmake gettext curl
```
- **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
```sh
@@ -485,7 +433,7 @@ gmake
2. Install [MacPorts](http://www.macports.org)
3. Install Neovim build dependencies:
```
sudo port install ninja cmake gettext git
sudo port install ninja cmake gettext
```
- **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
```sh

View File

@@ -35,11 +35,6 @@ include(InstallHelpers)
include(PreventInTreeBuilds)
include(Util)
if(NOT PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
# Auto-create a .gitignore in the specified "build" directory.
file(GENERATE OUTPUT .gitignore CONTENT "*")
endif()
#-------------------------------------------------------------------------------
# User settings
#-------------------------------------------------------------------------------
@@ -145,19 +140,19 @@ endif()
# If not in a git repo (e.g., a tarball) these tokens define the complete
# version string, else they are combined with the result of `git describe`.
set(NVIM_VERSION_MAJOR 0)
set(NVIM_VERSION_MINOR 12)
set(NVIM_VERSION_PATCH 0)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
set(NVIM_VERSION_MINOR 11)
set(NVIM_VERSION_PATCH 1)
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
# API level
set(NVIM_API_LEVEL 14) # Bump this after any API/stdlib change.
set(NVIM_API_LEVEL 13) # Bump this after any API/stdlib change.
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
set(NVIM_API_PRERELEASE true)
set(NVIM_API_PRERELEASE false)
# We _want_ assertions in RelWithDebInfo build-type.
if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
string(REPLACE "-DNDEBUG" "-DRELDEBUG" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/DNDEBUG" "/DRELDEBUG" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REPLACE " " " " CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") # Remove duplicate whitespace
endif()
@@ -241,7 +236,7 @@ set(STYLUA_DIRS runtime scripts src test contrib)
add_glob_target(
TARGET lintlua-luacheck
COMMAND $<TARGET_FILE:nvim_bin>
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr/share/lua/5.1 luacheck -q
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
GLOB_DIRS runtime scripts src test
GLOB_PAT *.lua
TOUCH_STRATEGY PER_DIR)
@@ -254,16 +249,6 @@ add_glob_target(
GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua
TOUCH_STRATEGY PER_DIR)
# Special handling of some files (which are ignored in .styluaignore).
# Workaround because stylua doesn't(?) support file-specific settings.
add_custom_target(lintlua-stylua2
COMMAND ${STYLUA_PRG} --config-path "${PROJECT_SOURCE_DIR}/.stylua2.toml"
--color=always --check
"${PROJECT_SOURCE_DIR}/test/functional/ui/decorations_spec.lua"
"${PROJECT_SOURCE_DIR}/test/functional/ui/float_spec.lua"
"${PROJECT_SOURCE_DIR}/test/functional/ui/multigrid_spec.lua"
)
add_dependencies(lintlua-stylua lintlua-stylua2)
add_custom_target(lintlua)
add_dependencies(lintlua lintlua-luacheck lintlua-stylua)
@@ -277,7 +262,7 @@ add_glob_target(
TOUCH_STRATEGY PER_DIR)
add_custom_target(lintcommit
COMMAND $<TARGET_FILE:nvim_bin> --clean -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
COMMAND $<TARGET_FILE:nvim_bin> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
add_dependencies(lintcommit nvim_bin)
add_custom_target(lint)
@@ -291,15 +276,7 @@ add_glob_target(
GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua
TOUCH_STRATEGY PER_DIR)
# Special handling of some files (which are ignored in .styluaignore).
# Workaround because stylua doesn't(?) support file-specific settings.
add_custom_target(formatlua2
COMMAND ${STYLUA_PRG} --config-path "${PROJECT_SOURCE_DIR}/.stylua2.toml"
"${PROJECT_SOURCE_DIR}/test/functional/ui/decorations_spec.lua"
"${PROJECT_SOURCE_DIR}/test/functional/ui/float_spec.lua"
"${PROJECT_SOURCE_DIR}/test/functional/ui/multigrid_spec.lua"
)
add_dependencies(formatlua formatlua2)
add_custom_target(format)
add_dependencies(format formatc formatlua)
@@ -346,13 +323,13 @@ else()
add_custom_target(lua_dev_deps)
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch")
if (CMAKE_SYSTEM_PROCESSOR MATCHES arm64)
set(LUALS_ARCH arm64)
else()
set(LUALS_ARCH x64)
endif()
set(LUALS_VERSION 3.15.0)
set(LUALS_VERSION 3.13.9)
set(LUALS "lua-language-server-${LUALS_VERSION}-${CMAKE_SYSTEM_NAME}-${LUALS_ARCH}")
set(LUALS_TARBALL ${LUALS}.tar.gz)
set(LUALS_URL https://github.com/LuaLS/lua-language-server/releases/download/${LUALS_VERSION}/${LUALS_TARBALL})

View File

@@ -273,7 +273,7 @@ If you need to modify or debug the documentation flow, these are the main files:
runtime/lua/vim/* => runtime/doc/lua.txt
runtime/lua/vim/lsp/ => runtime/doc/lsp.txt
src/nvim/api/* => runtime/doc/api.txt
src/nvim/eval.lua => runtime/doc/vimfn.txt
src/nvim/eval.lua => runtime/doc/builtin.txt
src/nvim/options.lua => runtime/doc/options.txt
```
@@ -299,7 +299,7 @@ types, etc. See [:help dev-lua-doc][dev-lua-doc].
- If possible, add type information (`table`, `string`, `number`, ...). Multiple valid types are separated by a bar (`string|table`). Indicate optional parameters via `type|nil`.
- If a function in your Lua module should _not_ be documented, add `@nodoc`.
- If the function is internal or otherwise non-public add `@private`.
- Private functions usually should be underscore-prefixed (named "_foo", not "foo"). Prefixing with an underscore implies `@nodoc`.
- Private functions usually should be underscore-prefixed (named "_foo", not "foo").
- Mark deprecated functions with `@deprecated`.
Third-party dependencies

View File

@@ -62,17 +62,15 @@ Several Neovim GUIs are available from scoop (extras): [scoop.sh/#/apps?q=neovim
- Add the `bin` folder (e.g. `C:\Program Files\nvim\bin`) to your PATH.
- This makes it easy to run `nvim` from anywhere.
- If `:set spell` does not work, create the `%LOCALAPPDATA%/nvim-data/site/spell` folder.
- If `:set spell` does not work, create the `C:/Users/foo/AppData/Local/nvim/site/spell` folder.
You can then copy your spell files over (for English, located
[here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.spl) and
[here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.sug));
- For Python plugins you need the `pynvim` module. Installation via uv
(https://docs.astral.sh/uv/) is recommended; the `--upgrade` switch ensures
installation of the latest version:
- For Python plugins you need the `pynvim` module. "Virtual envs" are recommended. After activating the virtual env do `pip install pynvim` (in *both*). Edit your `init.vim` so that it contains the path to the env's Python executable:
```vim
let g:python3_host_prog='C:/Users/foo/Envs/neovim3/Scripts/python.exe'
```
uv tool install --upgrade pynvim
```
- Run `:checkhealth` and read `:help provider-python` for more details.
- Run `:checkhealth` and read `:help provider-python`.
- **init.vim ("vimrc"):** If you already have Vim installed you can copy `%userprofile%\_vimrc` to `%userprofile%\AppData\Local\nvim\init.vim` to use your Vim config with Neovim.

View File

@@ -289,8 +289,3 @@ IV) It is not allowed to remove this license from the distribution of the Vim
license for previous Vim releases instead of the license that they came
with, at your option.
====
In addition, different license conditions may apply to some runtime files
included with Vim; these will be specified in the header of each respective
file.

View File

@@ -81,7 +81,7 @@ When a (non-experimental) feature is slated to be removed it should:
as described for Lua features.
- `vim.deprecate(…, 'x.y.z')` where major version `x` is greater than the
current Nvim major version, is always treated as _soft_ deprecation.
2. Be _hard_ deprecated in a release following the release in which it was soft deprecated.
2. Be _hard_ deprecated in a following a release in which it was soft deprecated.
- Use of the deprecated feature will still work but should issue a warning.
- Features implemented in C will need bespoke implementations to communicate
to users that the feature is deprecated.
@@ -127,9 +127,7 @@ Some can be auto-bumped by `scripts/bump_deps.lua`.
* [LuaJIT](https://github.com/LuaJIT/LuaJIT)
* [Lua](https://www.lua.org/download.html)
* [Luv](https://github.com/luvit/luv)
* When bumping, also sync
- [our bundled meta file](https://github.com/neovim/neovim/blob/master/runtime/lua/uv/_meta.lua) with [the upstream meta file](https://github.com/luvit/luv/blob/master/docs/meta.lua);
- [our bundled documentation](https://github.com/neovim/neovim/blob/master/runtime/doc/luvref.txt) with [the upstream documentation](https://github.com/luvit/luv/blob/master/docs/docs.md).
* When bumping, also sync [our bundled documentation](https://github.com/neovim/neovim/blob/master/runtime/doc/luvref.txt) with [the upstream documentation](https://github.com/luvit/luv/blob/master/docs.md).
* [gettext](https://ftp.gnu.org/pub/gnu/gettext/)
* [libiconv](https://ftp.gnu.org/pub/gnu/libiconv)
* [libuv](https://github.com/libuv/libuv)
@@ -154,7 +152,7 @@ These dependencies are "vendored" (inlined), we must update the sources manually
* `src/nvim/tui/terminfo_defs.h`: terminfo definitions
* Run `scripts/update_terminfo.sh` to update these definitions.
* `runtime/lua/vim/lsp/_meta/protocol.lua`: LSP specification
* Run `src/gen/gen_lsp.lua` to update.
* Run `scripts/gen_lsp.lua` to update.
* `runtime/lua/vim/_meta/lpeg.lua`: LPeg definitions.
* Refer to [`LuaCATS/lpeg`](https://github.com/LuaCATS/lpeg) for updates.
* Update the git SHA revision from which the documentation was taken.

View File

@@ -182,9 +182,3 @@ appimage-%:
bash scripts/genappimage.sh $*
.PHONY: test clean distclean nvim libnvim cmake deps install appimage checkprefix benchmark $(FORMAT) $(LINT) $(TEST)
.PHONY: emmylua-check
emmylua-check:
-emmylua_check runtime/lua \
--config .luarc.json \
--config .emmyrc.json

462
build.zig
View File

@@ -1,462 +0,0 @@
const std = @import("std");
const LazyPath = std.Build.LazyPath;
const build_lua = @import("src/build_lua.zig");
const gen = @import("src/gen/gen_steps.zig");
const runtime = @import("runtime/gen_runtime.zig");
const tests = @import("test/run_tests.zig");
const version = struct {
const major = 0;
const minor = 12;
const patch = 0;
const prerelease = "-dev";
const api_level = 14;
const api_level_compat = 0;
const api_prerelease = true;
};
// TODO(bfredl): this is for an upstream issue
pub fn lazyArtifact(d: *std.Build.Dependency, name: []const u8) ?*std.Build.Step.Compile {
var found: ?*std.Build.Step.Compile = null;
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
const inst = dep_step.cast(std.Build.Step.InstallArtifact) orelse continue;
if (std.mem.eql(u8, inst.artifact.name, name)) {
if (found != null) std.debug.panic("artifact name '{s}' is ambiguous", .{name});
found = inst.artifact;
}
}
return found;
}
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const t = target.result;
const os_tag = t.os.tag;
const is_windows = (os_tag == .windows);
const is_linux = (os_tag == .linux);
const is_darwin = os_tag.isDarwin();
const modern_unix = is_darwin or os_tag.isBSD() or is_linux;
const cross_compiling = b.option(bool, "cross", "cross compile") orelse false;
// TODO(bfredl): option to set nlua0 target explicitly when cross compiling?
const target_host = if (cross_compiling) b.graph.host else target;
const optimize_host = .ReleaseSafe;
// puc lua 5.1 is not ReleaseSafe "safe"
const optimize_lua = if (optimize == .Debug or optimize == .ReleaseSafe) .ReleaseSmall else optimize;
const arch = t.cpu.arch;
const default_luajit = (is_linux and arch == .x86_64) or (is_darwin and arch == .aarch64);
const use_luajit = b.option(bool, "luajit", "use luajit") orelse default_luajit;
const host_use_luajit = if (cross_compiling) false else use_luajit;
const E = enum { luajit, lua51 };
const ziglua = b.dependency("zlua", .{
.target = target,
.optimize = optimize_lua,
.lang = if (use_luajit) E.luajit else E.lua51,
.shared = false,
});
const ziglua_host = if (cross_compiling) b.dependency("zlua", .{
.target = target_host,
.optimize = optimize_lua,
.lang = if (host_use_luajit) E.luajit else E.lua51,
.shared = false,
}) else ziglua;
const lpeg = b.dependency("lpeg", .{});
const iconv = if (is_windows or is_darwin) b.lazyDependency("libiconv", .{ .target = target, .optimize = optimize }) else null;
// this is currently not necessary, as ziglua currently doesn't use lazy dependencies
// to circumvent ziglua.artifact() failing in a bad way.
const lua = lazyArtifact(ziglua, "lua") orelse return;
if (cross_compiling) {
_ = lazyArtifact(ziglua_host, "lua") orelse return;
}
// const lua = ziglua.artifact("lua");
const libuv_dep = b.dependency("libuv", .{ .target = target, .optimize = optimize });
const libuv = libuv_dep.artifact("uv");
const libluv = try build_lua.build_libluv(b, target, optimize, lua, libuv);
const libluv_host = if (cross_compiling) libluv_host: {
const libuv_dep_host = b.dependency("libuv", .{ .target = target_host, .optimize = optimize_host });
const libuv_host = libuv_dep_host.artifact("uv");
break :libluv_host try build_lua.build_libluv(b, target_host, optimize_host, ziglua_host.artifact("lua"), libuv_host);
} else libluv;
const utf8proc = b.dependency("utf8proc", .{ .target = target, .optimize = optimize });
const unibilium = b.dependency("unibilium", .{ .target = target, .optimize = optimize });
// TODO(bfredl): fix upstream bugs with UBSAN
const treesitter = b.dependency("treesitter", .{ .target = target, .optimize = .ReleaseFast });
const nlua0 = build_lua.build_nlua0(b, target_host, optimize_host, host_use_luajit, ziglua_host, lpeg, libluv_host);
// usual caveat emptor: might need to force a rebuild if the only change is
// addition of new .c files, as those are not seen by any hash
const subdirs = [_][]const u8{
"", // src/nvim itself
"os/",
"api/",
"api/private/",
"msgpack_rpc/",
"tui/",
"tui/termkey/",
"event/",
"eval/",
"lib/",
"lua/",
"viml/",
"viml/parser/",
"vterm/",
};
// source names _relative_ src/nvim/, not including other src/ subdircs
var nvim_sources = try std.ArrayList(gen.SourceItem).initCapacity(b.allocator, 100);
var nvim_headers = try std.ArrayList([]u8).initCapacity(b.allocator, 100);
// both source headers and the {module}.h.generated.h files
var api_headers = try std.ArrayList(std.Build.LazyPath).initCapacity(b.allocator, 10);
// TODO(bfredl): these should just become subdirs..
const windows_only = [_][]const u8{ "pty_proc_win.c", "pty_proc_win.h", "pty_conpty_win.c", "pty_conpty_win.h", "os_win_console.c", "win_defs.h" };
const unix_only = [_][]const u8{ "unix_defs.h", "pty_proc_unix.c", "pty_proc_unix.h" };
const exclude_list = if (is_windows) &unix_only else &windows_only;
const src_dir = b.build_root.handle;
for (subdirs) |s| {
var dir = try src_dir.openDir(b.fmt("src/nvim/{s}", .{s}), .{ .iterate = true });
defer dir.close();
var it = dir.iterateAssumeFirstIteration();
const api_export = std.mem.eql(u8, s, "api/");
const os_check = std.mem.eql(u8, s, "os/");
entries: while (try it.next()) |entry| {
if (entry.name.len < 3) continue;
if (entry.name[0] < 'a' or entry.name[0] > 'z') continue;
if (os_check) {
for (exclude_list) |name| {
if (std.mem.eql(u8, name, entry.name)) {
continue :entries;
}
}
}
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
try nvim_sources.append(.{ .name = b.fmt("{s}{s}", .{ s, entry.name }), .api_export = api_export });
}
if (std.mem.eql(u8, ".h", entry.name[entry.name.len - 2 ..])) {
try nvim_headers.append(b.fmt("{s}{s}", .{ s, entry.name }));
if (api_export and !std.mem.eql(u8, "ui_events.in.h", entry.name)) {
try api_headers.append(b.path(b.fmt("src/nvim/{s}{s}", .{ s, entry.name })));
}
}
}
}
const support_unittests = use_luajit;
const gen_config = b.addWriteFiles();
const version_lua = gen_config.add("nvim_version.lua", lua_version_info(b));
var config_str = b.fmt("zig build -Doptimize={s}", .{@tagName(optimize)});
if (cross_compiling) {
config_str = b.fmt("{s} -Dcross -Dtarget={s} (host: {s})", .{ config_str, try t.linuxTriple(b.allocator), try b.graph.host.result.linuxTriple(b.allocator) });
}
const versiondef_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/versiondef.h.in") } }, .{
.NVIM_VERSION_MAJOR = version.major,
.NVIM_VERSION_MINOR = version.minor,
.NVIM_VERSION_PATCH = version.patch,
.NVIM_VERSION_PRERELEASE = version.prerelease,
.NVIM_VERSION_MEDIUM = "",
.VERSION_STRING = "TODO", // TODO(bfredl): not sure what to put here. summary already in "config_str"
.CONFIG = config_str,
});
_ = gen_config.addCopyFile(versiondef_step.getOutput(), "auto/versiondef.h"); // run_preprocessor() workaronnd
const ptrwidth = t.ptrBitWidth() / 8;
const sysconfig_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/config.h.in") } }, .{
.SIZEOF_INT = t.cTypeByteSize(.int),
.SIZEOF_INTMAX_T = t.cTypeByteSize(.longlong), // TODO
.SIZEOF_LONG = t.cTypeByteSize(.long),
.SIZEOF_SIZE_T = ptrwidth,
.SIZEOF_VOID_PTR = ptrwidth,
.PROJECT_NAME = "nvim",
.HAVE__NSGETENVIRON = is_darwin,
.HAVE_FD_CLOEXEC = modern_unix,
.HAVE_FSEEKO = modern_unix,
.HAVE_LANGINFO_H = modern_unix,
.HAVE_NL_LANGINFO_CODESET = modern_unix,
.HAVE_NL_MSG_CAT_CNTR = t.isGnuLibC(),
.HAVE_PWD_FUNCS = modern_unix,
.HAVE_READLINK = modern_unix,
.HAVE_STRNLEN = modern_unix,
.HAVE_STRCASECMP = modern_unix,
.HAVE_STRINGS_H = modern_unix,
.HAVE_STRNCASECMP = modern_unix,
.HAVE_STRPTIME = modern_unix,
.HAVE_XATTR = is_linux,
.HAVE_SYS_SDT_H = false,
.HAVE_SYS_UTSNAME_H = modern_unix,
.HAVE_SYS_WAIT_H = false, // unused
.HAVE_TERMIOS_H = modern_unix,
.HAVE_WORKING_LIBINTL = t.isGnuLibC(),
.UNIX = modern_unix,
.CASE_INSENSITIVE_FILENAME = is_darwin or is_windows,
.HAVE_SYS_UIO_H = modern_unix,
.HAVE_READV = modern_unix,
.HAVE_DIRFD_AND_FLOCK = modern_unix,
.HAVE_FORKPTY = modern_unix and !is_darwin, // also on Darwin but we lack the headers :(
.HAVE_BE64TOH = modern_unix and !is_darwin,
.ORDER_BIG_ENDIAN = t.cpu.arch.endian() == .big,
.ENDIAN_INCLUDE_FILE = "endian.h",
.HAVE_EXECINFO_BACKTRACE = modern_unix and !t.isMuslLibC(),
.HAVE_BUILTIN_ADD_OVERFLOW = true,
.HAVE_WIMPLICIT_FALLTHROUGH_FLAG = true,
.HAVE_BITSCANFORWARD64 = null,
.VTERM_TEST_FILE = "test/vterm_test_output", // TODO(bfredl): revisit when porting libvterm tests
});
_ = gen_config.addCopyFile(sysconfig_step.getOutput(), "auto/config.h"); // run_preprocessor() workaronnd
_ = gen_config.add("auto/pathdef.h", b.fmt(
\\char *default_vim_dir = "/usr/local/share/nvim";
\\char *default_vimruntime_dir = "";
\\char *default_lib_dir = "/usr/local/lib/nvim";
, .{}));
// TODO(bfredl): include git version when available
const medium = b.fmt("v{}.{}.{}{s}+zig", .{ version.major, version.minor, version.patch, version.prerelease });
const versiondef_git = gen_config.add("auto/versiondef_git.h", b.fmt(
\\#define NVIM_VERSION_MEDIUM "{s}"
\\#define NVIM_VERSION_BUILD "???"
\\
, .{medium}));
// TODO(zig): using getEmittedIncludeTree() is ugly af. we want unittests
// to reuse the std.build.Module include_path thing
const unittest_include_path = [_]LazyPath{
b.path("src/"),
gen_config.getDirectory(),
lua.getEmittedIncludeTree(),
libuv.getEmittedIncludeTree(),
libluv.getEmittedIncludeTree(),
utf8proc.artifact("utf8proc").getEmittedIncludeTree(),
unibilium.artifact("unibilium").getEmittedIncludeTree(),
treesitter.artifact("tree-sitter").getEmittedIncludeTree(),
if (iconv) |dep| dep.artifact("iconv").getEmittedIncludeTree() else b.path("UNUSED_PATH/"),
};
const gen_headers, const funcs_data = try gen.nvim_gen_sources(b, nlua0, &nvim_sources, &nvim_headers, &api_headers, versiondef_git, version_lua);
const test_config_step = b.addWriteFiles();
_ = test_config_step.add("test/cmakeconfig/paths.lua", try test_config(b));
const test_gen_step = b.step("gen_headers", "debug: output generated headers");
const config_install = b.addInstallDirectory(.{ .source_dir = gen_config.getDirectory(), .install_dir = .prefix, .install_subdir = "config/" });
test_gen_step.dependOn(&config_install.step);
test_gen_step.dependOn(&b.addInstallDirectory(.{ .source_dir = gen_headers.getDirectory(), .install_dir = .prefix, .install_subdir = "headers/" }).step);
const nvim_exe = b.addExecutable(.{
.name = "nvim",
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
nvim_exe.rdynamic = true; // -E
nvim_exe.linkLibrary(lua);
nvim_exe.linkLibrary(libuv);
nvim_exe.linkLibrary(libluv);
if (iconv) |dep| nvim_exe.linkLibrary(dep.artifact("iconv"));
nvim_exe.linkLibrary(utf8proc.artifact("utf8proc"));
nvim_exe.linkLibrary(unibilium.artifact("unibilium"));
nvim_exe.linkLibrary(treesitter.artifact("tree-sitter"));
if (is_windows) {
nvim_exe.linkSystemLibrary("netapi32");
}
nvim_exe.addIncludePath(b.path("src"));
nvim_exe.addIncludePath(gen_config.getDirectory());
nvim_exe.addIncludePath(gen_headers.getDirectory());
build_lua.add_lua_modules(nvim_exe.root_module, lpeg, use_luajit, false);
var unit_test_sources = try std.ArrayList([]u8).initCapacity(b.allocator, 10);
if (support_unittests) {
var unit_test_fixtures = try src_dir.openDir("test/unit/fixtures/", .{ .iterate = true });
defer unit_test_fixtures.close();
var it = unit_test_fixtures.iterateAssumeFirstIteration();
while (try it.next()) |entry| {
if (entry.name.len < 3) continue;
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
try unit_test_sources.append(b.fmt("test/unit/fixtures/{s}", .{entry.name}));
}
}
}
const src_paths = try b.allocator.alloc([]u8, nvim_sources.items.len + unit_test_sources.items.len);
for (nvim_sources.items, 0..) |s, i| {
src_paths[i] = b.fmt("src/nvim/{s}", .{s.name});
}
@memcpy(src_paths[nvim_sources.items.len..], unit_test_sources.items);
const flags = [_][]const u8{
"-std=gnu99",
"-DZIG_BUILD",
"-D_GNU_SOURCE",
if (support_unittests) "-DUNIT_TESTING" else "",
if (use_luajit) "" else "-DNVIM_VENDOR_BIT",
if (is_windows) "-DMSWIN" else "",
if (is_windows) "-DWIN32_LEAN_AND_MEAN" else "",
if (is_windows) "-DUTF8PROC_STATIC" else "",
};
nvim_exe.addCSourceFiles(.{ .files = src_paths, .flags = &flags });
nvim_exe.addCSourceFiles(.{ .files = &.{
"src/xdiff/xdiffi.c",
"src/xdiff/xemit.c",
"src/xdiff/xhistogram.c",
"src/xdiff/xpatience.c",
"src/xdiff/xprepare.c",
"src/xdiff/xutils.c",
"src/cjson/lua_cjson.c",
"src/cjson/fpconv.c",
"src/cjson/strbuf.c",
}, .flags = &flags });
const nvim_exe_step = b.step("nvim_bin", "only the binary (not a fully working install!)");
const nvim_exe_install = b.addInstallArtifact(nvim_exe, .{});
nvim_exe_step.dependOn(&nvim_exe_install.step);
const gen_runtime = try runtime.nvim_gen_runtime(b, nlua0, funcs_data);
const runtime_install = b.addInstallDirectory(.{ .source_dir = gen_runtime.getDirectory(), .install_dir = .prefix, .install_subdir = "runtime/" });
const nvim = b.step("nvim", "build the editor");
nvim.dependOn(&nvim_exe_install.step);
nvim.dependOn(&runtime_install.step);
const lua_dev_deps = b.dependency("lua_dev_deps", .{});
const test_deps = b.step("test_deps", "test prerequisites");
test_deps.dependOn(&nvim_exe_install.step);
test_deps.dependOn(&runtime_install.step);
test_deps.dependOn(test_fixture(b, "shell-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize));
test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize));
const parser_c = b.dependency("treesitter_c", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "c", parser_c.path("."), false, target, optimize));
const parser_markdown = b.dependency("treesitter_markdown", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "markdown", parser_markdown.path("tree-sitter-markdown/"), true, target, optimize));
test_deps.dependOn(add_ts_parser(b, "markdown_inline", parser_markdown.path("tree-sitter-markdown-inline/"), true, target, optimize));
const parser_vim = b.dependency("treesitter_vim", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "vim", parser_vim.path("."), true, target, optimize));
const parser_vimdoc = b.dependency("treesitter_vimdoc", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "vimdoc", parser_vimdoc.path("."), false, target, optimize));
const parser_lua = b.dependency("treesitter_lua", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "lua", parser_lua.path("."), true, target, optimize));
const parser_query = b.dependency("treesitter_query", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "query", parser_query.path("."), false, target, optimize));
const unit_headers: ?[]const LazyPath = if (support_unittests) &(unittest_include_path ++ .{gen_headers.getDirectory()}) else null;
try tests.test_steps(b, nvim_exe, test_deps, lua_dev_deps.path("."), test_config_step.getDirectory(), unit_headers);
}
pub fn test_fixture(
b: *std.Build,
name: []const u8,
libuv: ?*std.Build.Step.Compile,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
) *std.Build.Step {
const fixture = b.addExecutable(.{
.name = name,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
const source = if (std.mem.eql(u8, name, "pwsh-test")) "shell-test" else name;
fixture.addCSourceFile(.{ .file = b.path(b.fmt("./test/functional/fixtures/{s}.c", .{source})) });
fixture.linkLibC();
if (libuv) |uv| fixture.linkLibrary(uv);
return &b.addInstallArtifact(fixture, .{}).step;
}
pub fn add_ts_parser(
b: *std.Build,
name: []const u8,
parser_dir: LazyPath,
scanner: bool,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
) *std.Build.Step {
const parser = b.addLibrary(.{
.name = name,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
.linkage = .dynamic,
});
parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/parser.c") });
if (scanner) parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/scanner.c") });
parser.addIncludePath(parser_dir.path(b, "src"));
parser.linkLibC();
const parser_install = b.addInstallArtifact(parser, .{ .dest_sub_path = b.fmt("parser/{s}.so", .{name}) });
return &parser_install.step;
}
pub fn lua_version_info(b: *std.Build) []u8 {
const v = version;
return b.fmt(
\\return {{
\\ {{"major", {}}},
\\ {{"minor", {}}},
\\ {{"patch", {}}},
\\ {{"prerelease", {}}},
\\ {{"api_level", {}}},
\\ {{"api_compatible", {}}},
\\ {{"api_prerelease", {}}},
\\}}
, .{ v.major, v.minor, v.patch, v.prerelease.len > 0, v.api_level, v.api_level_compat, v.api_prerelease });
}
pub fn test_config(b: *std.Build) ![]u8 {
var buf: [std.fs.max_path_bytes]u8 = undefined;
const src_path = try b.build_root.handle.realpath(".", &buf);
// we don't use test/cmakeconfig/paths.lua.in because it contains cmake specific logic
return b.fmt(
\\local M = {{}}
\\
\\M.apple_sysroot = ""
\\M.translations_enabled = "$ENABLE_TRANSLATIONS" == "ON"
\\M.is_asan = "$ENABLE_ASAN_UBSAN" == "ON"
\\M.is_zig_build = true
\\M.vterm_test_file = "test/vterm_test_output"
\\M.test_build_dir = "{[bin_dir]s}" -- bull
\\M.test_source_path = "{[src_path]s}"
\\M.test_lua_prg = ""
\\M.test_luajit_prg = ""
\\ -- include path passed on the cmdline, see test/lua_runner.lua
\\M.include_paths = _G.c_include_path or {{}}
\\
\\return M
, .{ .bin_dir = b.install_path, .src_path = src_path });
}

View File

@@ -1,72 +0,0 @@
.{
.name = .neovim,
.fingerprint = 0x66eb090879307a38,
.version = "0.12.0",
.minimum_zig_version = "0.14.0",
.dependencies = .{
.zlua = .{
.url = "git+https://github.com/natecraddock/ziglua#6889b2d90ee6ae96810a9f04ec7c62d9aa91d088",
.hash = "zlua-0.1.0-hGRpCxctBQDEQgDArJ0Kc4RDIsD-Hw3pw9pPPw_kGmmY",
},
.lpeg = .{
.url = "https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz",
.hash = "N-V-__8AAMnaAwCEutreuREG3QayBVEZqUTDQFY1Nsrv2OIt",
},
.luv = .{
.url = "git+https://github.com/luvit/luv?ref=1.51.0-1#4c9fbc6cf6f3338bb0e0426710cf885ee557b540",
.hash = "N-V-__8AAMlNDwCY07jUoMiq3iORXdZy0uFWKiHsy8MaDBJA",
},
.lua_compat53 = .{
.url = "https://github.com/lunarmodules/lua-compat-5.3/archive/v0.13.tar.gz",
.hash = "N-V-__8AADi-AwDnVoXwDCQvv2wcYOmN0bJLqZ44J3lwoQY2",
},
.treesitter = .{
.url = "git+https://github.com/tree-sitter/tree-sitter#d87921bb9c39b0b06c811f2082f9a9991cdca027",
.hash = "tree_sitter-0.26.0-Tw2sRxO7CwC0NyDrSygSi7UXRHMNUFEF8GRq6dK81lRF",
},
.libuv = .{
.url = "git+https://github.com/allyourcodebase/libuv#a2dfd385bd2a00d6d290fda85a40a55a9d6cffc5",
.hash = "libuv-1.51.0-htqqv6liAADxBLIBCZT-qUh_3nRRwtNYsOFQOUmrd_sx",
},
.utf8proc = .{ .path = "./deps/utf8proc/" },
.unibilium = .{ .path = "./deps/unibilium/" },
.libiconv = .{
.url = "git+https://github.com/allyourcodebase/libiconv#9def4c8a1743380e85bcedb80f2c15b455e236f3",
.hash = "libiconv-1.18.0-p9sJwWnqAACzVYeWgXB5r5lOQ74XwTPlptixV0JPRO28",
.lazy = true,
},
.lua_dev_deps = .{
.url = "https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz",
.hash = "N-V-__8AAGevEQCHAkCozca5AIdN9DFc3Luf3g3r2AcbyOrm",
},
.treesitter_c = .{
.url = "git+https://github.com/tree-sitter/tree-sitter-c?ref=v0.24.1#7fa1be1b694b6e763686793d97da01f36a0e5c12",
.hash = "N-V-__8AANxPSABzw3WBTSH_YkwaGAfrK6PBqAMqQedkDDim",
},
.treesitter_markdown = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-markdown?ref=v0.5.0#afaa4138517363362f54c89330c9d79391e81168",
.hash = "N-V-__8AAIIZUwD3CGdyI2DiHu7Suj2jIF_EAVlM6REFGwju",
},
.treesitter_lua = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-lua?ref=v0.4.0#4569d1c361129e71a205b94a05e158bd71b1709f",
.hash = "N-V-__8AAEF5CABqSL9zqc03aQsT6Nni54ZCcL98pnuDL2D3",
},
.treesitter_vim = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-vim?ref=v0.7.0#3dd4747082d1b717b8978211c06ef7b6cd16125b",
.hash = "N-V-__8AAMArVAB4uo2wg2XRs8HBviQ4Pq366cC_iRolX4Vc",
},
.treesitter_vimdoc = .{
.url = "git+https://github.com/neovim/tree-sitter-vimdoc?ref=v4.0.0#9f6191a98702edc1084245abd5523279d4b681fb",
.hash = "N-V-__8AAI4YCgD7OqxCEAmz2RqT_ohl6eA4F0fGMtLIe7nb",
},
.treesitter_query = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.6.2#8a43889f89fd0667289936341bff3a77bafade17",
.hash = "N-V-__8AAARLBACBLGiXGFTijEzLv8AwiqT_kJpmVjir1BgX",
},
},
.paths = .{
// TODO(bfredl): explicitly list the subdirs which actually are used
"",
},
}

View File

@@ -12,10 +12,6 @@
#endif
#define NVIM_VERSION_CFLAGS "${VERSION_STRING}"
#ifdef ZIG_BUILD
# define NVIM_VERSION_BUILD_TYPE "${CONFIG}"
#else
#define NVIM_VERSION_BUILD_TYPE "$<CONFIG>"
#endif
#endif // AUTO_VERSIONDEF_H

View File

@@ -73,7 +73,7 @@ if(HAS_OG_FLAG)
set(DEFAULT_MAKE_CFLAGS CFLAGS+=-Og ${DEFAULT_MAKE_CFLAGS})
endif()
set(DEPS_INCLUDE_FLAGS "-I\"${DEPS_INSTALL_DIR}/include\" -I\"${DEPS_INSTALL_DIR}/include/luajit-2.1\"")
set(DEPS_INCLUDE_FLAGS "-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/include/luajit-2.1")
# If the macOS deployment target is not set manually (via $MACOSX_DEPLOYMENT_TARGET),
# fall back to local system version. Needs to be done here and in top-level CMakeLists.txt.
@@ -96,10 +96,10 @@ else()
find_package(Lua 5.1 EXACT)
if(LUAJIT_FOUND)
set(LUA_ENGINE LuaJit)
string(APPEND DEPS_INCLUDE_FLAGS " -I\"${LUAJIT_INCLUDE_DIR}\"")
string(APPEND DEPS_INCLUDE_FLAGS " -I${LUAJIT_INCLUDE_DIR}")
elseif(LUA_FOUND)
set(LUA_ENGINE Lua)
string(APPEND DEPS_INCLUDE_FLAGS " -I\"${LUA_INCLUDE_DIR}\"")
string(APPEND DEPS_INCLUDE_FLAGS " -I${LUA_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Could not find system lua or luajit")
endif()

View File

@@ -42,7 +42,7 @@ if(APPLE)
endif()
if(UNIX)
BuildLuajit(INSTALL_COMMAND ${BUILDCMD_UNIX}
BuildLuaJit(INSTALL_COMMAND ${BUILDCMD_UNIX}
CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR}
${DEPLOYMENT_TARGET} install)
@@ -53,7 +53,7 @@ elseif(MINGW)
else()
set(LUAJIT_MAKE_PRG ${CMAKE_MAKE_PROGRAM})
endif()
BuildLuajit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER}
BuildLuaJit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER}
PREFIX=${DEPS_INSTALL_DIR}
CFLAGS+=-DLUA_USE_APICHECK
CFLAGS+=-funwind-tables
@@ -75,7 +75,7 @@ elseif(MINGW)
)
elseif(MSVC)
BuildLuajit(
BuildLuaJit(
BUILD_COMMAND ${CMAKE_COMMAND} -E chdir ${DEPS_BUILD_DIR}/src/luajit/src ${DEPS_BUILD_DIR}/src/luajit/src/msvcbuild.bat
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/luajit.exe ${DEPS_BIN_DIR}

View File

@@ -7,6 +7,5 @@ ExternalProject_Add(wasmtime
-D WASMTIME_FASTEST_RUNTIME=ON # build with full LTO
-D WASMTIME_DISABLE_ALL_FEATURES=ON # don't need all that crap...
-D WASMTIME_FEATURE_CRANELIFT=ON # ...except this one (compiles wasm to platform code)
-D WASMTIME_FEATURE_GC_DRC=ON # ...and this one (needed by ts to create engines)
USES_TERMINAL_BUILD TRUE
${EXTERNALPROJECT_OPTIONS})

View File

@@ -1,8 +1,8 @@
LIBUV_URL https://github.com/libuv/libuv/archive/v1.51.0.tar.gz
LIBUV_SHA256 27e55cf7083913bfb6826ca78cde9de7647cded648d35f24163f2d31bb9f51cd
LIBUV_URL https://github.com/libuv/libuv/archive/v1.50.0.tar.gz
LIBUV_SHA256 b1ec56444ee3f1e10c8bd3eed16ba47016ed0b94fe42137435aaf2e0bd574579
LUAJIT_URL https://github.com/luajit/luajit/archive/871db2c84ecefd70a850e03a6c340214a81739f0.tar.gz
LUAJIT_SHA256 ab3f16d82df6946543565cfb0d2810d387d79a3a43e0431695b03466188e2680
LUAJIT_URL https://github.com/luajit/luajit/archive/538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.gz
LUAJIT_SHA256 7acbc36be8f21072422eb9a5e5fc468d0eaa55bec1b70260d651e845684621e2
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
@@ -10,8 +10,8 @@ LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/v2.1.2.tar.gz
UNIBILIUM_SHA256 370ecb07fbbc20d91d1b350c55f1c806b06bf86797e164081ccc977fc9b3af7a
LUV_URL https://github.com/luvit/luv/archive/1.51.0-1.tar.gz
LUV_SHA256 d4a11178ae8e16ba5886799ea91905dd9b0b479c75aebd67866d37373e41526f
LUV_URL https://github.com/luvit/luv/archive/1.50.0-1.tar.gz
LUV_SHA256 bb4f0570571e40c1d2a7644f6f9c1309a6ccdb19bf4d397e8d7bfd0c6b88e613
LPEG_URL https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz
LPEG_SHA256 4b155d67d2246c1ffa7ad7bc466c1ea899bbc40fef0257cc9c03cecbaed4352a
@@ -34,25 +34,25 @@ LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/v2.10.0.tar.gz
UTF8PROC_SHA256 6f4f1b639daa6dca9f80bc5db1233e9cbaa31a67790887106160b33ef743f136
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.24.1.tar.gz
TREESITTER_C_SHA256 25dd4bb3dec770769a407e0fc803f424ce02c494a56ce95fedc525316dcf9b48
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.4.0.tar.gz
TREESITTER_LUA_SHA256 b0977aced4a63bb75f26725787e047b8f5f4a092712c840ea7070765d4049559
TREESITTER_VIM_URL https://github.com/tree-sitter-grammars/tree-sitter-vim/archive/v0.7.0.tar.gz
TREESITTER_VIM_SHA256 44eabc31127c4feacda19f2a05a5788272128ff561ce01093a8b7a53aadcc7b2
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v4.0.0.tar.gz
TREESITTER_VIMDOC_SHA256 8096794c0f090b2d74b7bff94548ac1be3285b929ec74f839bd9b3ff4f4c6a0b
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.6.2.tar.gz
TREESITTER_QUERY_SHA256 90682e128d048fbf2a2a17edca947db71e326fa0b3dba4136e041e096538b4eb
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.5.0.tar.gz
TREESITTER_MARKDOWN_SHA256 14c2c948ccf0e9b606eec39b09286c59dddf28307849f71b7ce2b1d1ef06937e
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.8.tar.gz
TREESITTER_SHA256 178b575244d967f4920a4642408dc4edf6de96948d37d7f06e5b78acee9c0b4e
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.23.4.tar.gz
TREESITTER_C_SHA256 b66c5043e26d84e5f17a059af71b157bcf202221069ed220aa1696d7d1d28a7a
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.3.0.tar.gz
TREESITTER_LUA_SHA256 a34cc70abfd8d2d4b0fabf01403ea05f848e1a4bc37d8a4bfea7164657b35d31
TREESITTER_VIM_URL https://github.com/tree-sitter-grammars/tree-sitter-vim/archive/v0.5.0.tar.gz
TREESITTER_VIM_SHA256 90019d12d2da0751c027124f27f5335babf069a050457adaed53693b5e9cf10a
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.1.tar.gz
TREESITTER_VIMDOC_SHA256 76b65e5bee9ff78eb21256619b1995aac4d80f252c19e1c710a4839481ded09e
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.5.1.tar.gz
TREESITTER_QUERY_SHA256 fe8c712880a529d454347cd4c58336ac2db22243bae5055bdb5844fb3ea56192
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.4.1.tar.gz
TREESITTER_MARKDOWN_SHA256 e0fdb2dca1eb3063940122e1475c9c2b069062a638c95939e374c5427eddee9f
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.3.tar.gz
TREESITTER_SHA256 862fac52653bc7bc9d2cd0630483e6bdf3d02bcd23da956ca32663c4798a93e3
WASMTIME_URL https://github.com/bytecodealliance/wasmtime/archive/v29.0.1.tar.gz
WASMTIME_SHA256 b94b6c6fd6aebaf05d4c69c1b12b5dc217b0d42c1a95f435b33af63dddfa5304
UNCRUSTIFY_URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.81.0.tar.gz
UNCRUSTIFY_SHA256 484623dc16b92206adc6ac0770077c6c67c6e441102148c2a121a19549330ff9
UNCRUSTIFY_URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.80.1.tar.gz
UNCRUSTIFY_SHA256 0e2616ec2f78e12816388c513f7060072ff7942b42f1175eb28b24cb75aaec48
LUA_DEV_DEPS_URL https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz
LUA_DEV_DEPS_SHA256 49f8399e453103064a23c65534f266f3067cda716b6502f016bfafeed5799354

View File

@@ -1,4 +1,4 @@
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|ARM64|aarch64)$")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
set(CMAKE_SYSTEM_PROCESSOR arm64)
endif()
@@ -27,13 +27,9 @@ set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
if(WIN32)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CPACK_PACKAGE_FILE_NAME "nvim-win-arm64")
else()
set(CPACK_PACKAGE_FILE_NAME "nvim-win64")
endif()
set(CPACK_GENERATOR ZIP WIX)
# WIX
# CPACK_WIX_UPGRADE_GUID should be set, but should never change.
# CPACK_WIX_PRODUCT_GUID should not be set (leave as default to auto-generate).

View File

@@ -7,7 +7,6 @@ set(ENV{XDG_DATA_HOME} ${BUILD_DIR}/Xtest_xdg/share)
set(ENV{XDG_STATE_HOME} ${BUILD_DIR}/Xtest_xdg/state)
unset(ENV{XDG_DATA_DIRS})
unset(ENV{NVIM}) # Clear $NVIM in case tests are running from Nvim. #11009
unset(ENV{TMUX}) # Nvim TUI shouldn't think it's running in tmux. #34173
# TODO(dundargoc): The CIRRUS_CI environment variable isn't passed to here from
# the main CMakeLists.txt, so we have to manually pass it to this script and
@@ -69,7 +68,7 @@ endif()
execute_process(
# Note: because of "-ll" (low-level interpreter mode), some modules like
# _editor.lua are not loaded.
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/ busted -v -o test.busted.outputHandlers.nvim
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR} busted -v -o test.busted.outputHandlers.nvim
--lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
--lpath=${BUILD_DIR}/?.lua
--lpath=${WORKING_DIR}/src/?.lua
@@ -79,6 +78,7 @@ execute_process(
${TEST_PATH}
TIMEOUT $ENV{TEST_TIMEOUT}
WORKING_DIRECTORY ${WORKING_DIR}
ERROR_VARIABLE err
RESULT_VARIABLE res
${EXTRA_ARGS})
@@ -87,6 +87,11 @@ file(REMOVE_RECURSE ${RM_FILES})
if(res)
message(STATUS "Tests exited non-zero: ${res}")
if("${err}" STREQUAL "")
message(STATUS "No output to stderr.")
else()
message(STATUS "Output to stderr:\n${err}")
endif()
# Dump the logfile on CI (if not displayed and moved already).
if(CI_BUILD)

View File

@@ -1,30 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const upstream = b.dependency("unibilium", .{});
const lib = b.addLibrary(.{
.name = "unibilium",
.linkage = .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
lib.addIncludePath(upstream.path(""));
lib.installHeader(upstream.path("unibilium.h"), "unibilium.h");
lib.linkLibC();
lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
"unibilium.c",
"uninames.c",
"uniutil.c",
}, .flags = &.{"-DTERMINFO_DIRS=\"/etc/terminfo:/usr/share/terminfo\""} });
b.installArtifact(lib);
}

View File

@@ -1,12 +0,0 @@
.{
.name = "unibilium",
.version = "2.1.2",
.paths = .{""},
.dependencies = .{
.unibilium = .{
.url = "git+https://github.com/neovim/unibilium?ref=v2.1.2#bfcb0350129dd76893bc90399cf37c45812268a2",
.hash = "N-V-__8AADO1CgCggvx73yptnBlXbEm7TjOSO6VGIqc0CvYR",
},
},
}

View File

@@ -1,27 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const upstream = b.dependency("utf8proc", .{});
const lib = b.addLibrary(.{
.name = "utf8proc",
.linkage = .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
lib.addIncludePath(upstream.path(""));
lib.installHeader(upstream.path("utf8proc.h"), "utf8proc.h");
lib.linkLibC();
lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
"utf8proc.c",
}, .flags = &.{"-DUTF8PROC_STATIC"} });
b.installArtifact(lib);
}

View File

@@ -1,12 +0,0 @@
.{
.name = "utf8proc",
.version = "2.10.0",
.paths = .{""},
.dependencies = .{
.utf8proc = .{
.url = "git+https://github.com/JuliaStrings/utf8proc?ref=v2.10.0#a1b99daa2a3393884220264c927a48ba1251a9c6",
.hash = "N-V-__8AAPJfKADYDOC95xuKyudrlob6eFqgzfFl8NbpOoU9",
},
},
}

View File

@@ -12,17 +12,12 @@ get_directory_property(LUA_GEN_DEPS DIRECTORY ${PROJECT_SOURCE_DIR}/src/nvim DEF
add_custom_command(OUTPUT ${GENERATED_SYN_VIM}
COMMAND ${LUA_GEN} ${SYN_VIM_GENERATOR} ${GENERATED_SYN_VIM} ${FUNCS_DATA}
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua
${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua
${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
DEPENDS
${LUA_GEN_DEPS}
${SYN_VIM_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua
${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
${PROJECT_SOURCE_DIR}/src/nvim/eval.c
${FUNCS_DATA}
)

View File

@@ -0,0 +1,859 @@
----------------------------------------
-- This file is generated via github.com/tjdevries/vim9jit
-- For any bugs, please first consider reporting there.
----------------------------------------
-- Ignore "value assigned to a local variable is unused" because
-- we can't guarantee that local variables will be used by plugins
-- luacheck: ignore
--- @diagnostic disable
local vim9 = require('_vim9script')
local M = {}
local prepended = nil
local grepCache = nil
local Complete = nil
local GetAddition = nil
local Tag2item = nil
local Dict2info = nil
local ParseTagline = nil
local Tagline2item = nil
local Tagcmd2extra = nil
local Nextitem = nil
local StructMembers = nil
local SearchMembers = nil
-- vim9script
-- # Vim completion script
-- # Language: C
-- # Maintainer: The Vim Project <https://github.com/vim/vim>
-- # Last Change: 2023 Aug 10
-- # Rewritten in Vim9 script by github user lacygoill
-- # Former Maintainer: Bram Moolenaar <Bram@vim.org>
prepended = ''
grepCache = vim.empty_dict()
-- # This function is used for the 'omnifunc' option.
Complete = function(findstart, abase)
findstart = vim9.bool(findstart)
if vim9.bool(findstart) then
-- # Locate the start of the item, including ".", "->" and "[...]".
local line = vim9.fn.getline('.')
local start = vim9.fn.charcol('.') - 1
local lastword = -1
while start > 0 do
if vim9.ops.RegexpMatches(vim9.index(line, vim9.ops.Minus(start, 1)), '\\w') then
start = start - 1
elseif
vim9.bool(vim9.ops.RegexpMatches(vim9.index(line, vim9.ops.Minus(start, 1)), '\\.'))
then
if lastword == -1 then
lastword = start
end
start = start - 1
elseif
vim9.bool(
start > 1
and vim9.index(line, vim9.ops.Minus(start, 2)) == '-'
and vim9.index(line, vim9.ops.Minus(start, 1)) == '>'
)
then
if lastword == -1 then
lastword = start
end
start = vim9.ops.Minus(start, 2)
elseif vim9.bool(vim9.index(line, vim9.ops.Minus(start, 1)) == ']') then
-- # Skip over [...].
local n = 0
start = start - 1
while start > 0 do
start = start - 1
if vim9.index(line, start) == '[' then
if n == 0 then
break
end
n = n - 1
elseif vim9.bool(vim9.index(line, start) == ']') then
n = n + 1
end
end
else
break
end
end
-- # Return the column of the last word, which is going to be changed.
-- # Remember the text that comes before it in prepended.
if lastword == -1 then
prepended = ''
return vim9.fn.byteidx(line, start)
end
prepended = vim9.slice(line, start, vim9.ops.Minus(lastword, 1))
return vim9.fn.byteidx(line, lastword)
end
-- # Return list of matches.
local base = prepended .. abase
-- # Don't do anything for an empty base, would result in all the tags in the
-- # tags file.
if base == '' then
return {}
end
-- # init cache for vimgrep to empty
grepCache = {}
-- # Split item in words, keep empty word after "." or "->".
-- # "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
-- # We can't use split, because we need to skip nested [...].
-- # "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> ['aa', 'bb', '[...]'], etc.
local items = {}
local s = 0
local arrays = 0
while 1 do
local e = vim9.fn.charidx(base, vim9.fn.match(base, '\\.\\|->\\|\\[', s))
if e < 0 then
if s == 0 or vim9.index(base, vim9.ops.Minus(s, 1)) ~= ']' then
vim9.fn.add(items, vim9.slice(base, s, nil))
end
break
end
if s == 0 or vim9.index(base, vim9.ops.Minus(s, 1)) ~= ']' then
vim9.fn.add(items, vim9.slice(base, s, vim9.ops.Minus(e, 1)))
end
if vim9.index(base, e) == '.' then
-- # skip over '.'
s = vim9.ops.Plus(e, 1)
elseif vim9.bool(vim9.index(base, e) == '-') then
-- # skip over '->'
s = vim9.ops.Plus(e, 2)
else
-- # Skip over [...].
local n = 0
s = e
e = e + 1
while e < vim9.fn.strcharlen(base) do
if vim9.index(base, e) == ']' then
if n == 0 then
break
end
n = n - 1
elseif vim9.bool(vim9.index(base, e) == '[') then
n = n + 1
end
e = e + 1
end
e = e + 1
vim9.fn.add(items, vim9.slice(base, s, vim9.ops.Minus(e, 1)))
arrays = arrays + 1
s = e
end
end
-- # Find the variable items[0].
-- # 1. in current function (like with "gd")
-- # 2. in tags file(s) (like with ":tag")
-- # 3. in current file (like with "gD")
local res = {}
if vim9.fn.searchdecl(vim9.index(items, 0), false, true) == 0 then
-- # Found, now figure out the type.
-- # TODO: join previous line if it makes sense
local line = vim9.fn.getline('.')
local col = vim9.fn.charcol('.')
if vim9.fn.stridx(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), ';') >= 0 then
-- # Handle multiple declarations on the same line.
local col2 = vim9.ops.Minus(col, 1)
while vim9.index(line, col2) ~= ';' do
col2 = col2 - 1
end
line = vim9.slice(line, vim9.ops.Plus(col2, 1), nil)
col = vim9.ops.Minus(col, col2)
end
if vim9.fn.stridx(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), ',') >= 0 then
-- # Handle multiple declarations on the same line in a function
-- # declaration.
local col2 = vim9.ops.Minus(col, 1)
while vim9.index(line, col2) ~= ',' do
col2 = col2 - 1
end
if
vim9.ops.RegexpMatches(
vim9.slice(line, vim9.ops.Plus(col2, 1), vim9.ops.Minus(col, 1)),
' *[^ ][^ ]* *[^ ]'
)
then
line = vim9.slice(line, vim9.ops.Plus(col2, 1), nil)
col = vim9.ops.Minus(col, col2)
end
end
if vim9.fn.len(items) == 1 then
-- # Completing one word and it's a local variable: May add '[', '.' or
-- # '->'.
local match = vim9.index(items, 0)
local kind = 'v'
if vim9.fn.match(line, '\\<' .. match .. '\\s*\\[') > 0 then
match = match .. '['
else
res = Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), { '' }, 0, true)
if vim9.fn.len(res) > 0 then
-- # There are members, thus add "." or "->".
if vim9.fn.match(line, '\\*[ \\t(]*' .. match .. '\\>') > 0 then
match = match .. '->'
else
match = match .. '.'
end
end
end
res = { { ['match'] = match, ['tagline'] = '', ['kind'] = kind, ['info'] = line } }
elseif vim9.bool(vim9.fn.len(items) == vim9.ops.Plus(arrays, 1)) then
-- # Completing one word and it's a local array variable: build tagline
-- # from declaration line
local match = vim9.index(items, 0)
local kind = 'v'
local tagline = '\t/^' .. line .. '$/'
res = { { ['match'] = match, ['tagline'] = tagline, ['kind'] = kind, ['info'] = line } }
else
-- # Completing "var.", "var.something", etc.
res =
Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), vim9.slice(items, 1, nil), 0, true)
end
end
if vim9.fn.len(items) == 1 or vim9.fn.len(items) == vim9.ops.Plus(arrays, 1) then
-- # Only one part, no "." or "->": complete from tags file.
local tags = {}
if vim9.fn.len(items) == 1 then
tags = vim9.fn.taglist('^' .. base)
else
tags = vim9.fn.taglist('^' .. vim9.index(items, 0) .. '$')
end
vim9.fn_mut('filter', {
vim9.fn_mut('filter', {
tags,
function(_, v)
return vim9.ternary(vim9.fn.has_key(v, 'kind'), function()
return v.kind ~= 'm'
end, true)
end,
}, { replace = 0 }),
function(_, v)
return vim9.ops.Or(
vim9.ops.Or(
vim9.prefix['Bang'](vim9.fn.has_key(v, 'static')),
vim9.prefix['Bang'](vim9.index(v, 'static'))
),
vim9.fn.bufnr('%') == vim9.fn.bufnr(vim9.index(v, 'filename'))
)
end,
}, { replace = 0 })
res = vim9.fn.extend(
res,
vim9.fn.map(tags, function(_, v)
return Tag2item(v)
end)
)
end
if vim9.fn.len(res) == 0 then
-- # Find the variable in the tags file(s)
local diclist = vim9.fn.filter(
vim9.fn.taglist('^' .. vim9.index(items, 0) .. '$'),
function(_, v)
return vim9.ternary(vim9.fn.has_key(v, 'kind'), function()
return v.kind ~= 'm'
end, true)
end
)
res = {}
for _, i in vim9.iter(vim9.fn.range(vim9.fn.len(diclist))) do
-- # New ctags has the "typeref" field. Patched version has "typename".
if vim9.bool(vim9.fn.has_key(vim9.index(diclist, i), 'typename')) then
res = vim9.fn.extend(
res,
StructMembers(
vim9.index(vim9.index(diclist, i), 'typename'),
vim9.slice(items, 1, nil),
true
)
)
elseif vim9.bool(vim9.fn.has_key(vim9.index(diclist, i), 'typeref')) then
res = vim9.fn.extend(
res,
StructMembers(
vim9.index(vim9.index(diclist, i), 'typeref'),
vim9.slice(items, 1, nil),
true
)
)
end
-- # For a variable use the command, which must be a search pattern that
-- # shows the declaration of the variable.
if vim9.index(vim9.index(diclist, i), 'kind') == 'v' then
local line = vim9.index(vim9.index(diclist, i), 'cmd')
if vim9.slice(line, nil, 1) == '/^' then
local col =
vim9.fn.charidx(line, vim9.fn.match(line, '\\<' .. vim9.index(items, 0) .. '\\>'))
res = vim9.fn.extend(
res,
Nextitem(
vim9.slice(line, 2, vim9.ops.Minus(col, 1)),
vim9.slice(items, 1, nil),
0,
true
)
)
end
end
end
end
if vim9.fn.len(res) == 0 and vim9.fn.searchdecl(vim9.index(items, 0), true) == 0 then
-- # Found, now figure out the type.
-- # TODO: join previous line if it makes sense
local line = vim9.fn.getline('.')
local col = vim9.fn.charcol('.')
res =
Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), vim9.slice(items, 1, nil), 0, true)
end
-- # If the last item(s) are [...] they need to be added to the matches.
local last = vim9.fn.len(items) - 1
local brackets = ''
while last >= 0 do
if vim9.index(vim9.index(items, last), 0) ~= '[' then
break
end
brackets = vim9.index(items, last) .. brackets
last = last - 1
end
return vim9.fn.map(res, function(_, v)
return Tagline2item(v, brackets)
end)
end
M['Complete'] = Complete
GetAddition = function(line, match, memarg, bracket)
bracket = vim9.bool(bracket)
-- # Guess if the item is an array.
if vim9.bool(vim9.ops.And(bracket, vim9.fn.match(line, match .. '\\s*\\[') > 0)) then
return '['
end
-- # Check if the item has members.
if vim9.fn.len(SearchMembers(memarg, { '' }, false)) > 0 then
-- # If there is a '*' before the name use "->".
if vim9.fn.match(line, '\\*[ \\t(]*' .. match .. '\\>') > 0 then
return '->'
else
return '.'
end
end
return ''
end
Tag2item = function(val)
-- # Turn the tag info "val" into an item for completion.
-- # "val" is is an item in the list returned by taglist().
-- # If it is a variable we may add "." or "->". Don't do it for other types,
-- # such as a typedef, by not including the info that GetAddition() uses.
local res = vim9.convert.decl_dict({ ['match'] = vim9.index(val, 'name') })
res[vim9.index_expr('extra')] =
Tagcmd2extra(vim9.index(val, 'cmd'), vim9.index(val, 'name'), vim9.index(val, 'filename'))
local s = Dict2info(val)
if s ~= '' then
res[vim9.index_expr('info')] = s
end
res[vim9.index_expr('tagline')] = ''
if vim9.bool(vim9.fn.has_key(val, 'kind')) then
local kind = vim9.index(val, 'kind')
res[vim9.index_expr('kind')] = kind
if kind == 'v' then
res[vim9.index_expr('tagline')] = '\t' .. vim9.index(val, 'cmd')
res[vim9.index_expr('dict')] = val
elseif vim9.bool(kind == 'f') then
res[vim9.index_expr('match')] = vim9.index(val, 'name') .. '('
end
end
return res
end
Dict2info = function(dict)
-- # Use all the items in dictionary for the "info" entry.
local info = ''
for _, k in vim9.iter(vim9.fn_mut('sort', { vim9.fn.keys(dict) }, { replace = 0 })) do
info = info .. k .. vim9.fn['repeat'](' ', 10 - vim9.fn.strlen(k))
if k == 'cmd' then
info = info
.. vim9.fn.substitute(
vim9.fn.matchstr(vim9.index(dict, 'cmd'), '/^\\s*\\zs.*\\ze$/'),
'\\\\\\(.\\)',
'\\1',
'g'
)
else
local dictk = vim9.index(dict, k)
if vim9.fn.typename(dictk) ~= 'string' then
info = info .. vim9.fn.string(dictk)
else
info = info .. dictk
end
end
info = info .. '\n'
end
return info
end
ParseTagline = function(line)
-- # Parse a tag line and return a dictionary with items like taglist()
local l = vim9.fn.split(line, '\t')
local d = vim.empty_dict()
if vim9.fn.len(l) >= 3 then
d[vim9.index_expr('name')] = vim9.index(l, 0)
d[vim9.index_expr('filename')] = vim9.index(l, 1)
d[vim9.index_expr('cmd')] = vim9.index(l, 2)
local n = 2
if vim9.ops.RegexpMatches(vim9.index(l, 2), '^/') then
-- # Find end of cmd, it may contain Tabs.
while n < vim9.fn.len(l) and vim9.ops.NotRegexpMatches(vim9.index(l, n), '/;"$') do
n = n + 1
d[vim9.index_expr('cmd')] = vim9.index(d, 'cmd') .. ' ' .. vim9.index(l, n)
end
end
for _, i in vim9.iter(vim9.fn.range(vim9.ops.Plus(n, 1), vim9.fn.len(l) - 1)) do
if vim9.index(l, i) == 'file:' then
d[vim9.index_expr('static')] = 1
elseif vim9.bool(vim9.ops.NotRegexpMatches(vim9.index(l, i), ':')) then
d[vim9.index_expr('kind')] = vim9.index(l, i)
else
d[vim9.index_expr(vim9.fn.matchstr(vim9.index(l, i), '[^:]*'))] =
vim9.fn.matchstr(vim9.index(l, i), ':\\zs.*')
end
end
end
return d
end
Tagline2item = function(val, brackets)
-- # Turn a match item "val" into an item for completion.
-- # "val['match']" is the matching item.
-- # "val['tagline']" is the tagline in which the last part was found.
local line = vim9.index(val, 'tagline')
local add = GetAddition(line, vim9.index(val, 'match'), { val }, brackets == '')
local res = vim9.convert.decl_dict({ ['word'] = vim9.index(val, 'match') .. brackets .. add })
if vim9.bool(vim9.fn.has_key(val, 'info')) then
-- # Use info from Tag2item().
res[vim9.index_expr('info')] = vim9.index(val, 'info')
else
-- # Parse the tag line and add each part to the "info" entry.
local s = Dict2info(ParseTagline(line))
if s ~= '' then
res[vim9.index_expr('info')] = s
end
end
if vim9.bool(vim9.fn.has_key(val, 'kind')) then
res[vim9.index_expr('kind')] = vim9.index(val, 'kind')
elseif vim9.bool(add == '(') then
res[vim9.index_expr('kind')] = 'f'
else
local s = vim9.fn.matchstr(line, '\\t\\(kind:\\)\\=\\zs\\S\\ze\\(\\t\\|$\\)')
if s ~= '' then
res[vim9.index_expr('kind')] = s
end
end
if vim9.bool(vim9.fn.has_key(val, 'extra')) then
res[vim9.index_expr('menu')] = vim9.index(val, 'extra')
return res
end
-- # Isolate the command after the tag and filename.
local s = vim9.fn.matchstr(
line,
'[^\\t]*\\t[^\\t]*\\t\\zs\\(/^.*$/\\|[^\\t]*\\)\\ze\\(;"\\t\\|\\t\\|$\\)'
)
if s ~= '' then
res[vim9.index_expr('menu')] = Tagcmd2extra(
s,
vim9.index(val, 'match'),
vim9.fn.matchstr(line, '[^\\t]*\\t\\zs[^\\t]*\\ze\\t')
)
end
return res
end
Tagcmd2extra = function(cmd, name, fname)
-- # Turn a command from a tag line to something that is useful in the menu
local x = ''
if vim9.ops.RegexpMatches(cmd, '^/^') then
-- # The command is a search command, useful to see what it is.
x = vim9.fn.substitute(
vim9.fn.substitute(
vim9.fn.matchstr(cmd, '^/^\\s*\\zs.*\\ze$/'),
'\\<' .. name .. '\\>',
'@@',
''
),
'\\\\\\(.\\)',
'\\1',
'g'
) .. ' - ' .. fname
elseif vim9.bool(vim9.ops.RegexpMatches(cmd, '^\\d*$')) then
-- # The command is a line number, the file name is more useful.
x = fname .. ' - ' .. cmd
else
-- # Not recognized, use command and file name.
x = cmd .. ' - ' .. fname
end
return x
end
Nextitem = function(lead, items, depth, all)
all = vim9.bool(all)
-- # Find composing type in "lead" and match items[0] with it.
-- # Repeat this recursively for items[1], if it's there.
-- # When resolving typedefs "depth" is used to avoid infinite recursion.
-- # Return the list of matches.
-- # Use the text up to the variable name and split it in tokens.
local tokens = vim9.fn.split(lead, '\\s\\+\\|\\<')
-- # Try to recognize the type of the variable. This is rough guessing...
local res = {}
local body = function(_, tidx)
-- # Skip tokens starting with a non-ID character.
if vim9.ops.NotRegexpMatches(vim9.index(tokens, tidx), '^\\h') then
return vim9.ITER_CONTINUE
end
-- # Recognize "struct foobar" and "union foobar".
-- # Also do "class foobar" when it's C++ after all (doesn't work very well
-- # though).
if
(
vim9.index(tokens, tidx) == 'struct'
or vim9.index(tokens, tidx) == 'union'
or vim9.index(tokens, tidx) == 'class'
) and vim9.ops.Plus(tidx, 1) < vim9.fn.len(tokens)
then
res = StructMembers(
vim9.index(tokens, tidx) .. ':' .. vim9.index(tokens, vim9.ops.Plus(tidx, 1)),
items,
all
)
return vim9.ITER_BREAK
end
-- # TODO: add more reserved words
if
vim9.fn.index(
{ 'int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern' },
vim9.index(tokens, tidx)
) >= 0
then
return vim9.ITER_CONTINUE
end
-- # Use the tags file to find out if this is a typedef.
local diclist = vim9.fn.taglist('^' .. vim9.index(tokens, tidx) .. '$')
local body = function(_, tagidx)
local item = vim9.convert.decl_dict(vim9.index(diclist, tagidx))
-- # New ctags has the "typeref" field. Patched version has "typename".
if vim9.bool(vim9.fn.has_key(item, 'typeref')) then
res = vim9.fn.extend(res, StructMembers(vim9.index(item, 'typeref'), items, all))
return vim9.ITER_CONTINUE
end
if vim9.bool(vim9.fn.has_key(item, 'typename')) then
res = vim9.fn.extend(res, StructMembers(vim9.index(item, 'typename'), items, all))
return vim9.ITER_CONTINUE
end
-- # Only handle typedefs here.
if vim9.index(item, 'kind') ~= 't' then
return vim9.ITER_CONTINUE
end
-- # Skip matches local to another file.
if
vim9.bool(
vim9.ops.And(
vim9.ops.And(vim9.fn.has_key(item, 'static'), vim9.index(item, 'static')),
vim9.fn.bufnr('%') ~= vim9.fn.bufnr(vim9.index(item, 'filename'))
)
)
then
return vim9.ITER_CONTINUE
end
-- # For old ctags we recognize "typedef struct aaa" and
-- # "typedef union bbb" in the tags file command.
local cmd = vim9.index(item, 'cmd')
local ei = vim9.fn.charidx(cmd, vim9.fn.matchend(cmd, 'typedef\\s\\+'))
if ei > 1 then
local cmdtokens = vim9.fn.split(vim9.slice(cmd, ei, nil), '\\s\\+\\|\\<')
if vim9.fn.len(cmdtokens) > 1 then
if
vim9.index(cmdtokens, 0) == 'struct'
or vim9.index(cmdtokens, 0) == 'union'
or vim9.index(cmdtokens, 0) == 'class'
then
local name = ''
-- # Use the first identifier after the "struct" or "union"
for _, ti in vim9.iter(vim9.fn.range((vim9.fn.len(cmdtokens) - 1))) do
if vim9.ops.RegexpMatches(vim9.index(cmdtokens, ti), '^\\w') then
name = vim9.index(cmdtokens, ti)
break
end
end
if name ~= '' then
res = vim9.fn.extend(
res,
StructMembers(vim9.index(cmdtokens, 0) .. ':' .. name, items, all)
)
end
elseif vim9.bool(depth < 10) then
-- # Could be "typedef other_T some_T".
res = vim9.fn.extend(
res,
Nextitem(vim9.index(cmdtokens, 0), items, vim9.ops.Plus(depth, 1), all)
)
end
end
end
return vim9.ITER_DEFAULT
end
for _, tagidx in vim9.iter(vim9.fn.range(vim9.fn.len(diclist))) do
local nvim9_status, nvim9_ret = body(_, tagidx)
if nvim9_status == vim9.ITER_BREAK then
break
elseif nvim9_status == vim9.ITER_RETURN then
return nvim9_ret
end
end
if vim9.fn.len(res) > 0 then
return vim9.ITER_BREAK
end
return vim9.ITER_DEFAULT
end
for _, tidx in vim9.iter(vim9.fn.range(vim9.fn.len(tokens))) do
local nvim9_status, nvim9_ret = body(_, tidx)
if nvim9_status == vim9.ITER_BREAK then
break
elseif nvim9_status == vim9.ITER_RETURN then
return nvim9_ret
end
end
return res
end
StructMembers = function(atypename, items, all)
all = vim9.bool(all)
-- # Search for members of structure "typename" in tags files.
-- # Return a list with resulting matches.
-- # Each match is a dictionary with "match" and "tagline" entries.
-- # When "all" is true find all, otherwise just return 1 if there is any member.
-- # Todo: What about local structures?
local fnames = vim9.fn.join(vim9.fn.map(vim9.fn.tagfiles(), function(_, v)
return vim9.fn.escape(v, ' \\#%')
end))
if fnames == '' then
return {}
end
local typename = atypename
local qflist = {}
local cached = 0
local n = ''
if vim9.bool(vim9.prefix['Bang'](all)) then
n = '1'
if vim9.bool(vim9.fn.has_key(grepCache, typename)) then
qflist = vim9.index(grepCache, typename)
cached = 1
end
else
n = ''
end
if vim9.bool(vim9.prefix['Bang'](cached)) then
while 1 do
vim.api.nvim_command(
'silent! keepjumps noautocmd '
.. n
.. 'vimgrep '
.. '/\\t'
.. typename
.. '\\(\\t\\|$\\)/j '
.. fnames
)
qflist = vim9.fn.getqflist()
if vim9.fn.len(qflist) > 0 or vim9.fn.match(typename, '::') < 0 then
break
end
-- # No match for "struct:context::name", remove "context::" and try again.
typename = vim9.fn.substitute(typename, ':[^:]*::', ':', '')
end
if vim9.bool(vim9.prefix['Bang'](all)) then
-- # Store the result to be able to use it again later.
grepCache[vim9.index_expr(typename)] = qflist
end
end
-- # Skip over [...] items
local idx = 0
local target = ''
while 1 do
if idx >= vim9.fn.len(items) then
target = ''
break
end
if vim9.index(vim9.index(items, idx), 0) ~= '[' then
target = vim9.index(items, idx)
break
end
idx = idx + 1
end
-- # Put matching members in matches[].
local matches = {}
for _, l in vim9.iter(qflist) do
local memb = vim9.fn.matchstr(vim9.index(l, 'text'), '[^\\t]*')
if vim9.ops.RegexpMatches(memb, '^' .. target) then
-- # Skip matches local to another file.
if
vim9.fn.match(vim9.index(l, 'text'), '\tfile:') < 0
or vim9.fn.bufnr('%')
== vim9.fn.bufnr(vim9.fn.matchstr(vim9.index(l, 'text'), '\\t\\zs[^\\t]*'))
then
local item =
vim9.convert.decl_dict({ ['match'] = memb, ['tagline'] = vim9.index(l, 'text') })
-- # Add the kind of item.
local s =
vim9.fn.matchstr(vim9.index(l, 'text'), '\\t\\(kind:\\)\\=\\zs\\S\\ze\\(\\t\\|$\\)')
if s ~= '' then
item[vim9.index_expr('kind')] = s
if s == 'f' then
item[vim9.index_expr('match')] = memb .. '('
end
end
vim9.fn.add(matches, item)
end
end
end
if vim9.fn.len(matches) > 0 then
-- # Skip over next [...] items
idx = idx + 1
while 1 do
if idx >= vim9.fn.len(items) then
return matches
end
if vim9.index(vim9.index(items, idx), 0) ~= '[' then
break
end
idx = idx + 1
end
-- # More items following. For each of the possible members find the
-- # matching following members.
return SearchMembers(matches, vim9.slice(items, idx, nil), all)
end
-- # Failed to find anything.
return {}
end
SearchMembers = function(matches, items, all)
all = vim9.bool(all)
-- # For matching members, find matches for following items.
-- # When "all" is true find all, otherwise just return 1 if there is any member.
local res = {}
for _, i in vim9.iter(vim9.fn.range(vim9.fn.len(matches))) do
local typename = ''
local line = ''
if vim9.bool(vim9.fn.has_key(vim9.index(matches, i), 'dict')) then
if vim9.bool(vim9.fn.has_key(vim9.index(vim9.index(matches, i), 'dict'), 'typename')) then
typename = vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'typename')
elseif vim9.bool(vim9.fn.has_key(vim9.index(vim9.index(matches, i), 'dict'), 'typeref')) then
typename = vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'typeref')
end
line = '\t' .. vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'cmd')
else
line = vim9.index(vim9.index(matches, i), 'tagline')
local eb = vim9.fn.matchend(line, '\\ttypename:')
local e = vim9.fn.charidx(line, eb)
if e < 0 then
eb = vim9.fn.matchend(line, '\\ttyperef:')
e = vim9.fn.charidx(line, eb)
end
if e > 0 then
-- # Use typename field
typename = vim9.fn.matchstr(line, '[^\\t]*', eb)
end
end
if typename ~= '' then
res = vim9.fn.extend(res, StructMembers(typename, items, all))
else
-- # Use the search command (the declaration itself).
local sb = vim9.fn.match(line, '\\t\\zs/^')
local s = vim9.fn.charidx(line, sb)
if s > 0 then
local e = vim9.fn.charidx(
line,
vim9.fn.match(line, '\\<' .. vim9.index(vim9.index(matches, i), 'match') .. '\\>', sb)
)
if e > 0 then
res =
vim9.fn.extend(res, Nextitem(vim9.slice(line, s, vim9.ops.Minus(e, 1)), items, 0, all))
end
end
end
if vim9.bool(vim9.ops.And(vim9.prefix['Bang'](all), vim9.fn.len(res) > 0)) then
break
end
end
return res
end
-- #}}}1
-- # vim: noet sw=2 sts=2
return M

View File

@@ -1,682 +1,8 @@
" Vim completion script
" Language: C
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2020 Nov 14
let s:cpo_save = &cpo
set cpo&vim
" This function is used for the 'omnifunc' option.
func ccomplete#Complete(findstart, base)
if a:findstart
" Locate the start of the item, including ".", "->" and "[...]".
let line = getline('.')
let start = col('.') - 1
let lastword = -1
while start > 0
if line[start - 1] =~ '\w'
let start -= 1
elseif line[start - 1] =~ '\.'
if lastword == -1
let lastword = start
endif
let start -= 1
elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
if lastword == -1
let lastword = start
endif
let start -= 2
elseif line[start - 1] == ']'
" Skip over [...].
let n = 0
let start -= 1
while start > 0
let start -= 1
if line[start] == '['
if n == 0
break
endif
let n -= 1
elseif line[start] == ']' " nested []
let n += 1
endif
endwhile
else
break
endif
endwhile
" Return the column of the last word, which is going to be changed.
" Remember the text that comes before it in s:prepended.
if lastword == -1
let s:prepended = ''
return start
endif
let s:prepended = strpart(line, start, lastword - start)
return lastword
endif
" Return list of matches.
let base = s:prepended . a:base
" Don't do anything for an empty base, would result in all the tags in the
" tags file.
if base == ''
return []
endif
" init cache for vimgrep to empty
let s:grepCache = {}
" Split item in words, keep empty word after "." or "->".
" "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
" We can't use split, because we need to skip nested [...].
" "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> ['aa', 'bb', '[...]'], etc.
let items = []
let s = 0
let arrays = 0
while 1
let e = match(base, '\.\|->\|\[', s)
if e < 0
if s == 0 || base[s - 1] != ']'
call add(items, strpart(base, s))
endif
break
endif
if s == 0 || base[s - 1] != ']'
call add(items, strpart(base, s, e - s))
endif
if base[e] == '.'
let s = e + 1 " skip over '.'
elseif base[e] == '-'
let s = e + 2 " skip over '->'
else
" Skip over [...].
let n = 0
let s = e
let e += 1
while e < len(base)
if base[e] == ']'
if n == 0
break
endif
let n -= 1
elseif base[e] == '[' " nested [...]
let n += 1
endif
let e += 1
endwhile
let e += 1
call add(items, strpart(base, s, e - s))
let arrays += 1
let s = e
endif
endwhile
if complete_check()
" return v:none
return []
endif
" Find the variable items[0].
" 1. in current function (like with "gd")
" 2. in tags file(s) (like with ":tag")
" 3. in current file (like with "gD")
let res = []
if searchdecl(items[0], 0, 1) == 0
" Found, now figure out the type.
" TODO: join previous line if it makes sense
let line = getline('.')
let col = col('.')
if stridx(strpart(line, 0, col), ';') != -1
" Handle multiple declarations on the same line.
let col2 = col - 1
while line[col2] != ';'
if complete_check()
return res
endif
let col2 -= 1
endwhile
let line = strpart(line, col2 + 1)
let col -= col2
endif
if stridx(strpart(line, 0, col), ',') != -1
" Handle multiple declarations on the same line in a function
" declaration.
let col2 = col - 1
while line[col2] != ','
if complete_check()
return res
endif
let col2 -= 1
endwhile
if strpart(line, col2 + 1, col - col2 - 1) =~ ' *[^ ][^ ]* *[^ ]'
let line = strpart(line, col2 + 1)
let col -= col2
endif
endif
if len(items) == 1
" Completing one word and it's a local variable: May add '[', '.' or
" '->'.
let match = items[0]
let kind = 'v'
if match(line, '\<' . match . '\s*\[') > 0
let match .= '['
else
let res = s:Nextitem(strpart(line, 0, col), [''], 0, 1)
if len(res) > 0
" There are members, thus add "." or "->".
if match(line, '\*[ \t(]*' . match . '\>') > 0
let match .= '->'
else
let match .= '.'
endif
endif
endif
let res = [{'match': match, 'tagline' : '', 'kind' : kind, 'info' : line}]
elseif len(items) == arrays + 1
" Completing one word and it's a local array variable: build tagline
" from declaration line
let match = items[0]
let kind = 'v'
let tagline = "\t/^" . line . '$/'
let res = [{'match': match, 'tagline' : tagline, 'kind' : kind, 'info' : line}]
else
" Completing "var.", "var.something", etc.
let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
endif
endif
if len(items) == 1 || len(items) == arrays + 1
" Only one part, no "." or "->": complete from tags file.
if len(items) == 1
let tags = taglist('^' . base)
else
let tags = taglist('^' . items[0] . '$')
endif
" Remove members, these can't appear without something in front.
call filter(tags, 'has_key(v:val, "kind") ? v:val["kind"] != "m" : 1')
" Remove static matches in other files.
call filter(tags, '!has_key(v:val, "static") || !v:val["static"] || bufnr("%") == bufnr(v:val["filename"])')
call extend(res, map(tags, 's:Tag2item(v:val)'))
endif
if len(res) == 0
" Find the variable in the tags file(s)
let diclist = taglist('^' . items[0] . '$')
" Remove members, these can't appear without something in front.
call filter(diclist, 'has_key(v:val, "kind") ? v:val["kind"] != "m" : 1')
let res = []
for i in range(len(diclist))
if complete_check()
return res
endif
" New ctags has the "typeref" field. Patched version has "typename".
if has_key(diclist[i], 'typename')
call extend(res, s:StructMembers(diclist[i]['typename'], items[1:], 1))
elseif has_key(diclist[i], 'typeref')
call extend(res, s:StructMembers(diclist[i]['typeref'], items[1:], 1))
endif
" For a variable use the command, which must be a search pattern that
" shows the declaration of the variable.
if diclist[i]['kind'] == 'v'
let line = diclist[i]['cmd']
if line[0] == '/' && line[1] == '^'
let col = match(line, '\<' . items[0] . '\>')
call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0, 1))
endif
endif
endfor
endif
if len(res) == 0 && searchdecl(items[0], 1) == 0
" Found, now figure out the type.
" TODO: join previous line if it makes sense
let line = getline('.')
let col = col('.')
let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
endif
" If the last item(s) are [...] they need to be added to the matches.
let last = len(items) - 1
let brackets = ''
while last >= 0
if complete_check()
return res
endif
if items[last][0] != '['
break
endif
let brackets = items[last] . brackets
let last -= 1
endwhile
return map(res, 's:Tagline2item(v:val, brackets)')
endfunc
func s:GetAddition(line, match, memarg, bracket)
" Guess if the item is an array.
if a:bracket && match(a:line, a:match . '\s*\[') > 0
return '['
endif
" Check if the item has members.
if len(s:SearchMembers(a:memarg, [''], 0)) > 0
" If there is a '*' before the name use "->".
if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0
return '->'
else
return '.'
endif
endif
return ''
endfunc
" Turn the tag info "val" into an item for completion.
" "val" is is an item in the list returned by taglist().
" If it is a variable we may add "." or "->". Don't do it for other types,
" such as a typedef, by not including the info that s:GetAddition() uses.
func s:Tag2item(val)
let res = {'match': a:val['name']}
let res['extra'] = s:Tagcmd2extra(a:val['cmd'], a:val['name'], a:val['filename'])
let s = s:Dict2info(a:val)
if s != ''
let res['info'] = s
endif
let res['tagline'] = ''
if has_key(a:val, "kind")
let kind = a:val['kind']
let res['kind'] = kind
if kind == 'v'
let res['tagline'] = "\t" . a:val['cmd']
let res['dict'] = a:val
elseif kind == 'f'
let res['match'] = a:val['name'] . '('
endif
endif
return res
endfunc
" Use all the items in dictionary for the "info" entry.
func s:Dict2info(dict)
let info = ''
for k in sort(keys(a:dict))
if complete_check()
return info
endif
let info .= k . repeat(' ', 10 - len(k))
if k == 'cmd'
let info .= substitute(matchstr(a:dict['cmd'], '/^\s*\zs.*\ze$/'), '\\\(.\)', '\1', 'g')
else
let info .= a:dict[k]
endif
let info .= "\n"
endfor
return info
endfunc
" Parse a tag line and return a dictionary with items like taglist()
func s:ParseTagline(line)
let l = split(a:line, "\t")
let d = {}
if len(l) >= 3
let d['name'] = l[0]
let d['filename'] = l[1]
let d['cmd'] = l[2]
let n = 2
if l[2] =~ '^/'
" Find end of cmd, it may contain Tabs.
while n < len(l) && l[n] !~ '/;"$'
let n += 1
let d['cmd'] .= " " . l[n]
endwhile
endif
for i in range(n + 1, len(l) - 1)
if complete_check()
return d
endif
if l[i] == 'file:'
let d['static'] = 1
elseif l[i] !~ ':'
let d['kind'] = l[i]
else
let d[matchstr(l[i], '[^:]*')] = matchstr(l[i], ':\zs.*')
endif
endfor
endif
return d
endfunc
" Turn a match item "val" into an item for completion.
" "val['match']" is the matching item.
" "val['tagline']" is the tagline in which the last part was found.
func s:Tagline2item(val, brackets)
let line = a:val['tagline']
let add = s:GetAddition(line, a:val['match'], [a:val], a:brackets == '')
let res = {'word': a:val['match'] . a:brackets . add }
if has_key(a:val, 'info')
" Use info from Tag2item().
let res['info'] = a:val['info']
else
" Parse the tag line and add each part to the "info" entry.
let s = s:Dict2info(s:ParseTagline(line))
if s != ''
let res['info'] = s
endif
endif
if has_key(a:val, 'kind')
let res['kind'] = a:val['kind']
elseif add == '('
let res['kind'] = 'f'
else
let s = matchstr(line, '\t\(kind:\)\=\zs\S\ze\(\t\|$\)')
if s != ''
let res['kind'] = s
endif
endif
if has_key(a:val, 'extra')
let res['menu'] = a:val['extra']
return res
endif
" Isolate the command after the tag and filename.
let s = matchstr(line, '[^\t]*\t[^\t]*\t\zs\(/^.*$/\|[^\t]*\)\ze\(;"\t\|\t\|$\)')
if s != ''
let res['menu'] = s:Tagcmd2extra(s, a:val['match'], matchstr(line, '[^\t]*\t\zs[^\t]*\ze\t'))
endif
return res
endfunc
" Turn a command from a tag line to something that is useful in the menu
func s:Tagcmd2extra(cmd, name, fname)
if a:cmd =~ '^/^'
" The command is a search command, useful to see what it is.
let x = matchstr(a:cmd, '^/^\s*\zs.*\ze$/')
let x = substitute(x, '\<' . a:name . '\>', '@@', '')
let x = substitute(x, '\\\(.\)', '\1', 'g')
let x = x . ' - ' . a:fname
elseif a:cmd =~ '^\d*$'
" The command is a line number, the file name is more useful.
let x = a:fname . ' - ' . a:cmd
else
" Not recognized, use command and file name.
let x = a:cmd . ' - ' . a:fname
endif
return x
endfunc
" Find composing type in "lead" and match items[0] with it.
" Repeat this recursively for items[1], if it's there.
" When resolving typedefs "depth" is used to avoid infinite recursion.
" Return the list of matches.
func s:Nextitem(lead, items, depth, all)
" Use the text up to the variable name and split it in tokens.
let tokens = split(a:lead, '\s\+\|\<')
" Try to recognize the type of the variable. This is rough guessing...
let res = []
for tidx in range(len(tokens))
if complete_check()
return res
endif
" Skip tokens starting with a non-ID character.
if tokens[tidx] !~ '^\h'
continue
endif
" Recognize "struct foobar" and "union foobar".
" Also do "class foobar" when it's C++ after all (doesn't work very well
" though).
if (tokens[tidx] == 'struct' || tokens[tidx] == 'union' || tokens[tidx] == 'class') && tidx + 1 < len(tokens)
let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items, a:all)
break
endif
" TODO: add more reserved words
if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
continue
endif
" Use the tags file to find out if this is a typedef.
let diclist = taglist('^' . tokens[tidx] . '$')
for tagidx in range(len(diclist))
if complete_check()
return res
endif
let item = diclist[tagidx]
" New ctags has the "typeref" field. Patched version has "typename".
if has_key(item, 'typeref')
call extend(res, s:StructMembers(item['typeref'], a:items, a:all))
continue
endif
if has_key(item, 'typename')
call extend(res, s:StructMembers(item['typename'], a:items, a:all))
continue
endif
" Only handle typedefs here.
if item['kind'] != 't'
continue
endif
" Skip matches local to another file.
if has_key(item, 'static') && item['static'] && bufnr('%') != bufnr(item['filename'])
continue
endif
" For old ctags we recognize "typedef struct aaa" and
" "typedef union bbb" in the tags file command.
let cmd = item['cmd']
let ei = matchend(cmd, 'typedef\s\+')
if ei > 1
let cmdtokens = split(strpart(cmd, ei), '\s\+\|\<')
if len(cmdtokens) > 1
if cmdtokens[0] == 'struct' || cmdtokens[0] == 'union' || cmdtokens[0] == 'class'
let name = ''
" Use the first identifier after the "struct" or "union"
for ti in range(len(cmdtokens) - 1)
if cmdtokens[ti] =~ '^\w'
let name = cmdtokens[ti]
break
endif
endfor
if name != ''
call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items, a:all))
endif
elseif a:depth < 10
" Could be "typedef other_T some_T".
call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1, a:all))
endif
endif
endif
endfor
if len(res) > 0
break
endif
endfor
return res
endfunc
" Search for members of structure "typename" in tags files.
" Return a list with resulting matches.
" Each match is a dictionary with "match" and "tagline" entries.
" When "all" is non-zero find all, otherwise just return 1 if there is any
" member.
func s:StructMembers(typename, items, all)
" Todo: What about local structures?
let fnames = join(map(tagfiles(), 'escape(v:val, " \\#%")'))
if fnames == ''
return []
endif
let typename = a:typename
let qflist = []
let cached = 0
if a:all == 0
let n = '1' " stop at first found match
if has_key(s:grepCache, a:typename)
let qflist = s:grepCache[a:typename]
let cached = 1
endif
else
let n = ''
endif
if !cached
while 1
if complete_check()
return []
endif
exe 'silent! keepj noautocmd ' . n . 'vimgrep /\t' . typename . '\(\t\|$\)/j ' . fnames
let qflist = getqflist()
if len(qflist) > 0 || match(typename, "::") < 0
break
endif
" No match for "struct:context::name", remove "context::" and try again.
let typename = substitute(typename, ':[^:]*::', ':', '')
endwhile
if a:all == 0
" Store the result to be able to use it again later.
let s:grepCache[a:typename] = qflist
endif
endif
" Skip over [...] items
let idx = 0
while 1
if complete_check()
return []
endif
if idx >= len(a:items)
let target = '' " No further items, matching all members
break
endif
if a:items[idx][0] != '['
let target = a:items[idx]
break
endif
let idx += 1
endwhile
" Put matching members in matches[].
let matches = []
for l in qflist
let memb = matchstr(l['text'], '[^\t]*')
if memb =~ '^' . target
" Skip matches local to another file.
if match(l['text'], "\tfile:") < 0 || bufnr('%') == bufnr(matchstr(l['text'], '\t\zs[^\t]*'))
let item = {'match': memb, 'tagline': l['text']}
" Add the kind of item.
let s = matchstr(l['text'], '\t\(kind:\)\=\zs\S\ze\(\t\|$\)')
if s != ''
let item['kind'] = s
if s == 'f'
let item['match'] = memb . '('
endif
endif
call add(matches, item)
endif
endif
endfor
if len(matches) > 0
" Skip over next [...] items
let idx += 1
while 1
if complete_check()
return matches
endif
if idx >= len(a:items)
return matches " No further items, return the result.
endif
if a:items[idx][0] != '['
break
endif
let idx += 1
endwhile
" More items following. For each of the possible members find the
" matching following members.
return s:SearchMembers(matches, a:items[idx :], a:all)
endif
" Failed to find anything.
return []
endfunc
" For matching members, find matches for following items.
" When "all" is non-zero find all, otherwise just return 1 if there is any
" member.
func s:SearchMembers(matches, items, all)
let res = []
for i in range(len(a:matches))
if complete_check()
return res
endif
let typename = ''
if has_key(a:matches[i], 'dict')
if has_key(a:matches[i].dict, 'typename')
let typename = a:matches[i].dict['typename']
elseif has_key(a:matches[i].dict, 'typeref')
let typename = a:matches[i].dict['typeref']
endif
let line = "\t" . a:matches[i].dict['cmd']
else
let line = a:matches[i]['tagline']
let e = matchend(line, '\ttypename:')
if e < 0
let e = matchend(line, '\ttyperef:')
endif
if e > 0
" Use typename field
let typename = matchstr(line, '[^\t]*', e)
endif
endif
if typename != ''
call extend(res, s:StructMembers(typename, a:items, a:all))
else
" Use the search command (the declaration itself).
let s = match(line, '\t\zs/^')
if s > 0
let e = match(line, '\<' . a:matches[i]['match'] . '\>', s)
if e > 0
call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0, a:all))
endif
endif
endif
if a:all == 0 && len(res) > 0
break
endif
endfor
return res
endfunc
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: noet sw=2 sts=2
" Generated vim file by vim9jit. Please do not edit
let s:path = expand("<script>")
let s:lua_path = fnamemodify(s:path, ":r") . ".lua"
let s:nvim_module = luaeval('require("_vim9script").autoload(_A)', s:lua_path)
function! ccomplete#Complete(findstart, abase) abort
return s:nvim_module.Complete(a:findstart, a:abase)
endfunction

View File

@@ -2,21 +2,6 @@
" Maintainer: Gregory Anders
" Last Change: 2024-09-03
" Based on: https://github.com/hashivim/vim-terraform
" License: ISC
"
" Copyright (c) 2014-2016 Mark Cornick <mark@markcornick.com>
"
" Permission to use, copy, modify, and/or distribute this software for any purpose
" with or without fee is hereby granted, provided that the above copyright notice
" and this permission notice appear in all copies.
"
" THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
" FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
" OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
" THIS SOFTWARE.
function! hcl#indentexpr(lnum)
" Beginning of the file should have no indent

View File

@@ -1,192 +0,0 @@
" HTML folding script, :h ft-html-plugin
" Latest Change: 2025 May 10
" Original Author: Aliaksei Budavei <0x000c70@gmail.com>
function! htmlfold#MapBalancedTags() abort
" Describe only _a capturable-name prefix_ for start and end patterns of
" a tag so that start tags with attributes spanning across lines can also be
" matched with a single call of "getline()".
let tag = '\m\c</\=\([0-9A-Za-z-]\+\)'
let names = []
let pairs = []
let ends = []
let pos = getpos('.')
try
call cursor(1, 1)
let [lnum, cnum] = searchpos(tag, 'cnW')
" Pair up nearest non-inlined tags in scope.
while lnum > 0
let name_attr = synIDattr(synID(lnum, cnum, 0), 'name')
if name_attr ==# 'htmlTag' || name_attr ==# 'htmlScriptTag'
let name = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
if !empty(name)
call insert(names, tolower(name), 0)
call insert(pairs, [lnum, -1], 0)
endif
elseif name_attr ==# 'htmlEndTag'
let name = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
if !empty(name)
let idx = index(names, tolower(name))
if idx >= 0
" Dismiss inlined balanced tags and opened-only tags.
if pairs[idx][0] != lnum
let pairs[idx][1] = lnum
call add(ends, lnum)
endif
" Claim a pair.
let names[: idx] = repeat([''], (idx + 1))
endif
endif
endif
" Advance the cursor, at "<", past "</a", "<a>", etc.
call cursor(lnum, (cnum + 3))
let [lnum, cnum] = searchpos(tag, 'cnW')
endwhile
finally
call setpos('.', pos)
endtry
if empty(ends)
return {}
endif
let folds = {}
let pending_end = ends[0]
let level = 0
while !empty(pairs)
let [start, end] = remove(pairs, -1)
if end < 0
continue
endif
if start >= pending_end
" Mark a sibling tag.
call remove(ends, 0)
while start >= ends[0]
" Mark a parent tag.
call remove(ends, 0)
let level -= 1
endwhile
let pending_end = ends[0]
else
" Mark a child tag.
let level += 1
endif
" Flatten the innermost inlined folds.
let folds[start] = get(folds, start, ('>' . level))
let folds[end] = get(folds, end, ('<' . level))
endwhile
return folds
endfunction
" See ":help vim9-mix".
if !has("vim9script")
finish
endif
def! g:htmlfold#MapBalancedTags(): dict<string>
# Describe only _a capturable-name prefix_ for start and end patterns of
# a tag so that start tags with attributes spanning across lines can also be
# matched with a single call of "getline()".
const tag: string = '\m\c</\=\([0-9A-Za-z-]\+\)'
var names: list<string> = []
var pairs: list<list<number>> = []
var ends: list<number> = []
const pos: list<number> = getpos('.')
try
cursor(1, 1)
var [lnum: number, cnum: number] = searchpos(tag, 'cnW')
# Pair up nearest non-inlined tags in scope.
while lnum > 0
const name_attr: string = synIDattr(synID(lnum, cnum, 0), 'name')
if name_attr ==# 'htmlTag' || name_attr ==# 'htmlScriptTag'
const name: string = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
if !empty(name)
insert(names, tolower(name), 0)
insert(pairs, [lnum, -1], 0)
endif
elseif name_attr ==# 'htmlEndTag'
const name: string = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
if !empty(name)
const idx: number = index(names, tolower(name))
if idx >= 0
# Dismiss inlined balanced tags and opened-only tags.
if pairs[idx][0] != lnum
pairs[idx][1] = lnum
add(ends, lnum)
endif
# Claim a pair.
names[: idx] = repeat([''], (idx + 1))
endif
endif
endif
# Advance the cursor, at "<", past "</a", "<a>", etc.
cursor(lnum, (cnum + 3))
[lnum, cnum] = searchpos(tag, 'cnW')
endwhile
finally
setpos('.', pos)
endtry
if empty(ends)
return {}
endif
var folds: dict<string> = {}
var pending_end: number = ends[0]
var level: number = 0
while !empty(pairs)
const [start: number, end: number] = remove(pairs, -1)
if end < 0
continue
endif
if start >= pending_end
# Mark a sibling tag.
remove(ends, 0)
while start >= ends[0]
# Mark a parent tag.
remove(ends, 0)
level -= 1
endwhile
pending_end = ends[0]
else
# Mark a child tag.
level += 1
endif
# Flatten the innermost inlined folds.
folds[start] = get(folds, start, ('>' .. level))
folds[end] = get(folds, end, ('<' .. level))
endwhile
return folds
enddef
" vim: fdm=syntax sw=2 ts=8 noet

View File

@@ -85,10 +85,10 @@ function! s:set_wayland() abort
endfunction
function! s:set_wayclip() abort
let s:copy['+'] = ['waycopy']
let s:paste['+'] = ['waypaste']
let s:copy['*'] = ['waycopy', '-p']
let s:paste['*'] = ['waypaste', '-p']
let s:copy['+'] = ['waycopy', '-t', 'text/plain']
let s:paste['+'] = ['waypaste', '-t', 'text/plain']
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
return 'wayclip'
endfunction
@@ -268,11 +268,13 @@ function! provider#clipboard#Executable() abort
endfunction
function! s:clipboard.get(reg) abort
if s:selections[a:reg].owner > 0
if type(s:paste[a:reg]) == v:t_func
return s:paste[a:reg]()
elseif s:selections[a:reg].owner > 0
return s:selections[a:reg].data
end
let clipboard_data = type(s:paste[a:reg]) == v:t_func ? s:paste[a:reg]() : s:try_cmd(s:paste[a:reg])
let clipboard_data = s:try_cmd(s:paste[a:reg])
if match(&clipboard, '\v(unnamed|unnamedplus)') >= 0
\ && type(clipboard_data) == v:t_list
\ && get(s:selections[a:reg].data, 0, []) ==# clipboard_data
@@ -292,12 +294,13 @@ function! s:clipboard.set(lines, regtype, reg) abort
return 0
end
if s:cache_enabled == 0 || type(s:copy[a:reg]) == v:t_func
if type(s:copy[a:reg]) == v:t_func
call s:copy[a:reg](a:lines, a:regtype)
else
return 0
end
if s:cache_enabled == 0
call s:try_cmd(s:copy[a:reg], a:lines)
endif
"Cache it anyway we can compare it later to get regtype of the yank
let s:selections[a:reg] = copy(s:selection)
let s:selections[a:reg].data = [a:lines, a:regtype]

View File

@@ -1,8 +1,5 @@
" Author: Stephen Sugden <stephen@stephensugden.com>
" Last Modified: 2023-09-11
" Last Change:
" 2025 Mar 31 by Vim project (rename s:RustfmtConfigOptions())
" 2025 Jul 14 by Vim project (don't parse rustfmt version automatically #17745)
"
" Adapted from https://github.com/fatih/vim-go
" For bugs, patches and license go to https://github.com/rust-lang/rust.vim
@@ -24,12 +21,6 @@ if !exists("g:rustfmt_fail_silently")
endif
function! rustfmt#DetectVersion()
let s:rustfmt_version = "0"
let s:rustfmt_help = ""
let s:rustfmt_unstable_features = ""
if !get(g:, 'rustfmt_detect_version', 0)
return s:rustfmt_version
endif
" Save rustfmt '--help' for feature inspection
silent let s:rustfmt_help = system(g:rustfmt_command . " --help")
let s:rustfmt_unstable_features = s:rustfmt_help =~# "--unstable-features"
@@ -38,7 +29,9 @@ function! rustfmt#DetectVersion()
silent let l:rustfmt_version_full = system(g:rustfmt_command . " --version")
let l:rustfmt_version_list = matchlist(l:rustfmt_version_full,
\ '\vrustfmt ([0-9]+[.][0-9]+[.][0-9]+)')
if len(l:rustfmt_version_list) >= 3
if len(l:rustfmt_version_list) < 3
let s:rustfmt_version = "0"
else
let s:rustfmt_version = l:rustfmt_version_list[1]
endif
return s:rustfmt_version
@@ -68,13 +61,7 @@ function! s:RustfmtWriteMode()
endif
endfunction
function! rustfmt#RustfmtConfigOptions()
let default = '--edition 2018'
if !get(g:, 'rustfmt_find_toml', 0)
return default
endif
function! s:RustfmtConfigOptions()
let l:rustfmt_toml = findfile('rustfmt.toml', expand('%:p:h') . ';')
if l:rustfmt_toml !=# ''
return '--config-path '.shellescape(fnamemodify(l:rustfmt_toml, ":p"))
@@ -86,7 +73,7 @@ function! rustfmt#RustfmtConfigOptions()
endif
" Default to edition 2018 in case no rustfmt.toml was found.
return default
return '--edition 2018'
endfunction
function! s:RustfmtCommandRange(filename, line1, line2)
@@ -97,7 +84,7 @@ function! s:RustfmtCommandRange(filename, line1, line2)
let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]}
let l:write_mode = s:RustfmtWriteMode()
let l:rustfmt_config = rustfmt#RustfmtConfigOptions()
let l:rustfmt_config = s:RustfmtConfigOptions()
" FIXME: When --file-lines gets to be stable, add version range checking
" accordingly.
@@ -112,7 +99,7 @@ endfunction
function! s:RustfmtCommand()
let write_mode = g:rustfmt_emit_files ? '--emit=stdout' : '--write-mode=display'
let config = rustfmt#RustfmtConfigOptions()
let config = s:RustfmtConfigOptions()
return join([g:rustfmt_command, write_mode, config, g:rustfmt_options])
endfunction

View File

@@ -12,11 +12,6 @@
" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
" 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
" 2025 Mar 02 by Vim Project: escape the filename before using :read
" 2025 Mar 02 by Vim Project: determine the compression using readblob()
" instead of shelling out to file(1)
" 2025 Apr 16 by Vim Project: decouple from netrw by adding s:WinPath()
" 2025 May 19 by Vim Project: restore working directory after read/write
" 2025 Jul 13 by Vim Project: warn with path traversal attacks
"
" Contains many ideas from Michael Toren's <tar.vim>
"
@@ -35,9 +30,9 @@ if &cp || exists("g:loaded_tar")
finish
endif
let g:loaded_tar= "v32b"
if !has('nvim-0.12') && v:version < 900
if v:version < 702
echohl WarningMsg
echo "***warning*** this version of tar needs vim 9.0"
echo "***warning*** this version of tar needs vim 7.2"
echohl Normal
finish
endif
@@ -47,10 +42,10 @@ set cpo&vim
" ---------------------------------------------------------------------
" Default Settings: {{{1
if !exists("g:tar_browseoptions")
let g:tar_browseoptions= "tf"
let g:tar_browseoptions= "Ptf"
endif
if !exists("g:tar_readoptions")
let g:tar_readoptions= "pxf"
let g:tar_readoptions= "pPxf"
endif
if !exists("g:tar_cmd")
let g:tar_cmd= "tar"
@@ -59,7 +54,6 @@ if !exists("g:tar_writeoptions")
let g:tar_writeoptions= "uf"
endif
if !exists("g:tar_delfile")
" Note: not supported on BSD
let g:tar_delfile="--delete -f"
endif
if !exists("g:netrw_cygwin")
@@ -108,26 +102,10 @@ if !exists("g:tar_shq")
endif
endif
let g:tar_secure=' -- '
let g:tar_leading_pat='^\%([.]\{,2\}/\)\+'
" ----------------
" Functions: {{{1
" ----------------
" ---------------------------------------------------------------------
" s:Msg: {{{2
fun! s:Msg(func, severity, msg)
redraw!
if a:severity =~? 'error'
echohl Error
else
echohl WarningMsg
endif
echo $"***{a:severity}*** ({a:func}) {a:msg}"
echohl None
endfunc
" ---------------------------------------------------------------------
" tar#Browse: {{{2
fun! tar#Browse(tarfile)
@@ -136,14 +114,16 @@ fun! tar#Browse(tarfile)
" sanity checks
if !executable(g:tar_cmd)
call s:Msg('tar#Browse', 'error', $"{g:tar_cmd} not available on your system")
redraw!
echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
let &report= repkeep
return
endif
if !filereadable(a:tarfile)
if a:tarfile !~# '^\a\+://'
" if it's an url, don't complain, let url-handlers such as vim do its thing
call s:Msg('tar#Browse', 'error', $"File not readable<{a:tarfile}>")
redraw!
echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
endif
let &report= repkeep
return
@@ -164,7 +144,7 @@ fun! tar#Browse(tarfile)
let lastline= line("$")
call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
call setline(lastline+3,'" Select a file with cursor and press ENTER, "x" to extract a file')
call setline(lastline+3,'" Select a file with cursor and press ENTER')
keepj $put =''
keepj sil! 0d
keepj $
@@ -181,19 +161,23 @@ fun! tar#Browse(tarfile)
elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' ||
\ tarfile =~# '\.\(tzst\)$' || tarfile =~# '\.\(tlz4\)$'
let header= s:Header(tarfile)
if has("unix") && executable("file")
let filekind= system("file ".shellescape(tarfile,1))
else
let filekind= ""
endif
if header =~? 'bzip2'
if filekind =~ "bzip2"
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif header =~? 'bzip3'
elseif filekind =~ "bzip3"
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif header =~? 'xz'
elseif filekind =~ "XZ"
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif header =~? 'zstd'
elseif filekind =~ "Zstandard"
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif header =~? 'lz4'
elseif filekind =~ "LZ4"
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif header =~? 'gzip'
else
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
endif
@@ -219,18 +203,28 @@ fun! tar#Browse(tarfile)
exe "sil! r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1)
endif
if v:shell_error != 0
call s:Msg('tar#Browse', 'warning', $"please check your g:tar_browseoptions '<{g:tar_browseoptions}>'")
redraw!
echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
return
endif
" remove tar: Removing leading '/' from member names
" Note: the message could be localized
if search('^tar: ') > 0 || search(g:tar_leading_pat) > 0
call append(3,'" Note: Path Traversal Attack detected!')
let b:leading_slash = 1
" remove the message output
sil g/^tar: /d
endif
"
" The following should not be neccessary, since in case of errors the
" previous if statement should have caught the problem (because tar exited
" with a non-zero exit code).
" if line("$") == curlast || ( line("$") == (curlast + 1) &&
" \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' &&
" \ getline("$") =~ '\s' )
" redraw!
" echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
" keepj sil! %d
" let eikeep= &ei
" set ei=BufReadCmd,FileReadCmd
" exe "r ".fnameescape(a:tarfile)
" let &ei= eikeep
" keepj sil! 1d
" call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
" return
" endif
" set up maps supported for tar
setlocal noma nomod ro
@@ -249,7 +243,12 @@ fun! s:TarBrowseSelect()
let repkeep= &report
set report=10
let fname= getline(".")
let ls= get(b:, 'leading_slash', 0)
if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
redraw!
echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
return
endif
" sanity check
if fname =~ '^"'
@@ -271,8 +270,7 @@ fun! s:TarBrowseSelect()
wincmd _
endif
let s:tblfile_{winnr()}= curfile
let b:leading_slash= ls
call tar#Read("tarfile:".tarfile.'::'.fname)
call tar#Read("tarfile:".tarfile.'::'.fname,1)
filetype detect
set nomod
exe 'com! -buffer -nargs=? -complete=file TarDiff :call tar#Diff(<q-args>,"'.fnameescape(fname).'")'
@@ -282,18 +280,26 @@ endfun
" ---------------------------------------------------------------------
" tar#Read: {{{2
fun! tar#Read(fname)
fun! tar#Read(fname,mode)
let repkeep= &report
set report=10
let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
" be careful not to execute special crafted files
let escape_file = fname->substitute(g:tar_leading_pat, '', '')->fnameescape()
let escape_file = fname->fnameescape()
" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
if !exists("*mkdir")
redraw!
echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
let &report= repkeep
return
endif
let curdir= getcwd()
let b:curdir= curdir
let tmpdir= tempname()
let b:tmpdir= tmpdir
let b:curdir= tmpdir
let b:tmpdir= curdir
if tmpdir =~ '\.'
let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
endif
@@ -301,9 +307,10 @@ fun! tar#Read(fname)
" attempt to change to the indicated directory
try
exe "lcd ".fnameescape(tmpdir)
exe "cd ".fnameescape(tmpdir)
catch /^Vim\%((\a\+)\)\=:E344/
call s:Msg('tar#Read', 'error', "cannot lcd to temporary directory")
redraw!
echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
let &report= repkeep
return
endtry
@@ -313,7 +320,7 @@ fun! tar#Read(fname)
call s:Rmdir("_ZIPVIM_")
endif
call mkdir("_ZIPVIM_")
lcd _ZIPVIM_
cd _ZIPVIM_
if has("win32unix") && executable("cygpath")
" assuming cygwin
@@ -349,66 +356,72 @@ fun! tar#Read(fname)
endif
endif
if exists("g:tar_secure")
let tar_secure= " -- "
else
let tar_secure= " "
endif
if tarfile =~# '\.bz2$'
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\.bz3$'
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\.\(gz\)$'
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
let filekind= s:Header(tarfile)
if filekind =~? "bzip2"
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
if has("unix") && executable("file")
let filekind= system("file ".shellescape(tarfile,1))
else
let filekind= ""
endif
if filekind =~ "bzip2"
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif filekind =~ "bzip3"
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif filekind =~? "xz"
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
elseif filekind =~ "XZ"
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif filekind =~? "zstd"
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
elseif filekind =~ "Zstandard"
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif filekind =~? "gzip"
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
else
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
endif
elseif tarfile =~# '\.lrp$'
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\.lzma$'
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\.\(xz\|txz\)$'
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
elseif tarfile =~# '\.\(lz4\|tlz4\)$'
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
else
if tarfile =~ '^\s*-'
" A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
let tarfile = substitute(tarfile, '-', './-', '')
endif
exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".g:tar_secure.shellescape(fname,1).decmp
exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
exe "read ".escape_file
endif
if get(b:, 'leading_slash', 0)
sil g/^tar: /d
endif
redraw!
if v:shell_error != 0
lcd ..
cd ..
call s:Rmdir("_ZIPVIM_")
exe "lcd ".fnameescape(curdir)
call s:Msg('tar#Read', 'error', $"sorry, unable to open or extract {tarfile} with {fname}")
exe "cd ".fnameescape(curdir)
echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None
endif
if doro
@@ -417,54 +430,40 @@ fun! tar#Read(fname)
endif
let b:tarfile= a:fname
exe "file tarfile::".fnameescape(fname)
" cleanup
keepj sil! 0d
set nomod
let &report= repkeep
exe "lcd ".fnameescape(curdir)
silent exe "file tarfile::". fname->fnameescape()
endfun
" ---------------------------------------------------------------------
" tar#Write: {{{2
fun! tar#Write(fname)
let pwdkeep= getcwd()
let repkeep= &report
set report=10
" temporary buffer variable workaround because too fucking tired. but it works now
let curdir= b:curdir
let tmpdir= b:tmpdir
if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
redraw!
echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"'
return
endif
" sanity checks
if !executable(g:tar_cmd)
redraw!
let &report= repkeep
return
endif
let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
if get(b:, 'leading_slash', 0)
call s:Msg('tar#Write', 'error', $"sorry, not attempting to update {tarfile} with {fname}")
let &report= repkeep
return
endif
if !isdirectory(fnameescape(tmpdir))
call mkdir(fnameescape(tmpdir), 'p')
endif
exe $"lcd {fnameescape(tmpdir)}"
if isdirectory("_ZIPVIM_")
call s:Rmdir("_ZIPVIM_")
endif
call mkdir("_ZIPVIM_")
lcd _ZIPVIM_
let dir = fnamemodify(fname, ':p:h')
if dir !~# '_ZIPVIM_$'
call mkdir(dir)
endif
" handle compressed archives
if tarfile =~# '\.bz2'
call system("bzip2 -d -- ".shellescape(tarfile,0))
@@ -500,10 +499,10 @@ fun! tar#Write(fname)
let tarfile = substitute(tarfile,'\.lzma','','e')
let compress= "lzma -- ".shellescape(tarfile,0)
endif
" Note: no support for name.tar.tbz/.txz/.tgz/.tlz4/.tzst
if v:shell_error != 0
call s:Msg('tar#Write', 'error', $"sorry, unable to update {tarfile} with {fname}")
redraw!
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
else
if fname =~ '/'
@@ -521,22 +520,28 @@ fun! tar#Write(fname)
let tarfile = substitute(tarfile, '-', './-', '')
endif
" don't overwrite a file forcefully
exe "w ".fnameescape(fname)
if exists("g:tar_secure")
let tar_secure= " -- "
else
let tar_secure= " "
endif
exe "w! ".fnameescape(fname)
if has("win32unix") && executable("cygpath")
let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
endif
" delete old file from tarfile
" Note: BSD tar does not support --delete flag
call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0))
call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
if v:shell_error != 0
call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)} --delete not supported?")
redraw!
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
else
" update tarfile with new file
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0))
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
if v:shell_error != 0
call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)}")
redraw!
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
elseif exists("compress")
call system(compress)
if exists("tgz")
@@ -562,9 +567,9 @@ fun! tar#Write(fname)
endif
" cleanup and restore current directory
lcd ..
cd ..
call s:Rmdir("_ZIPVIM_")
exe "lcd ".fnameescape(pwdkeep)
exe "cd ".fnameescape(curdir)
setlocal nomod
let &report= repkeep
@@ -577,7 +582,6 @@ fun! tar#Diff(userfname,fname)
if a:userfname != ""
let fname= a:userfname
endif
exe "lcd ".fnameescape(b:tmpdir). '/_ZIPVIM_'
if filereadable(fname)
" sets current file (from tarball) for diff'ing
" splits window vertically
@@ -601,6 +605,12 @@ fun! tar#Extract()
set report=10
let fname= getline(".")
if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
redraw!
echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
return
endif
" sanity check
if fname =~ '^"'
let &report= repkeep
@@ -610,11 +620,11 @@ fun! tar#Extract()
let tarball = expand("%")
let tarbase = substitute(tarball,'\..*$','','')
let extractcmd= s:WinPath(g:tar_extractcmd)
let extractcmd= netrw#WinPath(g:tar_extractcmd)
if filereadable(tarbase.".tar")
call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -623,7 +633,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-z","")
call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tgz {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -632,7 +642,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-z","")
call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.gz {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -641,7 +651,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-j","")
call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tbz {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -650,7 +660,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-j","")
call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz2 {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -659,7 +669,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-j","")
call system(extractcmd." ".shellescape(tarbase).".tar.bz3 ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz3 {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz3 ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -668,7 +678,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-J","")
call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.txz {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -677,7 +687,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-J","")
call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.xz {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -686,7 +696,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","--zstd","")
call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -695,7 +705,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","--zstd","")
call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -704,7 +714,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-I lz4","")
call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tlz4 ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -713,7 +723,7 @@ fun! tar#Extract()
let extractcmd= substitute(extractcmd,"-","-I lz4","")
call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 {fname}: failed!")
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.lz4 ".fname.": failed!" | echohl NONE
else
echo "***note*** successfully extracted ".fname
endif
@@ -726,50 +736,15 @@ endfun
" ---------------------------------------------------------------------
" s:Rmdir: {{{2
fun! s:Rmdir(fname)
call delete(a:fname, 'rf')
endfun
" s:FileHeader: {{{2
fun! s:Header(fname)
let header= readblob(a:fname, 0, 6)
" Nvim: see https://github.com/neovim/neovim/pull/34968
if header[0:2] == 0z425A68 " bzip2 header
return "bzip2"
elseif header[0:2] == 0z425A33 " bzip3 header
return "bzip3"
elseif header == 0zFD377A58.5A00 " xz header
return "xz"
elseif header[0:3] == 0z28B52FFD " zstd header
return "zstd"
elseif header[0:3] == 0z04224D18 " lz4 header
return "lz4"
elseif (header[0:1] == 0z1F9D ||
\ header[0:1] == 0z1F8B ||
\ header[0:1] == 0z1F9E ||
\ header[0:1] == 0z1FA0 ||
\ header[0:1] == 0z1F1E)
return "gzip"
endif
return "unknown"
endfun
" ---------------------------------------------------------------------
" s:WinPath: {{{2
fun! s:WinPath(path)
if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && has("win32")
" remove cygdrive prefix, if present
let path = substitute(a:path, '/cygdrive/\(.\)', '\1:', '')
" remove trailing slash (Win95)
let path = substitute(path, '\(\\\|/\)$', '', 'g')
" remove escaped spaces
let path = substitute(path, '\ ', ' ', 'g')
" convert slashes to backslashes
let path = substitute(path, '/', '\', 'g')
if has("unix")
call system("/bin/rm -rf -- ".shellescape(a:fname,0))
elseif has("win32") || has("win95") || has("win64") || has("win16")
if &shell =~? "sh$"
call system("/bin/rm -rf -- ".shellescape(a:fname,0))
else
let path = a:path
call system("del /S ".shellescape(a:fname,0))
endif
endif
return path
endfun
" =====================================================================

View File

@@ -77,11 +77,49 @@ function! tutor#TutorFolds()
endif
endfunction
" Marks: {{{1
function! tutor#ApplyMarks()
hi! link tutorExpect Special
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
let b:tutor_sign_id = 1
for expct in keys(b:tutor_metadata['expect'])
let lnum = eval(expct)
call matchaddpos('tutorExpect', [lnum])
call tutor#CheckLine(lnum)
endfor
endif
endfunction
function! tutor#ApplyMarksOnChanged()
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
let lnum = line('.')
if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1
call tutor#CheckLine(lnum)
endif
endif
endfunction
function! tutor#CheckLine(line)
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
let bufn = bufnr('%')
let ctext = getline(a:line)
let signs = sign_getplaced(bufn, {'lnum': a:line})[0].signs
if !empty(signs)
call sign_unplace('', {'id': signs[0].id})
endif
if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)]
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn
else
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn
endif
let b:tutor_sign_id+=1
endif
endfunction
" Tutor Cmd: {{{1
function! s:Locale()
" Make sure l:lang exists before returning.
let l:lang = 'en_US'
if exists('v:lang') && v:lang =~ '\a\a'
let l:lang = v:lang
elseif $LC_ALL =~ '\a\a'
@@ -94,6 +132,8 @@ function! s:Locale()
endif
elseif $LANG =~ '\a\a'
let l:lang = $LANG
else
let l:lang = 'en_US'
endif
return split(l:lang, '_')
endfunction
@@ -127,21 +167,15 @@ function! s:Sort(a, b)
return retval
endfunction
" returns a list of all tutor files matching the given name
function! tutor#GlobTutorials(name, locale)
let locale = a:locale
" pack/*/start/* are not reported in &rtp
let rtp = nvim_list_runtime_paths()
\ ->map({_, v -> escape(v:lua.vim.fs.normalize(v), ',')})
\ ->join(',')
function! s:GlobTutorials(name)
" search for tutorials:
" 1. non-localized
let l:tutors = s:GlobPath(rtp, 'tutor/'.a:name.'.tutor')
let l:tutors = s:GlobPath(&rtp, 'tutor/'.a:name.'.tutor')
" 2. localized for current locale
let l:locale_tutors = s:GlobPath(rtp, 'tutor/'.locale.'/'.a:name.'.tutor')
let l:locale_tutors = s:GlobPath(&rtp, 'tutor/'.s:Locale()[0].'/'.a:name.'.tutor')
" 3. fallback to 'en'
if len(l:locale_tutors) == 0
let l:locale_tutors = s:GlobPath(rtp, 'tutor/en/'.a:name.'.tutor')
let l:locale_tutors = s:GlobPath(&rtp, 'tutor/en/'.a:name.'.tutor')
endif
call extend(l:tutors, l:locale_tutors)
return uniq(sort(l:tutors, 's:Sort'), 's:Sort')
@@ -163,7 +197,7 @@ function! tutor#TutorCmd(tutor_name)
let l:tutor_name = fnamemodify(l:tutor_name, ':r')
endif
let l:tutors = tutor#GlobTutorials(l:tutor_name, s:Locale()[0])
let l:tutors = s:GlobTutorials(l:tutor_name)
if len(l:tutors) == 0
echom "No tutorial with that name found"
@@ -186,37 +220,15 @@ function! tutor#TutorCmd(tutor_name)
call tutor#SetupVim()
exe "edit ".l:to_open
call tutor#EnableInteractive(v:true)
call tutor#ApplyTransform()
endfunction
function! tutor#TutorCmdComplete(lead,line,pos)
let l:tutors = tutor#GlobTutorials('*', s:Locale()[0])
let l:tutors = s:GlobTutorials('*')
let l:names = uniq(sort(map(l:tutors, 'fnamemodify(v:val, ":t:r")'), 's:Sort'))
return join(l:names, "\n")
endfunction
" Enables/disables interactive mode.
function! tutor#EnableInteractive(enable)
let enable = a:enable
if enable
setlocal buftype=nofile
setlocal concealcursor+=inv
setlocal conceallevel=2
lua require('nvim.tutor').apply_marks()
augroup tutor_interactive
autocmd! TextChanged,TextChangedI <buffer> lua require('nvim.tutor').apply_marks_on_changed()
augroup END
else
setlocal buftype<
setlocal concealcursor<
setlocal conceallevel<
if exists('#tutor_interactive')
autocmd! tutor_interactive * <buffer>
endif
endif
endfunction
function! tutor#ApplyTransform()
if has('win32')
sil! %s/{unix:(\(.\{-}\)),win:(\(.\{-}\))}/\2/g

View File

@@ -15,7 +15,6 @@
" 2024 Aug 18 by Vim Project: correctly handle special globbing chars
" 2024 Aug 21 by Vim Project: simplify condition to detect MS-Windows
" 2025 Mar 11 by Vim Project: handle filenames with leading '-' correctly
" 2025 Jul 12 by Vim Project: drop ../ on write to prevent path traversal attacks
" License: Vim License (see vim's :help license)
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
@@ -72,9 +71,8 @@ fun! s:Mess(group, msg)
echohl Normal
endfun
if !has('nvim-0.10') && v:version < 901
" required for defer
call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 9.1 or later")
if v:version < 702
call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 7.2 or later")
finish
endif
" sanity checks
@@ -237,7 +235,6 @@ endfun
" zip#Write: {{{2
fun! zip#Write(fname)
let dict = s:SetSaneOpts()
let need_rename = 0
defer s:RestoreOpts(dict)
" sanity checks
@@ -245,6 +242,10 @@ fun! zip#Write(fname)
call s:Mess('Error', "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program")
return
endif
if !exists("*mkdir")
call s:Mess('Error', "***error*** (zip#Write) sorry, mkdir() doesn't work on your system")
return
endif
let curdir= getcwd()
let tmpdir= tempname()
@@ -272,11 +273,6 @@ fun! zip#Write(fname)
let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
endif
if fname =~ '^[.]\{1,2}/'
call system(g:zip_zipcmd." -d ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
let fname = fname->substitute('^\([.]\{1,2}/\)\+', '', 'g')
let need_rename = 1
endif
if fname =~ '/'
let dirpath = substitute(fname,'/[^/]\+$','','e')
@@ -289,8 +285,7 @@ fun! zip#Write(fname)
let zipfile= curdir.'/'.zipfile
endif
" don't overwrite files forcefully
exe "w ".fnameescape(fname)
exe "w! ".fnameescape(fname)
if has("win32unix") && executable("cygpath")
let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e')
endif
@@ -316,9 +311,6 @@ fun! zip#Write(fname)
let &binary = binkeep
q!
unlet s:zipfile_{winnr()}
elseif need_rename
exe $"sil keepalt file {fnameescape($"zipfile://{zipfile}::{fname}")}"
call s:Mess('Warning', "***error*** (zip#Browse) Path Traversal Attack detected, dropping relative path")
endif
" cleanup and restore current directory
@@ -327,6 +319,7 @@ fun! zip#Write(fname)
call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
call delete(tmpdir, "rf")
setlocal nomod
endfun
" ---------------------------------------------------------------------
@@ -344,9 +337,6 @@ fun! zip#Extract()
if fname =~ '/$'
call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
return
elseif fname =~ '^[.]\?[.]/'
call s:Mess('Error', "***error*** (zip#Browse) Path Traversal Attack detected, not extracting!")
return
endif
if filereadable(fname)
call s:Mess('Error', "***error*** (zip#Extract) <" .. fname .."> already exists in directory, not overwriting!")
@@ -378,6 +368,7 @@ fun! zip#Extract()
else
echomsg "***note*** successfully extracted ".fname
endif
endfun
" ---------------------------------------------------------------------

View File

@@ -47,7 +47,6 @@ hi('WildMenu', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', cterm
hi('VertSplit', { link = 'Normal' })
hi('WinSeparator', { link = 'VertSplit' })
hi('WinBarNC', { link = 'WinBar' })
hi('DiffTextAdd', { link = 'DiffText' })
hi('EndOfBuffer', { link = 'NonText' })
hi('LineNrAbove', { link = 'LineNr' })
hi('LineNrBelow', { link = 'LineNr' })
@@ -62,8 +61,6 @@ hi('PmenuMatchSel', { link = 'PmenuSel' })
hi('PmenuExtra', { link = 'Pmenu' })
hi('PmenuExtraSel', { link = 'PmenuSel' })
hi('ComplMatchIns', {})
hi('ComplHint', { link = 'NonText' })
hi('ComplHintMore', { link = 'MoreMsg' })
hi('Substitute', { link = 'Search' })
hi('Whitespace', { link = 'NonText' })
hi('MsgSeparator', { link = 'StatusLine' })
@@ -136,7 +133,6 @@ hi('DiagnosticDeprecated', { sp = 'Red', strikethrough = true, cterm =
hi('DiagnosticUnnecessary', { link = 'Comment' })
hi('LspInlayHint', { link = 'NonText' })
hi('SnippetTabstop', { link = 'Visual' })
hi('SnippetTabstopActive', { link = 'SnippetTabstop' })
-- Text
hi('@markup.raw', { link = 'Comment' })

View File

@@ -1,25 +0,0 @@
" Vim compiler file
" Language: Gleam
" Maintainer: Kirill Morozov <kirill@robotix.pro>
" Based On: https://github.com/gleam-lang/gleam.vim
" Last Change: 2025 Apr 21
if exists('current_compiler')
finish
endif
let current_compiler = "gleam_build"
CompilerSet makeprg=gleam\ build
" Example error message:
"
" error: Unknown variable
" ┌─ /home/michael/root/projects/tutorials/gleam/try/code/src/main.gleam:19:18
" │
" 19 │ Ok(tuple(name, spot))
" │ ^^^^ did you mean `sport`?
"
" The name `spot` is not in scope here.
CompilerSet errorformat=%Eerror:\ %m,%Wwarning:\ %m,%C\ %#┌─%#\ %f:%l:%c\ %#-%#
" vim: sw=2 sts=2 et

View File

@@ -2,7 +2,6 @@
" Compiler: Pandoc
" Maintainer: Konfekt
" Last Change: 2024 Nov 19
" 2025 May 15 Update the title regex for CompilerSet #17321
"
" Expects output file extension, say `:make html` or `:make pdf`.
" Passes additional arguments to pandoc, say `:make html --self-contained`.
@@ -52,7 +51,7 @@ endfunction
execute 'CompilerSet makeprg=pandoc'..escape(
\ ' --standalone'..
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s\+\S\+', 'cnw') > 0)) ?
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
\ '' : ' --metadata title=%:t:r:S')..
\ ' '..s:PandocLang()..
\ ' --from='..s:PandocFiletype(&filetype)..

View File

@@ -1,12 +0,0 @@
" Vim compiler file
" Compiler: PHPStan
" Maintainer: Dietrich Moerman <dietrich.moerman@gmail.com>
" Last Change: 2025 Jul 17
if exists("current_compiler")
finish
endif
let current_compiler = "phpstan"
CompilerSet makeprg=composer\ exec\ --\ phpstan\ analyse\ -v\ --no-progress\ --error-format=raw
CompilerSet errorformat=%f:%l:%m,%-G%.%#

File diff suppressed because it is too large Load Diff

View File

@@ -73,16 +73,11 @@ Or use `:execute`: >
Note that special characters (e.g., "%", "<cword>") in the ":autocmd"
arguments are not expanded when the autocommand is defined. These will be
expanded when the Event is recognized, and the {cmd} is executed. The only
exception is that "<sfile>" (unlike "<script>") is expanded when the autocmd
is defined. Example:
exception is that "<sfile>" is expanded when the autocmd is defined. Example:
>
:au BufNewFile,BufRead *.html so <sfile>:h/html.vim
Here Vim expands <sfile> to the name of the file containing this line.
However, <sfile> works differently in a function, in which case it's better to
use `:execute` with <script> to achieve the same purpose:
>
:exe $'au BufNewFile,BufRead *.html so {expand("<script>:h")}/html.vim'
`:autocmd` adds to the list of autocommands regardless of whether they are
already present. When your .vimrc file is sourced twice, the autocommands
@@ -262,7 +257,7 @@ BufLeave Before leaving to another buffer. Also when
Not used for ":qa" or ":q" when exiting Vim.
*BufModifiedSet*
BufModifiedSet After the `'modified'` value of a buffer has
been changed. Special-case of |OptionSet|.
been changed.
*BufNew*
BufNew After creating a new buffer (except during
startup, see |VimEnter|) or renaming an
@@ -306,7 +301,6 @@ BufUnload Before unloading a buffer, when the text in
going to exit.
NOTE: Current buffer "%" is not the target
buffer "<afile>", "<abuf>". |<buffer=abuf>|
*E1546*
Do not switch buffers or windows!
Not triggered when exiting and v:dying is 2 or
more.
@@ -350,8 +344,7 @@ BufWriteCmd Before writing the whole buffer to a file.
The buffer contents should not be changed.
When the command resets 'modified' the undo
information is adjusted to mark older undo
states as 'modified', like |:write| does. Use
the |'[| and |']| marks for the range of lines.
states as 'modified', like |:write| does.
|Cmd-event|
*BufWritePost*
BufWritePost After writing the whole buffer to a file
@@ -407,16 +400,6 @@ CmdlineLeave Before leaving the command-line (including
Note: `abort` can only be changed from false
to true: cannot execute an already aborted
cmdline by changing it to false.
*CmdlineLeavePre*
CmdlineLeavePre Just before leaving the command line, and
before |CmdlineLeave|. Useful for capturing
completion info with |cmdcomplete_info()|, as
this information is cleared before
|CmdlineLeave| is triggered. Triggered for
non-interactive use of ":" in a mapping, but
not when using |<Cmd>|. Also triggered when
abandoning the command line by typing CTRL-C
or <Esc>. <afile> is set to |cmdline-char|.
*CmdwinEnter*
CmdwinEnter After entering the command-line window.
Useful for setting options specifically for
@@ -494,16 +477,27 @@ CompleteDone After Insert mode completion is done. Either
- "accept": completion was
accepted by |complete_CTRL-Y|.
- "cancel": completion was
stopped by |complete_CTRL-E|.
stopped by |complete_CTRL-E.
- "discard": completion was
abandoned for other reason.
*CursorHold*
CursorHold When there is no user input for 'updatetime'
duration, in Normal-mode. Not triggered while
waiting for a command argument or movement
after an operator, nor while |recording|
a macro. See |CursorHold-example|.
CursorHold When the user doesn't press a key for the time
specified with 'updatetime'. Not triggered
until the user has pressed a key (i.e. doesn't
fire every 'updatetime' ms if you leave Vim to
make some coffee. :) See |CursorHold-example|
for previewing tags.
This event is only triggered in Normal mode.
It is not triggered when waiting for a command
argument to be typed, or a movement after an
operator.
While recording the CursorHold event is not
triggered. |q|
*<CursorHold>*
Internally the autocommand is triggered by the
<CursorHold> key. In an expression mapping
|getchar()| may see this character.
Note: Interactive commands cannot be used for
this event. There is no hit-enter prompt,
@@ -654,14 +648,14 @@ FileType When the 'filetype' option has been set. The
FileWriteCmd Before writing to a file, when not writing the
whole buffer. Should do the writing to the
file. Should not change the buffer. Use the
|'[| and |']| marks for the range of lines.
'[ and '] marks for the range of lines.
|Cmd-event|
*FileWritePost*
FileWritePost After writing to a file, when not writing the
whole buffer.
*FileWritePre*
FileWritePre Before writing to a file, when not writing the
whole buffer. Use the |'[| and |']| marks for the
whole buffer. Use the '[ and '] marks for the
range of lines.
*FilterReadPost*
FilterReadPost After reading a file from a filter command.
@@ -788,31 +782,6 @@ ModeChanged After changing the mode. The pattern is
:au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]'
:au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]'
:au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]'
Progress *Progress*
After a progress message is created or updated via
`nvim_echo`. The pattern is matched against
title of the message. The |event-data| contains:
id: id of the message
text: text of the message
title: title of the progress message
status: status of the progress message
percent: how much progress has been
made for this progress item
Usage example:
>
vim.api.nvim_create_autocmd('Progress', {
pattern={"term"},
callback = function(ev)
print(string.format('event fired: %s', vim.inspect(ev)))
end
})
local id = vim.api.nvim_echo({{'searching...'}}, true,
{kind='progress', status='running', percent=10, title="term"})
vim.api.nvim_echo({{'searching'}}, true,
{id = id, kind='progress', status='running', percent=50, title="term"})
vim.api.nvim_echo({{'done'}}, true,
{id = id, kind='progress', status='success', percent=100, title="term"})
< *OptionSet*
OptionSet After setting an option (except during
|startup|). The |autocmd-pattern| is matched
@@ -853,10 +822,6 @@ OptionSet After setting an option (except during
always use |:noautocmd| to prevent triggering
OptionSet.
Note: Not triggered by the 'modified' option;
the |BufModifiedSet| event may be used to
handle that.
Non-recursive: |:set| in the autocommand does
not trigger OptionSet again.
@@ -1069,7 +1034,7 @@ TermRequest When a |:terminal| child process emits an OSC,
autocommand defined without |autocmd-nested|.
*TermResponse*
TermResponse When Nvim receives a DA1, OSC, DCS, or APC response from
TermResponse When Nvim receives an OSC or DCS response from
the host terminal. Sets |v:termresponse|. The
|event-data| is a table with the following fields:
@@ -1093,7 +1058,7 @@ TermResponse When Nvim receives a DA1, OSC, DCS, or APC response from
local r, g, b = resp:match("\027%]4;1;rgb:(%w+)/(%w+)/(%w+)")
end,
})
vim.api.nvim_ui_send("\027]4;1;?\027\\")
io.stdout:write("\027]4;1;?\027\\")
<
*TextChanged*
TextChanged After a change was made to the text in the
@@ -1221,13 +1186,6 @@ WinScrolled After any window in the current tab page
or changed width or height. See
|win-scrolled-resized|.
Note: This can not be skipped with
`:noautocmd`, because it triggers after
processing normal commands when Vim is back in
the main loop. If you want to disable this,
consider setting the 'eventignore' option
instead.
The pattern is matched against the |window-ID|
of the first window that scrolled or resized.
Both <amatch> and <afile> are set to the

View File

@@ -1,16 +1,16 @@
*vimfn.txt* Nvim
*builtin.txt* Nvim
NVIM REFERENCE MANUAL
Vimscript functions *vimscript-functions* *builtin.txt*
Builtin functions *vimscript-functions* *builtin-functions*
For functions grouped by what they are used for see |function-list|.
Type |gO| to see the table of contents.
==============================================================================
1. Details *vimscript-functions-details*
1. Details *builtin-function-details*
abs({expr}) *abs()*
Return the absolute value of {expr}. When {expr} evaluates to
@@ -1008,23 +1008,16 @@ charidx({string}, {idx} [, {countcc} [, {utf16}]]) *charidx()*
Return: ~
(`integer`)
chdir({dir} [, {scope}]) *chdir()*
Changes the current working directory to {dir}. The scope of
the change is determined as follows:
If {scope} is not present, the current working directory is
changed to the scope of the current directory:
- If the window local directory (|:lcd|) is set, it
changes the current working directory for that scope.
- Otherwise, if the tab page local directory (|:tcd|) is
set, it changes the current directory for that scope.
- Otherwise, changes the global directory for that scope.
If {scope} is present, changes the current working directory
for the specified scope:
"window" Changes the window local directory. |:lcd|
"tabpage" Changes the tab page local directory. |:tcd|
"global" Changes the global directory. |:cd|
chdir({dir}) *chdir()*
Change the current working directory to {dir}. The scope of
the directory change depends on the directory of the current
window:
- If the current window has a window-local directory
(|:lcd|), then changes the window local directory.
- Otherwise, if the current tabpage has a local
directory (|:tcd|) then changes the tabpage local
directory.
- Otherwise, changes the global directory.
{dir} must be a String.
If successful, returns the previous working directory. Pass
this to another chdir() to restore the directory.
@@ -1040,7 +1033,6 @@ chdir({dir} [, {scope}]) *chdir()*
Parameters: ~
• {dir} (`string`)
• {scope} (`string?`)
Return: ~
(`string`)
@@ -1069,29 +1061,6 @@ clearmatches([{win}]) *clearmatches()*
Parameters: ~
• {win} (`integer?`)
cmdcomplete_info() *cmdcomplete_info()*
Returns a |Dictionary| with information about cmdline
completion. See |cmdline-completion|.
The items are:
cmdline_orig The original command-line string before
completion began.
pum_visible |TRUE| if popup menu is visible.
See |pumvisible()|.
matches List of all completion candidates. Each item
is a string.
selected Selected item index. First index is zero.
Index is -1 if no item is selected (showing
typed text only, or the last completion after
no item is selected when using the <Up> or
<Down> keys)
Returns an empty |Dictionary| if no completion was attempted,
if there was only one candidate and it was fully completed, or
if an error occurred.
Return: ~
(`table<string,any>`)
col({expr} [, {winid}]) *col()*
The result is a Number, which is the byte index of the column
position given with {expr}.
@@ -1244,7 +1213,6 @@ complete_info([{what}]) *complete_info()*
"omni" Omni completion |i_CTRL-X_CTRL-O|
"spell" Spelling suggestions |i_CTRL-X_s|
"eval" |complete()| completion
"register" Words from registers |i_CTRL-X_CTRL-R|
"unknown" Other internal modes
If the optional {what} list argument is supplied, then only
@@ -1272,56 +1240,6 @@ complete_info([{what}]) *complete_info()*
Return: ~
(`table`)
complete_match([{lnum}, {col}]) *complete_match()*
Searches backward from the given position and returns a List
of matches according to the 'isexpand' option. When no
arguments are provided, uses the current cursor position.
Each match is represented as a List containing
[startcol, trigger_text] where:
- startcol: column position where completion should start,
or -1 if no trigger position is found. For multi-character
triggers, returns the column of the first character.
- trigger_text: the matching trigger string from 'isexpand',
or empty string if no match was found or when using the
default 'iskeyword' pattern.
When 'isexpand' is empty, uses the 'iskeyword' pattern "\k\+$"
to find the start of the current keyword.
Examples: >vim
set isexpand=.,->,/,/*,abc
func CustomComplete()
let res = complete_match()
if res->len() == 0 | return | endif
let [col, trigger] = res[0]
let items = []
if trigger == '/*'
let items = ['/** */']
elseif trigger == '/'
let items = ['/*! */', '// TODO:', '// fixme:']
elseif trigger == '.'
let items = ['length()']
elseif trigger =~ '^\->'
let items = ['map()', 'reduce()']
elseif trigger =~ '^\abc'
let items = ['def', 'ghk']
endif
if items->len() > 0
let startcol = trigger =~ '^/' ? col : col + len(trigger)
call complete(startcol, items)
endif
endfunc
inoremap <Tab> <Cmd>call CustomComplete()<CR>
<
Parameters: ~
• {lnum} (`integer?`)
• {col} (`integer?`)
Return: ~
(`table`)
confirm({msg} [, {choices} [, {default} [, {type}]]]) *confirm()*
confirm() offers the user a dialog, from which a choice can be
made. It returns the number of the choice. For the first
@@ -2106,35 +2024,34 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
done like for the |cmdline-special| variables with their
associated modifiers. Here is a short overview:
% Current file name
# Alternate file name
#n Alternate file name n
<cfile> File name under the cursor
<afile> Autocmd file name
<abuf> Autocmd buffer number (as a String!)
<amatch> Autocmd matched name
% current file name
# alternate file name
#n alternate file name n
<cfile> file name under the cursor
<afile> autocmd file name
<abuf> autocmd buffer number (as a String!)
<amatch> autocmd matched name
<cexpr> C expression under the cursor
<sfile> Deprecated, use <script> or <stack>
<slnum> Sourced script line number or function
<sfile> sourced script file or function name
<slnum> sourced script line number or function
line number
<sflnum> Script file line number, also when in
<sflnum> script file line number, also when in
a function
<SID> "<SNR>123_" where "123" is the
current script ID |<SID>|
<script> Sourced script file, or script file
where the current function was defined.
For Lua see |lua-script-location|.
<stack> Call stack
<cword> Word under the cursor
<script> sourced script file, or script file
where the current function was defined
<stack> call stack
<cword> word under the cursor
<cWORD> WORD under the cursor
<client> The {clientid} of the last received
<client> the {clientid} of the last received
message
Modifiers:
:p Expand to full path
:h Head (last path component removed)
:t Tail (last path component only)
:r Root (one extension removed)
:e Extension only
:p expand to full path
:h head (last path component removed)
:t tail (last path component only)
:r root (one extension removed)
:e extension only
Example: >vim
let &tags = expand("%:p:h") .. "/tags"
@@ -2467,7 +2384,7 @@ finddir({name} [, {path} [, {count}]]) *finddir()*
• {count} (`integer?`)
Return: ~
(`string|string[]`)
(`any`)
findfile({name} [, {path} [, {count}]]) *findfile()*
Just like |finddir()|, but find a file instead of a directory.
@@ -2480,10 +2397,10 @@ findfile({name} [, {path} [, {count}]]) *findfile()*
Parameters: ~
• {name} (`string`)
• {path} (`string?`)
• {count} (`integer?`)
• {count} (`any?`)
Return: ~
(`string|string[]`)
(`any`)
flatten({list} [, {maxdepth}]) *flatten()*
Flatten {list} up to {maxdepth} levels. Without {maxdepth}
@@ -3124,7 +3041,6 @@ getbufvar({buf}, {varname} [, {def}]) *getbufvar()*
Examples: >vim
let bufmodified = getbufvar(1, "&mod")
echo "todo myvar = " .. getbufvar("todo", "myvar")
<
Parameters: ~
• {buf} (`integer|string`)
@@ -3173,7 +3089,8 @@ getchar([{expr} [, {opts}]]) *getchar()*
Return zero otherwise.
If {expr} is 1, only check if a character is available, it is
not consumed. Return zero if no character available.
To always get a string, specify "number" as |FALSE| in {opts}.
If you prefer always getting a string use |getcharstr()|, or
specify |FALSE| as "number" in {opts}.
Without {expr} and when {expr} is 0 a whole character or
special key is returned. If it is a single character, the
@@ -3327,7 +3244,7 @@ getcharsearch() *getcharsearch()*
Return: ~
(`table`)
getcharstr([{expr} [, {opts}]]) *getcharstr()*
getcharstr([{expr}]) *getcharstr()*
The same as |getchar()|, except that this always returns a
String, and "number" isn't allowed in {opts}.
@@ -3358,9 +3275,6 @@ getcmdcompltype() *getcmdcompltype()*
|getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|.
Returns an empty string when completion is not defined.
To get the type of the command-line completion for a specified
string, use |getcompletiontype()|.
Return: ~
(`string`)
@@ -3457,14 +3371,13 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
customlist,{func} custom completion, defined via {func}
diff_buffer |:diffget| and |:diffput| completion
dir directory names
dir_in_path directory names in 'cdpath'
dir_in_path directory names in |'cdpath'|
environment environment variable names
event autocommand events
expression Vim expression
file file and directory names
file_in_path file and directory names in 'path'
filetype filetype names 'filetype'
filetypecmd |:filetype| suboptions
file_in_path file and directory names in |'path'|
filetype filetype names |'filetype'|
function function name
help help subjects
highlight highlight groups
@@ -3477,13 +3390,12 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
messages |:messages| suboptions
option options
packadd optional package |pack-add| names
retab |:retab| suboptions
runtime |:runtime| completion
scriptnames sourced script names |:scriptnames|
shellcmd Shell command
shellcmdline Shell command line with filename arguments
sign |:sign| suboptions
syntax syntax file names 'syntax'
syntax syntax file names |'syntax'|
syntime |:syntime| suboptions
tag tags
tag_listfiles tags, file names
@@ -3521,19 +3433,6 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
Return: ~
(`string[]`)
getcompletiontype({pat}) *getcompletiontype()*
Return the type of the command-line completion using {pat}.
When no corresponding completion type is found, an empty
string is returned.
To get the current command-line completion type, use
|getcmdcompltype()|.
Parameters: ~
• {pat} (`string`)
Return: ~
(`string`)
getcurpos([{winid}]) *getcurpos()*
Get the position of the cursor. This is like getpos('.'), but
includes an extra "curswant" item in the list:
@@ -3563,7 +3462,7 @@ getcurpos([{winid}]) *getcurpos()*
• {winid} (`integer?`)
Return: ~
(`[integer, integer, integer, integer, integer]`)
(`any`)
getcursorcharpos([{winid}]) *getcursorcharpos()*
Same as |getcurpos()| but the column number in the returned
@@ -3872,7 +3771,7 @@ getmatches([{win}]) *getmatches()*
• {win} (`integer?`)
Return: ~
(`vim.fn.getmatches.ret.item[]`)
(`any`)
getmousepos() *getmousepos()*
Returns a |Dictionary| with the last known position of the
@@ -3978,7 +3877,7 @@ getpos({expr}) *getpos()*
• {expr} (`string`)
Return: ~
(`[integer, integer, integer, integer]`)
(`integer[]`)
getqflist([{what}]) *getqflist()*
Returns a |List| with all the current quickfix errors. Each
@@ -4115,7 +4014,6 @@ getreg([{regname} [, 1 [, {list}]]]) *getreg()*
Parameters: ~
• {regname} (`string?`)
• {expr} (`any?`)
• {list} (`nil|false?`)
Return: ~
@@ -4195,10 +4093,6 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()*
- It is evaluated in current window context, which makes a
difference if the buffer is displayed in a window with
different 'virtualedit' or 'list' values.
- When specifying an exclusive selection and {pos1} and {pos2}
are equal, the returned list contains a single character as
if selection is inclusive, to match the behavior of an empty
exclusive selection in Visual mode.
Examples: >vim
xnoremap <CR>
@@ -4207,9 +4101,9 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()*
<
Parameters: ~
• {pos1} (`[integer, integer, integer, integer]`)
• {pos2} (`[integer, integer, integer, integer]`)
• {opts} (`{type?:string, exclusive?:boolean}?`)
• {pos1} (`table`)
• {pos2} (`table`)
• {opts} (`table?`)
Return: ~
(`string[]`)
@@ -4247,13 +4141,12 @@ getregionpos({pos1}, {pos2} [, {opts}]) *getregionpos()*
(default: |FALSE|)
Parameters: ~
• {pos1} (`[integer, integer, integer, integer]`)
• {pos2} (`[integer, integer, integer, integer]`)
• {opts}
(`{type?:string, exclusive?:boolean, eol?:boolean}?`)
• {pos1} (`table`)
• {pos2} (`table`)
• {opts} (`table?`)
Return: ~
(`[ [integer, integer, integer, integer], [integer, integer, integer, integer] ][]`)
(`integer[][][]`)
getregtype([{regname}]) *getregtype()*
The result is a String, which is type of register {regname}.
@@ -4546,7 +4439,6 @@ getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*
Examples: >vim
let list_is_on = getwinvar(2, '&list')
echo "myvar = " .. getwinvar(1, 'myvar')
<
Parameters: ~
• {winnr} (`integer`)
@@ -5246,7 +5138,6 @@ inputlist({textlist}) *inputlist()*
Example: >vim
let color = inputlist(['Select color:', '1. red',
\ '2. green', '3. blue'])
<
Parameters: ~
• {textlist} (`string[]`)
@@ -5424,27 +5315,22 @@ isnan({expr}) *isnan()*
Return: ~
(`0|1`)
items({expr}) *items()*
Return a |List| with all key/index and value pairs of {expr}.
Each |List| item is a list with two items:
- for a |Dict|: the key and the value
- for a |List| or |String|: the index and the value
The returned |List| is in arbitrary order for a |Dict|,
otherwise it's in ascending order of the index.
Also see |keys()| and |values()|.
items({dict}) *items()*
Return a |List| with all the key-value pairs of {dict}. Each
|List| item is a list with two items: the key of a {dict}
entry and the value of this entry. The |List| is in arbitrary
order. Also see |keys()| and |values()|.
Example: >vim
let mydict = #{a: 'red', b: 'blue'}
for [key, value] in items(mydict)
echo $"{key} = {value}"
echo key .. ': ' .. value
endfor
echo items([1, 2, 3])
echo items("foobar")
<
A List or a String argument is also supported. In these
cases, items() returns a List with the index and the value at
the index.
Parameters: ~
• {expr} (`table|string`)
• {dict} (`table`)
Return: ~
(`any`)
@@ -5753,7 +5639,6 @@ libcall({libname}, {funcname}, {argument}) *libcall()* *E364* *E
object code must be compiled as position-independent ('PIC').
Examples: >vim
echo libcall("libc.so", "getenv", "HOME")
<
Parameters: ~
• {libname} (`string`)
@@ -7575,19 +7460,6 @@ printf({fmt}, {expr1} ...) *printf()*
Return: ~
(`string`)
prompt_getinput({buf}) *prompt_getinput()*
Gets the current user-input in |prompt-buffer| {buf} without invoking
prompt_callback. {buf} can be a buffer name or number.
If the buffer doesn't exist or isn't a prompt buffer, an empty
string is returned.
Parameters: ~
• {buf} (`integer|string`)
Return: ~
(`any`)
prompt_getprompt({buf}) *prompt_getprompt()*
Returns the effective prompt text for buffer {buf}. {buf} can
be a buffer name or number. See |prompt-buffer|.
@@ -7897,7 +7769,7 @@ readfile({fname} [, {type} [, {max}]]) *readfile()*
• {max} (`integer?`)
Return: ~
(`string[]`)
(`any`)
reduce({object}, {func} [, {initial}]) *reduce()* *E998*
{func} is called for every item in {object}, which can be a
@@ -8466,12 +8338,11 @@ searchcount([{options}]) *searchcount()*
To get the last search count when |n| or |N| was pressed, call
this function with `recompute: 0` . This sometimes returns
wrong information because of 'maxsearchcount'.
If the count exceeded 'maxsearchcount', the result must be
'maxsearchcount' + 1. If you want to get correct information,
specify `recompute: 1`: >vim
wrong information because |n| and |N|'s maximum count is 99.
If it exceeded 99 the result must be max count + 1 (100). If
you want to get correct information, specify `recompute: 1`: >vim
" result == 'maxsearchcount' + 1 when many matches
" result == maxcount + 1 (100) when many matches
let result = searchcount(#{recompute: 0})
" Below returns correct result (recompute defaults
@@ -8558,7 +8429,7 @@ searchcount([{options}]) *searchcount()*
result. if search exceeded
total count, "total" value
becomes `maxcount + 1`
(default: 'maxsearchcount')
(default: 0)
pos |List| `[lnum, col, off]` value
when recomputing the result.
this changes "current" result
@@ -8746,23 +8617,13 @@ searchpos({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]])
Return: ~
(`any`)
serverlist([{opts}]) *serverlist()*
serverlist() *serverlist()*
Returns a list of server addresses, or empty if all servers
were stopped. |serverstart()| |serverstop()|
The optional argument {opts} is a Dict and supports the following items:
peer : If |TRUE|, servers not started by |serverstart()|
will also be returned. (default: |FALSE|)
Not supported on Windows yet.
Example: >vim
echo serverlist()
<
Parameters: ~
• {opts} (`table?`)
Return: ~
(`string[]`)
@@ -9004,8 +8865,6 @@ setcursorcharpos({list})
call cursor(4, 3)
< positions the cursor on the first character '여'.
Returns 0 when the position could be set, -1 otherwise.
Parameters: ~
• {list} (`integer[]`)
@@ -9119,7 +8978,7 @@ setmatches({list} [, {win}]) *setmatches()*
window ID instead of the current window.
Parameters: ~
• {list} (`vim.fn.getmatches.ret.item[]`)
• {list} (`any`)
• {win} (`integer?`)
Return: ~
@@ -9360,7 +9219,6 @@ setreg({regname}, {value} [, {options}]) *setreg()*
You can also change the type of a register by appending
nothing: >vim
call setreg('a', '', 'al')
<
Parameters: ~
• {regname} (`string`)
@@ -9458,7 +9316,6 @@ setwinvar({nr}, {varname}, {val}) *setwinvar()*
Examples: >vim
call setwinvar(1, "&list", 0)
call setwinvar(2, "myvar", "foobar")
<
Parameters: ~
• {nr} (`integer`)
@@ -9929,7 +9786,6 @@ sign_unplace({group} [, {dict}]) *sign_unplace()*
" Remove all the placed signs from all the buffers
call sign_unplace('*')
<
Parameters: ~
• {group} (`string`)
@@ -10387,8 +10243,8 @@ stdpath({what}) *stdpath()* *E610
log String Logs directory (for use by plugins too).
run String Run directory: temporary, local storage
for sockets, named pipes, etc.
state String Session state: storage for backupdir,
file drafts, |shada|, swap, undo, 'viewdir'.
state String Session state directory: storage for file
drafts, swap, undo, |shada|.
Example: >vim
echo stdpath("config")
@@ -10586,7 +10442,6 @@ strftime({format} [, {time}]) *strftime()*
echo strftime("%H:%M") " 11:55
echo strftime("%c", getftime("file.c"))
" Show mod time of file.c.
<
Parameters: ~
• {format} (`string`)
@@ -10776,7 +10631,7 @@ strridx({haystack}, {needle} [, {start}]) *strridx()*
strtrans({string}) *strtrans()*
The result is a String, which is {string} with all unprintable
characters translated into printable characters 'isprint'.
characters translated into printable characters |'isprint'|.
Like they are shown in a window. Example: >vim
echo strtrans(@a)
< This displays a newline in register a as "^@" instead of
@@ -10929,7 +10784,6 @@ swapfilelist() *swapfilelist()*
let &directory = '.'
let swapfiles = swapfilelist()
let &directory = save_dir
<
Return: ~
(`string[]`)
@@ -11318,7 +11172,7 @@ taglist({expr} [, {filename}]) *taglist()*
Refer to |tag-regexp| for more information about the tag
search regular expression pattern.
Refer to 'tags' for information about how the tags file is
Refer to |'tags'| for information about how the tags file is
located by Vim. Refer to |tags-file-format| for the format of
the tags file generated by the different ctags tools.
@@ -11684,15 +11538,12 @@ undotree([{buf}]) *undotree()*
(`vim.fn.undotree.ret`)
uniq({list} [, {func} [, {dict}]]) *uniq()* *E882*
Note: Prefer |vim.list.unique()| in Lua.
Remove second and succeeding copies of repeated adjacent
{list} items in-place. Returns {list}. If you want a list
to remain unmodified make a copy first: >vim
let newlist = uniq(copy(mylist))
< The default compare function uses the string representation of
each item. For the use of {func} and {dict} see |sort()|.
For deduplicating text in the current buffer see |:uniq|.
Returns zero if {list} is not a |List|.
@@ -11772,7 +11623,7 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
last character. When "off" is omitted zero is used. When
Virtual editing is active in the current mode, a position
beyond the end of the line can be returned. Also see
'virtualedit'
|'virtualedit'|
If {list} is present and non-zero then virtcol() returns a
List with the first and last screen position occupied by the
@@ -11806,7 +11657,7 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
• {winid} (`integer?`)
Return: ~
(`integer|[integer, integer]`)
(`any`)
virtcol2col({winid}, {lnum}, {col}) *virtcol2col()*
The result is a Number, which is the byte index of the
@@ -11900,38 +11751,6 @@ wildmenumode() *wildmenumode()*
Return: ~
(`any`)
wildtrigger() *wildtrigger()*
Start wildcard expansion in the command-line, using the
behavior defined by the 'wildmode' and 'wildoptions' settings.
See |cmdline-completion|.
This function also enables completion in search patterns such
as |/|, |?|, |:s|, |:g|, |:v| and |:vimgrep|.
Unlike pressing 'wildchar' manually, this function does not
produce a beep when no matches are found and generally
operates more quietly. This makes it suitable for triggering
completion automatically, such as from an |:autocmd|.
*cmdline-autocompletion*
Example: To make the completion menu pop up automatically as
you type on the command line, use: >vim
autocmd CmdlineChanged [:/\?] call wildtrigger()
set wildmode=noselect:lastused,full wildoptions=pum
<
To retain normal history navigation (up/down keys): >vim
cnoremap <Up> <C-U><Up>
cnoremap <Down> <C-U><Down>
<
To set an option specifically when performing a search, e.g.
to set 'pumheight': >vim
autocmd CmdlineEnter [/\?] set pumheight=8
autocmd CmdlineLeave [/\?] set pumheight&
<
Return value is always 0.
Return: ~
(`number`)
win_execute({id}, {command} [, {silent}]) *win_execute()*
Like `execute()` but in the context of window {id}.
The window will temporarily be made the current window,
@@ -12210,7 +12029,7 @@ winlayout([{tabnr}]) *winlayout()*
• {tabnr} (`integer?`)
Return: ~
(`vim.fn.winlayout.ret`)
(`any[]`)
winline() *winline()*
The result is a Number, which is the screen line of the cursor
@@ -12225,8 +12044,7 @@ winline() *winline()*
winnr([{arg}]) *winnr()*
The result is a Number, which is the number of the current
window. The top window has number 1.
Returns zero for a hidden or non |focusable| window, unless
it is the current window.
Returns zero for a popup window.
The optional argument {arg} supports the following values:
$ the number of the last window (the window

View File

@@ -22,13 +22,13 @@ For inserting text see |insert.txt|.
"dl".
The <Del> key does not take a [count]. Instead, it
deletes the last character of the count.
See 'whichwrap' for deleting a line break (join
See |'whichwrap'| for deleting a line break (join
lines).
*X* *dh*
["x]X Delete [count] characters before the cursor [into
register x] (not |linewise|). Does the same as "dh".
Also see 'whichwrap'.
Also see |'whichwrap'|.
*d*
["x]d{motion} Delete text that {motion} moves over [into register
@@ -141,8 +141,8 @@ the 'joinspaces' option is on, these commands insert two spaces after a '.',
The 'B' and 'M' flags in 'formatoptions' change the behavior for inserting
spaces before and after a multibyte character |fo-table|.
The |'[| mark is set at the end of the first line that was joined, |']| at the
end of the resulting line.
The '[ mark is set at the end of the first line that was joined, '] at the end
of the resulting line.
==============================================================================
@@ -583,9 +583,9 @@ with ".". Vim does not recognize a comment (starting with '"') after the
={motion} Filter {motion} lines through the external program
given with the 'equalprg' option. When the 'equalprg'
option is empty (this is the default), use the
internal formatting function |C-indenting| and 'lisp'.
But when 'indentexpr' is not empty, it will be used
instead |indent-expression|.
internal formatting function |C-indenting| and
|'lisp'|. But when 'indentexpr' is not empty, it will
be used instead |indent-expression|.
*==*
== Filter [count] lines like with ={motion}.
@@ -644,9 +644,8 @@ original user.
Repeat last :substitute with same search pattern and
substitute string, but without the same flags. You
may add [flags], see |:s_flags|.
Note that after `:substitute` the '&' and '#' flags
can't be used, they're recognized as a pattern
separator.
Note that after `:substitute` the '&' flag can't be
used, it's recognized as a pattern separator.
The space between `:substitute` and the 'c', 'g',
'i', 'I' and 'r' flags isn't required, but in scripts
it's a good idea to keep it to avoid confusion.
@@ -949,26 +948,22 @@ This replaces each 'E' character with a euro sign. Read more in |<Char->|.
4.3 Changing tabs *change-tabs*
*:ret* *:retab* *:retab!*
:[range]ret[ab][!] [-indentonly] [{new-tabstop}]
:[range]ret[ab][!] [new_tabstop]
Replace all sequences of white-space containing a
<Tab> with new strings of white-space using
{new-tabstop}. If you do not specify {new-tabstop} or
it is zero, Vim uses the current value of 'tabstop'.
<Tab> with new strings of white-space using the new
tabstop value given. If you do not specify a new
tabstop size or it is zero, Vim uses the current value
of 'tabstop'.
The current value of 'tabstop' is always used to
compute the width of existing tabs.
With !, Vim also replaces strings of only normal
spaces with tabs where appropriate.
With 'expandtab' on, Vim replaces all tabs with the
appropriate number of spaces.
This command sets 'tabstop' to {new-tabstop} and if
performed on the whole file, which is default, should
not make any visible change.
When [-indentonly] is specified, only the leading
white-space will be targeted. Any other consecutive
white-space will not be changed.
Warning: This command modifies any <Tab> characters
This command sets 'tabstop' to the new value given,
and if performed on the whole file, which is default,
should not make any visible change.
Careful: This command modifies any <Tab> characters
inside of strings in a C program. Use "\t" to avoid
this (that's a good habit anyway).
`:retab!` may also change a sequence of spaces by
@@ -1110,11 +1105,6 @@ inside of strings can change! Also see 'softtabstop' option. >
:[line]pu[t]! [x] Put the text [from register x] before [line] (default
current line).
*:ip* *:iput*
:[line]ip[ut] [x] like |:put|, but adjust indent to the current line
:[line]ip[ut]! [x] like |:put|!, but adjust indent to the current line
["x]]p or *]p* *]<MiddleMouse>*
["x]]<MiddleMouse> Like "p", but adjust the indent to the current line.
Using the mouse only works when 'mouse' contains 'n'
@@ -1149,27 +1139,27 @@ the ":put" command, Vim always inserts the text in the next line. You can
exchange two characters with the command sequence "xp". You can exchange two
lines with the command sequence "ddp". You can exchange two words with the
command sequence "deep" (start with the cursor in the blank space before the
first word). You can use the |']| or |`]| command after the put command to
move the cursor to the end of the inserted text, or use |'[| or |`[| to move
first word). You can use the "']" or "`]" command after the put command to
move the cursor to the end of the inserted text, or use "'[" or "`[" to move
the cursor to the start.
*put-Visual-mode*
*put-Visual-mode* *v_p* *v_P*
When using a put command like |p| or |P| in Visual mode, Vim will try to
replace the selected text with the contents of the register. How this
works depends on the type of selection and the text. With blockwise selection
it also depends on the size of the block and whether the corners are on an
existing character. (Implementation detail: it actually works by first
putting the register after the selection and then deleting the selection.)
*v_p*
|p| in Visual mode puts text and sets the default register (unnamed,
selection, or clipboard) to the previously-selected text. Useful if you want
to put that text somewhere else. But you cannot repeat the same change.
*v_P*
|P| in Visual mode puts text without setting the default register. You can
repeat the change, but the deleted text cannot be used. If you do need it you
can use |p| with another register. E.g., yank the text to copy, Visually
select the text to replace and use "0p . You can repeat this as many times as
you like, and the unnamed register will be changed each time.
replace the selected text with the contents of the register. Whether this
works well depends on the type of selection and the type of the text in the
register. With blockwise selection it also depends on the size of the block
and whether the corners are on an existing character. (Implementation detail:
it actually works by first putting the register after the selection and then
deleting the selection.)
With |p| the previously selected text is put in the unnamed register (and
possibly the selection and/or clipboard). This is useful if you want to put
that text somewhere else. But you cannot repeat the same change.
With |P| the unnamed register is not changed (and neither the selection or
clipboard), you can repeat the same change. But the deleted text cannot be
used. If you do need it you can use |p| with another register. E.g., yank
the text to copy, Visually select the text to replace and use "0p . You can
repeat this as many times as you like, and the unnamed register will be
changed each time.
*blockwise-put*
When a register contains text from one line (characterwise), using a
blockwise Visual selection, putting that register will paste that text
@@ -1249,18 +1239,6 @@ mapped. E.g. |%| is mapped by the matchit plugin.
With each successive deletion or change, Vim shifts the previous contents
of register 1 into register 2, 2 into 3, and so forth, losing the previous
contents of register 9.
*yankring*
To also store yanks (not only deletions) in registers 1-9, try this: >lua
-- Yank-ring: store yanked text in registers 1-9.
vim.api.nvim_create_autocmd('TextYankPost', {
callback = function()
if vim.v.event.operator == 'y' then
for i = 9, 1, -1 do -- Shift all numbered registers.
vim.fn.setreg(tostring(i), vim.fn.getreg(tostring(i - 1)))
end
end
end,
})
3. Small delete register "- *quote_-* *quote-*
This register contains text from commands that delete less than one line,
@@ -1839,7 +1817,6 @@ And a few warnings:
Vim has a sorting function and a sorting command. The sorting function can be
found here: |sort()|, |uniq()|.
Also see |:uniq|.
*:sor* *:sort*
:[range]sor[t][!] [b][f][i][l][n][o][r][u][x] [/{pattern}/]
@@ -1849,7 +1826,7 @@ Also see |:uniq|.
With [!] the order is reversed.
With [i] case is ignored.
*:sort-l*
With [l] sort uses the current collation locale.
Implementation details: strcoll() is used to compare
strings. See |:language| to check or set the collation
@@ -1881,14 +1858,13 @@ Also see |:uniq|.
With [b] sorting is done on the first binary number in
the line (after or inside a {pattern} match).
*:sort-u* *:sort-uniq*
With [u] (u stands for unique) only keep the first of
a sequence of identical lines (ignoring case when [i]
is used). Without this flag, a sequence of identical
lines will be kept in their original order.
Note that leading and trailing white space may cause
lines to be different.
When you just want to make things unique, use |:uniq|.
When /{pattern}/ is specified and there is no [r] flag
the text matched with {pattern} is skipped, so that
@@ -1935,55 +1911,4 @@ The sorting can be interrupted, but if you interrupt it too late in the
process you may end up with duplicated lines. This also depends on the system
library function used.
==============================================================================
8. Deduplicating text *deduplicating* *unique*
Vim has a deduplicating function and a deduplicating command. The
deduplicating function can be found here: |uniq()|.
Also see |:sort-uniq|.
*:uni* *:uniq*
:[range]uni[q][!] [i][l][r][u] [/{pattern}/]
Remove duplicate lines that are adjacent to each other
in [range]. When no range is given, all lines are
processed.
With [i] case is ignored when comparing lines.
With [l] comparison uses the current collation locale.
See |:sort-l| for more details.
With [r] comparison is done on the text that matches
/{pattern}/ instead of the full line.
With [u] only keep lines that do not repeat (i.e., are
not immediately followed by the same line).
With [!] only keep lines that are immediately followed
by a duplicate.
If both [!] and [u] are given, [u] is ignored and [!]
takes effect.
When /{pattern}/ is specified and [r] is not used, the
text matched with {pattern} is skipped and comparison
is done on what comes after the match.
'ignorecase' applies to the pattern, but 'smartcase'
is not used.
Instead of the slash any non-letter can be used.
For example, to remove adjacent duplicate lines based
on the second comma-separated field: >
:uniq /[^,]*,/
< Or to keep only unique lines ignoring the first 5
characters: >
:uniq u /.\{5}/
< If {pattern} is empty (e.g. // is used), the last
search pattern is used.
Note that leading and trailing white space may cause
lines to be considered different.
To remove all duplicates regardless of position, use
|:sort-u| or external tools.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -177,85 +177,84 @@ Put this in `uppercase.vim` and run: >bash
==============================================================================
5. Using a prompt buffer *prompt-buffer*
Prompt buffers provide a "prompt" interface: they are like regular buffers,
except only the last section of the buffer is editable, and the user can
"submit" the prompt by hitting Enter. Useful for implementing:
- chat UI
- REPL or shell plugins
- advanced "picker" plugins
If you want to type input for the job in a Vim window you have a few options:
- Use a normal buffer and handle all possible commands yourself.
This will be complicated, since there are so many possible commands.
- Use a terminal window. This works well if what you type goes directly to
the job and the job output is directly displayed in the window.
See |terminal|.
- Use a window with a prompt buffer. This works well when entering a line for
the job in Vim while displaying (possibly filtered) output from the job.
A prompt buffer is created by setting 'buftype' to "prompt". You would
normally only do that in a newly created buffer: >vim
normally only do that in a newly created buffer.
:set buftype=prompt
The user can edit and enter one line of text at the very last line of the
buffer. When pressing Enter in the prompt line the callback set with
|prompt_setcallback()| is invoked. It would normally send the line to a job.
Another callback would receive the output from the job and display it in the
buffer, below the prompt (and above the next prompt).
The user can edit and enter text at the end of the buffer. Pressing Enter in
the prompt section invokes the |prompt_setcallback()| callback, which is
typically expected to process the prompt and show results by appending to the
buffer. To input multiline text, use Shift+Enter to add a new line without
submitting the prompt, or just |put| or |paste| multiline text.
Only the text in the last line, after the prompt, is editable. The rest of the
buffer is not modifiable with Normal mode commands. It can be modified by
calling functions, such as |append()|. Using other commands may mess up the
buffer.
Only the "prompt" part of the buffer user-editable, given by the |':| mark.
The rest of the buffer is not modifiable with Normal mode commands, though it
can be modified by functions such as |append()|. Using other commands may
mess up the buffer.
After setting 'buftype' to "prompt" Vim does not automatically start Insert
mode, use `:startinsert` if you want to enter Insert mode, so that the user
can start typing a line.
After setting `buftype=prompt`:
- Nvim unsets the 'comments' option.
- Nvim does not automatically start Insert mode (use `:startinsert` if you
want to enter Insert mode)
The prompt prefix defaults to "% ", but can be set with |prompt_setprompt()|.
You can get the effective prompt prefix for with |prompt_getprompt()|.
The text of the prompt can be set with the |prompt_setprompt()| function. If
no prompt is set with |prompt_setprompt()|, "% " is used. You can get the
effective prompt text for a buffer, with |prompt_getprompt()|.
The user can go to Normal mode and navigate through the buffer. This can be
useful to see older output or copy text.
By default during prompt insert-mode, the CTRL-W key can be used to start
a window command, such as CTRL-W w to switch to the next window. (Use
Shift-CTRL-W to delete a word). When leaving the window Insert mode will be
stopped. When coming back to the prompt window Insert mode will be restored.
The CTRL-W key can be used to start a window command, such as CTRL-W w to
switch to the next window. This also works in Insert mode (use Shift-CTRL-W
to delete a word). When leaving the window Insert mode will be stopped. When
coming back to the prompt window Insert mode will be restored.
Any command that starts Insert mode, such as "a", "i", "A" and "I", will move
the cursor to the last line. "A" will move to the end of the line, "I" to the
start of the line.
Example: start a shell in the background and prompt for the next shell
command, displaying shell output above the prompt: >vim
Here is an example for Unix. It starts a shell in the background and prompts
for the next shell command. Output from the shell is displayed above the
prompt. >vim
" Handles a line of user input.
func OnSubmit(text)
" Function handling a line of text that has been typed.
func TextEntered(text)
" Send the text to a shell with Enter appended.
call chansend(g:shell_job, [a:text, ''])
endfunc
" Handles output from the shell.
func OnOutput(channel, msg, name)
" Add shell output above the prompt.
call append(line('$') - 1, a:msg)
" Function handling output from the shell: Add it above the prompt.
func GotOutput(channel, msg, name)
call append(line("$") - 1, a:msg)
endfunc
" Handles the shell exit.
" Function handling the shell exits: close the window.
func JobExit(job, status, event)
quit!
endfunc
" Start a shell in the background.
let shell_job = jobstart(['/bin/sh'], #{
\ on_stdout: function('OnOutput'),
\ on_stderr: function('OnOutput'),
let shell_job = jobstart(["/bin/sh"], #{
\ on_stdout: function('GotOutput'),
\ on_stderr: function('GotOutput'),
\ on_exit: function('JobExit'),
\ })
new
set buftype=prompt
let buf = bufnr('')
call prompt_setcallback(buf, function('OnSubmit'))
call prompt_setprompt(buf, 'shell command: ')
call prompt_setcallback(buf, function("TextEntered"))
call prompt_setprompt(buf, "shell command: ")
" Start accepting shell commands.
" start accepting shell commands
startinsert
<
vim:tw=78:ts=8:et:sw=4:ft=help:norl:
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -142,16 +142,13 @@ CTRL-R {register} *c_CTRL-R* *c_<C-R>*
typing CTRL-R and the second character '"' will be displayed
to indicate that you are expected to enter the name of a
register.
When used with named or clipboard registers (A-Z,a-z,0-9,+)
text is inserted literally like pasting with "p". For other
registers, the text is inserted as if you typed it, but
mappings and abbreviations are not used. Command-line
completion through 'wildchar' is not triggered though. And
characters that end the command line are inserted literally
(<Esc>, <CR>, <NL>, <C-C>). A <BS> or CTRL-W could still end
the command line though, and remaining characters will then be
interpreted in another mode, which might not be what you
intended.
The text is inserted as if you typed it, but mappings and
abbreviations are not used. Command-line completion through
'wildchar' is not triggered though. And characters that end
the command line are inserted literally (<Esc>, <CR>, <NL>,
<C-C>). A <BS> or CTRL-W could still end the command line
though, and remaining characters will then be interpreted in
another mode, which might not be what you intended.
Special registers:
'"' the unnamed register, containing the text of
the last delete or yank
@@ -179,9 +176,7 @@ CTRL-R {register} *c_CTRL-R* *c_<C-R>*
sure the expression evaluates to an empty
string. E.g.: >
<C-R><C-R>=setcmdpos(2)[-1]<CR>
< You can use this to insert a register as
typed with CTRL-R =@reg.
See |registers| about registers.
< See |registers| about registers.
Implementation detail: When using the |expression| register
and invoking setcmdpos(), this sets the position before
inserting the resulting string. Use CTRL-R CTRL-R to set the
@@ -393,7 +388,7 @@ CTRL-D List names that match the pattern in front of the cursor.
to the end.
The 'wildoptions' option can be set to "tagfile" to list the
file of matching tags.
*c_CTRL-I* *c_wildchar* *c_<Tab>* */_<Tab>*
*c_CTRL-I* *c_wildchar* *c_<Tab>*
'wildchar' option
A match is done on the pattern in front of the cursor. The
match (if there are several, the first match) is inserted
@@ -403,10 +398,6 @@ CTRL-D List names that match the pattern in front of the cursor.
again and there were multiple matches, the next
match is inserted. After the last match, the first is used
again (wrap around).
In search context use <CTRL-V><Tab> or "\t" to search for a
literal <Tab> instead of triggering completion.
The behavior can be changed with the 'wildmode' option.
*c_<S-Tab>*
<S-Tab> Like 'wildchar' or <Tab>, but begin with the last match and
@@ -439,7 +430,7 @@ CTRL-G When 'incsearch' is set, entering a search pattern for "/" or
"?" and the current match is displayed then CTRL-G will move
to the next match (does not take |search-offset| into account)
Use CTRL-T to move to the previous match. Hint: on a regular
keyboard G is below T.
keyboard T is above G.
*c_CTRL-T* */_CTRL-T*
CTRL-T When 'incsearch' is set, entering a search pattern for "/" or
"?" and the current match is displayed then CTRL-T will move
@@ -456,8 +447,6 @@ When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
ending up back to what was typed. If the first match is not what you wanted,
you can use <S-Tab> or CTRL-P to go straight back to what you typed.
See also |wildtrigger()|.
The 'wildmenu' option can be set to show the matches just above the command
line.
@@ -575,6 +564,7 @@ that see the '"' as part of their argument:
:menu (and the like)
:mkspell
:normal
:ownsyntax
:popup
:registers
:return
@@ -947,6 +937,14 @@ Note: these are typed literally, they are not special keys!
events).
When the match is with a file name, it is expanded to the
full path.
*:<sfile>* *<sfile>*
<sfile> When executing a `:source` command, is replaced with the
file name of the sourced file. *E498*
When executing a function, is replaced with the call stack,
as with <stack> (this is for backwards compatibility, using
<stack> or <script> is preferred).
Note that filename-modifiers are useless when <sfile> is
not used inside a script.
*:<stack>* *<stack>*
<stack> is replaced with the call stack, using
"function {function-name}[{lnum}]" for a function line
@@ -954,7 +952,7 @@ Note: these are typed literally, they are not special keys!
".." in between items. E.g.:
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
If there is no call stack you get error *E489* .
*:<script>* *<script>* *E498*
*:<script>* *<script>*
<script> When executing a `:source` command, is replaced with the file
name of the sourced file. When executing a function, is
replaced with the file name of the script where it is
@@ -973,7 +971,7 @@ Note: these are typed literally, they are not special keys!
*filename-modifiers*
*:_%:* *::8* *::p* *::.* *::~* *::h* *::t* *::r* *::e* *::s* *::gs* *::S*
*%:8* *%:p* *%:.* *%:~* *%:h* *%:t* *%:r* *%:e* *%:s* *%:gs* *%:S*
The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<script>",
The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<sfile>",
"<afile>" or "<abuf>". They are also used with the |fnamemodify()| function.
These modifiers can be given, in this order:
:p Make file name a full path. Must be the first modifier. Also
@@ -1244,10 +1242,8 @@ Example: >
:au CmdwinLeave : let &cpt = b:cpt_save
This sets 'complete' to use completion in the current window for |i_CTRL-N|.
Another example: >
:au CmdwinEnter [/\?] startinsert
:au CmdwinEnter [/?] startinsert
This will make Vim start in Insert mode in the command-line window.
Note: The "?" needs to be escaped, as this is a |file-pattern|. See also
|cmdline-autocompletion|.
*cmdline-char* *cmdwin-char*
The character used for the pattern indicates the type of command-line:

View File

@@ -160,4 +160,5 @@ In WinDbg: choose Open Crash Dump on the File menu. Follow the instructions in
Visual Studio 2017 Community Edition can be downloaded for free from:
https://visualstudio.microsoft.com/downloads/
=========================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -12,42 +12,6 @@ They should not be used in new scripts, and old scripts should be updated.
==============================================================================
Deprecated features
------------------------------------------------------------------------------
DEPRECATED IN 0.12 *deprecated-0.12*
API
• todo
DIAGNOSTICS
• "float" in |vim.diagnostic.JumpOpts|. Use "on_jump" instead.
• "float" in |vim.diagnostic.Opts.Jump|. Use "on_jump" instead.
HIGHLIGHTS
• *:ownsyntax* *w:current_syntax* Use 'winhighlight' instead.
LSP
• *vim.lsp.client_is_stopped()* Use |vim.lsp.get_client_by_id()| instead.
• *vim.lsp.util.stylize_markdown()* Use |vim.treesitter.start()| with
`vim.wo.conceallevel = 2`.
• *vim.lsp.log.should_log()* Use |vim.lsp.log.set_format_func()| instead
and return `nil` to omit entries from the logfile.
• *vim.lsp.semantic_tokens.start()* Use `vim.lsp.semantic_tokens.enable(true)` instead
• *vim.lsp.semantic_tokens.stop()* Use `vim.lsp.semantic_tokens.enable(false)` instead
• *vim.lsp.set_log_level()* Use `vim.lsp.log.set_level()` instead
• *vim.lsp.get_log_path()* Use `vim.lsp.log.get_filename()` instead
LUA
• *vim.diff()* Renamed to |vim.text.diff()|
VIMSCRIPT
• todo
------------------------------------------------------------------------------
DEPRECATED IN 0.11 *deprecated-0.11*
@@ -102,7 +66,7 @@ LUA
• vim.validate(opts: table) Use form 1. See |vim.validate()|.
VIMSCRIPT
• *termopen()* Use |jobstart()| with `{term: v:true}`.
• *termopen()* Use |jobstart() with `{term: v:true}`.
------------------------------------------------------------------------------
DEPRECATED IN 0.10 *deprecated-0.10*
@@ -334,12 +298,13 @@ UI EXTENSIONS
• *term_background* Unused. The terminal background color is now detected
by the Nvim core directly instead of the TUI.
VIMSCRIPT
• *<sfile>* Use |<script>| or |<stack>| instead.
VARIABLES
• *b:terminal_job_pid* Use `jobpid(&channel)` instead.
• *b:terminal_job_id* Use `&channel` instead. To access in non-current buffer:
• Lua: `vim.bo[bufnr].channel`
• Vimscript: `getbufvar(bufnr, '&channel')`
VIMSCRIPT
• *buffer_exists()* Obsolete name for |bufexists()|.
• *buffer_name()* Obsolete name for |bufname()|.
• *buffer_number()* Obsolete name for |bufnr()|.

View File

@@ -53,27 +53,6 @@ Other references:
- https://github.com/neovim/neovim/pull/21605
==============================================================================
API
*dev-api-fast*
API functions and Vimscript "eval" functions may be marked as |api-fast| which
means they are safe to call in Lua callbacks and other scenarios. A functions
CANNOT be marked as "fast" if could trigger `os_breakcheck()`, which may
"yield" the current execution and start a new execution of code not expecting
this:
- accidentally recursing into a function not expecting this.
- changing (global) state without restoring it before returning to the
"yielded" callsite.
In practice, this means any code that could trigger `os_breakcheck()` cannot
be "fast". For example, commit 3940c435e405 fixed such a bug with
`nvim__get_runtime` by explicitly disallowing `os_breakcheck()` via the
`EW_NOBREAK` flag.
Common examples of non-fast code: regexp matching, wildcard expansion,
expression evaluation.
==============================================================================

View File

@@ -255,7 +255,8 @@ functions. >c
Integration with declarations generator ~
Every C file must contain #include of the generated header file.
Every C file must contain #include of the generated header file, guarded by
#ifdef INCLUDE_GENERATED_DECLARATIONS.
Include must go after other #includes and typedefs in .c files and after
everything else in header files. It is allowed to omit #include in a .c file
@@ -271,7 +272,9 @@ contain only non-static function declarations. >c
typedef int FooType;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "foo.c.generated.h"
#endif
@@ -281,7 +284,9 @@ contain only non-static function declarations. >c
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "foo.h.generated.h"
#endif
64-bit Portability ~
@@ -896,8 +901,8 @@ Return Values ~
Do not needlessly surround the `return` expression with parentheses.
Use parentheses in `return expr;` only where you would also use them in
`x = expr;`. >c
Use parentheses in `return expr`; only where you would use them in `x =
expr;`. >c
return result;
return (some_long_condition && another_condition);

View File

@@ -171,8 +171,8 @@ USING GDBSERVER IN TMUX
Consider using a custom makefile
https://github.com/neovim/neovim/blob/master/BUILD.md#custom-makefile to
quickly start debugging sessions using the `gdbserver` method mentioned above.
This example `local.mk` will create the debugging session when you type
`make debug`.
This example `local.mk` will create the debugging session when you type `make
debug`.
>make
.PHONY: dbg-start dbg-attach debug build

View File

@@ -311,7 +311,7 @@ Nvim's filetype detection behavior matches Vim, but is implemented as part of
|vim.filetype| (see `$VIMRUNTIME/lua/vim/filetype.lua`). The logic is encoded in
three tables, listed in order of precedence (the first match is returned):
1. `filename` for literal full path or basename lookup;
2. `pattern` for matching filenames or paths against |lua-pattern|s, optimized
2. `pattern` for matching filenames or paths against |lua-patterns|, optimized
for fast lookup;
3. `extension` for literal extension lookup.

View File

@@ -201,7 +201,7 @@ Docstring format:
- Markdown is supported.
- Tags are written as `[tag]()`.
- References are written as `[tag]`
- Use "```" for code samples.
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
Example: the help for |nvim_open_win()| is generated from a docstring defined
@@ -245,7 +245,7 @@ Docstring format:
- Markdown is supported.
- Tags are written as `[tag]()`.
- References are written as `[tag]`
- Use "```" for code samples.
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
- Use `@since <api-level>` to note the |api-level| when the function became
"stable". If `<api-level>` is greater than the current stable release (or
@@ -353,7 +353,7 @@ Where possible, these patterns apply to _both_ Lua and the API:
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
- Any function signature that accepts a callback (example: |table.foreach()|)
should place it as the LAST parameter (after opts), if possible (or ALWAYS
for |continuation|s——functions called exactly once).
for "continuation callbacks"—functions called exactly once).
- Improves readability by placing the less "noisy" arguments near the start.
- Consistent with luv.
- Useful for future async lib which transforms functions of the form
@@ -426,9 +426,6 @@ Use existing common {verb} names (actions) if possible:
- add: Appends or inserts into a collection
- attach: Listens to something to get events from it (TODO: rename to "on"?)
- call: Calls a function
- callback |continuation|: Function parameter (NOT a field) that
returns the result of an async function. Use the "on_…"
naming-convention for all other callbacks and event handlers.
- cancel: Cancels or dismisses an event or interaction, typically
user-initiated and without error. (Compare "abort", which
cancels and signals error/failure.)
@@ -444,15 +441,10 @@ Use existing common {verb} names (actions) if possible:
- get: Gets things. Two variants (overloads):
1. `get<T>(id: int): T` returns one item.
2. `get<T>(filter: dict): T[]` returns a list.
- has: Checks for the presence of an item, feature, etc.
- inspect: Presents a high-level, often interactive, view
- is_enabled: Checks if functionality is enabled.
- on_…: Handles events or async results, or registers such
a handler. |dev-name-events|
- open: Opens something (a buffer, window, …)
- parse: Parses something into a structured form
- request: Calls a remote (network, RPC) operation.
- send: Writes data or a message to a channel.
- set: Sets a thing (or group of things)
- start: Spin up a long-lived process. Prefer "enable" except when
"start" is obviously more appropriate.
@@ -460,10 +452,9 @@ Use existing common {verb} names (actions) if possible:
- try_{verb}: Best-effort operation, failure returns null or error obj
Do NOT use these deprecated verbs:
- contains: Prefer "has".
- disable: Prefer `enable(enable: boolean)`.
- exit: Prefer "cancel" (or "stop" if appropriate).
- is_disabled: Prefer `!is_enabled()`.
- is_disabled: Prefer `is_enabled()`.
- list: Redundant with "get"
- notify: Redundant with "print", "echo"
- show: Redundant with "print", "echo"
@@ -484,6 +475,7 @@ everywhere, not "buffer" in some places and "buf" in others.
Do NOT use these deprecated nouns:
- buffer Use "buf" instead
- callback Use on_foo instead
- command Use "cmd" instead
- window Use "win" instead
@@ -501,14 +493,6 @@ Use this format to name API (RPC) events: >
Example: >
nvim_buf_changedtick_event
<
*continuation*
A "continuation" is implemented as a callback function that returns the result
of an async function and is called exactly once. Often accepts `err` as the
first parameter, to avoid erroring on the main thread. Example: >
foo(…, callback: fun(err, …))
Use the name `callback` only for a continuation. All other callbacks and event
handlers should be named with the |dev-name-events| "on_…" convention.
*dev-api-name*
Use this format to name new RPC |API| functions: >
nvim_{topic}_{verb}_{arbitrary-qualifiers}
@@ -682,8 +666,6 @@ External UIs are expected to implement these common features:
the user).
- Support the text decorations/attributes given by |ui-event-hl_attr_define|.
The "url" attr should be presented as a clickable hyperlink.
- Handle the "restart" UI event so that |:restart| works.
- Detect capslock and show an indicator if capslock is active.
vim:tw=78:ts=8:sw=4:et:ft=help:norl:

View File

@@ -69,16 +69,6 @@ Functions that take a severity as an optional parameter (e.g.
<
This form allows users to filter for specific severities
==============================================================================
DEFAULTS *diagnostic-defaults*
These diagnostic keymaps are created unconditionally when Nvim starts:
- `]d` jumps to the next diagnostic in the buffer. |]d-default|
- `[d` jumps to the previous diagnostic in the buffer. |[d-default|
- `]D` jumps to the last diagnostic in the buffer. |]D-default|
- `[D` jumps to the first diagnostic in the buffer. |[D-default|
- `<C-w>d` shows diagnostic at cursor in a floating window. |CTRL-W_d-default|
==============================================================================
HANDLERS *diagnostic-handlers*
@@ -190,28 +180,6 @@ the `virtual_lines` handler with the following keymap: >lua
end, { desc = 'Toggle diagnostic virtual_lines' })
<
*diagnostic-on-jump-example*
You can use the `on_jump` option from |vim.diagnostic.jump()| to show the
diagnostic that was jumped to using a specific handler. For example, the
following uses the `virtual_lines` handler when jumping to a diagnostic: >lua
local virt_lines_ns = vim.api.nvim_create_namespace 'on_diagnostic_jump'
--- @param diagnostic? vim.Diagnostic
--- @param bufnr integer
local function on_jump(diagnostic, bufnr)
if not diagnostic then return end
vim.diagnostic.show(
virt_lines_ns,
bufnr,
{ diagnostic },
{ virtual_lines = { current_line = true }, virtual_text = false }
)
end
vim.diagnostic.config({ jump = { on_jump = on_jump } })
<
*diagnostic-loclist-example*
Whenever the |location-list| is opened, the following `show` handler will show
the most recent diagnostics: >lua
@@ -301,26 +269,6 @@ DiagnosticVirtualTextHint
DiagnosticVirtualTextOk
Used for "Ok" diagnostic virtual text.
*hl-DiagnosticVirtualLinesError*
DiagnosticVirtualLinesError
Used for "Error" diagnostic virtual lines.
*hl-DiagnosticVirtualLinesWarn*
DiagnosticVirtualLinesWarn
Used for "Warn" diagnostic virtual lines.
*hl-DiagnosticVirtualLinesInfo*
DiagnosticVirtualLinesInfo
Used for "Info" diagnostic virtual lines.
*hl-DiagnosticVirtualLinesHint*
DiagnosticVirtualLinesHint
Used for "Hint" diagnostic virtual lines.
*hl-DiagnosticVirtualLinesOk*
DiagnosticVirtualLinesOk
Used for "Ok" diagnostic virtual lines.
*hl-DiagnosticUnderlineError*
DiagnosticUnderlineError
Used to underline "Error" diagnostics.
@@ -440,43 +388,27 @@ Example: >lua
Lua module: vim.diagnostic *diagnostic-api*
*vim.Diagnostic*
Extends: |vim.Diagnostic.Set|
*diagnostic-structure*
Diagnostics use the same indexing as the rest of the Nvim API (i.e.
0-based rows and columns). |api-indexing|
Fields: ~
• {bufnr} (`integer`) Buffer number
• {end_lnum} (`integer`) The final line of the diagnostic (0-indexed)
• {col} (`integer`) The starting column of the diagnostic
(0-indexed)
• {end_col} (`integer`) The final column of the diagnostic
(0-indexed)
• {severity} (`vim.diagnostic.Severity`) The severity of the
diagnostic |vim.diagnostic.severity|
• {namespace}? (`integer`)
*vim.Diagnostic.Set*
Diagnostics use the same indexing as the rest of the Nvim API (i.e.
0-based rows and columns). |api-indexing|
Fields: ~
• {bufnr}? (`integer`) Buffer number
• {lnum} (`integer`) The starting line of the diagnostic
(0-indexed)
• {col}? (`integer`, default: `0`) The starting column of the
diagnostic (0-indexed)
• {end_lnum}? (`integer`, default: `lnum`) The final line of the
diagnostic (0-indexed)
• {end_col}? (`integer`, default: `col`) The final column of the
diagnostic (0-indexed)
• {severity}? (`vim.diagnostic.Severity`, default: `vim.diagnostic.severity.ERROR`)
The severity of the diagnostic |vim.diagnostic.severity|
• {end_lnum}? (`integer`) The final line of the diagnostic (0-indexed)
• {col} (`integer`) The starting column of the diagnostic
(0-indexed)
• {end_col}? (`integer`) The final column of the diagnostic
(0-indexed)
• {severity}? (`vim.diagnostic.Severity`) The severity of the
diagnostic |vim.diagnostic.severity|
• {message} (`string`) The diagnostic text
• {source}? (`string`) The source of the diagnostic
• {code}? (`string|integer`) The diagnostic code
• {user_data}? (`any`) arbitrary data plugins can add
• {namespace}? (`integer`)
*vim.diagnostic.GetOpts*
A table with the following keys:
@@ -488,9 +420,6 @@ Lua module: vim.diagnostic *diagnostic-api*
specified line number.
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|diagnostic-severity|.
• {enabled}? (`boolean`, default: `nil`) Limit diagnostics to only
enabled or disabled. If nil, enablement is ignored. See
|vim.diagnostic.enable()|
*vim.diagnostic.JumpOpts*
Extends: |vim.diagnostic.GetOpts|
@@ -516,9 +445,13 @@ Lua module: vim.diagnostic *diagnostic-api*
file or not. Similar to 'wrapscan'.
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|diagnostic-severity|.
• {on_jump}? (`fun(diagnostic:vim.Diagnostic?, bufnr:integer)`)
Optional callback invoked with the diagnostic that was
jumped to.
• {float}? (`boolean|vim.diagnostic.Opts.Float`, default: `false`)
If `true`, call |vim.diagnostic.open_float()| after
moving. If a table, pass the table as the {opts}
parameter to |vim.diagnostic.open_float()|. Unless
overridden, the float will show diagnostics at the new
cursor position (as if "cursor" were passed to the
"scope" option).
• {winid}? (`integer`, default: `0`) Window ID
*vim.diagnostic.NS*
@@ -572,8 +505,7 @@ Lua module: vim.diagnostic *diagnostic-api*
Fields: ~
• {bufnr}? (`integer`, default: current buffer) Buffer number
to show diagnostics from.
• {namespace}? (`integer|integer[]`) Limit diagnostics to the given
namespace(s).
• {namespace}? (`integer`) Limit diagnostics to the given namespace
• {scope}? (`'line'|'buffer'|'cursor'|'c'|'l'|'b'`, default:
`line`) Show diagnostics from the whole buffer
(`buffer"`, the current cursor line (`line`), or the
@@ -631,8 +563,8 @@ Lua module: vim.diagnostic *diagnostic-api*
*vim.diagnostic.Opts.Jump*
Fields: ~
• {on_jump}? (`fun(diagnostic:vim.Diagnostic?, bufnr:integer)`)
Default value of the {on_jump} parameter of
• {float}? (`boolean|vim.diagnostic.Opts.Float`, default: false)
Default value of the {float} parameter of
|vim.diagnostic.jump()|.
• {wrap}? (`boolean`, default: true) Default value of the {wrap}
parameter of |vim.diagnostic.jump()|.
@@ -692,12 +624,8 @@ Lua module: vim.diagnostic *diagnostic-api*
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show
virtual text for diagnostics matching the given
severity |diagnostic-severity|
• {current_line}? (`boolean`) Show or hide diagnostics based on
the current cursor line. If `true`, only
diagnostics on the current cursor line are
shown. If `false`, all diagnostics are shown
except on the current cursor line. If `nil`, all
diagnostics are shown. (default `nil`)
• {current_line}? (`boolean`) Only show diagnostics for the
current line. (default `false`)
• {source}? (`boolean|"if_many"`) Include the diagnostic
source in virtual text. Use `'if_many'` to only
show sources if there is more than one
@@ -956,7 +884,7 @@ set({namespace}, {bufnr}, {diagnostics}, {opts}) *vim.diagnostic.set()*
Parameters: ~
• {namespace} (`integer`) The diagnostic namespace
• {bufnr} (`integer`) Buffer number
• {diagnostics} (`vim.Diagnostic.Set[]`) See |vim.Diagnostic.Set|.
• {diagnostics} (`vim.Diagnostic[]`) See |vim.Diagnostic|.
• {opts} (`vim.diagnostic.Opts?`) Display options to pass to
|vim.diagnostic.show()|. See |vim.diagnostic.Opts|.
@@ -965,8 +893,8 @@ setloclist({opts}) *vim.diagnostic.setloclist()*
Parameters: ~
• {opts} (`table?`) Configuration table with the following keys:
• {namespace}? (`integer[]|integer`) Only add diagnostics from
the given namespace(s).
• {namespace}? (`integer`) Only add diagnostics from the given
namespace.
• {winnr}? (`integer`, default: `0`) Window number to set
location list for.
• {open}? (`boolean`, default: `true`) Open the location list
@@ -975,19 +903,14 @@ setloclist({opts}) *vim.diagnostic.setloclist()*
"Diagnostics".
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|diagnostic-severity|.
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
function that takes a diagnostic as input and returns a
string or nil. If the return value is nil, the diagnostic is
not displayed in the location list. Else the output text is
used to display the diagnostic.
setqflist({opts}) *vim.diagnostic.setqflist()*
Add all diagnostics to the quickfix list.
Parameters: ~
• {opts} (`table?`) Configuration table with the following keys:
• {namespace}? (`integer[]|integer`) Only add diagnostics from
the given namespace(s).
• {namespace}? (`integer`) Only add diagnostics from the given
namespace.
• {open}? (`boolean`, default: `true`) Open quickfix list
after setting.
• {title}? (`string`) Title of quickfix list. Defaults to
@@ -995,11 +918,6 @@ setqflist({opts}) *vim.diagnostic.setqflist()*
title, it's updated. If not, a new quickfix list is created.
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|diagnostic-severity|.
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
function that takes a diagnostic as input and returns a
string or nil. If the return value is nil, the diagnostic is
not displayed in the quickfix list. Else the output text is
used to display the diagnostic.
*vim.diagnostic.show()*
show({namespace}, {bufnr}, {diagnostics}, {opts})
@@ -1019,23 +937,6 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
• {opts} (`vim.diagnostic.Opts?`) Display options. See
|vim.diagnostic.Opts|.
status({bufnr}) *vim.diagnostic.status()*
Returns formatted string with diagnostics for the current buffer. The
severities with 0 diagnostics are left out. Example `E:2 W:3 I:4 H:5`
To customise appearance, set diagnostic signs text with >lua
vim.diagnostic.config({
signs = { text = { [vim.diagnostic.severity.ERROR] = 'e', ... } }
})
<
Parameters: ~
• {bufnr} (`integer?`) Buffer number to get diagnostics from. Defaults
to 0 for the current buffer
Return: ~
(`string`)
toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Convert a list of diagnostics to a list of quickfix items that can be
passed to |setqflist()| or |setloclist()|.

View File

@@ -214,28 +214,14 @@ The diffs are highlighted with these groups:
|hl-DiffAdd| DiffAdd Added (inserted) lines. These lines exist in
this buffer but not in another.
|hl-DiffChange| DiffChange Changed lines.
|hl-DiffText| DiffText Changed text inside a Changed line. Exact
behavior depends on the `inline:` setting in
'diffopt'.
With `inline:` set to "simple", Vim finds the
first character that is different, and the
last character that is different (searching
from the end of the line). The text in
between is highlighted. This means that parts
in the middle that are still the same are
highlighted anyway. The 'diffopt' flags
"iwhite" and "icase" are used here.
With `inline:` set to "char" or "word", Vim
uses the internal diff library to perform a
detailed diff between the changed blocks and
highlight the exact difference between the
two. Will respect any 'diffopt' flag that
affects internal diff.
Not used when `inline:` is set to "none".
|hl-DiffTextAdd| DiffTextAdd Added text inside a Changed line. Similar to
DiffText, but used when there is no
corresponding text in other buffers. Not used
when `inline:` is set to "simple" or "none".
|hl-DiffText| DiffText Changed text inside a Changed line. Vim
finds the first character that is different,
and the last character that is different
(searching from the end of the line). The
text in between is highlighted. This means
that parts in the middle that are still the
same are highlighted anyway. The 'diffopt'
flags "iwhite" and "icase" are used here.
|hl-DiffDelete| DiffDelete Deleted lines. Also called filler lines,
because they don't really exist in this
buffer.
@@ -292,20 +278,18 @@ that the buffers will be equal within the specified range.
When no [range] is given, the diff at the cursor position or just above it is
affected. There can be deleted lines below the last line of the buffer. When
the cursor is on the last line in the buffer and there is no diff above this
line, and no [range] is given, the diff below the cursor position will be used
instead.
affected. When [range] is used, Vim tries to only put or get the specified
lines. When there are deleted lines, this may not always be possible.
When [range] is used, Vim tries to only put or get the specified lines. When
there are deleted lines, they will be used if they are between the lines
specified by [range].
There can be deleted lines below the last line of the buffer. When the cursor
is on the last line in the buffer and there is no diff above this line, the
":diffget" and "do" commands will obtain lines from the other buffer.
To be able to put or get those lines to/from another buffer in a [range] it's
allowed to use 0 and the last line number plus one. This command gets all
diffs from the other buffer: >
To be able to get those lines from another buffer in a [range] it's allowed to
use the last line number plus one. This command gets all diffs from the other
buffer: >
:0,$+1diffget
:1,$+1diffget
Note that deleted lines are displayed, but not counted as text lines. You
can't move the cursor into them. To fill the deleted lines with the lines
@@ -324,131 +308,9 @@ name or a part of a buffer name. Examples:
diff mode (e.g., "file.c.v2")
==============================================================================
5. Diff anchors *diff-anchors*
5. Diff options *diff-options*
Diff anchors allow you to control where the diff algorithm aligns and
synchronize text across files. Each anchor matches each other in each file,
allowing you to control the output of a diff.
This is useful when a change involves complicated edits. For example, if a
function was moved to another location and further edited. By default, the
algorithm aims to create the smallest diff, which results in that entire
function being considered to be deleted and added on the other side, making it
hard to see what the actual edit on it was. You can use diff anchors to pin
that function so the diff algorithm will align based on it.
To use it, set anchors using 'diffanchors' which is a comma-separated list of
{address} in each file, and then add "anchor" to 'diffopt'. Internaly, Vim
splits each file up into sections split by the anchors. It performs the diff
on each pair of sections separately before merging the results back.
Setting 'diffanchors' will update the diff immediately. If an anchor is tied
to a mark, and you change what the mark is pointed to, you need to manually
call |:diffupdate| afterwards to get the updated diff results.
Example:
Let's say we have the following files, side-by-side. We are interested in the
change that happened to the function `foo()`, which was both edited and moved.
File A: >
int foo() {
int n = 1;
return n;
}
int g = 1;
int bar(int a) {
a *= 2;
a += 3;
return a;
}
<File B: >
int bar(int a) {
a *= 2;
a += 3;
return a;
}
int foo() {
int n = 999;
return n;
}
int g = 1;
<
A normal diff will usually align the diff result as such: >
int foo() { |----------------
int n = 1; |----------------
return n; |----------------
} |----------------
|----------------
int g = 1; |----------------
|----------------
int bar(int a) {|int bar(int a) {
a *= 2; | a *= 2;
a += 3; | a += 3;
return a; | return a;
} |}
----------------|
----------------|int foo() {
----------------| int n = 999;
----------------| return n;
----------------|}
----------------|
----------------|int g = 1;
<
What we want is to instead ask the diff to align on `foo()`: >
----------------|int bar(int a) {
----------------| a *= 2;
----------------| a += 3;
----------------| return a;
----------------|}
----------------|
int foo() { |int foo() {
int n = 1; | int n = 999;
return n; | return n;
} |}
|
int g = 1; |int g = 1;
|----------------
int bar(int a) {|----------------
a *= 2; |----------------
a += 3; |----------------
return a; |----------------
} |----------------
<
Below are some ways of setting diff anchors to get the above result. In each
example, 'diffopt' needs to have `anchor` set for this to take effect.
Marks: Set the |'a| mark on the `int foo()` lines in each file first before
setting the anchors: >
set diffanchors='a
Pattern: Specify the anchor using a |pattern| (see |:/|). Here, we make sure
to always start search from line 1 for consistency: >
set diffanchors=1/int\ foo(/
<
Selection: Use visual mode to select the entire `foo()` function body in each
file. Here, we use two anchors. This does a better job of making sure only
the function bodies are anchored against each other but not the lines after
it. Note the `'>+1` below. The "+1" is necessary as we want the split to
happen below the last line of the function, not above: >
set diffanchors='<,'>+1
<
Manually set two anchors using line numbers via buffer-local options: >
setlocal diffanchors=1,5
wincmd w
setlocal diffanchors=7,11
<
==============================================================================
6. Diff options *diff-options*
Also see 'diffopt' and the "diff" item of 'fillchars'.
Also see |'diffopt'| and the "diff" item of |'fillchars'|.
*diff-slow* *diff_translations*
For very long lines, the diff syntax highlighting might be slow, especially

View File

@@ -1094,8 +1094,8 @@ the 1', 2' and 3' digraphs.
⌕ TR 2315 8981 TELEPHONE RECORDER
⌠ Iu 2320 8992 TOP HALF INTEGRAL
⌡ Il 2321 8993 BOTTOM HALF INTEGRAL
<[ 27E8 10040 LEFT MATHEMATICAL ANGLE BRACKET
⟩ ]> 27E9 10041 RIGHT MATHEMATICAL ANGLE BRACKET
</ 2329 9001 LEFT-POINTING ANGLE BRACKET
〉 /> 232A 9002 RIGHT-POINTING ANGLE BRACKET
␣ Vs 2423 9251 OPEN BOX
⑀ 1h 2440 9280 OCR HOOK
⑁ 3h 2441 9281 OCR CHAIR

View File

@@ -630,7 +630,7 @@ list of the current window.
buffer.
Also see |++opt| and |+cmd|.
:[count]arge[dit][!] [++opt] [+cmd] {name} ... *:arge* *:argedit*
:[count]arge[dit][!] [++opt] [+cmd] {name} .. *:arge* *:argedit*
Add {name}s to the argument list and edit it.
There is no check for duplicates, it is possible to
add a file to the argument list twice |:argded|.
@@ -645,7 +645,7 @@ list of the current window.
edited. No check for duplicates is done.
Also see |++opt| and |+cmd|.
:[count]arga[dd] {name} ... *:arga* *:argadd* *E479*
:[count]arga[dd] {name} .. *:arga* *:argadd* *E479*
:[count]arga[dd] *E1156*
Add the {name}s to the argument list. When {name} is
omitted add the current buffer name to the argument
@@ -676,7 +676,7 @@ list of the current window.
If your current file is a duplicate, your current file
will change to the original file index.
:argd[elete] {pattern} ... *:argd* *:argdelete* *E480* *E610*
:argd[elete] {pattern} .. *:argd* *:argdelete* *E480* *E610*
Delete files from the argument list that match the
{pattern}s. {pattern} is used like a file pattern,
see |file-pattern|. "%" can be used to delete the
@@ -714,14 +714,11 @@ list of the current window.
omitted the current entry is used.
Also see |++opt| and |+cmd|.
:[count]n[ext] [++opt] [+cmd] *:n* *:ne* *:next* *E165* *E163*
:[count]n[ext] [++opt] [+cmd] *:n* *:ne* *:next* *]a* *E165* *E163*
Edit [count] next file. This fails when changes have
been made and Vim does not want to |abandon| the
current buffer. Also see |++opt| and |+cmd|.
*]a*
]a Mapped to |:next|. |default-mappings|
:[count]n[ext]! [++opt] [+cmd]
Edit [count] next file, discard any changes to the
buffer. Also see |++opt| and |+cmd|.
@@ -743,22 +740,16 @@ list of the current window.
any changes to the buffer. Also see |++opt| and
|+cmd|.
:[count]prev[ious] [count] [++opt] [+cmd] *:prev* *:previous*
:[count]prev[ious] [count] [++opt] [+cmd] *:prev* *:previous* *[a*
Same as :Next. Also see |++opt| and |+cmd|.
*[a*
[a Mapped to |:previous|. |default-mappings|
*:rew* *:rewind*
*:rew* *:rewind* *[A*
:rew[ind] [++opt] [+cmd]
Start editing the first file in the argument list.
This fails when changes have been made and Vim does
not want to |abandon| the current buffer.
Also see |++opt| and |+cmd|.
*[A*
[A Mapped to |:rewind|. |default-mappings|
:rew[ind]! [++opt] [+cmd]
Start editing the first file in the argument list.
Discard any changes to the buffer. Also see |++opt|
@@ -768,16 +759,13 @@ list of the current window.
:fir[st][!] [++opt] [+cmd]
Other name for ":rewind".
*:la* *:last*
*:la* *:last* *]A*
:la[st] [++opt] [+cmd]
Start editing the last file in the argument list.
This fails when changes have been made and Vim does
not want to |abandon| the current buffer.
Also see |++opt| and |+cmd|.
*]A*
]A Mapped to |:last|. |default-mappings|
:la[st]! [++opt] [+cmd]
Start editing the last file in the argument list.
Discard any changes to the buffer. Also see |++opt|
@@ -960,9 +948,8 @@ Note: When the 'write' option is off, you are not able to write any file.
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
The default [range] for the ":w" command is the whole buffer (1,$). The |'[|
and |']| marks will be set to the [range] being used for the write command.
If you write the whole buffer, it is no longer considered changed. When you
The default [range] for the ":w" command is the whole buffer (1,$). If you
write the whole buffer, it is no longer considered changed. When you
write it to a different file with ":w somefile" it depends on the "+" flag in
'cpoptions'. When included, the write command will reset the 'modified' flag,
even though the buffer itself may still be different from its file.
@@ -1242,10 +1229,10 @@ MULTIPLE WINDOWS AND BUFFERS *window-exit*
*:confirm* *:conf*
:conf[irm] {command} Execute {command}, and use a dialog when an
operation has to be confirmed. Can be used on the
|:edit|, |:restart|, |:q|, |:qa| and |:w| commands
(the latter to override a read-only setting), and any
commands that can fail because of unsaved changes,
such as |:only|, |:buffer|, |:bdelete|, etc.
|:edit|, |:q|, |:qa| and |:w| commands (the latter to
override a read-only setting), and any commands that
can fail because of unsaved changes, such as |:only|,
|:buffer|, |:bdelete|, etc.
Examples: >
:confirm w foo
@@ -1316,15 +1303,9 @@ b:browsefilter variable. You would most likely set b:browsefilter in a
filetype plugin, so that the browse dialog would contain entries related to
the type of file you are currently editing. Disadvantage: This makes it
difficult to start editing a file of a different type. To overcome this, you
can add the following as the final filter on Windows: >
All Files\t(*.*)\t*\n
<
Or the following on other platforms, so that the user can still access any
desired file: >
All Files\t(*)\t*\n
<
may want to add "All Files (*.*)\t*\n" as the final filter on Windows or "All
Files (*)\t*\n" on other platforms, so that the user can still access any
desired file.
To avoid setting browsefilter when Vim does not actually support it, you can
use has("browsefilter"): >
@@ -1356,7 +1337,7 @@ exist, the next-higher scope in the hierarchy applies.
:cd[!] {path} Change the current directory to {path}.
If {path} is relative, it is searched for in the
directories listed in 'cdpath'.
directories listed in |'cdpath'|.
Clear any window-local directory.
Does not change the meaning of an already opened file,
because its full path name is remembered. Files from

View File

@@ -1,10 +1,10 @@
*vimeval.txt* Nvim
*eval.txt* Nvim
VIM REFERENCE MANUAL by Bram Moolenaar
Expression evaluation *vimscript* *expression* *expr* *E15* *eval* *eval.txt*
Expression evaluation *vimscript* *expression* *expr* *E15* *eval*
Using expressions is introduced in chapter 41 of the user manual |usr_41.txt|.
@@ -1813,7 +1813,7 @@ functions. Scripts can also define |user-function|s.
See |function-list| to browse functions by topic.
The alphabetic list of all builtin functions and details are in a separate
help file: |vimscript-functions|.
help file: |builtin-functions|.
==============================================================================
5. Defining functions *user-function*
@@ -2099,7 +2099,7 @@ text...
CODE
<
*E121*
:let {var-name} ... List the value of variable {var-name}. Multiple
:let {var-name} .. List the value of variable {var-name}. Multiple
variable names may be given. Special names recognized
here: *E738*
g: global variables
@@ -2116,6 +2116,7 @@ text...
# Number
* Funcref
:unl[et][!] {name} ... *:unlet* *:unl* *E108* *E795*
Remove the internal variable {name}. Several variable
names can be given, they are all removed. The name
@@ -2459,7 +2460,7 @@ text...
line and not see the "|" that separates the commands.
*:ec* *:echo*
:ec[ho] {expr1} ... Echoes each {expr1}, with a space in between. The
:ec[ho] {expr1} .. Echoes each {expr1}, with a space in between. The
first {expr1} starts on a new line.
Also see |:comment|.
Use "\n" to start a new line. Use "\r" to move the
@@ -2492,7 +2493,7 @@ text...
level.
*:echon*
:echon {expr1} ... Echoes each {expr1}, without anything added. Also see
:echon {expr1} .. Echoes each {expr1}, without anything added. Also see
|:comment|.
Uses the highlighting set by the `:echohl` command.
Cannot be followed by a comment.
@@ -2523,7 +2524,7 @@ text...
otherwise all following echo's will be highlighted.
*:echom* *:echomsg*
:echom[sg] {expr1} ... Echo the expression(s) as a true message, saving the
:echom[sg] {expr1} .. Echo the expression(s) as a true message, saving the
message in the |message-history|.
Spaces are placed between the arguments as with the
`:echo` command. But unprintable characters are
@@ -2538,9 +2539,8 @@ text...
:echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
< See |:echo-redraw| to avoid the message disappearing
when the screen is redrawn.
*:echoe* *:echoerr*
:echoe[rr] {expr1} ... Echo the expression(s) as an error message, saving the
:echoe[rr] {expr1} .. Echo the expression(s) as an error message, saving the
message in the |message-history|. When used in a
script or function the line number will be added.
Spaces are placed between the arguments as with the
@@ -2572,7 +2572,7 @@ text...
*:exe* *:execute*
:exe[cute] {expr1} ... Executes the string that results from the evaluation
:exe[cute] {expr1} .. Executes the string that results from the evaluation
of {expr1} as an Ex command.
Multiple arguments are concatenated, with a space in
between. To avoid the extra space use the ".."
@@ -3774,7 +3774,7 @@ This is not allowed when the textlock is active:
- etc.
==============================================================================
Vim script library *vimscript-library*
Vim script library *vim-script-library*
Vim comes bundled with a Vim script library, that can be used by runtime,
script authors. Currently, it only includes very few functions, but it may

View File

@@ -187,19 +187,20 @@ Run |:checkhealth| in Nvim for automatic diagnosis.
Other hints:
- Read |provider-python| to learn how to install `pynvim`.
- Be sure you have the latest version of the `pynvim` Python module: >bash
uv tool install --upgrade pynvim
<
See |provider-python| for other installation options.
- If you're manually creating a Python virtual environment for the `pynvim` module
- The python `neovim` module was renamed to `pynvim` (long ago).
- If you're using pyenv or virtualenv for the `pynvim` module
https://pypi.org/project/pynvim/, you must set `g:python3_host_prog` to
the virtualenv's interpreter path.
- Read |provider-python|.
- Be sure you have the latest version of the `pynvim` Python module: >bash
python -m pip install setuptools
python -m pip install --upgrade pynvim
python3 -m pip install --upgrade pynvim
<
- Try with `nvim -u NORC` to make sure your config (|init.vim|) isn't causing a
problem. If you get `E117: Unknown function`, that means there's a runtime
issue: |faq-runtime|.
- The python `neovim` module was renamed to `pynvim` (long ago).
:CHECKHEALTH REPORTS E5009: INVALID $VIMRUNTIME ~
@@ -449,7 +450,10 @@ grow and enhance it. Changing the rules of Lua gains nothing in this context.
WILL NEOVIM TRANSLATE VIMSCRIPT TO LUA, INSTEAD OF EXECUTING VIMSCRIPT DIRECTLY? ~
We have no plans for transpiling Vimscript. It was explored in https://github.com/tjdevries/vim9jit
- We are experimenting with vim9jit https://github.com/tjdevries/vim9jit to
transpile Vim9script (Vim9's Vimscript variant) to Lua and have used this to
port Vim9 plugins https://github.com/neovim/neovim/pull/21662 to Nvim Lua.
- We have no plans for transpiling legacy Vimscript.
ARE PLUGIN AUTHORS ENCOURAGED TO PORT THEIR PLUGINS FROM VIMSCRIPT TO LUA? DO YOU PLAN ON SUPPORTING VIMSCRIPT INDEFINITELY? (#1152) ~
@@ -464,8 +468,4 @@ emphatically a fork of Vim in order to leverage the work already spent on
thousands of Vim plugins, while enabling new types of plugins and
integrations.
That being said, reimplementing legacy plugins in Lua in order to make use of
Nvim API and to integrate with Nvim-specific features such as treesitter can
be worthwhile.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -156,8 +156,6 @@ variables can be used to overrule the filetype used for certain extensions:
`*.inc` g:filetype_inc
`*.lsl` g:filetype_lsl
`*.m` g:filetype_m |ft-mathematica-syntax|
`*[mM]makefile,*.mk,*.mak,[mM]akefile*`
g:make_flavor |ft-make-syntax|
`*.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md`
g:filetype_md |ft-pandoc-syntax|
`*.mod` g:filetype_mod
@@ -264,7 +262,7 @@ D. If your filetype can only be detected by inspecting the contents of the
item of the 'runtimepath' option. Example for Unix: >
:!mkdir -p ~/.config/nvim
<
2. Create a Vim script file for doing this. Example: >
2. Create a vim script file for doing this. Example: >
if did_filetype() " filetype already set..
finish " ..don't do these checks
endif
@@ -625,16 +623,6 @@ possibilities: >
The `:Cycle` command is also mapped to the CTRL-A and CTRL-X keys.
For details, see `git-rebase --help`.
GLEAM *ft-gleam-plugin*
By default the following options are set for the recommended gleam style: >
setlocal expandtab shiftwidth=2 softtabstop=2
To disable this behavior, set the following variable in your vimrc: >
let g:gleam_recommended_style = 0
GO *ft-go-plugin*
By default the following options are set, based on Golang official docs: >
@@ -661,32 +649,6 @@ HARE *ft-hare*
Since the text for this plugin is rather long it has been put in a separate
file: |ft_hare.txt|.
HTML *ft-html-plugin*
Tag folding poses a few difficulties. Many elements, e.g. `blockquote`, are
always delimited by start and end tags; end tags for some elements, e.g. `p`,
can be omitted in certain contexts; void elements, e.g. `hr`, have no end tag.
Although the rules for supporting omissible end tags are ad-hoc and involved
[0], they apply to elements in scope. Assuming syntactical wellformedness, an
end tag can be associated with its nearest matching start tag discoverable in
scope [1] and towards the beginning of a file, whereas all unbalanced tags and
inlined tags can be disregarded. Having syntax highlighting in effect, tag
folding using the |fold-expr| method can be enabled with: >
let g:html_expr_folding = 1
<
By default, tag folding will be redone from scratch after each occurrence of
a |TextChanged| or an |InsertLeave| event. Such frequency may not be desired,
especially for large files, and this recomputation can be disabled with: >
let g:html_expr_folding_without_recomputation = 1
doautocmd FileType
<
To force another recomputation, do: >
unlet! b:foldsmap
normal zx
<
[0] https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
[1] https://en.wikipedia.org/wiki/Dangling_else
IDRIS2 *ft-idris2-plugin*
By default the following options are set: >
@@ -823,8 +785,8 @@ Variables:
For example in C one usually wants section 3 or 2: >
:let b:man_default_sections = '3,2'
*g:man_hardwrap* Hard-wrap to $MANWIDTH or window width if $MANWIDTH is
empty or larger than the window width. Enabled by
default. Set |FALSE| to enable soft wrapping.
empty. Enabled by default. Set |FALSE| to enable soft
wrapping.
To use Nvim as a manpager: >bash
export MANPAGER='nvim +Man!'
@@ -1155,13 +1117,6 @@ functions with [[ and ]]. Move around comments with ]" and [".
The mappings can be disabled with: >
let g:no_vim_maps = 1
YAML *ft-yaml-plugin*
By default, the YAML filetype plugin enables the following options: >
setlocal shiftwidth=2 softtabstop=2
To disable this, set the following variable: >
let g:yaml_recommended_style = 0
ZIG *ft-zig-plugin*

View File

@@ -632,17 +632,14 @@ what you type!
When using an operator, a closed fold is included as a whole. Thus "dl"
deletes the whole closed fold under the cursor.
For Ex commands that operate on buffer lines, the range is adjusted to always
For Ex commands that work on buffer lines the range is adjusted to always
start at the first line of a closed fold and end at the last line of a closed
fold. Thus, this command: >
fold. Thus this command: >
:s/foo/bar/g
when used with the cursor on a closed fold, will replace "foo" with "bar" in
all lines of the fold.
This does not happen for |:folddoopen| and |:folddoclosed|.
Note that for some Ex commands like |:source| the range is only adjusted when
using a two line specifiers [range].
When editing a buffer that has been edited before, the last used folding
settings are used again. For manual folding the defined folds are restored.
For all folding methods the manually opened and closed folds are restored.
@@ -650,4 +647,5 @@ If this buffer has been edited in this window, the values from back then are
used. Otherwise the values from the window where the buffer was edited last
are used.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -76,8 +76,8 @@ The Ada plug-in provides support for:
- user completion (|i_CTRL-X_CTRL-U|)
- tag searches (|tagsrch.txt|)
- Quick Fix (|quickfix.txt|)
- backspace handling ('backspace')
- comment handling ('comments', 'commentstring')
- backspace handling (|'backspace'|)
- comment handling (|'comments'|, |'commentstring'|)
The plug-in only activates the features of the Ada mode whenever an Ada
file is opened and adds Ada related entries to the main and pop-up menu.
@@ -197,7 +197,7 @@ g:gnat.Project_File string
*g:gnat.Make_Command*
g:gnat.Make_Command string
External command used for |g:gnat.Make()| ('makeprg').
External command used for |g:gnat.Make()| (|'makeprg'|).
*g:gnat.Pretty_Program*
g:gnat.Pretty_Program string
@@ -213,7 +213,7 @@ g:gnat.Tags_Command string
*g:gnat.Error_Format*
g:gnat.Error_Format string
Error format ('errorformat')
Error format (|'errorformat'|)
------------------------------------------------------------------------------
4.2 Dec Ada ~
@@ -243,11 +243,11 @@ g:decada.Unit_Name() function
*g:decada.Make_Command*
g:decada.Make_Command string
External command used for |g:decada.Make()| ('makeprg').
External command used for |g:decada.Make()| (|'makeprg'|).
*g:decada.Error_Format*
g:decada.Error_Format string
Error format ('errorformat').
Error format (|'errorformat'|).
==============================================================================
5. References ~
@@ -507,4 +507,6 @@ taglist.vim
The GNU Ada Project distribution (http://gnuada.sourceforge.net) of Vim
contains all of the above.
vim:tw=78:ts=8:noet:ft=help:norl:
==============================================================================
vim: textwidth=78 nowrap tabstop=8 shiftwidth=4 softtabstop=4 noexpandtab
vim: filetype=help

View File

@@ -73,4 +73,5 @@ The maximum search depth can be set to any integer, but using values higher
than 2 is not recommended, and will likely provide no tangible benefit in most
situations.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -60,4 +60,5 @@ Many other distributions are available for Windows like
https://chocolatey.org/packages/less/. Make sure `less` is in a directory
listed in the `PATH` environment variable, which chocolatey above does.
------------------------------------------------------------------------------
vim:ft=help:

View File

@@ -160,18 +160,7 @@ g:rustfmt_emit_files ~
provided) instead of '--write-mode=overwrite'. >vim
let g:rustfmt_emit_files = 0
<
*g:rustfmt_detect_version*
g:rustfmt_detect_version ~
When set to 1, will try to parse the version output from "rustfmt".
Disabled by default for performance reasons >vim
let g:rustfmt_detect_version = 1
<
*g:rustfmt_find_toml*
g:rustfmt_emit_files ~
When set to 1, will try to find "rustfmt.toml" file by searching from
current path upwards. Disabled by default for performance reasons >vim
let g:rustfmt_find_toml = 1
<
*g:rust_playpen_url*
g:rust_playpen_url ~
Set this option to override the url for the playpen to use: >vim

View File

@@ -172,7 +172,7 @@ with comments: >
------------------------------------------------------------------------------
1.4 Macros *sql-macros*
Vim's feature to find macro definitions, 'define', is supported using this
Vim's feature to find macro definitions, |'define'|, is supported using this
regular expression: >
\c\<\(VARIABLE\|DECLARE\|IN\|OUT\|INOUT\)\>
@@ -249,7 +249,7 @@ key to complete the optional parameter.
After typing the function name and a space, you can use the completion to
supply a parameter. The function takes the name of the Vim script you want to
source. Using the |cmdline-completion| feature, the SQLSetType function will
search the 'runtimepath' for all Vim scripts with a name containing "sql".
search the |'runtimepath'| for all Vim scripts with a name containing "sql".
This takes the guess work out of the spelling of the names. The following are
examples: >
:SQLSetType
@@ -412,7 +412,7 @@ Here are some examples of the entries which are pulled from the syntax files: >
Dynamic mode populates the popups with data directly from a database. In
order for the dynamic feature to be enabled you must have the dbext.vim
plugin installed, (https://www.vim.org/scripts/script.php?script_id=356).
plugin installed, (https://vim.sourceforge.net/script.php?script_id=356).
Dynamic mode is used by several features of the SQL completion plugin.
After installing the dbext plugin see the dbext-tutorial for additional
@@ -496,7 +496,7 @@ depending on the syntax file you are using. The SQL Anywhere syntax file
Dynamic features ~
To take advantage of the dynamic features you must first install the
dbext.vim plugin (https://www.vim.org/scripts/script.php?script_id=356). It
dbext.vim plugin (https://vim.sourceforge.net/script.php?script_id=356). It
also comes with a tutorial. From the SQL completion plugin's perspective,
the main feature dbext provides is a connection to a database. dbext
connection profiles are the most efficient mechanism to define connection
@@ -760,7 +760,7 @@ Step 1 ~
Begins by editing a Perl file. Vim automatically sets the filetype to
"perl". By default, Vim runs the appropriate filetype file
ftplugin/perl.vim. If you are using the syntax completion plugin by following
the directions at |ft-syntax-omni| then the 'omnifunc' option has been set to
the directions at |ft-syntax-omni| then the |'omnifunc'| option has been set to
"syntax#Complete". Pressing <C-X><C-O> will display the omni popup containing
the syntax items for Perl.
@@ -772,7 +772,7 @@ maps for SQL completion, see |sql-completion-maps|. Now these maps have
been created and the SQL completion plugin has been initialized. All SQL
syntax items have been cached in preparation. The SQL filetype script detects
we are attempting to use two different completion plugins. Since the SQL maps
begin with <C-C>, the maps will toggle the 'omnifunc' when in use. So you
begin with <C-C>, the maps will toggle the |'omnifunc'| when in use. So you
can use <C-X><C-O> to continue using the completion for Perl (using the syntax
completion plugin) and <C-C> to use the SQL completion features.

View File

@@ -17,8 +17,6 @@ TUI and GUI (assuming the UI supports the given feature). See |TUI| for notes
specific to the terminal UI. Help tags with the "gui-" prefix refer to UI
features, whereas help tags with the "ui-" prefix refer to the |ui-protocol|.
Type |gO| to see the table of contents.
==============================================================================
Third-party GUIs *third-party-guis* *vscode*
@@ -36,6 +34,8 @@ a Nvim GUI.
- VimR (macOS) https://github.com/qvacua/vimr
- Others https://github.com/neovim/neovim/wiki/Related-projects#gui
Type |gO| to see the table of contents.
==============================================================================
Starting the GUI *gui-config* *gui-start*
@@ -64,50 +64,7 @@ Stop or detach the current UI
the channel to be closed, it may be (incorrectly) reported as
an error.
Note: Not supported on Windows yet.
------------------------------------------------------------------------------
Restart Nvim
*:restart*
:restart [+cmd] [command]
Restarts Nvim.
1. Stops Nvim using `:qall!` (or |+cmd|, if given).
2. Starts a new Nvim server using the same |v:argv|,
optionally running [command] at startup. |-c|
3. Attaches the current UI to the new Nvim server. Other UIs
(if any) will not reattach on restart (this may change in
the future).
Use with `:confirm` to prompt if changes have been made.
Example: stop with `:qall!`, then restart: >
:restart +qall!
< Example: restart and restore the current session: >
:mksession! Session.vim | restart source Session.vim
< Example: restart and update plugins: >
:restart +qall! lua vim.pack.update()
<
Note: Only works if the UI and server are on the same system.
Note: If the UI hasn't implemented the "restart" UI event,
this command is equivalent to `:qall!`.
------------------------------------------------------------------------------
Connect UI to a different server
*:connect*
:connect {address}
Detaches the UI from the server it is currently attached to
and attaches it to the server at {address} instead.
Note: If the current UI hasn't implemented the "connect" UI
event, this command is equivalent to |:detach|.
:connect! {address}
Same as |:connect| but it also stops the detached server if
no other UI is currently attached to it.
Note: Not supported on Windows, currently.
------------------------------------------------------------------------------
GUI commands

View File

@@ -9,18 +9,18 @@
==============================================================================
Checkhealth *vim.health* *health*
vim.health is a minimal framework to help users troubleshoot configuration and
any other environment conditions that a plugin might care about. Nvim ships
with healthchecks for configuration, performance, python support, ruby
support, clipboard support, and more.
To run all healthchecks, use: >vim
:checkhealth
<
Plugin authors are encouraged to write new healthchecks. |health-dev|
COMMANDS *health-commands*
*:che* *:checkhealth*
@@ -56,6 +56,7 @@ Local mappings in the healthcheck buffer:
q Closes the window.
Global configuration:
*g:health*
g:health Dictionary with the following optional keys:
- `style` (`'float'|nil`) Set to "float" to display :checkhealth in
@@ -64,26 +65,16 @@ g:health Dictionary with the following optional keys:
Example: >lua
vim.g.health = { style = 'float' }
Local configuration:
Checkhealth sets its buffer filetype to "checkhealth". You can customize the
buffer by handling the |FileType| event. For example if you don't want emojis
in the health report: >vim
autocmd FileType checkhealth :set modifiable | silent! %s/\v( ?[^\x00-\x7F])//g
<
--------------------------------------------------------------------------------
Create a healthcheck *health-dev*
Healthchecks are functions that check the user environment, configuration, or
any other prerequisites that a plugin cares about. Nvim ships with
healthchecks in:
$VIMRUNTIME/autoload/health/
$VIMRUNTIME/lua/vim/lsp/health.lua
$VIMRUNTIME/lua/vim/treesitter/health.lua
and more...
- $VIMRUNTIME/autoload/health/
- $VIMRUNTIME/lua/vim/lsp/health.lua
- $VIMRUNTIME/lua/vim/treesitter/health.lua
- and more...
To add a new healthcheck for your own plugin, simply create a "health.lua"
module on 'runtimepath' that returns a table with a "check()" function. Then
@@ -91,19 +82,20 @@ module on 'runtimepath' that returns a table with a "check()" function. Then
For example if your plugin is named "foo", define your healthcheck module at
one of these locations (on 'runtimepath'):
lua/foo/health/init.lua
lua/foo/health.lua
- lua/foo/health/init.lua
- lua/foo/health.lua
If your plugin also provides a submodule named "bar" for which you want a
separate healthcheck, define the healthcheck at one of these locations:
lua/foo/bar/health/init.lua
lua/foo/bar/health.lua
If your plugin also provides a submodule named "bar" for which you want
a separate healthcheck, define the healthcheck at one of these locations:
- lua/foo/bar/health/init.lua
- lua/foo/bar/health.lua
All such health modules must return a Lua table containing a `check()`
function.
Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path
with your plugin name: >lua
local M = {}
M.check = function()
@@ -119,7 +111,6 @@ with your plugin name: >lua
end
return M
<
error({msg}, {...}) *vim.health.error()*

View File

@@ -112,6 +112,7 @@ API (EXTENSIBILITY/SCRIPTING/PLUGINS)
|channel| Nvim asynchronous IO
|vimscript| Vimscript reference
|vimscript-functions| Vimscript functions
|testing.txt| Vimscript testing functions
|remote-plugin| Nvim remote plugins
|health| Health checking

View File

@@ -337,7 +337,7 @@ in such a modeline, that can have undesired consequences.
TAGS
To define a help tag, place the name between asterisks ("*tag-name*"). The
To define a help tag, place the name between asterisks (*tag-name*). The
tag-name should be different from all the Vim help tag names and ideally
should begin with the name of the Vim plugin. The tag name is usually right
aligned on a line.
@@ -377,13 +377,7 @@ also implicitly stops the block of ex-commands before it. E.g. >
echo "Example"
endfunction
<
To enable syntax highlighting for a block of code, place a language name
annotation (e.g. "vim") after a greater than (>) character. E.g. >vim
function Example_Func()
echo "Example"
endfunction
<
*help-notation*
The following are highlighted differently in a Vim help file:
- a special key name expressed either in <> notation as in <PageDown>, or
as a Ctrl character as in CTRL-X
@@ -397,10 +391,4 @@ highlighting. So do these:
You can find the details in $VIMRUNTIME/syntax/help.vim
FILETYPE COMPLETION *ft-help-omni*
To get completion for help tags when writing a tag reference, you can use the
|i_CTRL-X_CTRL-O| command.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -268,4 +268,5 @@ These are also available via the "main" package:
$main::curwin The current Window object.
$main::curbuf The current Buffer object.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -645,6 +645,6 @@ To check if `pyx*` functions and commands are available: >vim
if has('pythonx')
echo 'pyx* commands are available. (Python ' .. &pyx .. ')'
endif
<
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -189,4 +189,5 @@ evaluate Ruby expressions and pass their values to Vim script.
The Ruby value "true", "false" and "nil" are converted to v:true, v:false and
v:null, respectively.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -146,7 +146,6 @@ commands in CTRL-X submode *i_CTRL-X_index*
|i_CTRL-X_CTRL-N| CTRL-X CTRL-N next completion
|i_CTRL-X_CTRL-O| CTRL-X CTRL-O omni completion
|i_CTRL-X_CTRL-P| CTRL-X CTRL-P previous completion
|i_CTRL-X_CTRL-R| CTRL-X CTRL-R complete contents from registers
|i_CTRL-X_CTRL-S| CTRL-X CTRL-S spelling suggestions
|i_CTRL-X_CTRL-T| CTRL-X CTRL-T complete identifiers from thesaurus
|i_CTRL-X_CTRL-Y| CTRL-X CTRL-Y scroll down
@@ -516,7 +515,7 @@ tag command action in op-pending and Visual mode ~
tag command action in Normal mode ~
------------------------------------------------------------------------------ ~
|CTRL-W_CTRL-B| CTRL-W CTRL-B same as "CTRL-W b"
|CTRL-W_CTRL-C| CTRL-W CTRL-C no-op
|CTRL-W_CTRL-C| CTRL-W CTRL-C same as "CTRL-W c"
|CTRL-W_CTRL-D| CTRL-W CTRL-D same as "CTRL-W d"
|CTRL-W_CTRL-F| CTRL-W CTRL-F same as "CTRL-W f"
CTRL-W CTRL-G same as "CTRL-W g .."
@@ -1017,7 +1016,7 @@ tag command action in Command-line editing mode ~
|c_CTRL-D| CTRL-D list completions that match the pattern in
front of the cursor
|c_CTRL-E| CTRL-E cursor to end of command-line
'cedit' CTRL-F default value for 'cedit': opens the
|'cedit'| CTRL-F default value for 'cedit': opens the
command-line window; otherwise not used
|c_CTRL-G| CTRL-G next match when 'incsearch' is active
|c_<BS>| <BS> delete the character in front of the cursor
@@ -1266,7 +1265,6 @@ tag command action ~
|:delcommand| :delc[ommand] delete user-defined command
|:delfunction| :delf[unction] delete a user function
|:delmarks| :delm[arks] delete marks
|:detach| :detach detach the current UI
|:diffupdate| :dif[fupdate] update 'diff' buffers
|:diffget| :diffg[et] remove differences in current buffer
|:diffoff| :diffo[ff] switch off diff mode
@@ -1350,8 +1348,6 @@ tag command action ~
|:inoreabbrev| :inorea[bbrev] like ":noreabbrev" but for Insert mode
|:inoremenu| :inoreme[nu] like ":noremenu" but for Insert mode
|:intro| :int[ro] print the introductory message
|:iput| :ip[ut] like |:put|, but adjust the indent to the
current line
|:isearch| :is[earch] list one line where identifier matches
|:isplit| :isp[lit] split window and jump to definition of
identifier
@@ -1473,6 +1469,7 @@ tag command action ~
|:options| :opt[ions] open the options-window
|:ounmap| :ou[nmap] like ":unmap" but for Operator-pending mode
|:ounmenu| :ounme[nu] remove menu for Operator-pending mode
|:ownsyntax| :ow[nsyntax] set new local syntax highlight for this window
|:packadd| :pa[ckadd] add a plugin from 'packpath'
|:packloadall| :packl[oadall] load all packages under 'packpath'
|:pbuffer| :pb[uffer] edit buffer in the preview window
@@ -1525,7 +1522,6 @@ tag command action ~
|:redrawtabline| :redrawt[abline] force a redraw of the tabline
|:registers| :reg[isters] display the contents of registers
|:resize| :res[ize] change current window height
|:restart| :restart restart the Nvim server
|:retab| :ret[ab] change tab size
|:return| :retu[rn] return from a user function
|:rewind| :rew[ind] go to the first file in the argument list
@@ -1667,7 +1663,6 @@ tag command action ~
|:unabbreviate| :una[bbreviate] remove abbreviation
|:unhide| :unh[ide] open a window for each loaded file in the
buffer list
|:uniq| :uni[q] uniq lines
|:unlet| :unl[et] delete variable
|:unlockvar| :unlo[ckvar] unlock variables
|:unmap| :unm[ap] remove mapping

View File

@@ -29,7 +29,7 @@ use "CTRL-V 003" to insert a CTRL-C. Note: When CTRL-V is mapped you can
often use CTRL-Q instead |i_CTRL-Q|.
If you are working in a special language mode when inserting text, see the
'langmap' option, 'langmap', on how to avoid switching this mode on and off
'langmap' option, |'langmap'|, on how to avoid switching this mode on and off
all the time.
char action ~
@@ -103,10 +103,8 @@ CTRL-P Find previous keyword (see |i_CTRL-P|).
CTRL-R {register} *i_CTRL-R*
Insert the contents of a register. Between typing CTRL-R and
the second character, '"' will be displayed to indicate that
you are expected to enter the name of a register. When used
with named or clipboard registers (A-Z,a-z,0-9,+) text is
inserted literally like pasting with "p". For other registers,
the text is inserted as if you typed it, but mappings and
you are expected to enter the name of a register.
The text is inserted as if you typed it, but mappings and
abbreviations are not used. If you have options like
'textwidth', 'formatoptions', or 'autoindent' set, this will
influence what will be inserted. This is different from what
@@ -133,8 +131,6 @@ CTRL-R {register} *i_CTRL-R*
special keys. E.g., you can use this to move
the cursor up:
CTRL-R ="\<Up>"
you can use this to insert a register as
typed with CTRL-R =@reg.
Use CTRL-R CTRL-R to insert text literally.
When the result is a |List| the items are used
as lines. They can have line breaks inside
@@ -273,17 +269,15 @@ The effect of the <BS>, CTRL-W, and CTRL-U depend on the 'backspace' option
item action ~
indent allow backspacing over autoindent
eol allow backspacing over line breaks (join lines)
start allow backspacing over the start of insert; CTRL-W and CTRL-U stop
once at the start of insert.
nostop like start, except CTRL-W and CTRL-U do not stop at the start of
insert.
eol allow backspacing over end-of-line (join lines)
start allow backspacing over the start position of insert; CTRL-W and
CTRL-U stop once at the start position
When 'backspace' is empty, Vi compatible backspacing is used. You cannot
backspace over autoindent, before column 1 or before where insert started.
For backwards compatibility the values "0", "1", "2" and "3" are also allowed,
see 'backspace'.
see |'backspace'|.
If the 'backspace' option does contain "eol" and the cursor is in column 1
when one of the three keys is used, the current line is joined with the
@@ -516,7 +510,7 @@ paragraph, no matter where the cursor currently is. Or you can use Visual
mode: hit "v", move to the end of the block, and type "gq". See also |gq|.
==============================================================================
4. 'expandtab', 'softtabstop' and 'smarttab' options *ins-expandtab*
4. 'expandtab', 'smarttab' and 'softtabstop' options *ins-expandtab*
If the 'expandtab' option is on, spaces will be used to fill the amount of
whitespace of the tab. If you want to enter a real <Tab>, type CTRL-V first
@@ -527,6 +521,13 @@ number of characters in the line increases. Backspacing will delete one
space at a time. The original character will be put back for only one space
that you backspace over (the last one).
*ins-smarttab*
When the 'smarttab' option is on, a <Tab> inserts 'shiftwidth' positions at
the beginning of a line and 'tabstop' positions in other places. This means
that often spaces instead of a <Tab> character are inserted. When 'smarttab'
is off, a <Tab> always inserts 'tabstop' positions, and 'shiftwidth' is only
used for ">>" and the like.
*ins-softtabstop*
When the 'softtabstop' option is non-zero, a <Tab> inserts 'softtabstop'
positions, and a <BS> used to delete white space, will delete 'softtabstop'
@@ -541,13 +542,6 @@ the cursor. Otherwise you cannot always delete a single character before the
cursor. You will have to delete 'softtabstop' characters first, and then type
extra spaces to get where you want to be.
*ins-smarttab*
When the 'smarttab' option is on, the <Tab> key indents by 'shiftwidth' if the
cursor is in leading whitespace. The <BS> key has the opposite effect. This
behaves as if 'softtabstop' were set to the value of 'shiftwidth'. This option
allows the user to set 'softtabstop' to a value other than 'shiftwidth' and
still use the <Tab> key for indentation.
==============================================================================
5. Replace mode *Replace* *Replace-mode* *mode-replace*
@@ -605,7 +599,7 @@ In 'list' mode, Virtual Replace mode acts as if it was not in 'list' mode,
unless "L" is in 'cpoptions'.
Note that the only situations for which characters beyond the cursor should
appear to move are in List mode 'list', and occasionally when 'wrap' is set
appear to move are in List mode |'list'|, and occasionally when 'wrap' is set
(and the line changes length to become shorter or wider than the width of the
screen). In other cases spaces may be inserted to avoid following characters
to move.
@@ -634,8 +628,7 @@ Completion can be done for:
10. User defined completion |i_CTRL-X_CTRL-U|
11. omni completion |i_CTRL-X_CTRL-O|
12. Spelling suggestions |i_CTRL-X_s|
13. completions from 'complete' |i_CTRL-N| |i_CTRL-P|
14. contents from registers |i_CTRL-X_CTRL-R|
13. keywords in 'complete' |i_CTRL-N| |i_CTRL-P|
Additionally, |i_CTRL-X_CTRL-Z| stops completion without changing the text.
@@ -645,9 +638,6 @@ and one of the CTRL-X commands. You exit CTRL-X mode by typing a key that is
not a valid CTRL-X mode command. Valid keys are the CTRL-X command itself,
CTRL-N (next), and CTRL-P (previous).
By default, the possible completions are showed in a menu and the first
completion is inserted into the text. This can be adjusted with 'completeopt'.
To get the current completion information, |complete_info()| can be used.
Also see the 'infercase' option if you want to adjust the case of the match.
@@ -661,11 +651,10 @@ When completion is active you can use CTRL-E to stop it and go back to the
originally typed text. The CTRL-E will not be inserted.
*complete_CTRL-Y*
When the popup menu is displayed, CTRL-Y stops completion and accepts the
currently selected entry. Typing a space, Enter, or some other unprintable
character will leave completion mode and insert that typed character. If you
want to use <Enter> to accept a completion item, use this mapping: >vim
inoremap <expr> <cr> pumvisible() ? '<c-y>' : '<cr>'
When the popup menu is displayed you can use CTRL-Y to stop completion and
accept the currently selected entry. The CTRL-Y is not inserted. Typing a
space, Enter, or some other unprintable character will leave completion mode
and insert that typed character.
When the popup menu is displayed there are a few more special keys, see
|popupmenu-keys|.
@@ -1009,25 +998,6 @@ CTRL-X CTRL-V Guess what kind of item is in front of the cursor and
completion, for example: >
:imap <Tab> <C-X><C-V>
Completing contents from registers *compl-register-words*
*i_CTRL-X_CTRL-R*
CTRL-X CTRL-R Guess what kind of item is in front of the cursor from
all registers and find the first match for it.
Further use of CTRL-R (without CTRL-X) will insert the
register content, see |i_CTRL-R|.
'ignorecase' applies to the matching.
CTRL-N Search forwards for next match. This match replaces
the previous one.
CTRL-P Search backwards for previous match. This match
replaces the previous one.
CTRL-X CTRL-R Further use of CTRL-X CTRL-R will copy the line
following the previous expansion in other contexts
unless a double CTRL-X is used (e.g. this switches
from completing register words to register contents).
User defined completion *compl-function*
Completion is done by a function that can be defined by the user with the
@@ -1088,23 +1058,25 @@ CTRL-X s Locate the word in front of the cursor and find the
previous one.
Completing from different sources *compl-generic*
Completing keywords from different sources *compl-generic*
*i_CTRL-N*
CTRL-N Find the next match for a word ending at the cursor,
using the sources specified in the 'complete' option.
All sources complete from keywords, except functions,
which may complete from non-keyword. The matched
text is inserted before the cursor.
CTRL-N Find next match for words that start with the
keyword in front of the cursor, looking in places
specified with the 'complete' option. The found
keyword is inserted in front of the cursor.
*i_CTRL-P*
CTRL-P Same as CTRL-N, but find the previous match.
CTRL-P Find previous match for words that start with the
keyword in front of the cursor, looking in places
specified with the 'complete' option. The found
keyword is inserted in front of the cursor.
CTRL-N Search forward through the matches and insert the
next one.
CTRL-N Search forward for next matching keyword. This
keyword replaces the previous matching keyword.
CTRL-P Search backward through the matches and insert the
previous one.
CTRL-P Search backwards for next matching keyword. This
keyword replaces the previous matching keyword.
CTRL-X CTRL-N or
CTRL-X CTRL-P Further use of CTRL-X CTRL-N or CTRL-X CTRL-P will
@@ -1118,25 +1090,26 @@ Stop completion *compl-stop*
CTRL-X CTRL-Z Stop completion without changing the text.
AUTOCOMPLETION *ins-autocompletion*
AUTO-COMPLETION *compl-autocomplete*
Vim can display a completion menu as you type, similar to using |i_CTRL-N|,
but triggered automatically. See 'autocomplete'. The menu items are collected
from the sources listed in the 'complete' option, in order.
A decaying timeout keeps Vim responsive. Sources earlier in the 'complete'
list get more time (higher priority), but all sources receive at least a small
time slice.
This mode is fully compatible with other completion modes. You can invoke
any of them at any time by typing |CTRL-X|, which temporarily suspends
autocompletion. To use |i_CTRL-N| or |i_CTRL-X_CTRL-N| specifically, press
|CTRL-E| first to dismiss the popup menu (see |complete_CTRL-E|).
See also 'autocomplete', 'autocompletetimeout' and 'autocompletedelay'.
To get LSP-driven auto-completion, see |lsp-completion|.
To get LSP-driven auto-completion, see |lsp-completion|. To get basic
auto-completion without installing plugins or LSP, try this: >lua
local triggers = {'.'}
vim.api.nvim_create_autocmd('InsertCharPre', {
buffer = vim.api.nvim_get_current_buf(),
callback = function()
if vim.fn.pumvisible() == 1 or vim.fn.state('m') == 'm' then
return
end
local char = vim.v.char
if vim.list_contains(triggers, char) then
local key = vim.keycode('<C-x><C-n>')
vim.api.nvim_feedkeys(key, 'm', false)
end
end
})
<
FUNCTIONS FOR FINDING COMPLETIONS *complete-functions*
@@ -1189,9 +1162,6 @@ For example, the function can contain this: >
let matches = ... list of words ...
return {'words': matches, 'refresh': 'always'}
<
If looking for matches is time-consuming, |complete_check()| may be used to
maintain responsiveness.
*complete-items*
Each list item can either be a string or a Dictionary. When it is a string it
is used as the completion. When it is a Dictionary it can contain these
@@ -1326,7 +1296,6 @@ use all space available.
The 'pumwidth' option can be used to set a minimum width. The default is 15
characters.
*compl-states*
There are three states:
1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P.
2. A cursor key has been used to select another match. The match was not
@@ -1954,7 +1923,7 @@ These commands are used to start inserting text. You can end insert mode with
<Esc>. See |mode-ins-repl| for the other special characters in Insert mode.
The effect of [count] takes place after Insert mode is exited.
The following |default-mappings| insert text, but stay in normal mode:
The following commands insert text, but stay in normal mode:
*]<Space>*
]<Space> Insert an empty line below the cursor without leaving

View File

@@ -89,7 +89,7 @@ To uninstall Nvim:
- Scoop (Windows): `scoop uninstall neovim`
==============================================================================
Sponsor Vim/Nvim development *sponsor*
Sponsor Vim/Nvim development *sponsor* *register*
Fixing bugs and adding new features takes a lot of time and effort. To show
your appreciation for the work and motivate developers to continue working on
@@ -605,7 +605,7 @@ status messages will only be used if an option is on: >
command characters 'showcmd' on off
cursor position 'ruler' off off
The current mode is "-- INSERT --" or "-- REPLACE --", see 'showmode'. The
The current mode is "-- INSERT --" or "-- REPLACE --", see |'showmode'|. The
command characters are those that you typed but were not used yet.
If you have a slow terminal you can switch off the status messages to speed
@@ -711,4 +711,5 @@ Arbitrary code registered via |:UpdateRemotePlugins|, that runs in a separate
process and communicates with Nvim via the |api|.
==============================================================================
vim:tw=78:ts=8:et:sw=4:ft=help:norl:

View File

@@ -140,4 +140,5 @@ A job may be killed at any time with the |jobstop()| function:
<
Individual streams can be closed without killing the job, see |chanclose()|.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More