diff --git a/ROADMAP.md b/ROADMAP.md index e71fd385a30..628d44a7106 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -246,20 +246,20 @@ Status | Command | Description ---|--------|------------------------------ | CTRL-V {char}.. | insert character literally, or enter decimal byte value :warning: | NL or CR or CTRL-M or CTRL-J | begin new line - | CTRL-E | insert the character from below the cursor - | CTRL-Y | insert the character from above the cursor +:white_check_mark: | CTRL-E | insert the character from below the cursor +:white_check_mark: | CTRL-Y | insert the character from above the cursor | CTRL-A | insert previously inserted text | CTRL-@ | insert previously inserted text and stop Insert mode - | CTRL-R {0-9a-z%#:.-="} | insert the contents of a register +:white_check_mark: | CTRL-R {0-9a-z%#:.-="} | insert the contents of a register | CTRL-N | insert next match of identifier before the cursor | CTRL-P | insert previous match of identifier before the cursor | CTRL-X ... | complete the word before the cursor in various ways - | BS or CTRL-H | delete the character before the cursor -:white_check_mark: | Del | delete the character under the cursor -:white_check_mark: | CTRL-W | delete word before the cursor - | CTRL-U | delete all entered characters in the current line - | CTRL-T | insert one shiftwidth of indent in front of the current line - | CTRL-D | delete one shiftwidth of indent in front of the current line +:white_check_mark: | BS or CTRL-H | delete the character before the cursor +:white_check_mark: | Del | delete the character under the cursor +:white_check_mark: | CTRL-W | delete word before the cursor +:white_check_mark: | CTRL-U | delete all entered characters in the current line +:white_check_mark: | CTRL-T | insert one shiftwidth of indent in front of the current line +:white_check_mark: | CTRL-D | delete one shiftwidth of indent in front of the current line | 0 CTRL-D | delete all indent in the current line | ^ CTRL-D | delete all indent in the current line, restore indent in next line diff --git a/package.json b/package.json index 36078cbdb2e..b5a8ad4da6e 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,11 @@ "command": "extension.vim_ctrl+b", "when": "editorTextFocus && vim.mode != 'Insert Mode'" }, + { + "key": "ctrl+h", + "command": "extension.vim_ctrl+h", + "when": "editorTextFocus && vim.mode == 'Insert Mode'" + }, { "key": "ctrl+e", "command": "extension.vim_ctrl+e", @@ -100,7 +105,7 @@ { "key": "ctrl+d", "command": "extension.vim_ctrl+d", - "when": "editorTextFocus" + "when": "editorTextFocus && vim.useCtrlKeys" }, { "key": "ctrl+[", @@ -127,6 +132,11 @@ "command": "extension.vim_ctrl+x", "when": "editorTextFocus && vim.useCtrlKeys" }, + { + "key": "ctrl+t", + "command": "extension.vim_ctrl+t", + "when": "editorTextFocus && vim.useCtrlKeys" + }, { "key": "left", "command": "extension.vim_left", diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 2cf255cf381..c49a23d2a65 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -409,6 +409,49 @@ class CommandRegister extends BaseCommand { } } +@RegisterAction +class CommandInsertRegisterContent extends BaseCommand { + modes = [ModeName.Insert]; + keys = ["ctrl+r", ""]; + isCompleteAction = false; + + public async exec(position: Position, vimState: VimState): Promise { + vimState.recordedState.registerName = this.keysPressed[1]; + const register = await Register.get(vimState); + let text: string; + + if (register.text instanceof Array) { + text = (register.text as string []).join("\n"); + } else { + text = register.text; + } + + if (register.registerMode === RegisterMode.LineWise) { + text += "\n"; + } + + await TextEditor.insertAt(text, position); + vimState.currentMode = ModeName.Insert; + vimState.cursorStartPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + vimState.cursorPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + + return vimState; + } + + public doesActionApply(vimState: VimState, keysPressed: string[]): boolean { + const register = keysPressed[1]; + + return super.doesActionApply(vimState, keysPressed) && Register.isValidRegister(register); + } + + public couldActionApply(vimState: VimState, keysPressed: string[]): boolean { + const register = keysPressed[1]; + + return super.couldActionApply(vimState, keysPressed) && Register.isValidRegister(register); + } + +} + @RegisterAction class CommandEsc extends BaseCommand { modes = [ @@ -472,6 +515,81 @@ class CommandCtrlE extends BaseCommand { } } +@RegisterAction +class CommandInsertBelowChar extends BaseCommand { + modes = [ModeName.Insert]; + keys = ["ctrl+e"]; + + public async exec(position: Position, vimState: VimState): Promise { + if (TextEditor.isLastLine(position)) { + return vimState; + } + + const charBelowCursorPosition = position.getDownByCount(1); + + if (charBelowCursorPosition.isLineEnd()) { + return vimState; + } + + const char = TextEditor.getText(new vscode.Range(charBelowCursorPosition, charBelowCursorPosition.getRight())); + await TextEditor.insert(char, position); + + vimState.cursorStartPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + vimState.cursorPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + + return vimState; + } +} + +@RegisterAction +class CommandInsertIndentInCurrentLine extends BaseCommand { + modes = [ModeName.Insert]; + keys = [""]; + + public async exec(position: Position, vimState: VimState): Promise { + const originalText = TextEditor.getLineAt(position).text; + const indentationWidth = TextEditor.getIndentationLevel(originalText); + const tabSize = Configuration.getInstance().tabstop; + const newIndentationWidth = (indentationWidth / tabSize + 1) * tabSize; + await TextEditor.replace(new vscode.Range(position.getLineBegin(), position.getLineEnd()), + TextEditor.setIndentationLevel(originalText, newIndentationWidth)); + + const cursorPosition = Position.FromVSCodePosition(position.with(position.line, + position.character + (newIndentationWidth - indentationWidth) / tabSize)); + vimState.cursorPosition = cursorPosition; + vimState.cursorStartPosition = cursorPosition; + vimState.currentMode = ModeName.Insert; + return vimState; + } +} + +@RegisterAction +class CommandDeleteIndentInCurrentLine extends BaseCommand { + modes = [ModeName.Insert]; + keys = [""]; + + public async exec(position: Position, vimState: VimState): Promise { + const originalText = TextEditor.getLineAt(position).text; + const indentationWidth = TextEditor.getIndentationLevel(originalText); + + if (indentationWidth === 0) { + return vimState; + } + + const tabSize = Configuration.getInstance().tabstop; + const newIndentationWidth = (indentationWidth / tabSize - 1) * tabSize; + await TextEditor.replace(new vscode.Range(position.getLineBegin(), position.getLineEnd()), + TextEditor.setIndentationLevel(originalText, newIndentationWidth < 0 ? 0 : newIndentationWidth)); + + const cursorPosition = Position.FromVSCodePosition(position.with(position.line, + position.character + (newIndentationWidth - indentationWidth) / tabSize )); + vimState.cursorPosition = cursorPosition; + vimState.cursorStartPosition = cursorPosition; + vimState.currentMode = ModeName.Insert; + return vimState; + } +} + @RegisterAction class CommandCtrlY extends BaseCommand { modes = [ModeName.Normal]; @@ -484,6 +602,32 @@ class CommandCtrlY extends BaseCommand { } } +@RegisterAction +class CommandInsertAboveChar extends BaseCommand { + modes = [ModeName.Insert]; + keys = ["ctrl+y"]; + + public async exec(position: Position, vimState: VimState): Promise { + if (TextEditor.isFirstLine(position)) { + return vimState; + } + + const charAboveCursorPosition = position.getUpByCount(1); + + if (charAboveCursorPosition.isLineEnd()) { + return vimState; + } + + const char = TextEditor.getText(new vscode.Range(charAboveCursorPosition, charAboveCursorPosition.getRight())); + await TextEditor.insert(char, position); + + vimState.cursorStartPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + vimState.cursorPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + + return vimState; + } +} + @RegisterAction class CommandCtrlC extends CommandEsc { keys = [""]; @@ -743,7 +887,7 @@ class CommandInsertInInsertMode extends BaseCommand { // The hard case is . where we have to track cursor pos since we don't // update the view public async exec(position: Position, vimState: VimState): Promise { - const char = this.keysPressed[this.keysPressed.length - 1]; + const char = this.keysPressed[this.keysPressed.length - 1]; if (char === "") { const newPosition = await TextEditor.backspace(position); @@ -766,6 +910,34 @@ class CommandInsertInInsertMode extends BaseCommand { } } +@RegisterAction +class CommandCtrlHInInsertMode extends BaseCommand { + modes = [ModeName.Insert]; + keys = ["ctrl+h"]; + + public async exec(position: Position, vimState: VimState): Promise { + const newPosition = await TextEditor.backspace(position); + vimState.cursorPosition = newPosition; + vimState.cursorStartPosition = newPosition; + return vimState; + } +} + +@RegisterAction +class CommandCtrlUInInsertMode extends BaseCommand { + modes = [ModeName.Insert]; + keys = ["ctrl+u"]; + + public async exec(position: Position, vimState: VimState): Promise { + const start = position.getLineBegin(); + const stop = position.getLineEnd(); + await TextEditor.delete(new vscode.Range(start, stop)); + vimState.cursorPosition = start; + vimState.cursorStartPosition = start; + return vimState; + } +} + @RegisterAction export class CommandSearchForwards extends BaseCommand { modes = [ModeName.Normal];