| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | |
| 5 /** | 4 /** |
| 6 * @constructor | 5 * @unrestricted |
| 7 * @extends {WebInspector.Widget} | |
| 8 */ | 6 */ |
| 9 WebInspector.ConsolePrompt = function() | 7 WebInspector.ConsolePrompt = class extends WebInspector.Widget { |
| 10 { | 8 constructor() { |
| 11 WebInspector.Widget.call(this); | 9 super(); |
| 12 this._addCompletionsFromHistory = true; | 10 this._addCompletionsFromHistory = true; |
| 13 this._history = new WebInspector.ConsoleHistoryManager(); | 11 this._history = new WebInspector.ConsoleHistoryManager(); |
| 14 | 12 |
| 15 this._initialText = ""; | 13 this._initialText = ''; |
| 16 this._editor = null; | 14 this._editor = null; |
| 17 | 15 |
| 18 this.element.tabIndex = 0; | 16 this.element.tabIndex = 0; |
| 19 | 17 |
| 20 self.runtime.extension(WebInspector.TextEditorFactory).instance().then(gotFa
ctory.bind(this)); | 18 self.runtime.extension(WebInspector.TextEditorFactory).instance().then(gotFa
ctory.bind(this)); |
| 21 | 19 |
| 22 /** | 20 /** |
| 23 * @param {!WebInspector.TextEditorFactory} factory | 21 * @param {!WebInspector.TextEditorFactory} factory |
| 24 * @this {WebInspector.ConsolePrompt} | 22 * @this {WebInspector.ConsolePrompt} |
| 25 */ | 23 */ |
| 26 function gotFactory(factory) | 24 function gotFactory(factory) { |
| 27 { | 25 this._editor = |
| 28 this._editor = factory.createEditor({ | 26 factory.createEditor({lineNumbers: false, lineWrapping: true, mimeType
: 'javascript', autoHeight: true}); |
| 29 lineNumbers: false, | 27 |
| 30 lineWrapping: true, | 28 this._editor.configureAutocomplete({ |
| 31 mimeType: "javascript", | 29 substituteRangeCallback: this._substituteRange.bind(this), |
| 32 autoHeight: true | 30 suggestionsCallback: this._wordsWithPrefix.bind(this), |
| 33 }); | 31 captureEnter: true |
| 34 | 32 }); |
| 35 this._editor.configureAutocomplete({ | 33 this._editor.widget().element.addEventListener('keydown', this._editorKeyD
own.bind(this), true); |
| 36 substituteRangeCallback: this._substituteRange.bind(this), | 34 this._editor.widget().show(this.element); |
| 37 suggestionsCallback: this._wordsWithPrefix.bind(this), | 35 |
| 38 captureEnter: true | 36 this.setText(this._initialText); |
| 39 }); | 37 delete this._initialText; |
| 40 this._editor.widget().element.addEventListener("keydown", this._editorKe
yDown.bind(this), true); | 38 if (this.hasFocus()) |
| 41 this._editor.widget().show(this.element); | 39 this.focus(); |
| 42 | 40 this.element.tabIndex = -1; |
| 43 this.setText(this._initialText); | 41 |
| 44 delete this._initialText; | 42 this._editorSetForTest(); |
| 45 if (this.hasFocus()) | 43 } |
| 46 this.focus(); | 44 } |
| 47 this.element.tabIndex = -1; | 45 |
| 48 | 46 /** |
| 49 this._editorSetForTest(); | 47 * @return {!WebInspector.ConsoleHistoryManager} |
| 50 } | 48 */ |
| 49 history() { |
| 50 return this._history; |
| 51 } |
| 52 |
| 53 clearAutocomplete() { |
| 54 if (this._editor) |
| 55 this._editor.clearAutocomplete(); |
| 56 } |
| 57 |
| 58 /** |
| 59 * @return {boolean} |
| 60 */ |
| 61 _isCaretAtEndOfPrompt() { |
| 62 return !!this._editor && this._editor.selection().collapseToEnd().equal(this
._editor.fullRange().collapseToEnd()); |
| 63 } |
| 64 |
| 65 moveCaretToEndOfPrompt() { |
| 66 if (this._editor) |
| 67 this._editor.setSelection(WebInspector.TextRange.createFromLocation(Infini
ty, Infinity)); |
| 68 } |
| 69 |
| 70 /** |
| 71 * @param {string} text |
| 72 */ |
| 73 setText(text) { |
| 74 if (this._editor) |
| 75 this._editor.setText(text); |
| 76 else |
| 77 this._initialText = text; |
| 78 } |
| 79 |
| 80 /** |
| 81 * @return {string} |
| 82 */ |
| 83 text() { |
| 84 return this._editor ? this._editor.text() : this._initialText; |
| 85 } |
| 86 |
| 87 /** |
| 88 * @param {boolean} value |
| 89 */ |
| 90 setAddCompletionsFromHistory(value) { |
| 91 this._addCompletionsFromHistory = value; |
| 92 } |
| 93 |
| 94 /** |
| 95 * @param {!Event} event |
| 96 */ |
| 97 _editorKeyDown(event) { |
| 98 var keyboardEvent = /** @type {!KeyboardEvent} */ (event); |
| 99 var newText; |
| 100 var isPrevious; |
| 101 |
| 102 switch (keyboardEvent.keyCode) { |
| 103 case WebInspector.KeyboardShortcut.Keys.Up.code: |
| 104 if (this._editor.selection().endLine > 0) |
| 105 break; |
| 106 newText = this._history.previous(this.text()); |
| 107 isPrevious = true; |
| 108 break; |
| 109 case WebInspector.KeyboardShortcut.Keys.Down.code: |
| 110 if (this._editor.selection().endLine < this._editor.fullRange().endLine) |
| 111 break; |
| 112 newText = this._history.next(); |
| 113 break; |
| 114 case WebInspector.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous |
| 115 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent.meta
Key && !keyboardEvent.altKey && |
| 116 !keyboardEvent.shiftKey) { |
| 117 newText = this._history.previous(this.text()); |
| 118 isPrevious = true; |
| 119 } |
| 120 break; |
| 121 case WebInspector.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next |
| 122 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent.meta
Key && !keyboardEvent.altKey && |
| 123 !keyboardEvent.shiftKey) |
| 124 newText = this._history.next(); |
| 125 break; |
| 126 case WebInspector.KeyboardShortcut.Keys.Enter.code: |
| 127 this._enterKeyPressed(keyboardEvent); |
| 128 break; |
| 129 } |
| 130 |
| 131 if (newText === undefined) |
| 132 return; |
| 133 keyboardEvent.consume(true); |
| 134 this.setText(newText); |
| 135 |
| 136 if (isPrevious) |
| 137 this._editor.setSelection(WebInspector.TextRange.createFromLocation(0, Inf
inity)); |
| 138 else |
| 139 this.moveCaretToEndOfPrompt(); |
| 140 } |
| 141 |
| 142 /** |
| 143 * @param {!KeyboardEvent} event |
| 144 */ |
| 145 _enterKeyPressed(event) { |
| 146 if (event.altKey || event.ctrlKey || event.shiftKey) |
| 147 return; |
| 148 |
| 149 event.consume(true); |
| 150 |
| 151 this.clearAutocomplete(); |
| 152 |
| 153 var str = this.text(); |
| 154 if (!str.length) |
| 155 return; |
| 156 |
| 157 var currentExecutionContext = WebInspector.context.flavor(WebInspector.Execu
tionContext); |
| 158 if (!this._isCaretAtEndOfPrompt() || !currentExecutionContext) { |
| 159 this._appendCommand(str, true); |
| 160 return; |
| 161 } |
| 162 currentExecutionContext.target().runtimeModel.compileScript( |
| 163 str, '', false, currentExecutionContext.id, compileCallback.bind(this)); |
| 164 |
| 165 /** |
| 166 * @param {!RuntimeAgent.ScriptId=} scriptId |
| 167 * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails |
| 168 * @this {WebInspector.ConsolePrompt} |
| 169 */ |
| 170 function compileCallback(scriptId, exceptionDetails) { |
| 171 if (str !== this.text()) |
| 172 return; |
| 173 if (exceptionDetails && |
| 174 (exceptionDetails.exception.description.startsWith('SyntaxError: Unexp
ected end of input') || |
| 175 exceptionDetails.exception.description.startsWith('SyntaxError: Unter
minated template literal'))) { |
| 176 this._editor.newlineAndIndent(); |
| 177 this._enterProcessedForTest(); |
| 178 return; |
| 179 } |
| 180 this._appendCommand(str, true); |
| 181 this._enterProcessedForTest(); |
| 182 } |
| 183 } |
| 184 |
| 185 /** |
| 186 * @param {string} text |
| 187 * @param {boolean} useCommandLineAPI |
| 188 */ |
| 189 _appendCommand(text, useCommandLineAPI) { |
| 190 this.setText(''); |
| 191 var currentExecutionContext = WebInspector.context.flavor(WebInspector.Execu
tionContext); |
| 192 if (currentExecutionContext) { |
| 193 WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext
, text, useCommandLineAPI); |
| 194 if (WebInspector.ConsolePanel.instance().isShowing()) |
| 195 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.Com
mandEvaluatedInConsolePanel); |
| 196 } |
| 197 } |
| 198 |
| 199 _enterProcessedForTest() { |
| 200 } |
| 201 |
| 202 /** |
| 203 * @param {string} prefix |
| 204 * @return {!WebInspector.SuggestBox.Suggestions} |
| 205 */ |
| 206 _historyCompletions(prefix) { |
| 207 if (!this._addCompletionsFromHistory || !this._isCaretAtEndOfPrompt()) |
| 208 return []; |
| 209 var result = []; |
| 210 var text = this.text(); |
| 211 var set = new Set(); |
| 212 var data = this._history.historyData(); |
| 213 for (var i = data.length - 1; i >= 0 && result.length < 50; --i) { |
| 214 var item = data[i]; |
| 215 if (!item.startsWith(text)) |
| 216 continue; |
| 217 if (set.has(item)) |
| 218 continue; |
| 219 set.add(item); |
| 220 result.push({title: item.substring(text.length - prefix.length), className
: 'additional'}); |
| 221 } |
| 222 return result; |
| 223 } |
| 224 |
| 225 /** |
| 226 * @override |
| 227 */ |
| 228 focus() { |
| 229 if (this._editor) |
| 230 this._editor.widget().focus(); |
| 231 else |
| 232 this.element.focus(); |
| 233 } |
| 234 |
| 235 /** |
| 236 * @param {number} lineNumber |
| 237 * @param {number} columnNumber |
| 238 * @return {?WebInspector.TextRange} |
| 239 */ |
| 240 _substituteRange(lineNumber, columnNumber) { |
| 241 var lineText = this._editor.line(lineNumber); |
| 242 var index; |
| 243 for (index = lineText.length - 1; index >= 0; index--) { |
| 244 if (' =:[({;,!+-*/&|^<>.'.indexOf(lineText.charAt(index)) !== -1) |
| 245 break; |
| 246 } |
| 247 return new WebInspector.TextRange(lineNumber, index + 1, lineNumber, columnN
umber); |
| 248 } |
| 249 |
| 250 /** |
| 251 * @param {!WebInspector.TextRange} prefixRange |
| 252 * @param {!WebInspector.TextRange} substituteRange |
| 253 * @return {!Promise<!WebInspector.SuggestBox.Suggestions>} |
| 254 */ |
| 255 _wordsWithPrefix(prefixRange, substituteRange) { |
| 256 var prefix = this._editor.text(prefixRange); |
| 257 var before = this._editor.text(new WebInspector.TextRange(0, 0, prefixRange.
startLine, prefixRange.startColumn)); |
| 258 var historyWords = this._historyCompletions(prefix); |
| 259 return WebInspector.ExecutionContextSelector.completionsForTextInCurrentCont
ext(before, prefix, true /* force */) |
| 260 .then(innerWordsWithPrefix); |
| 261 |
| 262 /** |
| 263 * @param {!Array<string>} words |
| 264 * @return {!WebInspector.SuggestBox.Suggestions} |
| 265 */ |
| 266 function innerWordsWithPrefix(words) { |
| 267 return words.map(item => ({title: item})).concat(historyWords); |
| 268 } |
| 269 } |
| 270 |
| 271 _editorSetForTest() { |
| 272 } |
| 51 }; | 273 }; |
| 52 | 274 |
| 53 WebInspector.ConsolePrompt.prototype = { | |
| 54 /** | |
| 55 * @return {!WebInspector.ConsoleHistoryManager} | |
| 56 */ | |
| 57 history: function() | |
| 58 { | |
| 59 return this._history; | |
| 60 }, | |
| 61 | |
| 62 clearAutocomplete: function() | |
| 63 { | |
| 64 if (this._editor) | |
| 65 this._editor.clearAutocomplete(); | |
| 66 }, | |
| 67 | |
| 68 /** | |
| 69 * @return {boolean} | |
| 70 */ | |
| 71 _isCaretAtEndOfPrompt: function() | |
| 72 { | |
| 73 return !!this._editor && this._editor.selection().collapseToEnd().equal(
this._editor.fullRange().collapseToEnd()); | |
| 74 }, | |
| 75 | |
| 76 moveCaretToEndOfPrompt: function() | |
| 77 { | |
| 78 if (this._editor) | |
| 79 this._editor.setSelection(WebInspector.TextRange.createFromLocation(
Infinity, Infinity)); | |
| 80 }, | |
| 81 | |
| 82 /** | |
| 83 * @param {string} text | |
| 84 */ | |
| 85 setText: function(text) | |
| 86 { | |
| 87 if (this._editor) | |
| 88 this._editor.setText(text); | |
| 89 else | |
| 90 this._initialText = text; | |
| 91 }, | |
| 92 | |
| 93 /** | |
| 94 * @return {string} | |
| 95 */ | |
| 96 text: function() | |
| 97 { | |
| 98 return this._editor ? this._editor.text() : this._initialText; | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * @param {boolean} value | |
| 103 */ | |
| 104 setAddCompletionsFromHistory: function(value) | |
| 105 { | |
| 106 this._addCompletionsFromHistory = value; | |
| 107 }, | |
| 108 | |
| 109 /** | |
| 110 * @param {!Event} event | |
| 111 */ | |
| 112 _editorKeyDown: function(event) | |
| 113 { | |
| 114 var keyboardEvent = /** @type {!KeyboardEvent} */ (event); | |
| 115 var newText; | |
| 116 var isPrevious; | |
| 117 | |
| 118 switch (keyboardEvent.keyCode) { | |
| 119 case WebInspector.KeyboardShortcut.Keys.Up.code: | |
| 120 if (this._editor.selection().endLine > 0) | |
| 121 break; | |
| 122 newText = this._history.previous(this.text()); | |
| 123 isPrevious = true; | |
| 124 break; | |
| 125 case WebInspector.KeyboardShortcut.Keys.Down.code: | |
| 126 if (this._editor.selection().endLine < this._editor.fullRange().endL
ine) | |
| 127 break; | |
| 128 newText = this._history.next(); | |
| 129 break; | |
| 130 case WebInspector.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous | |
| 131 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent.
metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey) { | |
| 132 newText = this._history.previous(this.text()); | |
| 133 isPrevious = true; | |
| 134 } | |
| 135 break; | |
| 136 case WebInspector.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next | |
| 137 if (WebInspector.isMac() && keyboardEvent.ctrlKey && !keyboardEvent.
metaKey && !keyboardEvent.altKey && !keyboardEvent.shiftKey) | |
| 138 newText = this._history.next(); | |
| 139 break; | |
| 140 case WebInspector.KeyboardShortcut.Keys.Enter.code: | |
| 141 this._enterKeyPressed(keyboardEvent); | |
| 142 break; | |
| 143 } | |
| 144 | |
| 145 if (newText === undefined) | |
| 146 return; | |
| 147 keyboardEvent.consume(true); | |
| 148 this.setText(newText); | |
| 149 | |
| 150 if (isPrevious) | |
| 151 this._editor.setSelection(WebInspector.TextRange.createFromLocation(
0, Infinity)); | |
| 152 else | |
| 153 this.moveCaretToEndOfPrompt(); | |
| 154 }, | |
| 155 | |
| 156 /** | |
| 157 * @param {!KeyboardEvent} event | |
| 158 */ | |
| 159 _enterKeyPressed: function(event) | |
| 160 { | |
| 161 if (event.altKey || event.ctrlKey || event.shiftKey) | |
| 162 return; | |
| 163 | |
| 164 event.consume(true); | |
| 165 | |
| 166 this.clearAutocomplete(); | |
| 167 | |
| 168 var str = this.text(); | |
| 169 if (!str.length) | |
| 170 return; | |
| 171 | |
| 172 var currentExecutionContext = WebInspector.context.flavor(WebInspector.E
xecutionContext); | |
| 173 if (!this._isCaretAtEndOfPrompt() || !currentExecutionContext) { | |
| 174 this._appendCommand(str, true); | |
| 175 return; | |
| 176 } | |
| 177 currentExecutionContext.target().runtimeModel.compileScript(str, "", fal
se, currentExecutionContext.id, compileCallback.bind(this)); | |
| 178 | |
| 179 /** | |
| 180 * @param {!RuntimeAgent.ScriptId=} scriptId | |
| 181 * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails | |
| 182 * @this {WebInspector.ConsolePrompt} | |
| 183 */ | |
| 184 function compileCallback(scriptId, exceptionDetails) | |
| 185 { | |
| 186 if (str !== this.text()) | |
| 187 return; | |
| 188 if (exceptionDetails && (exceptionDetails.exception.description.star
tsWith("SyntaxError: Unexpected end of input") | |
| 189 || exceptionDetails.exception.description.startsWith("SyntaxErro
r: Unterminated template literal"))) { | |
| 190 this._editor.newlineAndIndent(); | |
| 191 this._enterProcessedForTest(); | |
| 192 return; | |
| 193 } | |
| 194 this._appendCommand(str, true); | |
| 195 this._enterProcessedForTest(); | |
| 196 } | |
| 197 }, | |
| 198 | |
| 199 /** | |
| 200 * @param {string} text | |
| 201 * @param {boolean} useCommandLineAPI | |
| 202 */ | |
| 203 _appendCommand: function(text, useCommandLineAPI) | |
| 204 { | |
| 205 this.setText(""); | |
| 206 var currentExecutionContext = WebInspector.context.flavor(WebInspector.E
xecutionContext); | |
| 207 if (currentExecutionContext) { | |
| 208 WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionC
ontext, text, useCommandLineAPI); | |
| 209 if (WebInspector.ConsolePanel.instance().isShowing()) | |
| 210 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Ac
tion.CommandEvaluatedInConsolePanel); | |
| 211 } | |
| 212 }, | |
| 213 | |
| 214 _enterProcessedForTest: function() { }, | |
| 215 | |
| 216 /** | |
| 217 * @param {string} prefix | |
| 218 * @return {!WebInspector.SuggestBox.Suggestions} | |
| 219 */ | |
| 220 _historyCompletions: function(prefix) | |
| 221 { | |
| 222 if (!this._addCompletionsFromHistory || !this._isCaretAtEndOfPrompt()) | |
| 223 return []; | |
| 224 var result = []; | |
| 225 var text = this.text(); | |
| 226 var set = new Set(); | |
| 227 var data = this._history.historyData(); | |
| 228 for (var i = data.length - 1; i >= 0 && result.length < 50; --i) { | |
| 229 var item = data[i]; | |
| 230 if (!item.startsWith(text)) | |
| 231 continue; | |
| 232 if (set.has(item)) | |
| 233 continue; | |
| 234 set.add(item); | |
| 235 result.push({ title: item.substring(text.length - prefix.length), cl
assName: "additional" }); | |
| 236 } | |
| 237 return result; | |
| 238 }, | |
| 239 | |
| 240 /** | |
| 241 * @override | |
| 242 */ | |
| 243 focus: function() | |
| 244 { | |
| 245 if (this._editor) | |
| 246 this._editor.widget().focus(); | |
| 247 else | |
| 248 this.element.focus(); | |
| 249 }, | |
| 250 | |
| 251 /** | |
| 252 * @param {number} lineNumber | |
| 253 * @param {number} columnNumber | |
| 254 * @return {?WebInspector.TextRange} | |
| 255 */ | |
| 256 _substituteRange: function(lineNumber, columnNumber) | |
| 257 { | |
| 258 var lineText = this._editor.line(lineNumber); | |
| 259 var index; | |
| 260 for (index = lineText.length - 1; index >= 0; index--) { | |
| 261 if (" =:[({;,!+-*/&|^<>.".indexOf(lineText.charAt(index)) !== -1) | |
| 262 break; | |
| 263 } | |
| 264 return new WebInspector.TextRange(lineNumber, index + 1, lineNumber, col
umnNumber); | |
| 265 }, | |
| 266 | |
| 267 /** | |
| 268 * @param {!WebInspector.TextRange} prefixRange | |
| 269 * @param {!WebInspector.TextRange} substituteRange | |
| 270 * @return {!Promise<!WebInspector.SuggestBox.Suggestions>} | |
| 271 */ | |
| 272 _wordsWithPrefix: function(prefixRange, substituteRange) | |
| 273 { | |
| 274 var prefix = this._editor.text(prefixRange); | |
| 275 var before = this._editor.text(new WebInspector.TextRange(0, 0, prefixRa
nge.startLine, prefixRange.startColumn)); | |
| 276 var historyWords = this._historyCompletions(prefix); | |
| 277 return WebInspector.ExecutionContextSelector.completionsForTextInCurrent
Context(before, prefix, true /* force */).then(innerWordsWithPrefix); | |
| 278 | |
| 279 /** | |
| 280 * @param {!Array<string>} words | |
| 281 * @return {!WebInspector.SuggestBox.Suggestions} | |
| 282 */ | |
| 283 function innerWordsWithPrefix(words) | |
| 284 { | |
| 285 return words.map(item => ({title:item})).concat(historyWords); | |
| 286 } | |
| 287 }, | |
| 288 | |
| 289 _editorSetForTest: function() { }, | |
| 290 | |
| 291 __proto__: WebInspector.Widget.prototype | |
| 292 }; | |
| 293 | |
| 294 /** | 275 /** |
| 295 * @constructor | 276 * @unrestricted |
| 296 */ | 277 */ |
| 297 WebInspector.ConsoleHistoryManager = function() | 278 WebInspector.ConsoleHistoryManager = class { |
| 298 { | 279 constructor() { |
| 299 /** | 280 /** |
| 300 * @type {!Array.<string>} | 281 * @type {!Array.<string>} |
| 301 */ | 282 */ |
| 302 this._data = []; | 283 this._data = []; |
| 303 | 284 |
| 304 /** | 285 /** |
| 305 * 1-based entry in the history stack. | 286 * 1-based entry in the history stack. |
| 306 * @type {number} | 287 * @type {number} |
| 307 */ | 288 */ |
| 308 this._historyOffset = 1; | 289 this._historyOffset = 1; |
| 290 } |
| 291 |
| 292 /** |
| 293 * @return {!Array.<string>} |
| 294 */ |
| 295 historyData() { |
| 296 return this._data; |
| 297 } |
| 298 |
| 299 /** |
| 300 * @param {!Array.<string>} data |
| 301 */ |
| 302 setHistoryData(data) { |
| 303 this._data = data.slice(); |
| 304 this._historyOffset = 1; |
| 305 } |
| 306 |
| 307 /** |
| 308 * Pushes a committed text into the history. |
| 309 * @param {string} text |
| 310 */ |
| 311 pushHistoryItem(text) { |
| 312 if (this._uncommittedIsTop) { |
| 313 this._data.pop(); |
| 314 delete this._uncommittedIsTop; |
| 315 } |
| 316 |
| 317 this._historyOffset = 1; |
| 318 if (text === this._currentHistoryItem()) |
| 319 return; |
| 320 this._data.push(text); |
| 321 } |
| 322 |
| 323 /** |
| 324 * Pushes the current (uncommitted) text into the history. |
| 325 * @param {string} currentText |
| 326 */ |
| 327 _pushCurrentText(currentText) { |
| 328 if (this._uncommittedIsTop) |
| 329 this._data.pop(); // Throw away obsolete uncommitted text. |
| 330 this._uncommittedIsTop = true; |
| 331 this._data.push(currentText); |
| 332 } |
| 333 |
| 334 /** |
| 335 * @param {string} currentText |
| 336 * @return {string|undefined} |
| 337 */ |
| 338 previous(currentText) { |
| 339 if (this._historyOffset > this._data.length) |
| 340 return undefined; |
| 341 if (this._historyOffset === 1) |
| 342 this._pushCurrentText(currentText); |
| 343 ++this._historyOffset; |
| 344 return this._currentHistoryItem(); |
| 345 } |
| 346 |
| 347 /** |
| 348 * @return {string|undefined} |
| 349 */ |
| 350 next() { |
| 351 if (this._historyOffset === 1) |
| 352 return undefined; |
| 353 --this._historyOffset; |
| 354 return this._currentHistoryItem(); |
| 355 } |
| 356 |
| 357 /** |
| 358 * @return {string|undefined} |
| 359 */ |
| 360 _currentHistoryItem() { |
| 361 return this._data[this._data.length - this._historyOffset]; |
| 362 } |
| 309 }; | 363 }; |
| 310 | |
| 311 WebInspector.ConsoleHistoryManager.prototype = { | |
| 312 /** | |
| 313 * @return {!Array.<string>} | |
| 314 */ | |
| 315 historyData: function() | |
| 316 { | |
| 317 return this._data; | |
| 318 }, | |
| 319 | |
| 320 /** | |
| 321 * @param {!Array.<string>} data | |
| 322 */ | |
| 323 setHistoryData: function(data) | |
| 324 { | |
| 325 this._data = data.slice(); | |
| 326 this._historyOffset = 1; | |
| 327 }, | |
| 328 | |
| 329 /** | |
| 330 * Pushes a committed text into the history. | |
| 331 * @param {string} text | |
| 332 */ | |
| 333 pushHistoryItem: function(text) | |
| 334 { | |
| 335 if (this._uncommittedIsTop) { | |
| 336 this._data.pop(); | |
| 337 delete this._uncommittedIsTop; | |
| 338 } | |
| 339 | |
| 340 this._historyOffset = 1; | |
| 341 if (text === this._currentHistoryItem()) | |
| 342 return; | |
| 343 this._data.push(text); | |
| 344 }, | |
| 345 | |
| 346 /** | |
| 347 * Pushes the current (uncommitted) text into the history. | |
| 348 * @param {string} currentText | |
| 349 */ | |
| 350 _pushCurrentText: function(currentText) | |
| 351 { | |
| 352 if (this._uncommittedIsTop) | |
| 353 this._data.pop(); // Throw away obsolete uncommitted text. | |
| 354 this._uncommittedIsTop = true; | |
| 355 this._data.push(currentText); | |
| 356 }, | |
| 357 | |
| 358 /** | |
| 359 * @param {string} currentText | |
| 360 * @return {string|undefined} | |
| 361 */ | |
| 362 previous: function(currentText) | |
| 363 { | |
| 364 if (this._historyOffset > this._data.length) | |
| 365 return undefined; | |
| 366 if (this._historyOffset === 1) | |
| 367 this._pushCurrentText(currentText); | |
| 368 ++this._historyOffset; | |
| 369 return this._currentHistoryItem(); | |
| 370 }, | |
| 371 | |
| 372 /** | |
| 373 * @return {string|undefined} | |
| 374 */ | |
| 375 next: function() | |
| 376 { | |
| 377 if (this._historyOffset === 1) | |
| 378 return undefined; | |
| 379 --this._historyOffset; | |
| 380 return this._currentHistoryItem(); | |
| 381 }, | |
| 382 | |
| 383 /** | |
| 384 * @return {string|undefined} | |
| 385 */ | |
| 386 _currentHistoryItem: function() | |
| 387 { | |
| 388 return this._data[this._data.length - this._historyOffset]; | |
| 389 } | |
| 390 }; | |
| OLD | NEW |