OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
dgozman
2016/09/14 21:20:17
http://dev.chromium.org/blink/coding-style#TOC-Lic
einbinder
2016/09/15 00:14:09
Done.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @constructor | |
7 * @extends {WebInspector.Widget} | |
8 */ | |
9 WebInspector.ConsolePrompt = function() | |
10 { | |
11 WebInspector.Widget.call(this); | |
12 this._addCompletionsFromHistory = true; | |
13 this._history = new WebInspector.HistoryManager(); | |
14 | |
15 this._initialText = ""; | |
16 this._editor = null; | |
17 | |
18 this.element.tabIndex = 0; | |
19 this.element.addEventListener("keydown", this._editorKeyDown.bind(this), tru e); | |
20 | |
21 self.runtime.extension(WebInspector.TextEditorFactory).instance().then(gotFa ctory.bind(this)); | |
22 | |
23 /** | |
24 * @param {!WebInspector.TextEditorFactory} factory | |
25 * @this {WebInspector.ConsolePrompt} | |
26 */ | |
27 function gotFactory(factory) | |
28 { | |
29 this._editor = factory.createEditor({ | |
30 lineNumbers: false, | |
31 lineWrapping: true, | |
32 bracketMatchingFlag: "consoleBracketMatching", | |
33 mimeType: "javascript", | |
34 autoHeight: true | |
35 }); | |
36 | |
37 this._editor.configureAutocomplete({ | |
38 substituteRangeCallback: this._substituteRange.bind(this), | |
39 suggestionsCallback: this._wordsWithPrefix.bind(this), | |
40 captureEnter: true | |
41 }) | |
42 this._editor.widget().show(this.element); | |
43 | |
44 this.setText(this._initialText); | |
45 delete this._initialText; | |
46 if (this.hasFocus()) | |
47 this.focus(); | |
48 this.element.tabIndex = -1; | |
49 } | |
50 } | |
51 | |
52 WebInspector.ConsolePrompt.prototype = { | |
53 /** | |
54 * @return {!WebInspector.HistoryManager} | |
55 */ | |
56 history: function() | |
57 { | |
58 return this._history; | |
59 }, | |
60 | |
61 clearAutocomplete: function() | |
62 { | |
63 if (this._editor) | |
64 this._editor.clearAutocomplete(); | |
65 }, | |
66 | |
67 /** | |
68 * @return {boolean} | |
69 */ | |
70 isCaretInsidePrompt: function() | |
71 { | |
72 return this.hasFocus(); | |
73 }, | |
74 | |
75 /** | |
76 * @return {boolean} | |
77 */ | |
78 isCaretAtEndOfPrompt: function() | |
79 { | |
80 return !!this._editor && this._editor.selection().collapseToEnd().equal( this._editor.fullRange().collapseToEnd()); | |
81 }, | |
82 | |
83 /** | |
84 * @return {boolean} | |
85 */ | |
86 isCaretOnLastLine: function() | |
87 { | |
88 return !!this._editor && this._editor.selection().endLine === this._edit or.fullRange().endLine; | |
89 }, | |
90 | |
91 /** | |
92 * @return {boolean} | |
93 */ | |
94 isCaretOnFirstLine: function() | |
95 { | |
96 return !!this._editor && this._editor.selection().endLine === 0; | |
97 }, | |
98 | |
99 moveCaretToEndOfPrompt: function() | |
100 { | |
101 if (this._editor) | |
102 this._editor.setSelection(WebInspector.TextRange.createFromLocation( Infinity,Infinity)); | |
103 }, | |
104 | |
105 moveCaretToEndOfFirstLine: function() | |
106 { | |
107 if (this._editor) | |
108 this._editor.setSelection(WebInspector.TextRange.createFromLocation( 0,Infinity)); | |
109 }, | |
110 | |
111 /** | |
112 * @param {string} text | |
113 */ | |
114 setText: function(text) | |
115 { | |
116 if (this._editor) | |
117 this._editor.setText(text); | |
118 else | |
119 this._initialText = text; | |
120 }, | |
121 | |
122 /** | |
123 * @return {string} | |
124 */ | |
125 text: function() | |
126 { | |
127 return this._editor ? this._editor.text() : this._initialText; | |
128 }, | |
129 | |
130 /** | |
131 * @param {boolean} value | |
132 */ | |
133 setAddCompletionsFromHistory: function(value) | |
134 { | |
135 this._addCompletionsFromHistory = value; | |
136 }, | |
137 | |
138 /** | |
139 * @param {!Event} event | |
140 */ | |
141 _editorKeyDown: function(event) | |
142 { | |
143 var keyboardEvent = /** @type {!KeyboardEvent} */ (event); | |
144 var newText; | |
145 var isPrevious; | |
146 | |
147 switch (keyboardEvent.keyCode) { | |
148 case WebInspector.KeyboardShortcut.Keys.Up.code: | |
149 if (!this.isCaretOnFirstLine()) | |
150 break; | |
151 newText = this._history.previous(this.text()); | |
152 isPrevious = true; | |
153 break; | |
154 case WebInspector.KeyboardShortcut.Keys.Down.code: | |
155 if (!this.isCaretOnLastLine()) | |
156 break; | |
157 newText = this._history.next(); | |
158 break; | |
159 case WebInspector.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous | |
160 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent. metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey) { | |
161 newText = this._history.previous(this.text()); | |
162 isPrevious = true; | |
163 } | |
164 break; | |
165 case WebInspector.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next | |
166 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent. metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey) | |
167 newText = this._history.next(); | |
168 break; | |
169 } | |
170 | |
171 if (newText === undefined) | |
172 return; | |
173 keyboardEvent.consume(true); | |
174 this.setText(newText); | |
175 | |
176 if (isPrevious) | |
177 this.moveCaretToEndOfFirstLine(); | |
178 else | |
179 this.moveCaretToEndOfPrompt(); | |
180 }, | |
181 | |
182 /** | |
183 * @param {string} prefix | |
184 * @return {!WebInspector.SuggestBox.Suggestions} | |
185 */ | |
186 _historyCompletions: function(prefix) | |
187 { | |
188 if (!this._addCompletionsFromHistory || !this.isCaretAtEndOfPrompt()) | |
189 return []; | |
190 var result = []; | |
191 var text = this.text(); | |
192 var set = new Set(); | |
193 var data = this._history.historyData(); | |
194 for (var i = data.length - 1; i >= 0 && result.length < 50; --i) { | |
195 var item = data[i]; | |
196 if (!item.startsWith(text)) | |
197 continue; | |
198 if (set.has(item)) | |
199 continue; | |
200 set.add(item); | |
201 result.push({title: item.substring(text.length - prefix.length), cla ssName: "additional"}); | |
202 } | |
203 return result; | |
204 }, | |
205 | |
206 /** | |
207 * @override | |
208 */ | |
209 focus: function() | |
210 { | |
211 if (this._editor) | |
212 this._editor.widget().focus(); | |
213 else | |
214 this.element.focus(); | |
215 }, | |
216 | |
217 /** | |
218 * @param {number} lineNumber | |
219 * @param {number} columnNumber | |
220 * @return {?WebInspector.TextRange} | |
221 */ | |
222 _substituteRange: function(lineNumber, columnNumber) | |
223 { | |
224 var lineText = this._editor.line(lineNumber); | |
225 var index; | |
226 for (index = lineText.length - 1; index >= 0; index--) { | |
227 if (" =:[({;,!+-*/&|^<>.".indexOf(lineText.charAt(index)) !== -1) | |
228 break; | |
229 } | |
230 return new WebInspector.TextRange(lineNumber, index + 1, lineNumber, col umnNumber); | |
231 }, | |
232 | |
233 /** | |
234 * @param {!WebInspector.TextRange} prefixRange | |
235 * @param {!WebInspector.TextRange} substituteRange | |
236 * @return {!Promise.<!Array.<{title: string, className: (string|undefined)} >>} | |
237 */ | |
238 _wordsWithPrefix: function(prefixRange, substituteRange) | |
239 { | |
240 var resolve; | |
dgozman
2016/09/14 21:20:17
resolve -> fulfill
einbinder
2016/09/15 00:14:09
Done.
| |
241 var promise = new Promise(fufill => resolve = fufill); | |
242 var prefix = this._editor.text(prefixRange); | |
243 var before = this._editor.text(new WebInspector.TextRange(0, 0, prefixRa nge.startLine, prefixRange.startColumn)); | |
244 var historyWords = this._historyCompletions(prefix); | |
245 WebInspector.ExecutionContextSelector.completionsForTextInCurrentContext (before, prefix, false /* Don't force */, innerWordsWithPrefix); | |
246 return promise; | |
247 | |
248 /** | |
249 * @param {!Array.<string>} words | |
250 */ | |
251 function innerWordsWithPrefix(words) | |
252 { | |
253 resolve(words.map(item => ({title:item})).concat(historyWords)); | |
254 } | |
255 }, | |
256 | |
257 __proto__: WebInspector.Widget.prototype | |
258 } | |
OLD | NEW |