|
172 | 172 | { keys: '<C-o>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, |
173 | 173 | { keys: '<C-e>', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, |
174 | 174 | { keys: '<C-y>', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, |
175 | | - { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }}, |
176 | | - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }}, |
| 175 | + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, |
| 176 | + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, |
177 | 177 | { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, |
178 | | - { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }}, |
| 178 | + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, |
179 | 179 | { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }}, |
180 | | - { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }}, |
181 | | - { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }}, |
| 180 | + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, |
| 181 | + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, |
182 | 182 | { keys: 'v', type: 'action', action: 'toggleVisualMode' }, |
183 | 183 | { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, |
184 | 184 | { keys: '<C-v>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, |
|
191 | 191 | { keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' }, |
192 | 192 | // Handle Replace-mode as a special case of insert mode. |
193 | 193 | { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, |
194 | | - { keys: 'u', type: 'action', action: 'undo' }, |
| 194 | + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, |
195 | 195 | { keys: 'u', type: 'action', action: 'changeCase', actionArgs: {toLower: true}, context: 'visual', isEdit: true }, |
196 | 196 | { keys: 'U',type: 'action', action: 'changeCase', actionArgs: {toLower: false}, context: 'visual', isEdit: true }, |
197 | 197 | { keys: '<C-r>', type: 'action', action: 'redo' }, |
|
945 | 945 | var bestMatch; |
946 | 946 | for (var i = 0; i < matches.full.length; i++) { |
947 | 947 | var match = matches.full[i]; |
948 | | - if (!bestMatch || match.context == context) { |
| 948 | + if (!bestMatch) { |
949 | 949 | bestMatch = match; |
950 | 950 | } |
951 | 951 | } |
|
1507 | 1507 |
|
1508 | 1508 | var equal = cursorEqual(cursor, best); |
1509 | 1509 | var between = (motionArgs.forward) ? |
1510 | | - cusrorIsBetween(cursor, mark, best) : |
1511 | | - cusrorIsBetween(best, mark, cursor); |
| 1510 | + cursorIsBetween(cursor, mark, best) : |
| 1511 | + cursorIsBetween(best, mark, cursor); |
1512 | 1512 |
|
1513 | 1513 | if (equal || between) { |
1514 | 1514 | best = mark; |
|
1760 | 1760 | return null; |
1761 | 1761 | } |
1762 | 1762 |
|
1763 | | - return [tmp.start, tmp.end]; |
| 1763 | + if (!cm.state.vim.visualMode) { |
| 1764 | + return [tmp.start, tmp.end]; |
| 1765 | + } else { |
| 1766 | + return expandSelection(cm, tmp.start, tmp.end); |
| 1767 | + } |
1764 | 1768 | }, |
1765 | 1769 |
|
1766 | 1770 | repeatLastCharacterSearch: function(cm, motionArgs) { |
|
2634 | 2638 | } |
2635 | 2639 | return false; |
2636 | 2640 | } |
2637 | | - function cusrorIsBetween(cur1, cur2, cur3) { |
| 2641 | + function cursorMin(cur1, cur2) { |
| 2642 | + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; |
| 2643 | + } |
| 2644 | + function cursorMax(cur1, cur2) { |
| 2645 | + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; |
| 2646 | + } |
| 2647 | + function cursorIsBetween(cur1, cur2, cur3) { |
2638 | 2648 | // returns true if cur2 is between cur1 and cur3. |
2639 | 2649 | var cur1before2 = cursorIsBefore(cur1, cur2); |
2640 | 2650 | var cur2before3 = cursorIsBefore(cur2, cur3); |
|
2861 | 2871 | 'visualLine': vim.visualLine, |
2862 | 2872 | 'visualBlock': block}; |
2863 | 2873 | } |
| 2874 | + function expandSelection(cm, start, end) { |
| 2875 | + var head = cm.getCursor('head'); |
| 2876 | + var anchor = cm.getCursor('anchor'); |
| 2877 | + var tmp; |
| 2878 | + if (cursorIsBefore(end, start)) { |
| 2879 | + tmp = end; |
| 2880 | + end = start; |
| 2881 | + start = tmp; |
| 2882 | + } |
| 2883 | + if (cursorIsBefore(head, anchor)) { |
| 2884 | + head = cursorMin(start, head); |
| 2885 | + anchor = cursorMax(anchor, end); |
| 2886 | + } else { |
| 2887 | + anchor = cursorMin(start, anchor); |
| 2888 | + head = cursorMax(head, end); |
| 2889 | + } |
| 2890 | + return [anchor, head]; |
| 2891 | + } |
| 2892 | + function getHead(cm) { |
| 2893 | + var cur = cm.getCursor('head'); |
| 2894 | + if (cm.getSelection().length == 1) { |
| 2895 | + // Small corner case when only 1 character is selected. The "real" |
| 2896 | + // head is the left of head and anchor. |
| 2897 | + cur = cursorMin(cur, cm.getCursor('anchor')); |
| 2898 | + } |
| 2899 | + return cur; |
| 2900 | + } |
2864 | 2901 |
|
2865 | 2902 | function exitVisualMode(cm) { |
2866 | 2903 | cm.off('mousedown', exitVisualMode); |
|
2933 | 2970 | } |
2934 | 2971 |
|
2935 | 2972 | function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { |
2936 | | - var cur = cm.getCursor(); |
| 2973 | + var cur = getHead(cm); |
2937 | 2974 | var line = cm.getLine(cur.line); |
2938 | 2975 | var idx = cur.ch; |
2939 | 2976 |
|
|
3319 | 3356 | // TODO: perhaps this finagling of start and end positions belonds |
3320 | 3357 | // in codmirror/replaceRange? |
3321 | 3358 | function selectCompanionObject(cm, symb, inclusive) { |
3322 | | - var cur = cm.getCursor(), start, end; |
| 3359 | + var cur = getHead(cm), start, end; |
3323 | 3360 |
|
3324 | 3361 | var bracketRegexp = ({ |
3325 | 3362 | '(': /[()]/, ')': /[()]/, |
|
3364 | 3401 | // have identical opening and closing symbols |
3365 | 3402 | // TODO support across multiple lines |
3366 | 3403 | function findBeginningAndEnd(cm, symb, inclusive) { |
3367 | | - var cur = copyCursor(cm.getCursor()); |
| 3404 | + var cur = copyCursor(getHead(cm)); |
3368 | 3405 | var line = cm.getLine(cur.line); |
3369 | 3406 | var chars = line.split(''); |
3370 | 3407 | var start, end, i, len; |
|
0 commit comments