| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
| |
Problem:
- gQ does not restore follow-mode (q=).
- Users/plugins have no way to check if follow-mode is enabled.
Solution:
Introduce buffer-local 'follow' option.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
In the `enc=utf-8` only world, the 'isprint' option is quite obsolete.
The function is only consulted for decoded U+0080 to U+00FF chars
whose printability is defined by the unicode charset, just like
higher codepoints. Meanwhile, invalid `\x80` to `\xFF` bytes are always
unprintable.
Disentangle 'iskeyword', 'isfname' and 'isident' from each other by
giving them all separate bitsets. Now these can be updated individually.
These updaters can back out of errors gracefully, no need for extra
panic logic in option[str].c to restore partially updated chartabs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
A Visual selection produced by a Lua mapping is captured as the keys it
fed (`:norm!`), so non-primary cursors get the wrong selection.
Examples:
- API cursor-moves around a fed "o" are lost.
- `setpos("'<")` + "gv" reselects the primary's marks (treesitter `an`).
- A mapping that feeds an absolute selection (`:norm! <Esc>`, then
`norm! 3GV6G`).
Solution:
Classify fed keys as `lossy` if their produced selection differs from
the selection at mapping-end, or fed-key-start: the mapping moved it by
other means (API). Same idea as `composite.lossy` LHS-replay.
Now the captured Visual session contains the mapping's own cmd
(`<Cmd>…`, `:…`, or a Lua mapping-id) as one subatom, instead of the
keys it fed. E.g. `v…<K_LUA id>` instead of `v…V…G`.
Also affects dot-repeat (".").
A `:norm!` that ends a typed selection keeps the Visual session
(`vatom`) open (instead of the usual `atom_visual_reset()` plus
emit/stage), so the enclosing user frame (the mapping's `<Cmd>`/Lua, or
a typed `:norm!`) can complete or replace it.
- A child frame re-entering Visual does not restart it, so a later
`norm! V` continues that session instead of a new `kVatomFed` one.
- At end of the user (toplevel) frame, the fed subatoms are dropped in
favor of the mapping's own atom: as a subatom if Visual is active,
else as the session's closing suffix.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: While advancing the syntax highlighting, store_current_state()
calls syn_stack_find_entry() about once per parsed line, and
that function rescans the state-cache list from its head every
time. With the list capped at 1000 entries this linear rescan
dominates the cost of highlighting a large file.
Solution: Keep a cached position to the entry last located in the list
and resume the scan from it when it is at or before the wanted
line, advancing the finger as new states are stored
(Julien Voisin).
The list is sorted by line number, so when the remembered entry is at or
before the wanted line the answer can only follow it, never precede it;
resuming from there returns the same entry as a scan from the head. The
"at or before" guard keeps this correct for any lookup order: a backward
or random-access lookup whose remembered entry is past the wanted line
falls back to a full scan. The pointer is cleared whenever an entry is
freed, the array is reallocated or the block is freed, so it cannot
dangle.
Parsing the syntax of a 20000-line C file is about a third faster, a
5000-line file about a quarter faster, benchmarked via something like
this:
```
call synID(1, 1, 1) " warm-up
let s = reltime()
for l in range(1, line('$')) | call synID(l, 1, 1) | endfor
call writefile([reltimefloat(reltime(s))], $T)
```
closes: vim/vim#21166
https://github.com/vim/vim/commit/f1b454912996d6417acd0d738de0eb7b60902c56
Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
With mcursors and 'autocomplete', a non-literal key (`<BS>`) during an
active completion attempts to insert-cascade, which attempts a nested
`edit()`, which refuses with E565.
Solution:
Defer the flush while completion is active; the pending keys will be
handled later.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Replaying a deleted Lua mapping, may call an arbitrary function.
RHS of a Lua mapping embeds its LuaRef (`<K_LUA><ref><CR>`). The raw
keys may outlive the ref (redobuff ".", CmdAtom `keys`). If the mapping
is deleted, replaying it either (1) dereferences a freed registry slot,
or (2) calls whatever callback reused the slot (autocmd, timer, other
mapping).
Solution:
Assign a monotonic (never recycled) id to Lua mappings and encode the
mapping keys as `<K_LUA><id><CR>`.
Note: in the case of Vimscript, a deleted function raises E117, but if
the function is redefined with the same name, the mapping will find it.
Alternatives?:
- Globally ensure `LuaRef` ids are not recycled.
- Problem: could exhaust `int` in a long-lived Nvim session? Also,
difficult to impl bc the "recycling" is done by `luaL_ref` itself.
ref: 5ac2e47acc999472042df4f10f8f7b5ffa72ba3e
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
No way to set a buffer-local directory.
Use-cases:
- "Root dir" for LSP (and the "project" concept).
- `:terminal` OSC 7
Solution:
Add `:bcd` command.
- Extend `getcwd()` to take a third arg; `getcwd(-1, -1, bunfr)` returns
the buffer-local working directory.
- Buffer-local directories have less priority than window-local
ones, and more priority than tab-local ones.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Cannot assign Lua functions/closures to "func" ('completefunc',
'tagfun', …) or "expr" ('foldexpr', 'indentexpr', …) options.
Solution:
- Store "func"/"expr" options as `Callback` instead of string.
- Delete oceans of copy-pasted code.
- BREAKING: LuaRef returned via RPC/Vimscript is now represented as
`"<Lua N: file:line>"` (like what `:map` shows) instead of `nil`.
- Note: `man.vim` still uses `v:lua` string, bc it's a vimscript ftplugin.
Helped-by: Lewis Russell <lewis6991@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: An insecurely-set 'indentexpr', 'formatexpr', 'includeexpr'
or 'complete' value can end up evaluated outside the
sandbox after buf_copy_options() and clears the flag.
Solution: Copy the insecure flag alongside the value in
buf_copy_options(), and make 'complete' a per-buffer
insecure-flags field
Supported by AI.
closes: vim/vim#20861
https://github.com/vim/vim/commit/35f7fdfdfb036028cc8760d7c1556361bb85206a
I'm a bit hesitant to port this, but it's a follow-up to #39452.
Co-authored-by: Christian Brabandt <cb@256bit.org>
|
| |
|
|
| |
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Co-authored-by: Nathan Zeng <nathan.j.zeng@gmail.com>
|
| |
|
|
| |
- drop w_maxwidth/w_maxheight, calculate them on-demand from
'previewpopup' (this is cheap bc of `opt_keyset`)
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
Problem:
w_float_is_info conflates a window's role with its floating layout,
which are orthogonal properties.
Solution:
Replace w_float_is_info with a w_kind enum for the window's role.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
A successful `BufReadCmd` can leave an existing `filetype` without
rerunning its `FileType` setup, so state cleared during reload may not
be restored.
This also causes `:edit`/reload syntax `directoryDirectory` groups to
not be reapplied.
Solution:
After `BufReadCmd` handles a read, trigger `FileType` for the existing
`filetype` if no `FileType` event fired during the read.
|
| |
|
|
|
|
|
|
|
| |
Problem:
Insert-mode globals are scattered.
Solution:
Group them into one struct. Besides improving readability and
discoverability, this greatly helps with save/restore of an insert-mode
session.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
concealed (#40374)
Problem: When the cursor line has concealed text before the start of the
completion, the insert-mode completion popup is drawn at the wrong
screen column and the cursor no longer lines up with the completed
text.
Solution: Record the concealed width before the cursor on its screen line in
a new `win_T` field while `win_line()` draws it, subtract it in
`pum_display()` to place the menu over the visible text, and redraw
the cursor line so `win_line()` corrects the cursor too.
closes: vim/vim#20539
https://github.com/vim/vim/commit/d167c50de4b954e5ddd97208187c5b3b77dd89cc
Co-authored-by: Barrett Ruth <br@barrettruth.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
- Current 'statuscolumn' click label caveat is restrictive.
- v:virtnum is not unique to a line if it has both above and
below virtual lines.
- 'statuscolumn' click handler may expect v:virt/lnum to be set.
Solution:
- Store per-row click definitions for the statuscolumn in a
(nested line/virt number) map.
- Implement strategy that gives each 'statuscolumn' row a unique
v:virtnum.
- Set v:virt/lnum when determining which line is clicked.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: Deciding whether a group is in a "contains"/cluster list scans
the list and expands clusters on every check, which is slow for
syntaxes with large lists (e.g. plugins such as netrw).
Solution: Resolve each list once into a sorted, cluster-expanded set of
group IDs and use a binary search; cache it per syntax block and
drop the cache when syntax definitions change (Hirohito Higashi).
closes: vim/vim#20490
https://github.com/vim/vim/commit/48fbae4378ab9bb6e7fcbd2480544847eac10cd7
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
Problem:
BufModifiedSet autocmd only triggered for current buffer during
redraw, causing delayed events when :wa writes non-current buffers.
Solution:
- Use the aucmd_defer approach to implement `Optionset modified`.
- Drop BufModifiedSet.
|
| |
|
|
|
|
|
| |
Problem: A vim.ui_attach() callback that redraws to show a 'verbose'
regex message during 'incsearch' results in recusive redrawing.
Solution: Check that curwin was redrawn instead of just any window when
determining if 'incsearch' highlighting was cleared.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem: Cannot apply 'scrolloff' context lines at end of file
Solution: Add the 'scrolloffpad' option to keep 'scrolloff' context even
when at the end of the file (McAuley Penney).
closes: vim/vim#19040
https://github.com/vim/vim/commit/a414630393f81c9a5b8fa4d0fcc1287155f67751
Co-authored-by: McAuley Penney <jacobmpenney@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: Several win_T fields are declared as "int" or "char" but are
used strictly as boolean flags with TRUE/FALSE values. The
integer types obscure the boolean intent and are wider than
needed.
Solution: Change the following win_T members to bool (stdbool.h) and
update their assignments from TRUE/FALSE to true/false
accordingly.
The following conversions have been done:
- int -> bool (10 members):
w_set_curswant, w_botfill, w_old_botfill, w_do_win_fix_cursor,
w_popup_fixed, w_border_highlight_isset, w_cline_folded,
w_redr_status, w_arg_idx_invalid, w_has_scrollbar
- char -> bool (4 members):
w_topline_was_set, w_ru_empty, w_fold_manual, w_foldinvalid
No existing code compares these members against TRUE/FALSE explicitly or
uses ++/-- / bitwise ops on them, so only plain assignments are
affected.
Excluded:
- w_locked (recursion counter with ++/--),
- w_want_scrollbar (may hold -1 from dict_get_bool),
- w_winbar_height (used in arithmetic and exposed as number via
getwininfo()).
related: vim/vim#20005
closes: vim/vim#20008
https://github.com/vim/vim/commit/146d5da0d16b7ea9c767a978cf02384d0831eb92
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
- Unable to "pin" a window to prevent closing without specifically
being targeted.
- :fclose closes hidden windows (even before visible windows).
Solution:
- Add 'winpinned' window-local option. When set, window is skipped by
:fclose and :only. Pin the ui2 cmdline window (which should always be
visible), so that it is not closed by :only/fclose.
- Skip over hidden (and pinned) windows with :fclose.
Co-authored-by: glepnir <glephunter@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: w_locked can be bypassed when recursively set if not restored
to its prior value.
Solution: Rather than save/restore everywhere, just make it a count,
like other locks (Sean Dewar)
Requires the previous commit, otherwise b_nwindows will be wrong in
tests, which causes a bunch of weird failures.
closes: vim/vim#19728
https://github.com/vim/vim/commit/7cb43f286e55853cf21b9d8870a430390c1cc8f1
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
Currently, we recommend always inserting text above prompt-line in
prompt-buffer. This can be done using the `:` mark. However, although
we recommend it this way it can sometimes get confusing how to do it
best.
Solution:
Provide an api to append text to prompt buffer. This is a common
use-case for things using prompt-buffer.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: cannot display tabs for indentation
Solution: Add the "leadtab" value to the 'listchars' option to
distinguish between tabs used for indentation and tabs used
for alignment (HarshK97).
closes: vim/vim#19094
https://github.com/vim/vim/commit/8526d32647245b3b623986949e7807b4b353e624
Co-authored-by: HarshK97 <harshkapse1234@gmail.com>
|
| |
|
|
|
|
| |
Problem: Setting 'winhighlight' doesn't after setting global namespace
using nvim_win_set_hl_ns().
Solution: Check if using another namespace when setting 'winhighlight'
instead of disabling 'winhighlight' in nvim_win_set_hl_ns().
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: TabClosedPre may be triggered twice for the same tab page when
closing another tab page in BufWinLeave (after 9.1.1211).
Solution: Store whether TabClosedPre was triggered in tabpage_T
(zeertzjq).
Also fix the inconsistency that :tabclose! triggers TabClosedPre after
a failed :tabclose, but :close! doesn't even if there is only one window
in the tab page.
closes: vim/vim#19211
https://github.com/vim/vim/commit/9168a04e0c63c95eec643dab14a8e0a8933d90e7
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem: 'fsync' option cannot be set per buffer
Solution: Make 'fsync' option global-local
(glepnir)
closes: vim/vim#19019
https://github.com/vim/vim/commit/4d5b30372663e8ea356b25fe94334558c6ae283f
Co-authored-by: glepnir <glephunter@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#37056)
Problem: After :botright copen and closing the quikfix window, the
cursor ends up in the wrong window. The problem is fr_child
always points to the first (leftmost for FR_ROW, topmost for
FR_COL) child frame. When do :vsplit, the new window is
created on the left, and frame_insert() updates the parent's
fr_child to point to this new left window.
Solution: Create a snapshot before open the quickfix window and restore
it when close it (glepnir).
closes: vim/vim#18961
https://github.com/vim/vim/commit/b43f9ded7e98261e3e662a8e919f54e7399b0316
Co-authored-by: glepnir <glephunter@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: completion: complete_match() Vim script function and
'isexpand' option are not that useful and confusing
(after v9.1.1341)
Solution: Remove function and option and clean up code and documentation
(Girish Palya).
complete_match() and 'isexpand' add no real functionality to Vim. They
duplicate what `strridx()` already does, yet pretend to be part of the
completion system. They have nothing to do with the completion mechanism.
* `f_complete_match()` in `insexpand.c` does not call any completion code.
It’s just a `STRNCMP()` wrapper with fluff logic.
* `'isexpand'` exists only as a proxy argument to that function.
It does nothing on its own and amounts to misuse of a new option.
The following Vim script function can be used to implement the same
functionality:
```vim
func CompleteMatch(triggers, sep=',')
let line = getline('.')->strpart(0, col('.') - 1)
let result = []
for trig in split(a:triggers, a:sep)
let idx = strridx(line, trig)
if l:idx >= 0
call add(result, [idx + 1, trig])
endif
endfor
return result
endfunc
```
related: vim/vim#16716
fixes: vim/vim#18563
closes: vim/vim#18790
https://github.com/vim/vim/commit/cbcbff871224115c45bbd14582749a487c6fad30
Co-authored-by: Girish Palya <girishji@gmail.com>
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem: Cannot configure the inner foldlevel indicator for the
foldcolumn
Solution: Add "foldinner" suboption value to the 'fillchar' option
(Maria José Solano).
closes: vim/vim#18365
https://github.com/vim/vim/commit/1a691afd2717732c6f42dfe3278a9540db0d8110
Co-authored-by: Maria José Solano <majosolano99@gmail.com>
|
| |
|
|
|
|
|
|
|
|
| |
Problem: Option insecure flags not copied when splitting window.
Solution: Move window-local insecure flags to winopt_T and copy them
properly (zeertzjq).
closes: vim/vim#18434
https://github.com/vim/vim/commit/b3740f4b00a78701637a49445adeb20b13e6edf6
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: 'nowrap' in a modeline may hide malicious code.
Solution: Forcibly use '>' as 'listchars' "extends" if 'nowrap' was set
from a modeline (zeertzjq).
Manual `:setlocal nowrap` disables this behavior. There is a separate
problem with `:set nowrap` that also applies to some other options.
related: vim/vim#18214
related: vim/vim#18399
closes: vim/vim#18425
https://github.com/vim/vim/commit/9d5208a9313dd8b0d62c97af5485f1715af98a1c
Cherry-pick some test_modeline.vim changes from patches 9.0.{0363,0626}.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#35853)
Problem: completion: 'autocomplete' cannot be enabled per buffer
(Tomasz N)
Solution: Make 'autocomplete' global or local to buffer (Girish Palya)
fixes: vim/vim#18320
closes: vim/vim#18333
https://github.com/vim/vim/commit/0208b3e80a080740ff77a5661d0f65090e317d90
Co-authored-by: Girish Palya <girishji@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: TextChangedT fires depending on whether Nvim needs to update_screen
while in terminal mode. This makes little sense as redraws can be completely
unrelated to the terminal. Also, TextChanged could be fired from changes in
terminal mode after returning to normal mode.
Solution: trigger it when b:changedtick changes, like other such events. Happens
when invalid cells are refreshed, though is no longer affected by cursor
changes. Don't fire TextChanged from changes in terminal mode after leaving.
Unlike the other TextChanged* events, I've elected to not have it be influenced
by typeahead. Plus, unlike when leaving insert mode when no TextChangedI events
are defined, I don't trigger TextChanged when returning to normal mode from
changes in terminal mode (is that a Vim bug?)
Curiously, Vim's TextChangedT is different; it's tied to its terminal cursor
redraws, which triggers pretty eagerly (but is unaffected by unrelated redraws)
- usually *twice* when data is sent to the terminal (regardless of whether it
causes any visible changes, like incomplete escape codes; wasn't true for Nvim).
Not clear to me how this event was actually intended to work, but this seems to
make the most sense to me.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
F{func}
Problem: completion: cannot use autoloaded funcs in 'complete' F{func}
(Maxim Kim)
Solution: Make it work (Girish Palya)
fixes: vim/vim#17869
closes: vim/vim#17885
https://github.com/vim/vim/commit/1bfe86a7d37ea849078255f16f99ed69fbf205dc
Cherry-pick Test_omni_autoload() from patch 8.2.3223.
Co-authored-by: Girish Palya <girishji@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: not possible to anchor specific lines in diff mode
Solution: Add support for the anchoring lines in diff mode using the
'diffanchor' option (Yee Cheng Chin).
Adds support for anchoring specific lines to each other while viewing a
diff. While lines are anchored, they are guaranteed to be aligned to
each other in a diff view, allowing the user to control and inform the
diff algorithm what the desired alignment is. Internally, this is done
by splitting up the buffer at each anchor and run the diff algorithm on
each split section separately, and then merge the results back for a
logically consistent diff result.
To do this, add a new "diffanchors" option that takes a list of
`{address}`, and a new "diffopt" option value "anchor". Each address
specified will be an anchor, and the user can choose to use any type of
address, including marks, line numbers, or pattern search. Anchors are
sorted by line number in each file, and it's possible to have multiple
anchors on the same line (this is useful when doing multi-buffer diff).
Update documentation to provide examples.
This is similar to Git diff's `--anchored` flag. Other diff tools like
Meld/Araxis Merge also have similar features (called "synchronization
points" or "synchronization links"). We are not using Git/Xdiff's
`--anchored` implementation here because it has a very limited API
(it requires usage of the Patience algorithm, and can only anchor
unique lines that are the same across both files).
Because the user could anchor anywhere, diff anchors could result in
adjacent diff blocks (one block is directly touching another without a
gap), if there is a change right above the anchor point. We don't want
to merge these diff blocks because we want to line up the change at the
anchor. Adjacent diff blocks were first allowed when linematch was
added, but the existing code had a lot of branched paths where
line-matched diff blocks were handled differently. As a part of this
change, refactor them to have a more unified code path that is
generalized enough to handle adjacent diff blocks correctly and without
needing to carve in exceptions all over the place.
closes: vim/vim#17615
https://github.com/vim/vim/commit/0d9160e11ce4b921adff1e5621dd989ce96fb0f3
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
|
| |
|
|
|
|
|
|
| |
Problem:
Plugins cannot mark a buffer as "busy".
Solution:
- Add a buffer-local 'busy' option.
- Show a busy indicator in the default 'statusline'.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Cannot enter multiline prompts in a buftype=prompt buffer.
Solution:
- Support shift+enter (`<s-enter>`) to start a new line in the prompt.
- Pasting multiline text via OS paste, clipboard, "xp, etc.
|