GPQAPP

Форк
0
720 строк · 26.1 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://codemirror.net/LICENSE
3

4
// A rough approximation of Sublime Text's keybindings
5
// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js
6

7
(function(mod) {
8
  if (typeof exports == "object" && typeof module == "object") // CommonJS
9
    mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets"));
10
  else if (typeof define == "function" && define.amd) // AMD
11
    define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);
12
  else // Plain browser env
13
    mod(CodeMirror);
14
})(function(CodeMirror) {
15
  "use strict";
16

17
  var cmds = CodeMirror.commands;
18
  var Pos = CodeMirror.Pos;
19

20
  // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
21
  function findPosSubword(doc, start, dir) {
22
    if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
23
    var line = doc.getLine(start.line);
24
    if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
25
    var state = "start", type, startPos = start.ch;
26
    for (var pos = startPos, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {
27
      var next = line.charAt(dir < 0 ? pos - 1 : pos);
28
      var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
29
      if (cat == "w" && next.toUpperCase() == next) cat = "W";
30
      if (state == "start") {
31
        if (cat != "o") { state = "in"; type = cat; }
32
        else startPos = pos + dir
33
      } else if (state == "in") {
34
        if (type != cat) {
35
          if (type == "w" && cat == "W" && dir < 0) pos--;
36
          if (type == "W" && cat == "w" && dir > 0) { // From uppercase to lowercase
37
            if (pos == startPos + 1) { type = "w"; continue; }
38
            else pos--;
39
          }
40
          break;
41
        }
42
      }
43
    }
44
    return Pos(start.line, pos);
45
  }
46

47
  function moveSubword(cm, dir) {
48
    cm.extendSelectionsBy(function(range) {
49
      if (cm.display.shift || cm.doc.extend || range.empty())
50
        return findPosSubword(cm.doc, range.head, dir);
51
      else
52
        return dir < 0 ? range.from() : range.to();
53
    });
54
  }
55

56
  cmds.goSubwordLeft = function(cm) { moveSubword(cm, -1); };
57
  cmds.goSubwordRight = function(cm) { moveSubword(cm, 1); };
58

59
  cmds.scrollLineUp = function(cm) {
60
    var info = cm.getScrollInfo();
61
    if (!cm.somethingSelected()) {
62
      var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
63
      if (cm.getCursor().line >= visibleBottomLine)
64
        cm.execCommand("goLineUp");
65
    }
66
    cm.scrollTo(null, info.top - cm.defaultTextHeight());
67
  };
68
  cmds.scrollLineDown = function(cm) {
69
    var info = cm.getScrollInfo();
70
    if (!cm.somethingSelected()) {
71
      var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
72
      if (cm.getCursor().line <= visibleTopLine)
73
        cm.execCommand("goLineDown");
74
    }
75
    cm.scrollTo(null, info.top + cm.defaultTextHeight());
76
  };
77

78
  cmds.splitSelectionByLine = function(cm) {
79
    var ranges = cm.listSelections(), lineRanges = [];
80
    for (var i = 0; i < ranges.length; i++) {
81
      var from = ranges[i].from(), to = ranges[i].to();
82
      for (var line = from.line; line <= to.line; ++line)
83
        if (!(to.line > from.line && line == to.line && to.ch == 0))
84
          lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),
85
                           head: line == to.line ? to : Pos(line)});
86
    }
87
    cm.setSelections(lineRanges, 0);
88
  };
89

90
  cmds.singleSelectionTop = function(cm) {
91
    var range = cm.listSelections()[0];
92
    cm.setSelection(range.anchor, range.head, {scroll: false});
93
  };
94

95
  cmds.selectLine = function(cm) {
96
    var ranges = cm.listSelections(), extended = [];
97
    for (var i = 0; i < ranges.length; i++) {
98
      var range = ranges[i];
99
      extended.push({anchor: Pos(range.from().line, 0),
100
                     head: Pos(range.to().line + 1, 0)});
101
    }
102
    cm.setSelections(extended);
103
  };
104

