codemirror-rails 5.3 → 5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +26 -36
  4. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +4 -4
  5. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +3 -3
  6. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +69 -11
  7. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +4 -2
  8. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +24 -3
  9. data/vendor/assets/javascripts/codemirror/modes/clike.js +60 -25
  10. data/vendor/assets/javascripts/codemirror/modes/elm.js +205 -0
  11. data/vendor/assets/javascripts/codemirror/modes/factor.js +83 -0
  12. data/vendor/assets/javascripts/codemirror/modes/groovy.js +8 -5
  13. data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -2
  14. data/vendor/assets/javascripts/codemirror/modes/kotlin.js +5 -2
  15. data/vendor/assets/javascripts/codemirror/modes/markdown.js +37 -23
  16. data/vendor/assets/javascripts/codemirror/modes/php.js +20 -17
  17. data/vendor/assets/javascripts/codemirror/modes/python.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/modes/swift.js +203 -0
  19. data/vendor/assets/javascripts/codemirror/modes/twig.js +132 -0
  20. data/vendor/assets/javascripts/codemirror/modes/vb.js +2 -1
  21. data/vendor/assets/stylesheets/codemirror.css +9 -9
  22. data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +3 -2
  23. data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +1 -1
  24. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +2 -2
  25. data/vendor/assets/stylesheets/codemirror/themes/monokai.css +1 -0
  26. data/vendor/assets/stylesheets/codemirror/themes/solarized.css +2 -2
  27. data/vendor/assets/stylesheets/codemirror/themes/ttcn.css +9 -10
  28. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6ddde433ae7b37ee0173fe1a42d41cd91f3744d
4
- data.tar.gz: b69c9951146b7b058e70a132e59ea6572d16c853
3
+ metadata.gz: 10db6f811f18415146339d089880eed31b6fa1e2
4
+ data.tar.gz: 2d6da2b335ed897e73bfd5b8b215cc3707103c90
5
5
  SHA512:
6
- metadata.gz: cbd3e9ba7e1b89305aaa9f361cf5f7859b9a46c0297974d5211ffd357eb5dc0d5b0453eb0715bb46e3f786dd02d871ea5b9712eda1886b27e20585c79c86ac9d
7
- data.tar.gz: b232672158c10203601d827f7a3251b5c717f66ba0ce6e08b1e07537bf20854e42fd4a07c025bc5ddf84137544c4d2371fa4a89afbfc04d5720a3bd883cc017f
6
+ metadata.gz: fa0289f78e21921fed008e0a050114cae82355ce4c4da0788256d488e491ef85f4f1ab617a8c0d19f725b493313b6b2164657cb15bdbc725ec2a6aa4f45e407e
7
+ data.tar.gz: c7f55bed88131340665ae6b7685d454a57a6acc65ab8aecee48985d407fba3bdb104757bb8274091d10fa6c7072308936bcffc62e7af4fc0d75a938fe3e484a0
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '5.3'
4
- CODEMIRROR_VERSION = '5.3'
3
+ VERSION = '5.4'
4
+ CODEMIRROR_VERSION = '5.4'
5
5
  end
6
6
  end
@@ -1081,9 +1081,10 @@
1081
1081
  cm.display.shift = false;
1082
1082
  if (!sel) sel = doc.sel;
1083
1083
 
1084
+ var paste = cm.state.pasteIncoming || origin == "paste";
1084
1085
  var textLines = splitLines(inserted), multiPaste = null;
1085
1086
  // When pasing N lines into N selections, insert one line per selection
