codemirror-rails 4.4 → 4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +77 -47
- data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +2 -2
- data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +26 -14
- data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +4 -0
- data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +2 -1
- data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +53 -57
- data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +39 -16
- data/vendor/assets/javascripts/codemirror/addons/search/search.js +3 -3
- data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +6 -3
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +333 -90
- data/vendor/assets/javascripts/codemirror/modes/clike.js +11 -0
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -4
- data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/php.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +15 -9
- data/vendor/assets/javascripts/codemirror/modes/sass.js +91 -110
- data/vendor/assets/javascripts/codemirror/modes/slim.js +575 -0
- data/vendor/assets/javascripts/codemirror/modes/verilog.js +5 -0
- data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +6 -0
- metadata +3 -2
@@ -37,7 +37,7 @@
|
|
37
37
|
constructor: DiffView,
|
38
38
|
init: function(pane, orig, options) {
|
39
39
|
this.edit = this.mv.edit;
|
40
|
-
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly:
|
40
|
+
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
|
41
41
|
|
42
42
|
this.diff = getDiff(asString(orig), asString(options.value));
|
43
43
|
this.diffOutOfDate = false;
|
@@ -71,7 +71,7 @@
|
|
71
71
|
function update(mode) {
|
72
72
|
if (mode == "full") {
|
73
73
|
if (dv.svg) clear(dv.svg);
|
74
|
-
clear(dv.copyButtons);
|
74
|
+
if (dv.copyButtons) clear(dv.copyButtons);
|
75
75
|
clearMarks(dv.edit, edit.marked, dv.classes);
|
76
76
|
clearMarks(dv.orig, orig.marked, dv.classes);
|
77
77
|
edit.from = edit.to = orig.from = orig.to = 0;
|
@@ -257,7 +257,7 @@
|
|
257
257
|
var w = dv.gap.offsetWidth;
|
258
258
|
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
|
259
259
|
}
|
260
|
-
clear(dv.copyButtons);
|
260
|
+
if (dv.copyButtons) clear(dv.copyButtons);
|
261
261
|
|
262
262
|
var flip = dv.type == "left";
|
263
263
|
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
|
@@ -279,17 +279,30 @@
|
|
279
279
|
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
|
280
280
|
"class", dv.classes.connect);
|
281
281
|
}
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
282
|
+
if (dv.copyButtons) {
|
283
|
+
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
|
284
|
+
"CodeMirror-merge-copy"));
|
285
|
+
var editOriginals = dv.mv.options.allowEditingOriginals;
|
286
|
+
copy.title = editOriginals ? "Push to left" : "Revert chunk";
|
287
|
+
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
|
288
|
+
copy.style.top = top + "px";
|
289
|
+
|
290
|
+
if (editOriginals) {
|
291
|
+
var topReverse = dv.orig.heightAtLine(topEdit, "local") - sTopEdit;
|
292
|
+
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
|
293
|
+
"CodeMirror-merge-copy-reverse"));
|
294
|
+
copyReverse.title = "Push to right";
|
295
|
+
copyReverse.chunk = {topEdit: topOrig, botEdit: botOrig, topOrig: topEdit, botOrig: botEdit};
|
296
|
+
copyReverse.style.top = topReverse + "px";
|
297
|
+
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
|
298
|
+
}
|
299
|
+
}
|
287
300
|
});
|
288
301
|
}
|
289
302
|
|
290
|
-
function copyChunk(dv, chunk) {
|
303
|
+
function copyChunk(dv, to, from, chunk) {
|
291
304
|
if (dv.diffOutOfDate) return;
|
292
|
-
|
305
|
+
to.replaceRange(from.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),
|
293
306
|
Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));
|
294
307
|
}
|
295
308
|
|
@@ -298,6 +311,7 @@
|
|
298
311
|
var MergeView = CodeMirror.MergeView = function(node, options) {
|
299
312
|
if (!(this instanceof MergeView)) return new MergeView(node, options);
|
300
313
|
|
314
|
+
this.options = options;
|
301
315
|
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
|
302
316
|
var hasLeft = origLeft != null, hasRight = origRight != null;
|
303
317
|
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
|
@@ -323,6 +337,7 @@
|
|
323
337
|
(hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
|
324
338
|
|
325
339
|
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
|
340
|
+
|
326
341
|
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
|
327
342
|
this.edit = CodeMirror(editPane, copyObj(options));
|
328
343
|
|
@@ -345,12 +360,20 @@
|
|
345
360
|
lock.title = "Toggle locked scrolling";
|
346
361
|
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
|
347
362
|
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
363
|
+
var gapElts = [lockWrap];
|
364
|
+
if (dv.mv.options.revertButtons !== false) {
|
365
|
+
dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
|
366
|
+
CodeMirror.on(dv.copyButtons, "click", function(e) {
|
367
|
+
var node = e.target || e.srcElement;
|
368
|
+
if (!node.chunk) return;
|
369
|
+
if (node.className == "CodeMirror-merge-copy-reverse") {
|
370
|
+
copyChunk(dv, dv.orig, dv.edit, node.chunk);
|
371
|
+
return;
|
372
|
+
}
|
373
|
+
copyChunk(dv, dv.edit, dv.orig, node.chunk);
|
374
|
+
});
|
375
|
+
gapElts.unshift(dv.copyButtons);
|
376
|
+
}
|
354
377
|
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
|
355
378
|
if (svg && !svg.createSVGRect) svg = null;
|
356
379
|
dv.svg = svg;
|
@@ -71,7 +71,7 @@
|
|
71
71
|
return query;
|
72
72
|
}
|
73
73
|
var queryDialog =
|
74
|
-
'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
|
74
|
+
'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
|
75
75
|
function doSearch(cm, rev) {
|
76
76
|
var state = getSearchState(cm);
|
77
77
|
if (state.query) return findNext(cm, rev);
|
@@ -106,8 +106,8 @@
|
|
106
106
|
});}
|
107
107
|
|
108
108
|
var replaceQueryDialog =
|
109
|
-
'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
|
110
|
-
var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
|
109
|
+
'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
|
110
|
+
var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
|
111
111
|
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
|
112
112
|
function replace(cm, all) {
|
113
113
|
if (cm.getOption("readOnly")) return;
|
@@ -17,7 +17,8 @@
|
|
17
17
|
var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};
|
18
18
|
var cmds = CodeMirror.commands;
|
19
19
|
var Pos = CodeMirror.Pos;
|
20
|
-
var
|
20
|
+
var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
|
21
|
+
var ctrl = mac ? "Cmd-" : "Ctrl-";
|
21
22
|
|
22
23
|
// This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
|
23
24
|
function findPosSubword(doc, start, dir) {
|
@@ -186,7 +187,9 @@
|
|
186
187
|
});
|
187
188
|
};
|
188
189
|
|
189
|
-
|
190
|
+
var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";
|
191
|
+
|
192
|
+
cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {
|
190
193
|
var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
|
191
194
|
for (var i = 0; i < ranges.length; i++) {
|
192
195
|
var range = ranges[i], from = range.from().line - 1, to = range.to().line;
|
@@ -212,7 +215,7 @@
|
|
212
215
|
});
|
213
216
|
};
|
214
217
|
|
215
|
-
cmds[map[
|
218
|
+
cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {
|
216
219
|
var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
|
217
220
|
for (var i = ranges.length - 1; i >= 0; i--) {
|
218
221
|
var range = ranges[i], from = range.to().line + 1, to = range.from().line;
|
@@ -616,7 +616,9 @@
|
|
616
616
|
visualLine: false,
|
617
617
|
visualBlock: false,
|
618
618
|
lastSelection: null,
|
619
|
-
lastPastedText: null
|
619
|
+
lastPastedText: null,
|
620
|
+
// Used by two-character ESC keymap routines. Should not be changed from false here.
|
621
|
+
awaitingEscapeSecondCharacter: false
|
620
622
|
};
|
621
623
|
}
|
622
624
|
return cm.state.vim;
|
@@ -785,17 +787,19 @@
|
|
785
787
|
* pasted, should it insert itself into a new line, or should the text be
|
786
788
|
* inserted at the cursor position.)
|
787
789
|
*/
|
788
|
-
function Register(text, linewise) {
|
790
|
+
function Register(text, linewise, blockwise) {
|
789
791
|
this.clear();
|
790
792
|
this.keyBuffer = [text || ''];
|
791
793
|
this.insertModeChanges = [];
|
792
794
|
this.searchQueries = [];
|
793
795
|
this.linewise = !!linewise;
|
796
|
+
this.blockwise = !!blockwise;
|
794
797
|
}
|
795
798
|
Register.prototype = {
|
796
|
-
setText: function(text, linewise) {
|
799
|
+
setText: function(text, linewise, blockwise) {
|
797
800
|
this.keyBuffer = [text || ''];
|
798
801
|
this.linewise = !!linewise;
|
802
|
+
this.blockwise = !!blockwise;
|
799
803
|
},
|
800
804
|
pushText: function(text, linewise) {
|
801
805
|
// if this register has ever been set to linewise, use linewise.
|
@@ -840,7 +844,7 @@
|
|
840
844
|
registers['/'] = new Register();
|
841
845
|
}
|
842
846
|
RegisterController.prototype = {
|
843
|
-
pushText: function(registerName, operator, text, linewise) {
|
847
|
+
pushText: function(registerName, operator, text, linewise, blockwise) {
|
844
848
|
if (linewise && text.charAt(0) == '\n') {
|
845
849
|
text = text.slice(1) + '\n';
|
846
850
|
}
|
@@ -857,7 +861,7 @@
|
|
857
861
|
switch (operator) {
|
858
862
|
case 'yank':
|
859
863
|
// The 0 register contains the text from the most recent yank.
|
860
|
-
this.registers['0'] = new Register(text, linewise);
|
864
|
+
this.registers['0'] = new Register(text, linewise, blockwise);
|
861
865
|
break;
|
862
866
|
case 'delete':
|
863
867
|
case 'change':
|
@@ -873,7 +877,7 @@
|
|
873
877
|
break;
|
874
878
|
}
|
875
879
|
// Make sure the unnamed register is set to what just happened
|
876
|
-
this.unnamedRegister.setText(text, linewise);
|
880
|
+
this.unnamedRegister.setText(text, linewise, blockwise);
|
877
881
|
return;
|
878
882
|
}
|
879
883
|
|
@@ -882,7 +886,7 @@
|
|
882
886
|
if (append) {
|
883
887
|
register.pushText(text, linewise);
|
884
888
|
} else {
|
885
|
-
register.setText(text, linewise);
|
889
|
+
register.setText(text, linewise, blockwise);
|
886
890
|
}
|
887
891
|
// The unnamed register always has the same value as the last used
|
888
892
|
// register.
|
@@ -1860,6 +1864,12 @@
|
|
1860
1864
|
var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;
|
1861
1865
|
var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
|
1862
1866
|
var text = cm.getSelection();
|
1867
|
+
var visualBlock = vim.visualBlock;
|
1868
|
+
if (vim.lastSelection && !vim.visualMode) {
|
1869
|
+
visualBlock = vim.lastSelection.visualBlock ? true : visualBlock;
|
1870
|
+
}
|
1871
|
+
var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges;
|
1872
|
+
lastInsertModeChanges.inVisualBlock = visualBlock;
|
1863
1873
|
var replacement = new Array(selections.length).join('1').split('1');
|
1864
1874
|
// save the selectionEnd mark
|
1865
1875
|
var selectionEnd = vim.marks['>'] ? vim.marks['>'].find() : cm.getCursor('head');
|
@@ -1868,7 +1878,7 @@
|
|
1868
1878
|
operatorArgs.linewise);
|
1869
1879
|
if (operatorArgs.linewise) {
|
1870
1880
|
// 'C' in visual block extends the block till eol for all lines
|
1871
|
-
if (
|
1881
|
+
if (visualBlock){
|
1872
1882
|
var startLine = curStart.line;
|
1873
1883
|
while (startLine <= curEnd.line) {
|
1874
1884
|
var endCh = lineLength(cm, startLine);
|
@@ -1898,7 +1908,7 @@
|
|
1898
1908
|
curEnd = offsetCursor(curEnd, 0, - match[0].length);
|
1899
1909
|
}
|
1900
1910
|
}
|
1901
|
-
if (
|
1911
|
+
if (visualBlock) {
|
1902
1912
|
cm.replaceSelections(replacement);
|
1903
1913
|
} else {
|
1904
1914
|
cm.setCursor(curStart);
|
@@ -1916,17 +1926,19 @@
|
|
1916
1926
|
var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
|
1917
1927
|
// Save the '>' mark before cm.replaceRange clears it.
|
1918
1928
|
var selectionEnd, selectionStart;
|
1929
|
+
var blockwise = vim.visualBlock;
|
1919
1930
|
if (vim.visualMode) {
|
1920
1931
|
selectionEnd = vim.marks['>'].find();
|
1921
1932
|
selectionStart = vim.marks['<'].find();
|
1922
1933
|
} else if (vim.lastSelection) {
|
1923
1934
|
selectionEnd = vim.lastSelection.curStartMark.find();
|
1924
1935
|
selectionStart = vim.lastSelection.curEndMark.find();
|
1936
|
+
blockwise = vim.lastSelection.visualBlock;
|
1925
1937
|
}
|
1926
1938
|
var text = cm.getSelection();
|
1927
1939
|
vimGlobalState.registerController.pushText(
|
1928
1940
|
operatorArgs.registerName, 'delete', text,
|
1929
|
-
operatorArgs.linewise);
|
1941
|
+
operatorArgs.linewise, blockwise);
|
1930
1942
|
var replacement = new Array(selections.length).join('1').split('1');
|
1931
1943
|
// If the ending line is past the last line, inclusive, instead of
|
1932
1944
|
// including the trailing \n, include the \n before the starting line
|
@@ -1999,11 +2011,11 @@
|
|
1999
2011
|
cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd);
|
2000
2012
|
}
|
2001
2013
|
},
|
2002
|
-
yank: function(cm, operatorArgs,
|
2014
|
+
yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) {
|
2003
2015
|
var text = cm.getSelection();
|
2004
2016
|
vimGlobalState.registerController.pushText(
|
2005
2017
|
operatorArgs.registerName, 'yank',
|
2006
|
-
text, operatorArgs.linewise);
|
2018
|
+
text, operatorArgs.linewise, vim.visualBlock);
|
2007
2019
|
cm.setCursor(curOriginal);
|
2008
2020
|
}
|
2009
2021
|
};
|
@@ -2096,6 +2108,11 @@
|
|
2096
2108
|
vim.insertMode = true;
|
2097
2109
|
vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
|
2098
2110
|
var insertAt = (actionArgs) ? actionArgs.insertAt : null;
|
2111
|
+
if (vim.visualMode) {
|
2112
|
+
var selections = getSelectedAreaRange(cm, vim);
|
2113
|
+
var selectionStart = selections[0];
|
2114
|
+
var selectionEnd = selections[1];
|
2115
|
+
}
|
2099
2116
|
if (insertAt == 'eol') {
|
2100
2117
|
var cursor = cm.getCursor();
|
2101
2118
|
cursor = Pos(cursor.line, lineLength(cm, cursor.line));
|
@@ -2103,15 +2120,34 @@
|
|
2103
2120
|
} else if (insertAt == 'charAfter') {
|
2104
2121
|
cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
|
2105
2122
|
} else if (insertAt == 'firstNonBlank') {
|
2106
|
-
|
2123
|
+
if (vim.visualMode && !vim.visualBlock) {
|
2124
|
+
if (selectionEnd.line < selectionStart.line) {
|
2125
|
+
cm.setCursor(selectionEnd);
|
2126
|
+
} else {
|
2127
|
+
selectionStart = Pos(selectionStart.line, 0);
|
2128
|
+
cm.setCursor(selectionStart);
|
2129
|
+
}
|
2130
|
+
cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));
|
2131
|
+
} else if (vim.visualBlock) {
|
2132
|
+
selectionEnd = Pos(selectionEnd.line, selectionStart.ch);
|
2133
|
+
cm.setCursor(selectionStart);
|
2134
|
+
selectBlock(cm, selectionEnd);
|
2135
|
+
} else {
|
2136
|
+
cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));
|
2137
|
+
}
|
2107
2138
|
} else if (insertAt == 'endOfSelectedArea') {
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2139
|
+
if (vim.visualBlock) {
|
2140
|
+
selectionStart = Pos(selectionStart.line, selectionEnd.ch);
|
2141
|
+
cm.setCursor(selectionStart);
|
2142
|
+
selectBlock(cm, selectionEnd);
|
2143
|
+
} else if (selectionEnd.line < selectionStart.line) {
|
2111
2144
|
selectionEnd = Pos(selectionStart.line, 0);
|
2145
|
+
cm.setCursor(selectionEnd);
|
2146
|
+
}
|
2147
|
+
} else if (insertAt == 'inplace') {
|
2148
|
+
if (vim.visualMode){
|
2149
|
+
return;
|
2112
2150
|
}
|
2113
|
-
cm.setCursor(selectionEnd);
|
2114
|
-
exitVisualMode(cm);
|
2115
2151
|
}
|
2116
2152
|
cm.setOption('keyMap', 'vim-insert');
|
2117
2153
|
cm.setOption('disableInput', false);
|
@@ -2129,6 +2165,9 @@
|
|
2129
2165
|
cm.on('change', onChange);
|
2130
2166
|
CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
|
2131
2167
|
}
|
2168
|
+
if (vim.visualMode) {
|
2169
|
+
exitVisualMode(cm);
|
2170
|
+
}
|
2132
2171
|
},
|
2133
2172
|
toggleVisualMode: function(cm, actionArgs, vim) {
|
2134
2173
|
var repeat = actionArgs.repeat;
|
@@ -2339,6 +2378,7 @@
|
|
2339
2378
|
var text = Array(actionArgs.repeat + 1).join(text);
|
2340
2379
|
}
|
2341
2380
|
var linewise = register.linewise;
|
2381
|
+
var blockwise = register.blockwise;
|
2342
2382
|
if (linewise) {
|
2343
2383
|
if(vim.visualMode) {
|
2344
2384
|
text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n';
|
@@ -2351,6 +2391,12 @@
|
|
2351
2391
|
cur.ch = 0;
|
2352
2392
|
}
|
2353
2393
|
} else {
|
2394
|
+
if (blockwise) {
|
2395
|
+
text = text.split('\n');
|
2396
|
+
for (var i = 0; i < text.length; i++) {
|
2397
|
+
text[i] = (text[i] == '') ? ' ' : text[i];
|
2398
|
+
}
|
2399
|
+
}
|
2354
2400
|
cur.ch += actionArgs.after ? 1 : 0;
|
2355
2401
|
}
|
2356
2402
|
var curPosFinal;
|
@@ -2362,32 +2408,75 @@
|
|
2362
2408
|
var selectedArea = getSelectedAreaRange(cm, vim);
|
2363
2409
|
var selectionStart = selectedArea[0];
|
2364
2410
|
var selectionEnd = selectedArea[1];
|
2411
|
+
var selectedText = cm.getSelection();
|
2412
|
+
var selections = cm.listSelections();
|
2413
|
+
var emptyStrings = new Array(selections.length).join('1').split('1');
|
2365
2414
|
// save the curEnd marker before it get cleared due to cm.replaceRange.
|
2366
|
-
if (vim.lastSelection)
|
2415
|
+
if (vim.lastSelection) {
|
2416
|
+
lastSelectionCurEnd = vim.lastSelection.curEndMark.find();
|
2417
|
+
}
|
2367
2418
|
// push the previously selected text to unnamed register
|
2368
|
-
vimGlobalState.registerController.unnamedRegister.setText(
|
2369
|
-
|
2419
|
+
vimGlobalState.registerController.unnamedRegister.setText(selectedText);
|
2420
|
+
if (blockwise) {
|
2421
|
+
// first delete the selected text
|
2422
|
+
cm.replaceSelections(emptyStrings);
|
2423
|
+
// Set new selections as per the block length of the yanked text
|
2424
|
+
selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch);
|
2425
|
+
cm.setCursor(selectionStart);
|
2426
|
+
selectBlock(cm, selectionEnd);
|
2427
|
+
cm.replaceSelections(text);
|
2428
|
+
curPosFinal = selectionStart;
|
2429
|
+
} else if (vim.visualBlock) {
|
2430
|
+
cm.replaceSelections(emptyStrings);
|
2431
|
+
cm.setCursor(selectionStart);
|
2432
|
+
cm.replaceRange(text, selectionStart, selectionStart);
|
2433
|
+
curPosFinal = selectionStart;
|
2434
|
+
} else {
|
2435
|
+
cm.replaceRange(text, selectionStart, selectionEnd);
|
2436
|
+
curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);
|
2437
|
+
}
|
2370
2438
|
// restore the the curEnd marker
|
2371
|
-
if(lastSelectionCurEnd)
|
2372
|
-
|
2373
|
-
|
2439
|
+
if(lastSelectionCurEnd) {
|
2440
|
+
vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd);
|
2441
|
+
}
|
2442
|
+
if (linewise) {
|
2443
|
+
curPosFinal.ch=0;
|
2444
|
+
}
|
2374
2445
|
} else {
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2446
|
+
if (blockwise) {
|
2447
|
+
cm.setCursor(cur);
|
2448
|
+
for (var i = 0; i < text.length; i++) {
|
2449
|
+
var line = cur.line+i;
|
2450
|
+
if (line > cm.lastLine()) {
|
2451
|
+
cm.replaceRange('\n', Pos(line, 0));
|
2452
|
+
}
|
2453
|
+
var lastCh = lineLength(cm, line);
|
2454
|
+
if (lastCh < cur.ch) {
|
2455
|
+
extendLineToColumn(cm, line, cur.ch);
|
2456
|
+
}
|
2457
|
+
}
|
2458
|
+
cm.setCursor(cur);
|
2459
|
+
selectBlock(cm, Pos(cur.line + text.length-1, cur.ch));
|
2460
|
+
cm.replaceSelections(text);
|
2461
|
+
curPosFinal = cur;
|
2462
|
+
} else {
|
2463
|
+
cm.replaceRange(text, cur);
|
2464
|
+
// Now fine tune the cursor to where we want it.
|
2465
|
+
if (linewise && actionArgs.after) {
|
2466
|
+
curPosFinal = Pos(
|
2379
2467
|
cur.line + 1,
|
2380
2468
|
findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)));
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2469
|
+
} else if (linewise && !actionArgs.after) {
|
2470
|
+
curPosFinal = Pos(
|
2471
|
+
cur.line,
|
2472
|
+
findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)));
|
2473
|
+
} else if (!linewise && actionArgs.after) {
|
2474
|
+
idx = cm.indexFromPos(cur);
|
2475
|
+
curPosFinal = cm.posFromIndex(idx + text.length - 1);
|
2476
|
+
} else {
|
2477
|
+
idx = cm.indexFromPos(cur);
|
2478
|
+
curPosFinal = cm.posFromIndex(idx + text.length);
|
2479
|
+
}
|
2391
2480
|
}
|
2392
2481
|
}
|
2393
2482
|
cm.setCursor(curPosFinal);
|
@@ -2597,6 +2686,12 @@
|
|
2597
2686
|
function escapeRegex(s) {
|
2598
2687
|
return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1');
|
2599
2688
|
}
|
2689
|
+
function extendLineToColumn(cm, lineNum, column) {
|
2690
|
+
var endCh = lineLength(cm, lineNum);
|
2691
|
+
var spaces = new Array(column-endCh+1).join(' ');
|
2692
|
+
cm.setCursor(Pos(lineNum, endCh));
|
2693
|
+
cm.replaceRange(spaces, cm.getCursor());
|
2694
|
+
}
|
2600
2695
|
// This functions selects a rectangular block
|
2601
2696
|
// of text with selectionEnd as any of its corner
|
2602
2697
|
// Height of block:
|
@@ -2606,55 +2701,86 @@
|
|
2606
2701
|
function selectBlock(cm, selectionEnd) {
|
2607
2702
|
var selections = [], ranges = cm.listSelections();
|
2608
2703
|
var firstRange = ranges[0].anchor, lastRange = ranges[ranges.length-1].anchor;
|
2609
|
-
var start, end, selectionStart;
|
2704
|
+
var start, end, direction, selectionStart;
|
2610
2705
|
var curEnd = cm.getCursor('head');
|
2706
|
+
var originalSelectionEnd = copyCursor(selectionEnd);
|
2707
|
+
start = firstRange.line;
|
2708
|
+
end = lastRange.line;
|
2709
|
+
if (selectionEnd.line < curEnd.line) {
|
2710
|
+
direction = 'up';
|
2711
|
+
} else if (selectionEnd.line > curEnd.line) {
|
2712
|
+
direction = 'down';
|
2713
|
+
} else {
|
2714
|
+
if (selectionEnd.ch != curEnd.ch) {
|
2715
|
+
direction = selectionEnd.ch > curEnd.ch ? 'right' : 'left';
|
2716
|
+
}
|
2717
|
+
selectionStart = cm.getCursor('anchor');
|
2718
|
+
}
|
2611
2719
|
var primIndex = getIndex(ranges, curEnd);
|
2612
2720
|
// sets to true when selectionEnd already lies inside the existing selections
|
2613
|
-
var contains = getIndex(ranges, selectionEnd) < 0 ? false : true;
|
2614
2721
|
selectionEnd = cm.clipPos(selectionEnd);
|
2615
|
-
|
2616
|
-
var
|
2617
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
if (
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2625
|
-
|
2626
|
-
|
2627
|
-
|
2722
|
+
var contains = getIndex(ranges, selectionEnd) < 0 ? false : true;
|
2723
|
+
var isClipped = !cursorEqual(originalSelectionEnd, selectionEnd);
|
2724
|
+
// This function helps to check selection crossing
|
2725
|
+
// in case of short lines.
|
2726
|
+
var processSelectionCrossing = function() {
|
2727
|
+
if (isClipped) {
|
2728
|
+
if (curEnd.ch >= selectionStart.ch) {
|
2729
|
+
selectionStart.ch++;
|
2730
|
+
}
|
2731
|
+
} else if (curEnd.ch == lineLength(cm, curEnd.line)) {
|
2732
|
+
if (cursorEqual(ranges[primIndex].anchor, ranges[primIndex].head) && ranges.length>1) {
|
2733
|
+
if (direction == 'up') {
|
2734
|
+
if (contains || primIndex>0) {
|
2735
|
+
start = firstRange.line;
|
2736
|
+
end = selectionEnd.line;
|
2737
|
+
selectionStart = ranges[primIndex-1].anchor;
|
2738
|
+
}
|
2739
|
+
} else {
|
2740
|
+
if (contains || primIndex == 0) {
|
2741
|
+
end = lastRange.line;
|
2742
|
+
start = selectionEnd.line;
|
2743
|
+
selectionStart = ranges[primIndex+1].anchor;
|
2744
|
+
}
|
2745
|
+
}
|
2746
|
+
if (selectionEnd.ch >= selectionStart.ch) {
|
2747
|
+
selectionStart.ch--;
|
2748
|
+
}
|
2749
|
+
}
|
2628
2750
|
}
|
2629
|
-
}
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
2751
|
+
};
|
2752
|
+
switch(direction) {
|
2753
|
+
case 'up':
|
2754
|
+
start = contains ? firstRange.line : selectionEnd.line;
|
2755
|
+
end = contains ? selectionEnd.line : lastRange.line;
|
2756
|
+
selectionStart = lastRange;
|
2757
|
+
processSelectionCrossing();
|
2758
|
+
break;
|
2759
|
+
case 'down':
|
2760
|
+
start = contains ? selectionEnd.line : firstRange.line;
|
2761
|
+
end = contains ? lastRange.line : selectionEnd.line;
|
2762
|
+
selectionStart = firstRange;
|
2763
|
+
processSelectionCrossing();
|
2764
|
+
break;
|
2765
|
+
case 'left':
|
2766
|
+
if ((selectionEnd.ch <= selectionStart.ch) && (curEnd.ch > selectionStart.ch)) {
|
2767
|
+
selectionStart.ch++;
|
2768
|
+
selectionEnd.ch--;
|
2769
|
+
}
|
2770
|
+
break;
|
2771
|
+
case 'right':
|
2772
|
+
if ((selectionStart.ch <= selectionEnd.ch) && (curEnd.ch < selectionStart.ch)) {
|
2773
|
+
selectionStart.ch--;
|
2774
|
+
selectionEnd.ch++;
|
2775
|
+
}
|
2776
|
+
break;
|
2777
|
+
default:
|
2778
|
+
start = selectionStart.line;
|
2637
2779
|
end = selectionEnd.line;
|
2638
|
-
}
|
2639
|
-
}
|
2640
|
-
if (start > end) {
|
2641
|
-
var tmp = start;
|
2642
|
-
start = end;
|
2643
|
-
end = tmp;
|
2644
2780
|
}
|
2645
|
-
selectionStart = (near > 0) ? firstRange : lastRange;
|
2646
2781
|
while (start <= end) {
|
2647
2782
|
var anchor = {line: start, ch: selectionStart.ch};
|
2648
2783
|
var head = {line: start, ch: selectionEnd.ch};
|
2649
|
-
// Shift the anchor right or left
|
2650
|
-
// as each selection crosses itself.
|
2651
|
-
if ((anchor.ch < curEnd.ch) && ((head.ch == anchor.ch) || (anchor.ch - head.ch == 1))) {
|
2652
|
-
anchor.ch++;
|
2653
|
-
head.ch--;
|
2654
|
-
} else if ((anchor.ch > curEnd.ch) && ((head.ch == anchor.ch) || (anchor.ch - head.ch == -1))) {
|
2655
|
-
anchor.ch--;
|
2656
|
-
head.ch++;
|
2657
|
-
}
|
2658
2784
|
var range = {anchor: anchor, head: head};
|
2659
2785
|
selections.push(range);
|
2660
2786
|
if (cursorEqual(head, selectionEnd)) {
|
@@ -2666,16 +2792,29 @@
|
|
2666
2792
|
// after selection crossing
|
2667
2793
|
selectionEnd.ch = selections[0].head.ch;
|
2668
2794
|
selectionStart.ch = selections[0].anchor.ch;
|
2795
|
+
if (cursorEqual(selectionEnd, selections[0].head)) {
|
2796
|
+
selectionStart.line = selections[selections.length-1].anchor.line;
|
2797
|
+
} else {
|
2798
|
+
selectionStart.line = selections[0].anchor.line;
|
2799
|
+
}
|
2669
2800
|
cm.setSelections(selections, primIndex);
|
2670
2801
|
return selectionStart;
|
2671
2802
|
}
|
2672
|
-
|
2803
|
+
// getIndex returns the index of the cursor in the selections.
|
2804
|
+
function getIndex(ranges, cursor, end) {
|
2805
|
+
var pos = -1;
|
2673
2806
|
for (var i = 0; i < ranges.length; i++) {
|
2674
|
-
|
2675
|
-
|
2807
|
+
var atAnchor = cursorEqual(ranges[i].anchor, cursor);
|
2808
|
+
var atHead = cursorEqual(ranges[i].head, cursor);
|
2809
|
+
if (end == 'head') {
|
2810
|
+
pos = atHead ? i : pos;
|
2811
|
+
} else if (end == 'anchor') {
|
2812
|
+
pos = atAnchor ? i : pos;
|
2813
|
+
} else {
|
2814
|
+
pos = (atAnchor || atHead) ? i : pos;
|
2676
2815
|
}
|
2677
2816
|
}
|
2678
|
-
return
|
2817
|
+
return pos;
|
2679
2818
|
}
|
2680
2819
|
function getSelectedAreaRange(cm, vim) {
|
2681
2820
|
var lastSelection = vim.lastSelection;
|
@@ -2739,7 +2878,7 @@
|
|
2739
2878
|
var ranges = cm.listSelections();
|
2740
2879
|
// This check ensures to set the cursor
|
2741
2880
|
// position where we left off in previous selection
|
2742
|
-
var swap = getIndex(ranges, selectionStart) > -1;
|
2881
|
+
var swap = getIndex(ranges, selectionStart, 'head') > -1;
|
2743
2882
|
if (vim.visualBlock) {
|
2744
2883
|
var height = Math.abs(selectionStart.line - selectionEnd.line)+1;
|
2745
2884
|
var width = Math.abs(selectionStart.ch - selectionEnd.ch);
|
@@ -2759,14 +2898,16 @@
|
|
2759
2898
|
var vim = cm.state.vim;
|
2760
2899
|
var selectionStart = cm.getCursor('anchor');
|
2761
2900
|
var selectionEnd = cm.getCursor('head');
|
2901
|
+
// hack to place the cursor at the right place
|
2902
|
+
// in case of visual block
|
2903
|
+
if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) {
|
2904
|
+
selectionEnd.ch--;
|
2905
|
+
}
|
2762
2906
|
updateLastSelection(cm, vim);
|
2763
2907
|
vim.visualMode = false;
|
2764
2908
|
vim.visualLine = false;
|
2765
2909
|
vim.visualBlock = false;
|
2766
2910
|
if (!cursorEqual(selectionStart, selectionEnd)) {
|
2767
|
-
// Clear the selection and set the cursor only if the selection has not
|
2768
|
-
// already been cleared. Otherwise we risk moving the cursor somewhere
|
2769
|
-
// it's not supposed to be.
|
2770
2911
|
cm.setCursor(clipCursorToContent(cm, selectionEnd));
|
2771
2912
|
}
|
2772
2913
|
CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
|
@@ -4498,7 +4639,32 @@
|
|
4498
4639
|
var macroModeState = vimGlobalState.macroModeState;
|
4499
4640
|
var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.');
|
4500
4641
|
var isPlaying = macroModeState.isPlaying;
|
4642
|
+
var lastChange = macroModeState.lastInsertModeChanges;
|
4643
|
+
// In case of visual block, the insertModeChanges are not saved as a
|
4644
|
+
// single word, so we convert them to a single word
|
4645
|
+
// so as to update the ". register as expected in real vim.
|
4646
|
+
var text = [];
|
4501
4647
|
if (!isPlaying) {
|
4648
|
+
var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1;
|
4649
|
+
var changes = lastChange.changes;
|
4650
|
+
var text = [];
|
4651
|
+
var i = 0;
|
4652
|
+
// In case of multiple selections in blockwise visual,
|
4653
|
+
// the inserted text, for example: 'f<Backspace>oo', is stored as
|
4654
|
+
// 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines).
|
4655
|
+
// We push the contents of the changes array as per the following:
|
4656
|
+
// 1. In case of InsertModeKey, just increment by 1.
|
4657
|
+
// 2. In case of a character, jump by selLength (2 in the example).
|
4658
|
+
while (i < changes.length) {
|
4659
|
+
// This loop will convert 'ff<bs>oooo' to 'f<bs>oo'.
|
4660
|
+
text.push(changes[i]);
|
4661
|
+
if (changes[i] instanceof InsertModeKey) {
|
4662
|
+
i++;
|
4663
|
+
} else {
|
4664
|
+
i+= selLength;
|
4665
|
+
}
|
4666
|
+
}
|
4667
|
+
lastChange.changes = text;
|
4502
4668
|
cm.off('change', onChange);
|
4503
4669
|
CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
|
4504
4670
|
}
|
@@ -4515,13 +4681,64 @@
|
|
4515
4681
|
cm.setOption('disableInput', true);
|
4516
4682
|
cm.toggleOverwrite(false); // exit replace mode if we were in it.
|
4517
4683
|
// update the ". register before exiting insert mode
|
4518
|
-
insertModeChangeRegister.setText(
|
4684
|
+
insertModeChangeRegister.setText(lastChange.changes.join(''));
|
4519
4685
|
CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
|
4520
4686
|
if (macroModeState.isRecording) {
|
4521
4687
|
logInsertModeChange(macroModeState);
|
4522
4688
|
}
|
4523
4689
|
}
|
4524
4690
|
|
4691
|
+
defineOption('enableInsertModeEscKeys', false, 'boolean');
|
4692
|
+
// Use this option to customize the two-character ESC keymap.
|
4693
|
+
// If you want to use characters other than i j or k you'll have to add
|
4694
|
+
// lines to the vim-insert and await-second keymaps later in this file.
|
4695
|
+
defineOption('insertModeEscKeys', 'kj', 'string');
|
4696
|
+
// The timeout in milliseconds for the two-character ESC keymap should be
|
4697
|
+
// adjusted according to your typing speed to prevent false positives.
|
4698
|
+
defineOption('insertModeEscKeysTimeout', 200, 'number');
|
4699
|
+
function firstEscCharacterHandler(ch) {
|
4700
|
+
return function(cm){
|
4701
|
+
var keys = getOption('insertModeEscKeys');
|
4702
|
+
var firstEscCharacter = keys && keys.length > 1 && keys.charAt(0);
|
4703
|
+
if (!getOption('enableInsertModeEscKeys')|| firstEscCharacter !== ch) {
|
4704
|
+
return CodeMirror.Pass;
|
4705
|
+
} else {
|
4706
|
+
cm.replaceRange(ch, cm.getCursor(), cm.getCursor(), "+input");
|
4707
|
+
cm.setOption('keyMap', 'await-second');
|
4708
|
+
cm.state.vim.awaitingEscapeSecondCharacter = true;
|
4709
|
+
setTimeout(
|
4710
|
+
function(){
|
4711
|
+
if(cm.state.vim.awaitingEscapeSecondCharacter) {
|
4712
|
+
cm.state.vim.awaitingEscapeSecondCharacter = false;
|
4713
|
+
cm.setOption('keyMap', 'vim-insert');
|
4714
|
+
}
|
4715
|
+
},
|
4716
|
+
getOption('insertModeEscKeysTimeout'));
|
4717
|
+
}
|
4718
|
+
};
|
4719
|
+
}
|
4720
|
+
function secondEscCharacterHandler(ch){
|
4721
|
+
return function(cm) {
|
4722
|
+
var keys = getOption('insertModeEscKeys');
|
4723
|
+
var secondEscCharacter = keys && keys.length > 1 && keys.charAt(1);
|
4724
|
+
if (!getOption('enableInsertModeEscKeys')|| secondEscCharacter !== ch) {
|
4725
|
+
return CodeMirror.Pass;
|
4726
|
+
// This is not the handler you're looking for. Just insert as usual.
|
4727
|
+
} else {
|
4728
|
+
if (cm.state.vim.insertMode) {
|
4729
|
+
var lastChange = vimGlobalState.macroModeState.lastInsertModeChanges;
|
4730
|
+
if (lastChange && lastChange.changes.length) {
|
4731
|
+
lastChange.changes.pop();
|
4732
|
+
}
|
4733
|
+
}
|
4734
|
+
cm.state.vim.awaitingEscapeSecondCharacter = false;
|
4735
|
+
cm.replaceRange('', {ch: cm.getCursor().ch - 1, line: cm.getCursor().line},
|
4736
|
+
cm.getCursor(), "+input");
|
4737
|
+
exitInsertMode(cm);
|
4738
|
+
}
|
4739
|
+
};
|
4740
|
+
}
|
4741
|
+
|
4525
4742
|
CodeMirror.keyMap['vim-insert'] = {
|
4526
4743
|
// TODO: override navigation keys so that Esc will cancel automatic
|
4527
4744
|
// indentation from o, O, i_<CR>
|
@@ -4535,9 +4752,23 @@
|
|
4535
4752
|
CodeMirror.commands.newlineAndIndent;
|
4536
4753
|
fn(cm);
|
4537
4754
|
},
|
4755
|
+
// The next few lines are where you'd add additional handlers if
|
4756
|
+
// you wanted to use keys other than i j and k for two-character
|
4757
|
+
// escape sequences. Don't forget to add them in the await-second
|
4758
|
+
// section as well.
|
4759
|
+
"'i'": firstEscCharacterHandler('i'),
|
4760
|
+
"'j'": firstEscCharacterHandler('j'),
|
4761
|
+
"'k'": firstEscCharacterHandler('k'),
|
4538
4762
|
fallthrough: ['default']
|
4539
4763
|
};
|
4540
4764
|
|
4765
|
+
CodeMirror.keyMap['await-second'] = {
|
4766
|
+
"'i'": secondEscCharacterHandler('i'),
|
4767
|
+
"'j'": secondEscCharacterHandler('j'),
|
4768
|
+
"'k'": secondEscCharacterHandler('k'),
|
4769
|
+
fallthrough: ['vim-insert']
|
4770
|
+
};
|
4771
|
+
|
4541
4772
|
CodeMirror.keyMap['vim-replace'] = {
|
4542
4773
|
'Backspace': 'goCharLeft',
|
4543
4774
|
fallthrough: ['vim-insert']
|
@@ -4710,11 +4941,7 @@
|
|
4710
4941
|
// insert mode changes. Will conform to that behavior.
|
4711
4942
|
repeat = !vim.lastEditActionCommand ? 1 : repeat;
|
4712
4943
|
var changeObject = macroModeState.lastInsertModeChanges;
|
4713
|
-
// This isn't strictly necessary, but since lastInsertModeChanges is
|
4714
|
-
// supposed to be immutable during replay, this helps catch bugs.
|
4715
|
-
macroModeState.lastInsertModeChanges = {};
|
4716
4944
|
repeatInsertModeChanges(cm, changeObject.changes, repeat);
|
4717
|
-
macroModeState.lastInsertModeChanges = changeObject;
|
4718
4945
|
}
|
4719
4946
|
}
|
4720
4947
|
vim.inputState = vim.lastEditInputState;
|
@@ -4752,6 +4979,18 @@
|
|
4752
4979
|
}
|
4753
4980
|
return true;
|
4754
4981
|
}
|
4982
|
+
var curStart = cm.getCursor();
|
4983
|
+
var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock;
|
4984
|
+
if (inVisualBlock) {
|
4985
|
+
// Set up block selection again for repeating the changes.
|
4986
|
+
var vim = cm.state.vim;
|
4987
|
+
var block = vim.lastSelection.visualBlock;
|
4988
|
+
var curEnd = Pos(curStart.line + block.height-1, curStart.ch);
|
4989
|
+
cm.setCursor(curStart);
|
4990
|
+
selectBlock(cm, curEnd);
|
4991
|
+
repeat = cm.listSelections().length;
|
4992
|
+
cm.setCursor(curStart);
|
4993
|
+
}
|
4755
4994
|
for (var i = 0; i < repeat; i++) {
|
4756
4995
|
for (var j = 0; j < changes.length; j++) {
|
4757
4996
|
var change = changes[j];
|
@@ -4762,6 +5001,10 @@
|
|
4762
5001
|
cm.replaceRange(change, cur, cur);
|
4763
5002
|
}
|
4764
5003
|
}
|
5004
|
+
if (inVisualBlock) {
|
5005
|
+
curStart.line++;
|
5006
|
+
cm.setCursor(curStart);
|
5007
|
+
}
|
4765
5008
|
}
|
4766
5009
|
}
|
4767
5010
|
|