105
  function insertLine(cm, above) {
106
    if (cm.isReadOnly()) return CodeMirror.Pass
107
    cm.operation(function() {
108
      var len = cm.listSelections().length, newSelection = [], last = -1;
109
      for (var i = 0; i < len; i++) {
110
        var head = cm.listSelections()[i].head;
111
        if (head.line <= last) continue;
112
        var at = Pos(head.line + (above ? 0 : 1), 0);
113
        cm.replaceRange("\n", at, null, "+insertLine");
114
        cm.indentLine(at.line, null, true);
115
        newSelection.push({head: at, anchor: at});
116
        last = head.line + 1;
117
      }
118
      cm.setSelections(newSelection);
119
    });
120
    cm.execCommand("indentAuto");
121
  }
122

123
  cmds.insertLineAfter = function(cm) { return insertLine(cm, false); };
124

125
  cmds.insertLineBefore = function(cm) { return insertLine(cm, true); };
126

127
  function wordAt(cm, pos) {
128
    var start = pos.ch, end = start, line = cm.getLine(pos.line);
129
    while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;
130
    while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;
131
    return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};
132
  }
133

134
  cmds.selectNextOccurrence = function(cm) {
135
    var from = cm.getCursor("from"), to = cm.getCursor("to");
136
    var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;
137
    if (CodeMirror.cmpPos(from, to) == 0) {
138
      var word = wordAt(cm, from);
139
      if (!word.word) return;
140
      cm.setSelection(word.from, word.to);
141
      fullWord = true;
142
    } else {
143
      var text = cm.getRange(from, to);
144
      var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
145
      var cur = cm.getSearchCursor(query, to);
146
      var found = cur.findNext();
147
      if (!found) {
148
        cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
149
        found = cur.findNext();
150
      }
151
      if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) return
152
      cm.addSelection(cur.from(), cur.to());
153
    }
154
    if (fullWord)
155
      cm.state.sublimeFindFullWord = cm.doc.sel;
156
  };
157

158
  cmds.skipAndSelectNextOccurrence = function(cm) {
159
    var prevAnchor = cm.getCursor("anchor"), prevHead = cm.getCursor("head");
160
    cmds.selectNextOccurrence(cm);
161
    if (CodeMirror.cmpPos(prevAnchor, prevHead) != 0) {
162
      cm.doc.setSelections(cm.doc.listSelections()
163
          .filter(function (sel) {
164
            return sel.anchor != prevAnchor || sel.head != prevHead;
165
          }));
166
    }
167
  }
168

169
  function addCursorToSelection(cm, dir) {
170
    var ranges = cm.listSelections(), newRanges = [];
171
    for (var i = 0; i < ranges.length; i++) {
172
      var range = ranges[i];
173
      var newAnchor = cm.findPosV(
174
          range.anchor, dir, "line", range.anchor.goalColumn);
175
      var newHead = cm.findPosV(
176
          range.head, dir, "line", range.head.goalColumn);
177
      newAnchor.goalColumn = range.anchor.goalColumn != null ?
178
          range.anchor.goalColumn : cm.cursorCoords(range.anchor, "div").left;
179
      newHead.goalColumn = range.head.goalColumn != null ?
180
          range.head.goalColumn : cm.cursorCoords(range.head, "div").left;
181
      var newRange = {anchor: newAnchor, head: newHead};
182
      newRanges.push(range);
183
      newRanges.push(newRange);
184
    }
185
    cm.setSelections(newRanges);
186
  }
187
  cmds.addCursorToPrevLine = function(cm) { addCursorToSelection(cm, -1); };
188
  cmds.addCursorToNextLine = function(cm) { addCursorToSelection(cm, 1); };
189

190
  function isSelectedRange(ranges, from, to) {
191
    for (var i = 0; i < ranges.length; i++)
192
      if (CodeMirror.cmpPos(ranges[i].from(), from) == 0 &&
193
          CodeMirror.cmpPos(ranges[i].to(), to) == 0) return true
194
    return false
195
  }
196

197
  var mirror = "(){}[]";
198
  function selectBetweenBrackets(cm) {
199
    var ranges = cm.listSelections(), newRanges = []
200
    for (var i = 0; i < ranges.length; i++) {
201
      var range = ranges[i], pos = range.head, opening = cm.scanForBracket(pos, -1);
202
      if (!opening) return false;
203
      for (;;) {
204
        var closing = cm.scanForBracket(pos, 1);
205
        if (!closing) return false;
206
        if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {
207
          var startPos = Pos(opening.pos.line, opening.pos.ch + 1);
208
          if (CodeMirror.cmpPos(startPos, range.from()) == 0 &&
209
              CodeMirror.cmpPos(closing.pos, range.to()) == 0) {
210
            opening = cm.scanForBracket(opening.pos, -1);
211
            if (!opening) return false;
212
          } else {
213
            newRanges.push({anchor: startPos, head: closing.pos});
214
            break;
215
          }
216
        }
217
        pos = Pos(closing.pos.line, closing.pos.ch + 1);
218
      }
219
    }
220
    cm.setSelections(newRanges);
221
    return true;
222
  }
