| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
With multicursors, an Insert-mode edit by a Lua/`<Cmd>` mapping or API
(nvim_put(), …) is live-previewed at the other cursors, but dropped at
ESC: the cascade replays _redo_, which does not contain such edits.
Solution:
When `<Cmd>`/Lua/RPC changes the buffer during Insert-mode, sync the
previews and restart the capture (like a non-captured cursor-move). The
edit stays as text.
- The mapping runs only at the primary. Its text is mirrored as-is
(similar to insert-completion). Re-running it per cursor would require
a "partial-remap" span replay, and breaks single-session plugins
(vim.snippet).
- Not during completion; redo already captures the pre-inserted
candidate on accept.
- Text typed before the edit is kept as mirrored, not replayed, so
per-cursor effects ('textwidth' wrapping, …) don't apply to it.
Known issues:
- "o"/"O"/"cc" with 'autoindent' followed by the mapping: the per-cursor
insert-entry replay is still pending, so the edit is lost.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This applies to the callsites which already used utf_ptr2CharInfo
and then utfc_next. There is more work to be done, but this
is a lagom bisectable unit.
A lot of code is still wounded by the historical distinction between
"low" characters (c < 128) and "high" characters, with the UTF-8
specific rules behind compiler flags and virtual function calls. As a
result, there are both ptr2cells() and utf_ptr2cells(). My work aims at
slowly reintegrating the realms. As such, we consider ptr2cells() the
"correct" abstraction as is matches what actually is printed in a
displayed message and buffer text without extra bells and whistles,
except for tabs.
|
| |
|
|
|
|
|
|
|
|
| |
Incremental cleanup. A lot of this logic really made sense only for vim in in
single-byte/DBCS modes, where the user got to program their own charset.
Now we are just using UTF-8 internally, so the meaning of each byte in context
is fixed.
I think 'isprint' and CT_PRINT_CHAR also are in time to say goodby, but that
will be a separate followup.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
InsertCharPre is triggered for stuffed text (".", i_CTRL-R, i_CTRL-A).
But that text was already transformed when it was typed: the `v:char`
result is appended to the redo buffer literally (`redo_append_lit()`).
So "." transforms it again, e.g. an autopair handler turns "()" into
"())".
Solution:
Skip InsertCharPre for stuffed text.
Precedent: `vgetorpeek()` disables abbreviations for stuffed text for
the same reason (it is post-expansion).
Macros are unaffected.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
padding (#41799)
Problem: In Virtual Replace mode, backspacing over a character that
replaced several multi-byte characters deletes the padding
that follows it, so the text after the cursor loses its
alignment.
Solution: In replace_do_bs() advance by the length of the character at
the current offset instead of always measuring the first
restored character (Volodymyr Chernetskyi).
After the original characters are restored, replace_do_bs() adds up
their screen width so it knows how much of the alignment padding to drop
again. The loop advanced "i" by mb_ptr2len(p) - 1, which always returns
the length of the *first* restored character rather than the length of
the character at the offset being looked at.
One backspace can restore more than one character, because a wide
character may have replaced several narrow ones. When those characters
do not all have the same byte length the index lands in the middle of a
character: chartabsize() then measures a trailing byte, counts it as an
unprintable <xx> worth four cells, and the inflated width makes the
following loop delete padding spaces that should have been kept.
call setline(1, 'aé xyz')
call feedkeys("gR\u4e00\<BS>\e", 'xt')
leaves "aéxyz" instead of restoring the original line. Going the other
way round ('éa') happens to work, since there the first character is the
longer one.
This has been wrong since the loop was added in Vim 7.0.
closes: vim/vim#21211
https://github.com/vim/vim/commit/5d934b1bdb803c652a521f04481f92b2c2fa029e
Co-authored-by: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
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:
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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().
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
automatic (#41535)
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#21158
https://github.com/vim/vim/commit/c8e432b266149960f77ed1da2ec5ac33a71d7e96
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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#21143
https://github.com/vim/vim/commit/1f56c351dedad288f79c89b6b6f64be762ec3b9b
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
`RedoBuf` is mostly indirection. It has a mild benefit as an "ownership"
signal but it counteracts the general goal of unifying how "redo state"
is passed throughout the system, tends to sprout redundant interfaces,
and reduces clarity.
Solution:
Add `CmdSpec.body` to hold the "prefixless" key sequence.
Reuse `CmdSpec` to represent a "redo" buf.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Redo prep is scattered/duplicated.
- `do_pending_operator()` has 3 prep blocks whose conditions must be in
sync with `atom_capture_op()`.
- insert.c, spell_suggest() hand-roll `redo_new()` + `redo_append_xx()`
sequences.
- prep_redo() has 2 roles, decided by `keys != NULL`.
Solution:
- `atom_capture_op()` is the "operator" entry point: capture, then
prep.
- Extract `prep_redo_visual()`, `atom_capturable()`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
There is no unified notion of a "user action".
Vim processes input by one-char-at-a-time, and mostly throws away any
hints it might gather about the user's action, with one exception: it
stores the last _edit_ action (the "redo buffer", encoded as
unstructured `["x][v][count]body` bytes).
Plugins can only observe individual keys (vim.on_key) and high-level
effects (TextChanged, CursorMoved).
Solution:
- Users can subscribe to `CmdAtom` events to handle any user action.
- Event is deferred; handlers cannot cancel or interfere with user
actions.
- Capture `CmdSpec` from the normal/insert/visual subsystems.
- typeahead/readahead stay unstructured (`buffheader_T`): they are key
streams, not commands.
- the redo/record buffers become `StringBuilder`: fewer
allocations/copies.
- Repurpose the input/redo engine to accept `CmdSpec` objects.
"atom": one repeatable unit of user input, as a resolved (post-mapping)
keysequence plus structured fields. Only user actions, not `:normal`,
API calls, or non-"t" `feedkeys`.
BREAKING: dot-repeat of an Insert session, replays the entire session
including cursor-moves (:help ins-repeat).
BREAKING: dot-repeat of a Visual operation, replays the selection
instead of operating on a fixed-size region.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: The channel source file is too big.
Solution: Move job related code to a new source file.
----
Move eval-related prompt-buffer API to src/nvim/nvim/eval/buffer.c.
https://github.com/neovim/neovim/pull/37743#issuecomment-3897416840
----
https://github.com/vim/vim/commit/8b5866ded6036f7adece26b6d16962bbd2d47842
Co-authored-by: Bram Moolenaar <Bram@vim.org>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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:
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.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problems:
1. Can't get individual parts of a key-chord separately: modifiers, key.
2. Can't separate a key-combo into individual key-chords.
Solution:
Enhance `vim.keycode()` to optionally return a structured parse result
as a list of key-chords:
- `key_raw` the key-chord (problem 2)
- `mod` the modifiers of `key_raw` (problem 1)
- `key_orig` the key part of the key-chord, only here if differing from `key`
(this doesn't solve any of the above mentioned problems, but it may provide
useful and it's (in terms of code) free)
- `key` a normalized version of `key_orig` (solving problem 1), example(the
first is `key_orig` and second is `key`): `lt` and `<`, `Bar` and `|` (in
`<C-Bar>`)
|
| | |
|
| |
|
|
|
|
|
|
|
| |
Problem: LSP completion commitCharacters are not handled. Typing a
commit character (e.g. `.`, `(`, `;`) while a completion item is
selected does not accept the item first.
Solution: Store commit characters as a flat string in complete-items.
Check it before completion stops, accept the match and let
the character be inserted normally.
|
| |
|
|
|
|
|
|
|
| |
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.
|
|
|
Problem:
- `edit.c` is an unnecessarily misleading and less-discoverable name
than `insert.c`.
- Numerous insert-mode related things are named with a `ins_` prefix.
- There is already a `insexpand.c` module...
Solution:
Rename `edit.c` => `insert.c`.
|