codemirror-rails 4.8 → 4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -6
  3. data/lib/codemirror/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/codemirror.js +289 -184
  5. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/display/panel.js +94 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +4 -4
  8. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +1 -2
  9. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +1 -1
  10. data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +8 -3
  12. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +7 -4
  14. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +3 -4
  15. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +170 -63
  16. data/vendor/assets/javascripts/codemirror/addons/mode/simple.js +11 -8
  17. data/vendor/assets/javascripts/codemirror/addons/scroll/annotatescrollbar.js +76 -0
  18. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +139 -0
  19. data/vendor/assets/javascripts/codemirror/addons/search/matchesonscrollbar.js +90 -0
  20. data/vendor/assets/javascripts/codemirror/addons/search/search.js +9 -4
  21. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +5 -3
  22. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +25 -7
  23. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +181 -109
  24. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -2
  25. data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +5 -3
  26. data/vendor/assets/javascripts/codemirror/modes/cypher.js +1 -1
  27. data/vendor/assets/javascripts/codemirror/modes/dart.js +50 -0
  28. data/vendor/assets/javascripts/codemirror/modes/dockerfile.js +5 -9
  29. data/vendor/assets/javascripts/codemirror/modes/ebnf.js +195 -0
  30. data/vendor/assets/javascripts/codemirror/modes/javascript.js +2 -0
  31. data/vendor/assets/javascripts/codemirror/modes/markdown.js +3 -3
  32. data/vendor/assets/javascripts/codemirror/modes/puppet.js +2 -2
  33. data/vendor/assets/javascripts/codemirror/modes/shell.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/soy.js +198 -0
  35. data/vendor/assets/javascripts/codemirror/modes/spreadsheet.js +109 -0
  36. data/vendor/assets/javascripts/codemirror/modes/stex.js +4 -6
  37. data/vendor/assets/javascripts/codemirror/modes/textile.js +392 -476
  38. data/vendor/assets/javascripts/codemirror/modes/turtle.js +3 -1
  39. data/vendor/assets/stylesheets/codemirror.css +2 -11
  40. data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +14 -0
  41. data/vendor/assets/stylesheets/codemirror/addons/scroll/simplescrollbars.css +66 -0
  42. data/vendor/assets/stylesheets/codemirror/addons/search/matchesonscrollbar.css +8 -0
  43. data/vendor/assets/stylesheets/codemirror/themes/tomorrow-night-bright.css +35 -0
  44. data/vendor/assets/stylesheets/codemirror/themes/zenburn.css +37 -0
  45. metadata +14 -3
  46. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +0 -102
@@ -77,11 +77,11 @@
77
77
  { keys: '<Up>', type: 'keyToKey', toKeys: 'k' },
78
78
  { keys: '<Down>', type: 'keyToKey', toKeys: 'j' },
79
79
  { keys: '<Space>', type: 'keyToKey', toKeys: 'l' },
80
- { keys: '<BS>', type: 'keyToKey', toKeys: 'h' },
80
+ { keys: '<BS>', type: 'keyToKey', toKeys: 'h', context: 'normal'},
81
81
  { keys: '<C-Space>', type: 'keyToKey', toKeys: 'W' },
82
- { keys: '<C-BS>', type: 'keyToKey', toKeys: 'B' },
82
+ { keys: '<C-BS>', type: 'keyToKey', toKeys: 'B', context: 'normal' },
83
83
  { keys: '<S-Space>', type: 'keyToKey', toKeys: 'w' },
84
- { keys: '<S-BS>', type: 'keyToKey', toKeys: 'b' },
84
+ { keys: '<S-BS>', type: 'keyToKey', toKeys: 'b', context: 'normal' },
85
85
  { keys: '<C-n>', type: 'keyToKey', toKeys: 'j' },
86
86
  { keys: '<C-p>', type: 'keyToKey', toKeys: 'k' },