223

224
  cmds.selectScope = function(cm) {
225
    selectBetweenBrackets(cm) || cm.execCommand("selectAll");
226
  };
227
  cmds.selectBetweenBrackets = function(cm) {
228
    if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
229
  };
230

231
  function puncType(type) {
232
    return !type ? null : /\bpunctuation\b/.test(type) ? type : undefined
233
  }
234

235
  cmds.goToBracket = function(cm) {
236
    cm.extendSelectionsBy(function(range) {
237
      var next = cm.scanForBracket(range.head, 1, puncType(cm.getTokenTypeAt(range.head)));
238
      if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;
239
      var prev = cm.scanForBracket(range.head, -1, puncType(cm.getTokenTypeAt(Pos(range.head.line, range.head.ch + 1))));
240
      return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
241
    });
242
  };
243

244
  cmds.swapLineUp = function(cm) {
245
    if (cm.isReadOnly()) return CodeMirror.Pass
246
    var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
247
    for (var i = 0; i < ranges.length; i++) {
248
      var range = ranges[i], from = range.from().line - 1, to = range.to().line;
249
      newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),
250
                    head: Pos(range.head.line - 1, range.head.ch)});
251
      if (range.to().ch == 0 && !range.empty()) --to;
252
      if (from > at) linesToMove.push(from, to);
253
      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
254
      at = to;
255
    }
256
    cm.operation(function() {
257
      for (var i = 0; i < linesToMove.length; i += 2) {
258
        var from = linesToMove[i], to = linesToMove[i + 1];
259
        var line = cm.getLine(from);
260
        cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
261
        if (to > cm.lastLine())
262
          cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine");
263
        else
264
          cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
265
      }
266
      cm.setSelections(newSels);
267
      cm.scrollIntoView();
268
    });
269
  };
270

271
  cmds.swapLineDown = function(cm) {
272
    if (cm.isReadOnly()) return CodeMirror.Pass
273
    var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
274
    for (var i = ranges.length - 1; i >= 0; i--) {
275
      var range = ranges[i], from = range.to().line + 1, to = range.from().line;
276
      if (range.to().ch == 0 && !range.empty()) from--;
277
      if (from < at) linesToMove.push(from, to);
278
      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
279
      at = to;
280
    }
281
    cm.operation(function() {
282
      for (var i = linesToMove.length - 2; i >= 0; i -= 2) {
283
        var from = linesToMove[i], to = linesToMove[i + 1];
284
        var line = cm.getLine(from);
285
        if (from == cm.lastLine())
286
          cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");
287
        else
288
          cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
289
        cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
290
      }
291
      cm.scrollIntoView();
292
    });
293
  };
294

295
  cmds.toggleCommentIndented = function(cm) {
296
    cm.toggleComment({ indent: true });
297
  }
298

299
  cmds.joinLines = function(cm) {
300
    var ranges = cm.listSelections(), joined = [];
301
    for (var i = 0; i < ranges.length; i++) {
302
      var range = ranges[i], from = range.from();
303
      var start = from.line, end = range.to().line;
304
      while (i < ranges.length - 1 && ranges[i + 1].from().line == end)
305
        end = ranges[++i].to().line;
306
      joined.push({start: start, end: end, anchor: !range.empty() && from});
307
    }
308
    cm.operation(function() {
309
      var offset = 0, ranges = [];
310
      for (var i = 0; i < joined.length; i++) {
311
        var obj = joined[i];
312
        var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;
313
        for (var line = obj.start; line <= obj.end; line++) {
314
          var actual = line - offset;
315
          if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);
316
          if (actual < cm.lastLine()) {
317
            cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length));
318
            ++offset;
319
          }
320
        }
321
        ranges.push({anchor: anchor || head, head: head});
322
      }
323
      cm.setSelections(ranges, 0);
324
    });
325
  };
326

