| Index: Source/devtools/front_end/CodeMirrorTextEditor.js
|
| diff --git a/Source/devtools/front_end/CodeMirrorTextEditor.js b/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| index 2a5c328cff71bc9b466e28a8fdb985b41c5816ee..031948f3a771fe003168e518dc5090976dcf0349 100644
|
| --- a/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| +++ b/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| @@ -88,7 +88,8 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| "Tab": "defaultTab",
|
| "Shift-Tab": "indentLess",
|
| "Enter": "smartNewlineAndIndent",
|
| - "Ctrl-Space": "autocomplete"
|
| + "Ctrl-Space": "autocomplete",
|
| + "Esc": "dismissMultipleSelections"
|
| };
|
|
|
| CodeMirror.keyMap["devtools-pc"] = {
|
| @@ -147,7 +148,7 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| this._fixWordMovement = new WebInspector.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);
|
| this._autocompleteController = new WebInspector.CodeMirrorTextEditor.AutocompleteController(this, this._codeMirror);
|
|
|
| - this._codeMirror.on("change", this._change.bind(this));
|
| + this._codeMirror.on("changes", this._changes.bind(this));
|
| this._codeMirror.on("beforeChange", this._beforeChange.bind(this));
|
| this._codeMirror.on("gutterClick", this._gutterClick.bind(this));
|
| this._codeMirror.on("cursorActivity", this._cursorActivity.bind(this));
|
| @@ -238,6 +239,15 @@ CodeMirror.commands.redoAndReveal = function(codemirror)
|
| codemirror._codeMirrorTextEditor._autocompleteController.finishAutocomplete();
|
| }
|
|
|
| +CodeMirror.commands.dismissMultipleSelections = function(codemirror)
|
| +{
|
| + if (codemirror.getSelections().length <= 1)
|
| + return CodeMirror.Pass;
|
| + var range = codemirror.listSelections()[0];
|
| + codemirror.setSelection(range.anchor, range.head, {scroll: false});
|
| + codemirror._codeMirrorTextEditor._revealLine(range.anchor.line);
|
| +}
|
| +
|
| WebInspector.CodeMirrorTextEditor.LongLineModeLineLengthThreshold = 2000;
|
| WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan = 16;
|
| WebInspector.CodeMirrorTextEditor.MaxEditableTextSize = 1024 * 1024 * 10;
|
| @@ -937,10 +947,12 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
|
|
| /**
|
| * @param {!CodeMirror} codeMirror
|
| - * @param {!WebInspector.CodeMirrorTextEditor.ChangeObject} changeObject
|
| + * @param {!Array.<!WebInspector.CodeMirrorTextEditor.ChangeObject>} changes
|
| */
|
| - _change: function(codeMirror, changeObject)
|
| + _changes: function(codeMirror, changes)
|
| {
|
| + if (!changes.length)
|
| + return;
|
| // We do not show "scroll beyond end of file" span for one line documents, so we need to check if "document has one line" changed.
|
| var hasOneLine = this._codeMirror.lineCount() === 1;
|
| if (hasOneLine !== this._hasOneLine)
|
| @@ -959,7 +971,8 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
|
|
| var linesToUpdate = {};
|
| var singleCharInput = false;
|
| - do {
|
| + for (var changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
|
| + var changeObject = changes[changeIndex];
|
| var oldRange = this._toRange(changeObject.from, changeObject.to);
|
| var newRange = oldRange.clone();
|
| var linesAdded = changeObject.text.length;
|
| @@ -983,7 +996,7 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
| for (var i = newRange.startLine; i <= newRange.endLine; ++i)
|
| linesToUpdate[i] = this.line(i);
|
| }
|
| - } while (changeObject = changeObject.next);
|
| + }
|
| if (this._dictionary) {
|
| for (var lineNumber in linesToUpdate)
|
| this._addTextToCompletionDictionary(linesToUpdate[lineNumber]);
|
| @@ -1003,13 +1016,16 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
|
|
| /**
|
| * @param {!CodeMirror} codeMirror
|
| - * @param {!{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}} selection
|
| + * @param {{ranges: !Array.<{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}>}} selection
|
| */
|
| _beforeSelectionChange: function(codeMirror, selection)
|
| {
|
| if (!this._isHandlingMouseDownEvent)
|
| return;
|
| - this._reportJump(this.selection(), this._toRange(selection.anchor, selection.head));
|
| + if (!selection.ranges.length)
|
| + return;
|
| + var primarySelection = selection.ranges[0];
|
| + this._reportJump(this.selection(), this._toRange(primarySelection.anchor, primarySelection.head));
|
| },
|
|
|
| /**
|
| @@ -1334,7 +1350,10 @@ WebInspector.CodeMirrorTextEditor.TokenHighlighter.prototype = {
|
| if (selectionStart.ch === selectionEnd.ch)
|
| return;
|
|
|
| - var selectedText = this._codeMirror.getSelection();
|
| + var selections = this._codeMirror.getSelections();
|
| + if (selections.length !== 1)
|
| + return;
|
| + var selectedText = selections[0];
|
| if (this._isWord(selectedText, selectionStart.line, selectionStart.ch, selectionEnd.ch)) {
|
| if (selectionStart)
|
| this._codeMirror.addLineClass(selectionStart.line, "wrap", "cm-line-with-selection")
|
| @@ -1499,34 +1518,36 @@ WebInspector.CodeMirrorTextEditor.FixWordMovement = function(codeMirror)
|
| {
|
| function moveLeft(shift, codeMirror)
|
| {
|
| - var cursor = codeMirror.getCursor("head");
|
| - if (cursor.ch !== 0 || cursor.line === 0)
|
| - return CodeMirror.Pass;
|
| codeMirror.setExtending(shift);
|
| - codeMirror.execCommand("goLineUp");
|
| - codeMirror.execCommand("goLineEnd")
|
| + var cursor = codeMirror.getCursor("head");
|
| + codeMirror.execCommand("goGroupLeft");
|
| + var newCursor = codeMirror.getCursor("head");
|
| + if (newCursor.ch === 0 && newCursor.line !== 0) {
|
| + codeMirror.setExtending(false);
|
| + return;
|
| + }
|
| +
|
| + var skippedText = codeMirror.getRange(newCursor, cursor, "#");
|
| + if (/^\s+$/.test(skippedText))
|
| + codeMirror.execCommand("goGroupLeft");
|
| codeMirror.setExtending(false);
|
| }
|
| +
|
| function moveRight(shift, codeMirror)
|
| {
|
| - var cursor = codeMirror.getCursor("head");
|
| - var line = codeMirror.getLine(cursor.line);
|
| - if (cursor.ch !== line.length || cursor.line + 1 === codeMirror.lineCount())
|
| - return CodeMirror.Pass;
|
| codeMirror.setExtending(shift);
|
| - codeMirror.execCommand("goLineDown");
|
| - codeMirror.execCommand("goLineStart");
|
| - codeMirror.setExtending(false);
|
| - }
|
| - function delWordBack(codeMirror)
|
| - {
|
| - if (codeMirror.somethingSelected())
|
| - return CodeMirror.Pass;
|
| var cursor = codeMirror.getCursor("head");
|
| - if (cursor.ch === 0)
|
| - codeMirror.execCommand("delCharBefore");
|
| - else
|
| - return CodeMirror.Pass;
|
| + codeMirror.execCommand("goGroupRight");
|
| + var newCursor = codeMirror.getCursor("head");
|
| + if (newCursor.ch === 0 && newCursor.line !== 0) {
|
| + codeMirror.setExtending(false);
|
| + return;
|
| + }
|
| +
|
| + var skippedText = codeMirror.getRange(cursor, newCursor, "#");
|
| + if (/^\s+$/.test(skippedText))
|
| + codeMirror.execCommand("goGroupRight");
|
| + codeMirror.setExtending(false);
|
| }
|
|
|
| var modifierKey = WebInspector.isMac() ? "Alt" : "Ctrl";
|
| @@ -1537,7 +1558,6 @@ WebInspector.CodeMirrorTextEditor.FixWordMovement = function(codeMirror)
|
| keyMap[rightKey] = moveRight.bind(null, false);
|
| keyMap["Shift-" + leftKey] = moveLeft.bind(null, true);
|
| keyMap["Shift-" + rightKey] = moveRight.bind(null, true);
|
| - keyMap[modifierKey + "-Backspace"] = delWordBack;
|
| codeMirror.addKeyMap(keyMap);
|
| }
|
|
|
| @@ -1556,6 +1576,25 @@ WebInspector.CodeMirrorTextEditor.AutocompleteController = function(textEditor,
|
| }
|
|
|
| WebInspector.CodeMirrorTextEditor.AutocompleteController.prototype = {
|
| + /**
|
| + * @param {!WebInspector.TextRange} mainSelection
|
| + * @param {!Array.<!{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}>} selections
|
| + * @return {boolean}
|
| + */
|
| + _validateSelectionsContexts: function(mainSelection, selections)
|
| + {
|
| + var mainSelectionContext = this._textEditor.copyRange(mainSelection);
|
| + for (var i = 0; i < selections.length; ++i) {
|
| + var wordRange = this._textEditor._wordRangeForCursorPosition(selections[i].head.line, selections[i].head.ch, false);
|
| + if (!wordRange)
|
| + return false;
|
| + var context = this._textEditor.copyRange(wordRange);
|
| + if (context !== mainSelectionContext)
|
| + return false;
|
| + }
|
| + return true;
|
| + },
|
| +
|
| autocomplete: function()
|
| {
|
| var dictionary = this._textEditor._dictionary;
|
| @@ -1564,12 +1603,15 @@ WebInspector.CodeMirrorTextEditor.AutocompleteController.prototype = {
|
| return;
|
| }
|
|
|
| - var cursor = this._codeMirror.getCursor();
|
| + var selections = this._codeMirror.listSelections().slice();
|
| + var topSelection = selections.shift();
|
| + var cursor = topSelection.head;
|
| var substituteRange = this._textEditor._wordRangeForCursorPosition(cursor.line, cursor.ch, false);
|
| - if (!substituteRange || substituteRange.startColumn === cursor.ch) {
|
| + if (!substituteRange || substituteRange.startColumn === cursor.ch || !this._validateSelectionsContexts(substituteRange, selections)) {
|
| this.finishAutocomplete();
|
| return;
|
| }
|
| +
|
| var prefixRange = substituteRange.clone();
|
| prefixRange.endColumn = cursor.ch;
|
|
|
| @@ -1639,9 +1681,15 @@ WebInspector.CodeMirrorTextEditor.AutocompleteController.prototype = {
|
|
|
| acceptSuggestion: function()
|
| {
|
| - if (this._prefixRange.endColumn - this._prefixRange.startColumn !== this._currentSuggestion.length) {
|
| - var pos = this._textEditor._toPos(this._prefixRange);
|
| - this._codeMirror.replaceRange(this._currentSuggestion, pos.start, pos.end, "+autocomplete");
|
| + if (this._prefixRange.endColumn - this._prefixRange.startColumn === this._currentSuggestion.length)
|
| + return;
|
| +
|
| + var selections = this._codeMirror.listSelections().slice();
|
| + var prefixLength = this._prefixRange.endColumn - this._prefixRange.startColumn;
|
| + for (var i = selections.length - 1; i >= 0; --i) {
|
| + var start = selections[i].head;
|
| + var end = new CodeMirror.Pos(start.line, start.ch - prefixLength);
|
| + this._codeMirror.replaceRange(this._currentSuggestion, start, end, "+autocomplete");
|
| }
|
| },
|
|
|
|
|