<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rneovim.git/runtime/lua/vim/_meta/events.lua, branch master</title>
<subtitle>Neovim fork with Rahm's personal hacks.</subtitle>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/'/>
<entry>
<title>feat(cmdatom): mappings capture continuation</title>
<updated>2026-08-22T15:29:34+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-08-21T18:04:24+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=47cd769ed5a62db81f4c1d836902bf6c4c43ebd5'/>
<id>47cd769ed5a62db81f4c1d836902bf6c4c43ebd5</id>
<content type='text'>
Problem:
A mapping that ends mid-operation (`nnoremap ,D d`) emits a content-free
"mapping" atom plus a `pending` field, and the "continuation" motion
arrives as a sibling atom. Consumers must stitch the two together (which
has broken cases, e.g. Insert-opening mappings (",i") lose their session
entirely).

- ",i": the session atom is dropped bc the mapping RHS is consumed
  before the session starts (typebuf_maplen()==0), so
  atom_is_user_input()=false.
- ":normal"-in-opfunc: the opfunc internal "v..y" session (a) became
  kVatomTyped just because the deferred composite was open, masking the
  real operator capture via atom_captures, and (b) its nested frames
  re-derived the outer redo.
- "Motion" based on `moved=true`, has false negatives.
- `CmdAtom.remap` is unnecessary, and clutters the docs/usage.

Solution:
- Introduce `frame_id` to identify CmdFrames.
- Classify `type=motion` better, via `NV_MOTION` flag on the `nv_cmds` table.
- Drop `CmdAtom.pending`, `CmdAtom.remap`.
- Defer atom_composite_end() at the clock edge while an operator is
  pending, Visual is active, or `restart_edit` is set: the composite
  keeps collecting, so the continuation is captured in the mapping atom.
- ",i": Now an open composite counts as user input.
- ":normal"-in-opfunc: Now handled correctly.
- `remap` is now decided by `composite.payload || 0 subatoms`.
  atom_payload_mark() records the read the resolution never captures.
- `toplevel` is now decided by `CmdFrame.parent == NULL`.

before/after:

    INPUT       BEFORE                             AFTER
    ---------------------------------------------------------------------
    ,D w        {mapping lhs=,D pending=operator}  {operator lhs=,Dw keys=dw}
                + {operator keys=dw}
    ysiw"       {mapping lhs=ys pending=operator}  {operator lhs=ysiw" keys=g@iw"}
                + {operator lhs=g@iw"}
    ,v d        {mapping pending=visual}           {visual lhs=,vd keys=viwd}
                + {visual lhs=viwd}
    ,i XY&lt;Esc&gt;  {normal keys=i lhs=,iXY&lt;Esc&gt;}      {insert keys=1iXY&lt;Esc&gt; text=XY}
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
A mapping that ends mid-operation (`nnoremap ,D d`) emits a content-free
"mapping" atom plus a `pending` field, and the "continuation" motion
arrives as a sibling atom. Consumers must stitch the two together (which
has broken cases, e.g. Insert-opening mappings (",i") lose their session
entirely).

- ",i": the session atom is dropped bc the mapping RHS is consumed
  before the session starts (typebuf_maplen()==0), so
  atom_is_user_input()=false.
- ":normal"-in-opfunc: the opfunc internal "v..y" session (a) became
  kVatomTyped just because the deferred composite was open, masking the
  real operator capture via atom_captures, and (b) its nested frames
  re-derived the outer redo.
- "Motion" based on `moved=true`, has false negatives.
- `CmdAtom.remap` is unnecessary, and clutters the docs/usage.

Solution:
- Introduce `frame_id` to identify CmdFrames.
- Classify `type=motion` better, via `NV_MOTION` flag on the `nv_cmds` table.
- Drop `CmdAtom.pending`, `CmdAtom.remap`.
- Defer atom_composite_end() at the clock edge while an operator is
  pending, Visual is active, or `restart_edit` is set: the composite
  keeps collecting, so the continuation is captured in the mapping atom.
- ",i": Now an open composite counts as user input.
- ":normal"-in-opfunc: Now handled correctly.
- `remap` is now decided by `composite.payload || 0 subatoms`.
  atom_payload_mark() records the read the resolution never captures.
- `toplevel` is now decided by `CmdFrame.parent == NULL`.

before/after:

    INPUT       BEFORE                             AFTER
    ---------------------------------------------------------------------
    ,D w        {mapping lhs=,D pending=operator}  {operator lhs=,Dw keys=dw}
                + {operator keys=dw}
    ysiw"       {mapping lhs=ys pending=operator}  {operator lhs=ysiw" keys=g@iw"}
                + {operator lhs=g@iw"}
    ,v d        {mapping pending=visual}           {visual lhs=,vd keys=viwd}
                + {visual lhs=viwd}
    ,i XY&lt;Esc&gt;  {normal keys=i lhs=,iXY&lt;Esc&gt;}      {insert keys=1iXY&lt;Esc&gt; text=XY}
</pre>
</div>
</content>
</entry>
<entry>
<title>feat(cmdatom)!: eliminate the need for vim-repeat #41414</title>
<updated>2026-08-21T17:42:17+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-08-21T17:42:17+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=64236573525c257ecd7e268b255571328d4871c8'/>
<id>64236573525c257ecd7e268b255571328d4871c8</id>
<content type='text'>
Problem:
- `lhs` is not fully realized. E.g. for a "payload" mapping
  `lhs` omits the `getchar()` payload during a mapping (vim-surround
  `ds'` reports `lhs="ds"`). This means plugins like vim-repeat are
  still needed...
- The "delta" fields of a CmdAtom are calculated too late.
  - `&lt;abuf&gt;` and `changed` check whatever (wrong) buffer a command
    (":bnext") might land in.
  - CTRL-W_w between two windows on the same buffer reports type="motion".

Solution:
- `CmdOrigin` samples (buf/win/cursor/changedtick) at each "scope" entry
  (CmdFrame, composite, Visual session, insert session).
- `dd&lt;C-w&gt;l` reports `changed=true` for the buffer it edited, regardless
  of where the cursor ends up.
- New fields:
  - `pos`: cursor position at command start.
  - `moved`: indicates whether the cursor moved (in same buffer).
  - `undoseq`: undo state at settlement.
- lhs now includes the payload: "ds)" reports lhs="ds)" instead of "ds".
  - Easy for users to "replay" any atom.
- Rename: type "command" =&gt; "normal", "ex" =&gt; "excmd"; `arg` =&gt; `cmdarg`
- Drop `cascade` field (no reason to expose it)</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
- `lhs` is not fully realized. E.g. for a "payload" mapping
  `lhs` omits the `getchar()` payload during a mapping (vim-surround
  `ds'` reports `lhs="ds"`). This means plugins like vim-repeat are
  still needed...
- The "delta" fields of a CmdAtom are calculated too late.
  - `&lt;abuf&gt;` and `changed` check whatever (wrong) buffer a command
    (":bnext") might land in.
  - CTRL-W_w between two windows on the same buffer reports type="motion".

Solution:
- `CmdOrigin` samples (buf/win/cursor/changedtick) at each "scope" entry
  (CmdFrame, composite, Visual session, insert session).
- `dd&lt;C-w&gt;l` reports `changed=true` for the buffer it edited, regardless
  of where the cursor ends up.
- New fields:
  - `pos`: cursor position at command start.
  - `moved`: indicates whether the cursor moved (in same buffer).
  - `undoseq`: undo state at settlement.
- lhs now includes the payload: "ds)" reports lhs="ds)" instead of "ds".
  - Easy for users to "replay" any atom.
- Rename: type "command" =&gt; "normal", "ex" =&gt; "excmd"; `arg` =&gt; `cmdarg`
- Drop `cascade` field (no reason to expose it)</pre>
</div>
</content>
</entry>
<entry>
<title>feat(input)!: CmdAtom event #41297</title>
<updated>2026-08-14T13:30:31+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-08-14T13:30:31+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=64a301184ef39a0653c99c8edc1b63cd3fd16236'/>
<id>64a301184ef39a0653c99c8edc1b63cd3fd16236</id>
<content type='text'>
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.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.</pre>
</div>
</content>
</entry>
<entry>
<title>fix(tui): attribute `TermResponse` to source channel #40330</title>
<updated>2026-06-23T10:19:56+00:00</updated>
<author>
<name>Barrett Ruth</name>
<email>62671086+barrettruth@users.noreply.github.com</email>
</author>
<published>2026-06-23T10:19:56+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=db30608058db402de37be7a1d33fa60b7fc7de83'/>
<id>db30608058db402de37be7a1d33fa60b7fc7de83</id>
<content type='text'>
Problem: Attach-time terminal probes cannot distinguish responses from
different attached UIs.

Solution: Identify the UI by RPC channel id in `TermResponse` and make
`vim.tty.request()` filter responses by channel.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem: Attach-time terminal probes cannot distinguish responses from
different attached UIs.

Solution: Identify the UI by RPC channel id in `TermResponse` and make
`vim.tty.request()` filter responses by channel.</pre>
</div>
</content>
</entry>
<entry>
<title>feat(events): add TabMoved autocommand event #24137</title>
<updated>2026-05-16T17:55:42+00:00</updated>
<author>
<name>yashlala</name>
<email>yash@yashlala.com</email>
</author>
<published>2026-05-16T17:55:42+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=7d99104058fd2653903830c2b39b42d80092e646'/>
<id>7d99104058fd2653903830c2b39b42d80092e646</id>
<content type='text'>
Problem:
No way to handle a "tab moved" event.
Use-case: tabline plugins may cache tab labels, and need to know when to
invalidate their cache.

Solution:
Add a `TabMoved` event that triggers whenever tabs are reordered via `:tabmove`
or via mouse click-and-drag.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
No way to handle a "tab moved" event.
Use-case: tabline plugins may cache tab labels, and need to know when to
invalidate their cache.

Solution:
Add a `TabMoved` event that triggers whenever tabs are reordered via `:tabmove`
or via mouse click-and-drag.</pre>
</div>
</content>
</entry>
<entry>
<title>docs: misc #39045</title>
<updated>2026-04-18T19:38:59+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-04-18T19:38:59+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=54398c587473c0f1d96b601a281477e184865401'/>
<id>54398c587473c0f1d96b601a281477e184865401</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>docs(events): Lua types for autocmd event-data #38518</title>
<updated>2026-04-18T17:17:45+00:00</updated>
<author>
<name>Aditya Malik</name>
<email>102025295+alarcritty@users.noreply.github.com</email>
</author>
<published>2026-04-18T17:17:45+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=2cb240319b61eb98abcaae08b3c0a6d98fce53ac'/>
<id>2cb240319b61eb98abcaae08b3c0a6d98fce53ac</id>
<content type='text'>
Problem:
  No LuaLS types for event-data fields (ev.data). Types are only
  documented ad hoc in scattered locations.

Solution:
  Add runtime/lua/vim/_meta/events.lua defining vim.event.&lt;name&gt;.data
  classes for events that provide ev.data. Reference the types from
  each event's help in autocmd.txt, lsp.txt, and pack.txt.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
  No LuaLS types for event-data fields (ev.data). Types are only
  documented ad hoc in scattered locations.

Solution:
  Add runtime/lua/vim/_meta/events.lua defining vim.event.&lt;name&gt;.data
  classes for events that provide ev.data. Reference the types from
  each event's help in autocmd.txt, lsp.txt, and pack.txt.</pre>
</div>
</content>
</entry>
</feed>
