feat(cli): Add W, B, E Vim motions and operator support (#16209)

Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
This commit is contained in:
Adam DeMuri
2026-02-05 10:29:30 -07:00
committed by GitHub
parent 1cae5ab158
commit ee2c8eef19
6 changed files with 836 additions and 82 deletions

View File

@@ -156,6 +156,15 @@ describe('useVim hook', () => {
vimMoveWordForward: vi.fn(),
vimMoveWordBackward: vi.fn(),
vimMoveWordEnd: vi.fn(),
vimMoveBigWordForward: vi.fn(),
vimMoveBigWordBackward: vi.fn(),
vimMoveBigWordEnd: vi.fn(),
vimDeleteBigWordForward: vi.fn(),
vimDeleteBigWordBackward: vi.fn(),
vimDeleteBigWordEnd: vi.fn(),
vimChangeBigWordForward: vi.fn(),
vimChangeBigWordBackward: vi.fn(),
vimChangeBigWordEnd: vi.fn(),
vimDeleteChar: vi.fn(),
vimInsertAtCursor: vi.fn(),
vimAppendAtCursor: vi.fn().mockImplementation(() => {
@@ -570,6 +579,105 @@ describe('useVim hook', () => {
});
});
describe('Big Word movement', () => {
it('should handle W (next big word)', () => {
const testBuffer = createMockBuffer('hello world test');
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'W' }));
});
expect(testBuffer.vimMoveBigWordForward).toHaveBeenCalledWith(1);
});
it('should handle B (previous big word)', () => {
const testBuffer = createMockBuffer('hello world test', [0, 6]);
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'B' }));
});
expect(testBuffer.vimMoveBigWordBackward).toHaveBeenCalledWith(1);
});
it('should handle E (end of big word)', () => {
const testBuffer = createMockBuffer('hello world test');
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'E' }));
});
expect(testBuffer.vimMoveBigWordEnd).toHaveBeenCalledWith(1);
});
it('should handle dW (delete big word forward)', () => {
const testBuffer = createMockBuffer('hello.world test', [0, 0]);
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'd' }));
});
act(() => {
result.current.handleInput(createKey({ sequence: 'W' }));
});
expect(testBuffer.vimDeleteBigWordForward).toHaveBeenCalledWith(1);
});
it('should handle cW (change big word forward)', () => {
const testBuffer = createMockBuffer('hello.world test', [0, 0]);
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'c' }));
});
act(() => {
result.current.handleInput(createKey({ sequence: 'W' }));
});
expect(testBuffer.vimChangeBigWordForward).toHaveBeenCalledWith(1);
expect(result.current.mode).toBe('INSERT');
});
it('should handle dB (delete big word backward)', () => {
const testBuffer = createMockBuffer('hello.world test', [0, 11]);
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'd' }));
});
act(() => {
result.current.handleInput(createKey({ sequence: 'B' }));
});
expect(testBuffer.vimDeleteBigWordBackward).toHaveBeenCalledWith(1);
});
it('should handle dE (delete big word end)', () => {
const testBuffer = createMockBuffer('hello.world test', [0, 0]);
const { result } = renderVimHook(testBuffer);
exitInsertMode(result);
act(() => {
result.current.handleInput(createKey({ sequence: 'd' }));
});
act(() => {
result.current.handleInput(createKey({ sequence: 'E' }));
});
expect(testBuffer.vimDeleteBigWordEnd).toHaveBeenCalledWith(1);
});
});
describe('Disabled vim mode', () => {
it('should not respond to vim commands when disabled', () => {
mockVimContext.vimEnabled = false;