2 var ie_lt8
= /MSIE \d/.test(navigator
.userAgent
) &&
3 (document
.documentMode
== null || document
.documentMode
< 8);
5 var Pos
= CodeMirror
.Pos
;
7 var matching
= {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
8 function findMatchingBracket(cm
) {
9 var maxScanLen
= cm
.state
._matchBrackets
.maxScanLineLength
|| 10000;
11 var cur
= cm
.getCursor(), line
= cm
.getLineHandle(cur
.line
), pos
= cur
.ch
- 1;
12 var match
= (pos
>= 0 && matching
[line
.text
.charAt(pos
)]) || matching
[line
.text
.charAt(++pos
)];
13 if (!match
) return null;
14 var forward
= match
.charAt(1) == ">", d
= forward
? 1 : -1;
15 var style
= cm
.getTokenAt(Pos(cur
.line
, pos
+ 1)).type
;
17 var stack
= [line
.text
.charAt(pos
)], re
= /[(){}[\]]/;
18 function scan(line
, lineNo
, start
) {
19 if (!line
.text
) return;
20 var pos
= forward
? 0 : line
.text
.length
- 1, end
= forward
? line
.text
.length
: -1;
21 if (line
.text
.length
> maxScanLen
) return null;
22 var checkTokenStyles
= line
.text
.length
< 1000;
23 if (start
!= null) pos
= start
+ d
;
24 for (; pos
!= end
; pos
+= d
) {
25 var ch
= line
.text
.charAt(pos
);
26 if (re
.test(ch
) && (!checkTokenStyles
|| cm
.getTokenAt(Pos(lineNo
, pos
+ 1)).type
== style
)) {
27 var match
= matching
[ch
];
28 if (match
.charAt(1) == ">" == forward
) stack
.push(ch
);
29 else if (stack
.pop() != match
.charAt(0)) return {pos
: pos
, match
: false};
30 else if (!stack
.length
) return {pos
: pos
, match
: true};
34 for (var i
= cur
.line
, found
, e
= forward
? Math
.min(i
+ 100, cm
.lineCount()) : Math
.max(-1, i
- 100); i
!= e
; i
+=d
) {
35 if (i
== cur
.line
) found
= scan(line
, i
, pos
);
36 else found
= scan(cm
.getLineHandle(i
), i
);
39 return {from: Pos(cur
.line
, pos
), to
: found
&& Pos(i
, found
.pos
), match
: found
&& found
.match
};
42 function matchBrackets(cm
, autoclear
) {
43 // Disable brace matching in long lines, since it'll cause hugely slow updates
44 var maxHighlightLen
= cm
.state
._matchBrackets
.maxHighlightLineLength
|| 1000;
45 var found
= findMatchingBracket(cm
);
46 if (!found
|| cm
.getLine(found
.from.line
).length
> maxHighlightLen
||
47 found
.to
&& cm
.getLine(found
.to
.line
).length
> maxHighlightLen
)
50 var style
= found
.match
? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
51 var one
= cm
.markText(found
.from, Pos(found
.from.line
, found
.from.ch
+ 1), {className
: style
});
52 var two
= found
.to
&& cm
.markText(found
.to
, Pos(found
.to
.line
, found
.to
.ch
+ 1), {className
: style
});
53 // Kludge to work around the IE bug from issue #1193, where text
54 // input stops going to the textare whever this fires.
55 if (ie_lt8
&& cm
.state
.focused
) cm
.display
.input
.focus();
56 var clear = function() {
57 cm
.operation(function() { one
.clear(); two
&& two
.clear(); });
59 if (autoclear
) setTimeout(clear
, 800);
63 var currentlyHighlighted
= null;
64 function doMatchBrackets(cm
) {
65 cm
.operation(function() {
66 if (currentlyHighlighted
) {currentlyHighlighted(); currentlyHighlighted
= null;}
67 if (!cm
.somethingSelected()) currentlyHighlighted
= matchBrackets(cm
, false);
71 CodeMirror
.defineOption("matchBrackets", false, function(cm
, val
, old
) {
72 if (old
&& old
!= CodeMirror
.Init
)
73 cm
.off("cursorActivity", doMatchBrackets
);
75 cm
.state
._matchBrackets
= typeof val
== "object" ? val
: {};
76 cm
.on("cursorActivity", doMatchBrackets
);
80 CodeMirror
.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
81 CodeMirror
.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);});