codemirror-rails 5.1 → 5.2

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +92 -39
  4. data/vendor/assets/javascripts/codemirror/addons/display/panel.js +22 -4
  5. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +5 -5
  6. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +63 -65
  7. data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +1 -1
  8. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +14 -9
  9. data/vendor/assets/javascripts/codemirror/addons/scroll/annotatescrollbar.js +19 -4
  10. data/vendor/assets/javascripts/codemirror/addons/search/matchesonscrollbar.js +3 -1
  11. data/vendor/assets/javascripts/codemirror/addons/search/search.js +7 -4
  12. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +2 -2
  13. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +117 -23
  15. data/vendor/assets/javascripts/codemirror/modes/clike.js +1 -1
  16. data/vendor/assets/javascripts/codemirror/modes/css.js +3 -1
  17. data/vendor/assets/javascripts/codemirror/modes/django.js +307 -24
  18. data/vendor/assets/javascripts/codemirror/modes/handlebars.js +53 -0
  19. data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -1
  20. data/vendor/assets/javascripts/codemirror/modes/less_test.js +3 -0
  21. data/vendor/assets/javascripts/codemirror/modes/markdown.js +15 -13
  22. data/vendor/assets/javascripts/codemirror/modes/mumps.js +148 -0
  23. data/vendor/assets/javascripts/codemirror/modes/python.js +2 -4
  24. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/modes/smarty.js +17 -6
  26. data/vendor/assets/javascripts/codemirror/modes/soy.js +3 -3
  27. data/vendor/assets/javascripts/codemirror/modes/sql.js +4 -4
  28. data/vendor/assets/javascripts/codemirror/modes/stylus.js +8 -3
  29. data/vendor/assets/javascripts/codemirror/modes/z80.js +34 -18
  30. data/vendor/assets/stylesheets/codemirror.css +2 -0
  31. data/vendor/assets/stylesheets/codemirror/themes/liquibyte.css +95 -0
  32. data/vendor/assets/stylesheets/codemirror/themes/monokai.css +1 -1
  33. data/vendor/assets/stylesheets/codemirror/themes/solarized.css +1 -1
  34. metadata +4 -1
@@ -23,7 +23,7 @@
23
23
 
