codemirror-rails 2.35 → 2.36
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +22 -16
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +2 -1
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +263 -154
- data/vendor/assets/javascripts/codemirror/modes/clike.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +3 -1
- data/vendor/assets/javascripts/codemirror/modes/mysql.js +23 -6
- data/vendor/assets/javascripts/codemirror/modes/php.js +13 -33
- data/vendor/assets/javascripts/codemirror/modes/python.js +5 -3
- data/vendor/assets/javascripts/codemirror/modes/xml.js +5 -3
- data/vendor/assets/javascripts/codemirror/modes/z80.js +113 -0
- data/vendor/assets/javascripts/codemirror/utils/continuecomment.js +36 -0
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +10 -7
- data/vendor/assets/javascripts/codemirror/utils/xml-hint.js +0 -6
- data/vendor/assets/stylesheets/codemirror/themes/ambiance-mobile.css +6 -0
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/twilight.css +26 -0
- metadata +16 -12
@@ -1,4 +1,4 @@
|
|
1
|
-
// CodeMirror version 2.
|
1
|
+
// CodeMirror version 2.36
|
2
2
|
//
|
3
3
|
// All functions that need access to the editor's state live inside
|
4
4
|
// the CodeMirror function. Below that, at the bottom of the file,
|
@@ -232,6 +232,7 @@ window.CodeMirror = (function() {
|
|
232
232
|
var off = eltOffset(lineSpace);
|
233
233
|
return coordsChar(coords.x - off.left, coords.y - off.top);
|
234
234
|
},
|
235
|
+
defaultTextHeight: function() { return textHeight(); },
|
235
236
|
markText: operation(markText),
|
236
237
|
setBookmark: setBookmark,
|
237
238
|
findMarksAt: findMarksAt,
|
@@ -346,6 +347,11 @@ window.CodeMirror = (function() {
|
|
346
347
|
return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
|
347
348
|
height: scrollbar.scrollHeight, width: scroller.scrollWidth};
|
348
349
|
},
|
350
|
+
scrollIntoView: function(pos) {
|
351
|
+
var coords = localCoords(pos ? clipPos(pos) : sel.inverted ? sel.from : sel.to);
|
352
|
+
scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
|
353
|
+
},
|
354
|
+
|
349
355
|
setSize: function(width, height) {
|
350
356
|
function interpret(val) {
|
351
357
|
val = String(val);
|
@@ -395,7 +401,7 @@ window.CodeMirror = (function() {
|
|
395
401
|
}
|
396
402
|
|
397
403
|
function onScrollBar(e) {
|
398
|
-
if (scrollbar.scrollTop
|
404
|
+
if (Math.abs(scrollbar.scrollTop - lastScrollTop) > 1) {
|
399
405
|
lastScrollTop = scroller.scrollTop = scrollbar.scrollTop;
|
400
406
|
updateDisplay([]);
|
401
407
|
}
|
@@ -404,7 +410,7 @@ window.CodeMirror = (function() {
|
|
404
410
|
function onScrollMain(e) {
|
405
411
|
if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + "px")
|
406
412
|
gutter.style.left = scroller.scrollLeft + "px";
|
407
|
-
if (scroller.scrollTop
|
413
|
+
if (Math.abs(scroller.scrollTop - lastScrollTop) > 1) {
|
408
414
|
lastScrollTop = scroller.scrollTop;
|
409
415
|
if (scrollbar.scrollTop != lastScrollTop)
|
410
416
|
scrollbar.scrollTop = lastScrollTop;
|
@@ -637,7 +643,7 @@ window.CodeMirror = (function() {
|
|
637
643
|
if (handled) {
|
638
644
|
e_preventDefault(e);
|
639
645
|
restartBlink();
|
640
|
-
if (
|
646
|
+
if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
|
641
647
|
}
|
642
648
|
return handled;
|
643
649
|
}
|
@@ -2174,7 +2180,7 @@ window.CodeMirror = (function() {
|
|
2174
2180
|
keyMap.emacsy = {
|
2175
2181
|
"Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
|
2176
2182
|
"Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
|
2177
|
-
"Ctrl-V": "
|
2183
|
+
"Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft",
|
2178
2184
|
"Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
|
2179
2185
|
};
|
2180
2186
|
|
@@ -2232,15 +2238,13 @@ window.CodeMirror = (function() {
|
|
2232
2238
|
if (textarea.form) {
|
2233
2239
|
// Deplorable hack to make the submit method do the right thing.
|
2234
2240
|
var rmSubmit = connect(textarea.form, "submit", save, true);
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
};
|
2243
|
-
}
|
2241
|
+
var realSubmit = textarea.form.submit;
|
2242
|
+
textarea.form.submit = function wrappedSubmit() {
|
2243
|
+
save();
|
2244
|
+
textarea.form.submit = realSubmit;
|
2245
|
+
textarea.form.submit();
|
2246
|
+
textarea.form.submit = wrappedSubmit;
|
2247
|
+
};
|
2244
2248
|
}
|
2245
2249
|
|
2246
2250
|
textarea.style.display = "none";
|
@@ -3102,8 +3106,10 @@ window.CodeMirror = (function() {
|
|
3102
3106
|
if (collection[i] == elt) return i;
|
3103
3107
|
return -1;
|
3104
3108
|
}
|
3109
|
+
var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
|
3105
3110
|
function isWordChar(ch) {
|
3106
|
-
return /\w/.test(ch) || ch
|
3111
|
+
return /\w/.test(ch) || ch > "\x80" &&
|
3112
|
+
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
|
3107
3113
|
}
|
3108
3114
|
|
3109
3115
|
// See if "".split is the broken IE version, if so, provide an
|
@@ -3159,7 +3165,7 @@ window.CodeMirror = (function() {
|
|
3159
3165
|
for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
|
3160
3166
|
})();
|
3161
3167
|
|
3162
|
-
CodeMirror.version = "2.
|
3168
|
+
CodeMirror.version = "2.36";
|
3163
3169
|
|
3164
3170
|
return CodeMirror;
|
3165
3171
|
})();
|
@@ -18,7 +18,8 @@
|
|
18
18
|
"Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
|
19
19
|
"Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
|
20
20
|
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
|
21
|
-
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
|
21
|
+
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete", "Alt-V": "goPageUp",
|
22
|
+
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
|
22
23
|
fallthrough: ["basic", "emacsy"]
|
23
24
|
};
|
24
25
|
|
@@ -17,7 +17,7 @@
|
|
17
17
|
// Entering insert mode:
|
18
18
|
// i, I, a, A, o, O
|
19
19
|
// s
|
20
|
-
// ce, cb
|
20
|
+
// ce, cb
|
21
21
|
// cc
|
22
22
|
// S, C TODO
|
23
23
|
// cf<char>, cF<char>, ct<char>, cT<char>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
// x, X
|
27
27
|
// J
|
28
28
|
// dd, D
|
29
|
-
// de, db
|
29
|
+
// de, db
|
30
30
|
// df<char>, dF<char>, dt<char>, dT<char>
|
31
31
|
//
|
32
32
|
// Yanking and pasting:
|
@@ -48,22 +48,28 @@
|
|
48
48
|
//
|
49
49
|
|
50
50
|
(function() {
|
51
|
-
var count = "";
|
52
51
|
var sdir = "f";
|
53
52
|
var buf = "";
|
54
|
-
var
|
55
|
-
var
|
56
|
-
|
53
|
+
var mark = {};
|
54
|
+
var repeatCount = 0;
|
55
|
+
function isLine(cm, line) { return line >= 0 && line < cm.lineCount(); }
|
57
56
|
function emptyBuffer() { buf = ""; }
|
58
57
|
function pushInBuffer(str) { buf += str; }
|
59
|
-
function
|
60
|
-
function
|
58
|
+
function pushRepeatCountDigit(digit) {return function(cm) {repeatCount = (repeatCount * 10) + digit}; }
|
59
|
+
function getCountOrOne() {
|
60
|
+
var i = repeatCount;
|
61
|
+
return i || 1;
|
62
|
+
}
|
63
|
+
function clearCount() {
|
64
|
+
repeatCount = 0;
|
65
|
+
}
|
61
66
|
function iterTimes(func) {
|
62
|
-
for (var i = 0, c =
|
67
|
+
for (var i = 0, c = getCountOrOne(); i < c; ++i) func(i, i == c - 1);
|
68
|
+
clearCount();
|
63
69
|
}
|
64
70
|
function countTimes(func) {
|
65
71
|
if (typeof func == "string") func = CodeMirror.commands[func];
|
66
|
-
return function(cm) { iterTimes(function () { func(cm); }); };
|
72
|
+
return function(cm) { iterTimes(function (i, last) { func(cm, i, last); }); };
|
67
73
|
}
|
68
74
|
|
69
75
|
function iterObj(o, f) {
|
@@ -93,50 +99,110 @@
|
|
93
99
|
}
|
94
100
|
|
95
101
|
var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
// Finds a word on the given line, and continue searching the next line if it can't find one.
|
103
|
+
function findWord(cm, lineNum, pos, dir, regexps) {
|
104
|
+
var line = cm.getLine(lineNum);
|
105
|
+
while (true) {
|
106
|
+
var stop = (dir > 0) ? line.length : -1;
|
107
|
+
var wordStart = stop, wordEnd = stop;
|
108
|
+
// Find bounds of next word.
|
109
|
+
for (; pos != stop; pos += dir) {
|
110
|
+
for (var i = 0; i < regexps.length; ++i) {
|
111
|
+
if (regexps[i].test(line.charAt(pos))) {
|
112
|
+
wordStart = pos;
|
113
|
+
// Advance to end of word.
|
114
|
+
for (; pos != stop && regexps[i].test(line.charAt(pos)); pos += dir) {}
|
115
|
+
wordEnd = (dir > 0) ? pos : pos + 1;
|
116
|
+
return {
|
117
|
+
from: Math.min(wordStart, wordEnd),
|
118
|
+
to: Math.max(wordStart, wordEnd),
|
119
|
+
line: lineNum};
|
107
120
|
}
|
108
|
-
end = pos;
|
109
|
-
break outer;
|
110
121
|
}
|
111
122
|
}
|
123
|
+
// Advance to next/prev line.
|
124
|
+
lineNum += dir;
|
125
|
+
if (!isLine(cm, lineNum)) return null;
|
126
|
+
line = cm.getLine(lineNum);
|
127
|
+
pos = (dir > 0) ? 0 : line.length;
|
112
128
|
}
|
113
|
-
return {from: Math.min(start, end), to: Math.max(start, end)};
|
114
129
|
}
|
115
|
-
|
130
|
+
/**
|
131
|
+
* @param {boolean} cm CodeMirror object.
|
132
|
+
* @param {regexp} regexps Regular expressions for word characters.
|
133
|
+
* @param {number} dir Direction, +/- 1.
|
134
|
+
* @param {number} times Number of times to advance word.
|
135
|
+
* @param {string} where Go to "start" or "end" of word, 'e' vs 'w'.
|
136
|
+
* @param {boolean} yank Whether we are finding words to yank. If true,
|
137
|
+
* do not go to the next line to look for the last word. This is to
|
138
|
+
* prevent deleting new line on 'dw' at the end of a line.
|
139
|
+
*/
|
140
|
+
function moveToWord(cm, regexps, dir, times, where, yank) {
|
116
141
|
var cur = cm.getCursor();
|
117
|
-
|
142
|
+
if (yank) {
|
143
|
+
where = 'start';
|
144
|
+
}
|
118
145
|
for (var i = 0; i < times; i++) {
|
119
|
-
var
|
146
|
+
var startCh = cur.ch, startLine = cur.line, word;
|
120
147
|
while (true) {
|
121
|
-
//
|
122
|
-
|
123
|
-
|
124
|
-
cur.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
148
|
+
// Search and advance.
|
149
|
+
word = findWord(cm, cur.line, cur.ch, dir, regexps);
|
150
|
+
if (word) {
|
151
|
+
if (yank && times == 1 && dir == 1 && cur.line != word.line) {
|
152
|
+
// Stop at end of line of last word. Don't want to delete line return
|
153
|
+
// for dw if the last deleted word is at the end of a line.
|
154
|
+
cur.ch = cm.getLine(cur.line).length;
|
155
|
+
break;
|
156
|
+
} else {
|
157
|
+
// Move to the word we just found. If by moving to the word we end up
|
158
|
+
// in the same spot, then move an extra character and search again.
|
159
|
+
cur.line = word.line;
|
160
|
+
if (dir > 0 && where == 'end') {
|
161
|
+
// 'e'
|
162
|
+
if (startCh != word.to - 1 || startLine != word.line) {
|
163
|
+
cur.ch = word.to - 1;
|
164
|
+
break;
|
165
|
+
} else {
|
166
|
+
cur.ch = word.to;
|
167
|
+
}
|
168
|
+
} else if (dir > 0 && where == 'start') {
|
169
|
+
// 'w'
|
170
|
+
if (startCh != word.from || startLine != word.line) {
|
171
|
+
cur.ch = word.from;
|
172
|
+
break;
|
173
|
+
} else {
|
174
|
+
cur.ch = word.to;
|
175
|
+
}
|
176
|
+
} else if (dir < 0 && where == 'end') {
|
177
|
+
// 'ge'
|
178
|
+
if (startCh != word.to || startLine != word.line) {
|
179
|
+
cur.ch = word.to;
|
180
|
+
break;
|
181
|
+
} else {
|
182
|
+
cur.ch = word.from - 1;
|
183
|
+
}
|
184
|
+
} else if (dir < 0 && where == 'start') {
|
185
|
+
// 'b'
|
186
|
+
if (startCh != word.from || startLine != word.line) {
|
187
|
+
cur.ch = word.from;
|
188
|
+
break;
|
189
|
+
} else {
|
190
|
+
cur.ch = word.from - 1;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
}
|
194
|
+
} else {
|
195
|
+
// No more words to be found. Move to end of document.
|
196
|
+
for (; isLine(cm, cur.line + dir); cur.line += dir) {}
|
197
|
+
cur.ch = (dir > 0) ? cm.getLine(cur.line).length : 0;
|
198
|
+
break;
|
130
199
|
}
|
131
|
-
if (!line) break;
|
132
|
-
|
133
|
-
// On to the actual searching
|
134
|
-
word = findWord(line, cur.ch, dir, regexps);
|
135
|
-
cur.ch = word[where == "end" ? "to" : "from"];
|
136
|
-
if (startCh == cur.ch && word.from != word.to) cur.ch = word[dir < 0 ? "from" : "to"];
|
137
|
-
else break;
|
138
200
|
}
|
139
201
|
}
|
202
|
+
if (where == 'end' && yank) {
|
203
|
+
// Include the last character of the word for actions.
|
204
|
+
cur.ch++;
|
205
|
+
}
|
140
206
|
return cur;
|
141
207
|
}
|
142
208
|
function joinLineNext(cm) {
|
@@ -157,7 +223,7 @@
|
|
157
223
|
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
|
158
224
|
cm.setCursor(start);
|
159
225
|
for (var c = start; c <= end; c++) {
|
160
|
-
pushInBuffer("\n"+cm.getLine(start));
|
226
|
+
pushInBuffer("\n" + cm.getLine(start));
|
161
227
|
cm.removeLine(start);
|
162
228
|
}
|
163
229
|
}
|
@@ -169,7 +235,7 @@
|
|
169
235
|
}
|
170
236
|
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
|
171
237
|
for (var c = start; c <= end; c++) {
|
172
|
-
pushInBuffer("\n"+cm.getLine(c));
|
238
|
+
pushInBuffer("\n" + cm.getLine(c));
|
173
239
|
}
|
174
240
|
cm.setCursor(start);
|
175
241
|
}
|
@@ -220,7 +286,7 @@
|
|
220
286
|
|
221
287
|
function enterInsertMode(cm) {
|
222
288
|
// enter insert mode: switch mode and cursor
|
223
|
-
|
289
|
+
clearCount();
|
224
290
|
cm.setOption("keyMap", "vim-insert");
|
225
291
|
}
|
226
292
|
|
@@ -238,7 +304,8 @@
|
|
238
304
|
var map = CodeMirror.keyMap.vim = {
|
239
305
|
// Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
|
240
306
|
"'|'": function(cm) {
|
241
|
-
cm.setCursor(cm.getCursor().line,
|
307
|
+
cm.setCursor(cm.getCursor().line, getCountOrOne() - 1, true);
|
308
|
+
clearCount();
|
242
309
|
},
|
243
310
|
"A": function(cm) {
|
244
311
|
cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);
|
@@ -260,16 +327,26 @@
|
|
260
327
|
},
|
261
328
|
"G": function(cm) { cm.setOption("keyMap", "vim-prefix-g");},
|
262
329
|
"Shift-D": function(cm) {
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
*/
|
330
|
+
var cursor = cm.getCursor();
|
331
|
+
var lineN = cursor.line;
|
332
|
+
var line = cm.getLine(lineN);
|
333
|
+
cm.setLine(lineN, line.slice(0, cursor.ch));
|
334
|
+
|
269
335
|
emptyBuffer();
|
270
|
-
|
271
|
-
|
272
|
-
|
336
|
+
pushInBuffer(line.slice(cursor.ch));
|
337
|
+
|
338
|
+
if (repeatCount > 1) {
|
339
|
+
// we've already done it once
|
340
|
+
--repeatCount;
|
341
|
+
// the lines dissapear (ie, cursor stays on the same lineN),
|
342
|
+
// so only incremenet once
|
343
|
+
++lineN;
|
344
|
+
|
345
|
+
iterTimes(function() {
|
346
|
+
pushInBuffer(cm.getLine(lineN));
|
347
|
+
cm.removeLine(lineN);
|
348
|
+
});
|
349
|
+
}
|
273
350
|
},
|
274
351
|
|
275
352
|
"S": function (cm) {
|
@@ -278,13 +355,11 @@
|
|
278
355
|
})(cm);
|
279
356
|
enterInsertMode(cm);
|
280
357
|
},
|
281
|
-
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark =
|
282
|
-
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer();
|
358
|
+
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = {};},
|
359
|
+
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer();},
|
283
360
|
"Shift-Y": function(cm) {
|
284
361
|
emptyBuffer();
|
285
|
-
|
286
|
-
cm.setCursor(cm.getCursor(true).line);
|
287
|
-
yankTillMark(cm,"Shift-D"); mark = [];
|
362
|
+
iterTimes(function(i) { pushInBuffer("\n" + cm.getLine(cm.getCursor().line + i)); });
|
288
363
|
},
|
289
364
|
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f";},
|
290
365
|
"'?'": function(cm) {
|
@@ -300,8 +375,8 @@
|
|
300
375
|
if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
|
301
376
|
},
|
302
377
|
"Shift-G": function(cm) {
|
303
|
-
|
304
|
-
|
378
|
+
(repeatCount == 0) ? cm.setCursor(cm.lineCount()) : cm.setCursor(repeatCount - 1);
|
379
|
+
clearCount();
|
305
380
|
CodeMirror.commands.goLineStart(cm);
|
306
381
|
},
|
307
382
|
"':'": function(cm) {
|
@@ -325,21 +400,9 @@
|
|
325
400
|
};
|
326
401
|
});
|
327
402
|
|
328
|
-
function addCountBindings(keyMap) {
|
329
|
-
// Add bindings for number keys
|
330
|
-
keyMap["0"] = function(cm) {
|
331
|
-
count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);
|
332
|
-
};
|
333
|
-
for (var i = 1; i < 10; ++i) keyMap[i] = pushCountDigit(i);
|
334
|
-
}
|
335
|
-
addCountBindings(CodeMirror.keyMap.vim);
|
336
|
-
|
337
403
|
// main num keymap
|
338
404
|
// Add bindings that are influenced by number keys
|
339
405
|
iterObj({
|
340
|
-
"Left": "goColumnLeft", "Right": "goColumnRight",
|
341
|
-
"Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
|
342
|
-
"Space": "goCharRight",
|
343
406
|
"X": function(cm) {CodeMirror.commands.delCharRight(cm);},
|
344
407
|
"P": function(cm) {
|
345
408
|
var cur = cm.getCursor().line;
|
@@ -401,15 +464,18 @@
|
|
401
464
|
});
|
402
465
|
|
403
466
|
CodeMirror.keyMap["vim-prefix-g"] = {
|
404
|
-
"E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, word, -1, 1, "
|
405
|
-
"Shift-E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, bigWord, -1, 1, "
|
406
|
-
"G": function (cm) {
|
467
|
+
"E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, word, -1, 1, "end"));}),
|
468
|
+
"Shift-E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, bigWord, -1, 1, "end"));}),
|
469
|
+
"G": function (cm) {
|
470
|
+
cm.setCursor({line: repeatCount - 1, ch: cm.getCursor().ch});
|
471
|
+
clearCount();
|
472
|
+
},
|
407
473
|
auto: "vim", nofallthrough: true, style: "fat-cursor"
|
408
474
|
};
|
409
475
|
|
410
476
|
CodeMirror.keyMap["vim-prefix-d"] = {
|
411
477
|
"D": countTimes(function(cm) {
|
412
|
-
pushInBuffer("\n"+cm.getLine(cm.getCursor().line));
|
478
|
+
pushInBuffer("\n" + cm.getLine(cm.getCursor().line));
|
413
479
|
cm.removeLine(cm.getCursor().line);
|
414
480
|
cm.setOption("keyMap", "vim");
|
415
481
|
}),
|
@@ -428,8 +494,6 @@
|
|
428
494
|
},
|
429
495
|
nofallthrough: true, style: "fat-cursor"
|
430
496
|
};
|
431
|
-
// FIXME - does not work for bindings like "d3e"
|
432
|
-
addCountBindings(CodeMirror.keyMap["vim-prefix-d"]);
|
433
497
|
|
434
498
|
CodeMirror.keyMap["vim-prefix-c"] = {
|
435
499
|
"B": function (cm) {
|
@@ -471,10 +535,10 @@
|
|
471
535
|
mark[m] = cm.getCursor().line;
|
472
536
|
};
|
473
537
|
CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
|
474
|
-
delTillMark(cm,m);
|
538
|
+
delTillMark(cm, m);
|
475
539
|
};
|
476
540
|
CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
|
477
|
-
yankTillMark(cm,m);
|
541
|
+
yankTillMark(cm, m);
|
478
542
|
};
|
479
543
|
CodeMirror.keyMap["vim-prefix-r"][m] = function (cm) {
|
480
544
|
var cur = cm.getCursor();
|
@@ -508,8 +572,8 @@
|
|
508
572
|
setupPrefixBindingForKey("Space");
|
509
573
|
|
510
574
|
CodeMirror.keyMap["vim-prefix-y"] = {
|
511
|
-
"Y": countTimes(function(cm) {
|
512
|
-
pushInBuffer("\n"+cm.getLine(cm.getCursor().line+
|
575
|
+
"Y": countTimes(function(cm, i, last) {
|
576
|
+
pushInBuffer("\n" + cm.getLine(cm.getCursor().line + i));
|
513
577
|
cm.setOption("keyMap", "vim");
|
514
578
|
}),
|
515
579
|
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
|
@@ -588,67 +652,107 @@
|
|
588
652
|
return {start: start, end: end};
|
589
653
|
}
|
590
654
|
|
591
|
-
//
|
592
|
-
//
|
593
|
-
|
655
|
+
// takes in a symbol and a cursor and tries to simulate text objects that have
|
656
|
+
// identical opening and closing symbols
|
657
|
+
// TODO support across multiple lines
|
658
|
+
function findBeginningAndEnd(cm, symb, inclusive) {
|
659
|
+
var cur = cm.getCursor();
|
660
|
+
var line = cm.getLine(cur.line);
|
661
|
+
var chars = line.split('');
|
662
|
+
var start = undefined;
|
663
|
+
var end = undefined;
|
664
|
+
var firstIndex = chars.indexOf(symb);
|
665
|
+
|
666
|
+
// the decision tree is to always look backwards for the beginning first,
|
667
|
+
// but if the cursor is in front of the first instance of the symb,
|
668
|
+
// then move the cursor forward
|
669
|
+
if (cur.ch < firstIndex) {
|
670
|
+
cur.ch = firstIndex;
|
671
|
+
cm.setCursor(cur.line, firstIndex+1);
|
672
|
+
}
|
673
|
+
// otherwise if the cursor is currently on the closing symbol
|
674
|
+
else if (firstIndex < cur.ch && chars[cur.ch] == symb) {
|
675
|
+
end = cur.ch; // assign end to the current cursor
|
676
|
+
--cur.ch; // make sure to look backwards
|
677
|
+
}
|
594
678
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
},
|
679
|
+
// if we're currently on the symbol, we've got a start
|
680
|
+
if (chars[cur.ch] == symb && end == null)
|
681
|
+
start = cur.ch + 1; // assign start to ahead of the cursor
|
682
|
+
else {
|
683
|
+
// go backwards to find the start
|
684
|
+
for (var i = cur.ch; i > -1 && start == null; i--)
|
685
|
+
if (chars[i] == symb) start = i + 1;
|
686
|
+
}
|
604
687
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
688
|
+
// look forwards for the end symbol
|
689
|
+
if (start != null && end == null) {
|
690
|
+
for (var i = start, len = chars.length; i < len && end == null; i++) {
|
691
|
+
if (chars[i] == symb) end = i;
|
692
|
+
}
|
693
|
+
}
|
609
694
|
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
695
|
+
// nothing found
|
696
|
+
// FIXME still enters insert mode
|
697
|
+
if (start == null || end == null) return {
|
698
|
+
start: cur, end: cur
|
699
|
+
};
|
614
700
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
}
|
619
|
-
'W': function(cm, times) { return moveToWord(cm, word, 1, times); },
|
620
|
-
'Shift-W': function(cm, times) { return moveToWord(cm, bigWord, 1, times); },
|
621
|
-
"'^'": function(cm, times) {
|
622
|
-
var cur = cm.getCursor();
|
623
|
-
var line = cm.getLine(cur.line).split('');
|
701
|
+
// include the symbols
|
702
|
+
if (inclusive) {
|
703
|
+
--start; ++end;
|
704
|
+
}
|
624
705
|
|
625
|
-
|
626
|
-
|
706
|
+
return {
|
707
|
+
start: {line: cur.line, ch: start},
|
708
|
+
end: {line: cur.line, ch: end}
|
709
|
+
};
|
710
|
+
}
|
627
711
|
|
628
|
-
|
629
|
-
|
712
|
+
function offsetCursor(cm, line, ch) {
|
713
|
+
var cur = cm.getCursor(); return {line: cur.line + line, ch: cur.ch + ch};
|
714
|
+
}
|
715
|
+
|
716
|
+
// These are the motion commands we use for navigation and selection with
|
717
|
+
// certain other commands. All should return a cursor object.
|
718
|
+
var motions = {
|
719
|
+
"J": function(cm, times) { return offsetCursor(cm, times, 0); },
|
720
|
+
"Down": function(cm, times) { return offsetCursor(cm, times, 0); },
|
721
|
+
"K": function(cm, times) { return offsetCursor(cm, -times, 0); },
|
722
|
+
"Up": function(cm, times) { return offsetCursor(cm, -times, 0); },
|
723
|
+
"L": function(cm, times) { return offsetCursor(cm, 0, times); },
|
724
|
+
"Right": function(cm, times) { return offsetCursor(cm, 0, times); },
|
725
|
+
"Space": function(cm, times) { return offsetCursor(cm, 0, times); },
|
726
|
+
"H": function(cm, times) { return offsetCursor(cm, 0, -times); },
|
727
|
+
"Left": function(cm, times) { return offsetCursor(cm, 0, -times); },
|
728
|
+
"Backspace": function(cm, times) { return offsetCursor(cm, 0, -times); },
|
729
|
+
"B": function(cm, times, yank) { return moveToWord(cm, word, -1, times, 'start', yank); },
|
730
|
+
"Shift-B": function(cm, times, yank) { return moveToWord(cm, bigWord, -1, times, 'start', yank); },
|
731
|
+
"E": function(cm, times, yank) { return moveToWord(cm, word, 1, times, 'end', yank); },
|
732
|
+
"Shift-E": function(cm, times, yank) { return moveToWord(cm, bigWord, 1, times, 'end', yank); },
|
733
|
+
"W": function(cm, times, yank) { return moveToWord(cm, word, 1, times, 'start', yank); },
|
734
|
+
"Shift-W": function(cm, times, yank) { return moveToWord(cm, bigWord, 1, times, 'start', yank); },
|
735
|
+
"'^'": function(cm, times) {
|
736
|
+
var cur = cm.getCursor(), line = cm.getLine(cur.line).split('');
|
737
|
+
for (var i = 0; i < line.length; i++) {
|
738
|
+
if (line[i].match(/[^\s]/)) return {line: cur.line, ch: index};
|
630
739
|
}
|
740
|
+
return cur;
|
631
741
|
},
|
632
742
|
"'$'": function(cm) {
|
633
|
-
var cur = cm.getCursor();
|
634
|
-
|
635
|
-
return {line: cur.line, ch: line.length};
|
743
|
+
var cur = cm.getCursor(), ch = cm.getLine(cur.line).length;
|
744
|
+
return {line: cur.line, ch: ch};
|
636
745
|
},
|
637
746
|
"'%'": function(cm) { return findMatchedSymbol(cm, cm.getCursor()); },
|
638
|
-
"Esc" : function(cm) {
|
639
|
-
cm.setOption('vim');
|
640
|
-
reptTimes = 0;
|
641
|
-
|
642
|
-
return cm.getCursor();
|
643
|
-
}
|
747
|
+
"Esc" : function(cm) { cm.setOption("keyMap", "vim"); repeatCount = 0; return cm.getCursor(); }
|
644
748
|
};
|
645
749
|
|
646
750
|
// Map our movement actions each operator and non-operational movement
|
647
|
-
|
751
|
+
iterObj(motions, function(key, motion) {
|
648
752
|
CodeMirror.keyMap['vim-prefix-d'][key] = function(cm) {
|
649
753
|
// Get our selected range
|
650
754
|
var start = cm.getCursor();
|
651
|
-
var end =
|
755
|
+
var end = motion(cm, repeatCount ? repeatCount : 1, true);
|
652
756
|
|
653
757
|
// Set swap var if range is of negative length
|
654
758
|
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
@@ -658,56 +762,59 @@
|
|
658
762
|
cm.replaceRange("", swap ? end : start, swap ? start : end);
|
659
763
|
|
660
764
|
// And clean up
|
661
|
-
|
765
|
+
repeatCount = 0;
|
662
766
|
cm.setOption("keyMap", "vim");
|
663
767
|
};
|
664
768
|
|
665
769
|
CodeMirror.keyMap['vim-prefix-c'][key] = function(cm) {
|
666
770
|
var start = cm.getCursor();
|
667
|
-
var end =
|
771
|
+
var end = motion(cm, repeatCount ? repeatCount : 1, true);
|
668
772
|
|
669
773
|
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
670
774
|
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
671
775
|
cm.replaceRange("", swap ? end : start, swap ? start : end);
|
672
776
|
|
673
|
-
|
777
|
+
repeatCount = 0;
|
674
778
|
cm.setOption('keyMap', 'vim-insert');
|
675
779
|
};
|
676
780
|
|
677
781
|
CodeMirror.keyMap['vim-prefix-y'][key] = function(cm) {
|
678
782
|
var start = cm.getCursor();
|
679
|
-
var end =
|
783
|
+
var end = motion(cm, repeatCount ? repeatCount : 1, true);
|
680
784
|
|
681
785
|
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
682
786
|
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
683
787
|
|
684
|
-
|
788
|
+
repeatCount = 0;
|
685
789
|
cm.setOption("keyMap", "vim");
|
686
790
|
};
|
687
791
|
|
688
792
|
CodeMirror.keyMap['vim'][key] = function(cm) {
|
689
|
-
var cur =
|
793
|
+
var cur = motion(cm, repeatCount ? repeatCount : 1);
|
690
794
|
cm.setCursor(cur.line, cur.ch);
|
691
795
|
|
692
|
-
|
796
|
+
repeatCount = 0;
|
693
797
|
};
|
694
798
|
});
|
695
799
|
|
696
|
-
|
697
|
-
|
698
|
-
CodeMirror.keyMap[
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
reptTimes = (reptTimes * 10) + key;
|
706
|
-
};
|
707
|
-
CodeMirror.keyMap['vim-prefix-c'][key] = function (cm) {
|
708
|
-
reptTimes = (reptTimes * 10) + key;
|
800
|
+
function addCountBindings(keyMapName) {
|
801
|
+
// Add bindings for number keys
|
802
|
+
keyMap = CodeMirror.keyMap[keyMapName];
|
803
|
+
keyMap["0"] = function(cm) {
|
804
|
+
if (repeatCount > 0) {
|
805
|
+
pushRepeatCountDigit(0)(cm);
|
806
|
+
} else {
|
807
|
+
CodeMirror.commands.goLineStart(cm);
|
808
|
+
}
|
709
809
|
};
|
710
|
-
|
810
|
+
for (var i = 1; i < 10; ++i) {
|
811
|
+
keyMap[i] = pushRepeatCountDigit(i);
|
812
|
+
}
|
813
|
+
}
|
814
|
+
addCountBindings('vim');
|
815
|
+
addCountBindings('vim-prefix-d');
|
816
|
+
addCountBindings('vim-prefix-y');
|
817
|
+
addCountBindings('vim-prefix-c');
|
711
818
|
|
712
819
|
// Create our keymaps for each operator and make xa and xi where x is an operator
|
713
820
|
// change to the corrosponding keymap
|
@@ -721,12 +828,12 @@
|
|
721
828
|
};
|
722
829
|
|
723
830
|
CodeMirror.keyMap['vim-prefix-'+key]['A'] = function(cm) {
|
724
|
-
|
831
|
+
repeatCount = 0;
|
725
832
|
cm.setOption('keyMap', 'vim-prefix-' + key + 'a');
|
726
833
|
};
|
727
834
|
|
728
835
|
CodeMirror.keyMap['vim-prefix-'+key]['I'] = function(cm) {
|
729
|
-
|
836
|
+
repeatCount = 0;
|
730
837
|
cm.setOption('keyMap', 'vim-prefix-' + key + 'i');
|
731
838
|
};
|
732
839
|
});
|
@@ -739,7 +846,7 @@
|
|
739
846
|
|
740
847
|
// Create our text object functions. They work similar to motions but they
|
741
848
|
// return a start cursor as well
|
742
|
-
var textObjectList = ['W', 'Shift-[', 'Shift-9', '['];
|
849
|
+
var textObjectList = ['W', 'Shift-[', 'Shift-9', '[', "'", "Shift-'"];
|
743
850
|
var textObjects = {
|
744
851
|
'W': function(cm, inclusive) {
|
745
852
|
var cur = cm.getCursor();
|
@@ -754,7 +861,9 @@
|
|
754
861
|
},
|
755
862
|
'Shift-[': function(cm, inclusive) { return selectCompanionObject(cm, '}', inclusive); },
|
756
863
|
'Shift-9': function(cm, inclusive) { return selectCompanionObject(cm, ')', inclusive); },
|
757
|
-
'[': function(cm, inclusive) { return selectCompanionObject(cm, ']', inclusive); }
|
864
|
+
'[': function(cm, inclusive) { return selectCompanionObject(cm, ']', inclusive); },
|
865
|
+
"'": function(cm, inclusive) { return findBeginningAndEnd(cm, "'", inclusive); },
|
866
|
+
"Shift-'": function(cm, inclusive) { return findBeginningAndEnd(cm, '"', inclusive); }
|
758
867
|
};
|
759
868
|
|
760
869
|
// One function to handle all operation upon text objects. Kinda funky but it works
|