sublime.js (25450B)
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://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; 26 for (var pos = start.ch, 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 if (state == "in") { 33 if (type != cat) { 34 if (type == "w" && cat == "W" && dir < 0) pos--; 35 if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; } 36 break; 37 } 38 } 39 } 40 return Pos(start.line, pos); 41 } 42 43 function moveSubword(cm, dir) { 44 cm.extendSelectionsBy(function(range) { 45 if (cm.display.shift || cm.doc.extend || range.empty()) 46 return findPosSubword(cm.doc, range.head, dir); 47 else 48 return dir < 0 ? range.from() : range.to(); 49 }); 50 } 51 52 cmds.goSubwordLeft = function(cm) { moveSubword(cm, -1); }; 53 cmds.goSubwordRight = function(cm) { moveSubword(cm, 1); }; 54 55 cmds.scrollLineUp = function(cm) { 56 var info = cm.getScrollInfo(); 57 if (!cm.somethingSelected()) { 58 var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); 59 if (cm.getCursor().line >= visibleBottomLine) 60 cm.execCommand("goLineUp"); 61 } 62 cm.scrollTo(null, info.top - cm.defaultTextHeight()); 63 }; 64 cmds.scrollLineDown = function(cm) { 65 var info = cm.getScrollInfo(); 66 if (!cm.somethingSelected()) { 67 var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; 68 if (cm.getCursor().line <= visibleTopLine) 69 cm.execCommand("goLineDown"); 70 } 71 cm.scrollTo(null, info.top + cm.defaultTextHeight()); 72 }; 73 74 cmds.splitSelectionByLine = function(cm) { 75 var ranges = cm.listSelections(), lineRanges = []; 76 for (var i = 0; i < ranges.length; i++) { 77 var from = ranges[i].from(), to = ranges[i].to(); 78 for (var line = from.line; line <= to.line; ++line) 79 if (!(to.line > from.line && line == to.line && to.ch == 0)) 80 lineRanges.push({anchor: line == from.line ? from : Pos(line, 0), 81 head: line == to.line ? to : Pos(line)}); 82 } 83 cm.setSelections(lineRanges, 0); 84 }; 85 86 cmds.singleSelectionTop = function(cm) { 87 var range = cm.listSelections()[0]; 88 cm.setSelection(range.anchor, range.head, {scroll: false}); 89 }; 90 91 cmds.selectLine = function(cm) { 92 var ranges = cm.listSelections(), extended = []; 93 for (var i = 0; i < ranges.length; i++) { 94 var range = ranges[i]; 95 extended.push({anchor: Pos(range.from().line, 0), 96 head: Pos(range.to().line + 1, 0)}); 97 } 98 cm.setSelections(extended); 99 }; 100 101 function insertLine(cm, above) { 102 if (cm.isReadOnly()) return CodeMirror.Pass 103 cm.operation(function() { 104 var len = cm.listSelections().length, newSelection = [], last = -1; 105 for (var i = 0; i < len; i++) { 106 var head = cm.listSelections()[i].head; 107 if (head.line <= last) continue; 108 var at = Pos(head.line + (above ? 0 : 1), 0); 109 cm.replaceRange("\n", at, null, "+insertLine"); 110 cm.indentLine(at.line, null, true); 111 newSelection.push({head: at, anchor: at}); 112 last = head.line + 1; 113 } 114 cm.setSelections(newSelection); 115 }); 116 cm.execCommand("indentAuto"); 117 } 118 119 cmds.insertLineAfter = function(cm) { return insertLine(cm, false); }; 120 121 cmds.insertLineBefore = function(cm) { return insertLine(cm, true); }; 122 123 function wordAt(cm, pos) { 124 var start = pos.ch, end = start, line = cm.getLine(pos.line); 125 while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start; 126 while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end; 127 return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)}; 128 } 129 130 cmds.selectNextOccurrence = function(cm) { 131 var from = cm.getCursor("from"), to = cm.getCursor("to"); 132 var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel; 133 if (CodeMirror.cmpPos(from, to) == 0) { 134 var word = wordAt(cm, from); 135 if (!word.word) return; 136 cm.setSelection(word.from, word.to); 137 fullWord = true; 138 } else { 139 var text = cm.getRange(from, to); 140 var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; 141 var cur = cm.getSearchCursor(query, to); 142 var found = cur.findNext(); 143 if (!found) { 144 cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); 145 found = cur.findNext(); 146 } 147 if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) 148 return CodeMirror.Pass 149 cm.addSelection(cur.from(), cur.to()); 150 } 151 if (fullWord) 152 cm.state.sublimeFindFullWord = cm.doc.sel; 153 }; 154 155 function addCursorToSelection(cm, dir) { 156 var ranges = cm.listSelections(), newRanges = []; 157 for (var i = 0; i < ranges.length; i++) { 158 var range = ranges[i]; 159 var newAnchor = cm.findPosV(range.anchor, dir, "line"); 160 var newHead = cm.findPosV(range.head, dir, "line"); 161 var newRange = {anchor: newAnchor, head: newHead}; 162 newRanges.push(range); 163 newRanges.push(newRange); 164 } 165 cm.setSelections(newRanges); 166 } 167 cmds.addCursorToPrevLine = function(cm) { addCursorToSelection(cm, -1); }; 168 cmds.addCursorToNextLine = function(cm) { addCursorToSelection(cm, 1); }; 169 170 function isSelectedRange(ranges, from, to) { 171 for (var i = 0; i < ranges.length; i++) 172 if (ranges[i].from() == from && ranges[i].to() == to) return true 173 return false 174 } 175 176 var mirror = "(){}[]"; 177 function selectBetweenBrackets(cm) { 178 var ranges = cm.listSelections(), newRanges = [] 179 for (var i = 0; i < ranges.length; i++) { 180 var range = ranges[i], pos = range.head, opening = cm.scanForBracket(pos, -1); 181 if (!opening) return false; 182 for (;;) { 183 var closing = cm.scanForBracket(pos, 1); 184 if (!closing) return false; 185 if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) { 186 newRanges.push({anchor: Pos(opening.pos.line, opening.pos.ch + 1), 187 head: closing.pos}); 188 break; 189 } 190 pos = Pos(closing.pos.line, closing.pos.ch + 1); 191 } 192 } 193 cm.setSelections(newRanges); 194 return true; 195 } 196 197 cmds.selectScope = function(cm) { 198 selectBetweenBrackets(cm) || cm.execCommand("selectAll"); 199 }; 200 cmds.selectBetweenBrackets = function(cm) { 201 if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; 202 }; 203 204 cmds.goToBracket = function(cm) { 205 cm.extendSelectionsBy(function(range) { 206 var next = cm.scanForBracket(range.head, 1); 207 if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; 208 var prev = cm.scanForBracket(range.head, -1); 209 return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; 210 }); 211 }; 212 213 cmds.swapLineUp = function(cm) { 214 if (cm.isReadOnly()) return CodeMirror.Pass 215 var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; 216 for (var i = 0; i < ranges.length; i++) { 217 var range = ranges[i], from = range.from().line - 1, to = range.to().line; 218 newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), 219 head: Pos(range.head.line - 1, range.head.ch)}); 220 if (range.to().ch == 0 && !range.empty()) --to; 221 if (from > at) linesToMove.push(from, to); 222 else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; 223 at = to; 224 } 225 cm.operation(function() { 226 for (var i = 0; i < linesToMove.length; i += 2) { 227 var from = linesToMove[i], to = linesToMove[i + 1]; 228 var line = cm.getLine(from); 229 cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); 230 if (to > cm.lastLine()) 231 cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); 232 else 233 cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); 234 } 235 cm.setSelections(newSels); 236 cm.scrollIntoView(); 237 }); 238 }; 239 240 cmds.swapLineDown = function(cm) { 241 if (cm.isReadOnly()) return CodeMirror.Pass 242 var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; 243 for (var i = ranges.length - 1; i >= 0; i--) { 244 var range = ranges[i], from = range.to().line + 1, to = range.from().line; 245 if (range.to().ch == 0 && !range.empty()) from--; 246 if (from < at) linesToMove.push(from, to); 247 else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; 248 at = to; 249 } 250 cm.operation(function() { 251 for (var i = linesToMove.length - 2; i >= 0; i -= 2) { 252 var from = linesToMove[i], to = linesToMove[i + 1]; 253 var line = cm.getLine(from); 254 if (from == cm.lastLine()) 255 cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine"); 256 else 257 cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); 258 cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); 259 } 260 cm.scrollIntoView(); 261 }); 262 }; 263 264 cmds.toggleCommentIndented = function(cm) { 265 cm.toggleComment({ indent: true }); 266 } 267 268 cmds.joinLines = function(cm) { 269 var ranges = cm.listSelections(), joined = []; 270 for (var i = 0; i < ranges.length; i++) { 271 var range = ranges[i], from = range.from(); 272 var start = from.line, end = range.to().line; 273 while (i < ranges.length - 1 && ranges[i + 1].from().line == end) 274 end = ranges[++i].to().line; 275 joined.push({start: start, end: end, anchor: !range.empty() && from}); 276 } 277 cm.operation(function() { 278 var offset = 0, ranges = []; 279 for (var i = 0; i < joined.length; i++) { 280 var obj = joined[i]; 281 var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head; 282 for (var line = obj.start; line <= obj.end; line++) { 283 var actual = line - offset; 284 if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1); 285 if (actual < cm.lastLine()) { 286 cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length)); 287 ++offset; 288 } 289 } 290 ranges.push({anchor: anchor || head, head: head}); 291 } 292 cm.setSelections(ranges, 0); 293 }); 294 }; 295 296 cmds.duplicateLine = function(cm) { 297 cm.operation(function() { 298 var rangeCount = cm.listSelections().length; 299 for (var i = 0; i < rangeCount; i++) { 300 var range = cm.listSelections()[i]; 301 if (range.empty()) 302 cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0)); 303 else 304 cm.replaceRange(cm.getRange(range.from(), range.to()), range.from()); 305 } 306 cm.scrollIntoView(); 307 }); 308 }; 309 310 311 function sortLines(cm, caseSensitive) { 312 if (cm.isReadOnly()) return CodeMirror.Pass 313 var ranges = cm.listSelections(), toSort = [], selected; 314 for (var i = 0; i < ranges.length; i++) { 315 var range = ranges[i]; 316 if (range.empty()) continue; 317 var from = range.from().line, to = range.to().line; 318 while (i < ranges.length - 1 && ranges[i + 1].from().line == to) 319 to = ranges[++i].to().line; 320 if (!ranges[i].to().ch) to--; 321 toSort.push(from, to); 322 } 323 if (toSort.length) selected = true; 324 else toSort.push(cm.firstLine(), cm.lastLine()); 325 326 cm.operation(function() { 327 var ranges = []; 328 for (var i = 0; i < toSort.length; i += 2) { 329 var from = toSort[i], to = toSort[i + 1]; 330 var start = Pos(from, 0), end = Pos(to); 331 var lines = cm.getRange(start, end, false); 332 if (caseSensitive) 333 lines.sort(); 334 else 335 lines.sort(function(a, b) { 336 var au = a.toUpperCase(), bu = b.toUpperCase(); 337 if (au != bu) { a = au; b = bu; } 338 return a < b ? -1 : a == b ? 0 : 1; 339 }); 340 cm.replaceRange(lines, start, end); 341 if (selected) ranges.push({anchor: start, head: Pos(to + 1, 0)}); 342 } 343 if (selected) cm.setSelections(ranges, 0); 344 }); 345 } 346 347 cmds.sortLines = function(cm) { sortLines(cm, true); }; 348 cmds.sortLinesInsensitive = function(cm) { sortLines(cm, false); }; 349 350 cmds.nextBookmark = function(cm) { 351 var marks = cm.state.sublimeBookmarks; 352 if (marks) while (marks.length) { 353 var current = marks.shift(); 354 var found = current.find(); 355 if (found) { 356 marks.push(current); 357 return cm.setSelection(found.from, found.to); 358 } 359 } 360 }; 361 362 cmds.prevBookmark = function(cm) { 363 var marks = cm.state.sublimeBookmarks; 364 if (marks) while (marks.length) { 365 marks.unshift(marks.pop()); 366 var found = marks[marks.length - 1].find(); 367 if (!found) 368 marks.pop(); 369 else 370 return cm.setSelection(found.from, found.to); 371 } 372 }; 373 374 cmds.toggleBookmark = function(cm) { 375 var ranges = cm.listSelections(); 376 var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []); 377 for (var i = 0; i < ranges.length; i++) { 378 var from = ranges[i].from(), to = ranges[i].to(); 379 var found = cm.findMarks(from, to); 380 for (var j = 0; j < found.length; j++) { 381 if (found[j].sublimeBookmark) { 382 found[j].clear(); 383 for (var k = 0; k < marks.length; k++) 384 if (marks[k] == found[j]) 385 marks.splice(k--, 1); 386 break; 387 } 388 } 389 if (j == found.length) 390 marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false})); 391 } 392 }; 393 394 cmds.clearBookmarks = function(cm) { 395 var marks = cm.state.sublimeBookmarks; 396 if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); 397 marks.length = 0; 398 }; 399 400 cmds.selectBookmarks = function(cm) { 401 var marks = cm.state.sublimeBookmarks, ranges = []; 402 if (marks) for (var i = 0; i < marks.length; i++) { 403 var found = marks[i].find(); 404 if (!found) 405 marks.splice(i--, 0); 406 else 407 ranges.push({anchor: found.from, head: found.to}); 408 } 409 if (ranges.length) 410 cm.setSelections(ranges, 0); 411 }; 412 413 function modifyWordOrSelection(cm, mod) { 414 cm.operation(function() { 415 var ranges = cm.listSelections(), indices = [], replacements = []; 416 for (var i = 0; i < ranges.length; i++) { 417 var range = ranges[i]; 418 if (range.empty()) { indices.push(i); replacements.push(""); } 419 else replacements.push(mod(cm.getRange(range.from(), range.to()))); 420 } 421 cm.replaceSelections(replacements, "around", "case"); 422 for (var i = indices.length - 1, at; i >= 0; i--) { 423 var range = ranges[indices[i]]; 424 if (at && CodeMirror.cmpPos(range.head, at) > 0) continue; 425 var word = wordAt(cm, range.head); 426 at = word.from; 427 cm.replaceRange(mod(word.word), word.from, word.to); 428 } 429 }); 430 } 431 432 cmds.smartBackspace = function(cm) { 433 if (cm.somethingSelected()) return CodeMirror.Pass; 434 435 cm.operation(function() { 436 var cursors = cm.listSelections(); 437 var indentUnit = cm.getOption("indentUnit"); 438 439 for (var i = cursors.length - 1; i >= 0; i--) { 440 var cursor = cursors[i].head; 441 var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor); 442 var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize")); 443 444 // Delete by one character by default 445 var deletePos = cm.findPosH(cursor, -1, "char", false); 446 447 if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) { 448 var prevIndent = new Pos(cursor.line, 449 CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit)); 450 451 // Smart delete only if we found a valid prevIndent location 452 if (prevIndent.ch != cursor.ch) deletePos = prevIndent; 453 } 454 455 cm.replaceRange("", deletePos, cursor, "+delete"); 456 } 457 }); 458 }; 459 460 cmds.delLineRight = function(cm) { 461 cm.operation(function() { 462 var ranges = cm.listSelections(); 463 for (var i = ranges.length - 1; i >= 0; i--) 464 cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete"); 465 cm.scrollIntoView(); 466 }); 467 }; 468 469 cmds.upcaseAtCursor = function(cm) { 470 modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); 471 }; 472 cmds.downcaseAtCursor = function(cm) { 473 modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); 474 }; 475 476 cmds.setSublimeMark = function(cm) { 477 if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); 478 cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); 479 }; 480 cmds.selectToSublimeMark = function(cm) { 481 var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); 482 if (found) cm.setSelection(cm.getCursor(), found); 483 }; 484 cmds.deleteToSublimeMark = function(cm) { 485 var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); 486 if (found) { 487 var from = cm.getCursor(), to = found; 488 if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; } 489 cm.state.sublimeKilled = cm.getRange(from, to); 490 cm.replaceRange("", from, to); 491 } 492 }; 493 cmds.swapWithSublimeMark = function(cm) { 494 var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); 495 if (found) { 496 cm.state.sublimeMark.clear(); 497 cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); 498 cm.setCursor(found); 499 } 500 }; 501 cmds.sublimeYank = function(cm) { 502 if (cm.state.sublimeKilled != null) 503 cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); 504 }; 505 506 cmds.showInCenter = function(cm) { 507 var pos = cm.cursorCoords(null, "local"); 508 cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); 509 }; 510 511 cmds.selectLinesUpward = function(cm) { 512 cm.operation(function() { 513 var ranges = cm.listSelections(); 514 for (var i = 0; i < ranges.length; i++) { 515 var range = ranges[i]; 516 if (range.head.line > cm.firstLine()) 517 cm.addSelection(Pos(range.head.line - 1, range.head.ch)); 518 } 519 }); 520 }; 521 cmds.selectLinesDownward = function(cm) { 522 cm.operation(function() { 523 var ranges = cm.listSelections(); 524 for (var i = 0; i < ranges.length; i++) { 525 var range = ranges[i]; 526 if (range.head.line < cm.lastLine()) 527 cm.addSelection(Pos(range.head.line + 1, range.head.ch)); 528 } 529 }); 530 }; 531 532 function getTarget(cm) { 533 var from = cm.getCursor("from"), to = cm.getCursor("to"); 534 if (CodeMirror.cmpPos(from, to) == 0) { 535 var word = wordAt(cm, from); 536 if (!word.word) return; 537 from = word.from; 538 to = word.to; 539 } 540 return {from: from, to: to, query: cm.getRange(from, to), word: word}; 541 } 542 543 function findAndGoTo(cm, forward) { 544 var target = getTarget(cm); 545 if (!target) return; 546 var query = target.query; 547 var cur = cm.getSearchCursor(query, forward ? target.to : target.from); 548 549 if (forward ? cur.findNext() : cur.findPrevious()) { 550 cm.setSelection(cur.from(), cur.to()); 551 } else { 552 cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0) 553 : cm.clipPos(Pos(cm.lastLine()))); 554 if (forward ? cur.findNext() : cur.findPrevious()) 555 cm.setSelection(cur.from(), cur.to()); 556 else if (target.word) 557 cm.setSelection(target.from, target.to); 558 } 559 }; 560 cmds.findUnder = function(cm) { findAndGoTo(cm, true); }; 561 cmds.findUnderPrevious = function(cm) { findAndGoTo(cm,false); }; 562 cmds.findAllUnder = function(cm) { 563 var target = getTarget(cm); 564 if (!target) return; 565 var cur = cm.getSearchCursor(target.query); 566 var matches = []; 567 var primaryIndex = -1; 568 while (cur.findNext()) { 569 matches.push({anchor: cur.from(), head: cur.to()}); 570 if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch) 571 primaryIndex++; 572 } 573 cm.setSelections(matches, primaryIndex); 574 }; 575 576 577 var keyMap = CodeMirror.keyMap; 578 keyMap.macSublime = { 579 "Cmd-Left": "goLineStartSmart", 580 "Shift-Tab": "indentLess", 581 "Shift-Ctrl-K": "deleteLine", 582 "Alt-Q": "wrapLines", 583 "Ctrl-Left": "goSubwordLeft", 584 "Ctrl-Right": "goSubwordRight", 585 "Ctrl-Alt-Up": "scrollLineUp", 586 "Ctrl-Alt-Down": "scrollLineDown", 587 "Cmd-L": "selectLine", 588 "Shift-Cmd-L": "splitSelectionByLine", 589 "Esc": "singleSelectionTop", 590 "Cmd-Enter": "insertLineAfter", 591 "Shift-Cmd-Enter": "insertLineBefore", 592 "Cmd-D": "selectNextOccurrence", 593 "Shift-Cmd-Up": "addCursorToPrevLine", 594 "Shift-Cmd-Down": "addCursorToNextLine", 595 "Shift-Cmd-Space": "selectScope", 596 "Shift-Cmd-M": "selectBetweenBrackets", 597 "Cmd-M": "goToBracket", 598 "Cmd-Ctrl-Up": "swapLineUp", 599 "Cmd-Ctrl-Down": "swapLineDown", 600 "Cmd-/": "toggleCommentIndented", 601 "Cmd-J": "joinLines", 602 "Shift-Cmd-D": "duplicateLine", 603 "F9": "sortLines", 604 "Cmd-F9": "sortLinesInsensitive", 605 "F2": "nextBookmark", 606 "Shift-F2": "prevBookmark", 607 "Cmd-F2": "toggleBookmark", 608 "Shift-Cmd-F2": "clearBookmarks", 609 "Alt-F2": "selectBookmarks", 610 "Backspace": "smartBackspace", 611 "Cmd-K Cmd-K": "delLineRight", 612 "Cmd-K Cmd-U": "upcaseAtCursor", 613 "Cmd-K Cmd-L": "downcaseAtCursor", 614 "Cmd-K Cmd-Space": "setSublimeMark", 615 "Cmd-K Cmd-A": "selectToSublimeMark", 616 "Cmd-K Cmd-W": "deleteToSublimeMark", 617 "Cmd-K Cmd-X": "swapWithSublimeMark", 618 "Cmd-K Cmd-Y": "sublimeYank", 619 "Cmd-K Cmd-C": "showInCenter", 620 "Cmd-K Cmd-G": "clearBookmarks", 621 "Cmd-K Cmd-Backspace": "delLineLeft", 622 "Cmd-K Cmd-0": "unfoldAll", 623 "Cmd-K Cmd-J": "unfoldAll", 624 "Ctrl-Shift-Up": "selectLinesUpward", 625 "Ctrl-Shift-Down": "selectLinesDownward", 626 "Cmd-F3": "findUnder", 627 "Shift-Cmd-F3": "findUnderPrevious", 628 "Alt-F3": "findAllUnder", 629 "Shift-Cmd-[": "fold", 630 "Shift-Cmd-]": "unfold", 631 "Cmd-I": "findIncremental", 632 "Shift-Cmd-I": "findIncrementalReverse", 633 "Cmd-H": "replace", 634 "F3": "findNext", 635 "Shift-F3": "findPrev", 636 "fallthrough": "macDefault" 637 }; 638 CodeMirror.normalizeKeyMap(keyMap.macSublime); 639 640 keyMap.pcSublime = { 641 "Shift-Tab": "indentLess", 642 "Shift-Ctrl-K": "deleteLine", 643 "Alt-Q": "wrapLines", 644 "Ctrl-T": "transposeChars", 645 "Alt-Left": "goSubwordLeft", 646 "Alt-Right": "goSubwordRight", 647 "Ctrl-Up": "scrollLineUp", 648 "Ctrl-Down": "scrollLineDown", 649 "Ctrl-L": "selectLine", 650 "Shift-Ctrl-L": "splitSelectionByLine", 651 "Esc": "singleSelectionTop", 652 "Ctrl-Enter": "insertLineAfter", 653 "Shift-Ctrl-Enter": "insertLineBefore", 654 "Ctrl-D": "selectNextOccurrence", 655 "Alt-CtrlUp": "addCursorToPrevLine", 656 "Alt-CtrlDown": "addCursorToNextLine", 657 "Shift-Ctrl-Space": "selectScope", 658 "Shift-Ctrl-M": "selectBetweenBrackets", 659 "Ctrl-M": "goToBracket", 660 "Shift-Ctrl-Up": "swapLineUp", 661 "Shift-Ctrl-Down": "swapLineDown", 662 "Ctrl-/": "toggleCommentIndented", 663 "Ctrl-J": "joinLines", 664 "Shift-Ctrl-D": "duplicateLine", 665 "F9": "sortLines", 666 "Ctrl-F9": "sortLinesInsensitive", 667 "F2": "nextBookmark", 668 "Shift-F2": "prevBookmark", 669 "Ctrl-F2": "toggleBookmark", 670 "Shift-Ctrl-F2": "clearBookmarks", 671 "Alt-F2": "selectBookmarks", 672 "Backspace": "smartBackspace", 673 "Ctrl-K Ctrl-K": "delLineRight", 674 "Ctrl-K Ctrl-U": "upcaseAtCursor", 675 "Ctrl-K Ctrl-L": "downcaseAtCursor", 676 "Ctrl-K Ctrl-Space": "setSublimeMark", 677 "Ctrl-K Ctrl-A": "selectToSublimeMark", 678 "Ctrl-K Ctrl-W": "deleteToSublimeMark", 679 "Ctrl-K Ctrl-X": "swapWithSublimeMark", 680 "Ctrl-K Ctrl-Y": "sublimeYank", 681 "Ctrl-K Ctrl-C": "showInCenter", 682 "Ctrl-K Ctrl-G": "clearBookmarks", 683 "Ctrl-K Ctrl-Backspace": "delLineLeft", 684 "Ctrl-K Ctrl-0": "unfoldAll", 685 "Ctrl-K Ctrl-J": "unfoldAll", 686 "Ctrl-Alt-Up": "selectLinesUpward", 687 "Ctrl-Alt-Down": "selectLinesDownward", 688 "Ctrl-F3": "findUnder", 689 "Shift-Ctrl-F3": "findUnderPrevious", 690 "Alt-F3": "findAllUnder", 691 "Shift-Ctrl-[": "fold", 692 "Shift-Ctrl-]": "unfold", 693 "Ctrl-I": "findIncremental", 694 "Shift-Ctrl-I": "findIncrementalReverse", 695 "Ctrl-H": "replace", 696 "F3": "findNext", 697 "Shift-F3": "findPrev", 698 "fallthrough": "pcDefault" 699 }; 700 CodeMirror.normalizeKeyMap(keyMap.pcSublime); 701 702 var mac = keyMap.default == keyMap.macDefault; 703 keyMap.sublime = mac ? keyMap.macSublime : keyMap.pcSublime; 704 });