Commit Graph

10990 Commits

Author SHA1 Message Date
Artem Krinitsyn
dec3d8215d fix(text): indent() ignores expandtab when indent unchanged #40932
Problem:
After expanding tabs with the `expandtab` option, if the old indent
matches the requested one, `vim.text.indent()` returns the input
unchanged.
The optimization path assumes that if old_indent == size, the input
wouldn't be changed, which is not correct when old_indent is formed by
expanded tabs.

Solution:
Apply the optimization only when `expandtab` is not set.
2026-07-26 06:24:39 -04:00
Justin M. Keyes
6539bd6602 Merge #40910 from barrettruth/fix/dir-literal-env-paths 2026-07-26 06:11:01 -04:00
Barrett Ruth
3d5de7fd11 fix(buffer): name becomes empty when it is the cwd #40980
Problem: Shortening the name of a buffer whose full name is the current
directory + path sep yields empty string -> buf unnamed.
This doesn't interact well with things like `:mksession`, which
for example could `:badd` with no arg -> E471.

Solution: Keep the full path when shortening yields an empty name, as
`path_try_shorten_fname()` already does.
2026-07-26 05:36:03 -04:00
zeertzjq
7ee1bf91ad vim-patch:9.2.0855: 'showcmd' not redrawn with empty mapping triggered on timeout
Problem:  'showcmd' not redrawn with empty mapping triggered on timeout.
Solution: Don't postpone redraw when inside vgetorpeek(). Also move test
          for tabline 'showcmd' to test_tabline.vim.

fixes:  vim/vim#20839
closes: vim/vim#20840

2e9687647a
2026-07-26 07:07:38 +08:00
zeertzjq
a56f4d221e vim-patch:partial:9.2.0806: 'showcmd' may show internal command keys
Problem:  The `showcmd` statusline item may show internal command keys when a
          `<Cmd>` or `<ScriptCmd>` mapping redraws the statusline, and may
          leave stale text behind when `%S` is rendered directly.
Solution: Do not add these internal mapping dispatch keys to the `showcmd`
          buffer, and keep the clear state in sync when `%S` renders it
          (Barrett Ruth)

closes: vim/vim#20769

bd730293dc

Co-authored-by: Barrett Ruth <br@barrettruth.com>
2026-07-26 07:07:35 +08:00
Barrett Ruth
1594ca2368 fix(dir): preserve environment variables in paths 2026-07-25 18:02:55 -05:00
Barrett Ruth
ac4e5460b1 feat(vim.fs): dir(opts.normalize) 2026-07-25 18:02:55 -05:00
Justin M. Keyes
256a88d0ac Merge #40579 from barrettruth/fix/del-keymap-lhs-only-30258 2026-07-25 16:00:25 -04:00
mityu
26fed075ae fix(cmdwin): q: in visual-mode does not insert visual range #40973
Problem: `q:` in visual mode does not insert `'<,'>` automatically in
the current line on cmdwin.

Solution: Insert `'<,'>` in the current line on cmdwin when `q:` is used
in visual mode.
2026-07-25 15:50:31 -04:00
Barrett Ruth
22d44ef875 fix(api): add lhs option for keymap deletion 2026-07-25 10:36:56 -07:00
Barrett Ruth
6ffbb2962c test(api): allow added optional params 2026-07-25 10:01:08 -07:00
Justin M. Keyes
715d8887ec docs: misc #40847
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Co-authored-by: Nathan Zeng <nathan.j.zeng@gmail.com>
2026-07-25 12:47:51 -04:00
Barrett Ruth
4975a186f2 fix(dir): :browse edit opens dir browser #40930
Problem: `:browse edit` (and variants) without an argument fails instead
of opening a browser.

Solution: Dispatch to dir.lua using the cwd as the implied directory.
Replace the inherited GUI-only documentation with the supported
behavior. Support vsplit, split, tabedit variants.
2026-07-25 06:56:52 -04:00
zeertzjq
ba0e5b25bc vim-patch:9.2.0846: [security]: heap buffer overflow in set_sofo()
Problem:  [security]: heap buffer overflow in set_sofo()
          (Yazan Balawneh)
