From 6c9ecdc47c53ed0f79652113d48cb660bafd49a5 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Fri, 10 Apr 2020 22:39:56 +0800 Subject: [PATCH 1/7] Prevent s command in change mode --- keymap/vim.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/keymap/vim.js b/keymap/vim.js index 6baf39ceab..aedc07adcc 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -85,7 +85,7 @@ { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { 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' }, { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' }, @@ -2861,6 +2861,7 @@ if (context == 'insert' && command.context != 'insert' || command.context && command.context != context || inputState.operator && command.type == 'action' || + (command.excludeOperator && command.excludeOperator.includes(inputState.operator)) || !(match = commandMatch(keys, command.keys))) { continue; } if (match == 'partial') { partial.push(command); } if (match == 'full') { full.push(command); } From d69370ec8a1180e31329d5f24db926c5641f1293 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sat, 11 Apr 2020 00:40:28 +0800 Subject: [PATCH 2/7] 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); } From 9bcacef6b23e2e21c7019e0858a02f48b0fad0b1 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sat, 11 Apr 2020 10:42:07 +0800 Subject: [PATCH 3/7] Handle asterisk & space output --- keymap/vim.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 3b1098a0f0..dd219ff4c6 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -90,6 +90,7 @@ { 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: '\{' } }, @@ -2833,7 +2834,7 @@ var openCs = ['{', '(', '['] var mirroredPairs = {'(': ')', ')': '(', '[': ']', ']': '[', - '\'': true, '"': true, '`': true}; + '\'': true, '"': true, '`': true, '*': true}; var multilinePairs = { '{': '}', '}': '{' }; function transformCharacterPair (character) { @@ -2866,10 +2867,19 @@ var inner = lineContent.slice(openIndex + 1, closeIndex + cursor.ch) + var addSpace = openCs.includes(replaceCharacter) + 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) + var text + if (addSpace) { + text = replacePair[0] + ' ' + inner + ' ' + replacePair[1] + } else { + text = replacePair[0] + inner + replacePair[1] + } + + cm.replaceRange(text, openPos, closePos) } function replaceMultilineSurround () { From 2a28a9d164410569e0c410b77ec5195315b9e9dc Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sun, 26 Apr 2020 16:05:41 +0800 Subject: [PATCH 4/7] Change curly brace surround --- keymap/vim.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index dd219ff4c6..91b6dc9c90 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2842,11 +2842,13 @@ if (typeof mirroredPairs[character] === 'boolean') { openC = closeC = character } else { + let pairs = mirroredPairs[character] ? mirroredPairs : multilinePairs + if (openCs.includes(character)) { openC = character - closeC = mirroredPairs[character] + closeC = pairs[character] } else { - openC = mirroredPairs[character] + openC = pairs[character] closeC = character } } @@ -2882,8 +2884,20 @@ cm.replaceRange(text, openPos, closePos) } - function replaceMultilineSurround () { - + function replaceCharacterAt (cm, character, position) { + var pos = { + ch: position.ch + 1, + line: position.line + } + cm.replaceRange(character, position, pos) + } + + function replaceMultilineSurround (cm, searchCharacter, replaceCharacter) { + var tmp = selectCompanionObject(cm, cursor, searchCharacter, true) + const replacePair = transformCharacterPair(replaceCharacter) + + replaceCharacterAt(cm, replacePair[0], tmp.start) + replaceCharacterAt(cm, replacePair[1], { ch: tmp.end.ch - 1, line: tmp.end.line }) } if (mirroredPairs[actionArgs.search]) { From 8ece8a111afe3f1457302aa3a74e7cae803d5eef Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sun, 26 Apr 2020 17:18:05 +0800 Subject: [PATCH 5/7] Change surround to tag --- keymap/vim.js | 93 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 91b6dc9c90..f791d35f26 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2852,12 +2852,20 @@ closeC = character } } - return [openC, closeC] + + if (!openC || !closeC) { + return null + } else { + return [openC, closeC] + } } - function replaceSurround (cm, searchCharacter, replaceCharacter) { + function replaceSurround (cm, searchCharacter, replacePair, addSpace = false) { var searchPair = transformCharacterPair(searchCharacter) - var replacePair = transformCharacterPair(replaceCharacter) + + if (!replacePair) { + return + } var openIndex, closeIndex, lineContent = cm.getLine(cursor.line) openIndex = lineContent.slice(0, cursor.ch).lastIndexOf(searchPair[0]) @@ -2869,8 +2877,6 @@ var inner = lineContent.slice(openIndex + 1, closeIndex + cursor.ch) - var addSpace = openCs.includes(replaceCharacter) - var openPos = { ch: openIndex, line: cursor.line } var closePos = { ch: cursor.ch + closeIndex + 1, line: cursor.line } @@ -2896,17 +2902,80 @@ var tmp = selectCompanionObject(cm, cursor, searchCharacter, true) const replacePair = transformCharacterPair(replaceCharacter) + if (!replacePair) { + return + } + replaceCharacterAt(cm, replacePair[0], tmp.start) replaceCharacterAt(cm, replacePair[1], { ch: tmp.end.ch - 1, line: tmp.end.line }) } - if (mirroredPairs[actionArgs.search]) { - replaceSurround(cm, actionArgs.search, character) - } else if (multilinePairs[actionArgs.search]) { - replaceMultilineSurround(cm, actionArgs.search, character) - } + if (character === '<') { + // editing tags object + showPrompt(cm, { + onCloseDialog: function (inputRef) { + var input = inputRef.getElementsByTagName("input")[0].value + // Give the prompt some time to close so that if processCommand shows + // an error, the elements don't overlap. + vimGlobalState.exCommandHistoryController.pushInput(input + '>'); + vimGlobalState.exCommandHistoryController.reset(); + + input = '<' + input + '>'; + var openTagRegex = /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>/ + var match = input.match(openTagRegex) + if (!match) { + return + } - cm.setCursor(cursor) + replaceSurround(cm, actionArgs.search, [ + input, + '' + ]) + }, + prefix: '<', + onKeyDown: function (e, input, close) { + var keyName = CodeMirror.keyName(e), up, offset; + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || + (keyName == 'Backspace' && input == '')) { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + CodeMirror.e_stop(e); + clearInputState(cm); + close(); + cm.focus(); + } + if (e.key === '>') { + close(input) + CodeMirror.e_stop(e); + close() + } else if (keyName == 'Up' || keyName == 'Down') { + CodeMirror.e_stop(e); + up = keyName == 'Up' ? true : false; + offset = e.target ? e.target.selectionEnd : 0; + input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; + close(input); + if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); + } else if (keyName == 'Ctrl-U') { + // Ctrl-U clears input. + CodeMirror.e_stop(e); + close(''); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.exCommandHistoryController.reset(); + } + } + }); + } else { + if (mirroredPairs[actionArgs.search]) { + var replacePair = transformCharacterPair(character) + var addSpace = openCs.includes(character) + replaceSurround(cm, actionArgs.search, replacePair, addSpace) + } else if (multilinePairs[actionArgs.search]) { + replaceMultilineSurround(cm, actionArgs.search, character) + } + + cm.setCursor(cursor) + } } }; @@ -4070,7 +4139,7 @@ if (cm.openDialog) { cm.openDialog(template, onClose, { bottom: true, value: options.value, onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, - selectValueOnOpen: false}); + selectValueOnOpen: false, onClose: options.onCloseDialog}); } else { onClose(prompt(shortText, '')); From 380a9eaa9664c9ac08c1708bd23c484c3ccb4cf8 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sun, 26 Apr 2020 20:45:21 +0800 Subject: [PATCH 6/7] Replace all const with var --- keymap/vim.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index f791d35f26..dfd0034602 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -52,7 +52,7 @@ el.style.position = 'absolute'; el.style.left = '-9999px'; // Move outside the screen to make it invisible document.body.appendChild(el); // Append the
Key buffer: