Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / cm / closebrackets.js
blob83d4229f47b446824a38b0e9c658744c5cfaf7d3
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 var DEFAULT_BRACKETS = "()[]{}''\"\"";
13 var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
14 var SPACE_CHAR_REGEX = /\s/;
16 var Pos = CodeMirror.Pos;
18 CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
19 if (old != CodeMirror.Init && old)
20 cm.removeKeyMap("autoCloseBrackets");
21 if (!val) return;
22 var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
23 if (typeof val == "string") pairs = val;
24 else if (typeof val == "object") {
25 if (val.pairs != null) pairs = val.pairs;
26 if (val.explode != null) explode = val.explode;
28 var map = buildKeymap(pairs);
29 if (explode) map.Enter = buildExplodeHandler(explode);
30 cm.addKeyMap(map);
31 });
33 function charsAround(cm, pos) {
34 var str = cm.getRange(Pos(pos.line, pos.ch - 1),
35 Pos(pos.line, pos.ch + 1));
36 return str.length == 2 ? str : null;
39 function buildKeymap(pairs) {
40 var map = {
41 name : "autoCloseBrackets",
42 Backspace: function(cm) {
43 if (cm.getOption("disableInput")) return CodeMirror.Pass;
44 var ranges = cm.listSelections();
45 for (var i = 0; i < ranges.length; i++) {
46 if (!ranges[i].empty()) return CodeMirror.Pass;
47 var around = charsAround(cm, ranges[i].head);
48 if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
50 for (var i = ranges.length - 1; i >= 0; i--) {
51 var cur = ranges[i].head;
52 cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
56 var closingBrackets = "";
57 for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
58 if (left != right) closingBrackets += right;
59 map["'" + left + "'"] = function(cm) {
60 if (cm.getOption("disableInput")) return CodeMirror.Pass;
61 var ranges = cm.listSelections(), type, next;
62 for (var i = 0; i < ranges.length; i++) {
63 var range = ranges[i], cur = range.head, curType;
64 if (left == "'" && cm.getTokenTypeAt(cur) == "comment")
65 return CodeMirror.Pass;
66 var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
67 if (!range.empty())
68 curType = "surround";
69 else if (left == right && next == right) {
70 if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
71 curType = "skipThree";
72 else
73 curType = "skip";
74 } else if (left == right && cur.ch > 1 &&
75 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
76 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left))
77 curType = "addFour";
78 else if (left == right && CodeMirror.isWordChar(next))
79 return CodeMirror.Pass;
80 else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next))
81 curType = "both";
82 else
83 return CodeMirror.Pass;
84 if (!type) type = curType;
85 else if (type != curType) return CodeMirror.Pass;
88 cm.operation(function() {
89 if (type == "skip") {
90 cm.execCommand("goCharRight");
91 } else if (type == "skipThree") {
92 for (var i = 0; i < 3; i++)
93 cm.execCommand("goCharRight");
94 } else if (type == "surround") {
95 var sels = cm.getSelections();
96 for (var i = 0; i < sels.length; i++)
97 sels[i] = left + sels[i] + right;
98 cm.replaceSelections(sels, "around");
99 } else if (type == "both") {
100 cm.replaceSelection(left + right, null);
101 cm.execCommand("goCharLeft");
102 } else if (type == "addFour") {
103 cm.replaceSelection(left + left + left + left, "before");
104 cm.execCommand("goCharRight");
108 if (left != right) map["'" + right + "'"] = function(cm) {
109 var ranges = cm.listSelections();
110 for (var i = 0; i < ranges.length; i++) {
111 var range = ranges[i];
112 if (!range.empty() ||
113 cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
114 return CodeMirror.Pass;
116 cm.execCommand("goCharRight");
118 })(pairs.charAt(i), pairs.charAt(i + 1));
119 return map;
122 function buildExplodeHandler(pairs) {
123 return function(cm) {
124 if (cm.getOption("disableInput")) return CodeMirror.Pass;
125 var ranges = cm.listSelections();
126 for (var i = 0; i < ranges.length; i++) {
127 if (!ranges[i].empty()) return CodeMirror.Pass;
128 var around = charsAround(cm, ranges[i].head);
129 if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
131 cm.operation(function() {
132 cm.replaceSelection("\n\n", null);
133 cm.execCommand("goCharLeft");
134 ranges = cm.listSelections();
135 for (var i = 0; i < ranges.length; i++) {
136 var line = ranges[i].head.line;
137 cm.indentLine(line, null, true);
138 cm.indentLine(line + 1, null, true);