87
87
  { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>' },
@@ -229,55 +229,7 @@
229
229
 
230
230
  var Pos = CodeMirror.Pos;
231
231
 
232
- var modifierCodes = [16, 17, 18, 91];
233
- var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'};
234
- var mac = /Mac/.test(navigator.platform);
235
232
  var Vim = function() {
236
- function lookupKey(e) {
237
- var keyCode = e.keyCode;
238
- if (modifierCodes.indexOf(keyCode) != -1) { return; }
239
- var hasModifier = e.ctrlKey || e.metaKey;
240
- var key = CodeMirror.keyNames[keyCode];
241
- key = specialKey[key] || key;
242
- var name = '';
243
- if (e.ctrlKey) { name += 'C-'; }
244
- if (e.altKey) { name += 'A-'; }
245
- if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) {
246
- // Shift key bindings can only specified for special characters.
247
- return;
248
- } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) {
249
- name += 'S-';
250
- }
251
- if (key.length == 1) { key = key.toLowerCase(); }
252
- name += key;
253
- if (name.length > 1) { name = '<' + name + '>'; }
254
- return name;
255
- }
256
- // Keys with modifiers are handled using keydown due to limitations of
257
- // keypress event.
258
- function handleKeyDown(cm, e) {
259
- var name = lookupKey(e);
260
- if (!name) { return; }
261
-
262
- CodeMirror.signal(cm, 'vim-keypress', name);
263
- if (CodeMirror.Vim.handleKey(cm, name, 'user')) {
264
- CodeMirror.e_stop(e);
265
- }
266
- }
267
- // Keys without modifiers are handled using keypress to work best with
268
- // non-standard keyboard layouts.
269
- function handleKeyPress(cm, e) {
270
- var code = e.charCode || e.keyCode;
271
- if (e.ctrlKey || e.metaKey || e.altKey ||
272
- e.shiftKey && code < 32) { return; }
273
- var name = String.fromCharCode(code);
274
-
275
- CodeMirror.signal(cm, 'vim-keypress', name);
276
- if (CodeMirror.Vim.handleKey(cm, name, 'user')) {
277
- CodeMirror.e_stop(e);
278
- }
279
- }
280
-
281
233
  function enterVimMode(cm) {
282
234
  cm.setOption('disableInput', true);
283
235
  cm.setOption('showCursorWhenSelecting', false);
@@ -285,8 +237,6 @@
285
237
  cm.on('cursorActivity', onCursorActivity);
286
238
  maybeInitVimState(cm);
287
239
  CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm));
288
- cm.on('keypress', handleKeyPress);
289
- cm.on('keydown', handleKeyDown);
290
240
  }
291
241
 
292
242
  function leaveVimMode(cm) {
@@ -294,8 +244,6 @@
294
244
  cm.off('cursorActivity', onCursorActivity);
295
245
  CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm));
296
246
  cm.state.vim = null;
297
- cm.off('keypress', handleKeyPress);
298
- cm.off('keydown', handleKeyDown);
299
247
  }
300
248
 
301
249
  function detachVimMap(cm, next) {
@@ -320,6 +268,60 @@
320
268
  else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap")))
321
269
  cm.setOption("keyMap", "default");
322
270
  });
