From d69370ec8a1180e31329d5f24db926c5641f1293 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sat, 11 Apr 2020 00:40:28 +0800 Subject: [PATCH] Change inline pair --- keymap/vim.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index aedc07adcc..3b1098a0f0 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -85,6 +85,18 @@ { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + + // Vim Surround Testbench + { keys: 's\'', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\'' } }, + { keys: 's\"', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\"' } }, + { keys: 's\`', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\`' } }, + { keys: 's\(', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\(' } }, + { keys: 's\)', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\)' } }, + { keys: 's\{', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\{' } }, + { keys: 's\}', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\}' } }, + { keys: 's\[', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\[' } }, + { keys: 's\]', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\]' } }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal', excludeOperator: ['change'] }, { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'}, { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, @@ -2813,7 +2825,65 @@ indent: function(cm, actionArgs) { cm.indentLine(cm.getCursor().line, actionArgs.indentRight); }, - exitInsertMode: exitInsertMode + exitInsertMode: exitInsertMode, + vimChangeSurround: function (cm, actionArgs) { + var character = actionArgs.selectedCharacter; + var cursor = cm.getCursor() + + var openCs = ['{', '(', '['] + var mirroredPairs = {'(': ')', ')': '(', + '[': ']', ']': '[', + '\'': true, '"': true, '`': true}; + var multilinePairs = { '{': '}', '}': '{' }; + + function transformCharacterPair (character) { + var openC, closeC + if (typeof mirroredPairs[character] === 'boolean') { + openC = closeC = character + } else { + if (openCs.includes(character)) { + openC = character + closeC = mirroredPairs[character] + } else { + openC = mirroredPairs[character] + closeC = character + } + } + return [openC, closeC] + } + + function replaceSurround (cm, searchCharacter, replaceCharacter) { + var searchPair = transformCharacterPair(searchCharacter) + var replacePair = transformCharacterPair(replaceCharacter) + + var openIndex, closeIndex, lineContent = cm.getLine(cursor.line) + openIndex = lineContent.slice(0, cursor.ch).lastIndexOf(searchPair[0]) + closeIndex = lineContent.slice(cursor.ch).indexOf(searchPair[1]) + + if (openIndex === -1 || closeIndex === -1) { + return + } + + var inner = lineContent.slice(openIndex + 1, closeIndex + cursor.ch) + + var openPos = { ch: openIndex, line: cursor.line } + var closePos = { ch: cursor.ch + closeIndex + 1, line: cursor.line } + + cm.replaceRange(replacePair[0] + inner + replacePair[1], openPos, closePos) + } + + function replaceMultilineSurround () { + + } + + if (mirroredPairs[actionArgs.search]) { + replaceSurround(cm, actionArgs.search, character) + } else if (multilinePairs[actionArgs.search]) { + replaceMultilineSurround(cm, actionArgs.search, character) + } + + cm.setCursor(cursor) + } }; function defineAction(name, fn) { @@ -2860,7 +2930,7 @@ var command = keyMap[i]; if (context == 'insert' && command.context != 'insert' || command.context && command.context != context || - inputState.operator && command.type == 'action' || + inputState.operator && command.type == 'action' && !command.forceMatch || (command.excludeOperator && command.excludeOperator.includes(inputState.operator)) || !(match = commandMatch(keys, command.keys))) { continue; } if (match == 'partial') { partial.push(command); }