1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
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
11 })(function(CodeMirror
) {
12 var ie_lt8
= /MSIE \d/.test(navigator
.userAgent
) &&
13 (document
.documentMode
== null || document
.documentMode
< 8);
15 var Pos
= CodeMirror
.Pos
;
17 var matching
= {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
19 function findMatchingBracket(cm
, where
, strict
, config
) {
20 var line
= cm
.getLineHandle(where
.line
), pos
= where
.ch
- 1;
21 var match
= (pos
>= 0 && matching
[line
.text
.charAt(pos
)]) || matching
[line
.text
.charAt(++pos
)];
22 if (!match
) return null;
23 var dir
= match
.charAt(1) == ">" ? 1 : -1;
24 if (strict
&& (dir
> 0) != (pos
== where
.ch
)) return null;
25 var style
= cm
.getTokenTypeAt(Pos(where
.line
, pos
+ 1));
27 var found
= scanForBracket(cm
, Pos(where
.line
, pos
+ (dir
> 0 ? 1 : 0)), dir
, style
|| null, config
);
28 if (found
== null) return null;
29 return {from: Pos(where
.line
, pos
), to
: found
&& found
.pos
,
30 match
: found
&& found
.ch
== match
.charAt(0), forward
: dir
> 0};
33 // bracketRegex is used to specify which type of bracket to scan
34 // should be a regexp, e.g. /[[\]]/
36 // Note: If "where" is on an open bracket, then this bracket is ignored.
38 // Returns false when no bracket was found, null when it reached
39 // maxScanLines and gave up
40 function scanForBracket(cm
, where
, dir
, style
, config
) {
41 var maxScanLen
= (config
&& config
.maxScanLineLength
) || 10000;
42 var maxScanLines
= (config
&& config
.maxScanLines
) || 1000;
45 var re
= config
&& config
.bracketRegex
? config
.bracketRegex
: /[(){}[\]]/;
46 var lineEnd
= dir
> 0 ? Math
.min(where
.line
+ maxScanLines
, cm
.lastLine() + 1)
47 : Math
.max(cm
.firstLine() - 1, where
.line
- maxScanLines
);
48 for (var lineNo
= where
.line
; lineNo
!= lineEnd
; lineNo
+= dir
) {
49 var line
= cm
.getLine(lineNo
);
51 var pos
= dir
> 0 ? 0 : line
.length
- 1, end
= dir
> 0 ? line
.length
: -1;
52 if (line
.length
> maxScanLen
) continue;
53 if (lineNo
== where
.line
) pos
= where
.ch
- (dir
< 0 ? 1 : 0);
54 for (; pos
!= end
; pos
+= dir
) {
55 var ch
= line
.charAt(pos
);
56 if (re
.test(ch
) && (style
=== undefined || cm
.getTokenTypeAt(Pos(lineNo
, pos
+ 1)) == style
)) {
57 var match
= matching
[ch
];
58 if ((match
.charAt(1) == ">") == (dir
> 0)) stack
.push(ch
);
59 else if (!stack
.length
) return {pos
: Pos(lineNo
, pos
), ch
: ch
};
64 return lineNo
- dir
== (dir
> 0 ? cm
.lastLine() : cm
.firstLine()) ? false : null;
67 function matchBrackets(cm
, autoclear
, config
) {
68 // Disable brace matching in long lines, since it'll cause hugely slow updates
69 var maxHighlightLen
= cm
.state
.matchBrackets
.maxHighlightLineLength
|| 1000;
70 var marks
= [], ranges
= cm
.listSelections();
71 for (var i
= 0; i
< ranges
.length
; i
++) {
72 var match
= ranges
[i
].empty() && findMatchingBracket(cm
, ranges
[i
].head
, false, config
);
73 if (match
&& cm
.getLine(match
.from.line
).length
<= maxHighlightLen
) {
74 var style
= match
.match
? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
75 marks
.push(cm
.markText(match
.from, Pos(match
.from.line
, match
.from.ch
+ 1), {className
: style
}));
76 if (match
.to
&& cm
.getLine(match
.to
.line
).length
<= maxHighlightLen
)
77 marks
.push(cm
.markText(match
.to
, Pos(match
.to
.line
, match
.to
.ch
+ 1), {className
: style
}));
82 // Kludge to work around the IE bug from issue #1193, where text
83 // input stops going to the textare whever this fires.
84 if (ie_lt8
&& cm
.state
.focused
) cm
.display
.input
.focus();
86 var clear = function() {
87 cm
.operation(function() {
88 for (var i
= 0; i
< marks
.length
; i
++) marks
[i
].clear();
91 if (autoclear
) setTimeout(clear
, 800);
96 var currentlyHighlighted
= null;
97 function doMatchBrackets(cm
) {
98 cm
.operation(function() {
99 if (currentlyHighlighted
) {currentlyHighlighted(); currentlyHighlighted
= null;}
100 currentlyHighlighted
= matchBrackets(cm
, false, cm
.state
.matchBrackets
);
104 CodeMirror
.defineOption("matchBrackets", false, function(cm
, val
, old
) {
105 if (old
&& old
!= CodeMirror
.Init
)
106 cm
.off("cursorActivity", doMatchBrackets
);
108 cm
.state
.matchBrackets
= typeof val
== "object" ? val
: {};
109 cm
.on("cursorActivity", doMatchBrackets
);
113 CodeMirror
.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
114 CodeMirror
.defineExtension("findMatchingBracket", function(pos
, strict
, config
){
115 return findMatchingBracket(this, pos
, strict
, config
);
117 CodeMirror
.defineExtension("scanForBracket", function(pos
, dir
, style
, config
){
118 return scanForBracket(this, pos
, dir
, style
, config
);