1086
- if (cm.state.pasteIncoming && sel.ranges.length > 1) {
1087
+ if (paste && sel.ranges.length > 1) {
1087
1088
  if (lastCopied && lastCopied.join("\n") == inserted)
1088
1089
  multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
1089
1090
  else if (textLines.length == sel.ranges.length)
@@ -1097,16 +1098,16 @@
1097
1098
  if (range.empty()) {
1098
1099
  if (deleted && deleted > 0) // Handle deletion
1099
1100
  from = Pos(from.line, from.ch - deleted);
1100
- else if (cm.state.overwrite && !cm.state.pasteIncoming) // Handle overwrite
1101
+ else if (cm.state.overwrite && !paste) // Handle overwrite
1101
1102
  to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
1102
1103
  }
1103
1104
  var updateInput = cm.curOp.updateInput;
1104
1105
  var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
1105
- origin: origin || (cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
1106
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
1106
1107
  makeChange(cm.doc, changeEvent);
1107
1108
  signalLater(cm, "inputRead", cm, changeEvent);
1108
1109
  }
1109
- if (inserted && !cm.state.pasteIncoming)
1110
+ if (inserted && !paste)
1110
1111
  triggerElectric(cm, inserted);
1111
1112
 
1112
1113
  ensureCursorVisible(cm);
@@ -1115,6 +1116,15 @@
1115
1116
  cm.state.pasteIncoming = cm.state.cutIncoming = false;
1116
1117
  }
1117
1118
 
1119
+ function handlePaste(e, cm) {
1120
+ var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
1121
+ if (pasted) {
1122
+ e.preventDefault();
1123
+ runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
1124
+ return true;
1125
+ }
1126
+ }
1127
+
1118
1128
  function triggerElectric(cm, inserted) {
1119
1129
  // When an 'electric' character is inserted, immediately trigger a reindent
1120
1130
  if (!cm.options.electricChars || !cm.options.smartIndent) return;
@@ -1211,21 +1221,9 @@
1211
1221
  input.poll();
1212
1222
  });
1213
1223
 
1214
- on(te, "paste", function() {
1215
- // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
1216
- // Add a char to the end of textarea before paste occur so that
1217
- // selection doesn't span to the end of textarea.
1218
- if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
1219
- var start = te.selectionStart, end = te.selectionEnd;
1220
- te.value += "$";
1221
- // The selection end needs to be set before the start, otherwise there
1222
- // can be an intermediate non-empty selection between the two, which
1223
- // can override the middle-click paste buffer on linux and cause the
1224
- // wrong thing to get pasted.
1225
- te.selectionEnd = end;
1226
- te.selectionStart = start;
1227
- cm.state.fakedLastChar = true;
1228
- }
1224
+ on(te, "paste", function(e) {
1225
+ if (handlePaste(e, cm)) return true;
1226
+
1229
1227
  cm.state.pasteIncoming = true;
1230
1228
  input.fastPoll();
1231
1229
  });
@@ -1389,14 +1387,11 @@
1389
1387
  // possible when it is clear that nothing happened. hasSelection
1390
1388
  // will be the case when there is a lot of text in the textarea,
1391
1389
  // in which case reading its value would be expensive.
1392
- if (!cm.state.focused || (hasSelection(input) && !prevInput) ||
1390
+ if (this.contextMenuPending || !cm.state.focused ||
1391
+ (hasSelection(input) && !prevInput) ||
1393
1392
  isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
1394
1393
  return false;
1395
- // See paste handler for more on the fakedLastChar kludge
1396
- if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
1397
- input.value = input.value.substring(0, input.value.length - 1);
1398
- cm.state.fakedLastChar = false;
1399
- }
1394
+
1400
1395
  var text = input.value;
1401
1396
  // If nothing changed, bail.
1402
1397
  if (text == prevInput && !cm.somethingSelected()) return false;
@@ -1542,13 +1537,7 @@
1542
1537
  div.contentEditable = "true";
1543
1538
  disableBrowserMagic(div);
1544
1539
 
1545
- on(div, "paste", function(e) {
1546
- var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
1547
- if (pasted) {
1548
- e.preventDefault();
1549
- cm.replaceSelection(pasted, null, "paste");
1550
- }
1551
- });
1540
+ on(div, "paste", function(e) { handlePaste(e, cm); })
1552
1541
 
1553
1542
  on(div, "compositionstart", function(e) {
1554
1543
  var data = e.data;
@@ -1761,7 +1750,7 @@
1761
1750
  var toIndex = findViewIndex(cm, to.line);
1762
1751
  if (toIndex == display.view.length - 1) {
1763
1752
  var toLine = display.viewTo - 1;
1764
- var toNode = display.view[toIndex].node;
1753
+ var toNode = display.lineDiv.lastChild;
1765
1754
  } else {
1766
1755
  var toLine = lineNo(display.view[toIndex + 1].line) - 1;
1767
1756
  var toNode = display.view[toIndex + 1].node.previousSibling;
@@ -3567,7 +3556,8 @@
3567
3556
  var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
3568
3557
  if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
3569
3558
  type == "single" && (contained = sel.contains(start)) > -1 &&
3570
- !sel.ranges[contained].empty())
3559
+ (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
3560
+ (cmp(contained.to(), start) > 0 || start.xRel < 0))
3571
3561
  leftButtonStartDrag(cm, e, start, modifier);
3572
3562
  else
3573
3563
  leftButtonSelect(cm, e, start, type, modifier);
@@ -7587,7 +7577,7 @@
7587
7577
  Doc.prototype.eachLine = Doc.prototype.iter;
7588
7578
 
7589
7579
  // Set up methods on CodeMirror's prototype to redirect to the editor's document.
7590
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
7580
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
7591
7581
  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
7592
7582
  CodeMirror.prototype[prop] = (function(method) {
7593
7583
  return function() {return method.apply(this.doc, arguments);};
@@ -8739,7 +8729,7 @@
8739
8729
 
8740
8730
  // THE END
8741
8731
 
8742
- CodeMirror.version = "5.3.0";
8732
+ CodeMirror.version = "5.4.0";
8743
8733
 
8744
8734
  return CodeMirror;
8745
8735
  });
@@ -11,8 +11,8 @@
11
11
  })(function(CodeMirror) {
12
12
  "use strict";
13
13
 
14
- var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
15
- emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
14
+ var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))(\s*)/,
15
+ emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)[.)])(\s*)$/,
16
16
  unorderedListRE = /[*+-]\s/;
17
17
 
18
18
  CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
@@ -37,10 +37,10 @@
37
37
  });
38
38
  replacements[i] = "\n";
39
39
  } else {
40
- var indent = match[1], after = match[4];
40
+ var indent = match[1], after = match[5];
41
41
  var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
42
42
  ? match[2]
43
- : (parseInt(match[3], 10) + 1) + ".";
43
+ : (parseInt(match[3], 10) + 1) + match[4];
44
44
 
45
45
  replacements[i] = "\n" + indent + bullet + after;
46
46
  }
@@ -127,13 +127,13 @@
127
127
 
128
128
  if (columns) {
129
129
  addMatches(result, string, columns, function(w) {
130
+ var tableInsert = table;
131
+ if (alias == true) tableInsert = aliasTable;
130
132
  if (typeof w == "string") {
131
- var tableInsert = table;
132
- if (alias == true) tableInsert = aliasTable;
133
133
  w = tableInsert + "." + w;
134
134
  } else {
135
135
  w = shallowClone(w);
136
- w.text = table + "." + w.text;
136
+ w.text = tableInsert + "." + w.text;
137
137
  }
138
138
  return useBacktick ? insertBackticks(w) : w;
139
139
  });
@@ -3,19 +3,37 @@
3
3
 
4
4
  /* Just enough of CodeMirror to run runMode under node.js */
5
5
 
6
- // declare global: StringStream
6
+ function splitLines(string){return string.split(/\r\n?|\n/);};
7
7
 
8
- function splitLines(string){ return string.split(/\r?\n|\r/); };
8
+ // Counts the column offset in a string, taking tabs into account.
9
+ // Used mostly to find indentation.
10
+ var countColumn = function(string, end, tabSize, startIndex, startValue) {
11
+ if (end == null) {
12
+ end = string.search(/[^\s\u00a0]/);
13
+ if (end == -1) end = string.length;
14
+ }
15
+ for (var i = startIndex || 0, n = startValue || 0;;) {
16
+ var nextTab = string.indexOf("\t", i);
17
+ if (nextTab < 0 || nextTab >= end)
18
+ return n + (end - i);
19
+ n += nextTab - i;
20
+ n += tabSize - (n % tabSize);
21
+ i = nextTab + 1;
22
+ }
23
+ };
9
24
 
10
- function StringStream(string) {
25
+ function StringStream(string, tabSize) {
11
26
  this.pos = this.start = 0;
12
27
  this.string = string;
28
+ this.tabSize = tabSize || 8;
29
+ this.lastColumnPos = this.lastColumnValue = 0;
13
30
  this.lineStart = 0;
14
- }
31
+ };
32
+
15
33
  StringStream.prototype = {
16
34
  eol: function() {return this.pos >= this.string.length;},
17
- sol: function() {return this.pos == 0;},
18
- peek: function() {return this.string.charAt(this.pos) || null;},
35
+ sol: function() {return this.pos == this.lineStart;},
36
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
19
37
  next: function() {
20
38
  if (this.pos < this.string.length)
21
39
  return this.string.charAt(this.pos++);
@@ -42,8 +60,17 @@ StringStream.prototype = {
42
60
  if (found > -1) {this.pos = found; return true;}
43
61
  },
44
62
  backUp: function(n) {this.pos -= n;},
45
- column: function() {return this.start - this.lineStart;},
46
- indentation: function() {return 0;},
63
+ column: function() {
64
+ if (this.lastColumnPos < this.start) {
65
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
66
+ this.lastColumnPos = this.start;
67
+ }
68
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
69
+ },
70
+ indentation: function() {
71
+ return countColumn(this.string, null, this.tabSize) -
72
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
73
+ },
47
74
  match: function(pattern, consume, caseInsensitive) {
48
75
  if (typeof pattern == "string") {
49
76
  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
@@ -94,11 +121,42 @@ exports.resolveMode = function(spec) {
94
121
  if (typeof spec == "string") return {name: spec};
95
122
  else return spec || {name: "null"};
96
123
  };
124
+
125
+ function copyObj(obj, target, overwrite) {
126
+ if (!target) target = {};
127
+ for (var prop in obj)
128
+ if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
129
+ target[prop] = obj[prop];
130
+ return target;
131
+ }
132
+
133
+ // This can be used to attach properties to mode objects from
134
+ // outside the actual mode definition.
135
+ var modeExtensions = exports.modeExtensions = {};
136
+ exports.extendMode = function(mode, properties) {
137
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
138
+ copyObj(properties, exts);
139
+ };
140
+
97
141
  exports.getMode = function(options, spec) {
98
- spec = exports.resolveMode(spec);
142
+ var spec = exports.resolveMode(spec);
99
143
  var mfactory = modes[spec.name];
100
- if (!mfactory) throw new Error("Unknown mode: " + spec);
101
- return mfactory(options, spec);
144
+ if (!mfactory) return exports.getMode(options, "text/plain");
145
+ var modeObj = mfactory(options, spec);
146
+ if (modeExtensions.hasOwnProperty(spec.name)) {
147
+ var exts = modeExtensions[spec.name];
148
+ for (var prop in exts) {
149
+ if (!exts.hasOwnProperty(prop)) continue;
150
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
151
+ modeObj[prop] = exts[prop];
152
+ }
153
+ }
154
+ modeObj.name = spec.name;
155
+ if (spec.helperType) modeObj.helperType = spec.helperType;
156
+ if (spec.modeProps) for (var prop in spec.modeProps)
157
+ modeObj[prop] = spec.modeProps[prop];
158
+
159
+ return modeObj;
102
160
  };
103
161
  exports.registerHelper = exports.registerGlobalHelper = Math.min;
104
162
 
@@ -59,6 +59,7 @@
59
59
  this.options = options || {};
60
60
  var plugins = this.options.plugins || (this.options.plugins = {});
61
61
  if (!plugins.doc_comment) plugins.doc_comment = true;
62
+ this.docs = Object.create(null);
62
63
  if (this.options.useWorker) {
63
64
  this.server = new WorkerServer(this);
64
65
  } else {
@@ -69,7 +70,6 @@
69
70
  plugins: plugins
70
71
  });
71
72
  }
72
- this.docs = Object.create(null);
73
73
  this.trackChange = function(doc, change) { trackChange(self, doc, change); };
74
74
 
75
75
  this.cachedArgHints = null;
@@ -124,6 +124,8 @@
124
124
  var self = this;
125
125
  var doc = findDoc(this, cm.getDoc());
126
126
  var request = buildRequest(this, doc, query, pos);
127
+ var extraOptions = request.query && this.options.queryOptions && this.options.queryOptions[request.query.type]
128
+ if (extraOptions) for (var prop in extraOptions) request.query[prop] = extraOptions[prop];
127
129
 
128
130
  this.server.request(request, function (error, data) {
129
131
  if (!error && self.options.responseFilter)
@@ -442,7 +444,7 @@
442
444
 
443
445
  function atInterestingExpression(cm) {
444
446
  var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
445
- if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
447
+ if (tok.start < pos.ch && tok.type == "comment") return false;
446
448
  return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
447
449
  }
448
450
 
@@ -851,6 +851,8 @@
851
851
  mapCommand: mapCommand,
852
852
  _mapCommand: _mapCommand,
853
853
 
854
+ defineRegister: defineRegister,
855
+
854
856
  exitVisualMode: exitVisualMode,
855
857
  exitInsertMode: exitInsertMode
856
858
  };
@@ -940,6 +942,25 @@
940
942
  }
941
943
  };
942
944
 
945
+ /**
946
+ * Defines an external register.
947
+ *
948
+ * The name should be a single character that will be used to reference the register.
949
+ * The register should support setText, pushText, clear, and toString(). See Register
950
+ * for a reference implementation.
951
+ */
952
+ function defineRegister(name, register) {
953
+ var registers = vimGlobalState.registerController.registers[name];
954
+ if (!name || name.length != 1) {
955
+ throw Error('Register name must be 1 character');
956
+ }
957
+ if (registers[name]) {
958
+ throw Error('Register already defined ' + name);
959
+ }
960
+ registers[name] = register;
961
+ validRegisters.push(name);
962
+ }
963
+
943
964
  /*
944
965
  * vim registers allow you to keep many independent copy and paste buffers.
945
966
  * See http://usevim.com/2012/04/13/registers/ for an introduction.
@@ -4726,7 +4747,7 @@
4726
4747
  }
4727
4748
 
4728
4749
  function _mapCommand(command) {
4729
- defaultKeymap.push(command);
4750
+ defaultKeymap.unshift(command);
4730
4751
  }
4731
4752
 
4732
4753
  function mapCommand(keys, type, name, args, extra) {
@@ -4815,7 +4836,7 @@
4815
4836
  if (macroModeState.isPlaying) { return; }
4816
4837
  var registerName = macroModeState.latestRegister;
4817
4838
  var register = vimGlobalState.registerController.getRegister(registerName);
4818
- if (register) {
4839
+ if (register && register.pushInsertModeChanges) {
4819
4840
  register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
4820
4841
  }
4821
4842
  }
@@ -4824,7 +4845,7 @@
4824
4845
  if (macroModeState.isPlaying) { return; }
4825
4846
  var registerName = macroModeState.latestRegister;
4826
4847
  var register = vimGlobalState.registerController.getRegister(registerName);
4827
- if (register) {
4848
+ if (register && register.pushSearchQuery) {
4828
4849
  register.pushSearchQuery(query);
4829
4850
  }
4830
4851
  }
@@ -24,7 +24,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
24
24
  hooks = parserConfig.hooks || {},
25
25
  multiLineStrings = parserConfig.multiLineStrings,
26
26
  indentStatements = parserConfig.indentStatements !== false,
27
- indentSwitch = parserConfig.indentSwitch !== false;
27
+ indentSwitch = parserConfig.indentSwitch !== false,
28
+ namespaceSeparator = parserConfig.namespaceSeparator;
28
29
  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
29
30
 
30
31
  var curPunc, isDefKeyword;
@@ -62,6 +63,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
62
63
  return "operator";
63
64
  }
64
65
  stream.eatWhile(/[\w\$_\xa1-\uffff]/);
66
+ if (namespaceSeparator) while (stream.match(namespaceSeparator))
67
+ stream.eatWhile(/[\w\$_\xa1-\uffff]/);
68
+
65
69
  var cur = stream.current();
66
70
  if (keywords.propertyIsEnumerable(cur)) {
67
71
  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
@@ -109,12 +113,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
109
113
  this.align = align;
110
114
  this.prev = prev;
111
115
  }
112
- function isStatement(context) {
113
- return context.type == "statement" || context.type == "switchstatement";
116
+ function isStatement(type) {
117
+ return type == "statement" || type == "switchstatement" || type == "namespace";
114
118
  }
115
119
  function pushContext(state, col, type) {
116
120
  var indent = state.indented;
117
- if (state.context && isStatement(state.context))
121
+ if (state.context && isStatement(state.context.type) && !isStatement(type))
118
122
  indent = state.context.indented;
119
123
  return state.context = new Context(indent, col, type, null, state.context);
120
124
  }
@@ -127,7 +131,15 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
127
131
 
128
132
  function typeBefore(stream, state) {
129
133
  if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
130
- if (/\S[>*\]]\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true;
134
+ if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true;
135
+ }
136
+
137
+ function isTopScope(context) {
138
+ for (;;) {
139
+ if (!context || context.type == "top") return true;
140
+ if (context.type == "}" && context.prev.type != "namespace") return false;
141
+ context = context.prev;
142
+ }
131
143
  }
132
144
 
133
145
  // Interface
@@ -156,43 +168,53 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
156
168
  if (style == "comment" || style == "meta") return style;
157
169
  if (ctx.align == null) ctx.align = true;
158
170
 
159
- if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && isStatement(ctx)) popContext(state);
171
+ if ((curPunc == ";" || curPunc == ":" || curPunc == ","))
172
+ while (isStatement(state.context.type)) popContext(state);
160
173
  else if (curPunc == "{") pushContext(state, stream.column(), "}");
161
174
  else if (curPunc == "[") pushContext(state, stream.column(), "]");
162
175
  else if (curPunc == "(") pushContext(state, stream.column(), ")");
163
176
  else if (curPunc == "}") {
164
- while (isStatement(ctx)) ctx = popContext(state);
177
+ while (isStatement(ctx.type)) ctx = popContext(state);
165
178
  if (ctx.type == "}") ctx = popContext(state);
166
- while (isStatement(ctx)) ctx = popContext(state);
179
+ while (isStatement(ctx.type)) ctx = popContext(state);
167
180
  }
168
181
  else if (curPunc == ctx.type) popContext(state);
169
182
  else if (indentStatements &&
170
- (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
171
- (isStatement(ctx) && curPunc == "newstatement"))) {
172
- var type = "statement"
183
+ (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
184
+ (isStatement(ctx.type) && curPunc == "newstatement"))) {
185
+ var type = "statement";
173
186
  if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
174
- type = "switchstatement"
187
+ type = "switchstatement";
188
+ else if (style == "keyword" && stream.current() == "namespace")
189
+ type = "namespace";
175
190
  pushContext(state, stream.column(), type);
176
191
  }
177
192
 
178
193
  if (style == "variable" &&
179
194
  ((state.prevToken == "def" ||
180
195
  (parserConfig.typeFirstDefinitions && typeBefore(stream, state) &&
181
- stream.match(/^\s*\(/, false)))))
196
+ isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
182
197
  style = "def";
183
198
 
199
+ if (hooks.token) {
200
+ var result = hooks.token(stream, state, style);
201
+ if (result !== undefined) style = result;
202
+ }
203
+
204
+ if (style == "def" && parserConfig.styleDefs === false) style = "variable";
205
+
184
206
  state.startOfLine = false;
185
- state.prevToken = isDefKeyword ? "def" : style;
207
+ state.prevToken = isDefKeyword ? "def" : style || curPunc;
186
208
  return style;
187
209
  },
188
210
 
189
211
  indent: function(state, textAfter) {
190
212
  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
191
213
  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
192
- if (isStatement(ctx) && firstChar == "}") ctx = ctx.prev;
214
+ if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
193
215
  var closing = firstChar == ctx.type;
194
216
  var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
195
- if (isStatement(ctx))
217
+ if (isStatement(ctx.type))
196
218
  return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
197
219
  if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
198
220
  return ctx.column + (closing ? 0 : 1);
@@ -203,7 +225,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
203
225
  (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
204
226
  },
205
227
 
206
- electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{|\})$/ : /^\s*[{}]$/,
228
+ electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
207
229
  blockCommentStart: "/*",
208
230
  blockCommentEnd: "*/",
209
231
  lineComment: "//",
@@ -218,7 +240,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
218
240
  }
219
241
  var cKeywords = "auto if break case register continue return default do sizeof " +
220
242
  "static else struct switch extern typedef float union for " +
221
- "goto while enum const volatile true false";
243
+ "goto while enum const volatile";
222
244
  var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
223
245
 
224
246
  function cppHook(stream, state) {
@@ -268,6 +290,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
268
290
  return false;
269
291
  }
270
292
 
293
+ function cppLooksLikeConstructor(word) {
294
+ var lastTwo = /(\w+)::(\w+)$/.exec(word);
295
+ return lastTwo && lastTwo[1] == lastTwo[2];
296
+ }
297
+
271
298
  // C#-style strings where "" escapes a quote.
272
299
  function tokenAtString(stream, state) {
273
300
  var next;
@@ -322,19 +349,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
322
349
  blockKeywords: words("case do else for if switch while struct"),
323
350
  defKeywords: words("struct"),
324
351
  typeFirstDefinitions: true,
325
- atoms: words("null"),
352
+ atoms: words("null true false"),
326
353
  hooks: {"#": cppHook, "*": pointerHook},
327
354
  modeProps: {fold: ["brace", "include"]}
328
355
  });
