Problem: Nvim has many Lua APIs that start callback-driven work: timers,
jobs, libuv handles, and other event-loop tasks. Callers that need to
sequence or cancel that work have to build their own coroutine wrappers,
task bookkeeping, and cleanup rules. This makes async control flow hard
to share, test, and document.
Solution: Add `vim.async`, a structured-concurrency module vendored from
async.nvim. It provides task handles, await/pawait helpers,
sleep/timeout helpers, completion-order iteration, and semaphores on top
of Nvim's event loop.
The API follows the same broad model as Trio: async work has an owner,
tasks are awaited explicitly, and cancellation is cooperative. Include
generated vimdoc with an introductory overview and examples, a news
entry, and functional tests for the new module.
AI-assisted
Problem:
'guicursor' is not respected when extra cursors exist.
Per-cursor selection toggles Visual off, and the sandbox restores it
only after restore_current_state(), whose ui_cursor_shape() caches the
Normal shape.
Solution:
Restore Visual before restore_current_state().
Problem: there should be exactly one cell of padding between sections,
and exactly one cell of minimum padding between the left and the right.
- Spaces between sections waste space when a section is empty.
According to a comment in #33036, this was the reason to avoid `%k`
and implement the keymap section with a vim expression, but other
sections still have this problem.
- The diagnostics section wastes space because it is not entirely empty
when there are diagnostics in another buffer.
- The terminal exit code section can touch the right side, e.g. the
ruler, even though it belongs to the left side.
Solution:
- Use auto-hiding item groups (`%(` without width fields) to get rid of
unneeded spaces when a section shows no information.
This simplifies the 'showcmd' and 'keymap' sections in particular.
- As a slight simplification, `term_exitcode` is moved into the flags
section since it is formatted with square brackets like a flag.
- Count the diagnostics for the current buffer specifically.
- Ensure at least one cell of padding between the left and the right
side by adding a space next to the separator `%=`.
Problem: some sections are implemented with `%{%`, even though
reevaluation of the expression result is not needed.
This leads to otherwise needless %-escaping in `progress_status`.
Solution: use `%{` instead.
Problem: `%{` and `%{%` (without items) replace spaces with fillchars.
This looks out-of-place inside the terminal exit code section, and in
contrast to all other sections, the 'busy' section is surrounded by
fillchars, which looks inconsistent, and with some terminal-font
combinations, ◐ overlaps the fillchar, e.g. Alacritty & JetBrains Mono.
Solution: use non-breaking spaces U+202F to avoid fillchar substitution.
Problem: sections that appear/disappear frequently can make otherwise
more stable sections jump around a lot.
Solution: sort the sections on the right roughly by volatility:
'showcmd' in first place, 'keymap' next to the ruler.
Problem:
`shada_read()` rebuilds `v:oldfiles` for any "forced" read, which first
*clears* the list. For an in-memory caller such as multicursor, the list
is never repopulated. So `v:oldfiles` is empty after `Q` + edit.
Solution:
Rebuild `v:oldfiles` only when `kShaDaGetOldfiles` is requested.
`shada_read_everything()` (`:rshada[!]`, startup) always requests it.
old bug from 411a06c8b6
Problem:
During 'autocomplete', a completion-ending `<BS>` restarts completion
immediately. Multicursor insert-cascade skips replay (`edit()` refuses
to nest if compl/pum is active), so the mcursors do not update until
ESC.
Solution:
Flush pending keys in `TRIGGER_AUTOCOMPLETE`, just before autocomplete
restarts again.
Problem:
Insert entered by a Visual-mode operator mapping (`xnoremap c c`) does
not live-mirror at cursors.
Solution:
Decide `typed` from the Visual session's own provenance (`vatom`, which
spans the selection and knows whether it was user input) instead of only
negating it.
Problem: Drawing 'statuscolumn' leads to a heap-buffer-overflow if a
sign/number column comes after many items.
Solution: Avoid curitem >= stl_items_len when writing to stl_items.
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#21166f1b4549129
Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
Problem: NFA regexp matching is slower than necessary for ASCII text
because two indirect function calls are made for every
character.
Solution: Add an inline fast path for an ASCII byte that is not followed
by a composing character (Julien Voisin).
The main loop of nfa_regmatch() fetched the current character and its
byte length with two calls through the mb_ptr2char and mb_ptr2len
function pointers on every character. These pointers cannot be inlined,
yet for ASCII text, which is the common case, both merely return the byte
and a length of one.
Handle that case inline. NUL is checked first so that reading the next
byte cannot go past the end of the line, and the "next byte is ASCII"
condition matches the check in utfc_ptr2len(), so a base character
followed by a composing character still falls through to the original
calls.
A "perf stat -e instructions" on a full scroll of a 60000 line C file with
syntax highlighting enabled shows an instructions count reduction of 4%.
closes: vim/vim#2117958390ca285
Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
Problem: Cursor correction can move the cursor up at the end of the
buffer when 'scrolloffpad' is enabled (gx089).
Solution: Allow missing context below EOF in cursor_correct(). Add
regression tests for CTRL-D and CTRL-E (Seunghee Kim).
fixes: vim/vim#21096
closes: vim/vim#211886a3db67a52
Co-authored-by: SeungheeKim <ksh368@naver.com>
Problem:
With follow-mode ("q="), an 'operatorfunc' that only moves the cursor
does not cascade.
Solution:
Update the `effect` condition to include cursor-moves if follow-mode is
active.
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:
An atom queued in buffer A cascades on B's cursors if the mapping ends
in B ("nnoremap X x:bnext<CR>").
Solution:
Check the atom's origin buffer (`CmdAtom.origin.buf`).
Note: This does not preclude mappings etc from doing work in temporary
throwaway buffers, as long as they return to the origin buffer.
Problem:
If an edit cascades to cursor(s) that happen to be within a closed fold,
the edit acts on the fold itself (`:h fold-behavior`). E.g. "dd" deletes
the entire fold, not the cursor's line within the fold.
Solution:
Check `mc_replaying()` in `hasAnyFolding()`, so folds are ignored during
a multicursor cascade. This means multicursor always replays relative to
text *within* the fold.
Problem: NFA regexp matching is slower than necessary because addstate()
tracks the recursion depth in a static variable.
Solution: Pass the recursion depth as a function parameter so it stays in a
register instead of being spilled to memory around every recursive
call (Julien Voisin).
addstate() is called very frequently and recursively. Storing the depth
counter in a static variable forces the compiler to reload and store it in
memory around each recursive call, since it cannot prove the recursion does
not modify it. Passing it as a parameter keeps it in a register and drops
the increment/decrement bookkeeping on every return path. The recursion
limit behavior is unchanged.
This reduces the instruction count of NFA matching by roughly 4% on
state-heavy patterns. Benchmarking was done with something like:
```
set re=0
let s:word = repeat('abc123 def456 ghijk_lmnop QRSTUV wxyz0 ', 4000)
for i in range(120)
let s = s:word | let s = substitute(s, '\%#=2\(\a\+\)\(\d\+\)', '\2\1', 'g')
let s = s:word | let s = substitute(s, '\%#=2\a\+\d\+', 'X', 'g')
call matchstr(s:word, '\%#=2\(\a\|\d\|_\)\{3,}')
endfor
qa!
```
and `taskset -c 7 perf stat -e instructions ./vim -u NONE -N -X -es -S /tmp/nfabench/count.vim`
closes: vim/vim#212020e47c9612e
Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
Problem: With 'wildmode' set to list:full the matches are listed but the
wildmenu is not shown, although it is "full" that starts
wildmenu mode (zeertzjq).
Solution: List the matches and show the menu, as the two behaviors in
the same phase ask for. The menu is left to the phases that
ask for it, so that "list" on its own still only lists
(Hirohito Higashi).
fixes: vim/vim#21196closes: vim/vim#21205fa1ddffcce
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem: With 'wildmode' set to list:full, matches are listed but the
first match is not completed on the first Tab press (rendcrx).
Solution: Do not suppress selection when list and full are active in
the same completion phase. Add regression tests for file
completion, comma-separated phases and noselect precedence
(Seunghee Kim).
fixes: vim/vim#19532
related: vim/vim#18088
closes: vim/vim#2118154c988c6c5
Co-authored-by: SeungheeKim <ksh368@naver.com>
Other (squashed) commits:
fix(tui): emit ui_send output atomically with the frame
Problem:
tui_ui_send() writes directly to the TTY, bypassing the output buffer.
Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or
visual-dot-repeat) always arrive in a separate TTY write from the frame
they were computed for. This manifests as "tearing", or e.g. in the case
of multicursor the terminal renders text with stale cursor overlays.
Solution:
- tui_ui_send(): while a frame is being assembled (pending invalid
regions or buffered output), buffer instead of writing directly.
- Out-of-frame sends (tty queries, clear-on-disable) still write
immediately.
- mcursor.lua: emit the terminal-cursor update at the end of the redraw
cycle (`on_end`, when screen positions are final) instead of
vim.schedule().
Problem:
Literal path comparison ignored one trailing slash for every buffer name,
including URIs. Generic URI syntax does not make a non-empty path
equivalent to the same path with a trailing slash, so distinct URI
buffers collapsed into one.
Solution:
Require equal lengths when comparing URI buffer names, while retaining
trailing-separator normalization for filesystem paths.
AI-assisted
Problem:
`shorten_fnames()` always redraws the statusline/tabline, even if no
buffer name changed. Since b296666e a temp context-switch
(`win_execute()`, `vim._with{win=}`) restores the CWD, so every such
switch flickers the message area.
Solution:
Redraw only if `shorten_buf_fname()` actually changed a name.
vim-patch:8.2.0992: Vim9: crash when using :import in the Vim command
vim-patch:8.2.2872: Python tests fail without the channel feature
vim-patch:8.2.3589: failure when "term_rows" of term_start() is an unusual value
vim-patch:8.2.3597: Vim seems to hang when writing a long text to a terminal
vim-patch:8.2.3761: focus change is not passed on to a terminal window
vim-patch:8.2.4157: terminal test fails because Windows sets the title
vim-patch:8.2.4535: filename modifer ":8" removes the filename
vim-patch:8.2.4758: when using an LSP channel want to get the message ID
vim-patch:0646047b6 runtime(doc): clarify term_start() I/O behavior for Unix pty and MS-Windows ConPTY
vim-patch:9.2.0412: channel: term_start() out_cb/err_cb no longer deliver raw chunks
vim-patch:9.2.0420: channel: cannot handle binary data via channel callbacks
vim-patch:9.2.0565: [security]: out-of-bounds read in update_snapshot()
vim-patch:ba43008a2 runtime(doc): Update vim9.txt revisions, standardizing SS1,3-7
vim-patch:9.2.1013: [security]: out-of-bounds access in libvterm CSI 8 t resize
vim-patch:9.2.1021: GTK: Cursor blinks irregularly
vim-patch:4b2d42c43 CI: Bump github/codeql-action
vim-patch:9.2.1022: popup: width changes while scrolling
vim-patch:9.2.1023: GvimExt: destructors of polymorphic classes are not virtual
vim-patch:8.2.3979: Vim9: the feature is not mentioned in the right places
vim-patch:9.0.0058: Win32: cannot test low level events
vim-patch:9.0.1604: errors from the codestyle test are a bit confusing
vim-patch:3052bdb: runtime(doc): update the default value for 'isk' on Windows
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: 5ac2e47acc
Problem:
An operator completed by a Lua `:omap` textobject emits
`CmdAtom.type="mapping"` (lhs-only, no keys) instead of `type="operator"`.
Analysis:
`atom_redo_set()` declined K_LUA, though the prepped redo
("op" + K_LUA + id + CR) is exactly what "." replays. A no-edit "g@"
emits nothing at all.
Solution:
- `atom_redo_set`: don't decline K_LUA; the redo route now captures the
operator atom.
- `atom_capture_cmd`: don't early-return if the frame has prepped redo.
- op_function(): save/restore redobuff when invoking 'operatorfunc',
like `call_user_func()` does for Vimscript. (Else the Lua callback
may clobber the prepped "g@" redo / dot-repeat.)
fix#41482
TODO:
- async Lua (timer/vim.schedule) can still clobber the pending dot-repeat...
Problem: LPeg is hosted on a single unreliable external hoster, forcing
is to mirror it in neovim/deps, which adds maintenance friction. Also,
we have already vendored the Lua `re.lua` module.
Solution: Vendor all of LPeg v1.1.0; as development is not very active
anymore, this should not add much overhead (and allow us to simplify in
particular the Zig build scripts).
Note: LPeg defines a `luaL_newlib` macro for Lua 5.1, which conflicts
with LuaJIT's extension. This requires inlining the macro defined in
`lptypes.h` and used in `lptree.c`; see README.md for the patch.
Nvim uses utf8proc or an older process involving "src/unicode/"
and "download-unicode-files.sh" to decouple unicode characters
from "mbyte.c".
These unicode patches should be auto N/A but the diff hunk xfuncname
is wrong for utf_char2cells().
Is it because of the `#ifdef`?
Need a volunteer to inspect if these patches still have relevant
changes
Nvim
```c
/// same as utf_composinglike but operating on UCS-4 values
bool utf_iscomposing(int c1, int c2, GraphemeState *state)
{
return (!utf8proc_grapheme_break_stateful(c1, c2, state)
|| arabic_combine(c1, c2));
}
```
Vim
```c
/*
* Return TRUE if "c" is a composing UTF-8 character. This means it will be
* drawn on top of the preceding character.
* Based on code from Markus Kuhn.
*/
int
utf_iscomposing(int c)
{
// Sorted list of non-overlapping intervals.
// Generated by ../runtime/tools/unicode.vim.
static struct interval combining[] =
{
{0x0300, 0x036f},
{0x0483, 0x0489},
{0x0591, 0x05bd},
// ...
{0x0300, 0x036f},
{0x0483, 0x0489},
{0x0591, 0x05bd},
};
return intable(combining, sizeof(combining), c);
}
```
Problem: A completion asked for with CTRL-X CTRL-O while
'autocompletedelay' is running is given the look of an
automatic one, the implicit "noselect" among it.
Solution: Turn autocompletion off where a typed key takes the completion
over. A completion already on screen goes on being what it
was (Hirohito Higashi).
closes: vim/vim#21158c8e432b266
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem: A SwapExists autocmd can re-open the buffer being edited,
causing ml_close() to free the memfile that
ml_open_file() still holds a local pointer to, causing
use-after-free.
Solution: After findswapname() returns, verify that buf->b_ml.ml_mfp
is still the same as the copy mfp we hold.
closes: vim/vim#211717aecb2cca8
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem:
The Vim "stuff" concept breaks the ability to reason about the call
stack and thus the boundaries of a `CmdAtom`: a stuffed translation ("x"
=> "dl") defers to the main loop. This "continuation" must be modeled in
`CmdAtom`, by checking global flags at undefined times, during undefined
circumstances.
Solution:
- After a stuffed "translation", eagerly execute the stuff buffer
(`exec_stuffed()`).
- Delete the CmdAtom "continuation" junk.
Note:
- op_colon runs its cmdline "nested", but that's fine because operators
already nest interactive sessions there (op_change runs edit()), and
the cmdline is frameless so the operator's frame can own/capture it.
Problem:
If an autocommand handler focuses the tab page we're closing during a
`:tabonly` (with some conditions), we hit an assert failure in
`win_close_othertab()`.
For this to occur, we need:
- `nvim_buf_delete()` to trigger `close_windows()` (as is done in
`cmdwin.lua`'s `_cleanup()`)
- `close_windows()` then calls `win_close_othertab()`, removing the
window (`win_free_mem()`)
- then in the caller, `tabpage_close_other()`, the loop continues (we
don't detect `tp_lastwin == wp` since we've unlinked the window)
- the loop assumes that `curtab != tp`
but we've refocused `curtab` so the `ex_win_close()` call passes `tp` as
`curtab`, causing the assert to fail
Solution:
Detect the focus of `curtab` and abort closing the tab.
Problem:
gen_help_html.lua only outputs HTML, but Typst is useful for producing PDFs.
Solution:
Add gen_one_typ() and ts_node_to_typ(), which mirror the existing
gen_one_html() and ts_node_to_html().
Problem:
Undo places the cursor wherever the cursor happened to sit at "save
time" (`uh_cursor` is sampled lazily on the first change).
Examples:
- `i` preserves, but `a` does not
- `diw`, `atest<Esc>`, `d^` abandon the original position
- `D`, `o` restore it (by accident).
Solution:
`composite` tracks the pending atom (and its `origin`) across frames.
A `stuffed` continuation frame inherits the `origin` + prepped redo.
Store `origin` info in the undo header, so undo can restore it.
- Not for a mid-command undo break (i_CTRL-G_u).
- Undoing a mapping restores where the mapping started (which
technically may be different than where the "edit" started).
Problem: `restore_size` is scoped to all of `makeopens()`, so a window
excluded by 'sessionoptions' latches it off for every tabpage written
afterwards: with `sessionoptions-=terminal`, a terminal in tab 2 makes
tab 3 restore with `wincmd =` instead of its stored sizes.
Solution: Recompute it per tabpage.
Problem:
An insert-session entered by a scheduled `feedkeys('i','n')` is
classified on entry (as "not typed"), and not reevaluated after that,
thus user input following it is not captured.
Repro: an `:imap` that does `feedkeys('<esc>','n')` and schedules
re-entering insert, emits one CmdAtom for the first press, then nothing
else.
Solution:
Sample `maptick` (ticked by `gotchars()` on typed input, including
mappings) at session start; if it advanced by session end, the session
is user input.
I got annoyed about so many repeated `win_float_pos` events
for the popupmenu. This fixes some of them but not all of them.
vibe-less explanation: `need_highlight_changed = true` is very expensive
should not be needed when using a window-local highlight namespace. This
was only necessary when overriding the global highlight namespace. This
can instead be handled by using the correct `hl_attr_active` instead of
`highlight_attr`.
Also `pum_grid.pending_comp_index_update` can be cleared when using
win_float_pos prior to redraw.
I wanted to add a test for no repeated win_float_pos event in the same
redraw:flush cycle but that requires deeper cleanups, like
getting rid of crazy redraw panic intermingled deep into insexpand.c
(if "state" is correct, a single update_screen() after the weird
multilayer recursive dance should be enough.)
Problem:
`nlua_pcall()` references `_G.debug.traceback`. If user code deletes it
or breaks it some other way, various Lua features are broken.
_G.debug = nil
vim.schedule(function() end)
vim.wait(100)
E5113: Lua chunk: attempt to index a nil value
stack traceback:
[C]: in function 'loop_poll'
[string "vim/_core/editor"]:176: in function 'wait'
crash.lua:3: in main chunk
PANIC: unprotected error in call to Lua API (attempt to index a nil value)
Solution:
Check `_G.debug.traceback` before using it as errfunc. If it's broken,
omit the traceback and say so in the error message.
Note: We could cache `_G.debug` in LUA_REGISTRYINDEX on startup, but
that would prevent plugins from providing custom functionality there
(and we happen to do so in `tui_spec.lua` for example).
libvterm reads the first three sub-parameters of an SGR 38:2 or 48:2 sequence
as R:G:B, so a colour space id shifts the channels: the empty slot becomes red
via CSI_ARG_MISSING truncating to 255, and green and blue move over one.
Skip the colour space id when the colon-separated group holds more than three
arguments. The group length comes from CSI_ARG_HAS_MORE rather than the raw
argument count, so a following semicolon-separated parameter is not consumed.
vim-patch:8.1.2195: Vim does not exit when the terminal window is last window
vim-patch:8.1.2219: no autocommand for open window with terminal
vim-patch:8.2.1160: Vim9: memory leak in allocated types
vim-patch:8.2.2331: Vim9: wrong error when modifying dict declared with :final
vim-patch:8.2.4153: MS-Windows: Global IME is no longer supported
vim-patch:8.2.4586: Vim9: no error for using lower case name for "func" argument
vim-patch:9.0.0627: "const" and "final" both make the type a constant
vim-patch:9.0.1605: crash when calling method on super in child constructor
vim-patch:9.0.1760: vim9 class problem with new() constructor
vim-patch:9.1.0050: Win32 Keyboard handling is sub-optimal
vim-patch:9.1.0270: a few minor issues to fix
vim-patch:fb745756d runtime(doc): add MsgArea to 'highlight' option description
vim-patch:f0837ba0b runtime(doc): In builtin overview use {buf} as param for appendbufline/setbufline
vim-patch:6081c1789 runtime(doc): update help-toc description
vim-patch:2afdb3a65 runtime(doc): Fix minor typo in options.txt
vim-patch:ba0062b0c runtime(helptoc): the helptoc package can be improved
vim-patch:9340aa1bf runtime(helptoc): add s keymap to split and jump to selected entry
vim-patch:b2e21cccc runtime(doc): Tweak documentation in vi_diff.txt
vim-patch:3913f13a7 runtime(doc): Improve :help builtin-function-list table formatting
vim-patch:b8f58dd69 runtime(doc): Fix typos in version9.txt
vim-patch:9.2.0973: Vim9: internal error when a class member is initialized with a closure
vim-patch:9.2.0974: tests: Test_clientserver_serverlist_list() is flaky
vim-patch:9.2.0975: Vim9: assignment to a member of an object member fails
vim-patch:9.2.0977: tests: test_terminal_visual_empty_listchars() is flaky
vim-patch:9.2.0988: tests: Test_terminal_csi_resize_oob() returns early
vim-patch:9.2.0989: libvterm: hang when rendering REP with no preceding char
vim-patch:9.2.0990: libvterm: crash when a scroll region outlives a resize
vim-patch:9.2.0992: popup filter gets the key at the hit-enter prompt
vim-patch:9.2.0994: Vim9: No error for :open during compilation
vim-patch:b618f7ea1 CI: Bump github/codeql-action
vim-patch:b7e0c1cb3 runtime(doc): correct typo in bug report in version5.txt
vim-patch:632abba51 runtime(doc): fix typos and grammar in CONTRIBUTING.md
vim-patch:9.2.0999: serverlist() fails when there is no connection to the server
vim-patch:9.2.1000: Vim9: listener_add() fails when given only a callback
vim-patch:9.2.1003: popup: border is not shown when the popup does not fit
vim-patch:3e46ee723 patch 9.2.1010: compile error when folding feature is disabled
Problem: ins_compl_dict_alloc() builds the same dict as
fill_complete_info_dict().
Solution: Call fill_complete_info_dict() instead (glepnir).
closes: vim/vim#21140303a153694
Problem: A function used through 'omnifunc' or 'complete' is called the
same way whether 'autocomplete' started the completion or a
key asked for one, so it cannot answer differently.
Solution: Report which of the two it is in complete_info() as "auto". It
is returned only when asked for in {what}, so what
complete_info() says by itself does not change
(Hirohito Higashi).
closes: vim/vim#211431f56c351de
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem: backupcopy=auto overwrites a file in place when umask is restrictive.
The probe treats permission restore as impossible and writes in
place, keeping the same inode.
Solution: When creating the probe file, open() applies umask, so a 0644
file becomes 0600 with umask 0077. Use fchmod() to fix the
permissions of the probe (Pranav Dwivedi).
closes: vim/vim#21137fd8aea135d
Co-authored-by: Pranav Dwivedi <dwivedipranav2021@gmail.com>