| 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 |