codemirror-rails 5.3 → 5.4

Sign up to get free protection for your applications and to get access to all the features.
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\$]/);