From 84dc2d07fa19c237479c1681385a63d64fddcc74 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Wed, 6 Jul 2016 13:28:29 +0100 Subject: [PATCH] [vim bindings] Make Backspace delete characters In Replace mode (or Overwrite mode) it should still go backwards without deleting characters. --- keymap/vim.js | 19 ++++++++++++++++--- test/vim_test.js | 28 +++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 9891eb5fcb..afed132e36 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -53,7 +53,6 @@ { keys: '', type: 'keyToKey', toKeys: 'j' }, { keys: '', type: 'keyToKey', toKeys: 'l' }, { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, - { keys: '', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }, context: 'insert'}, { keys: '', type: 'keyToKey', toKeys: 'W' }, { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, { keys: '', type: 'keyToKey', toKeys: 'w' }, @@ -73,6 +72,7 @@ { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + { keys: '', type: 'action', action: 'toggleOverwrite', context: 'insert' }, // Motions { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, @@ -277,6 +277,7 @@ function cmKey(key, cm) { if (!cm) { return undefined; } + if (this[key]) { return this[key]; } var vimKey = cmKeyToVimKey(key); if (!vimKey) { return false; @@ -289,7 +290,7 @@ } var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; - var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'}; function cmKeyToVimKey(key) { if (key.charAt(0) == '\'') { // Keypress character binding of format "'a'" @@ -2175,6 +2176,17 @@ var registerName = actionArgs.selectedCharacter; macroModeState.enterMacroRecordMode(cm, registerName); }, + toggleOverwrite: function(cm) { + if (!cm.state.overwrite) { + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.toggleOverwrite(false); + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + }, enterInsertMode: function(cm, actionArgs, vim) { if (cm.getOption('readOnly')) { return; } vim.insertMode = true; @@ -2220,7 +2232,6 @@ return; } } - cm.setOption('keyMap', 'vim-insert'); cm.setOption('disableInput', false); if (actionArgs && actionArgs.replace) { // Handle Replace-mode as a special case of insert mode. @@ -2228,6 +2239,7 @@ cm.setOption('keyMap', 'vim-replace'); CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); } else { + cm.toggleOverwrite(false); cm.setOption('keyMap', 'vim-insert'); CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); } @@ -4779,6 +4791,7 @@ }; CodeMirror.keyMap['vim-replace'] = { + 'Backspace': 'goCharLeft', fallthrough: ['vim-insert'], attach: attachVimMap, detach: detachVimMap, diff --git a/test/vim_test.js b/test/vim_test.js index fb612b1407..159114cecd 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -145,7 +145,7 @@ function testVim(name, run, opts, expectedFail) { for (var i = 0; i < arguments.length; i++) { var key = arguments[i]; // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); + var handled = CodeMirror.lookupKey(key, cm.getOption('keyMap'), executeHandler, cm); // Record for insert mode. if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; @@ -1419,6 +1419,32 @@ testVim('i_repeat_delete', function(cm, vim, helpers) { eq('abe', cm.getValue()); helpers.assertCursorAt(0, 1); }, { value: 'abcde' }); +testVim('insert', function(cm, vim, helpers) { + helpers.doKeys('i'); + eq('vim-insert', cm.getOption('keyMap')); + eq(false, cm.state.overwrite); + helpers.doKeys(''); + eq('vim-replace', cm.getOption('keyMap')); + eq(true, cm.state.overwrite); + helpers.doKeys(''); + eq('vim-insert', cm.getOption('keyMap')); + eq(false, cm.state.overwrite); +}); +testVim('i_backspace', function(cm, vim, helpers) { + cm.setCursor(0, 10); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.assertCursorAt(0, 9); + eq('012345678', cm.getValue()); +}, { value: '0123456789'}); +testVim('i_overwrite_backspace', function(cm, vim, helpers) { + cm.setCursor(0, 10); + helpers.doKeys('i'); + helpers.doKeys(''); + helpers.doInsertModeKeys('Backspace'); + helpers.assertCursorAt(0, 9); + eq('0123456789', cm.getValue()); +}, { value: '0123456789'}); testVim('A', function(cm, vim, helpers) { helpers.doKeys('A'); helpers.assertCursorAt(0, lines[0].length);