271
+
272
+ function cmKey(key, cm) {
273
+ if (!cm) { return undefined; }
274
+ var vimKey = cmKeyToVimKey(key);
275
+ if (!vimKey) {
276
+ return false;
277
+ }
278
+ var cmd = CodeMirror.Vim.findKey(cm, vimKey);
279
+ if (typeof cmd == 'function') {
280
+ CodeMirror.signal(cm, 'vim-keypress', vimKey);
281
+ }
282
+ return cmd;
283
+ }
284
+
285
+ var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'};
286
+ var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'};
287
+ function cmKeyToVimKey(key) {
288
+ if (key.charAt(0) == '\'') {
289
+ // Keypress character binding of format "'a'"
290
+ return key.charAt(1);
291
+ }
292
+ var pieces = key.split('-');
293
+ if (/-$/.test(key)) {
294
+ // If the - key was typed, split will result in 2 extra empty strings
295
+ // in the array. Replace them with 1 '-'.
296
+ pieces.splice(-2, 2, '-');
297
+ }
298
+ var lastPiece = pieces[pieces.length - 1];
299
+ if (pieces.length == 1 && pieces[0].length == 1) {
300
+ // No-modifier bindings use literal character bindings above. Skip.
301
+ return false;
302
+ } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) {
303
+ // Ignore Shift+char bindings as they should be handled by literal character.
304
+ return false;
305
+ }
306
+ var hasCharacter = false;
307
+ for (var i = 0; i < pieces.length; i++) {
308
+ var piece = pieces[i];
309
+ if (piece in modifiers) { pieces[i] = modifiers[piece]; }
310
+ else { hasCharacter = true; }
311
+ if (piece in specialKeys) { pieces[i] = specialKeys[piece]; }
312
+ }
313
+ if (!hasCharacter) {
314
+ // Vim does not support modifier only keys.
315
+ return false;
316
+ }
317
+ // TODO: Current bindings expect the character to be lower case, but
318
+ // it looks like vim key notation uses upper case.
319
+ if (isUpperCase(lastPiece)) {
320
+ pieces[pieces.length - 1] = lastPiece.toLowerCase();
321
+ }
322
+ return '<' + pieces.join('-') + '>';
323
+ }
324
+
323
325
  function getOnPasteFn(cm) {
324
326
  var vim = cm.state.vim;
325
327
  if (!vim.onPasteFn) {
@@ -614,6 +616,8 @@
614
616
  // Testing hook.
615
617
  maybeInitVimState_: maybeInitVimState,
616
618
 
619
+ suppressErrorLogging: false,
620
+
617
621
  InsertModeKey: InsertModeKey,
618
622
  map: function(lhs, rhs, ctx) {
619
623
  // Add user defined key bindings.
@@ -629,9 +633,23 @@
629
633
  exCommands[name]=func;
630
634
  exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};
631
635
  },
632
- // This is the outermost function called by CodeMirror, after keys have
633
- // been mapped to their Vim equivalents.
634
- handleKey: function(cm, key, origin) {
636
+ handleKey: function (cm, key, origin) {
637
+ var command = this.findKey(cm, key, origin);
638
+ if (typeof command === 'function') {
639
+ return command();
640
+ }
641
+ },
642
+ /**
643
+ * This is the outermost function called by CodeMirror, after keys have
644
+ * been mapped to their Vim equivalents.
645
+ *
646
+ * Finds a command based on the key (and cached keys if there is a
647
+ * multi-key sequence). Returns `undefined` if no key is matched, a noop
648
+ * function if a partial match is found (multi-key), and a function to
649
+ * execute the bound command if a a key is matched. The function always
650
+ * returns true.
651
+ */
652
+ findKey: function(cm, key, origin) {
635
653
  var vim = maybeInitVimState(cm);
636
654
  function handleMacroRecording() {
637
655
  var macroModeState = vimGlobalState.macroModeState;
@@ -697,13 +715,7 @@
697
715
  cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input');
698
716
  }
699
717
  clearInputState(cm);
700
- var command = match.command;
701
- if (command.type == 'keyToKey') {
702
- doKeyToKey(command.toKeys);
703
- } else {
704
- commandDispatcher.processCommand(cm, vim, command);
705
- }
706
- return true;
718
+ return match.command;
707
719
  }
708
720
 
709
721
  function handleKeyNonInsertMode() {
@@ -721,31 +733,46 @@
721
733
  else if (match.type == 'partial') { return true; }
722
734
 
723
735
  vim.inputState.keyBuffer = '';
724
- var command = match.command;
725
736
  var keysMatcher = /^(\d*)(.*)$/.exec(keys);
726
737
  if (keysMatcher[1] && keysMatcher[1] != '0') {
727
738
  vim.inputState.pushRepeatDigit(keysMatcher[1]);
728
739
  }
729
- if (command.type == 'keyToKey') {
730
- doKeyToKey(command.toKeys);
731
- } else {
732
- commandDispatcher.processCommand(cm, vim, command);
733
- }
734
- return true;
740
+ return match.command;
735
741
  }
736
742
 
737
- return cm.operation(function() {
738
- cm.curOp.isVimOp = true;
739
- try {
740
- if (vim.insertMode) { return handleKeyInsertMode(); }
741
- else { return handleKeyNonInsertMode(); }
742
- } catch (e) {
743
- // clear VIM state in case it's in a bad state.
744
- cm.state.vim = undefined;
745
- maybeInitVimState(cm);
746
- throw e;
747
- }
748
- });
743
+ var command;
744
+ if (vim.insertMode) { command = handleKeyInsertMode(); }
745
+ else { command = handleKeyNonInsertMode(); }
746
+ if (command === false) {
747
+ return undefined;
748
+ } else if (command === true) {
749
+ // TODO: Look into using CodeMirror's multi-key handling.
750
+ // Return no-op since we are caching the key. Counts as handled, but
751
+ // don't want act on it just yet.
752
+ return function() {};
753
+ } else {
754
+ return function() {
755
+ return cm.operation(function() {
756
+ cm.curOp.isVimOp = true;
757
+ try {
758
+ if (command.type == 'keyToKey') {
759
+ doKeyToKey(command.toKeys);
760
+ } else {
761
+ commandDispatcher.processCommand(cm, vim, command);
762
+ }
763
+ } catch (e) {
764
+ // clear VIM state in case it's in a bad state.
765
+ cm.state.vim = undefined;
766
+ maybeInitVimState(cm);
767
+ if (!CodeMirror.Vim.suppressErrorLogging) {
768
+ console['log'](e);
769
+ }
770
+ throw e;
771
+ }
772
+ return true;
773
+ });
774
+ };
775
+ }
749
776
  },
750
777
  handleEx: function(cm, input) {
751
778
  exCommandDispatcher.processCommand(cm, input);
@@ -1306,7 +1333,9 @@
1306
1333
  newHead = copyCursor(origHead);
1307
1334
  }
1308
1335
  if (vim.visualMode) {
1309
- newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
1336
+ if (!(vim.visualBlock && newHead.ch === Infinity)) {
1337
+ newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
1338
+ }
1310
1339
  if (newAnchor) {
1311
1340
  newAnchor = clipCursorToContent(cm, newAnchor, true);
1312
1341
  }
@@ -1610,20 +1639,8 @@
1610
1639
  return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page');
1611
1640
  },
1612
1641
  moveByParagraph: function(cm, head, motionArgs) {
1613
- var line = head.line;
1614
- var repeat = motionArgs.repeat;
1615
- var inc = motionArgs.forward ? 1 : -1;
1616
- for (var i = 0; i < repeat; i++) {
1617
- if ((!motionArgs.forward && line === cm.firstLine() ) ||
1618
- (motionArgs.forward && line == cm.lastLine())) {
1619
- break;
1620
- }
1621
- line += inc;
1622
- while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) {
1623
- line += inc;
1624
- }
1625
- }
1626
- return Pos(line, 0);
1642
+ var dir = motionArgs.forward ? 1 : -1;
1643
+ return findParagraph(cm, head, motionArgs.repeat, dir);
1627
1644
  },
1628
1645
  moveByScroll: function(cm, head, motionArgs, vim) {
1629
1646
  var scrollbox = cm.getScrollInfo();
@@ -1723,7 +1740,7 @@
1723
1740
  return Pos(lineNum,
1724
1741
  findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)));
1725
1742
  },
1726
- textObjectManipulation: function(cm, head, motionArgs) {
1743
+ textObjectManipulation: function(cm, head, motionArgs, vim) {
1727
1744
  // TODO: lots of possible exceptions that can be thrown here. Try da(
1728
1745
  // outside of a () block.
1729
1746
 
@@ -1761,6 +1778,16 @@
1761
1778
  } else if (character === 'w') {
1762
1779
  tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
1763
1780
  false /** bigWord */);
1781
+ } else if (character === 'p') {
1782
+ tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);
1783
+ motionArgs.linewise = true;
1784
+ if (vim.visualMode) {
1785
+ if (!vim.visualLine) { vim.visualLine = true; }
1786
+ } else {
1787
+ var operatorArgs = vim.inputState.operatorArgs;
1788
+ if (operatorArgs) { operatorArgs.linewise = true; }
1789
+ tmp.end.line--;
1790
+ }
1764
1791
  } else {
1765
1792
  // No text object defined for this, don't move.
1766
1793
  return null;
@@ -3268,6 +3295,54 @@
3268
3295
  return idx;
3269
3296
  }
3270
3297
 
3298
+ function findParagraph(cm, head, repeat, dir, inclusive) {
3299
+ var line = head.line;
3300
+ var min = cm.firstLine();
3301
+ var max = cm.lastLine();
3302
+ var start, end, i = line;
3303
+ function isEmpty(i) { return !cm.getLine(i); }
3304
+ function isBoundary(i, dir, any) {
3305
+ if (any) { return isEmpty(i) != isEmpty(i + dir); }
3306
+ return !isEmpty(i) && isEmpty(i + dir);
3307
+ }
3308
+ if (dir) {
3309
+ while (min <= i && i <= max && repeat > 0) {
3310
+ if (isBoundary(i, dir)) { repeat--; }
3311
+ i += dir;
3312
+ }
3313
+ return new Pos(i, 0);
3314
+ }
3315
+
3316
+ var vim = cm.state.vim;
3317
+ if (vim.visualLine && isBoundary(line, 1, true)) {
3318
+ var anchor = vim.sel.anchor;
3319
+ if (isBoundary(anchor.line, -1, true)) {
3320
+ if (!inclusive || anchor.line != line) {
3321
+ line += 1;
3322
+ }
3323
+ }
3324
+ }
3325
+ var startState = isEmpty(line);
3326
+ for (i = line; i <= max && repeat; i++) {
3327
+ if (isBoundary(i, 1, true)) {
3328
+ if (!inclusive || isEmpty(i) != startState) {
3329
+ repeat--;
3330
+ }
3331
+ }
3332
+ }
3333
+ end = new Pos(i, 0);
3334
+ // select boundary before paragraph for the last one
3335
+ if (i > max && !startState) { startState = true; }
3336
+ else { inclusive = false; }
3337
+ for (i = line; i > min; i--) {
3338
+ if (!inclusive || isEmpty(i) == startState || i == line) {
3339
+ if (isBoundary(i, -1, true)) { break; }
3340
+ }
3341
+ }
3342
+ start = new Pos(i, 0);
3343
+ return { start: start, end: end };
3344
+ }
3345
+
3271
3346
  // TODO: perhaps this finagling of start and end positions belonds
3272
3347
  // in codmirror/replaceRange?
3273
3348
  function selectCompanionObject(cm, head, symb, inclusive) {
@@ -4476,7 +4551,8 @@
4476
4551
 
4477
4552
  CodeMirror.keyMap.vim = {
4478
4553
  attach: attachVimMap,
4479
- detach: detachVimMap
4554
+ detach: detachVimMap,
4555
+ call: cmKey
4480
4556
  };
4481
4557
 
4482
4558
  function exitInsertMode(cm) {
@@ -4549,20 +4625,16 @@
4549
4625
  },
4550
4626
  fallthrough: ['default'],
4551
4627
  attach: attachVimMap,
4552
- detach: detachVimMap
4553
- };
4554
-
4555
- CodeMirror.keyMap['await-second'] = {
4556
- fallthrough: ['vim-insert'],
4557
- attach: attachVimMap,
4558
- detach: detachVimMap
4628
+ detach: detachVimMap,
4629
+ call: cmKey
4559
4630
  };
4560
4631
 
4561
4632
  CodeMirror.keyMap['vim-replace'] = {
4562
4633
  'Backspace': 'goCharLeft',
4563
4634
  fallthrough: ['vim-insert'],
4564
4635
  attach: attachVimMap,
4565
- detach: detachVimMap
4636
+ detach: detachVimMap,
4637
+ call: cmKey
4566
4638
  };
4567
4639
 
4568
4640
  function executeMacroRegister(cm, vim, macroModeState, registerName) {
@@ -15,7 +15,7 @@
15
15
  })(function(CodeMirror) {
16
16
  "use strict";
17
17
 
18
- CodeMirror.defineMode("coffeescript", function(conf) {
18
+ CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
19
19
  var ERRORCLASS = "error";
20
20
 
21
21
  function wordRegexp(words) {
@@ -191,7 +191,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
191
191
  }
192
192
  }
193
193
  if (singleline) {
194
- if (conf.mode.singleLineStringErrors) {
194
+ if (parserConf.singleLineStringErrors) {
195
195
  outclass = ERRORCLASS;
196
196
  } else {
197
197
  state.tokenize = tokenBase;
@@ -12,6 +12,7 @@
12
12
  "use strict";
13
13
 
14
14
  CodeMirror.defineMode("commonlisp", function (config) {
15
+ var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;
15
16
  var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
16
17
  var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
17
18
  var symbol = /[^\s'`,@()\[\]";]/;
@@ -52,8 +53,8 @@ CodeMirror.defineMode("commonlisp", function (config) {
52
53
  var name = readSym(stream);
53
54
  if (name == ".") return null;
54
55
  type = "symbol";
55
- if (name == "nil" || name == "t") return "atom";
56
- if (name.charAt(0) == ":") return "keyword";
56
+ if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";
57
+ if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";
57
58
  if (name.charAt(0) == "&") return "variable-2";
58
59
  return "variable";
59
60
  }
@@ -80,7 +81,7 @@ CodeMirror.defineMode("commonlisp", function (config) {
80
81
 
81
82
  return {
82
83
  startState: function () {
83
- return {ctx: {prev: null, start: 0, indentTo: 0}, tokenize: base};
84
+ return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};
84
85
  },
85
86
 
86
87
  token: function (stream, state) {
@@ -98,6 +99,7 @@ CodeMirror.defineMode("commonlisp", function (config) {
98
99
  } else if (state.ctx.indentTo == "next") {
99
100
  state.ctx.indentTo = stream.column();
100
101
  }
102
+ state.lastType = type;
101
103
  }
102
104
  if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
103
105
  else if (type == "close") state.ctx = state.ctx.prev || state.ctx;