codemirror-rails 5.13.2 → 5.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +55 -42
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +9 -2
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/fold/brace-fold.js +8 -8
  7. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +3 -3
  8. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +25 -38
  9. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +2 -2
  10. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +2 -1
  11. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +9 -6
  12. data/vendor/assets/javascripts/codemirror/addons/search/match-highlighter.js +24 -27
  13. data/vendor/assets/javascripts/codemirror/addons/search/search.js +5 -2
  14. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +3 -21
  16. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +24 -25
  17. data/vendor/assets/javascripts/codemirror/modes/clike.js +34 -29
  18. data/vendor/assets/javascripts/codemirror/modes/clojure.js +59 -3
  19. data/vendor/assets/javascripts/codemirror/modes/crystal.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/modes/css.js +6 -6
  21. data/vendor/assets/javascripts/codemirror/modes/django.js +8 -8
  22. data/vendor/assets/javascripts/codemirror/modes/dtd.js +6 -6
  23. data/vendor/assets/javascripts/codemirror/modes/ebnf.js +1 -1
  24. data/vendor/assets/javascripts/codemirror/modes/haml.js +3 -3
  25. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
  26. data/vendor/assets/javascripts/codemirror/modes/jade.js +3 -3
  27. data/vendor/assets/javascripts/codemirror/modes/javascript.js +15 -9
  28. data/vendor/assets/javascripts/codemirror/modes/markdown.js +11 -21
  29. data/vendor/assets/javascripts/codemirror/modes/mathematica.js +1 -0
  30. data/vendor/assets/javascripts/codemirror/modes/mbox.js +129 -0
  31. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +6 -6
  32. data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
  33. data/vendor/assets/javascripts/codemirror/modes/php.js +1 -1
  34. data/vendor/assets/javascripts/codemirror/modes/powershell.js +396 -0
  35. data/vendor/assets/javascripts/codemirror/modes/properties.js +1 -1
  36. data/vendor/assets/javascripts/codemirror/modes/puppet.js +1 -1
  37. data/vendor/assets/javascripts/codemirror/modes/python.js +20 -28
  38. data/vendor/assets/javascripts/codemirror/modes/sas.js +315 -0
  39. data/vendor/assets/javascripts/codemirror/modes/slim.js +4 -4
  40. data/vendor/assets/javascripts/codemirror/modes/sparql.js +1 -1
  41. data/vendor/assets/javascripts/codemirror/modes/sql.js +10 -2
  42. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +78 -128
  43. data/vendor/assets/javascripts/codemirror/modes/verilog.js +1 -1
  44. data/vendor/assets/javascripts/codemirror/modes/vhdl.js +1 -1
  45. data/vendor/assets/javascripts/codemirror/modes/webidl.js +195 -0
  46. data/vendor/assets/javascripts/codemirror/modes/xquery.js +1 -1
  47. data/vendor/assets/javascripts/codemirror/modes/yacas.js +204 -0
  48. data/vendor/assets/stylesheets/codemirror.css +1 -1
  49. data/vendor/assets/stylesheets/codemirror/addons/lint/lint.css +2 -2
  50. data/vendor/assets/stylesheets/codemirror/themes/icecoder.css +4 -4
  51. metadata +6 -1
@@ -105,7 +105,7 @@
105
105
  }
106
106
 
107
107
  function nameCompletion(cur, token, result, editor) {
108
- // Try to complete table, colunm names and return start position of completion
108
+ // Try to complete table, column names and return start position of completion
109
109
  var useBacktick = false;
110
110
  var nameParts = [];
111
111
  var start = token.start;
@@ -241,7 +241,7 @@
241
241
  var defaultTableName = options && options.defaultTable;
242
242
  var disableKeywords = options && options.disableKeywords;
243
243
  defaultTable = defaultTableName && getTable(defaultTableName);
244
- keywords = keywords || getKeywords(editor);
244
+ keywords = getKeywords(editor);
245
245
 
246
246
  if (defaultTableName && !defaultTable)
247
247
  defaultTable = findTableByAlias(defaultTableName, editor);
@@ -204,7 +204,8 @@
204
204
 
205
205
  var annotations = [];
206
206
  for (var i = 0; i < spans.length; ++i) {
207
- annotations.push(spans[i].__annotation);
207
+ var ann = spans[i].__annotation;
208
+ if (ann) annotations.push(ann);
208
209
  }
209
210
  if (annotations.length) popupTooltips(annotations, e);
210
211
  }