327
  cmds.duplicateLine = function(cm) {
328
    cm.operation(function() {
329
      var rangeCount = cm.listSelections().length;
330
      for (var i = 0; i < rangeCount; i++) {
331
        var range = cm.listSelections()[i];
332
        if (range.empty())
333
          cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0));
334
        else
335
          cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());
336
      }
337
      cm.scrollIntoView();
338
    });
339
  };
340

341

342
  function sortLines(cm, caseSensitive, direction) {
343
    if (cm.isReadOnly()) return CodeMirror.Pass
344
    var ranges = cm.listSelections(), toSort = [], selected;
345
    for (var i = 0; i < ranges.length; i++) {
346
      var range = ranges[i];
347
      if (range.empty()) continue;
348
      var from = range.from().line, to = range.to().line;
349
      while (i < ranges.length - 1 && ranges[i + 1].from().line == to)
350
        to = ranges[++i].to().line;
351
      if (!ranges[i].to().ch) to--;
352
      toSort.push(from, to);
353
    }
354
    if (toSort.length) selected = true;
355
    else toSort.push(cm.firstLine(), cm.lastLine());
356

357
    cm.operation(function() {
358
      var ranges = [];
359
      for (var i = 0; i < toSort.length; i += 2) {
360
        var from = toSort[i], to = toSort[i + 1];
361
        var start = Pos(from, 0), end = Pos(to);
362
        var lines = cm.getRange(start, end, false);
363
        if (caseSensitive)
364
          lines.sort(function(a, b) { return a < b ? -direction : a == b ? 0 : direction; });
365
        else
366
          lines.sort(function(a, b) {
367
            var au = a.toUpperCase(), bu = b.toUpperCase();
368
            if (au != bu) { a = au; b = bu; }
369
            return a < b ? -direction : a == b ? 0 : direction;
370
          });
371
        cm.replaceRange(lines, start, end);
372
        if (selected) ranges.push({anchor: start, head: Pos(to + 1, 0)});
373
      }
374
      if (selected) cm.setSelections(ranges, 0);
375
    });
376
  }
377

378
  cmds.sortLines = function(cm) { sortLines(cm, true, 1); };
379
  cmds.reverseSortLines = function(cm) { sortLines(cm, true, -1); };
380
  cmds.sortLinesInsensitive = function(cm) { sortLines(cm, false, 1); };
381
  cmds.reverseSortLinesInsensitive = function(cm) { sortLines(cm, false, -1); };
382

383
  cmds.nextBookmark = function(cm) {
384
    var marks = cm.state.sublimeBookmarks;
385
    if (marks) while (marks.length) {
386
      var current = marks.shift();
387
      var found = current.find();
388
      if (found) {
389
        marks.push(current);
390
        return cm.setSelection(found.from, found.to);
391
      }
392
    }
393
  };
394

395
  cmds.prevBookmark = function(cm) {
396
    var marks = cm.state.sublimeBookmarks;
397
    if (marks) while (marks.length) {
398
      marks.unshift(marks.pop());
399
      var found = marks[marks.length - 1].find();
400
      if (!found)
401
        marks.pop();
402
      else
403
        return cm.setSelection(found.from, found.to);
404
    }
405
  };
406

407
  cmds.toggleBookmark = function(cm) {
408
    var ranges = cm.listSelections();
409
    var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);
410
    for (var i = 0; i < ranges.length; i++) {
411
      var from = ranges[i].from(), to = ranges[i].to();
412
      var found = ranges[i].empty() ? cm.findMarksAt(from) : cm.findMarks(from, to);
413
      for (var j = 0; j < found.length; j++) {
414
        if (found[j].sublimeBookmark) {
415
          found[j].clear();
416
          for (var k = 0; k < marks.length; k++)
417
            if (marks[k] == found[j])
418
              marks.splice(k--, 1);
419
          break;
420
        }
421
      }
422
      if (j == found.length)
423
        marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));
424
    }
425
  };
426

427
  cmds.clearBookmarks = function(cm) {
428
    var marks = cm.state.sublimeBookmarks;
429
    if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();
430
    marks.length = 0;
431
  };
432

