codemirror-rails 2.24 → 2.32
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.
- data/.gitignore +1 -0
- data/Rakefile +19 -0
- data/codemirror-rails.gemspec +6 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +56 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/codemirror_rails_integration_test.rb +13 -0
- data/test/test_helper.rb +13 -0
- data/vendor/assets/javascripts/codemirror.js +381 -197
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +1 -1
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +649 -94
- data/vendor/assets/javascripts/codemirror/modes/clike.js +53 -7
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +12 -7
- data/vendor/assets/javascripts/codemirror/modes/diff.js +24 -5
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/erlang.js +463 -0
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +38 -2
- data/vendor/assets/javascripts/codemirror/modes/go.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/haxe.js +432 -0
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/less.js +93 -93
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -6
- data/vendor/assets/javascripts/codemirror/modes/mysql.js +6 -8
- data/vendor/assets/javascripts/codemirror/modes/ocaml.js +114 -0
- data/vendor/assets/javascripts/codemirror/modes/pascal.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/pig.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/plsql.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/python.js +13 -16
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -8
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +74 -46
- data/vendor/assets/javascripts/codemirror/modes/shell.js +22 -7
- data/vendor/assets/javascripts/codemirror/modes/stex.js +7 -5
- data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/vb.js +260 -0
- data/vendor/assets/javascripts/codemirror/modes/verilog.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +3 -3
- data/vendor/assets/javascripts/codemirror/utils/closetag.js +24 -34
- data/vendor/assets/javascripts/codemirror/utils/dialog.js +5 -1
- data/vendor/assets/javascripts/codemirror/utils/foldcode.js +10 -5
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +8 -3
- data/vendor/assets/javascripts/codemirror/utils/loadmode.js +2 -1
- data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +81 -0
- data/vendor/assets/javascripts/codemirror/utils/overlay.js +2 -1
- data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +123 -0
- data/vendor/assets/javascripts/codemirror/utils/search.js +16 -12
- data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +4 -0
- data/vendor/assets/javascripts/codemirror/utils/xml-hint.js +137 -0
- data/vendor/assets/stylesheets/codemirror.css +59 -4
- data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +14 -21
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +1 -2
- data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +21 -0
- data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +2 -3
- data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +27 -0
- data/vendor/assets/stylesheets/codemirror/utils/dialog.css +4 -0
- metadata +98 -5
- data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
|
@@ -18,7 +18,7 @@
|
|
|
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",
|
|
21
|
+
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
|
|
22
22
|
fallthrough: ["basic", "emacsy"]
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -1,21 +1,96 @@
|
|
|
1
|
+
// Supported keybindings:
|
|
2
|
+
//
|
|
3
|
+
// Cursor movement:
|
|
4
|
+
// h, j, k, l
|
|
5
|
+
// e, E, w, W, b, B
|
|
6
|
+
// Ctrl-f, Ctrl-b
|
|
7
|
+
// Ctrl-n, Ctrl-p
|
|
8
|
+
// $, ^, 0
|
|
9
|
+
// G
|
|
10
|
+
// ge, gE
|
|
11
|
+
// gg
|
|
12
|
+
// f<char>, F<char>, t<char>, T<char>
|
|
13
|
+
// Ctrl-o, Ctrl-i TODO (FIXME - Ctrl-O wont work in Chrome)
|
|
14
|
+
// /, ?, n, N TODO (does not work)
|
|
15
|
+
// #, * TODO
|
|
16
|
+
//
|
|
17
|
+
// Entering insert mode:
|
|
18
|
+
// i, I, a, A, o, O
|
|
19
|
+
// s
|
|
20
|
+
// ce, cb (without support for number of actions like c3e - TODO)
|
|
21
|
+
// cc
|
|
22
|
+
// S, C TODO
|
|
23
|
+
// cf<char>, cF<char>, ct<char>, cT<char>
|
|
24
|
+
//
|
|
25
|
+
// Deleting text:
|
|
26
|
+
// x, X
|
|
27
|
+
// J
|
|
28
|
+
// dd, D
|
|
29
|
+
// de, db (without support for number of actions like d3e - TODO)
|
|
30
|
+
// df<char>, dF<char>, dt<char>, dT<char>
|
|
31
|
+
//
|
|
32
|
+
// Yanking and pasting:
|
|
33
|
+
// yy, Y
|
|
34
|
+
// p, P
|
|
35
|
+
// p'<char> TODO - test
|
|
36
|
+
// y'<char> TODO - test
|
|
37
|
+
// m<char> TODO - test
|
|
38
|
+
//
|
|
39
|
+
// Changing text in place:
|
|
40
|
+
// ~
|
|
41
|
+
// r<char>
|
|
42
|
+
//
|
|
43
|
+
// Visual mode:
|
|
44
|
+
// v, V TODO
|
|
45
|
+
//
|
|
46
|
+
// Misc:
|
|
47
|
+
// . TODO
|
|
48
|
+
//
|
|
49
|
+
|
|
1
50
|
(function() {
|
|
2
51
|
var count = "";
|
|
3
52
|
var sdir = "f";
|
|
4
53
|
var buf = "";
|
|
5
54
|
var yank = 0;
|
|
6
55
|
var mark = [];
|
|
56
|
+
var reptTimes = 0;
|
|
7
57
|
function emptyBuffer() { buf = ""; }
|
|
8
|
-
function pushInBuffer(str) { buf += str; }
|
|
9
|
-
function pushCountDigit(digit) { return function(cm) {count += digit;} }
|
|
10
|
-
function popCount() { var i = parseInt(count); count = ""; return i || 1; }
|
|
58
|
+
function pushInBuffer(str) { buf += str; }
|
|
59
|
+
function pushCountDigit(digit) { return function(cm) {count += digit;}; }
|
|
60
|
+
function popCount() { var i = parseInt(count, 10); count = ""; return i || 1; }
|
|
61
|
+
function iterTimes(func) {
|
|
62
|
+
for (var i = 0, c = popCount(); i < c; ++i) func(i, i == c - 1);
|
|
63
|
+
}
|
|
11
64
|
function countTimes(func) {
|
|
12
65
|
if (typeof func == "string") func = CodeMirror.commands[func];
|
|
13
|
-
return function(cm) {
|
|
66
|
+
return function(cm) { iterTimes(function () { func(cm); }); };
|
|
14
67
|
}
|
|
15
68
|
|
|
16
69
|
function iterObj(o, f) {
|
|
17
70
|
for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
|
|
18
71
|
}
|
|
72
|
+
function iterList(l, f) {
|
|
73
|
+
for (var i in l) f(l[i]);
|
|
74
|
+
}
|
|
75
|
+
function toLetter(ch) {
|
|
76
|
+
// T -> t, Shift-T -> T, '*' -> *, "Space" -> " "
|
|
77
|
+
if (ch.slice(0, 6) == "Shift-") {
|
|
78
|
+
return ch.slice(0, 1);
|
|
79
|
+
} else {
|
|
80
|
+
if (ch == "Space") return " ";
|
|
81
|
+
if (ch.length == 3 && ch[0] == "'" && ch[2] == "'") return ch[1];
|
|
82
|
+
return ch.toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
var SPECIAL_SYMBOLS = "~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;\"\'1234567890";
|
|
86
|
+
function toCombo(ch) {
|
|
87
|
+
// t -> T, T -> Shift-T, * -> '*', " " -> "Space"
|
|
88
|
+
if (ch == " ") return "Space";
|
|
89
|
+
var specialIdx = SPECIAL_SYMBOLS.indexOf(ch);
|
|
90
|
+
if (specialIdx != -1) return "'" + ch + "'";
|
|
91
|
+
if (ch.toLowerCase() == ch) return ch.toUpperCase();
|
|
92
|
+
return "Shift-" + ch.toUpperCase();
|
|
93
|
+
}
|
|
19
94
|
|
|
20
95
|
var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
|
|
21
96
|
function findWord(line, pos, dir, regexps) {
|
|
@@ -37,42 +112,62 @@
|
|
|
37
112
|
}
|
|
38
113
|
return {from: Math.min(start, end), to: Math.max(start, end)};
|
|
39
114
|
}
|
|
40
|
-
function moveToWord(cm, regexps, dir, where) {
|
|
41
|
-
var cur = cm.getCursor()
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
115
|
+
function moveToWord(cm, regexps, dir, times, where) {
|
|
116
|
+
var cur = cm.getCursor();
|
|
117
|
+
|
|
118
|
+
for (var i = 0; i < times; i++) {
|
|
119
|
+
var line = cm.getLine(cur.line), startCh = cur.ch, word;
|
|
120
|
+
while (true) {
|
|
121
|
+
// If we're at start/end of line, start on prev/next respectivly
|
|
122
|
+
if (cur.ch == line.length && dir > 0) {
|
|
123
|
+
cur.line++;
|
|
124
|
+
cur.ch = 0;
|
|
125
|
+
line = cm.getLine(cur.line);
|
|
126
|
+
} else if (cur.ch == 0 && dir < 0) {
|
|
127
|
+
cur.line--;
|
|
128
|
+
cur.ch = line.length;
|
|
129
|
+
line = cm.getLine(cur.line);
|
|
130
|
+
}
|
|
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
|
+
}
|
|
47
139
|
}
|
|
48
|
-
|
|
140
|
+
return cur;
|
|
49
141
|
}
|
|
50
142
|
function joinLineNext(cm) {
|
|
51
143
|
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
|
|
52
|
-
CodeMirror.commands.goLineEnd(cm);
|
|
144
|
+
CodeMirror.commands.goLineEnd(cm);
|
|
53
145
|
if (cur.line != cm.lineCount()) {
|
|
54
146
|
CodeMirror.commands.goLineEnd(cm);
|
|
55
147
|
cm.replaceSelection(" ", "end");
|
|
56
148
|
CodeMirror.commands.delCharRight(cm);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
function editCursor(mode) {
|
|
60
|
-
if (mode == "vim-insert") {
|
|
61
|
-
// put in your cursor css changing code
|
|
62
|
-
} else if (mode == "vim") {
|
|
63
|
-
// put in your cursor css changing code
|
|
64
149
|
}
|
|
65
150
|
}
|
|
66
|
-
function delTillMark(cm, cHar) {
|
|
67
|
-
var i = mark[cHar]
|
|
151
|
+
function delTillMark(cm, cHar) {
|
|
152
|
+
var i = mark[cHar];
|
|
153
|
+
if (i === undefined) {
|
|
154
|
+
// console.log("Mark not set"); // TODO - show in status bar
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
|
|
68
158
|
cm.setCursor(start);
|
|
69
159
|
for (var c = start; c <= end; c++) {
|
|
70
|
-
pushInBuffer("\n"+cm.getLine(start));
|
|
160
|
+
pushInBuffer("\n"+cm.getLine(start));
|
|
71
161
|
cm.removeLine(start);
|
|
72
162
|
}
|
|
73
163
|
}
|
|
74
|
-
function yankTillMark(cm, cHar) {
|
|
75
|
-
var i = mark[cHar]
|
|
164
|
+
function yankTillMark(cm, cHar) {
|
|
165
|
+
var i = mark[cHar];
|
|
166
|
+
if (i === undefined) {
|
|
167
|
+
// console.log("Mark not set"); // TODO - show in status bar
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
|
|
76
171
|
for (var c = start; c <= end; c++) {
|
|
77
172
|
pushInBuffer("\n"+cm.getLine(c));
|
|
78
173
|
}
|
|
@@ -84,25 +179,104 @@
|
|
|
84
179
|
cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);
|
|
85
180
|
}
|
|
86
181
|
|
|
182
|
+
function charIdxInLine(cm, cHar, motion_options) {
|
|
183
|
+
// Search for cHar in line.
|
|
184
|
+
// motion_options: {forward, inclusive}
|
|
185
|
+
// If inclusive = true, include it too.
|
|
186
|
+
// If forward = true, search forward, else search backwards.
|
|
187
|
+
// If char is not found on this line, do nothing
|
|
188
|
+
var cur = cm.getCursor(), line = cm.getLine(cur.line), idx;
|
|
189
|
+
var ch = toLetter(cHar), mo = motion_options;
|
|
190
|
+
if (mo.forward) {
|
|
191
|
+
idx = line.indexOf(ch, cur.ch + 1);
|
|
192
|
+
if (idx != -1 && mo.inclusive) idx += 1;
|
|
193
|
+
} else {
|
|
194
|
+
idx = line.lastIndexOf(ch, cur.ch);
|
|
195
|
+
if (idx != -1 && !mo.inclusive) idx += 1;
|
|
196
|
+
}
|
|
197
|
+
return idx;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function moveTillChar(cm, cHar, motion_options) {
|
|
201
|
+
// Move to cHar in line, as found by charIdxInLine.
|
|
202
|
+
var idx = charIdxInLine(cm, cHar, motion_options), cur = cm.getCursor();
|
|
203
|
+
if (idx != -1) cm.setCursor({line: cur.line, ch: idx});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function delTillChar(cm, cHar, motion_options) {
|
|
207
|
+
// delete text in this line, untill cHar is met,
|
|
208
|
+
// as found by charIdxInLine.
|
|
209
|
+
// If char is not found on this line, do nothing
|
|
210
|
+
var idx = charIdxInLine(cm, cHar, motion_options);
|
|
211
|
+
var cur = cm.getCursor();
|
|
212
|
+
if (idx !== -1) {
|
|
213
|
+
if (motion_options.forward) {
|
|
214
|
+
cm.replaceRange("", {line: cur.line, ch: cur.ch}, {line: cur.line, ch: idx});
|
|
215
|
+
} else {
|
|
216
|
+
cm.replaceRange("", {line: cur.line, ch: idx}, {line: cur.line, ch: cur.ch});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function enterInsertMode(cm) {
|
|
222
|
+
// enter insert mode: switch mode and cursor
|
|
223
|
+
popCount();
|
|
224
|
+
cm.setOption("keyMap", "vim-insert");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function dialog(cm, text, shortText, f) {
|
|
228
|
+
if (cm.openDialog) cm.openDialog(text, f);
|
|
229
|
+
else f(prompt(shortText, ""));
|
|
230
|
+
}
|
|
231
|
+
function showAlert(cm, text) {
|
|
232
|
+
if (cm.openDialog) cm.openDialog(CodeMirror.htmlEscape(text) + " <button type=button>OK</button>");
|
|
233
|
+
else alert(text);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// main keymap
|
|
87
237
|
var map = CodeMirror.keyMap.vim = {
|
|
88
|
-
"0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);},
|
|
89
238
|
// Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
|
|
90
|
-
"'|'": function(cm) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"Shift-
|
|
98
|
-
"
|
|
99
|
-
"
|
|
239
|
+
"'|'": function(cm) {
|
|
240
|
+
cm.setCursor(cm.getCursor().line, popCount() - 1, true);
|
|
241
|
+
},
|
|
242
|
+
"A": function(cm) {
|
|
243
|
+
cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);
|
|
244
|
+
enterInsertMode(cm);
|
|
245
|
+
},
|
|
246
|
+
"Shift-A": function(cm) { CodeMirror.commands.goLineEnd(cm); enterInsertMode(cm);},
|
|
247
|
+
"I": function(cm) { enterInsertMode(cm);},
|
|
248
|
+
"Shift-I": function(cm) { goLineStartText(cm); enterInsertMode(cm);},
|
|
249
|
+
"O": function(cm) {
|
|
250
|
+
CodeMirror.commands.goLineEnd(cm);
|
|
251
|
+
CodeMirror.commands.newlineAndIndent(cm);
|
|
252
|
+
enterInsertMode(cm);
|
|
253
|
+
},
|
|
254
|
+
"Shift-O": function(cm) {
|
|
255
|
+
CodeMirror.commands.goLineStart(cm);
|
|
256
|
+
cm.replaceSelection("\n", "start");
|
|
257
|
+
cm.indentLine(cm.getCursor().line);
|
|
258
|
+
enterInsertMode(cm);
|
|
259
|
+
},
|
|
260
|
+
"G": function(cm) { cm.setOption("keyMap", "vim-prefix-g");},
|
|
100
261
|
"Shift-D": function(cm) {
|
|
262
|
+
// commented out verions works, but I left original, cause maybe
|
|
263
|
+
// I don't know vim enouth to see what it does
|
|
264
|
+
/* var cur = cm.getCursor();
|
|
265
|
+
var f = {line: cur.line, ch: cur.ch}, t = {line: cur.line};
|
|
266
|
+
pushInBuffer(cm.getRange(f, t));
|
|
267
|
+
*/
|
|
101
268
|
emptyBuffer();
|
|
102
269
|
mark["Shift-D"] = cm.getCursor(false).line;
|
|
103
270
|
cm.setCursor(cm.getCursor(true).line);
|
|
104
271
|
delTillMark(cm,"Shift-D"); mark = [];
|
|
105
272
|
},
|
|
273
|
+
|
|
274
|
+
"S": function (cm) {
|
|
275
|
+
countTimes(function (_cm) {
|
|
276
|
+
CodeMirror.commands.delCharRight(_cm);
|
|
277
|
+
})(cm);
|
|
278
|
+
enterInsertMode(cm);
|
|
279
|
+
},
|
|
106
280
|
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
|
|
107
281
|
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
|
|
108
282
|
"Shift-Y": function(cm) {
|
|
@@ -111,7 +285,7 @@
|
|
|
111
285
|
cm.setCursor(cm.getCursor(true).line);
|
|
112
286
|
yankTillMark(cm,"Shift-D"); mark = [];
|
|
113
287
|
},
|
|
114
|
-
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"},
|
|
288
|
+
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f";},
|
|
115
289
|
"'?'": function(cm) {
|
|
116
290
|
var f = CodeMirror.commands.find;
|
|
117
291
|
if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
|
|
@@ -124,107 +298,488 @@
|
|
|
124
298
|
var fn = CodeMirror.commands.findNext;
|
|
125
299
|
if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
|
|
126
300
|
},
|
|
127
|
-
"Shift-G": function(cm) {
|
|
128
|
-
|
|
301
|
+
"Shift-G": function(cm) {
|
|
302
|
+
count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count, 10)-1);
|
|
303
|
+
popCount();
|
|
304
|
+
CodeMirror.commands.goLineStart(cm);
|
|
305
|
+
},
|
|
306
|
+
"':'": function(cm) {
|
|
307
|
+
var exModeDialog = ': <input type="text" style="width: 90%"/>';
|
|
308
|
+
dialog(cm, exModeDialog, ':', function(command) {
|
|
309
|
+
if (command.match(/^\d+$/)) {
|
|
310
|
+
cm.setCursor(command - 1, cm.getCursor().ch);
|
|
311
|
+
} else {
|
|
312
|
+
showAlert(cm, "Bad command: " + command);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
},
|
|
316
|
+
nofallthrough: true, style: "fat-cursor"
|
|
129
317
|
};
|
|
130
|
-
|
|
131
|
-
|
|
318
|
+
|
|
319
|
+
// standard mode switching
|
|
320
|
+
iterList(["d", "t", "T", "f", "F", "c", "r"],
|
|
321
|
+
function (ch) {
|
|
322
|
+
CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
|
|
323
|
+
cm.setOption("keyMap", "vim-prefix-" + ch);
|
|
324
|
+
emptyBuffer();
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
|
|
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
|
+
// main num keymap
|
|
132
338
|
// Add bindings that are influenced by number keys
|
|
133
339
|
iterObj({
|
|
134
|
-
"
|
|
135
|
-
"K": "goLineUp", "Left": "goColumnLeft", "Right": "goColumnRight",
|
|
340
|
+
"Left": "goColumnLeft", "Right": "goColumnRight",
|
|
136
341
|
"Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
|
|
137
342
|
"Space": "goCharRight",
|
|
138
|
-
"
|
|
139
|
-
"E": function(cm) {moveToWord(cm, word, 1, "end");},
|
|
140
|
-
"W": function(cm) {moveToWord(cm, word, 1, "start");},
|
|
141
|
-
"Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");},
|
|
142
|
-
"Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");},
|
|
143
|
-
"Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");},
|
|
144
|
-
"X": function(cm) {CodeMirror.commands.delCharRight(cm)},
|
|
343
|
+
"X": function(cm) {CodeMirror.commands.delCharRight(cm);},
|
|
145
344
|
"P": function(cm) {
|
|
146
345
|
var cur = cm.getCursor().line;
|
|
147
346
|
if (buf!= "") {
|
|
148
|
-
CodeMirror.commands.goLineEnd(cm);
|
|
347
|
+
if (buf[0] == "\n") CodeMirror.commands.goLineEnd(cm);
|
|
348
|
+
cm.replaceRange(buf, cm.getCursor());
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm);},
|
|
352
|
+
"Shift-J": function(cm) {joinLineNext(cm);},
|
|
353
|
+
"Shift-P": function(cm) {
|
|
354
|
+
var cur = cm.getCursor().line;
|
|
355
|
+
if (buf!= "") {
|
|
356
|
+
CodeMirror.commands.goLineUp(cm);
|
|
357
|
+
CodeMirror.commands.goLineEnd(cm);
|
|
149
358
|
cm.replaceSelection(buf, "end");
|
|
150
359
|
}
|
|
151
360
|
cm.setCursor(cur+1);
|
|
152
361
|
},
|
|
153
|
-
"Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm)},
|
|
154
|
-
"Shift-J": function(cm) {joinLineNext(cm)},
|
|
155
362
|
"'~'": function(cm) {
|
|
156
363
|
var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
|
|
157
364
|
cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
|
|
158
365
|
cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
|
|
159
366
|
cm.setCursor(cur.line, cur.ch+1);
|
|
160
367
|
},
|
|
161
|
-
"Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm)},
|
|
162
|
-
"Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm)},
|
|
368
|
+
"Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm);},
|
|
369
|
+
"Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm);},
|
|
163
370
|
"Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
|
|
164
|
-
"U": "undo", "Ctrl-R": "redo"
|
|
165
|
-
|
|
371
|
+
"U": "undo", "Ctrl-R": "redo"
|
|
372
|
+
}, function(key, cmd) { map[key] = countTimes(cmd); });
|
|
373
|
+
|
|
374
|
+
// empty key maps
|
|
375
|
+
iterList([
|
|
376
|
+
"vim-prefix-d'",
|
|
377
|
+
"vim-prefix-y'",
|
|
378
|
+
"vim-prefix-df",
|
|
379
|
+
"vim-prefix-dF",
|
|
380
|
+
"vim-prefix-dt",
|
|
381
|
+
"vim-prefix-dT",
|
|
382
|
+
"vim-prefix-c",
|
|
383
|
+
"vim-prefix-cf",
|
|
384
|
+
"vim-prefix-cF",
|
|
385
|
+
"vim-prefix-ct",
|
|
386
|
+
"vim-prefix-cT",
|
|
387
|
+
"vim-prefix-",
|
|
388
|
+
"vim-prefix-f",
|
|
389
|
+
"vim-prefix-F",
|
|
390
|
+
"vim-prefix-t",
|
|
391
|
+
"vim-prefix-T",
|
|
392
|
+
"vim-prefix-r",
|
|
393
|
+
"vim-prefix-m"
|
|
394
|
+
],
|
|
395
|
+
function (prefix) {
|
|
396
|
+
CodeMirror.keyMap[prefix] = {
|
|
397
|
+
auto: "vim",
|
|
398
|
+
nofallthrough: true,
|
|
399
|
+
style: "fat-cursor"
|
|
400
|
+
};
|
|
401
|
+
});
|
|
166
402
|
|
|
167
403
|
CodeMirror.keyMap["vim-prefix-g"] = {
|
|
168
|
-
"E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
|
|
169
|
-
"Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
|
|
170
|
-
|
|
171
|
-
nofallthrough: true
|
|
404
|
+
"E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, word, -1, 1, "start"));}),
|
|
405
|
+
"Shift-E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, bigWord, -1, 1, "start"));}),
|
|
406
|
+
"G": function (cm) { cm.setCursor({line: 0, ch: cm.getCursor().ch});},
|
|
407
|
+
auto: "vim", nofallthrough: true, style: "fat-cursor"
|
|
172
408
|
};
|
|
173
409
|
|
|
174
|
-
CodeMirror.keyMap["vim-prefix-m"] = {
|
|
175
|
-
auto: "vim",
|
|
176
|
-
nofallthrough: true
|
|
177
|
-
};
|
|
178
|
-
|
|
179
410
|
CodeMirror.keyMap["vim-prefix-d"] = {
|
|
180
|
-
"D": countTimes(function(cm) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
411
|
+
"D": countTimes(function(cm) {
|
|
412
|
+
pushInBuffer("\n"+cm.getLine(cm.getCursor().line));
|
|
413
|
+
cm.removeLine(cm.getCursor().line);
|
|
414
|
+
cm.setOption("keyMap", "vim");
|
|
415
|
+
}),
|
|
416
|
+
"'": function(cm) {
|
|
417
|
+
cm.setOption("keyMap", "vim-prefix-d'");
|
|
418
|
+
emptyBuffer();
|
|
419
|
+
},
|
|
420
|
+
"B": function(cm) {
|
|
421
|
+
var cur = cm.getCursor();
|
|
422
|
+
var line = cm.getLine(cur.line);
|
|
423
|
+
var index = line.lastIndexOf(" ", cur.ch);
|
|
424
|
+
|
|
425
|
+
pushInBuffer(line.substring(index, cur.ch));
|
|
426
|
+
cm.replaceRange("", {line: cur.line, ch: index}, cur);
|
|
427
|
+
cm.setOption("keyMap", "vim");
|
|
428
|
+
},
|
|
429
|
+
nofallthrough: true, style: "fat-cursor"
|
|
184
430
|
};
|
|
431
|
+
// FIXME - does not work for bindings like "d3e"
|
|
432
|
+
addCountBindings(CodeMirror.keyMap["vim-prefix-d"]);
|
|
185
433
|
|
|
186
|
-
CodeMirror.keyMap["vim-prefix-
|
|
187
|
-
|
|
188
|
-
|
|
434
|
+
CodeMirror.keyMap["vim-prefix-c"] = {
|
|
435
|
+
"B": function (cm) {
|
|
436
|
+
countTimes("delWordLeft")(cm);
|
|
437
|
+
enterInsertMode(cm);
|
|
438
|
+
},
|
|
439
|
+
"C": function (cm) {
|
|
440
|
+
iterTimes(function (i, last) {
|
|
441
|
+
CodeMirror.commands.deleteLine(cm);
|
|
442
|
+
if (i) {
|
|
443
|
+
CodeMirror.commands.delCharRight(cm);
|
|
444
|
+
if (last) CodeMirror.commands.deleteLine(cm);
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
enterInsertMode(cm);
|
|
448
|
+
},
|
|
449
|
+
nofallthrough: true, style: "fat-cursor"
|
|
189
450
|
};
|
|
190
451
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
452
|
+
iterList(["vim-prefix-d", "vim-prefix-c", "vim-prefix-"], function (prefix) {
|
|
453
|
+
iterList(["f", "F", "T", "t"],
|
|
454
|
+
function (ch) {
|
|
455
|
+
CodeMirror.keyMap[prefix][toCombo(ch)] = function (cm) {
|
|
456
|
+
cm.setOption("keyMap", prefix + ch);
|
|
457
|
+
emptyBuffer();
|
|
458
|
+
};
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
var MOTION_OPTIONS = {
|
|
463
|
+
"t": {inclusive: false, forward: true},
|
|
464
|
+
"f": {inclusive: true, forward: true},
|
|
465
|
+
"T": {inclusive: false, forward: false},
|
|
466
|
+
"F": {inclusive: true, forward: false}
|
|
194
467
|
};
|
|
195
468
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
469
|
+
function setupPrefixBindingForKey(m) {
|
|
470
|
+
CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
|
|
471
|
+
mark[m] = cm.getCursor().line;
|
|
472
|
+
};
|
|
473
|
+
CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
|
|
474
|
+
delTillMark(cm,m);
|
|
475
|
+
};
|
|
476
|
+
CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
|
|
477
|
+
yankTillMark(cm,m);
|
|
478
|
+
};
|
|
479
|
+
CodeMirror.keyMap["vim-prefix-r"][m] = function (cm) {
|
|
480
|
+
var cur = cm.getCursor();
|
|
481
|
+
cm.replaceRange(toLetter(m),
|
|
482
|
+
{line: cur.line, ch: cur.ch},
|
|
483
|
+
{line: cur.line, ch: cur.ch + 1});
|
|
484
|
+
CodeMirror.commands.goColumnLeft(cm);
|
|
485
|
+
};
|
|
486
|
+
// all commands, related to motions till char in line
|
|
487
|
+
iterObj(MOTION_OPTIONS, function (ch, options) {
|
|
488
|
+
CodeMirror.keyMap["vim-prefix-" + ch][m] = function(cm) {
|
|
489
|
+
moveTillChar(cm, m, options);
|
|
202
490
|
};
|
|
203
|
-
CodeMirror.keyMap["vim-prefix-d
|
|
204
|
-
|
|
491
|
+
CodeMirror.keyMap["vim-prefix-d" + ch][m] = function(cm) {
|
|
492
|
+
delTillChar(cm, m, options);
|
|
205
493
|
};
|
|
206
|
-
CodeMirror.keyMap["vim-prefix-
|
|
207
|
-
|
|
494
|
+
CodeMirror.keyMap["vim-prefix-c" + ch][m] = function(cm) {
|
|
495
|
+
delTillChar(cm, m, options);
|
|
496
|
+
enterInsertMode(cm);
|
|
208
497
|
};
|
|
209
|
-
}
|
|
498
|
+
});
|
|
210
499
|
}
|
|
500
|
+
for (var i = 65; i < 65 + 26; i++) { // uppercase alphabet char codes
|
|
501
|
+
var ch = String.fromCharCode(i);
|
|
502
|
+
setupPrefixBindingForKey(toCombo(ch));
|
|
503
|
+
setupPrefixBindingForKey(toCombo(ch.toLowerCase()));
|
|
504
|
+
}
|
|
505
|
+
iterList(SPECIAL_SYMBOLS, function (ch) {
|
|
506
|
+
setupPrefixBindingForKey(toCombo(ch));
|
|
507
|
+
});
|
|
508
|
+
setupPrefixBindingForKey("Space");
|
|
211
509
|
|
|
212
510
|
CodeMirror.keyMap["vim-prefix-y"] = {
|
|
213
511
|
"Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
|
|
214
512
|
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
|
|
215
|
-
|
|
216
|
-
nofallthrough: true
|
|
513
|
+
nofallthrough: true, style: "fat-cursor"
|
|
217
514
|
};
|
|
218
515
|
|
|
219
516
|
CodeMirror.keyMap["vim-insert"] = {
|
|
220
517
|
// TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>
|
|
221
518
|
"Esc": function(cm) {
|
|
222
|
-
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
|
|
519
|
+
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
|
|
223
520
|
cm.setOption("keyMap", "vim");
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
"Ctrl-
|
|
227
|
-
"Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */},
|
|
521
|
+
},
|
|
522
|
+
"Ctrl-N": "autocomplete",
|
|
523
|
+
"Ctrl-P": "autocomplete",
|
|
228
524
|
fallthrough: ["default"]
|
|
229
525
|
};
|
|
526
|
+
|
|
527
|
+
function findMatchedSymbol(cm, cur, symb) {
|
|
528
|
+
var line = cur.line;
|
|
529
|
+
var symb = symb ? symb : cm.getLine(line)[cur.ch];
|
|
530
|
+
|
|
531
|
+
// Are we at the opening or closing char
|
|
532
|
+
var forwards = ['(', '[', '{'].indexOf(symb) != -1;
|
|
533
|
+
|
|
534
|
+
var reverseSymb = (function(sym) {
|
|
535
|
+
switch (sym) {
|
|
536
|
+
case '(' : return ')';
|
|
537
|
+
case '[' : return ']';
|
|
538
|
+
case '{' : return '}';
|
|
539
|
+
case ')' : return '(';
|
|
540
|
+
case ']' : return '[';
|
|
541
|
+
case '}' : return '{';
|
|
542
|
+
default : return null;
|
|
543
|
+
}
|
|
544
|
+
})(symb);
|
|
545
|
+
|
|
546
|
+
// Couldn't find a matching symbol, abort
|
|
547
|
+
if (reverseSymb == null) return cur;
|
|
548
|
+
|
|
549
|
+
// Tracking our imbalance in open/closing symbols. An opening symbol wii be
|
|
550
|
+
// the first thing we pick up if moving forward, this isn't true moving backwards
|
|
551
|
+
var disBal = forwards ? 0 : 1;
|
|
552
|
+
|
|
553
|
+
while (true) {
|
|
554
|
+
if (line == cur.line) {
|
|
555
|
+
// First pass, do some special stuff
|
|
556
|
+
var currLine = forwards ? cm.getLine(line).substr(cur.ch).split('') : cm.getLine(line).substr(0,cur.ch).split('').reverse();
|
|
557
|
+
} else {
|
|
558
|
+
var currLine = forwards ? cm.getLine(line).split('') : cm.getLine(line).split('').reverse();
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
for (var index = 0; index < currLine.length; index++) {
|
|
562
|
+
if (currLine[index] == symb) disBal++;
|
|
563
|
+
else if (currLine[index] == reverseSymb) disBal--;
|
|
564
|
+
|
|
565
|
+
if (disBal == 0) {
|
|
566
|
+
if (forwards && cur.line == line) return {line: line, ch: index + cur.ch};
|
|
567
|
+
else if (forwards) return {line: line, ch: index};
|
|
568
|
+
else return {line: line, ch: currLine.length - index - 1 };
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (forwards) line++;
|
|
573
|
+
else line--;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function selectCompanionObject(cm, revSymb, inclusive) {
|
|
578
|
+
var cur = cm.getCursor();
|
|
579
|
+
|
|
580
|
+
var end = findMatchedSymbol(cm, cur, revSymb);
|
|
581
|
+
var start = findMatchedSymbol(cm, end);
|
|
582
|
+
start.ch += inclusive ? 1 : 0;
|
|
583
|
+
end.ch += inclusive ? 0 : 1;
|
|
584
|
+
|
|
585
|
+
return {start: start, end: end};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// These are our motion commands to be used for navigation and selection with
|
|
589
|
+
// certian other commands. All should return a cursor object.
|
|
590
|
+
var motionList = ['B', 'E', 'J', 'K', 'H', 'L', 'W', 'Shift-W', "'^'", "'$'", "'%'", 'Esc'];
|
|
591
|
+
|
|
592
|
+
motions = {
|
|
593
|
+
'B': function(cm, times) { return moveToWord(cm, word, -1, times); },
|
|
594
|
+
'Shift-B': function(cm, times) { return moveToWord(cm, bigWord, -1, times); },
|
|
595
|
+
'E': function(cm, times) { return moveToWord(cm, word, 1, times, 'end'); },
|
|
596
|
+
'Shift-E': function(cm, times) { return moveToWord(cm, bigWord, 1, times, 'end'); },
|
|
597
|
+
'J': function(cm, times) {
|
|
598
|
+
var cur = cm.getCursor();
|
|
599
|
+
return {line: cur.line+times, ch : cur.ch};
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
'K': function(cm, times) {
|
|
603
|
+
var cur = cm.getCursor();
|
|
604
|
+
return {line: cur.line-times, ch: cur.ch};
|
|
605
|
+
},
|
|
606
|
+
|
|
607
|
+
'H': function(cm, times) {
|
|
608
|
+
var cur = cm.getCursor();
|
|
609
|
+
return {line: cur.line, ch: cur.ch-times};
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
'L': function(cm, times) {
|
|
613
|
+
var cur = cm.getCursor();
|
|
614
|
+
return {line: cur.line, ch: cur.ch+times};
|
|
615
|
+
},
|
|
616
|
+
'W': function(cm, times) { return moveToWord(cm, word, 1, times); },
|
|
617
|
+
'Shift-W': function(cm, times) { return moveToWord(cm, bigWord, 1, times); },
|
|
618
|
+
"'^'": function(cm, times) {
|
|
619
|
+
var cur = cm.getCursor();
|
|
620
|
+
var line = cm.getLine(cur.line).split('');
|
|
621
|
+
|
|
622
|
+
// Empty line :o
|
|
623
|
+
if (line.length == 0) return cur;
|
|
624
|
+
|
|
625
|
+
for (var index = 0; index < line.length; index++) {
|
|
626
|
+
if (line[index].match(/[^\s]/)) return {line: cur.line, ch: index};
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
"'$'": function(cm) {
|
|
630
|
+
var cur = cm.getCursor();
|
|
631
|
+
var line = cm.getLine(cur.line);
|
|
632
|
+
return {line: cur.line, ch: line.length};
|
|
633
|
+
},
|
|
634
|
+
"'%'": function(cm) { return findMatchedSymbol(cm, cm.getCursor()); },
|
|
635
|
+
"Esc" : function(cm) {
|
|
636
|
+
cm.setOption('vim');
|
|
637
|
+
reptTimes = 0;
|
|
638
|
+
|
|
639
|
+
return cm.getCursor();
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// Map our movement actions each operator and non-operational movement
|
|
644
|
+
motionList.forEach(function(key, index, array) {
|
|
645
|
+
CodeMirror.keyMap['vim-prefix-d'][key] = function(cm) {
|
|
646
|
+
// Get our selected range
|
|
647
|
+
var start = cm.getCursor();
|
|
648
|
+
var end = motions[key](cm, reptTimes ? reptTimes : 1);
|
|
649
|
+
|
|
650
|
+
// Set swap var if range is of negative length
|
|
651
|
+
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
|
652
|
+
|
|
653
|
+
// Take action, switching start and end if swap var is set
|
|
654
|
+
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
|
655
|
+
cm.replaceRange("", swap ? end : start, swap ? start : end);
|
|
656
|
+
|
|
657
|
+
// And clean up
|
|
658
|
+
reptTimes = 0;
|
|
659
|
+
cm.setOption("keyMap", "vim");
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
CodeMirror.keyMap['vim-prefix-c'][key] = function(cm) {
|
|
663
|
+
var start = cm.getCursor();
|
|
664
|
+
var end = motions[key](cm, reptTimes ? reptTimes : 1);
|
|
665
|
+
|
|
666
|
+
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
|
667
|
+
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
|
668
|
+
cm.replaceRange("", swap ? end : start, swap ? start : end);
|
|
669
|
+
|
|
670
|
+
reptTimes = 0;
|
|
671
|
+
cm.setOption('keyMap', 'vim-insert');
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
CodeMirror.keyMap['vim-prefix-y'][key] = function(cm) {
|
|
675
|
+
var start = cm.getCursor();
|
|
676
|
+
var end = motions[key](cm, reptTimes ? reptTimes : 1);
|
|
677
|
+
|
|
678
|
+
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
|
|
679
|
+
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
|
680
|
+
|
|
681
|
+
reptTimes = 0;
|
|
682
|
+
cm.setOption("keyMap", "vim");
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
CodeMirror.keyMap['vim'][key] = function(cm) {
|
|
686
|
+
var cur = motions[key](cm, reptTimes ? reptTimes : 1);
|
|
687
|
+
cm.setCursor(cur.line, cur.ch);
|
|
688
|
+
|
|
689
|
+
reptTimes = 0;
|
|
690
|
+
};
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
var nums = [1,2,3,4,5,6,7,8,9];
|
|
694
|
+
nums.forEach(function(key, index, array) {
|
|
695
|
+
CodeMirror.keyMap['vim'][key] = function (cm) {
|
|
696
|
+
reptTimes = (reptTimes * 10) + key;
|
|
697
|
+
};
|
|
698
|
+
CodeMirror.keyMap['vim-prefix-d'][key] = function (cm) {
|
|
699
|
+
reptTimes = (reptTimes * 10) + key;
|
|
700
|
+
};
|
|
701
|
+
CodeMirror.keyMap['vim-prefix-y'][key] = function (cm) {
|
|
702
|
+
reptTimes = (reptTimes * 10) + key;
|
|
703
|
+
};
|
|
704
|
+
CodeMirror.keyMap['vim-prefix-c'][key] = function (cm) {
|
|
705
|
+
reptTimes = (reptTimes * 10) + key;
|
|
706
|
+
};
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// Create our keymaps for each operator and make xa and xi where x is an operator
|
|
710
|
+
// change to the corrosponding keymap
|
|
711
|
+
var operators = ['d', 'y', 'c'];
|
|
712
|
+
operators.forEach(function(key, index, array) {
|
|
713
|
+
CodeMirror.keyMap['vim-prefix-'+key+'a'] = {
|
|
714
|
+
auto: 'vim', nofallthrough: true, style: "fat-cursor"
|
|
715
|
+
};
|
|
716
|
+
CodeMirror.keyMap['vim-prefix-'+key+'i'] = {
|
|
717
|
+
auto: 'vim', nofallthrough: true, style: "fat-cursor"
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
CodeMirror.keyMap['vim-prefix-'+key]['A'] = function(cm) {
|
|
721
|
+
reptTimes = 0;
|
|
722
|
+
cm.setOption('keyMap', 'vim-prefix-' + key + 'a');
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
CodeMirror.keyMap['vim-prefix-'+key]['I'] = function(cm) {
|
|
726
|
+
reptTimes = 0;
|
|
727
|
+
cm.setOption('keyMap', 'vim-prefix-' + key + 'i');
|
|
728
|
+
};
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
function regexLastIndexOf(string, pattern, startIndex) {
|
|
732
|
+
for (var i = startIndex == null ? string.length : startIndex; i >= 0; --i)
|
|
733
|
+
if (pattern.test(string.charAt(i))) return i;
|
|
734
|
+
return -1;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Create our text object functions. They work similar to motions but they
|
|
738
|
+
// return a start cursor as well
|
|
739
|
+
var textObjectList = ['W', 'Shift-[', 'Shift-9', '['];
|
|
740
|
+
var textObjects = {
|
|
741
|
+
'W': function(cm, inclusive) {
|
|
742
|
+
var cur = cm.getCursor();
|
|
743
|
+
var line = cm.getLine(cur.line);
|
|
744
|
+
|
|
745
|
+
var line_to_char = new String(line.substring(0, cur.ch));
|
|
746
|
+
var start = regexLastIndexOf(line_to_char, /[^a-zA-Z0-9]/) + 1;
|
|
747
|
+
var end = motions["E"](cm, 1) ;
|
|
748
|
+
|
|
749
|
+
end.ch += inclusive ? 1 : 0 ;
|
|
750
|
+
return {start: {line: cur.line, ch: start}, end: end };
|
|
751
|
+
},
|
|
752
|
+
'Shift-[': function(cm, inclusive) { return selectCompanionObject(cm, '}', inclusive); },
|
|
753
|
+
'Shift-9': function(cm, inclusive) { return selectCompanionObject(cm, ')', inclusive); },
|
|
754
|
+
'[': function(cm, inclusive) { return selectCompanionObject(cm, ']', inclusive); }
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
// One function to handle all operation upon text objects. Kinda funky but it works
|
|
758
|
+
// better than rewriting this code six times
|
|
759
|
+
function textObjectManipulation(cm, object, remove, insert, inclusive) {
|
|
760
|
+
// Object is the text object, delete object if remove is true, enter insert
|
|
761
|
+
// mode if insert is true, inclusive is the difference between a and i
|
|
762
|
+
var tmp = textObjects[object](cm, inclusive);
|
|
763
|
+
var start = tmp.start;
|
|
764
|
+
var end = tmp.end;
|
|
765
|
+
|
|
766
|
+
if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true ;
|
|
767
|
+
|
|
768
|
+
pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
|
|
769
|
+
if (remove) cm.replaceRange("", swap ? end : start, swap ? start : end);
|
|
770
|
+
if (insert) cm.setOption('keyMap', 'vim-insert');
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// And finally build the keymaps up from the text objects
|
|
774
|
+
for (var i = 0; i < textObjectList.length; ++i) {
|
|
775
|
+
var object = textObjectList[i];
|
|
776
|
+
(function(object) {
|
|
777
|
+
CodeMirror.keyMap['vim-prefix-di'][object] = function(cm) { textObjectManipulation(cm, object, true, false, false); };
|
|
778
|
+
CodeMirror.keyMap['vim-prefix-da'][object] = function(cm) { textObjectManipulation(cm, object, true, false, true); };
|
|
779
|
+
CodeMirror.keyMap['vim-prefix-yi'][object] = function(cm) { textObjectManipulation(cm, object, false, false, false); };
|
|
780
|
+
CodeMirror.keyMap['vim-prefix-ya'][object] = function(cm) { textObjectManipulation(cm, object, false, false, true); };
|
|
781
|
+
CodeMirror.keyMap['vim-prefix-ci'][object] = function(cm) { textObjectManipulation(cm, object, true, true, false); };
|
|
782
|
+
CodeMirror.keyMap['vim-prefix-ca'][object] = function(cm) { textObjectManipulation(cm, object, true, true, true); };
|
|
783
|
+
})(object)
|
|
784
|
+
}
|
|
230
785
|
})();
|