browser/devtools/sourceeditor/codemirror/closebrackets.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/devtools/sourceeditor/codemirror/closebrackets.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,123 @@
     1.4 +(function(mod) {
     1.5 +  if (typeof exports == "object" && typeof module == "object") // CommonJS
     1.6 +    mod(require("../../lib/codemirror"));
     1.7 +  else if (typeof define == "function" && define.amd) // AMD
     1.8 +    define(["../../lib/codemirror"], mod);
     1.9 +  else // Plain browser env
    1.10 +    mod(CodeMirror);
    1.11 +})(function(CodeMirror) {
    1.12 +  var DEFAULT_BRACKETS = "()[]{}''\"\"";
    1.13 +  var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
    1.14 +  var SPACE_CHAR_REGEX = /\s/;
    1.15 +
    1.16 +  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
    1.17 +    if (old != CodeMirror.Init && old)
    1.18 +      cm.removeKeyMap("autoCloseBrackets");
    1.19 +    if (!val) return;
    1.20 +    var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
    1.21 +    if (typeof val == "string") pairs = val;
    1.22 +    else if (typeof val == "object") {
    1.23 +      if (val.pairs != null) pairs = val.pairs;
    1.24 +      if (val.explode != null) explode = val.explode;
    1.25 +    }
    1.26 +    var map = buildKeymap(pairs);
    1.27 +    if (explode) map.Enter = buildExplodeHandler(explode);
    1.28 +    cm.addKeyMap(map);
    1.29 +  });
    1.30 +
    1.31 +  function charsAround(cm, pos) {
    1.32 +    var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1),
    1.33 +                          CodeMirror.Pos(pos.line, pos.ch + 1));
    1.34 +    return str.length == 2 ? str : null;
    1.35 +  }
    1.36 +
    1.37 +  function buildKeymap(pairs) {
    1.38 +    var map = {
    1.39 +      name : "autoCloseBrackets",
    1.40 +      Backspace: function(cm) {
    1.41 +        if (cm.getOption("disableInput")) return CodeMirror.Pass;
    1.42 +        var ranges = cm.listSelections();
    1.43 +        for (var i = 0; i < ranges.length; i++) {
    1.44 +          if (!ranges[i].empty()) return CodeMirror.Pass;
    1.45 +          var around = charsAround(cm, ranges[i].head);
    1.46 +          if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
    1.47 +        }
    1.48 +        for (var i = ranges.length - 1; i >= 0; i--) {
    1.49 +          var cur = ranges[i].head;
    1.50 +          cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
    1.51 +        }
    1.52 +      }
    1.53 +    };
    1.54 +    var closingBrackets = "";
    1.55 +    for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
    1.56 +      if (left != right) closingBrackets += right;
    1.57 +      map["'" + left + "'"] = function(cm) {
    1.58 +        if (cm.getOption("disableInput")) return CodeMirror.Pass;
    1.59 +        var ranges = cm.listSelections(), type, next;
    1.60 +        for (var i = 0; i < ranges.length; i++) {
    1.61 +          var range = ranges[i], cur = range.head, curType;
    1.62 +          if (left == "'" && cm.getTokenTypeAt(cur) == "comment")
    1.63 +            return CodeMirror.Pass;
    1.64 +          var next = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
    1.65 +          if (!range.empty())
    1.66 +            curType = "surround";
    1.67 +          else if (left == right && next == right)
    1.68 +            curType = "skip";
    1.69 +          else if (left == right && CodeMirror.isWordChar(next))
    1.70 +            return CodeMirror.Pass;
    1.71 +          else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next))
    1.72 +            curType = "both";
    1.73 +          else
    1.74 +            return CodeMirror.Pass;
    1.75 +          if (!type) type = curType;
    1.76 +          else if (type != curType) return CodeMirror.Pass;
    1.77 +        }
    1.78 +
    1.79 +        if (type == "skip") {
    1.80 +          cm.execCommand("goCharRight");
    1.81 +        } else if (type == "surround") {
    1.82 +          var sels = cm.getSelections();
    1.83 +          for (var i = 0; i < sels.length; i++)
    1.84 +            sels[i] = left + sels[i] + right;
    1.85 +          cm.replaceSelections(sels, "around");
    1.86 +        } else if (type == "both") {
    1.87 +          cm.replaceSelection(left + right, null);
    1.88 +          cm.execCommand("goCharLeft");
    1.89 +        }
    1.90 +      };
    1.91 +      if (left != right) map["'" + right + "'"] = function(cm) {
    1.92 +        var ranges = cm.listSelections();
    1.93 +        for (var i = 0; i < ranges.length; i++) {
    1.94 +          var range = ranges[i];
    1.95 +          if (!range.empty() ||
    1.96 +              cm.getRange(range.head, CodeMirror.Pos(range.head.line, range.head.ch + 1)) != right)
    1.97 +            return CodeMirror.Pass;
    1.98 +        }
    1.99 +        cm.execCommand("goCharRight");
   1.100 +      };
   1.101 +    })(pairs.charAt(i), pairs.charAt(i + 1));
   1.102 +    return map;
   1.103 +  }
   1.104 +
   1.105 +  function buildExplodeHandler(pairs) {
   1.106 +    return function(cm) {
   1.107 +      if (cm.getOption("disableInput")) return CodeMirror.Pass;
   1.108 +      var ranges = cm.listSelections();
   1.109 +      for (var i = 0; i < ranges.length; i++) {
   1.110 +        if (!ranges[i].empty()) return CodeMirror.Pass;
   1.111 +        var around = charsAround(cm, ranges[i].head);
   1.112 +        if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
   1.113 +      }
   1.114 +      cm.operation(function() {
   1.115 +        cm.replaceSelection("\n\n", null);
   1.116 +        cm.execCommand("goCharLeft");
   1.117 +        ranges = cm.listSelections();
   1.118 +        for (var i = 0; i < ranges.length; i++) {
   1.119 +          var line = ranges[i].head.line;
   1.120 +          cm.indentLine(line, null, true);
   1.121 +          cm.indentLine(line + 1, null, true);
   1.122 +        }
   1.123 +      });
   1.124 +    };
   1.125 +  }
   1.126 +});

mercurial