mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-17 17:41:24 -07:00
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:
@@ -24,9 +24,15 @@ const CMD_TYPES = {
|
||||
DELETE_WORD_FORWARD: 'dw',
|
||||
DELETE_WORD_BACKWARD: 'db',
|
||||
DELETE_WORD_END: 'de',
|
||||
DELETE_BIG_WORD_FORWARD: 'dW',
|
||||
DELETE_BIG_WORD_BACKWARD: 'dB',
|
||||
DELETE_BIG_WORD_END: 'dE',
|
||||
CHANGE_WORD_FORWARD: 'cw',
|
||||
CHANGE_WORD_BACKWARD: 'cb',
|
||||
CHANGE_WORD_END: 'ce',
|
||||
CHANGE_BIG_WORD_FORWARD: 'cW',
|
||||
CHANGE_BIG_WORD_BACKWARD: 'cB',
|
||||
CHANGE_BIG_WORD_END: 'cE',
|
||||
DELETE_CHAR: 'x',
|
||||
DELETE_LINE: 'dd',
|
||||
CHANGE_LINE: 'cc',
|
||||
@@ -187,6 +193,21 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.DELETE_BIG_WORD_FORWARD: {
|
||||
buffer.vimDeleteBigWordForward(count);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.DELETE_BIG_WORD_BACKWARD: {
|
||||
buffer.vimDeleteBigWordBackward(count);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.DELETE_BIG_WORD_END: {
|
||||
buffer.vimDeleteBigWordEnd(count);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.CHANGE_WORD_FORWARD: {
|
||||
buffer.vimChangeWordForward(count);
|
||||
updateMode('INSERT');
|
||||
@@ -205,6 +226,24 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.CHANGE_BIG_WORD_FORWARD: {
|
||||
buffer.vimChangeBigWordForward(count);
|
||||
updateMode('INSERT');
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.CHANGE_BIG_WORD_BACKWARD: {
|
||||
buffer.vimChangeBigWordBackward(count);
|
||||
updateMode('INSERT');
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.CHANGE_BIG_WORD_END: {
|
||||
buffer.vimChangeBigWordEnd(count);
|
||||
updateMode('INSERT');
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TYPES.DELETE_CHAR: {
|
||||
buffer.vimDeleteChar(count);
|
||||
break;
|
||||
@@ -371,7 +410,10 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
* @returns boolean indicating if command was handled
|
||||
*/
|
||||
const handleOperatorMotion = useCallback(
|
||||
(operator: 'd' | 'c', motion: 'w' | 'b' | 'e'): boolean => {
|
||||
(
|
||||
operator: 'd' | 'c',
|
||||
motion: 'w' | 'b' | 'e' | 'W' | 'B' | 'E',
|
||||
): boolean => {
|
||||
const count = getCurrentCount();
|
||||
|
||||
const commandMap = {
|
||||
@@ -379,11 +421,17 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
w: CMD_TYPES.DELETE_WORD_FORWARD,
|
||||
b: CMD_TYPES.DELETE_WORD_BACKWARD,
|
||||
e: CMD_TYPES.DELETE_WORD_END,
|
||||
W: CMD_TYPES.DELETE_BIG_WORD_FORWARD,
|
||||
B: CMD_TYPES.DELETE_BIG_WORD_BACKWARD,
|
||||
E: CMD_TYPES.DELETE_BIG_WORD_END,
|
||||
},
|
||||
c: {
|
||||
w: CMD_TYPES.CHANGE_WORD_FORWARD,
|
||||
b: CMD_TYPES.CHANGE_WORD_BACKWARD,
|
||||
e: CMD_TYPES.CHANGE_WORD_END,
|
||||
W: CMD_TYPES.CHANGE_BIG_WORD_FORWARD,
|
||||
B: CMD_TYPES.CHANGE_BIG_WORD_BACKWARD,
|
||||
E: CMD_TYPES.CHANGE_BIG_WORD_END,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -524,6 +572,21 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'W': {
|
||||
// Check if this is part of a delete or change command (dW/cW)
|
||||
if (state.pendingOperator === 'd') {
|
||||
return handleOperatorMotion('d', 'W');
|
||||
}
|
||||
if (state.pendingOperator === 'c') {
|
||||
return handleOperatorMotion('c', 'W');
|
||||
}
|
||||
|
||||
// Normal big word movement
|
||||
buffer.vimMoveBigWordForward(repeatCount);
|
||||
dispatch({ type: 'CLEAR_COUNT' });
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'b': {
|
||||
// Check if this is part of a delete or change command (db/cb)
|
||||
if (state.pendingOperator === 'd') {
|
||||
@@ -539,6 +602,21 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'B': {
|
||||
// Check if this is part of a delete or change command (dB/cB)
|
||||
if (state.pendingOperator === 'd') {
|
||||
return handleOperatorMotion('d', 'B');
|
||||
}
|
||||
if (state.pendingOperator === 'c') {
|
||||
return handleOperatorMotion('c', 'B');
|
||||
}
|
||||
|
||||
// Normal backward big word movement
|
||||
buffer.vimMoveBigWordBackward(repeatCount);
|
||||
dispatch({ type: 'CLEAR_COUNT' });
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'e': {
|
||||
// Check if this is part of a delete or change command (de/ce)
|
||||
if (state.pendingOperator === 'd') {
|
||||
@@ -554,6 +632,21 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'E': {
|
||||
// Check if this is part of a delete or change command (dE/cE)
|
||||
if (state.pendingOperator === 'd') {
|
||||
return handleOperatorMotion('d', 'E');
|
||||
}
|
||||
if (state.pendingOperator === 'c') {
|
||||
return handleOperatorMotion('c', 'E');
|
||||
}
|
||||
|
||||
// Normal big word end movement
|
||||
buffer.vimMoveBigWordEnd(repeatCount);
|
||||
dispatch({ type: 'CLEAR_COUNT' });
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'x': {
|
||||
// Delete character under cursor
|
||||
buffer.vimDeleteChar(repeatCount);
|
||||
|
||||
Reference in New Issue
Block a user