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

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

Issue 2331053002: DevTools: Implement the console prompt with CodeMirror (Closed)
Patch Set: Merge 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 unified diff | Download patch
OLDNEW
(Empty)
1 /**
pfeldman 2016/09/14 00:31:52 Where is my copyright?
einbinder 2016/09/14 20:21:06 Done.
2 * @constructor
3 * @extends {WebInspector.Widget}
4 */
5 WebInspector.ConsolePrompt = function()
6 {
7 WebInspector.Widget.call(this);
pfeldman 2016/09/14 00:31:53 There is no point in making something a widget unl
einbinder 2016/09/14 20:21:06 Even if it needs a public .element and needs .focu
8 this._addCompletionsFromHistory = true;
9 this._history = new WebInspector.HistoryManager();
10
11 this._initialText = "";
12 this._needsFocus = false;
13 this._editor = null;
14
15 this.element.addEventListener("keydown", this._editorKeyDown.bind(this), tru e);
16
17 self.runtime.extension(WebInspector.TextEditorFactory).instance().then(gotFa ctory.bind(this));
18
19 /**
20 * @param {!WebInspector.TextEditorFactory} factory
21 * @this {!WebInspector.ConsolePrompt}
pfeldman 2016/09/14 00:31:52 drop !
einbinder 2016/09/14 20:21:05 Done.
22 */
23 function gotFactory(factory)
24 {
25 this._editor = factory.createEditor({
26 lineNumbers: false,
27 lineWrapping: true,
28 bracketMatchingFlag: "consoleBracketMatching",
29 mimeType: "javascript",
30 autoHeight: true
31 });
32
33 this._editor.configureAutocomplete({
34 substituteRangeCallback: this._substituteRange.bind(this),
35 suggestionsCallback: this._wordsWithPrefix.bind(this),
36 captureEnter: true
37 })
38 this._editor.widget().show(this.element);
39
40 this.setText(this._initialText)
dgozman 2016/09/14 04:26:17 semicolon
einbinder 2016/09/14 20:21:06 Done.
41 if (this._needsFocus)
pfeldman 2016/09/14 00:31:52 What if I already clicked away? Might need to set
dgozman 2016/09/14 04:26:17 delete this._initialText;
einbinder 2016/09/14 20:21:06 I thought it was acceptable losses. I can make it
42 this.focus();
43 this._needsFocus = false;
44 }
45 }
46
47 WebInspector.ConsolePrompt.prototype = {
48
lushnikov 2016/09/14 01:11:21 nit: stray line
einbinder 2016/09/14 20:21:06 Done.
49 /**
50 * @return {!WebInspector.HistoryManager}
51 */
52 history: function()
53 {
54 return this._history;
55 },
56
57 clearAutocomplete: function()
58 {
59 if (this._editor)
60 this._editor.clearAutocomplete();
61 },
62
63 /**
64 * @return {boolean}
65 */
66 isCaretInsidePrompt: function()
67 {
68 return this.hasFocus();
69 },
70
71 /**
72 * @return {boolean}
73 */
74 isCaretAtEndOfPrompt: function()
75 {
76 return !!this._editor && this._editor.selection().collapseToEnd().compar eTo(this._editor.fullRange().collapseToEnd()) === 0;
lushnikov 2016/09/14 01:11:21 nit: compareTo -> .equal
einbinder 2016/09/14 20:21:06 Done.
77 },
78
79 /**
80 * @return {boolean}
81 */
82 isCaretOnLastLine: function()
83 {
84 return !!this._editor && this._editor.selection().endLine === this._edit or.fullRange().endLine;
85 },
86
87 /**
88 * @return {boolean}
89 */
90 isCaretOnFirstLine: function()
91 {
92 return !!this._editor && this._editor.selection().endLine === 0;
93 },
94
95 moveCaretToEndOfPrompt: function()
96 {
97 if (this._editor)
98 this._editor.setSelection(WebInspector.TextRange.createFromLocation( Infinity,Infinity));
99 },
100
101 moveCaretToEndOfFirstLine: function()
102 {
103 if (this._editor)
104 this._editor.setSelection(WebInspector.TextRange.createFromLocation( 0,Infinity));
105 },
106
107 /**
108 * @param {string} text
109 */
110 setText: function(text)
111 {
112 if (this._editor)
113 this._editor.setText(text);
114 else
115 this._initialText = text;
116 },
117
118 /**
119 * @return {string}
120 */
121 text: function()
122 {
123 return this._editor ? this._editor.text() : this._initialText;
124 },
125
126 /**
127 * @param {boolean} value
128 */
129 setAddCompletionsFromHistory: function(value)
130 {
131 this._addCompletionsFromHistory = value;
132 },
133
134 /**
135 * @param {!Event} event
136 */
137 _editorKeyDown: function(event)
138 {
139 var keyboardEvent = /** @type {!KeyboardEvent} */ (event);
140 var newText;
141 var isPrevious;
142
143 switch (keyboardEvent.keyCode) {
lushnikov 2016/09/14 01:11:21 You probably will simplify key handling if you use
einbinder 2016/09/14 20:21:06 I stole this code from TextPrompt. How about I cle
144 case WebInspector.KeyboardShortcut.Keys.Up.code:
145 if (!this.isCaretOnFirstLine())
146 break;
147 newText = this._history.previous(this.text());
148 isPrevious = true;
149 break;
150 case WebInspector.KeyboardShortcut.Keys.Down.code:
151 if (!this.isCaretOnLastLine())
152 break;
153 newText = this._history.next();
154 break;
155 case WebInspector.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous
156 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent. metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey) {
157 newText = this._history.previous(this.text());
158 isPrevious = true;
159 }
160 break;
161 case WebInspector.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next
162 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent. metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey)
163 newText = this._history.next();
164 break;
165 }
166
167 if (newText !== undefined) {
lushnikov 2016/09/14 01:11:21 fast-return?
einbinder 2016/09/14 20:21:06 Done.
168 keyboardEvent.consume(true);
169 this.setText(newText);
170
171 if (isPrevious)
172 this.moveCaretToEndOfFirstLine();
173 else
174 this.moveCaretToEndOfPrompt();
175 }
176 },
177
178 /**
179 * @param {string} prefix
180 * @return {!WebInspector.SuggestBox.Suggestions}
181 */
182 _historyCompletions: function(prefix)
183 {
184 if (!this._addCompletionsFromHistory || !this.isCaretAtEndOfPrompt())
185 return [];
186 var result = [];
187 var text = this.text();
188 var set = new Set();
189 var data = this._history.historyData();
190 for (var i = data.length - 1; i >= 0 && result.length < 50; --i) {
191 var item = data[i];
192 if (!item.startsWith(text))
193 continue;
194 if (set.has(item))
195 continue;
196 set.add(item);
197 result.push({title: item.substring(text.length - prefix.length), cla ssName: "additional"});
198 }
199 return result;
200 },
201
202 /**
203 * @override
204 */
205 focus: function()
206 {
207 if (this._editor)
208 this._editor.widget().focus();
209 else
210 this._needsFocus = true;
dgozman 2016/09/14 04:26:17 Let's instead focus this.element here, and switch
einbinder 2016/09/14 20:21:05 Done.
211 },
212
213 /**
214 * @param {number} lineNumber
215 * @param {number} columnNumber
216 * @return {?WebInspector.TextRange}
217 */
218 _substituteRange: function(lineNumber, columnNumber)
219 {
220 if (!this._editor)
221 return null;
222
223 var lineText = this._editor.line(lineNumber);
224 var index;
225 for (index = lineText.length - 1; index >= 0; index--) {
226 if (" =:[({;,!+-*/&|^<>.".indexOf(lineText.charAt(index)) !== -1)
227 break;
228 }
229 return new WebInspector.TextRange(lineNumber, index + 1, lineNumber, col umnNumber);
230 },
231
232 /**
233 * @param {!WebInspector.TextRange} prefixRange
234 * @param {!WebInspector.TextRange} substituteRange
235 * @return {!Promise.<!Array.<{title: string, className: (string|undefined)} >>}
236 */
237 _wordsWithPrefix: function(prefixRange, substituteRange)
238 {
239 if (!this._editor)
lushnikov 2016/09/14 01:11:21 how could there be no editor?
240 return Promise.resolve([]);
241
242 var resolve;
243 var promise = new Promise(fufill => resolve = fufill);
244 var prefix = this._editor.text(prefixRange);
245 var before = this._editor.text(new WebInspector.TextRange(0,0,prefixRang e.startLine,prefixRange.startColumn));
dgozman 2016/09/14 04:26:18 spaces
einbinder 2016/09/14 20:21:06 Done.
246 var historyWords = this._historyCompletions(prefix);
247 WebInspector.ExecutionContextSelector.completionsForTextInCurrentContext (before, prefix, false, innerWordsWithPrefix);
dgozman 2016/09/14 04:26:17 Let's annotate false /* doSomething */
einbinder 2016/09/14 20:21:06 Done.
248 return promise;
249 /**
dgozman 2016/09/14 04:26:17 empty line please
einbinder 2016/09/14 20:21:05 Done.
250 * @param {!Array.<string>} words
251 */
252 function innerWordsWithPrefix(words)
253 {
254 resolve(words.map(item => ({title:item})).concat(historyWords));
255 }
256 },
257
258 __proto__: WebInspector.Widget.prototype
259 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698