433
  cmds.selectBookmarks = function(cm) {
434
    var marks = cm.state.sublimeBookmarks, ranges = [];
435
    if (marks) for (var i = 0; i < marks.length; i++) {
436
      var found = marks[i].find();
437
      if (!found)
438
        marks.splice(i--, 0);
439
      else
440
        ranges.push({anchor: found.from, head: found.to});
441
    }
442
    if (ranges.length)
443
      cm.setSelections(ranges, 0);
444
  };
445

446
  function modifyWordOrSelection(cm, mod) {
447
    cm.operation(function() {
448
      var ranges = cm.listSelections(), indices = [], replacements = [];
449
      for (var i = 0; i < ranges.length; i++) {
450
        var range = ranges[i];
451
        if (range.empty()) { indices.push(i); replacements.push(""); }
452
        else replacements.push(mod(cm.getRange(range.from(), range.to())));
453
      }
454
      cm.replaceSelections(replacements, "around", "case");
455
      for (var i = indices.length - 1, at; i >= 0; i--) {
456
        var range = ranges[indices[i]];
457
        if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;
458
        var word = wordAt(cm, range.head);
459
        at = word.from;
460
        cm.replaceRange(mod(word.word), word.from, word.to);
461
      }
462
    });
463
  }
464

465
  cmds.smartBackspace = function(cm) {
466
    if (cm.somethingSelected()) return CodeMirror.Pass;
467

468
    cm.operation(function() {
469
      var cursors = cm.listSelections();
470
      var indentUnit = cm.getOption("indentUnit");
471

472
      for (var i = cursors.length - 1; i >= 0; i--) {
473
        var cursor = cursors[i].head;
474
        var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
475
        var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
476

477
        // Delete by one character by default
478
        var deletePos = cm.findPosH(cursor, -1, "char", false);
479

480
        if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) {
481
          var prevIndent = new Pos(cursor.line,
482
            CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit));
483

484
          // Smart delete only if we found a valid prevIndent location
485
          if (prevIndent.ch != cursor.ch) deletePos = prevIndent;
486
        }
487

488
        cm.replaceRange("", deletePos, cursor, "+delete");
489
      }
490
    });
491
  };
492

493
  cmds.delLineRight = function(cm) {
494
    cm.operation(function() {
495
      var ranges = cm.listSelections();
496
      for (var i = ranges.length - 1; i >= 0; i--)
497
        cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");
498
      cm.scrollIntoView();
499
    });
500
  };
501

502
  cmds.upcaseAtCursor = function(cm) {
503
    modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
504
  };
505
  cmds.downcaseAtCursor = function(cm) {
506
    modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
507
  };
508

509
  cmds.setSublimeMark = function(cm) {
510
    if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
511
    cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
512
  };
513
  cmds.selectToSublimeMark = function(cm) {
514
    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
515
    if (found) cm.setSelection(cm.getCursor(), found);
516
  };
517
  cmds.deleteToSublimeMark = function(cm) {
518
    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
519
    if (found) {
520
      var from = cm.getCursor(), to = found;
521
      if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }
522
      cm.state.sublimeKilled = cm.getRange(from, to);
523
      cm.replaceRange("", from, to);
524
    }
525
  };
526
  cmds.swapWithSublimeMark = function(cm) {
527
    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
528
    if (found) {
529
      cm.state.sublimeMark.clear();
530
      cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
531
      cm.setCursor(found);
532
    }
533
  };
534
  cmds.sublimeYank = function(cm) {
535
    if (cm.state.sublimeKilled != null)
536
      cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
537
  };
538

539
  cmds.showInCenter = function(cm) {
540
    var pos = cm.cursorCoords(null, "local");
541
    cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
542
  };
543

544
  function getTarget(cm) {
545
    var from = cm.getCursor("from"), to = cm.getCursor("to");
546
    if (CodeMirror.cmpPos(from, to) == 0) {
547
      var word = wordAt(cm, from);
548
      if (!word.word) return;
549
      from = word.from;
550
      to = word.to;
551
    }
552
    return {from: from, to: to, query: cm.getRange(from, to), word: word};
553
  }
554

555
  function findAndGoTo(cm, forward) {
556
    var target = getTarget(cm);
557
    if (!target) return;
558
    var query = target.query;
559
    var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
560

561
    if (forward ? cur.findNext() : cur.findPrevious()) {
562
      cm.setSelection(cur.from(), cur.to());
563
    } else {
564
      cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)
565
                                              : cm.clipPos(Pos(cm.lastLine())));
