Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1305)

Unified Diff: Source/devtools/front_end/cm/codemirror.js

Issue 273763003: DevTools: [CodeMirror] roll codemirror to @687fb51 (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/devtools/front_end/cm/codemirror.js
diff --git a/Source/devtools/front_end/cm/codemirror.js b/Source/devtools/front_end/cm/codemirror.js
index fa31adc1619756c6fab654d5e6735d48c38889bb..ddb251461880fe7a0cc39d7192f385882df63bcc 100644
--- a/Source/devtools/front_end/cm/codemirror.js
+++ b/Source/devtools/front_end/cm/codemirror.js
@@ -1,3 +1,6 @@
+// CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// This is CodeMirror (http://codemirror.net), a code editor
// implemented in JavaScript on top of the browser's DOM.
//
@@ -93,6 +96,7 @@
if (ie_upto10) setTimeout(bind(resetInput, this, true), 20);
registerEventHandlers(this);
+ ensureGlobalHandlers();
var cm = this;
runInOp(this, function() {
@@ -230,6 +234,10 @@
// True when shift is held down.
d.shift = false;
+
+ // Used to track whether anything happened since the context menu
+ // was opened.
+ d.selForContextMenu = null;
}
// STATE UPDATES
@@ -455,7 +463,7 @@
// the the current scroll position). viewPort may contain top,
// height, and ensure (see op.scrollToPos) properties.
function visibleLines(display, doc, viewPort) {
- var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop;
+ var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop;
top = Math.floor(top - paddingTop(display));
var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;
@@ -659,7 +667,6 @@
cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
}
-
function checkForWebkitWidthBug(cm, measure) {
// Work around Webkit bug where it sometimes reserves space for a
// non-existing phantom scrollbar in the scroller (Issue #2420)
@@ -1621,7 +1628,7 @@
else
rect = nullRect;
} else {
- rect = range(node, start, end).getBoundingClientRect();
+ rect = range(node, start, end).getBoundingClientRect() || nullRect;
}
} else { // If it is a widget, simply get the box for the whole widget.
if (start > 0) collapse = bias = "right";
@@ -1922,6 +1929,10 @@
if (!updated && op.selectionChanged) updateSelection(cm);
if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);
+ // Abort mouse wheel delta measurement, when scrolling explicitly
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
+ display.wheelStartX = display.wheelStartY = null;
+
// Propagate the scroll position to the actual DOM scroller
if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
@@ -2135,7 +2146,8 @@
function viewCuttingPoint(cm, oldN, newN, dir) {
var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
- if (!sawCollapsedSpans) return {index: index, lineN: newN};
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
+ return {index: index, lineN: newN};
for (var i = 0, n = cm.display.viewFrom; i < index; i++)
n += view[i].size;
if (n != oldN) {
@@ -2246,6 +2258,8 @@
if (withOp) startOperation(cm);
cm.display.shift = false;
+ if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput)
+ prevInput = "\u200b";
// Find the part of the input that is actually new
var same = 0, l = Math.min(prevInput.length, text.length);
while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
@@ -2345,7 +2359,7 @@
var pos = posFromMouse(cm, e);
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
e_preventDefault(e);
- var word = findWordAt(cm.doc, pos);
+ var word = findWordAt(cm, pos);
extendSelection(cm.doc, word.anchor, word.head);
}));
else
@@ -2386,26 +2400,6 @@
// Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
- // When the window resizes, we need to refresh active editors.
- var resizeTimer;
- function onResize() {
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
- resizeTimer = null;
- // Might be a text scaling operation, clear size caches.
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;
- cm.setSize();
- }, 100);
- }
- on(window, "resize", onResize);
- // The above handler holds on to the editor and its data
- // structures. Here we poll to unregister it when the editor is no
- // longer in the document, so that it can be garbage-collected.
- function unregister() {
- if (contains(document.body, d.wrapper)) setTimeout(unregister, 5000);
- else off(window, "resize", onResize);
- }
- setTimeout(unregister, 5000);
-
on(d.input, "keyup", operation(cm, onKeyUp));
on(d.input, "input", function() {
if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
@@ -2482,6 +2476,14 @@
});
}
+ // Called when the window resizes
+ function onResize(cm) {
+ // Might be a text scaling operation, clear size caches.
+ var d = cm.display;
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
+ cm.setSize();
+ }
+
// MOUSE EVENTS
// Return true when the given mouse event happened in a widget
@@ -2629,7 +2631,7 @@
start = posFromMouse(cm, e, true, true);
ourIndex = -1;
} else if (type == "double") {
- var word = findWordAt(doc, start);
+ var word = findWordAt(cm, start);
if (cm.display.shift || doc.extend)
ourRange = extendRange(doc, ourRange, word.anchor, word.head);
else
@@ -2675,13 +2677,15 @@
ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
}
if (!ranges.length) ranges.push(new Range(start, start));
- setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), sel_mouse);
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
+ {origin: "*mouse", scroll: false});
+ cm.scrollIntoView(pos);
} else {
var oldRange = ourRange;
var anchor = oldRange.anchor, head = pos;
if (type != "single") {
if (type == "double")
- var range = findWordAt(doc, pos);
+ var range = findWordAt(cm, pos);
else
var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
if (cmp(range.anchor, anchor) > 0) {
@@ -3382,7 +3386,7 @@
var after = i ? computeSelAfterChange(doc, change, null) : lst(source);
makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
- if (doc.cm) ensureCursorVisible(doc.cm);
+ if (!i && doc.cm) doc.cm.scrollIntoView(change);
var rebased = [];
// Propagate to the linked documents
@@ -3399,12 +3403,17 @@
// Sub-views need their line numbers shifted when text is added
// above or below them in the parent document.
function shiftDoc(doc, distance) {
+ if (distance == 0) return;
doc.first += distance;
doc.sel = new Selection(map(doc.sel.ranges, function(range) {
return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
Pos(range.head.line + distance, range.head.ch));
}), doc.sel.primIndex);
- if (doc.cm) regChange(doc.cm, doc.first, doc.first - distance, distance);
+ if (doc.cm) {
+ regChange(doc.cm, doc.first, doc.first - distance, distance);
+ for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
+ regLineChange(doc.cm, l, "gutter");
+ }
}
// More lower-level change function, handling only a single document
@@ -3496,6 +3505,7 @@
if (changeHandler) signalLater(cm, "change", cm, obj);
if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
}
+ cm.display.selForContextMenu = null;
}
function replaceRange(doc, code, from, to, origin) {
@@ -3763,10 +3773,11 @@
else if (unit == "column") moveOnce(true);
else if (unit == "word" || unit == "group") {
var sawType = null, group = unit == "group";
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
for (var first = true;; first = false) {
if (dir < 0 && !moveOnce(!first)) break;
var cur = lineObj.text.charAt(ch) || "\n";
- var type = isWordChar(cur) ? "w"
+ var type = isWordChar(cur, helper) ? "w"
: group && cur == "\n" ? "n"
: !group || /\s/.test(cur) ? null
: "p";
@@ -3806,13 +3817,15 @@
}
// Find the word at the given position (as returned by coordsChar).
- function findWordAt(doc, pos) {
- var line = getLine(doc, pos.line).text;
+ function findWordAt(cm, pos) {
+ var doc = cm.doc, line = getLine(doc, pos.line).text;
var start = pos.ch, end = pos.ch;
if (line) {
+ var helper = cm.getHelper(pos, "wordChars");
if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
- var check = isWordChar(startChar) ? isWordChar
+ var check = isWordChar(startChar, helper)
+ ? function(ch) { return isWordChar(ch, helper); }
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
while (start > 0 && check(line.charAt(start - 1))) --start;
@@ -4617,13 +4630,25 @@
},
transposeChars: function(cm) {
runInOp(cm, function() {
- var ranges = cm.listSelections();
+ var ranges = cm.listSelections(), newSel = [];
for (var i = 0; i < ranges.length; i++) {
var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
- if (cur.ch > 0 && cur.ch < line.length - 1)
- cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
- Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+ if (line) {
+ if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
+ if (cur.ch > 0) {
+ cur = new Pos(cur.line, cur.ch + 1);
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
+ Pos(cur.line, cur.ch - 2), cur, "+transpose");
+ } else if (cur.line > cm.doc.first) {
+ var prev = getLine(cm.doc, cur.line - 1).text;
+ if (prev)
+ cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
+ Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
+ }
+ }
+ newSel.push(new Range(cur, cur));
}
+ cm.setSelections(newSel);
});
},
newlineAndIndent: function(cm) {
@@ -5583,10 +5608,11 @@
}
function readToken(mode, stream, state) {
- var style = mode.token(stream, state);
- if (stream.pos <= stream.start)
- throw new Error("Mode " + mode.name + " failed to advance stream.");
- return style;
+ for (var i = 0; i < 10; i++) {
+ var style = mode.token(stream, state);
+ if (stream.pos > stream.start) return style;
+ }
+ throw new Error("Mode " + mode.name + " failed to advance stream.");
}
// Run the given mode's parser over a line, calling f for each token.
@@ -7052,10 +7078,15 @@
}
var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
- var isWordChar = CodeMirror.isWordChar = function(ch) {
+ var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
};
+ function isWordChar(ch, helper) {
+ if (!helper) return isWordCharBasic(ch);
+ if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
+ return helper.test(ch);
+ }
function isEmpty(obj) {
for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
@@ -7137,6 +7168,43 @@
return b;
}
+ // WINDOW-WIDE EVENTS
+
+ // These must be handled carefully, because naively registering a
+ // handler for each editor will cause the editors to never be
+ // garbage collected.
+
+ function forEachCodeMirror(f) {
+ if (!document.body.getElementsByClassName) return;
+ var byClass = document.body.getElementsByClassName("CodeMirror");
+ for (var i = 0; i < byClass.length; i++) {
+ var cm = byClass[i].CodeMirror;
+ if (cm) f(cm);
+ }
+ }
+
+ var globalsRegistered = false;
+ function ensureGlobalHandlers() {
+ if (globalsRegistered) return;
+ registerGlobalHandlers();
+ globalsRegistered = true;
+ }
+ function registerGlobalHandlers() {
+ // When the window resizes, we need to refresh active editors.
+ var resizeTimer;
+ on(window, "resize", function() {
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
+ resizeTimer = null;
+ knownScrollbarWidth = null;
+ forEachCodeMirror(onResize);
+ }, 100);
+ });
+ // When the window loses focus, we want to show the editor as blurred
+ on(window, "blur", function() {
+ forEachCodeMirror(onBlur);
+ });
+ }
+
// FEATURE DETECTION
// Detect drag-and-drop
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698