Skip to content

Commit c459d62

Browse files
author
SqlRush
committed
Support visual vim g case operators
1 parent aa13976 commit c459d62

3 files changed

Lines changed: 51 additions & 1 deletion

File tree

docs/first-second-parity-audit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ M6 progress now includes:
237237
M7 progress now includes:
238238

239239
- `internal/tui`: lightweight terminal frame renderer using ANSI clear/home/cursor control, message/status/prompt/dialog components, prompt input editing including shared kill-ring state, shift-enter multiline prompt input, line-local multiline prompt ctrl-a/ctrl-e/ctrl-u/ctrl-k editing plus multiline prompt wrap/render/cursor placement, ctrl-b/ctrl-f/ctrl-u/ctrl-k/ctrl-w line editing, ctrl-p/ctrl-n prompt and reverse-search navigation, alt-b/alt-f/alt-d/alt-backspace word editing, ctrl-left/ctrl-right/alt-left/alt-right word motion, ctrl-y yank, and alt-y yank-pop initial support, reverse-search cursor/word editing/kill/yank/yank-pop initial support, ctrl-c interrupt/double-press exit events, ctrl-d delete-forward and empty-input double-press exit events, ctrl-l redraw events, ctrl-o/ctrl-t global toggle events, ctrl-g/ctrl-s/ctrl-x chord chat events, prompt history navigation, reverse-search state/rendering/selection/script assertions including empty/cancel paths and cursor position, paste/image hint input handling with OSC ST terminators and base64 filename decoding, text/image pasted-content references with expanded submit text, metadata script assertions, and history entry restoration, SGR mouse parsing, alternate terminal navigation key sequences including modified Home/End/Delete/PageUp/PageDown, wheel scrolling with modifiers, primary clicks with modifiers, primary drag viewport selection, configurable viewport half-page/top/bottom scrolling, viewport line selection and dialog action clicks, focus/blur events, resize scroll preservation, default and configurable keybinding resolver with chord pending/null-unbind behavior, key/action camelCase aliases, keybinding JSON config loading, and focus/mouse/paste/image key names, vim insert/normal word, WORD, ge/gE, operator ge/gE, line-local `^`/`$`/`0`/`|`/`I`/`A`/`D`, quote, bracket, and j/k linewise motions/text objects, persistent yank/register/paste paths, last-change dot-repeat, G/gg line navigation, toggle-case, join, open-line, indent, substitute, delete/count/replace/undo/find/till/repeat/matching-pair % actions, normal-mode arrow/backspace/delete mappings, and operator character ranges, permission/task dialog builders with kind/id routing/runtime resolution/status line, stale dialog race guards, active dialog cancellation, permission id/bulk cancellation, queued permission promotion, active task dialog refresh, task lifecycle state transitions and bulk cancellation, idempotent alternate screen lifecycle/reset/reassert-interactive sequences, mouse/focus/bracketed-paste terminal mode lifecycle/reconciliation and reassertion sequences, ANSI snapshot capture/stripping, snapshot corpus write/compare/script-file compare/missing-baseline/diff/batch/strict unexpected-baseline status, scripted interaction runner with JSON/JSONL/wrapper loading and file-runner entrypoints, JSON/runtime/task camel field aliases, keybinding mutations, permission-cancel runtime mutations, and assertions including vim mode/register/task state/dialog result/runtime mutation/task bulk-cancel/status negative/snapshot negative/screen size/event-sequence/event-count/no-event/dialog-result-count/no-dialog-result plus multi-key/text/paste/image/pasted-content metadata and named-key input, REPL screen model, viewport scrolling, and selection focus model.
240-
- `internal/tui`: Vim prompt editing now includes basic visual and visual-line mode support with `v`/`V`, motion-extended selections, active-end toggle with visual `o`/`O`, visual `<`/`>` line indent/outdent, visual `~` case toggling, visual `u`/`U` lower/upper-case conversion, `y`/`d`/`c` range operators plus common visual `x`/`s` aliases, Escape return-to-normal behavior, and script expectation aliases for `visual`/`visualLine` modes.
240+
- `internal/tui`: Vim prompt editing now includes basic visual and visual-line mode support with `v`/`V`, motion-extended selections, active-end toggle with visual `o`/`O`, visual `<`/`>` line indent/outdent, visual `~`/`g~` case toggling, visual `u`/`U` plus `gu`/`gU` lower/upper-case conversion, `y`/`d`/`c` range operators plus common visual `x`/`s` aliases, Escape return-to-normal behavior, and script expectation aliases for `visual`/`visualLine` modes.
241241
- `internal/tui`: Vim prompt editing now supports normal-mode `gv` reselecting the previous characterwise or linewise visual selection before applying another visual operator.
242242
- `internal/tui`: Vim prompt editing now includes `gu`/`gU`/`g~` case-conversion operators across motion, linewise, find/till, text-object, and dot-repeat paths without updating the yank register.
243243
- `internal/tui`: Vim prompt editing now includes normal-mode `gJ` raw line joins that do not insert or normalize whitespace and can be dot-repeated.

