Skip to content

Fix gv after leaving visual-line or visual-block mode with Esc - #281

Open
jiaxuan wants to merge 1 commit into
replit:masterfrom
jiaxuan:fix-gv-after-esc
Open

jiaxuan wants to merge 1 commit into
replit:masterfrom
jiaxuan:fix-gv-after-esc

Conversation

@jiaxuan

@jiaxuan jiaxuan commented Oct 22, 2026

Copy link
Copy Markdown

V j <Esc> gv reselects a charwise selection instead of a linewise one. The same happens to <C-v> ... <Esc> gv, which reselects charwise instead of blockwise.

Cause. A typed <Esc> exits visual mode from handleEsc inside findKey, outside a vim operation. The setCursor in exitVisualMode then reports cursor activity. handleExternalSelection sees visual mode over an empty selection and calls exitVisualMode(cm, false), which records the last selection with its visualLine / visualBlock flags and clears them. Back in the outer call, updateLastSelection runs again with the flags already false, overwriting the correct record.

It shows up when vim handles <Esc> itself, for example with Prec.highest(vim()). With vim at default precedence, CodeMirror's own Escape binding collapses the selection first and only the inner exit runs.

Fix. exitVisualMode returns before recording again when the cursor move already ended visual mode.

Tests. The existing reselect_visual_line and reselect_visual_block tests leave visual mode by toggling V / <C-v>, which never takes this path. Two new tests leave it with <Esc>. Both fail without the fix, and the full suite passes with it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W2aBHqJtz3wmW7kAdNmsYS

A typed <Esc> exits visual mode from handleEsc in findKey, outside a vim
operation. The cursor move in exitVisualMode then reports cursor activity,
handleExternalSelection sees visual mode over an empty selection and exits
visual mode itself, recording the last selection with its linewise or
blockwise flags. Back in the outer exitVisualMode, updateLastSelection ran
again after those flags were cleared, so `V j <Esc> gv` and
`<C-v> j l <Esc> gv` reselected charwise.

An exit that the cursor move already made now returns before recording
again. The existing reselect tests leave visual mode by toggling V or
<C-v>, which never takes this path; two tests leave it with <Esc>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W2aBHqJtz3wmW7kAdNmsYS

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant