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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb8e0f584aeb96820145217fba9658635664ce33
4
- data.tar.gz: 91c2ff5b741853b45e908e33b5c940e5f1d8bc3e
3
+ metadata.gz: 050b051a53f2101672d02e5b5a5b0e8882e01efa
4
+ data.tar.gz: 0a4451cf450a3dd4bd78c7269d779dfdda8fd7dd
5
5
  SHA512:
6
- metadata.gz: c779e40abb5943d41d80f957e9e311d2fe4e191a2ad56e007f6225771c9bc0189d5b22fca1885289fd0ab01af7224777230b4533e21a3df5c4c69323aaf01c2c
7
- data.tar.gz: 154d437fc78cbfdd03e7bdde74a734a54b098edc1bce1ac4c4cd2c742a8c02135ded6af0731bd91fe2a2f819bc47a5231964e0a58ca3378f12b28c8c74450a3e
6
+ metadata.gz: 00407212b29c41420da933d548ab4d703276f80a539a5593ac6ca21127f5837a7fd0fbf21af9414dd1bf275bbf96fa0de3c83be7834d7118767f6f29de00da45
7
+ data.tar.gz: 49f03cf54ac054fd36d13e8e038956647eeb0120db8c3186a5036575d185e8ca71d2c1e9556bdcf675c95e2dffefb016772dfb5c59664cdad12caed2af2df4bb
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '5.1'
4
- CODEMIRROR_VERSION = '5.1'
3
+ VERSION = '5.2'
4
+ CODEMIRROR_VERSION = '5.2'
5
5
  end
6
6
  end
@@ -1079,7 +1079,7 @@
1079
1079
  // was made out of.
1080
1080
  var lastCopied = null;
1081
1081
 
1082
- function applyTextInput(cm, inserted, deleted, sel) {
1082
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
1083
1083
  var doc = cm.doc;
1084
1084
  cm.display.shift = false;
1085
1085
  if (!sel) sel = doc.sel;
@@ -1105,7 +1105,7 @@
1105
1105
  }
1106
1106
  var updateInput = cm.curOp.updateInput;
1107
1107
  var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
1108
- origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
1108
+ origin: origin || (cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
1109
1109
  makeChange(cm.doc, changeEvent);
1110
1110
  signalLater(cm, "inputRead", cm, changeEvent);
1111
1111
  // When an 'electric' character is inserted, immediately trigger a reindent
@@ -1114,16 +1114,18 @@
1114
1114
  (!i || sel.ranges[i - 1].head.line != range.head.line)) {
1115
1115
  var mode = cm.getModeAt(range.head);
1116
1116
  var end = changeEnd(changeEvent);
1117
+ var indented = false;
1117
1118
  if (mode.electricChars) {
1118
1119
  for (var j = 0; j < mode.electricChars.length; j++)
1119
1120
  if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
1120
- indentLine(cm, end.line, "smart");
1121
+ indented = indentLine(cm, end.line, "smart");
1121
1122
  break;
1122
1123
  }
1123
1124
  } else if (mode.electricInput) {
1124
1125
  if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
1125
- indentLine(cm, end.line, "smart");
1126
+ indented = indentLine(cm, end.line, "smart");
1126
1127
  }
1128
+ if (indented) signalLater(cm, "electricInput", cm, end.line);
1127
1129
  }
1128
1130
  }
1129
1131
  ensureCursorVisible(cm);
@@ -1167,6 +1169,7 @@
1167
1169
  this.inaccurateSelection = false;
1168
1170
  // Used to work around IE issue with selection being forgotten when focus moves away from textarea
1169
1171
  this.hasSelection = false;
1172
+ this.composing = null;
1170
1173
  };
1171
1174
 
1172
1175
  function hiddenTextarea() {
@@ -1231,6 +1234,8 @@
1231
1234
  te.value = lastCopied.join("\n");
1232
1235
  selectInput(te);
1233
1236
  }
1237
+ } else if (!cm.options.lineWiseCopyCut) {
1238
+ return;
1234
1239
  } else {
1235
1240
  var ranges = copyableRanges(cm);
1236
1241
  lastCopied = ranges.text;
@@ -1257,6 +1262,21 @@
1257
1262
  on(display.lineSpace, "selectstart", function(e) {
1258
1263
  if (!eventInWidget(display, e)) e_preventDefault(e);
1259
1264
  });
1265
+
1266
+ on(te, "compositionstart", function() {
1267
+ var start = cm.getCursor("from");
1268
+ input.composing = {
1269
+ start: start,
1270
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
1271
+ };
1272
+ });
1273
+ on(te, "compositionend", function() {
1274
+ if (input.composing) {
1275
+ input.poll();
1276
+ input.composing.range.clear();
1277
+ input.composing = null;
1278
+ }
1279
+ });
1260
1280
  },
1261
1281
 
1262
1282
  prepareSelection: function() {
@@ -1385,12 +1405,9 @@
1385
1405
  }
1386
1406
 
1387
1407
  if (cm.doc.sel == cm.display.selForContextMenu) {
1388
- if (text.charCodeAt(0) == 0x200b) {
1389
- if (!prevInput) prevInput = "\u200b";
1390
- } else if (prevInput == "\u200b") {
1391
- text = text.slice(1);
1392
- prevInput = "";
1393
- }
1408
+ var first = text.charCodeAt(0);
1409
+ if (first == 0x200b && !prevInput) prevInput = "\u200b";
1410
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
1394
1411
  }
1395
1412
  // Find the part of the input that is actually new
1396
1413
  var same = 0, l = Math.min(prevInput.length, text.length);
@@ -1398,11 +1415,18 @@
1398
1415
 
1399
1416
  var self = this;
1400
1417
  runInOp(cm, function() {
1401
- applyTextInput(cm, text.slice(same), prevInput.length - same);
1418
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
1419
+ null, self.composing ? "*compose" : null);
1402
1420
 
1403
1421
  // Don't leave long text in the textarea, since it makes further polling slow
1404
1422
  if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
1405
1423
  else self.prevInput = text;
1424
+
1425
+ if (self.composing) {
1426
+ self.composing.range.clear();
1427
+ self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
1428
+ {className: "CodeMirror-composing"});
1429
+ }
1406
1430
  });
1407
1431
  return true;
1408
1432
  },
