openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

matchbrackets.min.js (6058B)


      1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
      2 // Distributed under an MIT license: http://codemirror.net/LICENSE
      3 
      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 ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
     13     (document.documentMode == null || document.documentMode < 8);
     14 
     15   var Pos = CodeMirror.Pos;
     16 
     17   var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
     18 
     19   function findMatchingBracket(cm, where, config) {
     20     var line = cm.getLineHandle(where.line), pos = where.ch - 1;
     21     var afterCursor = config && config.afterCursor
     22     if (afterCursor == null)
     23       afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className)
     24 
     25     // A cursor is defined as between two characters, but in in vim command mode
     26     // (i.e. not insert mode), the cursor is visually represented as a
     27     // highlighted box on top of the 2nd character. Otherwise, we allow matches
     28     // from before or after the cursor.
     29     var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) ||
     30         matching[line.text.charAt(++pos)];
     31     if (!match) return null;
     32     var dir = match.charAt(1) == ">" ? 1 : -1;
     33     if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
     34     var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
     35 
     36     var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
     37     if (found == null) return null;
     38     return {from: Pos(where.line, pos), to: found && found.pos,
     39             match: found && found.ch == match.charAt(0), forward: dir > 0};
     40   }
     41 
     42   // bracketRegex is used to specify which type of bracket to scan
     43   // should be a regexp, e.g. /[[\]]/
     44   //
     45   // Note: If "where" is on an open bracket, then this bracket is ignored.
     46   //
     47   // Returns false when no bracket was found, null when it reached
     48   // maxScanLines and gave up
     49   function scanForBracket(cm, where, dir, style, config) {
     50     var maxScanLen = (config && config.maxScanLineLength) || 10000;
     51     var maxScanLines = (config && config.maxScanLines) || 1000;
     52 
     53     var stack = [];
     54     var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
     55     var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
     56                           : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
     57     for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
     58       var line = cm.getLine(lineNo);
     59       if (!line) continue;
     60       var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
     61       if (line.length > maxScanLen) continue;
     62       if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
     63       for (; pos != end; pos += dir) {
     64         var ch = line.charAt(pos);
     65         if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
     66           var match = matching[ch];
     67           if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
     68           else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
     69           else stack.pop();
     70         }
     71       }
     72     }
     73     return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
     74   }
     75 
     76   function matchBrackets(cm, autoclear, config) {
     77     // Disable brace matching in long lines, since it'll cause hugely slow updates
     78     var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
     79     var marks = [], ranges = cm.listSelections();
     80     for (var i = 0; i < ranges.length; i++) {
     81       var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
     82       if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
     83         var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
     84         marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
     85         if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
     86           marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
     87       }
     88     }
     89 
     90     if (marks.length) {
     91       // Kludge to work around the IE bug from issue #1193, where text
     92       // input stops going to the textare whever this fires.
     93       if (ie_lt8 && cm.state.focused) cm.focus();
     94 
     95       var clear = function() {
     96         cm.operation(function() {
     97           for (var i = 0; i < marks.length; i++) marks[i].clear();
     98         });
     99       };
    100       if (autoclear) setTimeout(clear, 800);
    101       else return clear;
    102     }
    103   }
    104 
    105   var currentlyHighlighted = null;
    106   function doMatchBrackets(cm) {
    107     cm.operation(function() {
    108       if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
    109       currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
    110     });
    111   }
    112 
    113   CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
    114     if (old && old != CodeMirror.Init) {
    115       cm.off("cursorActivity", doMatchBrackets);
    116       if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
    117     }
    118     if (val) {
    119       cm.state.matchBrackets = typeof val == "object" ? val : {};
    120       cm.on("cursorActivity", doMatchBrackets);
    121     }
    122   });
    123 
    124   CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
    125   CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){
    126     // Backwards-compatibility kludge
    127     if (oldConfig || typeof config == "boolean") {
    128       if (!oldConfig) {
    129         config = config ? {strict: true} : null
    130       } else {
    131         oldConfig.strict = config
    132         config = oldConfig
    133       }
    134     }
    135     return findMatchingBracket(this, pos, config)
    136   });
    137   CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
    138     return scanForBracket(this, pos, dir, style, config);
    139   });
    140 });