internal/tui/tui_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4336,6 +4336,52 @@ func TestREPLScreenVimVisualCharOperators(t *testing.T) {
43364336
}
43374337
}
43384338

4339+
func TestREPLScreenVimVisualGCaseOperators(t *testing.T) {
4340+
screen := NewREPLScreen(40, 8, nil)
4341+
screen.SetVimEnabled(true)
4342+
typePromptText(&screen, "alpha beta")
4343+
screen.ApplyKey(ParseKey("\x1b"))
4344+
for _, seq := range []string{"0", "v", "e", "g", "U"} {
4345+
screen.ApplyKey(ParseKey(seq))
4346+
}
4347+
if screen.VimMode != VimNormal || screen.Prompt.Text != "ALPHA beta" || screen.Prompt.Cursor != 0 {
4348+
t.Fatalf("after visual gU screen = %#v", screen)
4349+
}
4350+
4351+
screen = NewREPLScreen(40, 8, nil)
4352+
screen.SetVimEnabled(true)
4353+
typePromptText(&screen, "ALPHA beta")
4354+
screen.ApplyKey(ParseKey("\x1b"))
4355+
for _, seq := range []string{"0", "v", "e", "g", "u"} {
4356+
screen.ApplyKey(ParseKey(seq))
4357+
}
4358+
if screen.VimMode != VimNormal || screen.Prompt.Text != "alpha beta" || screen.Prompt.Cursor != 0 {
4359+
t.Fatalf("after visual gu screen = %#v", screen)
4360+
}
4361+
4362+
screen = NewREPLScreen(40, 8, nil)
4363+
screen.SetVimEnabled(true)
4364+
typePromptText(&screen, "alpha BETA")
4365+
screen.ApplyKey(ParseKey("\x1b"))
4366+
for _, seq := range []string{"0", "v", "e", "g", "~"} {
4367+
screen.ApplyKey(ParseKey(seq))
4368+
}
4369+
if screen.VimMode != VimNormal || screen.Prompt.Text != "ALPHA BETA" || screen.Prompt.Cursor != 0 {
4370+
t.Fatalf("after visual g~ screen = %#v", screen)
4371+
}
4372+
4373+
screen = NewREPLScreen(40, 8, nil)
4374+
screen.SetVimEnabled(true)
4375+
typePromptText(&screen, "one\ntwo\nthree")
4376+
screen.ApplyKey(ParseKey("\x1b"))
4377+
for _, seq := range []string{"g", "g", "V", "j", "g", "U"} {
4378+
screen.ApplyKey(ParseKey(seq))
4379+
}
4380+
if screen.VimMode != VimNormal || screen.Prompt.Text != "ONE\nTWO\nthree" || screen.Prompt.Cursor != 0 {
4381+
t.Fatalf("after visual line gU screen = %#v", screen)
4382+
}
4383+
}
4384+
43394385
func TestREPLScreenVimVisualLineOperators(t *testing.T) {
43404386
screen := NewREPLScreen(40, 8, nil)
43414387
screen.SetVimEnabled(true)

internal/tui/vim.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ func (s *REPLScreen) applyVimVisualG(r rune) ScreenEvent {
436436
s.applyVimVisualJoin(true)
437437
case '_':
438438
s.Prompt.moveVimLastNonBlankMotion(count)
439+
case 'u', 'U':
440+
s.applyVimVisualChangeCase(r)
441+
case '~':
442+
s.applyVimVisualToggleCase()
439443
}
440444
return ScreenEvent{}
441445
}

0 commit comments

Comments
 (0)