improvise-3h9w: a captured commit is not refused for the cursor's cell

refused_here (from #286) ran before commit() consulted the capture and,
for the commit keys, judged the cell under the cursor. After a reframe
left the cursor on an aggregate, a captured editor's Enter was declined
on every retry. The commit-key guard now applies only to an editor that
captured nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-23 20:10:36 -07:00
parent 0458b43519
commit 3dad3b0954
3 changed files with 32 additions and 1 deletions
+8
View File
@@ -3064,6 +3064,14 @@ held window is `None`, `settle_opened` simply tries again on the next fold, and
the capture lands once the host projects the cell. #274 took #286 by merge
rather than porting the reader; the PR body says why.
**A captured commit is not judged by the cursor's cell either (improvise-3h9w).**
#286's `refused_here` declines a commit key whose cursor cell `i` would decline,
and waits on one that is unprojected. It runs in `step()` before `commit()`,
so it must skip an editor that captured its target: that commit writes, or
basis-refuses, the captured cell, whatever now sits under the cursor. The guard
is kept for an editor that captured nothing, which is the case it was written
for.
**What the commit is follows the capture too.** Whether `Enter` writes a value
or renames a coordinate is read off `opened.target()`, not off the cell under
the cursor (ChatGPT Codex on PR #274): a relayed reframe can leave the cursor on
+22
View File
@@ -5708,3 +5708,25 @@ captured cell stick. On the merged tree the rival that reads the capture
through the cursor's offsets (`opened_at_cursor` through `row_offset`/`col_offset`
rather than `cell_at_cursor`) fails exactly that case, with `["Jan/Revenue"]`
against `["Feb/Revenue"]`.
### a_captured_edit_commits_when_the_cursor_now_sits_on_an_aggregate
improvise-3h9w, a regression from merging #286 into #274, found by ChatGPT Codex
and the delta review at `8c28360f`. `step()` runs `refused_here` before
`commit()` consults the capture, and for the commit keys `refused_here` judged
the **cursor's** cell. A opens an editor on North/Cost and types `42`. B moves
Region to None, the relays reset A's cursor, and it now sits on an aggregate.
A's `Enter` was declined with "Cannot write to an aggregate" on every retry, no
frame was sent, and Esc lost the text, where `8d9de94e` wrote North/Cost. It
failed at the North/Cost assertion with `None`.
The vanished-rows test could not see this, because `unprojected` exempts an
empty grid, so no guard fired there. This case needs the cell under the cursor
to change **kind** while it stays projected.
- **Rival: `refused_here` without the `state.opened.is_some()` arm** (the state
before the fix). Fails only this test.
- **Not covered:** a captured editor whose cursor lands on a cell that is
inside the grid but outside the held window. The same arm exempts it, but no
test builds it, because every reframe here resets the cursor to the origin,
which is always inside the window.
+2 -1
View File
@@ -325,11 +325,12 @@ fn step(state: &ClientState, event: KeyEvent, name: &str, args: &[String]) -> St
}
/// A commit onto a cell `i` declines is refused as `committable_cell_key` refuses
/// it, out loud with the binding (ik6l); a cell op on an unprojected cell waits (7mro).
/// it (ik6l); a cell op on an unprojected cell waits (7mro). Not a captured commit (3h9w).
fn refused_here(state: &ClientState, name: &str) -> Option<String> {
let (row, col) = state.view.cursor().selected;
let waiting = unprojected(state, row, col).then(|| NOT_PROJECTED.to_string());
match name {
"commit-cell-edit" | "commit-and-advance-right" if state.opened.is_some() => None,
"commit-cell-edit" | "commit-and-advance-right" => declined_at(state, row, col).or(waiting),
"clear-cell" | "yank" | "paste" => waiting,
_ => None,