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

Unified Diff: third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js

Issue 2331053002: DevTools: Implement the console prompt with CodeMirror (Closed)
Patch Set: Merge with PageUp fix Created 4 years, 3 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
Index: third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
new file mode 100644
index 0000000000000000000000000000000000000000..f50d5e52489dcfd794433fecd2d5b6a912a76fd5
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
@@ -0,0 +1,262 @@
+/**
+ * @constructor
+ */
+WebInspector.ConsolePrompt = function()
+{
+ this._addCompletionsFromHistory = true;
+ this._history = new WebInspector.HistoryManager();
+}
+
+/**
+ * @return {!Promise}
+ */
+WebInspector.ConsolePrompt.create = function()
+{
+ var prompt = new WebInspector.ConsolePrompt();
+ return self.runtime.extension(WebInspector.TextEditorFactory).instance().then(innerCreate);
+
+ /**
+ * @param {!WebInspector.TextEditorFactory} factory
+ */
+ function innerCreate(factory)
+ {
+ prompt.setEditor(factory.createEditor({
dgozman 2016/09/12 21:38:56 Let's pass editor/factory in constructor instead.
einbinder 2016/09/13 01:07:59 Done.
+ lineNumbers: false,
+ lineWrapping: true,
+ bracketMatchingFlag: "consoleBracketMatching",
+ mimeType: "javascript",
+ autoHeight: true
+ }));
+ return prompt;
+ }
+}
+WebInspector.ConsolePrompt.prototype = {
+
+ /**
+ * @return {!WebInspector.HistoryManager}
+ */
+ history: function()
+ {
+ return this._history;
+ },
+
+ /**
+ * @param {!WebInspector.TextEditor} editor
+ */
+ setEditor: function(editor)
+ {
+ this._editor = editor;
+ this._editor.configureAutocomplete({
+ substituteRangeCallback: this._substituteRange.bind(this),
+ suggestionsCallback: this._wordsWithPrefix.bind(this),
+ captureEnter: true
+ })
+ this.addKeyDownHandler(this._editorKeyDown.bind(this));
+ this.element = this._editor.widget().element;
+ },
+
+ /**
+ * @param {!Element} element
+ * @return {!Element}
+ */
+ attach: function(element)
dgozman 2016/09/12 21:38:56 Let's maybe make ConsolePrompt a widget itself?
einbinder 2016/09/13 01:07:59 Done.
einbinder 2016/09/13 01:07:59 Done.
+ {
+ this._editor.widget().show(element);
+ return this._editor.widget().element;
+ },
+
+ /**
+ * @param {function(!KeyboardEvent)} handler
+ */
+ addKeyDownHandler: function(handler)
dgozman 2016/09/12 21:38:56 Is this used outside?
einbinder 2016/09/13 01:07:59 Removed.
+ {
+ this._editor.addKeyDownHandler(handler);
+ },
+
+ clearAutoComplete: function()
dgozman 2016/09/12 21:38:57 |clearAutocomplete| to match editor.
einbinder 2016/09/13 01:07:59 Done.
+ {
+ this._editor.clearAutocomplete();
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isCaretInsidePrompt: function()
+ {
+ return this.hasFocus();
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isCaretAtEndOfPrompt: function()
+ {
+ return this._editor.selection().collapseToEnd().compareTo(this._editor.fullRange().collapseToEnd()) === 0;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isCaretOnLastLine: function()
+ {
+ return this._editor.selection().endLine === this._editor.fullRange().endLine;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isCaretOnFirstLine: function()
+ {
+ return (this._editor.selection().endLine === 0);
dgozman 2016/09/12 21:38:56 nit: extra ()
einbinder 2016/09/13 01:07:59 Done.
+ },
+
+ moveCaretToEndOfPrompt: function()
+ {
+ this._editor.setSelection(WebInspector.TextRange.createFromLocation(Infinity,Infinity));
+ },
+
+ moveCaretToEndOfFirstLine: function()
+ {
+ this._editor.setSelection(WebInspector.TextRange.createFromLocation(0,Infinity));
+ },
+
+ /**
+ * @param {string} text
+ */
+ setText: function(text){
dgozman 2016/09/12 21:38:56 { on next line
einbinder 2016/09/13 01:07:59 Done.
+ this._editor.setText(text);
+ },
+
+ /**
+ * @return {string}
+ */
+ text: function()
+ {
+ return this._editor.text();
+ },
+
+ setAddCompletionsFromHistory: function(value)
dgozman 2016/09/12 21:38:57 annotate please.
einbinder 2016/09/13 01:07:59 Done.
+ {
+ this._addCompletionsFromHistory = value;
+ },
+
+ /**
+ * @param {!KeyboardEvent} event
+ */
+ _editorKeyDown: function(event)
+ {
+ var newText;
+ var isPrevious;
+
+ switch (event.keyCode) {
+ case WebInspector.KeyboardShortcut.Keys.Up.code:
+ if (!this.isCaretOnFirstLine())
+ break;
+ newText = this._history.previous(this.text());
+ isPrevious = true;
+ break;
+ case WebInspector.KeyboardShortcut.Keys.Down.code:
+ if (!this.isCaretOnLastLine())
+ break;
+ newText = this._history.next();
+ break;
+ case WebInspector.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous
+ if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
+ newText = this._history.previous(this.text());
+ isPrevious = true;
+ }
+ break;
+ case WebInspector.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next
+ if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey)
+ newText = this._history.next();
+ break;
+ }
+
+ if (newText !== undefined) {
+ event.consume(true);
+ this.setText(newText);
+
+ if (isPrevious)
+ this.moveCaretToEndOfFirstLine();
+ else
+ this.moveCaretToEndOfPrompt();
+ return;
dgozman 2016/09/12 21:38:56 No need to return.
einbinder 2016/09/13 01:07:59 Done.
+ }
+ },
+
+ /**
+ * @param {string} prefix
+ * @return {!WebInspector.SuggestBox.Suggestions}
+ */
+ historyCompletions: function(prefix)
dgozman 2016/09/12 21:38:56 Is this used outside?
einbinder 2016/09/13 01:07:59 Doesn't appear to be anymore. Fixed.
+ {
+ if (!this._addCompletionsFromHistory || !this.isCaretAtEndOfPrompt())
+ return [];
+ var result = [];
+ var text = this.text();
+ var set = new Set();
+ var data = this._history.historyData();
+ for (var i = data.length - 1; i >= 0 && result.length < 50; --i) {
+ var item = data[i];
+ if (!item.startsWith(text))
+ continue;
+ if (set.has(item))
+ continue;
+ set.add(item);
+ result.push({title: item.substring(text.length - prefix.length), className: "additional"});
+ }
+ return result;
+ },
+
+ focus: function()
+ {
+ this._editor.focus();
+ },
+
+ /**
+ * @return {boolean}
+ */
+ hasFocus: function()
dgozman 2016/09/12 21:38:56 Is this used outside?
einbinder 2016/09/13 01:07:59 Removed.
+ {
+ return this._editor.hasFocus();
+ },
+
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?WebInspector.TextRange}
+ */
+ _substituteRange: function(lineNumber, columnNumber)
+ {
+ var lineText = this._editor.line(lineNumber);
+ var index;
+ for (index = lineText.length - 1; index >= 0; index--) {
+ if (" =:[({;,!+-*/&|^<>.".indexOf(lineText.charAt(index)) !== -1)
+ break;
+ }
+ return new WebInspector.TextRange(lineNumber, index + 1, lineNumber, columnNumber);
+ },
+
+ /**
+ * @param {!WebInspector.TextRange} prefixRange
+ * @param {!WebInspector.TextRange} substituteRange
+ * @return {!Promise.<!Array.<{title: string, className: (string|undefined)}>>}
+ */
+ _wordsWithPrefix: function(prefixRange, substituteRange)
+ {
+ var resolve;
+ var promise = new Promise(fufill => resolve = fufill);
+ var prefix = this._editor.text(prefixRange);
+ var before = this._editor.text(new WebInspector.TextRange(0,0,prefixRange.startLine,prefixRange.startColumn));
+ var historyWords = this.historyCompletions(prefix);
+ WebInspector.ExecutionContextSelector.completionsForTextInCurrentContext(before, prefix, false, innerWordsWithPrefix);
+ return promise;
+ /**
+ * @param {!Array.<string>} words
+ */
+ function innerWordsWithPrefix(words)
+ {
+ resolve(words.map(item => ({title:item})).concat(historyWords));
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698