|
85 | 85 | { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>' },
|
86 | 86 | { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
|
87 | 87 | { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
|
| 88 | + |
| 89 | + // Vim Surround Testbench |
| 90 | + { keys: 's\'<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\'' } }, |
| 91 | + { keys: 's\"<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\"' } }, |
| 92 | + { keys: 's\`<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\`' } }, |
| 93 | + { keys: 's\(<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\(' } }, |
| 94 | + { keys: 's\)<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\)' } }, |
| 95 | + { keys: 's\{<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\{' } }, |
| 96 | + { keys: 's\}<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\}' } }, |
| 97 | + { keys: 's\[<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\[' } }, |
| 98 | + { keys: 's\]<character>', type: 'action', forceMatch: true, action: 'vimChangeSurround', actionArgs: { search: '\]' } }, |
| 99 | + |
88 | 100 | { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal', excludeOperator: ['change'] },
|
89 | 101 | { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'},
|
90 | 102 | { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },
|
|
2813 | 2825 | indent: function(cm, actionArgs) {
|
2814 | 2826 | cm.indentLine(cm.getCursor().line, actionArgs.indentRight);
|
2815 | 2827 | },
|
2816 |
| - exitInsertMode: exitInsertMode |
| 2828 | + exitInsertMode: exitInsertMode, |
| 2829 | + vimChangeSurround: function (cm, actionArgs) { |
| 2830 | + var character = actionArgs.selectedCharacter; |
| 2831 | + var cursor = cm.getCursor() |
| 2832 | + |
| 2833 | + var openCs = ['{', '(', '['] |
| 2834 | + var mirroredPairs = {'(': ')', ')': '(', |
| 2835 | + '[': ']', ']': '[', |
| 2836 | + '\'': true, '"': true, '`': true}; |
| 2837 | + var multilinePairs = { '{': '}', '}': '{' }; |
| 2838 | + |
| 2839 | + function transformCharacterPair (character) { |
| 2840 | + var openC, closeC |
| 2841 | + if (typeof mirroredPairs[character] === 'boolean') { |
| 2842 | + openC = closeC = character |
| 2843 | + } else { |
| 2844 | + if (openCs.includes(character)) { |
| 2845 | + openC = character |
| 2846 | + closeC = mirroredPairs[character] |
| 2847 | + } else { |
| 2848 | + openC = mirroredPairs[character] |
| 2849 | + closeC = character |
| 2850 | + } |
| 2851 | + } |
| 2852 | + return [openC, closeC] |
| 2853 | + } |
| 2854 | + |
| 2855 | + function replaceSurround (cm, searchCharacter, replaceCharacter) { |
| 2856 | + var searchPair = transformCharacterPair(searchCharacter) |
| 2857 | + var replacePair = transformCharacterPair(replaceCharacter) |
| 2858 | + |
| 2859 | + var openIndex, closeIndex, lineContent = cm.getLine(cursor.line) |
| 2860 | + openIndex = lineContent.slice(0, cursor.ch).lastIndexOf(searchPair[0]) |
| 2861 | + closeIndex = lineContent.slice(cursor.ch).indexOf(searchPair[1]) |
| 2862 | + |
| 2863 | + if (openIndex === -1 || closeIndex === -1) { |
| 2864 | + return |
| 2865 | + } |
| 2866 | + |
| 2867 | + var inner = lineContent.slice(openIndex + 1, closeIndex + cursor.ch) |
| 2868 | + |
| 2869 | + var openPos = { ch: openIndex, line: cursor.line } |
| 2870 | + var closePos = { ch: cursor.ch + closeIndex + 1, line: cursor.line } |
| 2871 | + |
| 2872 | + cm.replaceRange(replacePair[0] + inner + replacePair[1], openPos, closePos) |
| 2873 | + } |
| 2874 | + |
| 2875 | + function replaceMultilineSurround () { |
| 2876 | + |
| 2877 | + } |
| 2878 | + |
| 2879 | + if (mirroredPairs[actionArgs.search]) { |
| 2880 | + replaceSurround(cm, actionArgs.search, character) |
| 2881 | + } else if (multilinePairs[actionArgs.search]) { |
| 2882 | + replaceMultilineSurround(cm, actionArgs.search, character) |
| 2883 | + } |
| 2884 | + |
| 2885 | + cm.setCursor(cursor) |
| 2886 | + } |
2817 | 2887 | };
|
2818 | 2888 |
|
2819 | 2889 | function defineAction(name, fn) {
|
|
2860 | 2930 | var command = keyMap[i];
|
2861 | 2931 | if (context == 'insert' && command.context != 'insert' ||
|
2862 | 2932 | command.context && command.context != context ||
|
2863 |
| - inputState.operator && command.type == 'action' || |
| 2933 | + inputState.operator && command.type == 'action' && !command.forceMatch || |
2864 | 2934 | (command.excludeOperator && command.excludeOperator.includes(inputState.operator)) ||
|
2865 | 2935 | !(match = commandMatch(keys, command.keys))) { continue; }
|
2866 | 2936 | if (match == 'partial') { partial.push(command); }
|
|
0 commit comments