@@ -1449,7 +1473,9 @@
1449
1473
  function prepareSelectAllHack() {
1450
1474
  if (te.selectionStart != null) {
1451
1475
  var selected = cm.somethingSelected();
1452
- var extval = te.value = "\u200b" + (selected ? te.value : "");
1476
+ var extval = "\u200b" + (selected ? te.value : "");
1477
+ te.value = "\u21da"; // Used to catch context-menu undo
1478
+ te.value = extval;
1453
1479
  input.prevInput = selected ? "" : "\u200b";
1454
1480
  te.selectionStart = 1; te.selectionEnd = extval.length;
1455
1481
  // Re-set this, in case some other handler touched the
@@ -1467,7 +1493,8 @@
1467
1493
  if (te.selectionStart != null) {
1468
1494
  if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
1469
1495
  var i = 0, poll = function() {
1470
- if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && input.prevInput == "\u200b")
1496
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
1497
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
1471
1498
  operation(cm, commands.selectAll)(cm);
1472
1499
  else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
1473
1500
  else display.input.reset();
@@ -1562,6 +1589,8 @@
1562
1589
  if (cm.somethingSelected()) {
1563
1590
  lastCopied = cm.getSelections();
1564
1591
  if (e.type == "cut") cm.replaceSelection("", null, "cut");
1592
+ } else if (!cm.options.lineWiseCopyCut) {
1593
+ return;
1565
1594
  } else {
1566
1595
  var ranges = copyableRanges(cm);
1567
1596
  lastCopied = ranges.text;
@@ -2919,6 +2948,7 @@
2919
2948
  updateMaxLine: false, // Set when the widest line needs to be determined anew
2920
2949
  scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
2921
2950
  scrollToPos: null, // Used to scroll to a specific position
2951
+ focus: false,
2922
2952
  id: ++nextOpId // Unique ID
2923
2953
  };
2924
2954
  if (operationGroup) {
@@ -3036,6 +3066,7 @@
3036
3066
 
3037
3067
  if (cm.state.focused && op.updateInput)
3038
3068
  cm.display.input.reset(op.typing);
3069
+ if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
3039
3070
  }
3040
3071
 
3041
3072
  function endOperation_finish(op) {
@@ -3400,15 +3431,11 @@
3400
3431
  // Prevent wrapper from ever scrolling
3401
3432
  on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
3402
3433
 
3403
- function drag_(e) {
3404
- if (!signalDOMEvent(cm, e)) e_stop(e);
3405
- }
3406
- if (cm.options.dragDrop) {
3407
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
3408
- on(d.scroller, "dragenter", drag_);
3409
- on(d.scroller, "dragover", drag_);
3410
- on(d.scroller, "drop", operation(cm, onDrop));
3411
- }
3434
+ d.dragFunctions = {
3435
+ simple: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
3436
+ start: function(e){onDragStart(cm, e);},
3437
+ drop: operation(cm, onDrop)
3438
+ };
3412
3439
 
3413
3440
  var inp = d.input.getField();
3414
3441
  on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
@@ -3418,6 +3445,18 @@
3418
3445
  on(inp, "blur", bind(onBlur, cm));
3419
3446
  }
3420
3447
 
3448
+ function dragDropChanged(cm, value, old) {
3449
+ var wasOn = old && old != CodeMirror.Init;
3450
+ if (!value != !wasOn) {
3451
+ var funcs = cm.display.dragFunctions;
3452
+ var toggle = value ? on : off;
3453
+ toggle(cm.display.scroller, "dragstart", funcs.start);
3454
+ toggle(cm.display.scroller, "dragenter", funcs.simple);
3455
+ toggle(cm.display.scroller, "dragover", funcs.simple);
3456
+ toggle(cm.display.scroller, "drop", funcs.drop);
3457
+ }
3458
+ }
3459
+
3421
3460
  // Called when the window resizes
3422
3461
  function onResize(cm) {
3423
3462
  var d = cm.display;
@@ -3507,7 +3546,7 @@
3507
3546
  var lastClick, lastDoubleClick;
3508
3547
  function leftButtonDown(cm, e, start) {
3509
3548
  if (ie) setTimeout(bind(ensureFocus, cm), 0);
3510
- else ensureFocus(cm);
3549
+ else cm.curOp.focus = activeElt();
3511
3550
 
3512
3551
  var now = +new Date, type;
3513
3552
  if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
@@ -3532,7 +3571,7 @@
3532
3571
  // Start a text drag. When it ends, see if any dragging actually
3533
3572
  // happen, and treat as a click if it didn't.
3534
3573
  function leftButtonStartDrag(cm, e, start, modifier) {
3535
- var display = cm.display;
3574
+ var display = cm.display, startTime = +new Date;
3536
3575
  var dragEnd = operation(cm, function(e2) {
3537
3576
  if (webkit) display.scroller.draggable = false;
3538
3577
  cm.state.draggingText = false;
@@ -3540,7 +3579,7 @@
3540
3579
  off(display.scroller, "drop", dragEnd);
3541
3580
  if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
3542
3581
  e_preventDefault(e2);
3543
- if (!modifier)
3582
+ if (!modifier && +new Date - 200 < startTime)
3544
3583
  extendSelection(cm.doc, start);
3545
3584
  // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
3546
3585
  if (webkit || ie && ie_version == 9)
@@ -3667,7 +3706,7 @@
3667
3706
  var cur = posFromMouse(cm, e, true, type == "rect");
3668
3707
  if (!cur) return;
3669
3708
  if (cmp(cur, lastPos) != 0) {
3670
- ensureFocus(cm);
3709
+ cm.curOp.focus = activeElt();
3671
3710
  extendTo(cur);
3672
3711
  var visible = visibleLines(display, doc);
3673
3712
  if (cur.line >= visible.to || cur.line < visible.from)
@@ -3770,7 +3809,7 @@
3770
3809
  try {
3771
3810
  var text = e.dataTransfer.getData("Text");
3772
3811
  if (text) {
3773
- if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
3812
+ if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
3774
3813
  var selected = cm.listSelections();
3775
3814
  setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
3776
3815
  if (selected) for (var i = 0; i < selected.length; ++i)
@@ -4025,7 +4064,7 @@
4025
4064
  var lastStoppedKey = null;
4026
4065
  function onKeyDown(e) {
4027
4066
  var cm = this;
4028
- ensureFocus(cm);
4067
+ cm.curOp.focus = activeElt();
4029
4068
  if (signalDOMEvent(cm, e)) return;
4030
4069
  // IE does strange things with escape.
4031
4070
  if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
@@ -4613,6 +4652,8 @@
4613
4652
 
4614
4653
  if (indentString != curSpaceString) {
4615
4654
  replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
4655
+ line.stateAfter = null;
4656
+ return true;
4616
4657
  } else {
4617
4658
  // Ensure that, if the cursor was in the whitespace at the start
4618
4659
  // of the line, it is moved to the end of that space.
@@ -4625,7 +4666,6 @@
4625
4666
  }
4626
4667
  }
4627
4668
  }
4628
- line.stateAfter = null;
4629
4669
  }
4630
4670
 
4631
4671
  // Utility for applying a change to a line by handle or number,
@@ -4915,10 +4955,15 @@
4915
4955
  return lineAtHeight(this.doc, height + this.display.viewOffset);
4916
4956
  },
4917
4957
  heightAtLine: function(line, mode) {
4918
- var end = false, last = this.doc.first + this.doc.size - 1;
4919
- if (line < this.doc.first) line = this.doc.first;
4920
- else if (line > last) { line = last; end = true; }
4921
- var lineObj = getLine(this.doc, line);
4958
+ var end = false, lineObj;
4959
+ if (typeof line == "number") {
4960
+ var last = this.doc.first + this.doc.size - 1;
4961
+ if (line < this.doc.first) line = this.doc.first;
4962
+ else if (line > last) { line = last; end = true; }
4963
+ lineObj = getLine(this.doc, line);
4964
+ } else {
4965
+ lineObj = line;
4966
+ }
4922
4967
  return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
4923
4968
  (end ? this.doc.height - heightAtLine(lineObj) : 0);
4924
4969
  },
@@ -5270,6 +5315,7 @@
5270
5315
  option("showCursorWhenSelecting", false, updateSelection, true);
5271
5316
 
5272
5317
  option("resetSelectionOnContextMenu", true);
5318
+ option("lineWiseCopyCut", true);
5273
5319
 
5274
5320
  option("readOnly", false, function(cm, val) {
5275
5321
  if (val == "nocursor") {
@@ -5282,7 +5328,7 @@
5282
5328
  }
5283
5329
  });
5284
5330
  option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
5285
- option("dragDrop", true);
5331
+ option("dragDrop", true, dragDropChanged);
5286
5332
 
5287
5333
  option("cursorBlinkRate", 530);
5288
5334
  option("cursorScrollMargin", 0);
@@ -6922,8 +6968,13 @@
6922
6968
  var foundBookmarks = [];
6923
6969
  for (var j = 0; j < spans.length; ++j) {
6924
6970
  var sp = spans[j], m = sp.marker;
6925
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
6926
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
6971
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
6972
+ foundBookmarks.push(m);
6973
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
6974
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
6975
+ nextChange = sp.to;
6976
+ spanEndStyle = "";
6977
+ }
6927
6978
  if (m.className) spanStyle += " " + m.className;
6928
6979
  if (m.css) css = m.css;
6929
6980
  if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
@@ -6934,12 +6985,12 @@
6934
6985
  } else if (sp.from > pos && nextChange > sp.from) {
6935
6986
  nextChange = sp.from;
6936
6987
  }
6937
- if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
6938
6988
  }
6939
6989
  if (collapsed && (collapsed.from || 0) == pos) {
6940
6990
  buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
6941
6991
  collapsed.marker, collapsed.from == null);
6942
6992
  if (collapsed.to == null) return;
6993
+ if (collapsed.to == pos) collapsed = false;
6943
6994
  }
6944
6995
  if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
6945
6996
  buildCollapsedSpan(builder, 0, foundBookmarks[j]);
@@ -8148,7 +8199,7 @@
8148
8199
  return function(){return f.apply(null, args);};
8149
8200
  }
8150
8201
 
8151
- var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
8202
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
8152
8203
  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
8153
8204
  return /\w/.test(ch) || ch > "\x80" &&
8154
8205
  (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -8670,6 +8721,8 @@
8670
8721
  lst(order).to -= m[0].length;
8671
8722
  order.push(new BidiSpan(0, len - m[0].length, len));
8672
8723
  }
8724
+ if (order[0].level == 2)
8725
+ order.unshift(new BidiSpan(1, order[0].to, order[0].to));
8673
8726
  if (order[0].level != lst(order).level)
8674
8727
  order.push(new BidiSpan(order[0].level, len, len));
8675
8728
 
@@ -8679,7 +8732,7 @@
8679
8732
 
8680
8733
  // THE END
8681
8734
 
8682
- CodeMirror.version = "5.1.0";
8735
+ CodeMirror.version = "5.2.0";
8683
8736
 
8684
8737
  return CodeMirror;
8685
8738
  });
@@ -10,13 +10,31 @@
10
10
  mod(CodeMirror);
11
11
  })(function(CodeMirror) {
12
12
  CodeMirror.defineExtension("addPanel", function(node, options) {
13
+ options = options || {};
14
+
13
15
  if (!this.state.panels) initPanels(this);
14
16
 
15
17
  var info = this.state.panels;
16
- if (options && options.position == "bottom")
17
- info.wrapper.appendChild(node);
18
- else
19
- info.wrapper.insertBefore(node, info.wrapper.firstChild);
18
+ var wrapper = info.wrapper;
19
+ var cmWrapper = this.getWrapperElement();
20
+
21
+ if (options.after instanceof Panel && !options.after.cleared) {
22
+ wrapper.insertBefore(node, options.before.node.nextSibling);
23
+ } else if (options.before instanceof Panel && !options.before.cleared) {
24
+ wrapper.insertBefore(node, options.before.node);
25
+ } else if (options.replace instanceof Panel && !options.replace.cleared) {
26
+ wrapper.insertBefore(node, options.replace.node);
27
+ options.replace.clear();
28
+ } else if (options.position == "bottom") {
29
+ wrapper.appendChild(node);
30
+ } else if (options.position == "before-bottom") {
31
+ wrapper.insertBefore(node, cmWrapper.nextSibling);
32
+ } else if (options.position == "after-top") {
33
+ wrapper.insertBefore(node, cmWrapper);
34
+ } else {
35
+ wrapper.insertBefore(node, wrapper.firstChild);
36
+ }
37
+
20
38
  var height = (options && options.height) || node.offsetHeight;
21
39
  this._setSize(null, info.heightLeft -= height);
22
40
  info.panels++;
@@ -19,23 +19,23 @@
19
19
  if (cm.getOption("disableInput")) return CodeMirror.Pass;
20
20
  var ranges = cm.listSelections(), replacements = [];
21
21
  for (var i = 0; i < ranges.length; i++) {
22
- var pos = ranges[i].head, match;
22
+ var pos = ranges[i].head;
23
23
  var eolState = cm.getStateAfter(pos.line);
24
24
  var inList = eolState.list !== false;
25
- var inQuote = eolState.quote !== false;
25
+ var inQuote = eolState.quote !== 0;
26
26
 
27
- if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {
27
+ var line = cm.getLine(pos.line), match = listRE.exec(line);
28
+ if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
28
29
  cm.execCommand("newlineAndIndent");
29
30
  return;
30
31
  }
31
- if (cm.getLine(pos.line).match(emptyListRE)) {
32
+ if (emptyListRE.test(line)) {
32
33
  cm.replaceRange("", {
33
34
  line: pos.line, ch: 0
34
35
  }, {
35
36
  line: pos.line, ch: pos.ch + 1
36
37
  });
37
38
  replacements[i] = "\n";
38
-
39
39
  } else {
40
40
  var indent = match[1], after = match[4];
41
41
  var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
@@ -24,44 +24,44 @@
24
24
  return cm.showHint(newOpts);
25
25
  };
26
26
 
27
- var asyncRunID = 0;
28
- function retrieveHints(getter, cm, options, then) {
29
- if (getter.async) {
30
- var id = ++asyncRunID;
31
- getter(cm, function(hints) {
32
- if (asyncRunID == id) then(hints);
33
- }, options);
34
- } else {
35
- then(getter(cm, options));
36
- }
37
- }
38
-
39
27
  CodeMirror.defineExtension("showHint", function(options) {
40
28
  // We want a single cursor position.
41
29
  if (this.listSelections().length > 1 || this.somethingSelected()) return;
42
30
 
43
31
  if (this.state.completionActive) this.state.completionActive.close();
44
32
  var completion = this.state.completionActive = new Completion(this, options);
45
- var getHints = completion.options.hint;
46
- if (!getHints) return;
33
+ if (!completion.options.hint) return;
47
34
 
48
35
  CodeMirror.signal(this, "startCompletion", this);
49
- return retrieveHints(getHints, this, completion.options, function(hints) { completion.showHints(hints); });
36
+ completion.update();
50
37
  });
51
38
 
52
39
  function Completion(cm, options) {
53
40
  this.cm = cm;
54
41
  this.options = this.buildOptions(options);
55
- this.widget = this.onClose = null;
42
+ this.widget = null;
43
+ this.debounce = 0;
44
+ this.tick = 0;
45
+ this.startPos = this.cm.getCursor();
46
+ this.startLen = this.cm.getLine(this.startPos.line).length;
47
+
48
+ var self = this;
49
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
56
50
  }
57
51
 
52
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
53
+ return setTimeout(fn, 1000/60);
54
+ };
55
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
56
+
58
57
  Completion.prototype = {
59
58
  close: function() {
60
59
  if (!this.active()) return;
61
60
  this.cm.state.completionActive = null;
61
+ this.tick = null;
62
+ this.cm.off("cursorActivity", this.activityFunc);
62
63
 
63
64
  if (this.widget) this.widget.close();
64
- if (this.onClose) this.onClose();
65
65
  CodeMirror.signal(this.cm, "endCompletion", this.cm);
66
66
  },
67
67
 
@@ -87,61 +87,51 @@
87
87
  this.showWidget(data);
88
88
  },
89
89
 
90
- showWidget: function(data) {
91
- this.widget = new Widget(this, data);
92
- CodeMirror.signal(data, "shown");
93
-
94
- var debounce = 0, completion = this, finished;
95
- var closeOn = this.options.closeCharacters;
96
- var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
97
-
98
- var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
99
- return setTimeout(fn, 1000/60);
100
- };
101
- var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
102
-
103
- function done() {
104
- if (finished) return;
105
- finished = true;
106
- completion.close();
107
- completion.cm.off("cursorActivity", activity);
108
- if (data) CodeMirror.signal(data, "close");
90
+ cursorActivity: function() {
91
+ if (this.debounce) {
92
+ cancelAnimationFrame(this.debounce);
93
+ this.debounce = 0;
109
94
  }
110
95
 
111
- function update() {
112
- if (finished) return;
113
- CodeMirror.signal(data, "update");
114
- retrieveHints(completion.options.hint, completion.cm, completion.options, finishUpdate);
115
- }
116
- function finishUpdate(data_) {
117
- data = data_;
118
- if (finished) return;
119
- if (!data || !data.list.length) return done();
120
- if (completion.widget) completion.widget.close();
121
- completion.widget = new Widget(completion, data);
96
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
97
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
98
+ pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
99
+ (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
100
+ this.close();
101
+ } else {
102
+ var self = this;
103
+ this.debounce = requestAnimationFrame(function() {self.update();});
104
+ if (this.widget) this.widget.disable();
122
105
  }
106
+ },
123
107
 
124
- function clearDebounce() {
125
- if (debounce) {
126
- cancelAnimationFrame(debounce);
127
- debounce = 0;
128
- }
108
+ update: function() {
109
+ if (this.tick == null) return;
110
+ if (this.data) CodeMirror.signal(this.data, "update");
111
+ if (!this.options.hint.async) {
112
+ this.finishUpdate(this.options.hint(this.cm, this.options), myTick);
113
+ } else {
114
+ var myTick = ++this.tick, self = this;
115
+ this.options.hint(this.cm, function(data) {
116
+ if (self.tick == myTick) self.finishUpdate(data);
117
+ }, this.options);
129
118
  }
119
+ },
130
120
 
131
- function activity() {
132
- clearDebounce();
133
- var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
134
- if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
135
- pos.ch < startPos.ch || completion.cm.somethingSelected() ||
136
- (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
137
- completion.close();
138
- } else {
139
- debounce = requestAnimationFrame(update);
140
- if (completion.widget) completion.widget.close();
141
- }
121
+ finishUpdate: function(data) {
122
+ this.data = data;
123
+ var picked = this.widget && this.widget.picked;
124
+ if (this.widget) this.widget.close();
125
+ if (data && data.list.length) {
126
+ if (picked && data.list.length == 1) this.pick(data, 0);
127
+ else this.widget = new Widget(this, data);
142
128
  }
143
- this.cm.on("cursorActivity", activity);
144
- this.onClose = done;
129
+ },
130
+
131
+ showWidget: function(data) {
132
+ this.data = data;
133
+ this.widget = new Widget(this, data);
134
+ CodeMirror.signal(data, "shown");
145
135
  },
146
136
 
147
137
  buildOptions: function(options) {
@@ -206,6 +196,7 @@
206
196
  function Widget(completion, data) {
207
197
  this.completion = completion;
208
198
  this.data = data;
199
+ this.picked = false;
209
200
  var widget = this, cm = completion.cm;
210
201
 
211
202
  var hints = this.hints = document.createElement("ul");
@@ -320,6 +311,13 @@
320
311
  cm.off("scroll", this.onScroll);
321
312
  },
322
313
 
314
+ disable: function() {
315
+ this.completion.cm.removeKeyMap(this.keyMap);
316
+ var widget = this;
317
+ this.keyMap = {Enter: function() { widget.picked = true; }};
318
+ this.completion.cm.addKeyMap(this.keyMap);
319
+ },
320
+
323
321
  pick: function() {
324
322
  this.completion.pick(this.data, this.selectedHint);
325
323
  },