329
356
 
330
357
  def(["text/x-c++src", "text/x-c++hdr"], {
331
358
  name: "clike",
332
- keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
359
+ keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
333
360
  "static_cast typeid catch operator template typename class friend private " +
334
361
  "this using const_cast inline public throw virtual delete mutable protected " +
335
- "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
362
+ "alignas alignof constexpr decltype nullptr noexcept thread_local final " +
336
363
  "static_assert override"),
337
- types: words(cTypes + "bool wchar_t"),
364
+ types: words(cTypes + " bool wchar_t"),
338
365
  blockKeywords: words("catch class do else finally for if struct switch try while"),
339
366
  defKeywords: words("class namespace struct enum union"),
340
367
  typeFirstDefinitions: true,
@@ -345,8 +372,16 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
345
372
  "u": cpp11StringHook,
346
373
  "U": cpp11StringHook,
347
374
  "L": cpp11StringHook,
348
- "R": cpp11StringHook
375
+ "R": cpp11StringHook,
376
+ token: function(stream, state, style) {
377
+ if (style == "variable" && stream.peek() == "(" &&
378
+ (state.prevToken == ";" || state.prevToken == null ||
379
+ state.prevToken == "}") &&
380
+ cppLooksLikeConstructor(stream.current()))
381
+ return "def";
382
+ }
349
383
  },
384
+ namespaceSeparator: "::",
350
385
  modeProps: {fold: ["brace", "include"]}
351
386
  });
352
387
 
@@ -532,7 +567,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
532
567
  "signal task uses abstract extends"),
533
568
  types: words(cTypes),
534
569
  blockKeywords: words("case do else for if switch while struct"),
535
- atoms: words("null"),
570
+ atoms: words("null true false"),
536
571
  hooks: {"#": cppHook},
537
572
  modeProps: {fold: ["brace", "include"]}
538
573
  });
@@ -542,7 +577,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
542
577
  keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
543
578
  "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
544
579
  types: words(cTypes),
545
- atoms: words("YES NO NULL NILL ON OFF"),
580
+ atoms: words("YES NO NULL NILL ON OFF true false"),
546
581
  hooks: {
547
582
  "@": function(stream) {
548
583
  stream.eatWhile(/[\w\$]/);