OLD | NEW |
1 (function() { | 1 (function(mod) { |
| 2 if (typeof exports == "object" && typeof module == "object") // CommonJS |
| 3 mod(require("../../lib/codemirror")); |
| 4 else if (typeof define == "function" && define.amd) // AMD |
| 5 define(["../../lib/codemirror"], mod); |
| 6 else // Plain browser env |
| 7 mod(CodeMirror); |
| 8 })(function(CodeMirror) { |
2 var DEFAULT_BRACKETS = "()[]{}''\"\""; | 9 var DEFAULT_BRACKETS = "()[]{}''\"\""; |
3 var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; | 10 var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; |
4 var SPACE_CHAR_REGEX = /\s/; | 11 var SPACE_CHAR_REGEX = /\s/; |
5 | 12 |
| 13 var Pos = CodeMirror.Pos; |
| 14 |
6 CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { | 15 CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { |
7 if (old != CodeMirror.Init && old) | 16 if (old != CodeMirror.Init && old) |
8 cm.removeKeyMap("autoCloseBrackets"); | 17 cm.removeKeyMap("autoCloseBrackets"); |
9 if (!val) return; | 18 if (!val) return; |
10 var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER; | 19 var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER; |
11 if (typeof val == "string") pairs = val; | 20 if (typeof val == "string") pairs = val; |
12 else if (typeof val == "object") { | 21 else if (typeof val == "object") { |
13 if (val.pairs != null) pairs = val.pairs; | 22 if (val.pairs != null) pairs = val.pairs; |
14 if (val.explode != null) explode = val.explode; | 23 if (val.explode != null) explode = val.explode; |
15 } | 24 } |
16 var map = buildKeymap(pairs); | 25 var map = buildKeymap(pairs); |
17 if (explode) map.Enter = buildExplodeHandler(explode); | 26 if (explode) map.Enter = buildExplodeHandler(explode); |
18 cm.addKeyMap(map); | 27 cm.addKeyMap(map); |
19 }); | 28 }); |
20 | 29 |
21 function charsAround(cm, pos) { | 30 function charsAround(cm, pos) { |
22 var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1), | 31 var str = cm.getRange(Pos(pos.line, pos.ch - 1), |
23 CodeMirror.Pos(pos.line, pos.ch + 1)); | 32 Pos(pos.line, pos.ch + 1)); |
24 return str.length == 2 ? str : null; | 33 return str.length == 2 ? str : null; |
25 } | 34 } |
26 | 35 |
27 function buildKeymap(pairs) { | 36 function buildKeymap(pairs) { |
28 var map = { | 37 var map = { |
29 name : "autoCloseBrackets", | 38 name : "autoCloseBrackets", |
30 Backspace: function(cm) { | 39 Backspace: function(cm) { |
31 if (cm.somethingSelected()) return CodeMirror.Pass; | 40 if (cm.getOption("disableInput")) return CodeMirror.Pass; |
32 var cur = cm.getCursor(), around = charsAround(cm, cur); | 41 var ranges = cm.listSelections(); |
33 if (around && pairs.indexOf(around) % 2 == 0) | 42 for (var i = 0; i < ranges.length; i++) { |
34 cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.P
os(cur.line, cur.ch + 1)); | 43 if (!ranges[i].empty()) return CodeMirror.Pass; |
35 else | 44 var around = charsAround(cm, ranges[i].head); |
36 return CodeMirror.Pass; | 45 if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; |
| 46 } |
| 47 for (var i = ranges.length - 1; i >= 0; i--) { |
| 48 var cur = ranges[i].head; |
| 49 cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch +
1)); |
| 50 } |
37 } | 51 } |
38 }; | 52 }; |
39 var closingBrackets = ""; | 53 var closingBrackets = ""; |
40 for (var i = 0; i < pairs.length; i += 2) (function(left, right) { | 54 for (var i = 0; i < pairs.length; i += 2) (function(left, right) { |
41 if (left != right) closingBrackets += right; | 55 if (left != right) closingBrackets += right; |
42 function surround(cm) { | |
43 var selection = cm.getSelection(); | |
44 cm.replaceSelection(left + selection + right); | |
45 } | |
46 function maybeOverwrite(cm) { | |
47 var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.li
ne, cur.ch + 1)); | |
48 if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass; | |
49 else cm.execCommand("goCharRight"); | |
50 } | |
51 map["'" + left + "'"] = function(cm) { | 56 map["'" + left + "'"] = function(cm) { |
52 if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment") | 57 if (cm.getOption("disableInput")) return CodeMirror.Pass; |
53 return CodeMirror.Pass; | 58 var ranges = cm.listSelections(), type, next; |
54 if (cm.somethingSelected()) return surround(cm); | 59 for (var i = 0; i < ranges.length; i++) { |
55 if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return; | 60 var range = ranges[i], cur = range.head, curType; |
56 var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1); | 61 if (left == "'" && cm.getTokenTypeAt(cur) == "comment") |
57 var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar
= cur.ch > 0 ? line.charAt(cur.ch - 1) : ""; | 62 return CodeMirror.Pass; |
58 if (left == right && CodeMirror.isWordChar(curChar)) | 63 var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); |
59 return CodeMirror.Pass; | 64 if (!range.empty()) |
60 if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || S
PACE_CHAR_REGEX.test(nextChar)) | 65 curType = "surround"; |
61 cm.replaceSelection(left + right, {head: ahead, anchor: ahead}); | 66 else if (left == right && next == right) { |
62 else | 67 if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + lef
t) |
63 return CodeMirror.Pass; | 68 curType = "skipThree"; |
| 69 else |
| 70 curType = "skip"; |
| 71 } else if (left == right && cur.ch > 1 && |
| 72 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left) |
| 73 curType = "addFour"; |
| 74 else if (left == right && CodeMirror.isWordChar(next)) |
| 75 return CodeMirror.Pass; |
| 76 else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.inde
xOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) |
| 77 curType = "both"; |
| 78 else |
| 79 return CodeMirror.Pass; |
| 80 if (!type) type = curType; |
| 81 else if (type != curType) return CodeMirror.Pass; |
| 82 } |
| 83 |
| 84 cm.operation(function() { |
| 85 if (type == "skip") { |
| 86 cm.execCommand("goCharRight"); |
| 87 } else if (type == "skipThree") { |
| 88 for (var i = 0; i < 3; i++) |
| 89 cm.execCommand("goCharRight"); |
| 90 } else if (type == "surround") { |
| 91 var sels = cm.getSelections(); |
| 92 for (var i = 0; i < sels.length; i++) |
| 93 sels[i] = left + sels[i] + right; |
| 94 cm.replaceSelections(sels, "around"); |
| 95 } else if (type == "both") { |
| 96 cm.replaceSelection(left + right, null); |
| 97 cm.execCommand("goCharLeft"); |
| 98 } else if (type == "addFour") { |
| 99 cm.replaceSelection(left + left + left + left, "before"); |
| 100 cm.execCommand("goCharRight"); |
| 101 } |
| 102 }); |
64 }; | 103 }; |
65 if (left != right) map["'" + right + "'"] = maybeOverwrite; | 104 if (left != right) map["'" + right + "'"] = function(cm) { |
| 105 var ranges = cm.listSelections(); |
| 106 for (var i = 0; i < ranges.length; i++) { |
| 107 var range = ranges[i]; |
| 108 if (!range.empty() || |
| 109 cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) !
= right) |
| 110 return CodeMirror.Pass; |
| 111 } |
| 112 cm.execCommand("goCharRight"); |
| 113 }; |
66 })(pairs.charAt(i), pairs.charAt(i + 1)); | 114 })(pairs.charAt(i), pairs.charAt(i + 1)); |
67 return map; | 115 return map; |
68 } | 116 } |
69 | 117 |
70 function buildExplodeHandler(pairs) { | 118 function buildExplodeHandler(pairs) { |
71 return function(cm) { | 119 return function(cm) { |
72 var cur = cm.getCursor(), around = charsAround(cm, cur); | 120 if (cm.getOption("disableInput")) return CodeMirror.Pass; |
73 if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; | 121 var ranges = cm.listSelections(); |
| 122 for (var i = 0; i < ranges.length; i++) { |
| 123 if (!ranges[i].empty()) return CodeMirror.Pass; |
| 124 var around = charsAround(cm, ranges[i].head); |
| 125 if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; |
| 126 } |
74 cm.operation(function() { | 127 cm.operation(function() { |
75 var newPos = CodeMirror.Pos(cur.line + 1, 0); | 128 cm.replaceSelection("\n\n", null); |
76 cm.replaceSelection("\n\n", {anchor: newPos, head: newPos}, "+input"); | 129 cm.execCommand("goCharLeft"); |
77 cm.indentLine(cur.line + 1, null, true); | 130 ranges = cm.listSelections(); |
78 cm.indentLine(cur.line + 2, null, true); | 131 for (var i = 0; i < ranges.length; i++) { |
| 132 var line = ranges[i].head.line; |
| 133 cm.indentLine(line, null, true); |
| 134 cm.indentLine(line + 1, null, true); |
| 135 } |
79 }); | 136 }); |
80 }; | 137 }; |
81 } | 138 } |
82 })(); | 139 }); |
OLD | NEW |