summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/ConsolePrompt.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/ConsolePrompt.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/ConsolePrompt.js291
1 files changed, 291 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/ConsolePrompt.js b/Source/WebInspectorUI/UserInterface/ConsolePrompt.js
new file mode 100644
index 000000000..5b62b8a1f
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/ConsolePrompt.js
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ConsolePrompt = function(delegate, mimeType, element)
+{
+ WebInspector.Object.call(this);
+
+ this._element = element || document.createElement("div");
+ this._element.classList.add(WebInspector.ConsolePrompt.StyleClassName);
+ this._element.classList.add(WebInspector.SyntaxHighlightedStyleClassName);
+
+ this._delegate = delegate || null;
+
+ this._codeMirror = CodeMirror(this.element, {
+ lineWrapping: true,
+ mode: mimeType,
+ indentWithTabs: true,
+ indentUnit: 4,
+ matchBrackets: true
+ });
+
+ var keyMap = {
+ "Up": this._handlePreviousKey.bind(this),
+ "Down": this._handleNextKey.bind(this),
+ "Ctrl-P": this._handlePreviousKey.bind(this),
+ "Ctrl-N": this._handleNextKey.bind(this),
+ "Enter": this._handleEnterKey.bind(this),
+ "Cmd-Enter": this._handleCommandEnterKey.bind(this)
+ };
+
+ this._codeMirror.addKeyMap(keyMap);
+
+ this._completionController = new WebInspector.CodeMirrorCompletionController(this._codeMirror, this);
+
+ this._history = [{}];
+ this._historyIndex = 0;
+};
+
+WebInspector.ConsolePrompt.StyleClassName = "console-prompt";
+WebInspector.ConsolePrompt.MaximumHistorySize = 30;
+
+WebInspector.ConsolePrompt.prototype = {
+ constructor: WebInspector.ConsolePrompt,
+
+ // Public
+
+ get element()
+ {
+ return this._element;
+ },
+
+ get delegate()
+ {
+ return this._delegate;
+ },
+
+ set delegate(delegate)
+ {
+ this._delegate = delegate || null;
+ },
+
+ get text()
+ {
+ return this._codeMirror.getValue();
+ },
+
+ set text(text)
+ {
+ this._codeMirror.setValue(text || "");
+ this._codeMirror.clearHistory();
+ this._codeMirror.markClean();
+ },
+
+ get history()
+ {
+ this._history[this._historyIndex] = this._historyEntryForCurrentText();
+ return this._history;
+ },
+
+ set history(history)
+ {
+ this._history = history instanceof Array ? history.slice(0, WebInspector.ConsolePrompt.MaximumHistorySize) : [{}];
+ this._historyIndex = 0;
+ this._restoreHistoryEntry(0);
+ },
+
+ get focused()
+ {
+ return this._codeMirror.getWrapperElement().classList.contains("CodeMirror-focused");
+ },
+
+ focus: function()
+ {
+ this._codeMirror.focus();
+ },
+
+ shown: function()
+ {
+ this._codeMirror.refresh();
+ },
+
+ updateLayout: function()
+ {
+ this._codeMirror.refresh();
+ },
+
+ updateCompletions: function(completions, implicitSuffix)
+ {
+ this._completionController.updateCompletions(completions, implicitSuffix);
+ },
+
+ // Protected
+
+ completionControllerCompletionsNeeded: function(completionController, prefix, defaultCompletions, base, suffix, forced)
+ {
+ if (this.delegate && typeof this.delegate.consolePromptCompletionsNeeded === "function")
+ this.delegate.consolePromptCompletionsNeeded(this, defaultCompletions, base, prefix, suffix, forced);
+ else
+ this._completionController.updateCompletions(defaultCompletions);
+ },
+
+ completionControllerShouldAllowEscapeCompletion: function(completionController)
+ {
+ // Only allow escape to complete if there is text in the prompt. Otherwise allow it to pass through
+ // so escape to toggle the quick console still works.
+ return !!this.text;
+ },
+
+ // Private
+
+ _handlePreviousKey: function(codeMirror)
+ {
+ if (this._codeMirror.somethingSelected())
+ return CodeMirror.Pass;
+
+ // Pass unless we are on the first line.
+ if (this._codeMirror.getCursor().line)
+ return CodeMirror.Pass;
+
+ var historyEntry = this._history[this._historyIndex + 1];
+ if (!historyEntry)
+ return CodeMirror.Pass;
+
+ this._rememberCurrentTextInHistory();
+
+ ++this._historyIndex;
+
+ this._restoreHistoryEntry(this._historyIndex);
+ },
+
+ _handleNextKey: function(codeMirror)
+ {
+ if (this._codeMirror.somethingSelected())
+ return CodeMirror.Pass;
+
+ // Pass unless we are on the last line.
+ if (this._codeMirror.getCursor().line !== this._codeMirror.lastLine())
+ return CodeMirror.Pass;
+
+ var historyEntry = this._history[this._historyIndex - 1];
+ if (!historyEntry)
+ return CodeMirror.Pass;
+
+ this._rememberCurrentTextInHistory();
+
+ --this._historyIndex;
+
+ this._restoreHistoryEntry(this._historyIndex);
+ },
+
+ _handleEnterKey: function(codeMirror, forceCommit)
+ {
+ var currentText = this.text;
+
+ // Always do nothing when there is just whitespace.
+ if (!currentText.trim())
+ return;
+
+ var cursor = this._codeMirror.getCursor();
+ var lastLine = this._codeMirror.lastLine();
+ var lastLineLength = this._codeMirror.getLine(lastLine).length;
+ var cursorIsAtLastPosition = positionsEqual(cursor, {line: lastLine, ch: lastLineLength});
+
+ function positionsEqual(a, b)
+ {
+ console.assert(a);
+ console.assert(b);
+ return a.line === b.line && a.ch === b.ch;
+ }
+
+ function commitTextOrInsertNewLine(commit)
+ {
+ if (!commit) {
+ // Only insert a new line if the previous cursor and the current cursor are in the same position.
+ if (positionsEqual(cursor, this._codeMirror.getCursor()))
+ CodeMirror.commands.newlineAndIndent(this._codeMirror);
+ return;
+ }
+
+ var historyEntry = this._historyEntryForCurrentText();
+
+ // Replace the previous entry if it does not have text or if the text is the same.
+ if (this._history[1] && (!this._history[1].text || this._history[1].text === historyEntry.text)) {
+ this._history[1] = historyEntry;
+ this._history[0] = {};
+ } else {
+ // Replace the first history entry and push a new empty one.
+ this._history[0] = historyEntry;
+ this._history.unshift({});
+
+ // Trim the history length if needed.
+ if (this._history.length > WebInspector.ConsolePrompt.MaximumHistorySize)
+ this._history = this._history.slice(0, WebInspector.ConsolePrompt.MaximumHistorySize);
+ }
+
+ this._historyIndex = 0;
+
+ this._codeMirror.setValue("");
+ this._codeMirror.clearHistory();
+
+ if (this.delegate && typeof this.delegate.consolePromptHistoryDidChange === "function")
+ this.delegate.consolePromptHistoryDidChange(this);
+
+ if (this.delegate && typeof this.delegate.consolePromptTextCommitted === "function")
+ this.delegate.consolePromptTextCommitted(this, currentText);
+ }
+
+ if (!forceCommit && this.delegate && typeof this.delegate.consolePromptShouldCommitText === "function") {
+ this.delegate.consolePromptShouldCommitText(this, currentText, cursorIsAtLastPosition, commitTextOrInsertNewLine.bind(this));
+ return;
+ }
+
+ commitTextOrInsertNewLine.call(this, true);
+ },
+
+ _handleCommandEnterKey: function(codeMirror)
+ {
+ this._handleEnterKey(codeMirror, true);
+ },
+
+ _restoreHistoryEntry: function(index)
+ {
+ var historyEntry = this._history[index];
+
+ this._codeMirror.setValue(historyEntry.text || "");
+
+ if (historyEntry.undoHistory)
+ this._codeMirror.setHistory(historyEntry.undoHistory);
+ else
+ this._codeMirror.clearHistory();
+
+ this._codeMirror.setCursor(historyEntry.cursor || {line: 0});
+ },
+
+ _historyEntryForCurrentText: function()
+ {
+ return {text: this.text, undoHistory: this._codeMirror.getHistory(), cursor: this._codeMirror.getCursor()};
+ },
+
+ _rememberCurrentTextInHistory: function()
+ {
+ this._history[this._historyIndex] = this._historyEntryForCurrentText();
+
+ if (this.delegate && typeof this.delegate.consolePromptHistoryDidChange === "function")
+ this.delegate.consolePromptHistoryDidChange(this);
+ }
+};
+
+WebInspector.ConsolePrompt.prototype.__proto__ = WebInspector.Object.prototype;