Skip to content

Commit d32787e

Browse files
author
SqlRush
committed
Support visual vim linewise X and S
1 parent 6e41065 commit d32787e

3 files changed

Lines changed: 28 additions & 2 deletions

File tree

docs/first-second-parity-audit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ M7 progress now includes:
253253
- `internal/tui`: Vim prompt editing now supports `/`, `?`, `n`, and `N` in visual and visual-line modes, returning from the search prompt to the active selection on Enter and preserving the original selection on Escape cancellation.
254254
- `internal/tui`: Vim prompt editing now supports `"{reg}` named register prefixes across normal/operator/visual yank, delete, and paste paths, including uppercase append registers, black-hole no-op handling, and cleanup of unused register selections after non-register commands.
255255
- `internal/tui`: Vim prompt editing now updates unnamed or selected named registers for normal-mode `x`/`X` character deletions while preserving dot-repeat replay for those delete commands.
256-
- `internal/tui`: Vim prompt editing now supports visual and visual-line `Y`/`D`/`C` linewise aliases, forcing characterwise selections to operate on whole selected lines while preserving linewise unnamed or named register contents.
256+
- `internal/tui`: Vim prompt editing now supports visual and visual-line `Y`/`D`/`C`/`X`/`S` linewise aliases, forcing characterwise selections to operate on whole selected lines while preserving linewise unnamed or named register contents.
257257
- `internal/session`: prompt history now persists image pasted-content metadata such as media type, filename, dimensions, and image-cache source path while still omitting inline base64 image bytes and text-paste hashes for images.
258258
- `internal/session`: prompt history loading now backfills missing image source paths from existing per-session image-cache files and refreshes the in-memory image path cache when those files exist.
259259
- `internal/tui`: interaction script key fields now accept DOM-style key event objects with `key`/`code` including `Numpad*`, extended numpad paren/hash/backspace codes, and punctuation key codes, legacy `keyIdentifier`, numeric `keyCode`/`which`/`charCode` including punctuation and numpad operators, `keypress.which` char-code replay, modifier booleans such as `ctrlKey`/`altKey`/`metaKey`/`shiftKey`, and modifier arrays, including wrapper payloads and modifier-only event filtering.

internal/tui/tui_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4500,6 +4500,17 @@ func TestREPLScreenVimVisualUppercaseLineOperators(t *testing.T) {
45004500
t.Fatalf("after visual \"aD screen = %#v", screen)
45014501
}
45024502

4503+
screen = NewREPLScreen(40, 8, nil)
4504+
screen.SetVimEnabled(true)
4505+
typePromptText(&screen, "one\ntwo\nthree")
4506+
screen.ApplyKey(ParseKey("\x1b"))
4507+
for _, seq := range []string{"g", "g", "j", "v", "l", "X"} {
4508+
screen.ApplyKey(ParseKey(seq))
4509+
}
4510+
if screen.VimMode != VimNormal || screen.Prompt.Text != "one\nthree" || screen.Prompt.Cursor != len([]rune("one\n")) || screen.VimRegister != "two\n" || !screen.VimRegisterLinewise {
4511+
t.Fatalf("after visual X screen = %#v", screen)
4512+
}
4513+
45034514
screen = NewREPLScreen(40, 8, nil)
45044515
screen.SetVimEnabled(true)
45054516
typePromptText(&screen, "one\ntwo\nthree")
@@ -4510,6 +4521,17 @@ func TestREPLScreenVimVisualUppercaseLineOperators(t *testing.T) {
45104521
if screen.VimMode != VimInsert || screen.Prompt.Text != "one\nthree" || screen.Prompt.Cursor != len([]rune("one\n")) || screen.VimRegister != "two\n" || !screen.VimRegisterLinewise {
45114522
t.Fatalf("after visual C screen = %#v", screen)
45124523
}
4524+
4525+
screen = NewREPLScreen(40, 8, nil)
4526+
screen.SetVimEnabled(true)
4527+
typePromptText(&screen, "one\ntwo\nthree")
4528+
screen.ApplyKey(ParseKey("\x1b"))
4529+
for _, seq := range []string{"g", "g", "j", "v", "l", "S"} {
4530+
screen.ApplyKey(ParseKey(seq))
4531+
}
4532+
if screen.VimMode != VimInsert || screen.Prompt.Text != "one\nthree" || screen.Prompt.Cursor != len([]rune("one\n")) || screen.VimRegister != "two\n" || !screen.VimRegisterLinewise {
4533+
t.Fatalf("after visual S screen = %#v", screen)
4534+
}
45134535
}
45144536

45154537
func TestREPLScreenVimGLineNavigationAndOperators(t *testing.T) {

internal/tui/vim.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ func (s *REPLScreen) applyVimVisualRune(r rune) ScreenEvent {
396396
s.applyVimVisualLineOperator('d')
397397
case 'C':
398398
s.applyVimVisualLineOperator('c')
399+
case 'X':
400+
s.applyVimVisualLineOperator('d')
401+
case 'S':
402+
s.applyVimVisualLineOperator('c')
399403
case 'y', 'd', 'c':
400404
s.applyVimVisualOperator(r)
401405
case 'p', 'P':
@@ -1616,7 +1620,7 @@ func vimNormalCommandUsesRegister(r rune) bool {
16161620

16171621
func vimVisualCommandUsesRegister(r rune) bool {
16181622
switch r {
1619-
case 'y', 'd', 'c', 'Y', 'D', 'C', 'p', 'P', 'x', 's':
1623+
case 'y', 'd', 'c', 'Y', 'D', 'C', 'X', 'S', 'p', 'P', 'x', 's':
16201624
return true
16211625
default:
16221626
return false

0 commit comments

Comments
 (0)