| Index: Source/devtools/front_end/CodeMirrorTextEditor.js
|
| diff --git a/Source/devtools/front_end/CodeMirrorTextEditor.js b/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| index 89c132aed488d513ce33fd506b49b60553fd0a43..c2a50b0e2642bf63cfda4e3636fd8bebdf7a0758 100644
|
| --- a/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| +++ b/Source/devtools/front_end/CodeMirrorTextEditor.js
|
| @@ -55,6 +55,14 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| this.registerRequiredCSS("cm/showhint.css");
|
| this.registerRequiredCSS("cm/cmdevtools.css");
|
|
|
| + function autocompleteCommand()
|
| + {
|
| + if (!this._dictionary || this._codeMirror.somethingSelected())
|
| + return;
|
| + CodeMirror.showHint(this._codeMirror, this._autocomplete.bind(this));
|
| + }
|
| + CodeMirror.commands.autocomplete = autocompleteCommand.bind(this);
|
| +
|
| this._codeMirror = window.CodeMirror(this.element, {
|
| lineNumbers: true,
|
| gutters: ["CodeMirror-linenumbers"],
|
| @@ -65,7 +73,7 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| autoCloseBrackets: true
|
| });
|
|
|
| - var extraKeys = {};
|
| + var extraKeys = {"Ctrl-Space": "autocomplete"};
|
| var indent = WebInspector.settings.textEditorIndent.get();
|
| if (indent === WebInspector.TextUtils.Indent.TabCharacter) {
|
| this._codeMirror.setOption("indentWithTabs", true);
|
| @@ -87,6 +95,7 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| this._fixWordMovement = new WebInspector.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);
|
|
|
| this._codeMirror.on("change", this._change.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));
|
| this._codeMirror.on("scroll", this._scroll.bind(this));
|
| @@ -98,6 +107,7 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| this._nestedUpdatesCounter = 0;
|
|
|
| this.element.addEventListener("focus", this._handleElementFocus.bind(this), false);
|
| + this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
|
| this.element.tabIndex = 0;
|
| this._setupSelectionColor();
|
| }
|
| @@ -131,10 +141,69 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
| document.head.appendChild(style);
|
| },
|
|
|
| + _autocomplete: function(codeMirror)
|
| + {
|
| + var cursor = codeMirror.getCursor();
|
| + var prefixRange = this._wordRangeForCursorPosition(cursor.line, cursor.ch, true);
|
| + if (!prefixRange)
|
| + return null;
|
| + var prefix = this.copyRange(prefixRange);
|
| + this._dictionary.removeWord(prefix);
|
| + var wordsWithPrefix = this._dictionary.wordsWithPrefix(this.copyRange(prefixRange));
|
| + this._dictionary.addWord(prefix);
|
| +
|
| + var data = {
|
| + list: wordsWithPrefix,
|
| + from: new CodeMirror.Pos(prefixRange.startLine, prefixRange.startColumn),
|
| + to: new CodeMirror.Pos(prefixRange.endLine, prefixRange.endColumn)
|
| + };
|
| + CodeMirror.on(data, "close", this._handleAutocompletionClose.bind(this));
|
| +
|
| + return data;
|
| + },
|
| +
|
| + _handleKeyDown: function(e)
|
| + {
|
| + if (!!this._consumeEsc && e.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
|
| + e.consume(true);
|
| + delete this._consumeEsc;
|
| + },
|
| +
|
| + _handleAutocompletionClose: function()
|
| + {
|
| + this._consumeEsc = true;
|
| + },
|
| +
|
| + /**
|
| + * @param {string} text
|
| + */
|
| + _addTextToCompletionDictionary: function(text)
|
| + {
|
| + var words = WebInspector.TextUtils.textToWords(text);
|
| + for(var i = 0; i < words.length; ++i) {
|
| + this._dictionary.addWord(words[i]);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * @param {string} text
|
| + */
|
| + _removeTextFromCompletionDictionary: function(text)
|
| + {
|
| + var words = WebInspector.TextUtils.textToWords(text);
|
| + for(var i = 0; i < words.length; ++i) {
|
| + this._dictionary.removeWord(words[i]);
|
| + }
|
| + },
|
| +
|
| /**
|
| * @param {WebInspector.CompletionDictionary} dictionary
|
| */
|
| - setCompletionDictionary: function(dictionary) { },
|
| + setCompletionDictionary: function(dictionary)
|
| + {
|
| + this._dictionary = dictionary;
|
| + this._addTextToCompletionDictionary(this.text());
|
| + },
|
|
|
| /**
|
| * @param {number} lineNumber
|
| @@ -494,6 +563,37 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
| return newRange;
|
| },
|
|
|
| + /**
|
| + * @param {number} lineNumber
|
| + * @param {number} column
|
| + * @param {boolean=} prefixOnly
|
| + * @return {?WebInspector.TextRange}
|
| + */
|
| + _wordRangeForCursorPosition: function(lineNumber, column, prefixOnly)
|
| + {
|
| + var line = this.line(lineNumber);
|
| + if (!WebInspector.TextUtils.isWordChar(line.charAt(column - 1)))
|
| + return null;
|
| + var wordStart = column - 1;
|
| + while(wordStart > 0 && WebInspector.TextUtils.isWordChar(line.charAt(wordStart - 1)))
|
| + --wordStart;
|
| + if (prefixOnly)
|
| + return new WebInspector.TextRange(lineNumber, wordStart, lineNumber, column);
|
| + var wordEnd = column;
|
| + while(wordEnd < line.length && WebInspector.TextUtils.isWordChar(line.charAt(wordEnd)))
|
| + ++wordEnd;
|
| + return new WebInspector.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
|
| + },
|
| +
|
| + _beforeChange: function(codeMirror, changeObject)
|
| + {
|
| + if (!this._dictionary)
|
| + return;
|
| + this._updatedLines = this._updatedLines || {};
|
| + for(var i = changeObject.from.line; i <= changeObject.to.line; ++i)
|
| + this._updatedLines[i] = this.line(i);
|
| + },
|
| +
|
| _change: function(codeMirror, changeObject)
|
| {
|
| var widgets = this._elementToWidget.values();
|
| @@ -501,6 +601,13 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
| this._codeMirror.removeLineWidget(widgets[i]);
|
| this._elementToWidget.clear();
|
|
|
| + if (this._updatedLines) {
|
| + for(var lineNumber in this._updatedLines)
|
| + this._removeTextFromCompletionDictionary(this._updatedLines[lineNumber]);
|
| + delete this._updatedLines;
|
| + }
|
| +
|
| + var linesToUpdate = {};
|
| do {
|
| var oldRange = this._toRange(changeObject.from, changeObject.to);
|
| var newRange = oldRange.clone();
|
| @@ -519,7 +626,18 @@ WebInspector.CodeMirrorTextEditor.prototype = {
|
| if (!this._muteTextChangedEvent)
|
| this._delegate.onTextChanged(oldRange, newRange);
|
|
|
| + for(var i = newRange.startLine; i <= newRange.endLine; ++i) {
|
| + linesToUpdate[i] = true;
|
| + }
|
| + if (this._dictionary) {
|
| + 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]);
|
| + }
|
| },
|
|
|
| _cursorActivity: function()
|
|
|