diff --git a/client.js b/client.js
index bf0644cf..cbc1608f 100644
--- a/client.js
+++ b/client.js
@@ -1121,6 +1121,15 @@ CloudClient.init = (function(){
});
CloudClient.baseInit = (function(){
+ if(applicationCache){
+ var lFunc = applicationCache.onupdateready;
+ applicationCache.onupdateready = function(){
+ console.log('app cacheed');
+ location.reload();
+ if(typeof lFunc === 'function')
+ lFunc();
+ };
+ }
/* меняем title
* если js включен - имена папок отображать необязательно...
* а может и обязательно при переходе, можно будет это сделать
diff --git a/lib/client/keyBinding.js b/lib/client/keyBinding.js
index 18301cfa..d8d4be5c 100644
--- a/lib/client/keyBinding.js
+++ b/lib/client/keyBinding.js
@@ -60,7 +60,7 @@ var CloudCommander;
};
- var key_event = function(event){
+ var key_event = function(event){
/* получаем выдленный файл*/
var lCurrentFile = Util.getCurrentFile(),
lName, i;
@@ -382,7 +382,7 @@ var CloudCommander;
/* добавляем обработчик клавишь */
if(document.addEventListener)
- document.addEventListener('keydown', key_event,false);
+ document.addEventListener('keydown', key_event, false);
else document.onkeydown = key_event;
/* клавиши назначены*/
diff --git a/lib/client/terminal.js b/lib/client/terminal.js
index 043dfc86..7839bdf7 100644
--- a/lib/client/terminal.js
+++ b/lib/client/terminal.js
@@ -1,11 +1,12 @@
-var CloudCommander;
+var CloudCommander, $;
/* object contains terminal jqconsole */
(function(){
+ "use strict";
+
var cloudcmd = CloudCommander,
Util = CloudCommander.Util,
KeyBinding = CloudCommander.KeyBinding,
- JQConsole,
TerminalId,
Hidden = false;
@@ -15,28 +16,35 @@ var CloudCommander;
jqconsole.load = (function(){
- Util.cssLoad({
- src : 'lib/client/terminal/jqconsole/ansi.css'
- });
-
- Util.cssSet({
- id :'terminal-css',
- inner :'#terminal{' +
- 'position : relative' +
- '},' +
- '#terminal::selection{' +
- 'background: #fe57a1;' +
- 'color: #fff;' +
- 'text-shadow: none;' +
- '}'
- });
-
- Util.jsload('lib/client/terminal/jqconsole/jqconsole-2.7.min.js', function(){
- jqconsole.init();
- jqconsole.show();
- });
+ Util.cssLoad({
+ src : 'lib/client/terminal/jquery-terminal/jquery.terminal.css'
});
+ Util.cssSet({
+ id :'terminal-css',
+ inner :'#terminal{' +
+ 'position : relative' +
+ '},' +
+ '#terminal::selection{' +
+ 'background: #fe57a1;' +
+ 'color: #fff;' +
+ 'text-shadow: none;' +
+ '}'
+ });
+
+ var lLoadTerm_func = function(){
+ Util.jsload('lib/client/terminal/jquery-terminal/jquery.terminal.js',
+ function(){
+ jqconsole.init();
+ jqconsole.show();
+ });
+ };
+
+ Util.jsload('lib/client/terminal/jquery-terminal/jquery.mousewheel.js',
+ lLoadTerm_func);
+ });
+
+
jqconsole.init = (function(){
if(!TerminalId){
var lFM = Util.getById('fm');
@@ -57,29 +65,24 @@ var CloudCommander;
Util.hidePanel();
KeyBinding.unSet();
- $(function () {
- if(!JQConsole){
- JQConsole = $('#terminal').jqconsole('Hi\n', '>>>');
- var startPrompt = function () {
- // Start the prompt with history enabled.
- JQConsole.Prompt(true, function (input) {
- // Output input with the class jqconsole-output.
- JQConsole.Write(input + '\n', 'jqconsole-output');
-
- console.log(input);
- // Restart the prompt.
- startPrompt();
- });
- };
- startPrompt();
- }
+ $(function($, undefined) {
+ $('#terminal').terminal(function(command, term) {
+ term.echo('');
+ });
});
};
+ function jqueryLoad (pCallBack)
+ {
+ /* загружаем jquery: */
+ Util.jsload('lib/client/terminal/jquery-terminal/jquery-1.7.1.min.js',
+ function(){
+ if(typeof pCallBack === 'function')
+ pCallBack();
+ });
+}
- cloudcmd.Terminal.Keys = (function(){
- "use strict";
-
+ cloudcmd.Terminal.Keys = (function(){
/* loading js and css*/
Util.jqueryLoad( jqconsole.load );
diff --git a/lib/client/terminal/jqconsole/README-v1.md b/lib/client/terminal/jqconsole/README-v1.md
deleted file mode 100644
index e9380537..00000000
--- a/lib/client/terminal/jqconsole/README-v1.md
+++ /dev/null
@@ -1,107 +0,0 @@
-#jq-console
-
-A simple jQuery terminal plugin written in CoffeeScript.
-
-This project was spawned because of our need for a simple web terminal plugin
-for the jsREPL project. It
-tries to simulate a low level terminal by providing (almost) raw input/output
-streams as well as input and output states.
-
-##Tested Browsers
-
-The plugin has been tested on the following browsers:
-
-* IE 8
-* Chrome 10
-* Firefox 3.6
-* Safari 4
-* Opera 10
-
-##Getting Started
-
-###Instantiating
-
- var jqconsole = $(div).jqconsole(welcomeString);
-
-* `div` is the div element or selector.
-* `welcomeString` is the string to be shown when the terminal is first rendered.
-
-###Configuration
-
-There isn't much initial configuration needed, because the user must supply
-options and callbacks with each state change. The only config method is used to
-create custom shortcuts:
-
-* `jqconsole.RegisterShortcut`: Registers a callback for a keyboard shortcut.
- It takes two arguments:
-
- * `int keyCode`: The code of the key pressing which (when Ctrl is held) will
- trigger this shortcut.
-
- * `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(82, function() {
- this.Reset();
- });
-
-##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. It 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 input 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. If this function returns a falsy value, the input operation
- is completed. Otherwise, input continues and the cursor moves to the next
- line.
-
- Example:
-
- jqconsole.Input(true, function(input) {
- alert(input);
- }, function (input) {
- return /\\$/.test('asdasd \\');
- });
-
-* `jqconsole.Write`: Writes the given text to the console in a ``, with an
- optional class. This is used for output and writing prompt labels. It takes
- two arguments:
-
- * `string text`: The text to write.
-
- * `string cls`: The class to give the span containing the text. Optional.
-
- Examples:
-
- jqconsole.Write('>>>', 'prompt')
- jqconsole.Write(output, 'output')
- jqconsole.Write(err.message, 'error')
-
-* `jqconsole.SetPromptText` Sets the text currently in the input prompt. Takes
- only 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)]')
-
-##Contributors
-
-[Max Shawabkeh](http://max99x.com/)
-[Amjad Masad](http://twitter.com/amjad_masad)
diff --git a/lib/client/terminal/jqconsole/README.md b/lib/client/terminal/jqconsole/README.md
deleted file mode 100644
index cf486c85..00000000
--- a/lib/client/terminal/jqconsole/README.md
+++ /dev/null
@@ -1,678 +0,0 @@
-#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.
-
-NOTE: This info is for jq-console v2.0. For jq-console v1.0 see README-v1.md.
-
-
-##Tested Browsers
-
-The plugin has been tested on the following browsers:
-
-* IE 9-10
-* Chrome 10-14
-* Firefox 3.6-6
-* Opera 11
-
-
-##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.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.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.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).
-
-
- | Code |
- Effect |
- Class |
-
-
- | 0 |
- Reset / Normal |
- |
-
-
- | 1 |
- Bold |
- `jqconsole-ansi-bold` |
-
-
- | 2 |
- Faint |
- `jqconsole-ansi-lighter` |
-
-
- | 3 |
- Italic |
- `jqconsole-ansi-italic` |
-
-
- | 4 |
- Line below text |
- `jqconsole-ansi-underline` |
-
-
- | 5 |
- Blink: 1s delay |
- `jqconsole-ansi-blink` |
-
-
- | 6 |
- Blink: 0.5s delay |
- `jqconsole-ansi-blink-rapid` |
-
-
- | 8 |
- Hide text |
- `jqconsole-ansi-hidden` |
-
-
- | 9 |
- Line through text |
- `jqconsole-ansi-line-through` |
-
-
- | 10 |
- Remove all fonts |
- |
-
-
- | 11-19 |
- Add custom font |
- `jqconsole-ansi-fonts-{N}` where N is code - 10 |
-
-
- | 20 |
- Add Fraktur font (not implemented in ansi.css) |
- `jqconsole-ansi-fraktur` |
-
-
- | 21 |
- Remove Bold and Faint effects |
- |
-
-
- | 22 |
- Same as 21 |
- |
-
-
- | 23 |
- Remove italic and fraktur effects |
- |
-
-
- | 24 |
- Remove underline effect |
- |
-
-
- | 25 |
- Remove blinking effect(s). |
- |
-
-
- | 28 |
- Reveal text |
- |
-
-
- | 29 |
- Remove line-through effect |
- |
-
-
- | 30-37 |
- Set foreground color to color from the color table below |
- jqconsole-ansi-color-{COLOR} where {COLOR} is the color name |
-
-
- | 39 |
- Restore default foreground color |
- |
-
-
- | 40-47 |
- Set background color to color from the color table below |
- `jqconsole-ansi-background-color-{COLOR}` where {COLOR} is the color name |
-
-
- | 49 |
- Restore default background color |
- |
-
-
- | 51 |
- Adds a frame around the text |
- `jqconsole-ansi-framed` |
-
-
- | 53 |
- Line above text |
- jqconsole-ansi-overline |
-
-
- | 54 |
- Remove frame effect |
- |
-
-
- | 55 |
- Remove over-line effect |
- |
-
-
-
-###Colors
-[Reference](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors).
-
-
- | Code offset |
- Color |
-
-
- | 0 |
- Black |
-
-
- | 1 |
- Red |
-
-
- | 2 |
- Green |
-
-
- | 3 |
- Yellow |
-
-
- | 4 |
- Blue |
-
-
- | 5 |
- Magenta |
-
-
- | 6 |
- Cyan |
-
-
- | 7 |
- White |
-
-
-
-##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/terminal/jqconsole/ansi.css b/lib/client/terminal/jqconsole/ansi.css
deleted file mode 100644
index 296cfc60..00000000
--- a/lib/client/terminal/jqconsole/ansi.css
+++ /dev/null
@@ -1,172 +0,0 @@
-.jqconsole-ansi-bold {
- font-weight: bold!important;
-}
-
-.jqconsole-ansi-lighter {
- font-weight: lighter!important;
-}
-
-.jqconsole-ansi-italic {
- font-style: italic!important;
-}
-
-.jqconsole-ansi-underline {
- text-decoration: underline!important;
-}
-
-@-webkit-keyframes blinker {
- from { opacity: 1.0; }
- to { opacity: 0.0; }
-}
-
-@-moz-keyframes blinker {
- from { opacity: 1.0; }
- to { opacity: 0.0; }
-}
-
-@-ms-keyframes blinker {
- from { opacity: 1.0; }
- to { opacity: 0.0; }
-}
-
-@-o-keyframes blinker {
- from { opacity: 1.0; }
- to { opacity: 0.0; }
-}
-
-.jqconsole-ansi-blink {
- -webkit-animation-name: blinker;
- -moz-animation-name: blinker;
- -ms-animation-name: blinker;
- -o-animation-name: blinker;
- -webkit-animation-iteration-count: infinite;
- -moz-animation-iteration-count: infinite;
- -ms-animation-iteration-count: infinite;
- -o-animation-iteration-count: infinite;
- -webkit-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -ms-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -o-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -moz-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -webkit-animation-duration: 1s;
- -moz-animation-duration: 1s;
- -o-animation-duration: 1s;
- -ms-animation-duration: 1s;
-}
-
-.jqconsole-ansi-blink-rapid {
- -webkit-animation-name: blinker;
- -moz-animation-name: blinker;
- -ms-animation-name: blinker;
- -o-animation-name: blinker;
- -webkit-animation-iteration-count: infinite;
- -moz-animation-iteration-count: infinite;
- -ms-animation-iteration-count: infinite;
- -o-animation-iteration-count: infinite;
- -webkit-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -ms-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -o-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -moz-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
- -webkit-animation-duration: 0.5s;
- -moz-animation-duration: 0.5s;
- -o-animation-duration: 0.5s;
- -ms-animation-duration: 0.5s;
-}
-
-
-.jqconsole-ansi-hidden {
- visibility:hidden!important;
-}
-
-.jqconsole-ansi-line-through {
- text-decoration: line-through;
-}
-
-.jqconsole-ansi-fonts-1 {
-
-}
-.jqconsole-ansi-fonts-2 {
-
-}
-.jqconsole-ansi-fonts-3 {
-
-}
-.jqconsole-ansi-fonts-4 {
-
-}
-.jqconsole-ansi-fonts-5 {
-
-}
-.jqconsole-ansi-fonts-6 {
-
-}
-.jqconsole-ansi-fonts-7 {
-
-}
-.jqconsole-ansi-fonts-8 {
-
-}
-.jqconsole-ansi-fonts-9 {
-
-}
-
-.jqconsole-ansi-fraktur {
-
-}
-
-.jqconsole-ansi-color-black {
- color: black!important;
-}
-.jqconsole-ansi-color-red {
- color: red!important;
-}
-.jqconsole-ansi-color-green {
- color: green!important;
-}
-.jqconsole-ansi-color-yellow {
- color: yellow!important;
-}
-.jqconsole-ansi-color-blue {
- color: blue!important;
-}
-.jqconsole-ansi-color-magenta {
- color: magenta!important;
-}
-.jqconsole-ansi-color-cyan {
- color: cyan!important;
-}
-.jqconsole-ansi-color-white {
- color: white!important;
-}
-
-.jqconsole-ansi-background-color-black {
- background-color: black!important;
-}
-.jqconsole-ansi-background-color-red {
- background-color: red!important;
-}
-.jqconsole-ansi-background-color-green {
- background-color: green!important;
-}
-.jqconsole-ansi-background-color-yellow {
- background-color: yellow!important;
-}
-.jqconsole-ansi-background-color-blue {
- background-color: blue!important;
-}
-.jqconsole-ansi-background-color-magenta {
- background-color: magenta!important;
-}
-.jqconsole-ansi-background-color-cyan {
- background-color: cyan!important;
-}
-.jqconsole-ansi-background-color-white {
- background-color: white!important;
-}
-
-.jqconsole-ansi-framed {
- border: 1px solid!important;
-}
-.jqconsole-ansi-overline {
- text-decoration: overline!important;
-}
-
diff --git a/lib/client/terminal/jqconsole/jqconsole-2.7.min.js b/lib/client/terminal/jqconsole/jqconsole-2.7.min.js
deleted file mode 100644
index 5ca306ea..00000000
--- a/lib/client/terminal/jqconsole/jqconsole-2.7.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
-Copyrights 2011, the repl.it project.
-Licensed under the MIT license
-*/
-(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L=function(a,b){return function(){return a.apply(b,arguments)}},M=Array.prototype.slice;a=jQuery,H=0,I=1,J=2,y=13,E=9,v=46,u=8,A=37,D=39,F=38,w=40,z=36,x=35,C=33,B=34,i="jqconsole-",e=""+i+"cursor",f=""+i+"header",j=""+i+"prompt",h=""+i+"old-prompt",g=""+i+"input",d=""+i+"blurred",s="keypress",p="",n="",o=":empty",G="\n",m=">>> ",l="... ",k=2,c=""+i+"ansi-",q="",r=/\[(\d*)(?:;(\d*))*m/,b=function(){function a(){this.stylize=L(this.stylize,this),this._closeSpan=L(this._closeSpan,this),this._openSpan=L(this._openSpan,this),this.getClasses=L(this.getClasses,this),this._style=L(this._style,this),this._color=L(this._color,this),this._remove=L(this._remove,this),this._append=L(this._append,this),this.klasses=[]}return a.prototype.COLORS=["black","red","green","yellow","blue","magenta","cyan","white"],a.prototype._append=function(a){a=""+c+a;if(this.klasses.indexOf(a)===-1)return this.klasses.push(a)},a.prototype._remove=function(){var a,b,d,e,f,g;d=1<=arguments.length?M.call(arguments,0):[],g=[];for(e=0,f=d.length;e'+a},a.prototype._closeSpan=function(a){return""+a+""},a.prototype.stylize=function(a){var b,c,d,e,f,g;a=this._openSpan(a),d=0;while((d=a.indexOf(q,d))&&d!==-1)if(c=a.slice(d).match(r)){g=c.slice(1);for(e=0,f=g.length;e'+(b||"")+""},t=function(){function c(c,d,e,g){this.container=c,this._HideComposition=L(this._HideComposition,this),this._ShowComposition=L(this._ShowComposition,this),this._UpdateComposition=L(this._UpdateComposition,this),this._EndComposition=L(this._EndComposition,this),this._StartComposition=L(this._StartComposition,this),this._CheckComposition=L(this._CheckComposition,this),this._ProcessMatch=L(this._ProcessMatch,this),this._HandleKey=L(this._HandleKey,this),this._HandleChar=L(this._HandleChar,this),this.isMobile=!!navigator.userAgent.match(/iPhone|iPad|iPod|Android/i),this.isIos=!!navigator.userAgent.match(/iPhone|iPad|iPod/i),this.isAndroid=!!navigator.userAgent.match(/Android/i),this.$window=a(window),this.header=d||"",this.prompt_label_main=e||m,this.prompt_label_continue=" \n"+(g||l),this.indent_width=k,this.state=I,this.input_queue=[],this.input_callback=null,this.multiline_callback=null,this.history=[],this.history_index=0,this.history_new="",this.history_active=!1,this.shortcuts={},this.$console=a('
').appendTo(this.container),this.$console.css({position:"absolute",top:0,bottom:0,right:0,left:0,margin:0,overflow:"auto"}),this.$console_focused=!0,this.$input_container=a(n).appendTo(this.container),this.$input_container.css({position:"relative",width:1,height:0,overflow:"hidden"}),this.$input_source=a(""),this.$input_source.attr("wrap","off").css({position:"absolute",width:2}),this.$input_source.appendTo(this.$input_container),this.$composition=a(n),this.$composition.addClass(""+i+"composition"),this.$composition.css({display:"inline",position:"relative"}),this.matchings={openings:{},closings:{},clss:[]},this.ansi=new b,this._InitPrompt(),this._SetupEvents(),this.Write(this.header,f),a(this.container).data("jqconsole",this)}return c.prototype.ResetHistory=function(){return this.history=[],this.history_index=0,this.history_current=""},c.prototype.ResetShortcuts=function(){return this.shortcuts={}},c.prototype.ResetMatchings=function(){return this.matchings={openings:{},closings:{},clss:[]}},c.prototype.Reset=function(){this.state!==I&&this.ClearPromptText(!0),this.state=I,this.input_queue=[],this.input_callback=null,this.multiline_callback=null,this.ResetHistory(),this.ResetShortcuts(),this.ResetMatchings(),this.$prompt.detach(),this.$input_container.detach(),this.$console.html(""),this.$prompt.appendTo(this.$console),this.$input_container.appendTo(this.container),this.Write(this.header,f)},c.prototype._CheckKeyCode=function(a){isNaN(a)?a=a.charCodeAt(0):a=parseInt(a,10);if(0>> ")):f.push(a(c).text());return f}().join(" ")},c.prototype.GetState=function(){return this.state===H?"input":this.state===I?"output":"prompt"},c.prototype.Disable=function(){return this.$input_source.attr("disabled",!0),this.$input_source.blur()},c.prototype.Enable=function(){return this.$input_source.attr("disabled",!1)},c.prototype.IsDisabled=function(){return Boolean(this.$input_source.attr("disabled"))},c.prototype.MoveToStart=function(a){this._MoveTo(a,!0)},c.prototype.MoveToEnd=function(a){this._MoveTo(a,!1)},c.prototype._CheckInputQueue=function(){if(this.input_queue.length)return this.input_queue.shift()()},c.prototype._InitPrompt=function(){this.$prompt=a(K(g)).appendTo(this.$console),this.$prompt_before=a(p).appendTo(this.$prompt),this.$prompt_current=a(p).appendTo(this.$prompt),this.$prompt_after=a(p).appendTo(this.$prompt),this.$prompt_label=a(p).appendTo(this.$prompt_current),this.$prompt_left=a(p).appendTo(this.$prompt_current),this.$prompt_right=a(p).appendTo(this.$prompt_current),this.$prompt_right.css({position:"relative"}),this.$prompt_cursor=a(K(e," ")),this.$prompt_cursor.insertBefore(this.$prompt_right),this.$prompt_cursor.css({color:"transparent",display:"inline",zIndex:0});if(!this.isMobile)return this.$prompt_cursor.css("position","absolute")},c.prototype._SetupEvents=function(){var b,c,e,f=this;this.isMobile?this.$console.click(function(a){return a.preventDefault(),f.Focus()}):this.$console.mouseup(function(a){var b;return b=function(){if(!window.getSelection().toString())return a.preventDefault(),f.Focus()},setTimeout(b,0)}),this.$input_source.focus(function(){var a,b;return f._ScrollToEnd(),f.$console_focused=!0,f.$console.removeClass(d),b=function(){if(f.$console_focused)return f.$console.removeClass(d)},setTimeout(b,100),a=function(){if(f.isIos&&f.$console_focuseded)return f.$input_source.hide()},setTimeout(a,500)}),this.$input_source.blur(function(){var a;return f.$console_focused=!1,f.isIos&&f.$input_source.show(),a=function(){if(!f.$console_focused)return f.$console.addClass(d)},setTimeout(a,100)}),e=a.browser.opera?"input":"paste",this.$input_source.bind(e,function(){var a;return a=function(){if(f.in_composition)return;return f._AppendPromptText(f.$input_source.val()),f.$input_source.val(""),f.Focus()},setTimeout(a,0)}),this.$input_source.keypress(this._HandleChar),c=a.browser.mozilla||a.browser.opera?s:"keydown",this.$input_source[c](this._HandleKey),this.$input_source.keydown(this._CheckComposition),a.browser.mozilla!=null&&(this.$input_source.bind("compositionstart",this._StartComposition),this.$input_source.bind("compositionend",this._EndCommposition),this.$input_source.bind("text",this._UpdateComposition));if(a.browser.opera!=null)return b=function(){if(f.in_composition)return;if(f.$input_source.val().length)return f._StartComposition()},setInterval(b,200)},c.prototype._HandleChar=function(b){var c;if(this.state===I||b.metaKey||b.ctrlKey)return!0;c=b.which;if(c===8||c===9||c===13)return!1;if(a.browser.mozilla)if(b.keyCode||b.altKey)return!0;return a.browser.opera&&b.altKey?!0:(this.$prompt_left.text(this.$prompt_left.text()+String.fromCharCode(c)),this._ScrollToEnd(),!1)},c.prototype._HandleKey=function(b){var c;if(this.state===I)return!0;c=b.keyCode||b.which,setTimeout(a.proxy(this._CheckMatchings,this),0);if(b.altKey)return!0;if(b.ctrlKey||b.metaKey)return this._HandleCtrlShortcut(c);if(b.shiftKey){switch(c){case y:this._HandleEnter(!0);break;case E:this._Unindent();break;case F:this._MoveUp();break;case w:this._MoveDown();break;case C:this._ScrollUp();break;case B:this._ScrollDown();break;default:return!0}return!1}switch(c){case y:this._HandleEnter(!1);break;case E:this._Indent();break;case v:this._Delete(!1);break;case u:this._Backspace(!1);break;case A:this._MoveLeft(!1);break;case D:this._MoveRight(!1);break;case F:this._HistoryPrevious();break;case w:this._HistoryNext();break;case z:this.MoveToStart(!1);break;case x:this.MoveToEnd(!1);break;case C:this._ScrollUp();break;case B:this._ScrollDown();break;default:return!0}return!1},c.prototype._HandleCtrlShortcut=function(a){var b,c,d,e;switch(a){case v:this._Delete(!0);break;case u:this._Backspace(!0);break;case A:this._MoveLeft(!0);break;case D:this._MoveRight(!0);break;case F:this._MoveUp();break;case w:this._MoveDown();break;case x:this.MoveToEnd(!0);break;case z:this.MoveToStart(!0);break;default:if(a in this.shortcuts){e=this.shortcuts[a];for(c=0,d=e.length;cg;0<=g?f++:f--)a>0?h.push(d._Indent()):h.push(d._Unindent());return h}return e=d.state===H?"input":"prompt",d.Write(d.GetPromptText(!0)+G,""+i+"old-"+e),d.ClearPromptText(!0),d.history_active&&((!d.history.length||d.history[d.history.length-1]!==c)&&d.history.push(c),d.history_index=d.history.length),d.state=I,b=d.input_callback,d.input_callback=null,b&&b(c),d._CheckInputQueue()},this.multiline_callback?this.async_multiline?this.multiline_callback(c,b):b(this.multiline_callback(c)):b(!1))},c.prototype._GetDirectionals=function(b){var c,d,e,f,g,h,i,j;return f=b?this.$prompt_left:this.$prompt_right,c=b?this.$prompt_right:this.$prompt_left,e=b?this.$prompt_before:this.$prompt_after,d=b?this.$prompt_after:this.$prompt_before,h=b?a.proxy(this.MoveToStart,this):a.proxy(this.MoveToEnd,this),g=b?a.proxy(this._MoveLeft,this):a.proxy(this._MoveRight,this),j=b?"last":"first",i=b?"prependTo":"appendTo",{$prompt_which:f,$prompt_opposite:c,$prompt_relative:e,$prompt_rel_opposite:d,MoveToLimit:h,MoveDirection:g,which_end:j,where_append:i}},c.prototype._VerticalMove=function(a){var b,c,d,e,f,g,h,i;i=this._GetDirectionals(a),d=i.$prompt_which,b=i.$prompt_opposite,c=i.$prompt_relative,f=i.MoveToLimit,e=i.MoveDirection;if(c.is(o))return;return g=this.$prompt_left.text().length,f(),e(),h=d.text(),b.text(a?h.slice(g):h.slice(0,g)),d.text(a?h.slice(0,g):h.slice(g))},c.prototype._MoveUp=function(){return this._VerticalMove(!0)},c.prototype._MoveDown=function(){return this._VerticalMove()},c.prototype._HorizontalMove=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,q,r,s;s=this._GetDirectionals(c),h=s.$prompt_which,e=s.$prompt_opposite,g=s.$prompt_relative,f=s.$prompt_rel_opposite,q=s.which_end,n=s.where_append,k=c?/\w*\W*$/:/^\w*\W*/,l=h.text();if(l){if(b){r=l.match(k);if(!r)return;return r=r[0],m=e.text(),e.text(c?r+m:m+r),j=r.length,h.text(c?l.slice(0,-j):l.slice(j))}return m=e.text(),e.text(c?l.slice(-1)+m:m+l[0]),h.text(c?l.slice(0,-1):l.slice(1))}if(!g.is(o))return i=a(p)[n](f),i.append(a(p).text(this.$prompt_label.text())),i.append(a(p).text(e.text())),d=g.children()[q]().detach(),this.$prompt_label.text(d.children().first().text()),h.text(d.children().last().text()),e.text("")},c.prototype._MoveLeft=function(a){return this._HorizontalMove(a,!0)},c.prototype._MoveRight=function(a){return this._HorizontalMove(a)},c.prototype._MoveTo=function(a,b){var c,d,e,f,g,h,i;h=this._GetDirectionals(b),e=h.$prompt_which,c=h.$prompt_opposite,d=h.$prompt_relative,g=h.MoveToLimit,f=h.MoveDirection;if(a){i=[];while(!d.is(o)||e.text()!=="")g(!1),i.push(f(!1));return i}return c.text(this.$prompt_left.text()+this.$prompt_right.text()),e.text("")},c.prototype._Delete=function(a){var b,c,d;c=this.$prompt_right.text();if(c){if(a){d=c.match(/^\w*\W*/);if(!d)return;return d=d[0],this.$prompt_right.text(c.slice(d.length))}return this.$prompt_right.text(c.slice(1))}if(!this.$prompt_after.is(o))return b=this.$prompt_after.children().first().detach(),this.$prompt_right.text(b.children().last().text())},c.prototype._Backspace=function(b){var c,d,e;setTimeout(a.proxy(this._ScrollToEnd,this),0),d=this.$prompt_left.text();if(d){if(b){e=d.match(/\w*\W*$/);if(!e)return;return e=e[0],this.$prompt_left.text(d.slice(0,-e.length))}return this.$prompt_left.text(d.slice(0,-1))}if(!this.$prompt_before.is(o))return c=this.$prompt_before.children().last().detach(),this.$prompt_label.text(c.children().first().text()),this.$prompt_left.text(c.children().last().text())},c.prototype._Indent=function(){var a;return this.$prompt_left.prepend(function(){var b,c;c=[];for(a=1,b=this.indent_width;1<=b?a<=b:a>=b;1<=b?a++:a--)c.push(" ");return c}.call(this).join(""))},c.prototype._Unindent=function(){var a,b,c,d;a=this.$prompt_left.text()+this.$prompt_right.text(),d=[];for(b=1,c=this.indent_width;1<=c?b<=c:b>=c;1<=c?b++:b--){if(!/^ /.test(a))break;this.$prompt_left.text()?this.$prompt_left.text(this.$prompt_left.text().slice(1)):this.$prompt_right.text(this.$prompt_right.text().slice(1)),d.push(a=a.slice(1))}return d},c.prototype._InsertNewLine=function(b){var c,d,e;return b==null&&(b=!1),e=this._SelectPromptLabel(!this.$prompt_before.is(o)),c=a(p).appendTo(this.$prompt_before),c.append(a(p).text(e)),c.append(a(p).text(this.$prompt_left.text())),this.$prompt_label.text(this._SelectPromptLabel(!0)),b&&(d=this.$prompt_left.text().match(/^\s+/))?this.$prompt_left.text(d[0]):this.$prompt_left.text(""),this._ScrollToEnd()},c.prototype._AppendPromptText=function(a){var b,c,d,e,f,g;c=a.split(G),this.$prompt_left.text(this.$prompt_left.text()+c[0]),f=c.slice(1),g=[];for(d=0,e=f.length;de.top)return b.$window.scrollTop(d)}else{if(h+ad)return b.$window.scrollTop(e.top)}},setTimeout(a,0)},c.prototype._SelectPromptLabel=function(a){return this.state===J?a?this.prompt_label_continue:this.prompt_label_main:a?"\n ":" "},c.prototype._outerHTML=function(b){return document.body.outerHTML?b.get(0).outerHTML:a(n).append(b.eq(0).clone()).html()},c.prototype._Wrap=function(a,b,c){var d,e;return e=a.html(),d=e.slice(0,b)+K(c,e[b])+e.slice(b+1),a.html(d)},c.prototype._WalkCharacters=function(a,b,c,d,e){var f,g,h;g=e?a.length:0,a=a.split(""),h=function(){var b,c,d,f;return e?(d=a,a=2<=d.length?M.call(d,0,c=d.length-1):(c=0,[]),b=d[c++]):(f=a,b=f[0],a=2<=f.length?M.call(f,1):[]),b&&(g+=e?-1:1),b};while(f=h()){f===b?d++:f===c&&d--;if(d===0)return{index:g,current_count:d}}return{index:-1,current_count:d}},c.prototype._ProcessMatch=function(b,c,d){var e,f,g,h,i,j,k,l,m,n,o,p,q=this;return n=c?[b.closing_char,b.opening_char]:[b.opening_char,b.closing_char],h=n[0],l=n[1],o=this._GetDirectionals(c),g=o.$prompt_which,f=o.$prompt_relative,i=1,j=!1,m=g.html(),c||(m=m.slice(1)),d&&c&&(m=m.slice(0,-1)),p=this._WalkCharacters(m,h,l,i,c),k=p.index,i=p.current_count,k>-1?(this._Wrap(g,k,b.cls),j=!0):(e=f.children(),e=c?Array.prototype.reverse.call(e):e,e.each(function(d,e){var f,g;f=a(e).children().last(),m=f.html(),g=q._WalkCharacters(m,h,l,i,c),k=g.index,i=g.current_count;if(k>-1)return c||k--,q._Wrap(f,k,b.cls),j=!0,!1})),j},c.prototype._CheckMatchings=function(b){var c,d,e,f,g,h,i;e=b?this.$prompt_left.text().slice(this.$prompt_left.text().length-1):this.$prompt_right.text()[0],i=this.matchings.clss;for(g=0,h=i.length;g=this.history.length)return;return this.history_index===this.history.length-1?(this.history_index++,this.SetPromptText(this.history_new)):this.SetPromptText(this.history[++this.history_index])},c.prototype._CheckComposition=function(b){var c;c=b.keyCode||b.which,a.browser.opera!=null&&this.in_composition&&this._UpdateComposition();if(c===229)return this.in_composition?this._UpdateComposition():this._StartComposition()},c.prototype._StartComposition=function(){return this.$input_source.bind(s,this._EndComposition),this.in_composition=!0,this._ShowComposition(),setTimeout(this._UpdateComposition,0)},c.prototype._EndComposition=function(){return this.$input_source.unbind(s,this._EndComposition),this.in_composition=!1,this._HideComposition(),this.$input_source.val("")},c.prototype._UpdateComposition=function(a){var b,c=this;return b=function(){if(!c.in_composition)return;return c.$composition.text(c.$input_source.val())},setTimeout(b,0)},c.prototype._ShowComposition=function(){return this.$composition.css("height",this.$prompt_cursor.height()),this.$composition.empty(),this.$composition.appendTo(this.$prompt_left)},c.prototype._HideComposition=function(){return this.$composition.detach()},c}(),a.fn.jqconsole=function(a,b,c){return new t(this,a,b,c)}}).call(this)
\ No newline at end of file
diff --git a/lib/client/terminal/jqconsole/jqconsole.coffee b/lib/client/terminal/jqconsole/jqconsole.coffee
deleted file mode 100644
index c0a76c16..00000000
--- a/lib/client/terminal/jqconsole/jqconsole.coffee
+++ /dev/null
@@ -1,1279 +0,0 @@
-###
-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 = '\033'
-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
- @_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
- @_append 'color-' + @_color code - 30
- when 39 then @_remove 'color'
- when 40,41,42,43,44,45,46,47
- @_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 = prompt_label or DEFAULT_PROMPT_LABEL
- @prompt_label_continue = ' \n' + (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 = $('')
- @$input_source.attr('wrap', 'off').css
- position: 'absolute'
- width: 2
- @$input_source.appendTo @$input_container
-
- @$composition = $(EMPTY_DIV)
- @$composition.addClass "#{CLASS_PREFIX}composition"
- @$composition.css
- display: 'inline'
- position: 'relative'
-
- # Hash containing all matching settings
- # openings/closings[char] = matching_config
- # where char is the opening/closing character.
- # clss is an array of classes for fast unhighlighting
- # for matching_config see Match method
- @matchings =
- openings: {}
- closings: {}
- clss: []
-
- @ansi = new Ansi()
-
- # Prepare console for interaction.
- @_InitPrompt()
- @_SetupEvents()
- @Write @header, CLASS_HEADER
-
- # Save this instance to be accessed if lost.
- $(@container).data 'jqconsole', this
-
- # Resets the history into intitial state.
- ResetHistory: ->
- @history = []
- @history_index = 0
- @history_current = ''
-
- # Resets the shortcut configuration.
- ResetShortcuts: ->
- @shortcuts = {}
-
- # Resets the matching configuration.
- ResetMatchings: ->
- @matchings =
- openings: {}
- closings: {}
- clss: []
-
- # Resets the console to its initial state.
- Reset: ->
- if @state != STATE_OUTPUT then @ClearPromptText true
- @state = STATE_OUTPUT
- @input_queue = []
- @input_callback = null
- @multiline_callback = null
- @ResetHistory()
- @ResetShortcuts()
- @ResetMatchings()
- @$prompt.detach()
- @$input_container.detach()
- @$console.html ''
- @$prompt.appendTo @$console
- @$input_container.appendTo @container
- @Write @header, CLASS_HEADER
- return undefined
-
- ###------------------------ Shortcut Methods -----------------------------###
-
- # Checks the type/value of key codes passed in for registering/unregistering
- # shortcuts and handles accordingly.
- _CheckKeyCode: (key_code) ->
- if isNaN key_code
- key_code = key_code.charCodeAt 0
- else
- key_code = parseInt key_code, 10
-
- if not (0 < key_code < 256) or isNaN key_code
- throw new Error 'Key code must be a number between 0 and 256 exclusive.'
-
- return key_code
-
- # A helper function responsible for calling the register/unregister callback
- # twice passing in both the upper and lower case letters.
- _LetterCaseHelper: (key_code, callback)->
- callback key_code
- if 65 <= key_code <= 90 then callback key_code + 32
- if 97 <= key_code <= 122 then callback key_code - 32
-
- # Registers a Ctrl+Key shortcut.
- # @arg key_code: The code of the key pressing which (when Ctrl is held) will
- # trigger this shortcut. If a string is provided, the character code of
- # the first character is taken.
- # @arg callback: A function called when the shortcut is pressed; "this" will
- # point to the JQConsole object.
- RegisterShortcut: (key_code, callback) ->
- key_code = @_CheckKeyCode key_code
- if not callback instanceof Function
- throw new Error 'Callback must be a function, not ' + callback + '.'
-
- addShortcut = (key) =>
- if key not of @shortcuts then @shortcuts[key] = []
- @shortcuts[key].push callback
-
- @_LetterCaseHelper key_code, addShortcut
- return undefined
-
- # Removes a Ctrl+Key shortcut from shortcut registry.
- # @arg key_code: The code of the key pressing which (when Ctrl is held) will
- # trigger this shortcut. If a string is provided, the character code of
- # the first character is taken.
- # @arg handler: The handler that was used when registering the shortcut,
- # if not supplied then all shortcut handlers corrosponding to the key
- # would be removed.
- UnRegisterShortcut: (key_code, handler) ->
- key_code = @_CheckKeyCode key_code
-
- removeShortcut = (key)=>
- if key of @shortcuts
- if handler
- @shortcuts[key].splice @shortcuts[key].indexOf(handler), 1
- else
- delete @shortcuts[key]
-
- @_LetterCaseHelper key_code, removeShortcut
- return undefined
-
- ###---------------------- END Shortcut Methods ---------------------------###
-
- # Returns the 0-based number of the column on which the cursor currently is.
- GetColumn: ->
- @$prompt_cursor.text ''
- lines = @$console.text().split NEWLINE
- @$prompt_cursor.html ' '
- return lines[lines.length - 1].length
-
- # Returns the 0-based number of the line on which the cursor currently is.
- GetLine: ->
- return @$console.text().split(NEWLINE).length - 1
-
- # Clears the contents of the prompt.
- # @arg clear_label: If true, also clears the main prompt label (e.g. ">>>").
- ClearPromptText: (clear_label) ->
- if @state == STATE_OUTPUT
- throw new Error 'ClearPromptText() is not allowed in output state.'
- @$prompt_before.html ''
- @$prompt_after.html ''
- @$prompt_label.text if clear_label then '' else @_SelectPromptLabel false
- @$prompt_left.text ''
- @$prompt_right.text ''
- return undefined
-
- # Returns the contents of the prompt.
- # @arg full: If true, also includes the prompt labels (e.g. ">>>").
- GetPromptText: (full) ->
- if @state == STATE_OUTPUT
- throw new Error 'GetPromptText() is not allowed in output state.'
-
- if full
- @$prompt_cursor.text ''
- text = @$prompt.text()
- @$prompt_cursor.html ' '
- return text
- else
- getPromptLines = (node) ->
- buffer = []
- node.children().each -> buffer.push $(@).children().last().text()
- return buffer.join NEWLINE
-
- before = getPromptLines @$prompt_before
- if before then before += NEWLINE
-
- current = @$prompt_left.text() + @$prompt_right.text()
-
- after = getPromptLines @$prompt_after
- if after then after = NEWLINE + after
-
- return before + current + after
-
- # Sets the contents of the prompt.
- # @arg text: The text to put in the prompt. May contain multiple lines.
- SetPromptText: (text) ->
- if @state == STATE_OUTPUT
- throw new Error 'SetPromptText() is not allowed in output state.'
- @ClearPromptText false
- @_AppendPromptText text
- @_ScrollToEnd()
- return undefined
-
- # Writes the given text to the console in a , with an optional class.
- # @arg text: The text to write.
- # @arg cls: The class to give the span containing the text. Optional.
- Write: (text, cls, escape=true) ->
- if escape
- text = @ansi.stylize $(EMPTY_SPAN).text(text).html()
-
- span = $(EMPTY_SPAN).html text
- if cls? then span.addClass cls
- span.insertBefore @$prompt
- @_ScrollToEnd()
- # Force reclaculation of the cursor's position.
- @$prompt_cursor.detach().insertAfter @$prompt_left
- return undefined
-
- # Starts an input operation. 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.
- # @arg input_callback: A function called with the user's input when the
- # user presses Enter and the input operation is complete.
- Input: (input_callback) ->
- if @state == STATE_PROMPT
- # Input operation has a higher priority, Abort and defer current prompt
- # by putting it on top of the queue.
- current_input_callback = @input_callback
- current_multiline_callback = @multiline_callback
- current_history_active = @history_active
- current_async_multiline = @async_multiline
- @AbortPrompt()
- @input_queue.unshift => @Prompt current_history_active,
- current_input_callback,
- current_multiline_callback,
- current_async_multiline
- else if @state != STATE_OUTPUT
- @input_queue.push => @Input input_callback
- return
- @history_active = false
- @input_callback = input_callback
- @multiline_callback = null
- @state = STATE_INPUT
- @$prompt.attr 'class', CLASS_INPUT
- @$prompt_label.text @_SelectPromptLabel false
- @Focus()
- @_ScrollToEnd()
- return undefined
-
- # Starts a command prompt operation. If another input or prompt operation is
- # currently underway, the new prompt operation is enqueued and will be called
- # when the current operation and all previously enqueued operations finish.
- # @arg 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.
- # @arg result_callback: A function called with the user's input when the
- # user presses Enter and the prompt operation is complete.
- # @arg 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.
- Prompt: (history_enabled, result_callback, multiline_callback, async_multiline) ->
- if @state != STATE_OUTPUT
- @input_queue.push =>
- @Prompt history_enabled, result_callback, multiline_callback, async_multiline
- return
- @history_active = history_enabled
- @input_callback = result_callback
- @multiline_callback = multiline_callback
- @async_multiline = async_multiline
- @state = STATE_PROMPT
- @$prompt.attr 'class', CLASS_PROMPT + ' ' + @ansi.getClasses()
- @$prompt_label.text @_SelectPromptLabel false
- @Focus()
- @_ScrollToEnd()
- return undefined
-
- # Aborts the current prompt operation and returns to output mode or the next
- # queued input/prompt operation.
- AbortPrompt: ->
- if @state != STATE_PROMPT
- throw new Error 'Cannot abort prompt when not in prompt state.'
- @Write @GetPromptText(true) + NEWLINE, CLASS_OLD_PROMPT
- @ClearPromptText true
- @state = STATE_OUTPUT
- @input_callback = @multiline_callback = null
- @_CheckInputQueue()
- return undefined
-
- # Sets focus on the console's hidden input box so input can be read.
- Focus: ->
- @$input_source.focus() if not @IsDisabled()
- return undefined
-
- # Sets the number of spaces inserted when indenting.
- SetIndentWidth: (width) ->
- @indent_width = width
-
- # Returns the number of spaces inserted when indenting.
- GetIndentWidth: ->
- return @indent_width
-
- # Registers character matching settings for a single matching
- # @arg open: the openning character
- # @arg close: the closing character
- # @arg cls: the html class to add to the matched characters
- RegisterMatching: (open, close, cls) ->
- match_config =
- opening_char: open
- closing_char: close
- cls: cls
-
- @matchings.clss.push(cls)
- @matchings.openings[open] = match_config
- @matchings.closings[close] = match_config
-
- # Unregisters a character matching. cls is optional.
- UnRegisterMatching: (open, close) ->
- cls = @matchings.openings[open].cls
- delete @matchings.openings[open]
- delete @matchings.closings[close]
- @matchings.clss.splice @matchings.clss.indexOf(cls), 1
-
- # Dumps the content of the console before the current prompt.
- Dump: ->
- $elems = @$console.find(".#{CLASS_HEADER}").nextUntil(".#{CLASS_PROMPT}")
-
- return (
- for elem in $elems
- if $(elem).is ".#{CLASS_OLD_PROMPT}"
- $(elem).text().replace /^\s+/, '>>> '
- else
- $(elem).text()
- ).join ' '
-
- # Gets the current prompt state.
- GetState: ->
- return if @state is STATE_INPUT
- 'input'
- else if @state is STATE_OUTPUT
- 'output'
- else
- 'prompt'
-
- # Disables focus and input on the console.
- Disable: ->
- @$input_source.attr 'disabled', on
- @$input_source.blur();
-
- # Enables focus and input on the console.
- Enable: ->
- @$input_source.attr 'disabled', off
-
- # Returns true if the console is disabled.
- IsDisabled: ->
- return Boolean @$input_source.attr 'disabled'
-
- # Moves the cursor to the start of the current prompt line.
- # @arg all_lines: If true, moves to the beginning of the first prompt line,
- # instead of the beginning of the current.
- MoveToStart: (all_lines) ->
- @_MoveTo all_lines, true
- return undefined
-
- # Moves the cursor to the end of the current prompt line.
- MoveToEnd: (all_lines) ->
- @_MoveTo all_lines, false
- return undefined
-
- ###------------------------ Private Methods -------------------------------###
-
- _CheckInputQueue: ->
- if @input_queue.length
- @input_queue.shift()()
-
- # Creates the movable prompt span. When the console is in input mode, this is
- # shown and allows user input. The structure of the spans are as follows:
- # $prompt
- # $prompt_before
- # line1
- # prompt_label
- # prompt_content
- # ...
- # lineN
- # prompt_label
- # prompt_content
- # $prompt_current
- # $prompt_label
- # $prompt_left
- # $prompt_cursor
- # $prompt_right
- # $prompt_after
- # line1
- # prompt_label
- # prompt_content
- # ...
- # lineN
- # prompt_label
- # prompt_content
- _InitPrompt: ->
- # The main prompt container.
- @$prompt = $(spanHtml(CLASS_INPUT)).appendTo @$console
- # The main divisions of the prompt - the lines before the current line, the
- # current line, and the lines after it.
- @$prompt_before = $(EMPTY_SPAN).appendTo @$prompt
- @$prompt_current = $(EMPTY_SPAN).appendTo @$prompt
- @$prompt_after = $(EMPTY_SPAN).appendTo @$prompt
-
- # The subdivisions of the current prompt line - the static prompt label
- # (e.g. ">>> "), and the editable text to the left and right of the cursor.
- @$prompt_label = $(EMPTY_SPAN).appendTo @$prompt_current
- @$prompt_left = $(EMPTY_SPAN).appendTo @$prompt_current
- @$prompt_right = $(EMPTY_SPAN).appendTo @$prompt_current
-
- # Needed for the CSS z-index on the cursor to work.
- @$prompt_right.css position: 'relative'
-
- # The cursor. A span containing a space that shades its following character.
- # If the font of the prompt is not monospace, the content should be set to
- # the first character of @$prompt_right to get the appropriate width.
- @$prompt_cursor = $(spanHtml(CLASS_CURSOR, ' '))
- @$prompt_cursor.insertBefore @$prompt_right
- @$prompt_cursor.css
- color: 'transparent'
- display: 'inline'
- zIndex: 0
- @$prompt_cursor.css('position', 'absolute') if not @isMobile
-
- # Binds all the required input and focus events.
- _SetupEvents: ->
-
- # Click to focus.
- if @isMobile
- @$console.click (e) =>
- e.preventDefault()
- @Focus()
- else
- @$console.mouseup (e) =>
- fn = =>
- if not window.getSelection().toString()
- e.preventDefault()
- @Focus()
- # Force selection update.
- setTimeout fn, 0
-
- # Mark the console with a style when it loses focus.
- @$input_source.focus =>
- @_ScrollToEnd()
- @$console_focused = true
- @$console.removeClass CLASS_BLURRED
- removeClass = =>
- if @$console_focused then @$console.removeClass CLASS_BLURRED
- setTimeout removeClass, 100
- hideTextInput = =>
- if @isIos and @$console_focused then @$input_source.hide()
- setTimeout hideTextInput, 500
-
- @$input_source.blur =>
- @$console_focused = false
- if @isIos then @$input_source.show()
- addClass = =>
- if not @$console_focused then @$console.addClass CLASS_BLURRED
- setTimeout addClass, 100
-
- # Intercept pasting.
- paste_event = if $.browser.opera then 'input' else 'paste'
- @$input_source.bind paste_event, =>
- handlePaste = =>
- # Opera fires input on composition end.
- return if @in_composition
- @_AppendPromptText @$input_source.val()
- @$input_source.val ''
- @Focus()
- # Wait until the browser has handled the paste event before scraping.
- setTimeout handlePaste, 0
-
- # Actual key-by-key handling.
- @$input_source.keypress @_HandleChar
-
- # FF & opera fires keydown events only once (even when holding) and
- # also delegates control keys to keypress that *is* fired more than
- # once on holding down the key.
- key_event = if $.browser.mozilla or $.browser.opera
- E_KEYPRESS
- else
- 'keydown'
- @$input_source[key_event] @_HandleKey
- @$input_source.keydown @_CheckComposition
-
- # Firefox don't fire any key event for composition characters, so we listen
- # for the unstandard composition-events.
- if $.browser.mozilla?
- @$input_source.bind 'compositionstart', @_StartComposition
- @$input_source.bind 'compositionend', @_EndCommposition
- @$input_source.bind 'text', @_UpdateComposition
-
- # There is no way to detect compositionstart in opera so we poll for it.
- if $.browser.opera?
- cb = =>
- return if @in_composition
- # if there was characters that actually escaped to the input source
- # then its most probably a multibyte char.
- if @$input_source.val().length
- @_StartComposition()
- setInterval cb, 200
-
- # Handles a character key press.
- # @arg event: The jQuery keyboard Event object to handle.
- _HandleChar: (event) =>
- # We let the browser take over during output mode.
- # Skip everything when a modifier key other than shift is held.
- # Allow alt key to pass through for unicode & multibyte characters.
- if @state == STATE_OUTPUT or event.metaKey or event.ctrlKey
- return true
-
- # IE & Chrome capture non-control characters and Enter.
- # Mozilla and Opera capture everything.
-
- # This is the most reliable cross-browser; charCode/keyCode break on Opera.
- char_code = event.which
-
- # Skip Enter on IE and Chrome and Tab & backspace on Opera.
- # These are handled in _HandleKey().
- if char_code in [8, 9, 13] then return false
-
- # Pass control characters which are captured on Mozilla/Safari.
- if $.browser.mozilla
- if event.keyCode or event.altKey
- return true
- # Pass control characters which are captured on Opera.
- if $.browser.opera
- if event.altKey
- return true
-
- @$prompt_left.text @$prompt_left.text() + String.fromCharCode char_code
- @_ScrollToEnd()
- return false
-
- # Handles a key up event and dispatches specific handlers.
- # @arg event: The jQuery keyboard Event object to handle.
- _HandleKey: (event) =>
- # We let the browser take over during output mode.
- if @state == STATE_OUTPUT then return true
-
- key = event.keyCode or event.which
-
- # Check for char matching next time the callstack unwinds.
- setTimeout $.proxy(@_CheckMatchings, this), 0
-
- # Don't care about alt-modifier.
- if event.altKey
- return true
- # Handle shortcuts.
- else if event.ctrlKey or event.metaKey
- return @_HandleCtrlShortcut key
- else if event.shiftKey
- # Shift-modifier shortcut.
- switch key
- when KEY_ENTER then @_HandleEnter true
- when KEY_TAB then @_Unindent()
- when KEY_UP then @_MoveUp()
- when KEY_DOWN then @_MoveDown()
- when KEY_PAGE_UP then @_ScrollUp()
- when KEY_PAGE_DOWN then @_ScrollDown()
- # Allow other Shift shortcuts to pass through to the browser.
- else return true
- return false
- else
- # Not a modifier shortcut.
- switch key
- when KEY_ENTER then @_HandleEnter false
- when KEY_TAB then @_Indent()
- when KEY_DELETE then @_Delete false
- when KEY_BACKSPACE then @_Backspace false
- when KEY_LEFT then @_MoveLeft false
- when KEY_RIGHT then @_MoveRight false
- when KEY_UP then @_HistoryPrevious()
- when KEY_DOWN then @_HistoryNext()
- when KEY_HOME then @MoveToStart false
- when KEY_END then @MoveToEnd false
- when KEY_PAGE_UP then @_ScrollUp()
- when KEY_PAGE_DOWN then @_ScrollDown()
- # Let any other key continue its way to keypress.
- else return true
- return false
-
- # Handles a Ctrl+Key shortcut.
- # @arg key: The keyCode of the pressed key.
- _HandleCtrlShortcut: (key) ->
- switch key
- when KEY_DELETE then @_Delete true
- when KEY_BACKSPACE then @_Backspace true
- when KEY_LEFT then @_MoveLeft true
- when KEY_RIGHT then @_MoveRight true
- when KEY_UP then @_MoveUp()
- when KEY_DOWN then @_MoveDown()
- when KEY_END then @MoveToEnd true
- when KEY_HOME then @MoveToStart true
- else
- if key of @shortcuts
- # Execute custom shortcuts.
- handler.call(this) for handler in @shortcuts[key]
- return false
- else
- # Allow unhandled Ctrl shortcuts.
- return true
- # Block handled shortcuts.
- return false
-
- # Handles the user pressing the Enter key.
- # @arg shift: Whether the shift key is held.
- _HandleEnter: (shift) ->
- if shift
- @_InsertNewLine true
- else
- text = @GetPromptText()
- continuation = (indent) =>
- if indent isnt false
- @MoveToEnd true
- @_InsertNewLine true
- for _ in [0...Math.abs indent]
- if indent > 0 then @_Indent() else @_Unindent()
- else
- # Done with input.
- cls_suffix = if @state == STATE_INPUT then 'input' else 'prompt'
- @Write @GetPromptText(true) + NEWLINE, "#{CLASS_PREFIX}old-" + cls_suffix
- @ClearPromptText true
- if @history_active
- if not @history.length or @history[@history.length - 1] != text
- @history.push text
- @history_index = @history.length
- @state = STATE_OUTPUT
- callback = @input_callback
- @input_callback = null
- if callback then callback text
- @_CheckInputQueue()
-
- if @multiline_callback
- if @async_multiline
- @multiline_callback text, continuation
- else
- continuation @multiline_callback text
- else
- continuation false
-
-
- # Returns the appropriate variables for usage in methods that depends on the
- # direction of the interaction with the console.
- _GetDirectionals: (back) ->
- $prompt_which = if back then @$prompt_left else @$prompt_right
- $prompt_opposite = if back then @$prompt_right else @$prompt_left
- $prompt_relative = if back then @$prompt_before else @$prompt_after
- $prompt_rel_opposite = if back then @$prompt_after else @$prompt_before
- MoveToLimit = if back
- $.proxy @MoveToStart, @
- else
- $.proxy @MoveToEnd, @
- MoveDirection = if back
- $.proxy @_MoveLeft, @
- else
- $.proxy @_MoveRight, @
- which_end = if back then 'last' else 'first'
- where_append = if back then 'prependTo' else 'appendTo'
- return {
- $prompt_which
- $prompt_opposite
- $prompt_relative
- $prompt_rel_opposite
- MoveToLimit
- MoveDirection
- which_end
- where_append
- }
-
- # Moves the cursor vertically in the current prompt,
- # in the same column. (Used by _MoveUp, _MoveDown)
- _VerticalMove: (up) ->
- {
- $prompt_which
- $prompt_opposite
- $prompt_relative
- MoveToLimit
- MoveDirection
- } = @_GetDirectionals(up)
-
- if $prompt_relative.is EMPTY_SELECTOR then return
- pos = @$prompt_left.text().length
- MoveToLimit()
- MoveDirection()
- text = $prompt_which.text()
- $prompt_opposite.text if up then text[pos..] else text[...pos]
- $prompt_which.text if up then text[...pos] else text[pos..]
-
-
- # Moves the cursor to the line above the current one, in the same column.
- _MoveUp: ->
- @_VerticalMove true
-
- # Moves the cursor to the line below the current one, in the same column.
- _MoveDown: ->
- @_VerticalMove()
-
- # Moves the cursor horizontally in the current prompt.
- # Used by _MoveLeft, _MoveRight
- _HorizontalMove: (whole_word, back) ->
- {
- $prompt_which
- $prompt_opposite
- $prompt_relative
- $prompt_rel_opposite
- which_end
- where_append
- } = @_GetDirectionals(back)
- regexp = if back then /\w*\W*$/ else /^\w*\W*/
-
- text = $prompt_which.text()
- if text
- if whole_word
- word = text.match regexp
- if not word then return
- word = word[0]
- tmp = $prompt_opposite.text()
- $prompt_opposite.text if back then word + tmp else tmp + word
- len = word.length
- $prompt_which.text if back then text[...-len] else text[len..]
- else
- tmp = $prompt_opposite.text()
- $prompt_opposite.text if back then text[-1...] + tmp else tmp + text[0]
- $prompt_which.text if back then text[...-1] else text[1...]
- else if not $prompt_relative.is EMPTY_SELECTOR
- $which_line = $(EMPTY_SPAN)[where_append] $prompt_rel_opposite
- $which_line.append $(EMPTY_SPAN).text @$prompt_label.text()
- $which_line.append $(EMPTY_SPAN).text $prompt_opposite.text()
-
- $opposite_line = $prompt_relative.children()[which_end]().detach()
- @$prompt_label.text $opposite_line.children().first().text()
- $prompt_which.text $opposite_line.children().last().text()
- $prompt_opposite.text ''
-
- # Moves the cursor to the left.
- # @arg whole_word: Whether to move by a whole word rather than a character.
- _MoveLeft: (whole_word) ->
- @_HorizontalMove whole_word, true
-
- # Moves the cursor to the right.
- # @arg whole_word: Whether to move by a whole word rather than a character.
- _MoveRight: (whole_word) ->
- @_HorizontalMove whole_word
-
- # Moves the cursor either to the start or end of the current prompt line(s).
- _MoveTo: (all_lines, back) ->
- {
- $prompt_which
- $prompt_opposite
- $prompt_relative
- MoveToLimit
- MoveDirection
- } = @_GetDirectionals(back)
-
- if all_lines
- # Warning! FF 3.6 hangs on is(EMPTY_SELECTOR)
- until $prompt_relative.is(EMPTY_SELECTOR) and $prompt_which.text() == ''
- MoveToLimit false
- MoveDirection false
- else
- $prompt_opposite.text @$prompt_left.text() + @$prompt_right.text()
- $prompt_which.text ''
-
- # Deletes the character or word following the cursor.
- # @arg whole_word: Whether to delete a whole word rather than a character.
- _Delete: (whole_word) ->
- text = @$prompt_right.text()
- if text
- if whole_word
- word = text.match /^\w*\W*/
- if not word then return
- word = word[0]
- @$prompt_right.text text[word.length...]
- else
- @$prompt_right.text text[1...]
- else if not @$prompt_after.is EMPTY_SELECTOR
- $lower_line = @$prompt_after.children().first().detach()
- @$prompt_right.text $lower_line.children().last().text()
-
- # Deletes the character or word preceding the cursor.
- # @arg whole_word: Whether to delete a whole word rather than a character.
- _Backspace: (whole_word) ->
- setTimeout $.proxy(@_ScrollToEnd, @), 0
- text = @$prompt_left.text()
- if text
- if whole_word
- word = text.match /\w*\W*$/
- if not word then return
- word = word[0]
- @$prompt_left.text text[...-word.length]
- else
- @$prompt_left.text text[...-1]
- else if not @$prompt_before.is EMPTY_SELECTOR
- $upper_line = @$prompt_before.children().last().detach()
- @$prompt_label.text $upper_line.children().first().text()
- @$prompt_left.text $upper_line.children().last().text()
-
- # Indents the current line.
- _Indent: ->
- @$prompt_left.prepend (' ' for _ in [1..@indent_width]).join ''
-
- # Unindents the current line.
- _Unindent: ->
- line_text = @$prompt_left.text() + @$prompt_right.text()
- for _ in [1..@indent_width]
- if not /^ /.test(line_text) then break
- if @$prompt_left.text()
- @$prompt_left.text @$prompt_left.text()[1..]
- else
- @$prompt_right.text @$prompt_right.text()[1..]
- line_text = line_text[1..]
-
- # Inserts a new line at the cursor position.
- # @arg indent: If specified and true, the inserted line is indented to the
- # same column as the last line.
- _InsertNewLine: (indent = false) ->
- old_prompt = @_SelectPromptLabel not @$prompt_before.is EMPTY_SELECTOR
- $old_line = $(EMPTY_SPAN).appendTo @$prompt_before
- $old_line.append $(EMPTY_SPAN).text old_prompt
- $old_line.append $(EMPTY_SPAN).text @$prompt_left.text()
-
- @$prompt_label.text @_SelectPromptLabel true
- if indent and match = @$prompt_left.text().match /^\s+/
- @$prompt_left.text match[0]
- else
- @$prompt_left.text ''
- @_ScrollToEnd()
-
- # Appends the given text to the prompt.
- # @arg text: The text to append. Can contain multiple lines.
- _AppendPromptText: (text) ->
- lines = text.split NEWLINE
- @$prompt_left.text @$prompt_left.text() + lines[0]
- for line in lines[1..]
- @_InsertNewLine()
- @$prompt_left.text line
-
- # Scrolls the console area up one page (with animation).
- _ScrollUp: ->
- target = @$console[0].scrollTop - @$console.height()
- @$console.stop().animate {scrollTop: target}, 'fast'
-
- # Scrolls the console area down one page (with animation).
- _ScrollDown: ->
- target = @$console[0].scrollTop + @$console.height()
- @$console.stop().animate {scrollTop: target}, 'fast'
-
- # Scrolls the console area to its bottom;
- # Scrolls the window to the cursor vertical position.
- # Called with every input/output to the console.
- _ScrollToEnd: ->
- # Scroll console to the bottom.
- @$console.scrollTop @$console[0].scrollHeight
-
- # The cursor's top position is effected by the scroll-top of the console
- # so we need to this asynchronously to give the browser a chance to
- # reflow and recaluclate the cursor's possition.
- cont = =>
- line_height = @$prompt_cursor.height()
- screen_top = @$window.scrollTop()
- screen_left = @$window.scrollLeft()
- doc_height = document.documentElement.clientHeight
- pos = @$prompt_cursor.offset()
- rel_pos = @$prompt_cursor.position()
-
- # Move the input element to the cursor position.
- @$input_container.css
- left: rel_pos.left
- top: rel_pos.top
-
- optimal_pos = pos.top - (2 * line_height)
- # Follow the cursor vertically on mobile and desktop.
- if @isMobile and orientation?
- # Since the keyboard takes up most of the screen, we don't care about how
- # far the the cursor position from the screen top is. We just follow it.
- if screen_top < pos.top or screen_top > pos.top
- @$window.scrollTop optimal_pos
- else
- if screen_top + doc_height < pos.top
- # Scroll just to a place where the cursor is in the view port.
- @$window.scrollTop pos.top - doc_height + line_height
- else if screen_top > optimal_pos
- # If the window is scrolled beyond the cursor, scroll to the cursor's
- # position and give two line to the top.
- @$window.scrollTop pos.top
-
- setTimeout cont, 0
-
- # Selects the prompt label appropriate to the current mode.
- # @arg continuation: If true, returns the continuation prompt rather than
- # the main one.
- _SelectPromptLabel: (continuation) ->
- if @state == STATE_PROMPT
- return if continuation then @prompt_label_continue else @prompt_label_main
- else
- return if continuation then '\n ' else ' '
-
- # Cross-browser outerHTML
- _outerHTML: ($elem) ->
- if document.body.outerHTML
- return $elem.get(0).outerHTML
- else
- return $(EMPTY_DIV).append($elem.eq(0).clone()).html()
-
- # Wraps a single character in an element with a having a class
- # @arg $elem: The JqDom element in question
- # @arg index: the index of the character to be wrapped
- # @arg cls: the html class to be given to the wrapping
- _Wrap: ($elem, index, cls) ->
- text = $elem.html()
- html = text[0...index]+
- spanHtml(cls, text[index])+
- text[index + 1...]
- $elem.html html
-
- # Walks a string of characters incrementing current_count each time a char is found
- # and decrementing each time an opposing char is found.
- # @arg text: the text in question
- # @arg char: the char that would increment the counter
- # @arg opposing_char: the char that would decrement the counter
- # @arg back: specifies whether the walking should be done backwards.
- _WalkCharacters: (text, char, opposing_char, current_count, back) ->
- index = if back then text.length else 0
- text = text.split ''
- read_char = () ->
- if back
- [text..., ret] = text
- else
- [ret, text...] = text
- if ret
- index = index + if back then -1 else +1
- ret
-
- while ch = read_char()
- if ch is char
- current_count++
- else if ch is opposing_char
- current_count--
- if current_count is 0
- return {index: index, current_count: current_count}
-
- return {index: -1, current_count: current_count}
-
- _ProcessMatch: (config, back, before_char) =>
- [char, opposing_char] = if back
- [
- config['closing_char']
- config['opening_char']
- ]
- else
- [
- config['opening_char']
- config['closing_char']
- ]
- {$prompt_which, $prompt_relative} = @_GetDirectionals(back)
-
- current_count = 1
- found = false
- # check current line first
- text = $prompt_which.html()
- # When on the same line discard checking the first character, going backwards
- # is not an issue since the cursor's current character is found in $prompt_right.
- if !back then text = text[1...]
- if before_char and back then text = text[...-1]
- {index, current_count} = @_WalkCharacters text, char, opposing_char, current_count, back
- if index > -1
- @_Wrap $prompt_which, index, config.cls
- found = true
- else
- $collection = $prompt_relative.children()
- # When going backwards we have to the reverse our jQuery collection
- # for fair matchings
- $collection = if back then Array.prototype.reverse.call($collection) else $collection
- $collection.each (i, elem) =>
- $elem = $(elem).children().last()
- text = $elem.html()
- {index, current_count} = @_WalkCharacters text, char, opposing_char, current_count, back
- if index > -1
- # When checking for matchings ona different line going forward we must decrement
- # the index since the current char is not included
- if !back then index--
- @_Wrap $elem, index, config.cls
- found = true
- return false
-
- return found
-
- # Unrwaps all prevoisly matched characters.
- # Checks if the cursor's current character is one to be matched, then walks
- # the following/preceeding characters to look for the opposing character that
- # would satisfy the match. If found both characters would be wrapped with a
- # span and applied the html class that was found in the match_config.
- _CheckMatchings: (before_char) ->
- current_char = if before_char then @$prompt_left.text()[@$prompt_left.text().length - 1...] else @$prompt_right.text()[0]
- # on every move unwrap all matched elements
- # TODO(amasad): cache previous matched elements since this must be costly
- $('.' + cls, @$console).contents().unwrap() for cls in @matchings.clss
-
- if config = @matchings.closings[current_char]
- found = @_ProcessMatch config, true, before_char
- else if config = @matchings.openings[current_char]
- found = @_ProcessMatch config, false, before_char
- else if not before_char
- @_CheckMatchings true
-
- if before_char
- @_Wrap @$prompt_left, @$prompt_left.html().length - 1, config.cls if found
- else
- # Wrap current element when a matching was found
- @_Wrap @$prompt_right, 0, config.cls if found
-
-
- # Sets the prompt to the previous history item.
- _HistoryPrevious: ->
- if not @history_active then return
- if @history_index <= 0 then return
- if @history_index == @history.length
- @history_new = @GetPromptText()
- @SetPromptText @history[--@history_index]
-
- # Sets the prompt to the next history item.
- _HistoryNext: ->
- if not @history_active then return
- if @history_index >= @history.length then return
- if @history_index == @history.length - 1
- @history_index++
- @SetPromptText @history_new
- else
- @SetPromptText @history[++@history_index]
-
- # Check if this could be the start of a composition or an update to it.
- _CheckComposition: (e) =>
- key = e.keyCode or e.which
- if $.browser.opera? and @in_composition
- @_UpdateComposition()
- if key == 229
- if @in_composition then @_UpdateComposition() else @_StartComposition()
-
- # Starts a multibyte character composition.
- _StartComposition: =>
- @$input_source.bind E_KEYPRESS, @_EndComposition
- @in_composition = true
- @_ShowComposition()
- setTimeout @_UpdateComposition, 0
-
- # Ends a multibyte character composition.
- _EndComposition: =>
- @$input_source.unbind E_KEYPRESS, @_EndComposition
- @in_composition = false
- @_HideComposition()
- @$input_source.val ''
-
- # Updates a multibyte character composition.
- _UpdateComposition: (e) =>
- cb = =>
- return if not @in_composition
- @$composition.text @$input_source.val()
- setTimeout cb, 0
-
- # Shows a multibyte character composition.
- _ShowComposition: =>
- @$composition.css 'height', @$prompt_cursor.height()
- @$composition.empty()
- @$composition.appendTo @$prompt_left
-
- # Hides a multibyte character composition.
- _HideComposition: =>
- # We just detach the element because by now the text value of this element
- # is already extracted and has been put on the left of the prompt.
- @$composition.detach()
-
-$.fn.jqconsole = (header, prompt_main, prompt_continue) ->
- new JQConsole this, header, prompt_main, prompt_continue