From 8aa477706e31d74f2ffb32748ddb93674f5c618a Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 10 Jul 2013 07:43:43 +0000 Subject: [PATCH] chore(console) add jqconsole files --- lib/client/console/Cakefile | 16 + lib/client/console/ChangeLog | 68 ++ lib/client/console/README.md | 723 ++++++++++++ lib/client/console/jqconsole.coffee | 1310 ++++++++++++++++++++++ lib/client/console/jqconsole.jquery.json | 22 + 5 files changed, 2139 insertions(+) create mode 100644 lib/client/console/Cakefile create mode 100644 lib/client/console/ChangeLog create mode 100644 lib/client/console/README.md create mode 100644 lib/client/console/jqconsole.coffee create mode 100644 lib/client/console/jqconsole.jquery.json diff --git a/lib/client/console/Cakefile b/lib/client/console/Cakefile new file mode 100644 index 00000000..af53e80d --- /dev/null +++ b/lib/client/console/Cakefile @@ -0,0 +1,16 @@ +{spawn, exec} = require 'child_process' + +task 'watch', 'Build and watch the CoffeeScript source files', -> + coffee = spawn 'coffee', ['-cw', '-o', 'lib', 'src'] + test = spawn 'coffee', ['-cw', 'test'] + log = (d)-> console.log d.toString() + coffee.stdout.on 'data', log + test.stdout.on 'data', log + +task 'build', 'Build minified file with uglify', -> + console.log 'building...' + exec 'uglifyjs -o jqconsole.min.js lib/jqconsole.js', (err, res)-> + if err + console.error 'failed with', err + else + console.log 'build complete' diff --git a/lib/client/console/ChangeLog b/lib/client/console/ChangeLog new file mode 100644 index 00000000..85ae8052 --- /dev/null +++ b/lib/client/console/ChangeLog @@ -0,0 +1,68 @@ +2011.08.28, Version 2.4.2 + +* Fix for issue #13 . +* Add optional parameter "escape" to the Write method, see README for more +info. + +20011.10.9, Version 2.5 + +* Added mobile support. +* Follow the cursor's position when the window is scrolled away. +* Add async_multiline option in prompt, see README for more info. +* Add Dump method that would dump the console's text content. +* Add GetState method that gets the current state of the console. +* Publicize MoveToStart and MoveToEnd methods. + +2011.11.1, Version 2.5.1 + +* Added Disable/Enable functionality and methods. +* Added IsDisabled method. + +2011.11.3, Version 2.5.2 + +* Added multibyte character input support, issue #19. + +2011.11.4, Version 2.6 + +* Fix safari paste. Issue #15. +* Created constants and minifier friendliness. Issue #14. + +2011.11.19, Version 2.6.1 + +* Fix issues #20, #21 +* Implement feature #22 +* Add built-in css for ease of use. + +2011.12.6, Version 2.6.2 +* Fix issue #23. + +2011.12.16 Version 2.6.3 +* Fix issue #24. + +2011.12.28 Version 2.7 +* Implement ANSI graphics, Issue #12 +* Fix issue #25 + +2012.3.7 Version 2.7.1 +* Fix issue #26 +* Complete issue #12 by adding stacking graphics support. + +2012.10.28 Version 2.7.2 +* Add set / get History methods. +* Add Append method. + +2012.11.10 Version 2.7.3 +* Allow empty string in prompt. + +2012.12.13 Version 2.7.4 +* Fix issue #36 +* Fix issue #35 + +2013.1.21 Version 2.7.5 +* Add SetPromptLabel method. + +2013.1.22 Version 2.7.6 +* Continue label argument in SetPromptLabel method. + +2013.1.26 Version 2.7.7 +* Support for middle click paste on linux. #47. diff --git a/lib/client/console/README.md b/lib/client/console/README.md new file mode 100644 index 00000000..7eada46b --- /dev/null +++ b/lib/client/console/README.md @@ -0,0 +1,723 @@ +#jq-console + +A jQuery terminal plugin written in CoffeeScript. + +This project was spawned because of our need for a simple web terminal plugin +for the repl.it project. It tries to simulate a low level terminal by providing (almost) +raw input/output streams as well as input and output states. + +Version 2.0 adds baked-in support for rich multi-line prompting and operation +queueing. + + +##Tested Browsers + +The plugin has been tested on the following browsers: + +* IE 9+ +* Chrome 10+ +* Firefox 4+ +* Opera 11+ +* iOS 4+ + + +##Getting Started + +###Echo example + +```css + /* The console container element */ + #console { + position: absolute; + width: 400px; + height: 500px; + background-color:black; + } + /* The inner console element. */ + .jqconsole { + padding: 10px; + } + /* The cursor. */ + .jqconsole-cursor { + background-color: gray; + } + /* The cursor color when the console looses focus. */ + .jqconsole-blurred .jqconsole-cursor { + background-color: #666; + } + /* The current prompt text color */ + .jqconsole-prompt { + color: #0d0; + } + /* The command history */ + .jqconsole-old-prompt { + color: #0b0; + font-weight: normal; + } + /* The text color when in input mode. */ + .jqconsole-input { + color: #dd0; + } + /* Previously entered input. */ + .jqconsole-old-input { + color: #bb0; + font-weight: normal; + } + /* The text color of the output. */ + .jqconsole-output { + color: white; + } +``` + +```html +
+ + + +``` + + +###Instantiating + +```javascript + $(div).jqconsole(welcomeString, promptLabel, continueLabel); +``` + +* `div` is the div element or selector. Note that this element must be + explicity sized and positioned `absolute` or `relative`. +* `welcomeString` is the string to be shown when the terminal is first rendered. +* `promptLabel` is the label to be shown before the input when using Prompt(). +* `continueLabel` is the label to be shown before the continued lines of the + input when using Prompt(). + +##Configuration + +There isn't much initial configuration needed, because the user must supply +options and callbacks with each state change. There are a few config methods +provided to create custom shortcuts and change indentation width: + +###jqconsole.RegisterShortcut +Registers a callback for a keyboard shortcut. +Takes two arguments: + + * __(int|string)__ *keyCode*: The code of the key pressing which (when Ctrl is + held) will trigger this shortcut. If a string is provided, the ASCII code + of the first character is taken. + + * __function__ *callback*: A function called when the shortcut is pressed; + "this" will point to the JQConsole object. + + + Example: + + // Ctrl+R: resets the console. + jqconsole.RegisterShortcut('R', function() { + this.Reset(); + }); + +###jqconsole.SetIndentWidth +Sets the number of spaces inserted when indenting and removed when unindenting. +Takes one argument: + + * __int__ *width*: The code of the key pressing which (when Ctrl is held) will + trigger this shortcut. + + + Example: + + // Sets the indent width to 4 spaces. + jqconsole.SetIndentWidth(4); + +###jqconsole.RegisterMatching +Registers an opening and closing characters to match and wraps each of the +opening and closing characters with a span with the specified class. +Takes one parameters: + + * __char__ *open*: The opening character of a "block". + * __char__ *close*: The closing character of a "block". + * __string__ *class*: The css class that is applied to the matched characters. + + + Example: + + jqconsole.RegisterMatching('{', '}', 'brackets'); + +##Usage + +Unlike most terminal plugins, jq-console gives you complete low-level control +over the execution; you have to call the appropriate methods to start input +or output: + +###jqconsole.Input: +Asks user for input. If another input or prompt operation is currently underway, +the new input operation is enqueued and will be called when the current +operation and all previously enqueued operations finish. Takes one argument: + + * __function__ *input_callback*: A function called with the user's input when + the user presses Enter and the input operation is complete. + + + Example: + + // Echo the input. + jqconsole.Input(function(input) { + jqconsole.Write(input); + }); + + +###jqconsole.Prompt +Asks user for input. If another input or prompt operation is currently underway +the new prompt operation is enqueued and will be called when the current +peration and all previously enqueued operations finish. Takes three arguments: + + * __bool__ *history_enabled*: Whether this input should use history. If true, + the user can select the input from history, and their input will also be + added as a new history item. + + * __function__ *result_callback*: A function called with the user's input when + the user presses Enter and the prompt operation is complete. + + * __function__ *multiline_callback*: If specified, this function is called when + the user presses Enter to check whether the input should continue to the + next line. The function must return one of the following values: + + * `false`: the input operation is completed. + + * `0`: the input continues to the next line with the current indent. + + * `N` (int): the input continues to the next line, and the current + indent is adjusted by `N`, e.g. `-2` to unindent two levels. + + + * __bool__ *async_multiline*: Whether the multiline callback function should + be treated as an asynchronous operation and be passed a continuation + function that should be called with one of the return values mentioned + above: `false`/`0`/`N`. + + + Example: + + jqconsole.Prompt(true, function(input) { + // Alert the user with the command. + alert(input); + }, function (input) { + // Continue if the last character is a backslash. + return /\\$/.test(input); + }); + +###jqconsole.AbortPrompt +Aborts the current prompt operation and returns to output mode or the next +queued input/prompt operation. Takes no arguments. + + Example: + + jqconsole.Prompt(true, function(input) { + alert(input); + }); + // Give the user 2 seconds to enter the command. + setTimeout(function() { + jqconsole.AbortPrompt(); + }, 2000); + +###jqconsole.Write +Writes the given text to the console in a ``, with an +optional class. If a prompt is currently being shown, the text is inserted +before it. Takes two arguments: + + * __string__ *text*: The text to write. + + * __string__ *cls*: The class to give the span containing the text. Optional. + + * __bool__ *escape*: Whether the text to write should be html escaped. + Optional, defaults to true. + + + Examples: + + jqconsole.Write(output, 'my-output-class') + jqconsole.Write(err.message, 'my-error-class') + +###jqconsole.Append +Append the given node to the DOM. If a prompt is currently being shown, the +text is inserted before it. Takes a single argument: + + * __(string|Element)__ *node*: The DOM Element or html string to append to + the console just before the prompt. + + Example: + + // Add a div with the text 'hello' on a red background using jquery + jqconsole.Append($('
hello
').css('background-color', 'red')); + + // We can also use document.createElement + node = document.createElement("div"); + content = document.createTextNode("hello"); + node.appendChild(content); + jqconsole.Append(node); + + +###jqconsole.SetPromptText +Sets the text currently in the input prompt. Takes one parameter: + + * __string__ *text*: The text to put in the prompt. + + Examples: + + jqconsole.SetPromptText('ls') + jqconsole.SetPromptText('print [i ** 2 for i in range(10)]') + + +###jqconsole.SetPromptLabel +Replaces the main prompt label. Takes two parameters: + + * __string__ *main_label*: String to replace the main prompt label. + * __string__ *continuation_label*: String to replace the continuation prompt label. Optional. + + Examples: + + jqconsole.SetPromptLabel('$') + jqconsole.SetPromptLabel(' $','..') + + +###jqconsole.ClearPromptText +Clears all the text currently in the input prompt. Takes one parameter: + + * __bool__ *clear_label*: If specified and true, also clears the main prompt + label (e.g. ">>>"). + + + Example: + + jqconsole.ClearPromptText() + + +###jqconsole.GetPromptText +Returns the contents of the prompt. Takes one parameter: + + * __bool__ *full*: If specified and true, also includes the prompt labels + (e.g. ">>>"). + + + Examples: + + var currentCommand = jqconsole.GetPromptText() + var logEntry = jqconsole.GetPromptText(true) + + +###jqconsole.Reset +Resets the console to its initial state, cancelling all current and pending +operations. Takes no parameters. + + Example: + + jqconsole.Reset() + + +###jqconsole.GetColumn +Returns the 0-based number of the column on which the cursor currently is. +Takes no parameters. + + Example: + + // Show the current line and column in a status area. + $('#status').text(jqconsole.GetLine() + ', ' + jqconsole.GetColumn()) + + +###jqconsole.GetLine +Returns the 0-based number of the line on which the cursor currently is. +Takes no parameters. + + Example: + + // Show the current line and column in a status area. + $('#status').text(jqconsole.GetLine() + ', ' + jqconsole.GetColumn()) + +###jqconsole.Focus +Forces the focus onto the console so events can be captured. +Takes no parameters. + + Example: + + // Redirect focus to the console whenever the user clicks anywhere. + $(window).click(function() { + jqconsole.Focus(); + }) + + +###jqconsole.GetIndentWidth +Returns the number of spaces inserted when indenting. Takes no parameters. + + Example: + + jqconsole.SetIndentWidth(4); + console.assert(jqconsole.GetIndentWidth() == 4); + + +###jqconsole.UnRegisterMatching +Deletes a certain matching settings set by `jqconsole.RegisterMatching`. +Takes two paramaters: + + * __char__ *open*: The opening character of a "block". + * __char__ *close*: The closing character of a "block". + + + Example: + + jqconsole.UnRegisterMatching('{', '}'); + + +###jqconsole.Dump +Returns the text content of the console. + +###jqconsole.GetState +Returns the current state of the console. Could be one of the following: + + * Input: `"input"` + * Output: `"output"` + * Prompt: `"prompt"` + + + Example: + + jqconsole.GetState(); //output + + +###jqconsole.MoveToStart +Moves the cursor to the start of the current line. +Takes one parameter: + + * __bool__ *all_lines*: If true moves the cursor to the beginning of the first + line in the current prompt. Defaults to false. + + + Example: + + // Move to line start Ctrl+A. + jqconsole.RegisterShortcut('A', function() { + jqconsole.MoveToStart(); + handler(); + }); + + +###jqconsole.MoveToEnd +Moves the cursor to the end of the current line. +Takes one parameter: + + * __bool__ *all_lines*: If true moves the cursor to the end of the first + line in the current prompt. Defaults to false. + + Example: + + // Move to line end Ctrl+E. + jqconsole.RegisterShortcut('E', function() { + jqconsole.MoveToEnd(); + handler(); + }); + +###jqconsole.Disable +Disables input and focus on the console. + + +###jqconsole.Enable +Enables input and focus on the console. + + +###jqconsole.IsDisabled +Returns true if the console is disabled. + + +###jqconsole.GetHistory +Returns the contents of the history buffer. + + +###jqconsole.SetHistory +Set the history buffer to the given array. + +Takes one parameter: + + * __array__ *history*: The history buffer to use. + + Example: + + jqconsole.SetHistory(['a = 3', 'a + 3']); + + +###jqconsole.ResetHistory +Resets the console history. + + +###jqconsole.ResetMatchings +Resets the character matching configuration. + + +###jqconsole.ResetShortcuts +Resets the shortcut configuration. + + +##Default Key Config + +The console responds to the followind keys and key combinations by default: + +* `Delete`: Delete the following character. +* `Ctrl+Delete`: Delete the following word. +* `Backspace`: Delete the preceding character. +* `Ctrl+Backspace`: Delete the preceding word. +* `Ctrl+Left`: Move one word to the left. +* `Ctrl+Right`: Move one word to the right. +* `Home`: Move to the beginning of the current line. +* `Ctrl+Home`: Move to the beginnig of the first line. +* `End`: Move to the end of the current line. +* `Ctrl+End`: Move to the end of the last line. +* `Shift+Up`, `Ctrl+Up`: Move cursor to the line above the current one. +* `Shift+Down`, `Ctrl+Down`: Move cursor to the line below the current one. +* `Tab`: Indent. +* `Shift+Tab`: Unindent. +* `Up`: Previous history item. +* `Down`: Next history item. +* `Enter`: Finish input/prompt operation. See Input() and Prompt() for details. +* `Shift+Enter`: New line. +* `Page Up`: Scroll console one page up. +* `Page Down`: Scroll console one page down. + +##ANSI escape code SGR support + +jq-console implements a large subset of the ANSI escape code graphics. +Using the `.Write` method you could add style to the console using +the following syntax: + +`ASCII 27 (decimal) or 0x1b (hex)` `[` `SGR code` `m` + +Example: + + jqconsole.Write('\033[31mRed Text'); + +Note that the third parameter `escape` must be true which defaults to it. + +You'll need to include the `ansi.css` file for default effects or create your +own using the css classes from the table below. + +###SGR +[Reference](http://en.wikipedia.org/wiki/ANSI_escape_code#graphics). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeEffectClass
0Reset / Normal
1Bold`jqconsole-ansi-bold`
2Faint`jqconsole-ansi-lighter`
3Italic`jqconsole-ansi-italic`
4Line below text`jqconsole-ansi-underline`
5Blink: 1s delay`jqconsole-ansi-blink`
6Blink: 0.5s delay`jqconsole-ansi-blink-rapid`
8Hide text`jqconsole-ansi-hidden`
9Line through text`jqconsole-ansi-line-through`
10Remove all fonts
11-19Add custom font`jqconsole-ansi-fonts-{N}` where N is code - 10
20Add Fraktur font (not implemented in ansi.css)`jqconsole-ansi-fraktur`
21Remove Bold and Faint effects
22Same as 21
23Remove italic and fraktur effects
24Remove underline effect
25Remove blinking effect(s).
28Reveal text
29Remove line-through effect
30-37Set foreground color to color from the color table belowjqconsole-ansi-color-{COLOR} where {COLOR} is the color name
39Restore default foreground color
40-47Set background color to color from the color table below`jqconsole-ansi-background-color-{COLOR}` where {COLOR} is the color name
49Restore default background color
51Adds a frame around the text`jqconsole-ansi-framed`
53Line above textjqconsole-ansi-overline
54Remove frame effect
55Remove over-line effect
+ +###Colors +[Reference](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Code offsetColor
0Black
1Red
2Green
3Yellow
4Blue
5Magenta
6Cyan
7White
+ +##CSS Classes + +Several CSS classes are provided to help stylize the console: + +* `jqconsole`: The main console container. +* `jqconsole, jqconsole-blurred`: The main console container, when not in focus. +* `jqconsole-cursor`: The cursor. +* `jqconsole-header`: The welcome message at the top of the console. +* `jqconsole-input`: The prompt area during input. May have multiple lines. +* `jqconsole-old-input`: Previously-entered inputs. +* `jqconsole-prompt`: The prompt area during prompting. May have multiple lines. +* `jqconsole-old-prompt`: Previously-entered prompts. +* `jqconsole-composition`: The div encapsulating the composition of multi-byte + characters. + + +Of course, custom classes may be specified when using `jqconsole.Write()` for +further customization. + + +##Contributors + +[Max Shawabkeh](http://max99x.com/) +[Amjad Masad](http://twitter.com/amjad_masad) diff --git a/lib/client/console/jqconsole.coffee b/lib/client/console/jqconsole.coffee new file mode 100644 index 00000000..0230629c --- /dev/null +++ b/lib/client/console/jqconsole.coffee @@ -0,0 +1,1310 @@ +### +Copyrights 2011, the repl.it project. +Licensed under the MIT license +### + +# Shorthand for jQuery. +$ = jQuery + +# The states in which the console can be. +STATE_INPUT = 0 +STATE_OUTPUT = 1 +STATE_PROMPT = 2 + +# Key code values. +KEY_ENTER = 13 +KEY_TAB = 9 +KEY_DELETE = 46 +KEY_BACKSPACE = 8 +KEY_LEFT = 37 +KEY_RIGHT = 39 +KEY_UP = 38 +KEY_DOWN = 40 +KEY_HOME = 36 +KEY_END = 35 +KEY_PAGE_UP = 33 +KEY_PAGE_DOWN = 34 + +# CSS classes +CLASS_PREFIX = 'jqconsole-' +CLASS_CURSOR = "#{CLASS_PREFIX}cursor" +CLASS_HEADER = "#{CLASS_PREFIX}header" +CLASS_PROMPT = "#{CLASS_PREFIX}prompt" +CLASS_OLD_PROMPT = "#{CLASS_PREFIX}old-prompt" +CLASS_INPUT = "#{CLASS_PREFIX}input" +CLASS_BLURRED = "#{CLASS_PREFIX}blurred" + +# Frequently used string literals +E_KEYPRESS = 'keypress' +EMPTY_SPAN = '' +EMPTY_DIV = '
' +EMPTY_SELECTOR = ':empty' +NEWLINE = '\n' + +# Default prompt text for main and continuation prompts. +DEFAULT_PROMPT_LABEL = '>>> ' +DEFAULT_PROMPT_CONINUE_LABEL = '... ' + +# The default number of spaces inserted when indenting. +DEFAULT_INDENT_WIDTH = 2 + +CLASS_ANSI = "#{CLASS_PREFIX}ansi-" +ESCAPE_CHAR = '\x1B' +ESCAPE_SYNTAX = /\[(\d*)(?:;(\d*))*m/ + +class Ansi + COLORS: ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'] + + constructor: -> + @klasses = []; + + _append: (klass) => + klass = "#{CLASS_ANSI}#{klass}" + if @klasses.indexOf(klass) is -1 + @klasses.push klass + + _remove: (klasses...) => + for klass in klasses + if klass in ['fonts', 'color', 'background-color'] + @klasses = (cls for cls in @klasses when cls.indexOf(klass) isnt CLASS_ANSI.length) + else + klass = "#{CLASS_ANSI}#{klass}" + @klasses = (cls for cls in @klasses when cls isnt klass) + + _color: (i) => @COLORS[i] + + _style: (code) => + code = 0 if code == '' + code = parseInt code + + return if isNaN code + + switch code + when 0 then @klasses = [] + when 1 then @_append 'bold' + when 2 then @_append 'lighter' + when 3 then @_append 'italic' + when 4 then @_append 'underline' + when 5 then @_append 'blink' + when 6 then @_append 'blink-rapid' + when 8 then @_append 'hidden' + when 9 then @_append 'line-through' + when 10 then @_remove 'fonts' + when 11,12,13,14,15,16,17,18,19 + @_remove 'fonts' + @_append "fonts-#{code - 10}" + when 20 then @_append 'fraktur' + when 21 then @_remove 'bold', 'lighter' + when 22 then @_remove 'bold', 'lighter' + when 23 then @_remove 'italic', 'fraktur' + when 24 then @_remove 'underline' + when 25 then @_remove 'blink', 'blink-rapid' + when 28 then @_remove 'hidden' + when 29 then @_remove 'line-through' + when 30,31,32,33,34,35,36,37 + @_remove 'color' + @_append 'color-' + @_color code - 30 + when 39 then @_remove 'color' + when 40,41,42,43,44,45,46,47 + @_remove 'background-color' + @_append 'background-color-' + @_color code - 40 + when 49 then @_remove 'background-color' + when 51 then @_append 'framed' + when 53 then @_append 'overline' + when 54 then @_remove 'framed' + when 55 then @_remove 'overline' + + getClasses: => @klasses.join ' ' + + _openSpan: (text) => "#{text}" + _closeSpan: (text) => "#{text}" + + stylize: (text) => + text = @_openSpan text + + i = 0 + while (i = text.indexOf(ESCAPE_CHAR ,i)) and i isnt -1 + if d = text[i...].match ESCAPE_SYNTAX + @_style code for code in d[1...] + text = @_closeSpan(text[0...i]) + @_openSpan text[i + 1 + d[0].length...] + else i++ + + return @_closeSpan text + +# Helper functions +spanHtml = (klass, content) -> "#{content or ''}" + +class JQConsole + # Creates a console. + # @arg container: The DOM element into which the console is inserted. + # @arg header: Text to print at the top of the console on reset. Optional. + # Defaults to an empty string. + # @arg prompt_label: The label to show before the command prompt. Optional. + # Defaults to DEFAULT_PROMPT_LABEL. + # @arg prompt_continue: The label to show before continuation lines of the + # command prompt. Optional. Defaults to DEFAULT_PROMPT_CONINUE_LABEL. + constructor: (@container, header, prompt_label, prompt_continue_label) -> + # Mobile devices supported sniff. + @isMobile = !!navigator.userAgent.match /iPhone|iPad|iPod|Android/i + @isIos = !!navigator.userAgent.match /iPhone|iPad|iPod/i + @isAndroid = !!navigator.userAgent.match /Android/i + + @$window = $(window) + + # The header written when the console is reset. + @header = header or '' + + # The prompt label used by Prompt(). + @prompt_label_main = if typeof prompt_label == 'string' + prompt_label + else + DEFAULT_PROMPT_LABEL + @prompt_label_continue = (prompt_continue_label or + DEFAULT_PROMPT_CONINUE_LABEL) + + # How many spaces are inserted when a tab character is pressed. + @indent_width = DEFAULT_INDENT_WIDTH + + # By default, the console is in the output state. + @state = STATE_OUTPUT + + # A queue of input/prompt operations waiting to be called. The items are + # bound functions ready to be called. + @input_queue = [] + + # The function to call when input is accepted. Valid only in + # input/prompt mode. + @input_callback = null + # The function to call to determine whether the input should continue to the + # next line. + @multiline_callback = null + + # A table of all "recorded" inputs given so far. + @history = [] + # The index of the currently selected history item. If this is past the end + # of @history, then the user has not selected a history item. + @history_index = 0 + # The command which the user was typing before browsing history. Keeping + # track of this allows us to restore the user's command if they browse the + # history then decide to go back to what they were typing. + @history_new = '' + # Whether the current input operation is using history. + @history_active = false + + # A table of custom shortcuts, mapping character codes to callbacks. + @shortcuts = {} + + # The main console area. Everything else happens inside this. + @$console = $('
').appendTo @container
+    @$console.css 
+      position: 'absolute'
+      top: 0
+      bottom: 0
+      right: 0
+      left: 0
+      margin: 0
+      overflow: 'auto'
+
+    # Whether the console currently has focus.
+    @$console_focused = true
+    
+    # On screen somehow invisible textbox for input.
+    # Copied from codemirror2, this works for both mobile and desktop browsers.
+    @$input_container = $(EMPTY_DIV).appendTo @container
+    @$input_container.css
+      position: 'relative'
+      width: 1
+      height: 0
+      overflow: 'hidden'
+    @$input_source = $('