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 ie_lt8 = /MSIE \d/.test(navigator.userAgent) && | 9 var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && |
3 (document.documentMode == null || document.documentMode < 8); | 10 (document.documentMode == null || document.documentMode < 8); |
4 | 11 |
5 var Pos = CodeMirror.Pos; | 12 var Pos = CodeMirror.Pos; |
6 | 13 |
7 var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{
<"}; | 14 var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{
<"}; |
8 function findMatchingBracket(cm, where, strict) { | |
9 var state = cm.state.matchBrackets; | |
10 var maxScanLen = (state && state.maxScanLineLength) || 10000; | |
11 var maxScanLines = (state && state.maxScanLines) || 100; | |
12 | 15 |
13 var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos =
cur.ch - 1; | 16 function findMatchingBracket(cm, where, strict, config) { |
| 17 var line = cm.getLineHandle(where.line), pos = where.ch - 1; |
14 var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.t
ext.charAt(++pos)]; | 18 var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.t
ext.charAt(++pos)]; |
15 if (!match) return null; | 19 if (!match) return null; |
16 var forward = match.charAt(1) == ">", d = forward ? 1 : -1; | 20 var dir = match.charAt(1) == ">" ? 1 : -1; |
17 if (strict && forward != (pos == cur.ch)) return null; | 21 if (strict && (dir > 0) != (pos == where.ch)) return null; |
18 var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1)); | 22 var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); |
19 | 23 |
20 var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; | 24 var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir
, style || null, config); |
21 function scan(line, lineNo, start) { | 25 return {from: Pos(where.line, pos), to: found && found.pos, |
22 if (!line.text) return; | 26 match: found && found.ch == match.charAt(0), forward: dir > 0}; |
23 var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.le
ngth : -1; | 27 } |
24 if (line.text.length > maxScanLen) return null; | 28 |
25 if (start != null) pos = start + d; | 29 // bracketRegex is used to specify which type of bracket to scan |
26 for (; pos != end; pos += d) { | 30 // should be a regexp, e.g. /[[\]]/ |
27 var ch = line.text.charAt(pos); | 31 // |
28 if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) { | 32 // Note: If "where" is on an open bracket, then this bracket is ignored. |
| 33 function scanForBracket(cm, where, dir, style, config) { |
| 34 var maxScanLen = (config && config.maxScanLineLength) || 10000; |
| 35 var maxScanLines = (config && config.maxScanLines) || 500; |
| 36 |
| 37 var stack = []; |
| 38 var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; |
| 39 var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() +
1) |
| 40 : Math.max(cm.firstLine() - 1, where.line - maxScanLin
es); |
| 41 for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { |
| 42 var line = cm.getLine(lineNo); |
| 43 if (!line) continue; |
| 44 var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; |
| 45 if (line.length > maxScanLen) continue; |
| 46 if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); |
| 47 for (; pos != end; pos += dir) { |
| 48 var ch = line.charAt(pos); |
| 49 if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo,
pos + 1)) == style)) { |
29 var match = matching[ch]; | 50 var match = matching[ch]; |
30 if (match.charAt(1) == ">" == forward) stack.push(ch); | 51 if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); |
31 else if (stack.pop() != match.charAt(0)) return {pos: pos, match: fals
e}; | 52 else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; |
32 else if (!stack.length) return {pos: pos, match: true}; | 53 else stack.pop(); |
33 } | 54 } |
34 } | 55 } |
35 } | 56 } |
36 for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.li
neCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) { | |
37 if (i == cur.line) found = scan(line, i, pos); | |
38 else found = scan(cm.getLineHandle(i), i); | |
39 if (found) break; | |
40 } | |
41 return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos), | |
42 match: found && found.match, forward: forward}; | |
43 } | 57 } |
44 | 58 |
45 function matchBrackets(cm, autoclear) { | 59 function matchBrackets(cm, autoclear, config) { |
46 // Disable brace matching in long lines, since it'll cause hugely slow updat
es | 60 // Disable brace matching in long lines, since it'll cause hugely slow updat
es |
47 var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; | 61 var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; |
48 var found = findMatchingBracket(cm); | 62 var marks = [], ranges = cm.listSelections(); |
49 if (!found || cm.getLine(found.from.line).length > maxHighlightLen || | 63 for (var i = 0; i < ranges.length; i++) { |
50 found.to && cm.getLine(found.to.line).length > maxHighlightLen) | 64 var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, f
alse, config); |
51 return; | 65 if (match && cm.getLine(match.from.line).length <= maxHighlightLen && |
| 66 match.to && cm.getLine(match.to.line).length <= maxHighlightLen) { |
| 67 var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-non
matchingbracket"; |
| 68 marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch +
1), {className: style})); |
| 69 if (match.to) |
| 70 marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1),
{className: style})); |
| 71 } |
| 72 } |
52 | 73 |
53 var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatc
hingbracket"; | 74 if (marks.length) { |
54 var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {
className: style}); | 75 // Kludge to work around the IE bug from issue #1193, where text |
55 var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch +
1), {className: style}); | 76 // input stops going to the textare whever this fires. |
56 // Kludge to work around the IE bug from issue #1193, where text | 77 if (ie_lt8 && cm.state.focused) cm.display.input.focus(); |
57 // input stops going to the textare whever this fires. | 78 |
58 if (ie_lt8 && cm.state.focused) cm.display.input.focus(); | 79 var clear = function() { |
59 var clear = function() { | 80 cm.operation(function() { |
60 cm.operation(function() { one.clear(); two && two.clear(); }); | 81 for (var i = 0; i < marks.length; i++) marks[i].clear(); |
61 }; | 82 }); |
62 if (autoclear) setTimeout(clear, 800); | 83 }; |
63 else return clear; | 84 if (autoclear) setTimeout(clear, 800); |
| 85 else return clear; |
| 86 } |
64 } | 87 } |
65 | 88 |
66 var currentlyHighlighted = null; | 89 var currentlyHighlighted = null; |
67 function doMatchBrackets(cm) { | 90 function doMatchBrackets(cm) { |
68 cm.operation(function() { | 91 cm.operation(function() { |
69 if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted =
null;} | 92 if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted =
null;} |
70 if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, fals
e); | 93 currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); |
71 }); | 94 }); |
72 } | 95 } |
73 | 96 |
74 CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { | 97 CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { |
75 if (old && old != CodeMirror.Init) | 98 if (old && old != CodeMirror.Init) |
76 cm.off("cursorActivity", doMatchBrackets); | 99 cm.off("cursorActivity", doMatchBrackets); |
77 if (val) { | 100 if (val) { |
78 cm.state.matchBrackets = typeof val == "object" ? val : {}; | 101 cm.state.matchBrackets = typeof val == "object" ? val : {}; |
79 cm.on("cursorActivity", doMatchBrackets); | 102 cm.on("cursorActivity", doMatchBrackets); |
80 } | 103 } |
81 }); | 104 }); |
82 | 105 |
83 CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, tr
ue);}); | 106 CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, tr
ue);}); |
84 CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){ | 107 CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config
){ |
85 return findMatchingBracket(this, pos, strict); | 108 return findMatchingBracket(this, pos, strict, config); |
86 }); | 109 }); |
87 })(); | 110 CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config)
{ |
| 111 return scanForBracket(this, pos, dir, style, config); |
| 112 }); |
| 113 }); |
OLD | NEW |