GPQAPP

Форк
0
201 строка · 7.0 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://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
    closeBefore: ")]}'\":;>",
15
    triples: "",
16
    explode: "[]{}"
17
  };
18

19
  var Pos = CodeMirror.Pos;
20

21
  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
22
    if (old && old != CodeMirror.Init) {
23
      cm.removeKeyMap(keyMap);
24
      cm.state.closeBrackets = null;
25
    }
26
    if (val) {
27
      ensureBound(getOption(val, "pairs"))
28
      cm.state.closeBrackets = val;
29
      cm.addKeyMap(keyMap);
30
    }
31
  });
32

33
  function getOption(conf, name) {
34
    if (name == "pairs" && typeof conf == "string") return conf;
35
    if (typeof conf == "object" && conf[name] != null) return conf[name];
36
    return defaults[name];
37
  }
38

39
  var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
40
  function ensureBound(chars) {
41
    for (var i = 0; i < chars.length; i++) {
42
      var ch = chars.charAt(i), key = "'" + ch + "'"
43
      if (!keyMap[key]) keyMap[key] = handler(ch)
44
    }
45
  }
46
  ensureBound(defaults.pairs + "`")
47

48
  function handler(ch) {
49
    return function(cm) { return handleChar(cm, ch); };
50
  }
51

52
  function getConfig(cm) {
53
    var deflt = cm.state.closeBrackets;
54
    if (!deflt || deflt.override) return deflt;
55
    var mode = cm.getModeAt(cm.getCursor());
56
    return mode.closeBrackets || deflt;
57
  }
58

59
  function handleBackspace(cm) {
60
    var conf = getConfig(cm);
61
    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
62

63
    var pairs = getOption(conf, "pairs");
64
    var ranges = cm.listSelections();
65
    for (var i = 0; i < ranges.length; i++) {
66
      if (!ranges[i].empty()) return CodeMirror.Pass;
67
      var around = charsAround(cm, ranges[i].head);
68
      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
69
    }
70
    for (var i = ranges.length - 1; i >= 0; i--) {
71
      var cur = ranges[i].head;
72
      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
73
    }
74
  }
75

76
  function handleEnter(cm) {
77
    var conf = getConfig(cm);
78
    var explode = conf && getOption(conf, "explode");
79
    if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
80

81
    var ranges = cm.listSelections();
82
    for (var i = 0; i < ranges.length; i++) {
83
      if (!ranges[i].empty()) return CodeMirror.Pass;
84
      var around = charsAround(cm, ranges[i].head);
85
      if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
86
    }
87
    cm.operation(function() {
88
      var linesep = cm.lineSeparator() || "\n";
89
      cm.replaceSelection(linesep + linesep, null);
90
      moveSel(cm, -1)
91
      ranges = cm.listSelections();
92
      for (var i = 0; i < ranges.length; i++) {
93
        var line = ranges[i].head.line;
94
        cm.indentLine(line, null, true);
95
        cm.indentLine(line + 1, null, true);
96
      }
97
    });
98
  }
99

100
  function moveSel(cm, dir) {
101
    var newRanges = [], ranges = cm.listSelections(), primary = 0
102
    for (var i = 0; i < ranges.length; i++) {
103
      var range = ranges[i]
104
      if (range.head == cm.getCursor()) primary = i
105
      var pos = range.head.ch || dir > 0 ? {line: range.head.line, ch: range.head.ch + dir} : {line: range.head.line - 1}
106
      newRanges.push({anchor: pos, head: pos})
107
    }
108
    cm.setSelections(newRanges, primary)
109
  }
110

111
  function contractSelection(sel) {
112
    var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
113
    return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
114
            head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
115
  }
116

117
  function handleChar(cm, ch) {
118
    var conf = getConfig(cm);
119
    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
120

121
    var pairs = getOption(conf, "pairs");
122
    var pos = pairs.indexOf(ch);
123
    if (pos == -1) return CodeMirror.Pass;
124

125
    var closeBefore = getOption(conf,"closeBefore");
126

127
    var triples = getOption(conf, "triples");
128

129
    var identical = pairs.charAt(pos + 1) == ch;
130
    var ranges = cm.listSelections();
131
    var opening = pos % 2 == 0;
132

133
    var type;
134
    for (var i = 0; i < ranges.length; i++) {
135
      var range = ranges[i], cur = range.head, curType;
136
      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
137
      if (opening && !range.empty()) {
138
        curType = "surround";
139
      } else if ((identical || !opening) && next == ch) {
140
        if (identical && stringStartsAfter(cm, cur))
141
          curType = "both";
142
        else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
143
          curType = "skipThree";
144
        else
145
          curType = "skip";
146
      } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
147
                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
148
        if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
149
        curType = "addFour";
150
      } else if (identical) {
151
        var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
152
        if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
153
        else return CodeMirror.Pass;
154
      } else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) {
155
        curType = "both";
156
      } else {
157
        return CodeMirror.Pass;
158
      }
159
      if (!type) type = curType;
160
      else if (type != curType) return CodeMirror.Pass;
161
    }
162

163
    var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
164
    var right = pos % 2 ? ch : pairs.charAt(pos + 1);
165
    cm.operation(function() {
166
      if (type == "skip") {
167
        moveSel(cm, 1)
168
      } else if (type == "skipThree") {
169
        moveSel(cm, 3)
170
      } else if (type == "surround") {
171
        var sels = cm.getSelections();
172
        for (var i = 0; i < sels.length; i++)
173
          sels[i] = left + sels[i] + right;
174
        cm.replaceSelections(sels, "around");
175
        sels = cm.listSelections().slice();
176
        for (var i = 0; i < sels.length; i++)
177
          sels[i] = contractSelection(sels[i]);
178
        cm.setSelections(sels);
179
      } else if (type == "both") {
180
        cm.replaceSelection(left + right, null);
181
        cm.triggerElectric(left + right);
182
        moveSel(cm, -1)
183
      } else if (type == "addFour") {
184
        cm.replaceSelection(left + left + left + left, "before");
185
        moveSel(cm, 1)
186
      }
187
    });
188
  }
189

190
  function charsAround(cm, pos) {
191
    var str = cm.getRange(Pos(pos.line, pos.ch - 1),
192
                          Pos(pos.line, pos.ch + 1));
193
    return str.length == 2 ? str : null;
194
  }
195

196
  function stringStartsAfter(cm, pos) {
197
    var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
198
    return /\bstring/.test(token.type) && token.start == pos.ch &&
199
      (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
200
  }
201
});
202

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.