24
24
  function validator(text, options) {
25
25
  if (!window.JSHINT) return [];
26
- JSHINT(text, options);
26
+ JSHINT(text, options, options.globals);
27
27
  var errors = JSHINT.data().errors, result = [];
28
28
  if (errors) parseErrors(errors, result);
29
29
  return result;
@@ -14,12 +14,14 @@
14
14
  CodeMirror.multiplexingMode = function(outer /*, others */) {
15
15
  // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
16
16
  var others = Array.prototype.slice.call(arguments, 1);
17
- var n_others = others.length;
18
17
 
19
- function indexOf(string, pattern, from) {
20
- if (typeof pattern == "string") return string.indexOf(pattern, from);
18
+ function indexOf(string, pattern, from, returnEnd) {
19
+ if (typeof pattern == "string") {
20
+ var found = string.indexOf(pattern, from);
21
+ return returnEnd && found > -1 ? found + pattern.length : found;
22
+ }
21
23
  var m = pattern.exec(from ? string.slice(from) : string);
22
- return m ? m.index + from : -1;
24
+ return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
23
25
  }
24
26
 
25
27
  return {
@@ -42,11 +44,11 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
42
44
  token: function(stream, state) {
43
45
  if (!state.innerActive) {
44
46
  var cutOff = Infinity, oldContent = stream.string;
45
- for (var i = 0; i < n_others; ++i) {
47
+ for (var i = 0; i < others.length; ++i) {
46
48
  var other = others[i];
47
49
  var found = indexOf(oldContent, other.open, stream.pos);
48
50
  if (found == stream.pos) {
49
- stream.match(other.open);
51
+ if (!other.parseDelimiters) stream.match(other.open);
50
52
  state.innerActive = other;
51
53
  state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
52
54
  return other.delimStyle;
@@ -64,8 +66,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
64
66
  state.innerActive = state.inner = null;
65
67
  return this.token(stream, state);
66
68
  }
67
- var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
68
- if (found == stream.pos) {
69
+ var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
70
+ if (found == stream.pos && !curInner.parseDelimiters) {
69
71
  stream.match(curInner.close);
70
72
  state.innerActive = state.inner = null;
71
73
  return curInner.delimStyle;
@@ -74,6 +76,9 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
74
76
  var innerToken = curInner.mode.token(stream, state.inner);
75
77
  if (found > -1) stream.string = oldContent;
76
78
 
79
+ if (found == stream.pos && curInner.parseDelimiters)
80
+ state.innerActive = state.inner = null;
81
+
77
82
  if (curInner.innerStyle) {
78
83
  if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
79
84
  else innerToken = curInner.innerStyle;
@@ -95,7 +100,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
95
100
  mode.blankLine(state.innerActive ? state.inner : state.outer);
96
101
  }
97
102
  if (!state.innerActive) {
98
- for (var i = 0; i < n_others; ++i) {
103
+ for (var i = 0; i < others.length; ++i) {
99
104
  var other = others[i];
100
105
  if (other.open === "\n") {
101
106
  state.innerActive = other;
@@ -68,15 +68,30 @@
68
68
  var cm = this.cm, hScale = this.hScale;
69
69
 
70
70
  var frag = document.createDocumentFragment(), anns = this.annotations;
71
+
72
+ var wrapping = cm.getOption("lineWrapping");
73
+ var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
74
+ var curLine = null, curLineObj = null;
75
+ function getY(pos, top) {
76
+ if (curLine != pos.line) {
77
+ curLine = pos.line;
78
+ curLineObj = cm.getLineHandle(curLine);
79
+ }
80
+ if (wrapping && curLineObj.height > singleLineH)
81
+ return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
82
+ var topY = cm.heightAtLine(curLineObj, "local");
83
+ return topY + (top ? 0 : curLineObj.height);
84
+ }
85
+
71
86
  if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
72
87
  var ann = anns[i];
73
- var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
74
- var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
88
+ var top = nextTop || getY(ann.from, true) * hScale;
89
+ var bottom = getY(ann.to, false) * hScale;
75
90
  while (i < anns.length - 1) {
76
- nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
91
+ nextTop = getY(anns[i + 1].from, true) * hScale;
77
92
  if (nextTop > bottom + .9) break;
78
93
  ann = anns[++i];
79
- bottom = cm.charCoords(ann.to, "local").bottom * hScale;
94
+ bottom = getY(ann.to, false) * hScale;
80
95
  }
81
96
  if (bottom == top) continue;
82
97
  var height = Math.max(bottom - top, 3);
@@ -19,6 +19,7 @@
19
19
 
20
20
  function SearchAnnotation(cm, query, caseFold, options) {
21
21
  this.cm = cm;
22
+ this.options = options;
22
23
  var annotateOptions = {listenForChanges: false};
23
24
  for (var prop in options) annotateOptions[prop] = options[prop];
24
25
  if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
@@ -46,11 +47,12 @@
46
47
  if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
47
48
  }
48
49
  var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
50
+ var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
49
51
  while (cursor.findNext()) {
50
52
  var match = {from: cursor.from(), to: cursor.to()};
51
53
  if (match.from.line >= this.gap.to) break;
52
54
  this.matches.splice(i++, 0, match);
53
- if (this.matches.length > MAX_MATCHES) break;
55
+ if (this.matches.length > maxMatches) break;
54
56
  }
55
57
  this.gap = null;
56
58
  };
@@ -39,7 +39,7 @@
39
39
  }
40
40
 
41
41
  function SearchState() {
42
- this.posFrom = this.posTo = this.query = null;
42
+ this.posFrom = this.posTo = this.lastQuery = this.query = null;
43
43
  this.overlay = null;
44
44
  }
45
45
  function getSearchState(cm) {
@@ -53,7 +53,7 @@
53
53
  return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
54
54
  }
55
55
  function dialog(cm, text, shortText, deflt, f) {
56
- if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
56
+ if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
57
57
  else f(prompt(shortText, deflt));
58
58
  }
59
59
  function confirmDialog(cm, text, shortText, fs) {
@@ -75,7 +75,8 @@
75
75
  function doSearch(cm, rev) {
76
76
  var state = getSearchState(cm);
77
77
  if (state.query) return findNext(cm, rev);
78
- dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
78
+ var q = cm.getSelection() || state.lastQuery;
79
+ dialog(cm, queryDialog, "Search for:", q, function(query) {
79
80
  cm.operation(function() {
80
81
  if (!query || state.query) return;
81
82
  state.query = parseQuery(query);
@@ -104,6 +105,7 @@
104
105
  });}
105
106
  function clearSearch(cm) {cm.operation(function() {
106
107
  var state = getSearchState(cm);
108
+ state.lastQuery = state.query;
107
109
  if (!state.query) return;
108
110
  state.query = null;
109
111
  cm.removeOverlay(state.overlay);
@@ -116,7 +118,8 @@
116
118
  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
117
119
  function replace(cm, all) {
118
120
  if (cm.getOption("readOnly")) return;
119
- dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
121
+ var query = cm.getSelection() || getSearchState().lastQuery;
122
+ dialog(cm, replaceQueryDialog, "Replace:", query, function(query) {
120
123
  if (!query) return;
121
124
  query = parseQuery(query);
122
125
  dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
@@ -148,10 +148,10 @@
148
148
  from: function() {if (this.atOccurrence) return this.pos.from;},
149
149
  to: function() {if (this.atOccurrence) return this.pos.to;},
150
150
 
151
- replace: function(newText) {
151
+ replace: function(newText, origin) {
152
152
  if (!this.atOccurrence) return;
153
153
  var lines = CodeMirror.splitLines(newText);
154
- this.doc.replaceRange(lines, this.pos.from, this.pos.to);
154
+ this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
155
155
  this.pos.to = Pos(this.pos.from.line + lines.length - 1,
156
156
  lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
157
157
  }
@@ -416,7 +416,7 @@
416
416
  var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
417
417
  var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
418
418
 
419
- if (!/\S/.test(toStartOfLine) && column % cm.getOption("indentUnit") == 0)
419
+ if (toStartOfLine && !/\S/.test(toStartOfLine) && column % cm.getOption("indentUnit") == 0)
420
420
  return cm.indentSelection("subtract");
421
421
  else
422
422
  return CodeMirror.Pass;
@@ -382,18 +382,30 @@
382
382
  }
383
383
 
384
384
  var options = {};
385
- function defineOption(name, defaultValue, type) {
386
- if (defaultValue === undefined) { throw Error('defaultValue is required'); }
385
+ function defineOption(name, defaultValue, type, aliases, callback) {
386
+ if (defaultValue === undefined && !callback) {
387
+ throw Error('defaultValue is required unless callback is provided');
388
+ }
387
389
  if (!type) { type = 'string'; }
388
390
  options[name] = {
389
391
  type: type,
390
- defaultValue: defaultValue
392
+ defaultValue: defaultValue,
393
+ callback: callback
391
394
  };
392
- setOption(name, defaultValue);
395
+ if (aliases) {
396
+ for (var i = 0; i < aliases.length; i++) {
397
+ options[aliases[i]] = options[name];
398
+ }
399
+ }
400
+ if (defaultValue) {
401
+ setOption(name, defaultValue);
402
+ }
393
403
  }
394
404
 
395
- function setOption(name, value) {
405
+ function setOption(name, value, cm, cfg) {
396
406
  var option = options[name];
407
+ cfg = cfg || {};
408
+ var scope = cfg.scope;
397
409
  if (!option) {
398
410
  throw Error('Unknown option: ' + name);
399
411
  }
@@ -405,17 +417,60 @@
405
417
  value = true;
406
418
  }
407
419
  }
408
- option.value = option.type == 'boolean' ? !!value : value;
420
+ if (option.callback) {
421
+ if (scope !== 'local') {
422
+ option.callback(value, undefined);
423
+ }
424
+ if (scope !== 'global' && cm) {
425
+ option.callback(value, cm);
426
+ }
427
+ } else {
428
+ if (scope !== 'local') {
429
+ option.value = option.type == 'boolean' ? !!value : value;
430
+ }
431
+ if (scope !== 'global' && cm) {
432
+ cm.state.vim.options[name] = {value: value};
433
+ }
434
+ }
409
435
  }
410
436
 
411
- function getOption(name) {
437
+ function getOption(name, cm, cfg) {
412
438
  var option = options[name];
439
+ cfg = cfg || {};
440
+ var scope = cfg.scope;
413
441
  if (!option) {
414
442
  throw Error('Unknown option: ' + name);
415
443
  }
416
- return option.value;
444
+ if (option.callback) {
445
+ var local = cm && option.callback(undefined, cm);
446
+ if (scope !== 'global' && local !== undefined) {
447
+ return local;
448
+ }
449
+ if (scope !== 'local') {
450
+ return option.callback();
451
+ }
452
+ return;
453
+ } else {
454
+ var local = (scope !== 'global') && (cm && cm.state.vim.options[name]);
455
+ return (local || (scope !== 'local') && option || {}).value;
456
+ }
417
457
  }
418
458
 
459
+ defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) {
460
+ // Option is local. Do nothing for global.
461
+ if (cm === undefined) {
462
+ return;
463
+ }
464
+ // The 'filetype' option proxies to the CodeMirror 'mode' option.
465
+ if (name === undefined) {
466
+ var mode = cm.getMode().name;
467
+ return mode == 'null' ? '' : mode;
468
+ } else {
469
+ var mode = name == '' ? 'null' : name;
470
+ cm.setOption('mode', mode);
471
+ }
472
+ });
473
+
419
474
  var createCircularJumpList = function() {
420
475
  var size = 100;
421
476
  var pointer = -1;
@@ -568,8 +623,9 @@
568
623
  visualBlock: false,
569
624
  lastSelection: null,
570
625
  lastPastedText: null,
571
- sel: {
572
- }
626
+ sel: {},
627
+ // Buffer-local/window-local values of vim options.
628
+ options: {}
573
629
  };
574
630
  }
575
631
  return cm.state.vim;
@@ -627,6 +683,8 @@
627
683
  // Add user defined key bindings.
628
684
  exCommandDispatcher.map(lhs, rhs, ctx);
629
685
  },
686
+ // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace
687
+ // them, or somehow make them work with the existing CodeMirror setOption/getOption API.
630
688
  setOption: setOption,
631
689
  getOption: getOption,
632
690
  defineOption: defineOption,
@@ -1178,7 +1236,8 @@
1178
1236
  }
1179
1237
  function onPromptKeyDown(e, query, close) {
1180
1238
  var keyName = CodeMirror.keyName(e);
1181
- if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
1239
+ if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
1240
+ (keyName == 'Backspace' && query == '')) {
1182
1241
  vimGlobalState.searchHistoryController.pushInput(query);
1183
1242
  vimGlobalState.searchHistoryController.reset();
1184
1243
  updateSearchQuery(cm, originalQuery);
@@ -1188,6 +1247,10 @@
1188
1247
  clearInputState(cm);
1189
1248
  close();
1190
1249
  cm.focus();
1250
+ } else if (keyName == 'Ctrl-U') {
1251
+ // Ctrl-U clears input.
1252
+ CodeMirror.e_stop(e);
1253
+ close('');
1191
1254
  }
1192
1255
  }
1193
1256
  switch (command.searchArgs.querySrc) {
@@ -1248,7 +1311,8 @@
1248
1311
  }
1249
1312
  function onPromptKeyDown(e, input, close) {
1250
1313
  var keyName = CodeMirror.keyName(e), up;
1251
- if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
1314
+ if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
1315
+ (keyName == 'Backspace' && input == '')) {
1252
1316
  vimGlobalState.exCommandHistoryController.pushInput(input);
1253
1317
  vimGlobalState.exCommandHistoryController.reset();
1254
1318
  CodeMirror.e_stop(e);
@@ -1260,6 +1324,10 @@
1260
1324
  up = keyName == 'Up' ? true : false;
1261
1325
  input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
1262
1326
  close(input);
1327
+ } else if (keyName == 'Ctrl-U') {
1328
+ // Ctrl-U clears input.
1329
+ CodeMirror.e_stop(e);
1330
+ close('');
1263
1331
  } else {
1264
1332
  if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
1265
1333
  vimGlobalState.exCommandHistoryController.reset();
@@ -1289,8 +1357,8 @@
1289
1357
  var registerName = inputState.registerName;
1290
1358
  var sel = vim.sel;
1291
1359
  // TODO: Make sure cm and vim selections are identical outside visual mode.
1292
- var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head'));
1293
- var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor'));
1360
+ var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head'));
1361
+ var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor'));
1294
1362
  var oldHead = copyCursor(origHead);
1295
1363
  var oldAnchor = copyCursor(origAnchor);
1296
1364
  var newHead, newAnchor;
@@ -1856,10 +1924,11 @@
1856
1924
  var anchor = ranges[0].anchor,
1857
1925
  head = ranges[0].head;
1858
1926
  text = cm.getRange(anchor, head);
1859
- if (!isWhiteSpaceString(text)) {
1927
+ var lastState = vim.lastEditInputState || {};
1928
+ if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
1860
1929
  // Exclude trailing whitespace if the range is not all whitespace.
1861
1930
  var match = (/\s+$/).exec(text);
1862
- if (match) {
1931
+ if (match && lastState.motionArgs && lastState.motionArgs.forward) {
1863
1932
  head = offsetCursor(head, 0, - match[0].length);
1864
1933
  text = text.slice(0, - match[0].length);
1865
1934
  }
@@ -3849,6 +3918,7 @@
3849
3918
  // pair of commands that have a shared prefix, at least one of their
3850
3919
  // shortNames must not match the prefix of the other command.
3851
3920
  var defaultExCommandMap = [
3921
+ { name: 'colorscheme', shortName: 'colo' },
3852
3922
  { name: 'map' },
3853
3923
  { name: 'imap', shortName: 'im' },
3854
3924
  { name: 'nmap', shortName: 'nm' },
@@ -3857,7 +3927,10 @@
3857
3927
  { name: 'write', shortName: 'w' },
3858
3928
  { name: 'undo', shortName: 'u' },
3859
3929
  { name: 'redo', shortName: 'red' },
3860
- { name: 'set', shortName: 'set' },
3930
+ { name: 'set', shortName: 'se' },
3931
+ { name: 'set', shortName: 'se' },
3932
+ { name: 'setlocal', shortName: 'setl' },
3933
+ { name: 'setglobal', shortName: 'setg' },
3861
3934
  { name: 'sort', shortName: 'sor' },
3862
3935
  { name: 'substitute', shortName: 's', possiblyAsync: true },
3863
3936
  { name: 'nohlsearch', shortName: 'noh' },
@@ -4089,6 +4162,13 @@
4089
4162
  };
4090
4163
 
4091
4164
  var exCommands = {
4165
+ colorscheme: function(cm, params) {
4166
+ if (!params.args || params.args.length < 1) {
4167
+ showConfirm(cm, cm.getOption('theme'));
4168
+ return;
4169
+ }
4170
+ cm.setOption('theme', params.args[0]);
4171
+ },
4092
4172
  map: function(cm, params, ctx) {
4093
4173
  var mapArgs = params.args;
4094
4174
  if (!mapArgs || mapArgs.length < 2) {
@@ -4122,6 +4202,9 @@
4122
4202
  },
4123
4203
  set: function(cm, params) {
4124
4204
  var setArgs = params.args;
4205
+ // Options passed through to the setOption/getOption calls. May be passed in by the
4206
+ // local/global versions of the set command
4207
+ var setCfg = params.setCfg || {};
4125
4208
  if (!setArgs || setArgs.length < 1) {
4126
4209
  if (cm) {
4127
4210
  showConfirm(cm, 'Invalid mapping: ' + params.input);
@@ -4145,24 +4228,35 @@
4145
4228
  optionName = optionName.substring(2);
4146
4229
  value = false;
4147
4230
  }
4231
+
4148
4232
  var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
4149
4233
  if (optionIsBoolean && value == undefined) {
4150
4234
  // Calling set with a boolean option sets it to true.
4151
4235
  value = true;
4152
4236
  }
4153
- if (!optionIsBoolean && !value || forceGet) {
4154
- var oldValue = getOption(optionName);
4155
- // If no value is provided, then we assume this is a get.
4237
+ // If no value is provided, then we assume this is a get.
4238
+ if (!optionIsBoolean && value === undefined || forceGet) {
4239
+ var oldValue = getOption(optionName, cm, setCfg);
4156
4240
  if (oldValue === true || oldValue === false) {
4157
4241
  showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
4158
4242
  } else {
4159
4243
  showConfirm(cm, ' ' + optionName + '=' + oldValue);
4160
4244
  }
4161
4245
  } else {
4162
- setOption(optionName, value);
4246
+ setOption(optionName, value, cm, setCfg);
4163
4247
  }
4164
4248
  },
4165
- registers: function(cm,params) {
4249
+ setlocal: function (cm, params) {
4250
+ // setCfg is passed through to setOption
4251
+ params.setCfg = {scope: 'local'};
4252
+ this.set(cm, params);
4253
+ },
4254
+ setglobal: function (cm, params) {
4255
+ // setCfg is passed through to setOption
4256
+ params.setCfg = {scope: 'global'};
4257
+ this.set(cm, params);
4258
+ },
4259
+ registers: function(cm, params) {
4166
4260
  var regArgs = params.args;
4167
4261
  var registers = vimGlobalState.registerController.registers;
4168
4262
  var regInfo = '----------Registers----------<br><br>';
@@ -4784,7 +4878,7 @@
4784
4878
  }
4785
4879
  function updateFakeCursor(cm) {
4786
4880
  var vim = cm.state.vim;
4787
- var from = copyCursor(vim.sel.head);
4881
+ var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
4788
4882
  var to = offsetCursor(from, 0, 1);
4789
4883
  if (vim.fakeCursor) {
4790
4884
  vim.fakeCursor.clear();