codemirror-rails 5.1 → 5.2

Sign up to get free protection for your applications and to get access to all the features.
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
  },