Solution: Reset sl_sal_first (Yasuhiro Matsumoto).

A crafted spell file with an empty SN_SAL section before an SN_SOFO
section reaches set_sofo() with sl_sal_first[] already set to -1 by
set_sal_first(). The counting loop then under-counts colliding
multi-byte "from" characters, allocates an undersized list and writes
past its end.

Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-9jqx-hgpr-6v64

05c41c9223

Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-07-25 07:07:43 +08:00
zeertzjq
63c84e4c1a vim-patch:9.2.0848: tagfunc "cmd" with a generic Ex command corrupts the tag entry (#40951)
Problem:  When a tagfunc returns a "cmd" that is neither a line number nor
          a search pattern, the tag entry is corrupted: the "kind" field is
          lost and taglist() returns a mangled "cmd".
Solution: Accept any Ex command in "cmd" as in a tags file, terminate a
          generic command with a bar so the trailing fields are preserved,
          and reject a value that cannot be stored in a tag line with E987
          (Hirohito Higashi).

fixes:   vim/vim#20781
related: vim/vim#20790
closes:  vim/vim#20828

86adef19fc

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Mao-Yining <mao.yining@outlook.com>
2026-07-25 07:07:22 +08:00
zeertzjq
19c89b6d68 vim-patch:9.2.0849: filetype: osquery config files are not recognized
Problem:  filetype: osquery config files are not recognized.
Solution: Detect osquery.conf as jsonc filetype (Fionn Fitzmaurice).

Reference:
https://osquery.readthedocs.io/en/stable/deployment/configuration/#configuration-components

closes: vim/vim#20826

ea183ce4e5

Co-authored-by: Fionn Fitzmaurice <fionn@github.com>
2026-07-25 06:29:04 +08:00
zeertzjq
72b2c713ea vim-patch:9.2.0845: [security]: arbitrary Ex command execution during C omni-completion
Problem:  [security]: arbitrary Ex command execution during C
          omni-completion (Threonine)
Solution: Match tags typeref literally to block Ex command injection
          (Yasuhiro Matsumoto).

Escaping only "/" and "\" left the typeref able to break out of the
:vimgrep pattern without a "/": an unclosed "[" makes vimgrep's pattern
skipping fail, and the parser then treats a following "|" as a command
separator, so the tag value runs as Ex commands during C omni-completion.
Match the field literally with \V so no regex metacharacter can affect
pattern parsing.

Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-cx73-phcg-3j5g

2f628d8104

Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-07-25 06:23:13 +08:00
Justin M. Keyes
bf3d4210c3 refactor: 'previewpopup' #40945
- drop w_maxwidth/w_maxheight, calculate them on-demand from
  'previewpopup' (this is cheap bc of `opt_keyset`)
2026-07-24 13:49:47 -04:00
Olivia Kinnear
bb104ba4db feat(health): improvements to :checkhealth #40935
Changes:
- Removed the blank line before the first healthcheck header.
- Fixed a bug where the entire "Terminal" section of `vim.health` would
  not appear if the `infocmp` executable was not found.
- Fixed a typo in `vim.lsp` when displaying the LSP log level.
2026-07-24 11:54:12 -04:00
Justin M. Keyes
e8195baaef refactor(options): 'previewpopup' validation
Use a schema instead of manual parsing.
2026-07-24 13:05:20 +02:00
Justin M. Keyes
3fceb84560 refactor(options): store dict options in :set-string form
The parent commit made a valiant effort to store "dict options" in their
reified form, but this is more trouble than it's worth:
- inconsistent model for developers to understand.
- string lifetime issues (the "varp" convention is to pass around an
  aliased, long-lived option value).
- lots of extra plumbing to deal with the 2 different option-storage
  paradigms.
2026-07-24 13:05:20 +02:00
Justin M. Keyes
f8cfd7f06a feat(options): schema, "dict" options, messages
Problem:
Options parsing is still painful for dict-style options.

Solution:
schema-maxxing => better `opt:get()` (will be the basis for `vim.o()`),
unified (and more-detailed) err msgs.

- Drop bespoke structure-builder in `_core/options.lua`.
- Define `schema` for all non-primitive options (except 'guicursor' and
  statusline-style options); generate reified keysets `OptKeyDict`).
  - Generate 'fillchars' => `fcs_tab`, 'listchars' => `lcs_tab`.
- `nvim_set_option_value`:
  - Return the improved structures. Also from `vim.opt.x:get()`.
  - Eliminate api <=> lua roundtrip, centralize option structure
    handling.
- Improve/unify errors.
  - Bump ERR_BUFLEN 80 → 256 so the "one of" list isn't truncated.
- Eliminate old 'diffopt' order-dependence (`iwhiteall` before `iwhite`)

Error samples:

    Typed-key path (opt_strings_check → diffopt/mousescroll/breakindentopt):
    E474: Unknown item 'foo'
    E474: 'context' requires a number
    E474: 'ver' number is out of range
    E474: 'algorithm' must be one of: myers, minimal, patience, histogram
    E474: 'filler' does not take a value

Related:

- #31084
- #34661
- #31820
- #14739
- #20107
- fix #18875
  - :get() returns `{ sbr = true, shift = '3' }` (reified-keyset) instead of `{'sbr', 'shift:3'}`
  - Setting via table now works too. `object_as_optval_for` `is_map` now recognizes struct options.
- fix #30296
  - instead of `E474: Invalid argument`, errors now look like:
    ```
    E474: Invalid value 'x', expected one of: single, double: ambiwidth=x
    E474: Unknown item 'foo': diffopt=foo
    E474: 'context' requires a number: diffopt=context:x
    ```

simplify `win_float_parse_option` from #26799.
2026-07-24 13:05:20 +02:00
Barrett Ruth
5d76b9836a feat(dir): support counts for parent navigation #40927 2026-07-24 06:48:47 -04:00
Barrett Ruth
ce9cc43f23 fix(dir): open CWD from unnamed buffer with - mapping #40926 2026-07-24 06:45:13 -04:00
glepnir
f95bd73935 feat(float): 'previewpopup' option #26799
Problem:
The preview-window (:pedit, etc.) always uses a split, but it would be
useful as a floatwin (or "popup").