@@ -59,10 +59,10 @@
59
59
  CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
60
60
  }
61
61
 
62
- Bar.prototype.setPos = function(pos) {
62
+ Bar.prototype.setPos = function(pos, force) {
63
63
  if (pos < 0) pos = 0;
64
64
  if (pos > this.total - this.screen) pos = this.total - this.screen;
65
- if (pos == this.pos) return false;
65
+ if (!force && pos == this.pos) return false;
66
66
  this.pos = pos;
67
67
  this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
68
68
  (pos * (this.size / this.total)) + "px";
@@ -76,9 +76,12 @@
76
76
  var minButtonSize = 10;
77
77
 
78
78
  Bar.prototype.update = function(scrollSize, clientSize, barSize) {
79
- this.screen = clientSize;
80
- this.total = scrollSize;
81
- this.size = barSize;
79
+ var sizeChanged = this.screen != clientSize || this.total != scrollSize || this.size != barSize
80
+ if (sizeChanged) {
81
+ this.screen = clientSize;
82
+ this.total = scrollSize;
83
+ this.size = barSize;
84
+ }
82
85
 
83
86
  var buttonSize = this.screen * (this.size / this.total);
84
87
  if (buttonSize < minButtonSize) {
@@ -87,7 +90,7 @@
87
90
  }
88
91
  this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
89
92
  buttonSize + "px";
90
- this.setPos(this.pos);
93
+ this.setPos(this.pos, sizeChanged);
91
94
  };
92
95
 
93
96
  function SimpleScrollbars(cls, place, scroll) {
@@ -16,7 +16,7 @@
16
16
  // highlighted only if the selected text is a word. showToken, when enabled,
17
17
  // will cause the current token to be highlighted when nothing is selected.
18
18
  // delay is used to specify how much time to wait, in milliseconds, before
19
- // highlighting the matches. If annotateScrollbar is enabled, the occurances
19
+ // highlighting the matches. If annotateScrollbar is enabled, the occurences
20
20
  // will be highlighted on the scrollbar via the matchesonscrollbar addon.
21
21
 
22
22
  (function(mod) {
@@ -29,24 +29,20 @@
29
29
  })(function(CodeMirror) {
30
30
  "use strict";
31
31
 
32
- var DEFAULT_MIN_CHARS = 2;
33
- var DEFAULT_TOKEN_STYLE = "matchhighlight";
34
- var DEFAULT_DELAY = 100;
35
- var DEFAULT_WORDS_ONLY = false;
32
+ var defaults = {
33
+ style: "matchhighlight",
34
+ minChars: 2,
35
+ delay: 100,
36
+ wordsOnly: false,
37
+ annotateScrollbar: false,
38
+ showToken: false,
39
+ trim: true
40
+ }
36
41
 
37
42
  function State(options) {
38
- if (typeof options == "object") {
39
- this.minChars = options.minChars;
40
- this.style = options.style;
41
- this.showToken = options.showToken;
42
- this.delay = options.delay;
43
- this.wordsOnly = options.wordsOnly;
44
- this.annotateScrollbar = options.annotateScrollbar;
45
- }
46
- if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
47
- if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
48
- if (this.delay == null) this.delay = DEFAULT_DELAY;
49
- if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
43
+ this.options = {}
44
+ for (var name in defaults)
45
+ this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name]
50
46
  this.overlay = this.timeout = null;
51
47
  this.matchesonscroll = null;
52
48
  }
@@ -68,13 +64,13 @@
68
64
  function cursorActivity(cm) {
69
65
  var state = cm.state.matchHighlighter;
70
66
  clearTimeout(state.timeout);
71
- state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
67
+ state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay);
72
68
  }
73
69
 
74
70
  function addOverlay(cm, query, hasBoundary, style) {
75
71
  var state = cm.state.matchHighlighter;
76
72
  cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
77
- if (state.annotateScrollbar) {
73
+ if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
78
74
  var searchFor = hasBoundary ? new RegExp("\\b" + query + "\\b") : query;
79
75
  state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, true,
80
76
  {className: "CodeMirror-selection-highlight-scrollbar"});
@@ -86,7 +82,7 @@
86
82
  if (state.overlay) {
87
83
  cm.removeOverlay(state.overlay);
88
84
  state.overlay = null;
89
- if (state.annotateScrollbar) {
85
+ if (state.matchesonscroll) {
90
86
  state.matchesonscroll.clear();
91
87
  state.matchesonscroll = null;
92
88
  }
@@ -97,21 +93,22 @@
97
93
  cm.operation(function() {
98
94
  var state = cm.state.matchHighlighter;
99
95
  removeOverlay(cm);
100
- if (!cm.somethingSelected() && state.showToken) {
101
- var re = state.showToken === true ? /[\w$]/ : state.showToken;
96
+ if (!cm.somethingSelected() && state.options.showToken) {
97
+ var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
102
98
  var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
103
99
  while (start && re.test(line.charAt(start - 1))) --start;
104
100
  while (end < line.length && re.test(line.charAt(end))) ++end;
105
101
  if (start < end)
106
- addOverlay(cm, line.slice(start, end), re, state.style);
102
+ addOverlay(cm, line.slice(start, end), re, state.options.style);
107
103
  return;
108
104
  }
109
105
  var from = cm.getCursor("from"), to = cm.getCursor("to");
110
106
  if (from.line != to.line) return;
111
- if (state.wordsOnly && !isWord(cm, from, to)) return;
112
- var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
113
- if (selection.length >= state.minChars)
114
- addOverlay(cm, selection, false, state.style);
107
+ if (state.options.wordsOnly && !isWord(cm, from, to)) return;
108
+ var selection = cm.getRange(from, to)
109
+ if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "")
110
+ if (selection.length >= state.options.minChars)
111
+ addOverlay(cm, selection, false, state.options.style);
115
112
  });
116
113
  }
117
114
 
@@ -121,7 +121,10 @@
121
121
  persistentDialog(cm, queryDialog, q, function(query, event) {
122
122
  CodeMirror.e_stop(event);
123
123
  if (!query) return;
124
- if (query != state.queryText) startSearch(cm, state, query);
124
+ if (query != state.queryText) {
125
+ startSearch(cm, state, query);
126
+ state.posFrom = state.posTo = cm.getCursor();
127
+ }
125
128
  if (hiding) hiding.style.opacity = 1
126
129
  findNext(cm, event.shiftKey, function(_, to) {
127
130
  var dialog
@@ -193,7 +196,7 @@
193
196
  replaceAll(cm, query, text)
194
197
  } else {
195
198
  clearSearch(cm);
196
- var cursor = getSearchCursor(cm, query, cm.getCursor());
199
+ var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
197
200
  var advance = function() {
198
201
  var start = cursor.from(), match;
199
202
  if (!(match = cursor.findNext())) {
@@ -179,7 +179,7 @@
179
179
  var data = findDoc(ts, doc);
180
180
 
181
181
  var argHints = ts.cachedArgHints;
182
- if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
182
+ if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) >= 0)
183
183
  ts.cachedArgHints = null;
184
184
 
185
185
  var changed = data.changed;
@@ -306,7 +306,7 @@
306
306
  ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
307
307
  if (error || !data.type || !(/^fn\(/).test(data.type)) return;
308
308
  ts.cachedArgHints = {
309
- start: pos,
309
+ start: start,
310
310
  type: parseFnType(data.type),
311
311
  name: data.exprName || data.name || "fn",
312
312
  guess: data.guess,
@@ -55,6 +55,8 @@
55
55
  cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
56
56
  cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };
57
57
 
58
+ if (mac) map["Cmd-Left"] = "goLineStartSmart";
59
+
58
60
  var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-";
59
61
 
60
62
  cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) {
@@ -122,6 +124,7 @@
122
124
  }
123
125
  cm.setSelections(newSelection);
124
126
  });
127
+ cm.execCommand("indentAuto");
125
128
  }
126
129
 
127
130
  cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { return insertLine(cm, false); };
@@ -417,27 +420,6 @@
417
420
 
418
421
  map[cK + ctrl + "Backspace"] = "delLineLeft";
419
422
 
420
- cmds[map["Backspace"] = "smartBackspace"] = function(cm) {
421
- if (cm.somethingSelected()) return CodeMirror.Pass;
422
-
423
- var cursor = cm.getCursor();
424
- var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
425
- var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
426
- var indentUnit = cm.getOption("indentUnit");
427
-
428
- if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) {
429
- var prevIndent = new Pos(cursor.line,
430
- CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit));
431
-
432
- // If no smart delete is happening (due to tab sizing) just do a regular delete
433
- if (prevIndent.ch == cursor.ch) return CodeMirror.Pass;
434
-
435
- return cm.replaceRange("", prevIndent, cursor, "+delete");
436
- } else {
437
- return CodeMirror.Pass;
438
- }
439
- };
440
-
441
423
  cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
442
424
  cm.operation(function() {
443
425
  var ranges = cm.listSelections();
@@ -26,7 +26,7 @@
26
26
  * 2. Variable declarations and short basic helpers
27
27
  * 3. Instance (External API) implementation
28
28
  * 4. Internal state tracking objects (input state, counter) implementation
29
- * and instanstiation
29
+ * and instantiation
30
30
  * 5. Key handler (the main command dispatcher) implementation
31
31
  * 6. Motion, operator, and action implementations
32
32
  * 7. Helper functions for the key handler, motions, operators, and actions
@@ -226,6 +226,7 @@
226
226
  { name: 'sort', shortName: 'sor' },
227
227
  { name: 'substitute', shortName: 's', possiblyAsync: true },
228
228
  { name: 'nohlsearch', shortName: 'noh' },
229
+ { name: 'yank', shortName: 'y' },
229
230
  { name: 'delmarks', shortName: 'delm' },
230
231
  { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
231
232
  { name: 'global', shortName: 'g' }
@@ -641,7 +642,7 @@
641
642
  jumpList: createCircularJumpList(),
642
643
  macroModeState: new MacroModeState,
643
644
  // Recording latest f, t, F or T motion command.
644
- lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''},
645
+ lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''},
645
646
  registerController: new RegisterController({}),
646
647
  // search history buffer
647
648
  searchHistoryController: new HistoryController({}),
@@ -1047,7 +1048,7 @@
1047
1048
  };
1048
1049
  function HistoryController() {
1049
1050
  this.historyBuffer = [];
1050
- this.iterator;
1051
+ this.iterator = 0;
1051
1052
  this.initialPrefix = null;
1052
1053
  }
1053
1054
  HistoryController.prototype = {
@@ -1372,7 +1373,7 @@
1372
1373
  }
1373
1374
  },
1374
1375
  evalInput: function(cm, vim) {
1375
- // If the motion comand is set, execute both the operator and motion.
1376
+ // If the motion command is set, execute both the operator and motion.
1376
1377
  // Otherwise return.
1377
1378
  var inputState = vim.inputState;
1378
1379
  var motion = inputState.motion;
@@ -1909,7 +1910,7 @@
1909
1910
  },
1910
1911
 
1911
1912
  repeatLastCharacterSearch: function(cm, head, motionArgs) {
1912
- var lastSearch = vimGlobalState.lastChararacterSearch;
1913
+ var lastSearch = vimGlobalState.lastCharacterSearch;
1913
1914
  var repeat = motionArgs.repeat;
1914
1915
  var forward = motionArgs.forward === lastSearch.forward;
1915
1916
  var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
@@ -3002,7 +3003,7 @@
3002
3003
  // Only clip if the selection ends with trailing newline + whitespace
3003
3004
  if (/\n\s*$/.test(selection)) {
3004
3005
  var lines = selection.split('\n');
3005
- // We know this is all whitepsace.
3006
+ // We know this is all whitespace.
3006
3007
  lines.pop();
3007
3008
 
3008
3009
  // Cases:
@@ -3088,9 +3089,9 @@
3088
3089
  }
3089
3090
 
3090
3091
  function recordLastCharacterSearch(increment, args) {
3091
- vimGlobalState.lastChararacterSearch.increment = increment;
3092
- vimGlobalState.lastChararacterSearch.forward = args.forward;
3093
- vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter;
3092
+ vimGlobalState.lastCharacterSearch.increment = increment;
3093
+ vimGlobalState.lastCharacterSearch.forward = args.forward;
3094
+ vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter;
3094
3095
  }
3095
3096
 
3096
3097
  var symbolToMode = {
@@ -3289,8 +3290,6 @@
3289
3290
  line = cm.getLine(lineNum);
3290
3291
  pos = (dir > 0) ? 0 : line.length;
3291
3292
  }
3292
- // Should never get here.
3293
- throw new Error('The impossible happened.');
3294
3293
  }
3295
3294
 
3296
3295
  /**
@@ -3452,7 +3451,7 @@
3452
3451
  }
3453
3452
 
3454
3453
  // TODO: perhaps this finagling of start and end positions belonds
3455
- // in codmirror/replaceRange?
3454
+ // in codemirror/replaceRange?
3456
3455
  function selectCompanionObject(cm, head, symb, inclusive) {
3457
3456
  var cur = head, start, end;
3458
3457
 
@@ -3783,17 +3782,10 @@
3783
3782
  }
3784
3783
  }
3785
3784
  function makePrompt(prefix, desc) {
3786
- var raw = '';
3787
- if (prefix) {
3788
- raw += '<span style="font-family: monospace">' + prefix + '</span>';
3789
- }
3790
- raw += '<input type="text"/> ' +
3791
- '<span style="color: #888">';
3792
- if (desc) {
3793
- raw += '<span style="color: #888">';
3794
- raw += desc;
3795
- raw += '</span>';
3796
- }
3785
+ var raw = '<span style="font-family: monospace; white-space: pre">' +
3786
+ (prefix || "") + '<input type="text"></span>';
3787
+ if (desc)
3788
+ raw += ' <span style="color: #888">' + desc + '</span>';
3797
3789
  return raw;
3798
3790
  }
3799
3791
  var searchPromptDesc = '(Javascript regexp)';
@@ -4514,14 +4506,21 @@
4514
4506
  if (CodeMirror.commands.save) {
4515
4507
  // If a save command is defined, call it.
4516
4508
  CodeMirror.commands.save(cm);
4517
- } else {
4518
- // Saves to text area if no save command is defined.
4509
+ } else if (cm.save) {
4510
+ // Saves to text area if no save command is defined and cm.save() is available.
4519
4511
  cm.save();
4520
4512
  }
4521
4513
  },
4522
4514
  nohlsearch: function(cm) {
4523
4515
  clearSearchHighlight(cm);
4524
4516
  },
4517
+ yank: function (cm) {
4518
+ var cur = copyCursor(cm.getCursor());
4519
+ var line = cur.line;
4520
+ var lineText = cm.getLine(line);
4521
+ vimGlobalState.registerController.pushText(
4522
+ '0', 'yank', lineText, true, true);
4523
+ },
4525
4524
  delmarks: function(cm, params) {
4526
4525
  if (!params.argString || !trim(params.argString)) {
4527
4526
  showConfirm(cm, 'Argument required');
@@ -11,21 +11,19 @@
11
11
  })(function(CodeMirror) {
12
12
  "use strict";
13
13
 
14
- function Context(indented, column, type, align, prev) {
14
+ function Context(indented, column, type, info, align, prev) {
15
15
  this.indented = indented;
16
16
  this.column = column;
17
17
  this.type = type;
18
+ this.info = info;
18
19
  this.align = align;
19
20
  this.prev = prev;
20
21
  }
21
- function isStatement(type) {
22
- return type == "statement" || type == "switchstatement" || type == "namespace";
23
- }
24
- function pushContext(state, col, type) {
22
+ function pushContext(state, col, type, info) {
25
23
  var indent = state.indented;
26
- if (state.context && isStatement(state.context.type) && !isStatement(type))
24
+ if (state.context && state.context.type != "statement" && type != "statement")
27
25
  indent = state.context.indented;
28
- return state.context = new Context(indent, col, type, null, state.context);
26
+ return state.context = new Context(indent, col, type, info, null, state.context);
29
27
  }
30
28
  function popContext(state) {
31
29
  var t = state.context.type;
@@ -34,15 +32,16 @@ function popContext(state) {
34
32
  return state.context = state.context.prev;
35
33
  }
36
34
 
37
- function typeBefore(stream, state) {
35
+ function typeBefore(stream, state, pos) {
38
36
  if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
39
- if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true;
37
+ if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
38
+ if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
40
39
  }
41
40
 
42
41
  function isTopScope(context) {
43
42
  for (;;) {
44
43
  if (!context || context.type == "top") return true;
45
- if (context.type == "}" && context.prev.type != "namespace") return false;
44
+ if (context.type == "}" && context.prev.info != "namespace") return false;
46
45
  context = context.prev;
47
46
  }
48
47
  }
@@ -147,13 +146,18 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
147
146
  return "comment";
148
147
  }
149
148
 
149
+ function maybeEOL(stream, state) {
150
+ if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
151
+ state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
152
+ }
153
+
150
154
  // Interface
151
155
 
152
156
  return {
153
157
  startState: function(basecolumn) {
154
158
  return {
155
159
  tokenize: null,
156
- context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
160
+ context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
157
161
  indented: 0,
158
162
  startOfLine: true,
159
163
  prevToken: null
@@ -167,36 +171,31 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
167
171
  state.indented = stream.indentation();
168
172
  state.startOfLine = true;
169
173
  }
170
- if (stream.eatSpace()) return null;
174
+ if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
171
175
  curPunc = isDefKeyword = null;
172
176
  var style = (state.tokenize || tokenBase)(stream, state);
173
177
  if (style == "comment" || style == "meta") return style;
174
178
  if (ctx.align == null) ctx.align = true;
175
179
 
176
- if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);
180
+ if (endStatement.test(curPunc)) while (state.context.type == "statement") popContext(state);
177
181
  else if (curPunc == "{") pushContext(state, stream.column(), "}");
178
182
  else if (curPunc == "[") pushContext(state, stream.column(), "]");
179
183
  else if (curPunc == "(") pushContext(state, stream.column(), ")");
180
184
  else if (curPunc == "}") {
181
- while (isStatement(ctx.type)) ctx = popContext(state);
185
+ while (ctx.type == "statement") ctx = popContext(state);
182
186
  if (ctx.type == "}") ctx = popContext(state);
183
- while (isStatement(ctx.type)) ctx = popContext(state);
187
+ while (ctx.type == "statement") ctx = popContext(state);
184
188
  }
185
189
  else if (curPunc == ctx.type) popContext(state);
186
190
  else if (indentStatements &&
187
191
  (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
188
- (isStatement(ctx.type) && curPunc == "newstatement"))) {
189
- var type = "statement";
190
- if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
191
- type = "switchstatement";
192
- else if (style == "keyword" && stream.current() == "namespace")
193
- type = "namespace";
194
- pushContext(state, stream.column(), type);
192
+ (ctx.type == "statement" && curPunc == "newstatement"))) {
193
+ pushContext(state, stream.column(), "statement", stream.current());
195
194
  }
196
195
 
197
196
  if (style == "variable" &&
198
197
  ((state.prevToken == "def" ||
199
- (parserConfig.typeFirstDefinitions && typeBefore(stream, state) &&
198
+ (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
200
199
  isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
201
200
  style = "def";
202
201
 
@@ -209,24 +208,28 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
209
208
 
210
209
  state.startOfLine = false;
211
210
  state.prevToken = isDefKeyword ? "def" : style || curPunc;
211
+ maybeEOL(stream, state);
212
212
  return style;
213
213
  },
214
214
 
215
215
  indent: function(state, textAfter) {
216
- if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
216
+ if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
217
217
  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
218
- if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
218
+ if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
219
+ if (parserConfig.dontIndentStatements)
220
+ while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
221
+ ctx = ctx.prev
219
222
  if (hooks.indent) {
220
223
  var hook = hooks.indent(state, ctx, textAfter);
221
224
  if (typeof hook == "number") return hook
222
225
  }
223
226
  var closing = firstChar == ctx.type;
224
- var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
227
+ var switchBlock = ctx.prev && ctx.prev.info == "switch";
225
228
  if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
226
229
  while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
227
230
  return ctx.indented
228
231
  }
229
- if (isStatement(ctx.type))
232
+ if (ctx.type == "statement")
230
233
  return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
231
234
  if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
232
235
  return ctx.column + (closing ? 0 : 1);
@@ -386,6 +389,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
386
389
  defKeywords: words("class namespace struct enum union"),
387
390
  typeFirstDefinitions: true,
388
391
  atoms: words("true false null"),
392
+ dontIndentStatements: /^template$/,
389
393
  hooks: {
390
394
  "#": cppHook,
391
395
  "*": pointerHook,
@@ -429,6 +433,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
429
433
  typeFirstDefinitions: true,
430
434
  atoms: words("true false null"),
431
435
  endStatement: /^[;:]$/,
436
+ number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
432
437
  hooks: {
433
438
  "@": function(stream) {
434
439
  stream.eatWhile(/[\w\$_]/);
@@ -531,7 +536,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
531
536
  "=": function(stream, state) {
532
537
  var cx = state.context
533
538
  if (cx.type == "}" && cx.align && stream.eat(">")) {
534
- state.context = new Context(cx.indented, cx.column, cx.type, null, cx.prev)
539
+ state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
535
540
  return "operator"
536
541
  } else {
537
542
  return false
@@ -667,7 +672,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
667
672
 
668
673
  def("text/x-objectivec", {
669
674
  name: "clike",
670
- keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
675
+ keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
671
676
  "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
672
677
  types: words(cTypes),
673
678
  atoms: words("YES NO NULL NILL ON OFF true false"),