diff --git a/documents/howtouse.md b/documents/howtouse.md index 0c1c52de5..e0212bbc4 100644 --- a/documents/howtouse.md +++ b/documents/howtouse.md @@ -60,7 +60,7 @@ | **Z** **Z**
Write current file and exit | **Z** **Q**
Same as `:q!` | **Ctrl** **w** **c**
Close current window | **?**
`keyword` Search backwards | | **/**
`keyword` Search forwards | **\\** **r**
Quick Run | **s** OR **c****u**
Delete current charater and enter insert mode | **y****{**
Yank to the previous blank line | | **y****}**
Yank to the next blank line | **y****l**
Yank a character| **X** OR **d****h**
Cut a character before cursor | **g****a**
Show current character info | -| **t****x**
Move to the left of the next ```x``` (any character) on the current line | **T****x**
Move to the right of the back ```x ``` (any character) on the current line | **y****t**
**Any key**
Yank characters to an any character | +| **t****x**
Move to the left of the next ```x``` (any character) on the current line | **T****x**
Move to the right of the back ```x ``` (any character) on the current line | **y****t**
**Any key**
Yank characters to an any character | **c****f**
**Any key**
Delete characters to an any character and enter insert mode | diff --git a/src/moepkg/help.nim b/src/moepkg/help.nim index b5eada04c..c63b03e35 100644 --- a/src/moepkg/help.nim +++ b/src/moepkg/help.nim @@ -72,6 +72,7 @@ ciw - Delete the current word and enter insert mode ci( or ci) - Delete the inside of round brackets and enter insert mode ci[ or ci] - Delete the inside of square brackets and enter insert mode ci{ or ci} - Delete the inside of curly brackets and enter insert mode +cf any - Delete characters to the any character and enter insert mode di" - Delete the inside of double quotes di' - Delete the inside of single quotes diw - Delete the current word diff --git a/src/moepkg/normalmode.nim b/src/moepkg/normalmode.nim index b10654eec..5df835831 100644 --- a/src/moepkg/normalmode.nim +++ b/src/moepkg/normalmode.nim @@ -770,6 +770,35 @@ proc deleteCharactersAfterBlankInLine(status: var EditorStatus) = registerName, status.settings) +# cf command +proc deleteCharactersToCharacterAndEnterInsertMode(status: var EditorStatus, + rune: Rune, + registerName: string) = + + if currentBufStatus.isReadonly: + status.commandLine.writeReadonlyModeWarning + return + + let + currentColumn = currentMainWindowNode.currentColumn + # Get the position of a character + position = currentBufStatus.searchOneCharacterToEndOfLine( + currentMainWindowNode, + rune) + + if position > currentColumn: + currentBufStatus.cmdLoop = position - currentColumn + 1 + status.deleteCharacters + + status.changeMode(Mode.insert) + +# cf command +proc deleteCharactersToCharacterAndEnterInsertMode(status: var EditorStatus, + rune: Rune) = + + const registerName = "" + status.deleteCharactersToCharacterAndEnterInsertMode(rune, registerName) + proc enterInsertModeAfterCursor(status: var EditorStatus) = if currentBufStatus.isReadonly: status.commandLine.writeReadonlyModeWarning @@ -895,6 +924,10 @@ proc addRegister(status: var EditorStatus, command, registerName: string) = status.changeInnerCommand(command[2].toRune, registerName) elif command.len == 3 and command[0 .. 1] == "yt": status.yankCharactersToCharacter(command[2].toRune, registerName) + elif command.len == 3 and command[0 .. 1] == "cf": + status.deleteCharactersToCharacterAndEnterInsertMode( + command[2].toRune, + registerName) else: discard @@ -954,7 +987,8 @@ proc registerCommand(status: var EditorStatus, command: seq[Rune]) = cmd == "dh" or cmd == "cl" or cmd == "s" or (cmd.len == 3 and cmd[0 .. 1] == "ci") or - (cmd.len == 3 and cmd[0 .. 1] == "yt"): + (cmd.len == 3 and cmd[0 .. 1] == "yt") or + (cmd.len == 3 and cmd[0 .. 1] == "cf"): status.addRegister(cmd, $registerName) proc pasteAfterCursor(status: var EditorStatus) {.inline.} = @@ -1111,13 +1145,16 @@ proc normalCommand(status: var EditorStatus, if secondKey == ord('c'): status.deleteCharactersAfterBlankInLine status.enterInsertModeAfterCursor - if secondKey == ord('l'): + elif secondKey == ord('l'): status.deleteCharacterAndEnterInsertMode elif secondKey == ord('i'): let thirdKey = commands[2] if isParen(thirdKey) or thirdKey == ord('w'): status.changeInnerCommand(thirdKey) + elif secondKey == ord('f'): + let thirdKey = commands[2] + status.deleteCharactersToCharacterAndEnterInsertMode(thirdKey) elif key == ord('d'): let secondKey = commands[1] if secondKey == ord('d'): @@ -1371,15 +1408,16 @@ proc isNormalModeCommand(command: seq[Rune]): InputState = if command.len == 1: result = InputState.Continue elif command.len == 2: - if command[1] == ord('i'): + if command[1] == ord('i') or + command[1] == ord('f'): result = InputState.Continue elif command[1] == ord('c') or command[1] == ('l'): result = InputState.Valid elif command.len == 3: - if command[1] == ord('i'): - if isParen(command[2]) or - command[2] == ord('w'): - result = InputState.Valid + if command[1] == ord('f') or + (command[1] == ord('i') and + (isParen(command[2]) or command[2] == ord('w'))): + result = InputState.Valid elif command[0] == ord('d'): if command.len == 1: diff --git a/tests/tnormalmode.nim b/tests/tnormalmode.nim index f59c76089..3d858209f 100644 --- a/tests/tnormalmode.nim +++ b/tests/tnormalmode.nim @@ -1916,3 +1916,39 @@ suite "Normal mode: Yank characters to any character": check currentBufStatus.buffer[0] == buffer check status.registers.noNameRegister.buffer.len == 0 + +suite "Normal mode: Delete characters to any characters and Enter insert mode": + test "Case 1: Delete characters to 'd' and enter insert mode (\"cfd\" command)": + var status = initEditorStatus() + status.addNewBuffer + + const buffer = ru "abcd" + currentBufStatus.buffer = initGapBuffer(@[buffer]) + + const command = ru "cfd" + status.normalCommand(command, 100, 100) + + check currentBufStatus.buffer.len == 1 + check currentBufStatus.buffer[0] == ru "" + + check not status.registers.noNameRegister.isLine + check status.registers.noNameRegister.buffer[0] == ru "abcd" + + check currentBufStatus.mode == Mode.insert + + test "Case 1: Do nothing (\"cfz\" command)": + var status = initEditorStatus() + status.addNewBuffer + + const buffer = ru "abcd" + currentBufStatus.buffer = initGapBuffer(@[buffer]) + + const command = ru "cfz" + status.normalCommand(command, 100, 100) + + check currentBufStatus.buffer.len == 1 + check currentBufStatus.buffer[0] == buffer + + check status.registers.noNameRegister.buffer.len == 0 + + check currentBufStatus.mode == Mode.normal