Commit | Line | Data |
---|---|---|
837afb80 TD |
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) { | |
77b7b761 | 9 | var DEFAULT_BRACKETS = "()[]{}''\"\""; |
837afb80 | 10 | var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; |
77b7b761 TD |
11 | var SPACE_CHAR_REGEX = /\s/; |
12 | ||
13 | CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { | |
837afb80 | 14 | if (old != CodeMirror.Init && old) |
77b7b761 | 15 | cm.removeKeyMap("autoCloseBrackets"); |
837afb80 TD |
16 | if (!val) return; |
17 | var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER; | |
18 | if (typeof val == "string") pairs = val; | |
19 | else if (typeof val == "object") { | |
20 | if (val.pairs != null) pairs = val.pairs; | |
21 | if (val.explode != null) explode = val.explode; | |
22 | } | |
23 | var map = buildKeymap(pairs); | |
24 | if (explode) map.Enter = buildExplodeHandler(explode); | |
25 | cm.addKeyMap(map); | |
77b7b761 TD |
26 | }); |
27 | ||
837afb80 TD |
28 | function charsAround(cm, pos) { |
29 | var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1), | |
30 | CodeMirror.Pos(pos.line, pos.ch + 1)); | |
31 | return str.length == 2 ? str : null; | |
32 | } | |
33 | ||
77b7b761 TD |
34 | function buildKeymap(pairs) { |
35 | var map = { | |
36 | name : "autoCloseBrackets", | |
37 | Backspace: function(cm) { | |
837afb80 TD |
38 | if (cm.getOption("disableInput")) return CodeMirror.Pass; |
39 | var ranges = cm.listSelections(); | |
40 | for (var i = 0; i < ranges.length; i++) { | |
41 | if (!ranges[i].empty()) return CodeMirror.Pass; | |
42 | var around = charsAround(cm, ranges[i].head); | |
43 | if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; | |
44 | } | |
45 | for (var i = ranges.length - 1; i >= 0; i--) { | |
46 | var cur = ranges[i].head; | |
77b7b761 | 47 | cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1)); |
837afb80 | 48 | } |
77b7b761 TD |
49 | } |
50 | }; | |
51 | var closingBrackets = ""; | |
52 | for (var i = 0; i < pairs.length; i += 2) (function(left, right) { | |
53 | if (left != right) closingBrackets += right; | |
77b7b761 | 54 | map["'" + left + "'"] = function(cm) { |
837afb80 TD |
55 | if (cm.getOption("disableInput")) return CodeMirror.Pass; |
56 | var ranges = cm.listSelections(), type, next; | |
57 | for (var i = 0; i < ranges.length; i++) { | |
58 | var range = ranges[i], cur = range.head, curType; | |
59 | if (left == "'" && cm.getTokenTypeAt(cur) == "comment") | |
60 | return CodeMirror.Pass; | |
61 | var next = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1)); | |
62 | if (!range.empty()) | |
63 | curType = "surround"; | |
64 | else if (left == right && next == right) | |
65 | curType = "skip"; | |
66 | else if (left == right && CodeMirror.isWordChar(next)) | |
67 | return CodeMirror.Pass; | |
68 | else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) | |
69 | curType = "both"; | |
70 | else | |
71 | return CodeMirror.Pass; | |
72 | if (!type) type = curType; | |
73 | else if (type != curType) return CodeMirror.Pass; | |
74 | } | |
75 | ||
76 | if (type == "skip") { | |
77 | cm.execCommand("goCharRight"); | |
78 | } else if (type == "surround") { | |
79 | var sels = cm.getSelections(); | |
80 | for (var i = 0; i < sels.length; i++) | |
81 | sels[i] = left + sels[i] + right; | |
82 | cm.replaceSelections(sels, "around"); | |
83 | } else if (type == "both") { | |
84 | cm.replaceSelection(left + right, null); | |
85 | cm.execCommand("goCharLeft"); | |
86 | } | |
87 | }; | |
88 | if (left != right) map["'" + right + "'"] = function(cm) { | |
89 | var ranges = cm.listSelections(); | |
90 | for (var i = 0; i < ranges.length; i++) { | |
91 | var range = ranges[i]; | |
92 | if (!range.empty() || | |
93 | cm.getRange(range.head, CodeMirror.Pos(range.head.line, range.head.ch + 1)) != right) | |
94 | return CodeMirror.Pass; | |
95 | } | |
96 | cm.execCommand("goCharRight"); | |
77b7b761 | 97 | }; |
77b7b761 TD |
98 | })(pairs.charAt(i), pairs.charAt(i + 1)); |
99 | return map; | |
100 | } | |
837afb80 TD |
101 | |
102 | function buildExplodeHandler(pairs) { | |
103 | return function(cm) { | |
104 | if (cm.getOption("disableInput")) return CodeMirror.Pass; | |
105 | var ranges = cm.listSelections(); | |
106 | for (var i = 0; i < ranges.length; i++) { | |
107 | if (!ranges[i].empty()) return CodeMirror.Pass; | |
108 | var around = charsAround(cm, ranges[i].head); | |
109 | if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; | |
110 | } | |
111 | cm.operation(function() { | |
112 | cm.replaceSelection("\n\n", null); | |
113 | cm.execCommand("goCharLeft"); | |
114 | ranges = cm.listSelections(); | |
115 | for (var i = 0; i < ranges.length; i++) { | |
116 | var line = ranges[i].head.line; | |
117 | cm.indentLine(line, null, true); | |
118 | cm.indentLine(line + 1, null, true); | |
119 | } | |
120 | }); | |
121 | }; | |
122 | } | |
123 | }); |