Chromium Code Reviews| 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..8791a308093d0ebb6f5dba6dcbf6e526e2162e9f 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,7 +95,9 @@ 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)); |
| + |
|
vsevik
2013/05/24 16:32:34
extra line
|
| this._codeMirror.on("cursorActivity", this._cursorActivity.bind(this)); |
| this._codeMirror.on("scroll", this._scroll.bind(this)); |
| this.element.addEventListener("contextmenu", this._contextMenu.bind(this)); |
| @@ -98,6 +108,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 +142,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 +564,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 +602,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 +627,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() |