566
      if (forward ? cur.findNext() : cur.findPrevious())
567
        cm.setSelection(cur.from(), cur.to());
568
      else if (target.word)
569
        cm.setSelection(target.from, target.to);
570
    }
571
  };
572
  cmds.findUnder = function(cm) { findAndGoTo(cm, true); };
573
  cmds.findUnderPrevious = function(cm) { findAndGoTo(cm,false); };
574
  cmds.findAllUnder = function(cm) {
575
    var target = getTarget(cm);
576
    if (!target) return;
577
    var cur = cm.getSearchCursor(target.query);
578
    var matches = [];
579
    var primaryIndex = -1;
580
    while (cur.findNext()) {
581
      matches.push({anchor: cur.from(), head: cur.to()});
582
      if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
583
        primaryIndex++;
584
    }
585
    cm.setSelections(matches, primaryIndex);
586
  };
587

588

589
  var keyMap = CodeMirror.keyMap;
590
  keyMap.macSublime = {
591
    "Cmd-Left": "goLineStartSmart",
592
    "Shift-Tab": "indentLess",
593
    "Shift-Ctrl-K": "deleteLine",
594
    "Alt-Q": "wrapLines",
595
    "Ctrl-Left": "goSubwordLeft",
596
    "Ctrl-Right": "goSubwordRight",
597
    "Ctrl-Alt-Up": "scrollLineUp",
598
    "Ctrl-Alt-Down": "scrollLineDown",
599
    "Cmd-L": "selectLine",
600
    "Shift-Cmd-L": "splitSelectionByLine",
601
    "Esc": "singleSelectionTop",
602
    "Cmd-Enter": "insertLineAfter",
603
    "Shift-Cmd-Enter": "insertLineBefore",
604
    "Cmd-D": "selectNextOccurrence",
605
    "Shift-Cmd-Space": "selectScope",
606
    "Shift-Cmd-M": "selectBetweenBrackets",
607
    "Cmd-M": "goToBracket",
608
    "Cmd-Ctrl-Up": "swapLineUp",
609
    "Cmd-Ctrl-Down": "swapLineDown",
610
    "Cmd-/": "toggleCommentIndented",
611
    "Cmd-J": "joinLines",
612
    "Shift-Cmd-D": "duplicateLine",
613
    "F5": "sortLines",
614
    "Shift-F5": "reverseSortLines",
615
    "Cmd-F5": "sortLinesInsensitive",
616
    "Shift-Cmd-F5": "reverseSortLinesInsensitive",
617
    "F2": "nextBookmark",
618
    "Shift-F2": "prevBookmark",
619
    "Cmd-F2": "toggleBookmark",
620
    "Shift-Cmd-F2": "clearBookmarks",
621
    "Alt-F2": "selectBookmarks",
622
    "Backspace": "smartBackspace",
623
    "Cmd-K Cmd-D": "skipAndSelectNextOccurrence",
624
    "Cmd-K Cmd-K": "delLineRight",
625
    "Cmd-K Cmd-U": "upcaseAtCursor",
626
    "Cmd-K Cmd-L": "downcaseAtCursor",
627
    "Cmd-K Cmd-Space": "setSublimeMark",
628
    "Cmd-K Cmd-A": "selectToSublimeMark",
629
    "Cmd-K Cmd-W": "deleteToSublimeMark",
630
    "Cmd-K Cmd-X": "swapWithSublimeMark",
631
    "Cmd-K Cmd-Y": "sublimeYank",
632
    "Cmd-K Cmd-C": "showInCenter",
633
    "Cmd-K Cmd-G": "clearBookmarks",
634
    "Cmd-K Cmd-Backspace": "delLineLeft",
635
    "Cmd-K Cmd-1": "foldAll",
636
    "Cmd-K Cmd-0": "unfoldAll",
637
    "Cmd-K Cmd-J": "unfoldAll",
638
    "Ctrl-Shift-Up": "addCursorToPrevLine",
639
    "Ctrl-Shift-Down": "addCursorToNextLine",
640
    "Cmd-F3": "findUnder",
641
    "Shift-Cmd-F3": "findUnderPrevious",
642
    "Alt-F3": "findAllUnder",
643
    "Shift-Cmd-[": "fold",
644
    "Shift-Cmd-]": "unfold",
645
    "Cmd-I": "findIncremental",
646
    "Shift-Cmd-I": "findIncrementalReverse",
647
    "Cmd-H": "replace",
648
    "F3": "findNext",
649
    "Shift-F3": "findPrev",
650
    "fallthrough": "macDefault"
651
  };
