Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 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 defaults = {
13
    pairs: "()[]{}''\"\"",
14
    triples: "",
15
    explode: "[]{}"
16
  };
17
 
18
  var Pos = CodeMirror.Pos;
19
 
20
  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
21
    if (old && old != CodeMirror.Init) {
22
      cm.removeKeyMap(keyMap);
23
      cm.state.closeBrackets = null;
24
    }
25
    if (val) {
26
      cm.state.closeBrackets = val;
27
      cm.addKeyMap(keyMap);
28
    }
29
  });
30
 
31
  function getOption(conf, name) {
32
    if (name == "pairs" && typeof conf == "string") return conf;
33
    if (typeof conf == "object" && conf[name] != null) return conf[name];
34
    return defaults[name];
35
  }
36
 
37
  var bind = defaults.pairs + "`";
38
  var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
39
  for (var i = 0; i < bind.length; i++)
40
    keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
41
 
42
  function handler(ch) {
43
    return function(cm) { return handleChar(cm, ch); };
44
  }
45
 
46
  function getConfig(cm) {
47
    var deflt = cm.state.closeBrackets;
48
    if (!deflt) return null;
49
    var mode = cm.getModeAt(cm.getCursor());
50
    return mode.closeBrackets || deflt;
51
  }
52
 
53
  function handleBackspace(cm) {
54
    var conf = getConfig(cm);
55
    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
56
 
57
    var pairs = getOption(conf, "pairs");
58
    var ranges = cm.listSelections();
59
    for (var i = 0; i < ranges.length; i++) {
60
      if (!ranges[i].empty()) return CodeMirror.Pass;
61
      var around = charsAround(cm, ranges[i].head);
62
      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
63
    }
64
    for (var i = ranges.length - 1; i >= 0; i--) {
65
      var cur = ranges[i].head;
66
      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
67
    }
68
  }
69
 
70
  function handleEnter(cm) {
71
    var conf = getConfig(cm);
72
    var explode = conf && getOption(conf, "explode");
73
    if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
74
 
75
    var ranges = cm.listSelections();
76
    for (var i = 0; i < ranges.length; i++) {
77
      if (!ranges[i].empty()) return CodeMirror.Pass;
78
      var around = charsAround(cm, ranges[i].head);
79
      if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
80
    }
81
    cm.operation(function() {
82
      cm.replaceSelection("\n\n", null);
83
      cm.execCommand("goCharLeft");
84
      ranges = cm.listSelections();
85
      for (var i = 0; i < ranges.length; i++) {
86
        var line = ranges[i].head.line;
87
        cm.indentLine(line, null, true);
88
        cm.indentLine(line + 1, null, true);
89
      }
90
    });
91
  }
92
 
93
  function handleChar(cm, ch) {
94
    var conf = getConfig(cm);
95
    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
96
 
97
    var pairs = getOption(conf, "pairs");
98
    var pos = pairs.indexOf(ch);
99
    if (pos == -1) return CodeMirror.Pass;
100
    var triples = getOption(conf, "triples");
101
 
102
    var identical = pairs.charAt(pos + 1) == ch;
103
    var ranges = cm.listSelections();
104
    var opening = pos % 2 == 0;
105
 
106
    var type, next;
107
    for (var i = 0; i < ranges.length; i++) {
108
      var range = ranges[i], cur = range.head, curType;
109
      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
110
      if (opening && !range.empty()) {
111
        curType = "surround";
112
      } else if ((identical || !opening) && next == ch) {
113
        if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
114
          curType = "skipThree";
115
        else
116
          curType = "skip";
117
      } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
118
                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
119
                 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
120
        curType = "addFour";
121
      } else if (identical) {
122
        if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
123
        else return CodeMirror.Pass;
124
      } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
125
                             isClosingBracket(next, pairs) ||
126
                             /\s/.test(next))) {
127
        curType = "both";
128
      } else {
129
        return CodeMirror.Pass;
130
      }
131
      if (!type) type = curType;
132
      else if (type != curType) return CodeMirror.Pass;
133
    }
134
 
135
    var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
136
    var right = pos % 2 ? ch : pairs.charAt(pos + 1);
137
    cm.operation(function() {
138
      if (type == "skip") {
139
        cm.execCommand("goCharRight");
140
      } else if (type == "skipThree") {
141
        for (var i = 0; i < 3; i++)
142
          cm.execCommand("goCharRight");
143
      } else if (type == "surround") {
144
        var sels = cm.getSelections();
145
        for (var i = 0; i < sels.length; i++)
146
          sels[i] = left + sels[i] + right;
147
        cm.replaceSelections(sels, "around");
148
      } else if (type == "both") {
149
        cm.replaceSelection(left + right, null);
150
        cm.triggerElectric(left + right);
151
        cm.execCommand("goCharLeft");
152
      } else if (type == "addFour") {
153
        cm.replaceSelection(left + left + left + left, "before");
154
        cm.execCommand("goCharRight");
155
      }
156
    });
157
  }
158
 
159
  function isClosingBracket(ch, pairs) {
160
    var pos = pairs.lastIndexOf(ch);
161
    return pos > -1 && pos % 2 == 1;
162
  }
163
 
164
  function charsAround(cm, pos) {
165
    var str = cm.getRange(Pos(pos.line, pos.ch - 1),
166
                          Pos(pos.line, pos.ch + 1));
167
    return str.length == 2 ? str : null;
168
  }
169
 
170
  // Project the token type that will exists after the given char is
171
  // typed, and use it to determine whether it would cause the start
172
  // of a string token.
173
  function enteringString(cm, pos, ch) {
174
    var line = cm.getLine(pos.line);
175
    var token = cm.getTokenAt(pos);
176
    if (/\bstring2?\b/.test(token.type)) return false;
177
    var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
178
    stream.pos = stream.start = token.start;
179
    for (;;) {
180
      var type1 = cm.getMode().token(stream, token.state);
181
      if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
182
      stream.start = stream.pos;
183
    }
184
  }
185
});