Solution:
Support Vim's 'previewpopup' option.
2026-07-23 17:27:14 -04:00
zeertzjq
b81c60c3fa vim-patch:9.2.0830: the completion menu is not used on terminals without colors (#40917)
Problem:  When the terminal reports no colors ("t_Co" is 0 or 1) the
          insert mode completion popup menu is not shown at all, while
          the command line completion popup menu ('wildoptions' contains
          "pum") is shown.  In 'wildmenu' completion the current match
          cannot be told apart from the other matches (Maxim Kim)
Solution: Show the insert mode completion popup menu regardless of the
          number of colors and add "term" attributes to the default
          highlighting of Pmenu, PmenuSel and PmenuThumb.  The wildmenu
          is drawn with the attributes of the status line, which is
          reversed, and on most terminals the standout mode is the same
          as the reverse mode, thus use the underline mode for the
          default highlighting of WildMenu (Hirohito Higashi).

fixes:  vim/vim#20800
closes: vim/vim#20803

52485e0d24

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 07:40:11 +00:00
zeertzjq
53cbf66bd2 vim-patch:9.2.0838: searchcount() returns wrong cached maxcount (#40913)
Problem:  Cached searchcount() returns 'maxsearchcount' instead of the
          requested maxcount.
Solution: return the remembered last_maxcount (glepnir)

closes: vim/vim#20701

4352dc6ab0

Co-authored-by: glepnir <glephunter@gmail.com>
2026-07-23 09:03:29 +08:00
zeertzjq
05c5cf7e40 vim-patch:9.2.0836: filetype: .git-blame-ignore-revs file is not recognized (#40912)
Problem:  filetype: .git-blame-ignore-revs file is not recognized
Solution: Detect .git-blame-ignore-revs file as gitrevlist filetype,
          include syntax and filetype plugins (Fionn Fitzmaurice)

A Git revision list is

> a list of object names (i.e. one unabbreviated SHA-1 per line)...,
> comments (#), empty lines, and any leading and trailing whitespace are
> ignored.

(from Git's fsck.skipList documentation).

The default output of git rev-list will match this. It is also suitable
as input to git blame --ignore-revs-file.

This adds filetype detection matching .git-blame-ignore-revs files,
syntax highlighting and basic filetype settings.

closes: vim/vim#20702

a8d5be9284

Co-authored-by: Fionn Fitzmaurice <fionn@github.com>
2026-07-23 09:03:07 +08:00
Barrett Ruth
ada2007453 feat(dir): provider framework #40738
Problem:
The core behaviors of `nvim.dir` cannot be reused by consumers
such as the archive plugin, ssh browser, etc.

Solution:
- Define a basic "provider" shape.
- Extract the filesystem provider.
2026-07-22 13:21:39 -04:00
Ondrej Balaz
8b6bdb79e6 fix(ui): invalid ruler items in other windows #40891
Problem:
When buffer is open in multiple windows and its line count changes, any
'statusline' or 'rulerformat' items depending on it (e.g. %P) will
become invalid in non-current windows because w_redr_status is only set
on first change.

Solution:
Set w_redr_status on all windows with the buffer when the line count
changes.

Signed-off-by: Ondrej Balaz <blami@blami.net>
2026-07-22 12:05:37 -04:00
tao
e397b2c2ca refactor(path): path_has_wildcard() #40893
Problem:
Redundant code.

Solution:
Combine path_has_wildcard() and path_has_exp_wildcard(). They have similar logic.
Also, the latter operates on whatever wildcards remain after shell/env/backtick
expansion, so the two felt somewhat related.

Also drop some unnecessary MB_PTR_ADV calls.
2026-07-22 10:39:29 -04:00
zeertzjq
47e97c1ad6 vim-patch:9.2.0827: :startinsert enters Insert mode in a non-modifiable buffer (#40906)
Problem:  ":startinsert" enters Insert mode in a buffer where
          'modifiable' is off, the error only appears when a character
          is typed.  Typing "i" gives the error right away (Barrett Ruth)
Solution: Give the error when the buffer is not modifiable, like "i"
          does.  Keep ignoring the command in a terminal window, where
          ":startinsert" is documented to be ineffective, and keep
          accepting it when 'insertmode' is set, like "i" does
          (Hirohito Higashi).

fixes:  vim/vim#20804
closes: vim/vim#20806

6ab1976e49

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
2026-07-22 14:03:05 +00:00
XiaowenHu
bd73d8c011 fix(inccommand): enforce timeout during matching, not just after a line #40892
Problem: do_sub() only checks the timeout limit after finishing a line.
         A pathological regex will run on a single line input unbounded
         until the compute is completed.

Solution: Pass the timeout limit to `vim_regexec_multi()` so the
          computation on the regex engine is bounded per-line.

Signed-off-by: XiaowenHu96 <me@xiaowenhu.com>
2026-07-22 08:27:54 -04:00
phanium
526365a8d1 fix(help): handle escape edge cases #40901
* fix(help): preserve multi-letter CTRL modifiers in :help subject

Problem: After PR 39537 normalized `CTRL-U-default` by excluding
`-` from the trigger char class, the regex `(CTRL%-[^{])([^-_\\])`
also fires between `CTRL-S` and the `H` of the `SHIFT` modifier
in tags like `c_CTRL-SHIFT-V`, splitting it into the non-existent
`c_CTRL-S_HIFT-V`.

Solution: Exclude uppercase letters from the char class so a
multi-letter modifier following `CTRL-X` (e.g. `SHIFT`, `ALT`) is
no longer split. The `-` exclusion from 39537 is preserved so
`i_CTRL-U-default` still works.

* fix(help): escape ~ in expr-=~? exception to keep regex valid

Problem: The `expr-=~?` exception in the tag alias table maps to
`=~?`, but in Vim's regex engine `~` refers to the previous
substitute pattern. With no prior substitute the pattern fails to
compile, so `:help expr-=~?` returns E149 even though the tag exists.

Solution: Escape `~` as \\\~` so the alias expands to a valid
regex (`=\\\~?`) that substring-matches the `expr-=~?` tag. Other
`expr-X?` entries are unaffected since they don't contain `~`.

* fix(help): don't insert _ before CTRL- when preceded by -

Problem: The rule `([^_])CTRL%- -> %1_CTRL-` inserts an underscore
between any non-underscore char and `CTRL-`, which wrongly rewrites
tags like `map-CTRL-C` and `telnet-CTRL-]` (where `CTRL-` is
literal text in the tag, not a key chord).

Solution: Exclude `-` from the trigger char class so a hyphen
immediately before `CTRL-` is preserved. The existing behavior for
`iCTRL-GCTRL-J` -> `i_CTRL-G_CTRL-J` is unaffected because the
`G` before `CTRL-J` is not `-`.

* fix(help): only treat ^X as caret notation for valid control chars

Problem: The regex `%^([^_])` converts any `^X` to `CTRL-X`,
including `:set^=` where `^=` is literal text in the tag, not a
caret-notation control character.

Solution: Restrict the transformation to caret-notation chars
(`%a` or one of `?@[\\]^{}`). This matches the C reference
behavior where `^X` is only converted when X is alphanumeric or one
of the control-notation punctuation chars. `{` is retained so
`^{char}` still maps to the `CTRL-{char}` placeholder tag.
2026-07-22 07:26:09 -04:00
zeertzjq
c9326e6df8 vim-patch:9.2.0825: regexp: submatch in a look-behind is empty with the NFA engine (#40899)
Problem:  With the NFA engine a sub-expression inside a variable width
          look-behind, e.g. "\v(.)@<=", is empty for the first match on
          every line except the first one.  The old engine is correct
          (Mukundan)
Solution: The look-behind is retried from the previous line, because the
          width of "." is over-estimated.  While scanning that line the
          start state is added at the end of the line, where it gets the
          position of the line break as its start position, even though
          the match actually starts on the next line.  Use the position
          of the start of the next line in that case (Hirohito Higashi).

fixes:  vim/vim#20802
closes: vim/vim#20805

ade577e4dc

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 09:32:24 +00:00
zeertzjq
a277c08d98 vim-patch:9.2.0821: filetype: msmtp system-wide rc file not detected (#40895)
Problem:  filetype: msmtp system-wide rc file not detected (chdiza).
Solution: Detect 'msmtprc' as filetype msmtp, like '.msmtprc'
          (Doug Kearns).

fixes:  vim/vim#20751
closes: vim/vim#20752

88440f9a34

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2026-07-21 23:16:33 +00:00
Justin M. Keyes
008ea4dd65 Merge #40873 fix(ui): handle combining chunked float titles 2026-07-21 11:45:44 -04:00
Justin M. Keyes
6d5b774362 build(luals): drop src/.luarc.json, test/.luarc.json #40887
Problem:
emmylua reports `unresolved-require` for `require('test.testutil')` and
friends, and a file under `test/` cannot even resolve its own siblings.

This happens because `test/.emmyrc.json` and `test/.luarc.json`, cause
vim.lsp to root the workspace at `test/` instead of the repo top-level.

Solution:
Drop the nested configs:

    src/.luarc.json
    test/.luarc.json
    test/.emmyrc.json

Outcomes:
- No "libraries" needed: luv types come from `runtime/lua/uv/_meta.lua`,
  not `${3rd}/luv` (which would only duplicate them).
- Drop `test/` from the root `.luarc.json` `ignoreDir` so its modules are
  resolvable by LuaLS/Emmylua.
  - Note: this means that LuaLS diagnostics will now be reported for
    `test/`, but that is not a bad thing...
2026-07-21 08:56:42 -04:00
Justin M. Keyes
f907614088 Merge #40865 from justinmk/fixci 2026-07-21 08:04:16 -04:00
Sanzhar Kuandyk
a87e91677c fix(system): use native path for Windows executables #40885
Problem:
When 'shellslash' is set, exepath() returns forward-slashed paths.
Passing that path to vim.system() can prevent cmd.exe from launching.

Solution:
Convert the resolved executable path to native separators before spawning.
Add a Windows regression test for cmd.exe with 'shellslash' enabled.
2026-07-21 07:58:44 -04:00
Justin M. Keyes
1250821ba8 test: drop assert.is_true() and friends 2026-07-21 13:22:39 +02:00
Justin M. Keyes
6d8c8b18d5 test(harness): migrate away from magic globals
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.

- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
  merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
  "know" about the various magic symbols.

So they harm DX, which means they serve no purpose at all.

Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
  `t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
2026-07-21 13:22:39 +02:00
zeertzjq
116d15e6b6 vim-patch:9.2.0815: deeply nested regexp patterns may cause stack overflow (#40878)
Problem:  Deeply nested regexp groups can cause uncontrolled recursion
          in the regexp compiler and exhaust the C stack.
Solution: Limit recursive regexp parsing depth in both the backtracking
          and NFA compilers (lipengyu)

closes: vim/vim#20731

a79cd6bfc3

Co-authored-by: lipengyu <lipengyu@kylinos.cn>
2026-07-21 07:37:01 +08:00
zeertzjq
60b643a815 vim-patch:9.2.0812: :argdelete with pattern leads to wrong argidx() (#40876)
Problem:  :argdelete with pattern leads to wrong argidx().
Solution: Correct argidx() in both branches of ex_argdelete().  Also use
          ARGCOUNT macro in two more places (zeertzjq).

related: patch 7.4.1119
related: neovim/neovim#40564
closes:  vim/vim#20697

3b40a14a46
2026-07-21 07:01:52 +08:00
Barrett Ruth
16c145d240 fix(ui2): preserve Visual mode messages #40828
Problem:
The existing `showmode` overlay can immediately cover messages emitted while
Visual mode is active, including the `g CTRL-G` word count.

Solution:
Protect Visual mode messages with the existing message delay and temporarily
hide the previous last-line overlay until it is restored.
2026-07-20 15:44:37 -04:00
Artem Krinitsyn
18d6b2309f fix(ui): handle combining chunked float titles
Problem:
The title is combined with window's attributes only if the title is a
string (which implies the FloatTitle / FloatFooter highlight groups),
but not when the title is text-hl chunks.

Solution:
Combine specified highlight group with window-local Normal highlight as
well.
2026-07-20 19:35:08 +00:00
Justin M. Keyes
86fbcd67be test: unreliable "CursorHold not triggered after only K_EVENT on startup" #40863
Problem:

    FAILED   …/cursorhold_spec.lua @ 73: CursorHold is not triggered after only K_EVENT on startup
    Expected values to be equal.
    Expected:
    1
    Actual:
    0
    stack traceback:
    …/cursorhold_spec.lua:79: in function <…/cursorhold_spec.lua:73>

Solution:
Retry instead of hardcoding sleep(50).
2026-07-20 11:12:53 -04:00
Justin M. Keyes
317c5ddda6 fix(lsp): incorrect rendering of markdown codeblock #40861
Problem:
LSP hover erroneously drops blank lines before a 4-space-indented
codeblock, which is not valid Markdown. This causes incorrect parsing
and wrong display.

Solution:
Fix `split_lines` so that it doesn't drop the blank line just before
a 4-space-indented codeblock.

fix https://github.com/neovim/neovim/issues/40860
2026-07-20 10:03:11 -04:00
PinkLea
a56b74bde3 feat(lua): Iter:count() #40831 2026-07-20 09:53:06 -04:00
Barrett Ruth
4121f2cf25 test(api): normalize context comparisons #40854 2026-07-20 04:53:21 -04:00