652
  CodeMirror.normalizeKeyMap(keyMap.macSublime);
653

654
  keyMap.pcSublime = {
655
    "Shift-Tab": "indentLess",
656
    "Shift-Ctrl-K": "deleteLine",
657
    "Alt-Q": "wrapLines",
658
    "Ctrl-T": "transposeChars",
659
    "Alt-Left": "goSubwordLeft",
660
    "Alt-Right": "goSubwordRight",
661
    "Ctrl-Up": "scrollLineUp",
662
    "Ctrl-Down": "scrollLineDown",
663
    "Ctrl-L": "selectLine",
664
    "Shift-Ctrl-L": "splitSelectionByLine",
665
    "Esc": "singleSelectionTop",
666
    "Ctrl-Enter": "insertLineAfter",
667
    "Shift-Ctrl-Enter": "insertLineBefore",
668
    "Ctrl-D": "selectNextOccurrence",
669
    "Shift-Ctrl-Space": "selectScope",
670
    "Shift-Ctrl-M": "selectBetweenBrackets",
671
    "Ctrl-M": "goToBracket",
672
    "Shift-Ctrl-Up": "swapLineUp",
673
    "Shift-Ctrl-Down": "swapLineDown",
674
    "Ctrl-/": "toggleCommentIndented",
675
    "Ctrl-J": "joinLines",
676
    "Shift-Ctrl-D": "duplicateLine",
677
    "F9": "sortLines",
678
    "Shift-F9": "reverseSortLines",
679
    "Ctrl-F9": "sortLinesInsensitive",
680
    "Shift-Ctrl-F9": "reverseSortLinesInsensitive",
681
    "F2": "nextBookmark",
682
    "Shift-F2": "prevBookmark",
683
    "Ctrl-F2": "toggleBookmark",
684
    "Shift-Ctrl-F2": "clearBookmarks",
685
    "Alt-F2": "selectBookmarks",
686
    "Backspace": "smartBackspace",
687
    "Ctrl-K Ctrl-D": "skipAndSelectNextOccurrence",
688
    "Ctrl-K Ctrl-K": "delLineRight",
689
    "Ctrl-K Ctrl-U": "upcaseAtCursor",
690
    "Ctrl-K Ctrl-L": "downcaseAtCursor",
691
    "Ctrl-K Ctrl-Space": "setSublimeMark",
692
    "Ctrl-K Ctrl-A": "selectToSublimeMark",
693
    "Ctrl-K Ctrl-W": "deleteToSublimeMark",
694
    "Ctrl-K Ctrl-X": "swapWithSublimeMark",
695
    "Ctrl-K Ctrl-Y": "sublimeYank",
696
    "Ctrl-K Ctrl-C": "showInCenter",
697
    "Ctrl-K Ctrl-G": "clearBookmarks",
698
    "Ctrl-K Ctrl-Backspace": "delLineLeft",
699
    "Ctrl-K Ctrl-1": "foldAll",
700
    "Ctrl-K Ctrl-0": "unfoldAll",
701
    "Ctrl-K Ctrl-J": "unfoldAll",
702
    "Ctrl-Alt-Up": "addCursorToPrevLine",
703
    "Ctrl-Alt-Down": "addCursorToNextLine",
704
    "Ctrl-F3": "findUnder",
705
    "Shift-Ctrl-F3": "findUnderPrevious",
706
    "Alt-F3": "findAllUnder",
707
    "Shift-Ctrl-[": "fold",
708
    "Shift-Ctrl-]": "unfold",
709
    "Ctrl-I": "findIncremental",
710
    "Shift-Ctrl-I": "findIncrementalReverse",
711
    "Ctrl-H": "replace",
712
    "F3": "findNext",
713
    "Shift-F3": "findPrev",
714
    "fallthrough": "pcDefault"
715
  };
716
  CodeMirror.normalizeKeyMap(keyMap.pcSublime);
717

718
  var mac = keyMap.default == keyMap.macDefault;
719
  keyMap.sublime = mac ? keyMap.macSublime : keyMap.pcSublime;
720
});
721

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.