mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 10:45:47 +00:00
feature(console) consle -> console-io from npm
This commit is contained in:
parent
c96e97f618
commit
21501736cb
35 changed files with 122 additions and 20655 deletions
|
|
@ -1,55 +0,0 @@
|
|||
.error-msg {
|
||||
color: crimson;
|
||||
}
|
||||
|
||||
.log-msg{
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.error-msg, .log-msg {
|
||||
display : block;
|
||||
padding : 10px;
|
||||
margin : 10px;
|
||||
font : 16px "Droid Sans Mono";
|
||||
background : beige;
|
||||
-webkit-border-radius : 5px;
|
||||
-moz-border-radius : 5px;
|
||||
border-radius : 5px;
|
||||
}
|
||||
|
||||
.jqconsole {
|
||||
padding : 10px;
|
||||
padding-bottom : 10px;
|
||||
background : #fffdf9;
|
||||
}
|
||||
|
||||
.jqconsole-cursor {
|
||||
background-color: #999;
|
||||
}
|
||||
.jqconsole-blurred .jqconsole-cursor {
|
||||
background-color: #666;
|
||||
}
|
||||
.jqconsole-prompt {
|
||||
color: #4a473a
|
||||
}
|
||||
.jqconsole-old-prompt {
|
||||
font-weight : normal;
|
||||
color : #b7b4a8;
|
||||
}
|
||||
|
||||
.jqconsole-prompt, .jqconsole-old-prompt {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.brace {
|
||||
color: #00FFFF;
|
||||
}
|
||||
.paran {
|
||||
color: #FF00FF;
|
||||
}
|
||||
.bracket {
|
||||
color: #FFFF00;
|
||||
}
|
||||
.jqconsole-composition {
|
||||
background-color: red;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
"contact",
|
||||
"socket",
|
||||
"terminal",
|
||||
"console", [{
|
||||
"konsole", [{
|
||||
"name": "remote",
|
||||
"data": [{
|
||||
"name": "jquery",
|
||||
|
|
|
|||
|
|
@ -1,220 +0,0 @@
|
|||
var CloudCmd, Util, join, DOM, CloudFunc, $;
|
||||
|
||||
(function(CloudCmd, Util, join, DOM, CloudFunc) {
|
||||
'use strict';
|
||||
|
||||
CloudCmd.Console = ConsoleProto;
|
||||
|
||||
function ConsoleProto() {
|
||||
var Name = 'Console',
|
||||
Buffer = {
|
||||
log : '',
|
||||
error : ''
|
||||
},
|
||||
Loading,
|
||||
jqconsole,
|
||||
|
||||
log = Util.exec.with(write, 'log'),
|
||||
error = Util.exec.with(write, 'error'),
|
||||
|
||||
Element,
|
||||
MouseBinded,
|
||||
Socket,
|
||||
Images = DOM.Images,
|
||||
Notify = DOM.Notify,
|
||||
|
||||
CHANNEL = CloudFunc.CHANNEL_CONSOLE,
|
||||
|
||||
Console = this;
|
||||
|
||||
function init() {
|
||||
Loading = true;
|
||||
|
||||
Util.exec.series([
|
||||
DOM.loadJquery,
|
||||
CloudCmd.View,
|
||||
load,
|
||||
CloudCmd.Socket,
|
||||
function(callback) {
|
||||
Socket = CloudCmd.Socket;
|
||||
Util.exec(callback);
|
||||
},
|
||||
Console.show,
|
||||
addListeners,
|
||||
]);
|
||||
}
|
||||
|
||||
this.show = show;
|
||||
this.clear = clear;
|
||||
|
||||
// Handle a command.
|
||||
function handler(command) {
|
||||
if (command)
|
||||
Socket.emit(CHANNEL, command);
|
||||
else
|
||||
jqconsole.Prompt(true, handler);
|
||||
}
|
||||
|
||||
function show(callback) {
|
||||
if (!Loading) {
|
||||
Images.showLoad({top:true});
|
||||
|
||||
if (!Element) {
|
||||
Element = DOM.load({
|
||||
name : 'div',
|
||||
className : 'console'
|
||||
});
|
||||
|
||||
jqconsole = $(Element).jqconsole('', '> ');
|
||||
|
||||
addShortCuts(jqconsole);
|
||||
}
|
||||
|
||||
CloudCmd.View.show(Element, {
|
||||
afterShow: function() {
|
||||
var console = jqconsole.$console,
|
||||
input = jqconsole.$input_source,
|
||||
|
||||
focus = function() {
|
||||
var x = window.scrollX,
|
||||
y = window.scrollY;
|
||||
|
||||
input.focus();
|
||||
window.scrollTo(x,y);
|
||||
};
|
||||
|
||||
focus();
|
||||
|
||||
if (!MouseBinded) {
|
||||
MouseBinded = true;
|
||||
|
||||
console.mouseup(function() {
|
||||
var top,
|
||||
isSelection = '' + window.getSelection();
|
||||
|
||||
if (!isSelection) {
|
||||
top = console.scrollTop();
|
||||
|
||||
focus();
|
||||
console.scrollTop(top);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Util.exec(callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function write(status, msg) {
|
||||
var isContain;
|
||||
|
||||
if (msg) {
|
||||
Buffer[status] += msg;
|
||||
isContain = Util.isContainStr(Buffer[status], '\n');
|
||||
|
||||
if (jqconsole && isContain) {
|
||||
jqconsole.Write(Buffer[status], status + '-msg');
|
||||
Notify.send(Buffer[status]);
|
||||
Buffer[status] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addShortCuts(jqconsole) {
|
||||
jqconsole.RegisterShortcut('Z', function() {
|
||||
jqconsole.SetPromptText('');
|
||||
});
|
||||
|
||||
jqconsole.RegisterShortcut('L', clear);
|
||||
|
||||
jqconsole.RegisterShortcut('P', function() {
|
||||
var command = jqconsole.GetPromptText();
|
||||
|
||||
command += DOM.getCurrentDirPath();
|
||||
jqconsole.SetPromptText(command);
|
||||
});
|
||||
}
|
||||
|
||||
function clear() {
|
||||
jqconsole.Reset();
|
||||
addShortCuts(jqconsole);
|
||||
jqconsole.Prompt(true, handler);
|
||||
}
|
||||
|
||||
function load(callback) {
|
||||
var dir = CloudCmd.LIBDIRCLIENT + 'console/',
|
||||
jsPath = dir + 'lib/',
|
||||
|
||||
css = join([
|
||||
'/css/console.css',
|
||||
dir + 'css/ansi.css',
|
||||
]),
|
||||
|
||||
files = [
|
||||
jsPath + 'jqconsole.js',
|
||||
css
|
||||
];
|
||||
|
||||
DOM.load.parallel(files, function() {
|
||||
Util.timeEnd(Name + ' load');
|
||||
Loading = false;
|
||||
|
||||
Util.exec(callback);
|
||||
});
|
||||
|
||||
Util.time(Name + ' load');
|
||||
}
|
||||
|
||||
function isPrompt() {
|
||||
var state = jqconsole.GetState(),
|
||||
is = state === 'prompt';
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
function addListeners(callback) {
|
||||
var options = {
|
||||
'connect' : function() {
|
||||
log(Socket.CONNECTED);
|
||||
},
|
||||
|
||||
'disconnect': function() {
|
||||
var is = isPrompt();
|
||||
|
||||
error(Socket.DISCONNECTED);
|
||||
|
||||
if (is)
|
||||
jqconsole.AbortPrompt();
|
||||
}
|
||||
};
|
||||
|
||||
options[CHANNEL] = onMessage;
|
||||
|
||||
Socket.on(options);
|
||||
|
||||
Util.exec(callback);
|
||||
}
|
||||
|
||||
function onMessage(json) {
|
||||
var is = isPrompt();
|
||||
|
||||
if (json) {
|
||||
Util.log(json);
|
||||
|
||||
log(json.stdout);
|
||||
error(json.stderr);
|
||||
|
||||
if (json.path)
|
||||
jqconsole.SetPromptLabel(json.path + '> ');
|
||||
}
|
||||
|
||||
if (!is)
|
||||
jqconsole.Prompt(true, handler);
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
})(CloudCmd, Util, join, DOM, CloudFunc);
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{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 -m -o jqconsole.min.js lib/jqconsole.js', (err, res)->
|
||||
if err
|
||||
console.error 'failed with', err
|
||||
else
|
||||
console.log 'build complete'
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
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.
|
||||
|
||||
2013.8.5 Version 2.7.8
|
||||
* Fix issue #51.
|
||||
|
||||
2014.2.3 Version 2.8.0
|
||||
* Remove browser sniffing. Fix #37 #42 #53
|
||||
* Update android support. Fix #41
|
||||
* Add wrapper div for padding/styling of console. Fix #40
|
||||
|
||||
2014.2.8 Version 2.9.0
|
||||
* Fixed `GetColumn` method to return the column number up until the cursor.
|
||||
* `Dump`: Add header contents in console dump and remove extra spaces.
|
||||
|
||||
2014.2.8 Version 2.10.0
|
||||
* Add `Clear` method to clear the console
|
||||
|
||||
|
|
@ -1,730 +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 <a href="http://repl.it">repl.it</a> 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
|
||||
* Firefox
|
||||
* Opera
|
||||
* iOS Safari and Chrome
|
||||
* Android Chrome
|
||||
|
||||
|
||||
##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
|
||||
<div id="console"></div>
|
||||
<script src="jquery.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="jqconsole.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
var jqconsole = $('#console').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');
|
||||
// Restart the prompt.
|
||||
startPrompt();
|
||||
});
|
||||
};
|
||||
startPrompt();
|
||||
});
|
||||
</script>
|
||||
```
|
||||
<iframe src="demo/echo.html" style="width:400px;height:500px">
|
||||
</iframe>
|
||||
|
||||
###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 number of spaces in each indentation level.
|
||||
|
||||
|
||||
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 `<span>`, 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($('<div>hello</div>').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.
|
||||
|
||||
|
||||
###jqconsole.Clear
|
||||
Clears the console's content excluding the current prompt
|
||||
|
||||
##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).
|
||||
<table>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Effect</th>
|
||||
<th>Class</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>Reset / Normal</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Bold</td>
|
||||
<td>`jqconsole-ansi-bold`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Faint</td>
|
||||
<td>`jqconsole-ansi-lighter`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Italic</td>
|
||||
<td>`jqconsole-ansi-italic`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Line below text</td>
|
||||
<td>`jqconsole-ansi-underline`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Blink: 1s delay</td>
|
||||
<td>`jqconsole-ansi-blink`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Blink: 0.5s delay</td>
|
||||
<td>`jqconsole-ansi-blink-rapid`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td>Hide text</td>
|
||||
<td>`jqconsole-ansi-hidden`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9</td>
|
||||
<td>Line through text</td>
|
||||
<td>`jqconsole-ansi-line-through`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10</td>
|
||||
<td>Remove all fonts</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>11-19</td>
|
||||
<td>Add custom font</td>
|
||||
<td>`jqconsole-ansi-fonts-{N}` where N is code - 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>20</td>
|
||||
<td>Add Fraktur font (not implemented in ansi.css)</td>
|
||||
<td>`jqconsole-ansi-fraktur`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>21</td>
|
||||
<td>Remove Bold and Faint effects</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>22</td>
|
||||
<td>Same as 21</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>23</td>
|
||||
<td>Remove italic and fraktur effects</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24</td>
|
||||
<td>Remove underline effect</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>25</td>
|
||||
<td>Remove blinking effect(s).</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>28</td>
|
||||
<td>Reveal text</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>29</td>
|
||||
<td>Remove line-through effect</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>30-37</td>
|
||||
<td>Set foreground color to color from the color table below</td>
|
||||
<td>jqconsole-ansi-color-{COLOR} where {COLOR} is the color name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>39</td>
|
||||
<td>Restore default foreground color</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>40-47</td>
|
||||
<td>Set background color to color from the color table below</td>
|
||||
<td>`jqconsole-ansi-background-color-{COLOR}` where {COLOR} is the color name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>49</td>
|
||||
<td>Restore default background color</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>51</td>
|
||||
<td>Adds a frame around the text</td>
|
||||
<td>`jqconsole-ansi-framed`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>53</td>
|
||||
<td>Line above text</td>
|
||||
<td>jqconsole-ansi-overline</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>54</td>
|
||||
<td>Remove frame effect</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>55</td>
|
||||
<td>Remove over-line effect</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
###Colors
|
||||
[Reference](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors).
|
||||
<table>
|
||||
<tr>
|
||||
<th>Code offset</th>
|
||||
<th>Color</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>Black</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Red</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Green</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Yellow</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Blue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Magenta</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Cyan</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td>White</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
##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/amasad)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](http://opensource.org/licenses/MIT)
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
.jqconsole-ansi-bold {
|
||||
/* font-weight: bold; */
|
||||
}
|
||||
|
||||
.jqconsole-ansi-lighter {
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.jqconsole-ansi-italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.jqconsole-ansi-underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@-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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
.jqconsole-ansi-color-red {
|
||||
color: red;
|
||||
}
|
||||
.jqconsole-ansi-color-green {
|
||||
color: green;
|
||||
}
|
||||
.jqconsole-ansi-color-yellow {
|
||||
color: yellow;
|
||||
}
|
||||
.jqconsole-ansi-color-blue {
|
||||
color: rgb(49,123,249);
|
||||
}
|
||||
.jqconsole-ansi-color-magenta {
|
||||
color: magenta;
|
||||
}
|
||||
.jqconsole-ansi-color-cyan {
|
||||
color: cyan;
|
||||
}
|
||||
.jqconsole-ansi-color-white {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.jqconsole-ansi-background-color-black {
|
||||
background-color: black;
|
||||
}
|
||||
.jqconsole-ansi-background-color-red {
|
||||
background-color: red;
|
||||
}
|
||||
.jqconsole-ansi-background-color-green {
|
||||
background-color: green;
|
||||
}
|
||||
.jqconsole-ansi-background-color-yellow {
|
||||
background-color: yellow;
|
||||
}
|
||||
.jqconsole-ansi-background-color-blue {
|
||||
background-color: blue;
|
||||
}
|
||||
.jqconsole-ansi-background-color-magenta {
|
||||
background-color: magenta;
|
||||
}
|
||||
.jqconsole-ansi-background-color-cyan {
|
||||
background-color: cyan;
|
||||
}
|
||||
.jqconsole-ansi-background-color-white {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.jqconsole-ansi-framed {
|
||||
border: 1px solid;
|
||||
}
|
||||
.jqconsole-ansi-overline {
|
||||
text-decoration: overline;
|
||||
}
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
html, body {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
font-family: monospace;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
/* The console container element */
|
||||
#console {
|
||||
height: 400px;
|
||||
width: 750px;
|
||||
position:relative;
|
||||
background-color: black;
|
||||
border: 2px solid #CCC;
|
||||
margin: 0 auto;
|
||||
margin-top: 50px;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="console"></div>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../lib/jqconsole.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
var jqconsole = $('#console').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');
|
||||
// Restart the prompt.
|
||||
startPrompt();
|
||||
});
|
||||
};
|
||||
startPrompt();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../css/ansi.css" type="text/css" media="all" />
|
||||
<style>
|
||||
html, body {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
font-family: monospace;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#console {
|
||||
height: 400px;
|
||||
width: 750px;
|
||||
position:relative;
|
||||
background-color: black;
|
||||
border: 2px solid #CCC;
|
||||
margin: 0 auto;
|
||||
margin-top: 50px;
|
||||
}
|
||||
.jqconsole {
|
||||
padding: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.jqconsole-cursor {
|
||||
background-color: #999;
|
||||
}
|
||||
.jqconsole-blurred .jqconsole-cursor {
|
||||
background-color: #666;
|
||||
}
|
||||
.jqconsole-prompt {
|
||||
color: #0d0;
|
||||
}
|
||||
.jqconsole-old-prompt {
|
||||
color: #0b0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.jqconsole-input {
|
||||
color: #dd0;
|
||||
}
|
||||
.jqconsole-old-input {
|
||||
color: #bb0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.brace {
|
||||
color: #00FFFF;
|
||||
}
|
||||
.paran {
|
||||
color: #FF00FF;
|
||||
}
|
||||
.bracket {
|
||||
color: #FFFF00;
|
||||
}
|
||||
.jqconsole-composition {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="console"></div>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../lib/jqconsole.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
// Creating the console.
|
||||
var header = 'Welcome to JQConsole!\n' +
|
||||
'Use jqconsole.Write() to write and ' +
|
||||
'jqconsole.Input() to read.\n';
|
||||
window.jqconsole = $('#console').jqconsole(header, 'JS> ');
|
||||
|
||||
// Abort prompt on Ctrl+Z.
|
||||
jqconsole.RegisterShortcut('Z', function() {
|
||||
jqconsole.AbortPrompt();
|
||||
handler();
|
||||
});
|
||||
// Move to line start Ctrl+A.
|
||||
jqconsole.RegisterShortcut('A', function() {
|
||||
jqconsole.MoveToStart();
|
||||
handler();
|
||||
});
|
||||
// Move to line end Ctrl+E.
|
||||
jqconsole.RegisterShortcut('E', function() {
|
||||
jqconsole.MoveToEnd();
|
||||
handler();
|
||||
});
|
||||
jqconsole.RegisterMatching('{', '}', 'brace');
|
||||
jqconsole.RegisterMatching('(', ')', 'paran');
|
||||
jqconsole.RegisterMatching('[', ']', 'bracket');
|
||||
// Handle a command.
|
||||
var handler = function(command) {
|
||||
if (command) {
|
||||
try {
|
||||
jqconsole.Write('==> ' + window.eval(command) + '\n');
|
||||
} catch (e) {
|
||||
jqconsole.Write('ERROR: ' + e.message + '\n');
|
||||
}
|
||||
}
|
||||
jqconsole.Prompt(true, handler, function(command) {
|
||||
// Continue line if can't compile the command.
|
||||
try {
|
||||
Function(command);
|
||||
} catch (e) {
|
||||
if (/[\[\{\(]$/.test(command)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
// Initiate the first prompt.
|
||||
handler();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "jqconsole",
|
||||
"version": "2.8.0",
|
||||
"title": "Feature complete web terminal.",
|
||||
"author": {
|
||||
"name": "Amjad Masad",
|
||||
"email": "amjad.masad@gmail.com",
|
||||
"url": "http://amasad.me"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://opensource.org/licenses/MIT"
|
||||
}
|
||||
],
|
||||
"description": "A jQuery terminal plugin with raw input/output streams as well as input and output states and support for rich multi-line prompting and operation queueing.",
|
||||
"keywords": ["terminal", "console", "emulator", "REPL", "repl.it"],
|
||||
"demo": "http://repl.it/",
|
||||
"dependencies": {
|
||||
"jquery": ">=1.5"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
module.exports = function(config) {
|
||||
config.set({
|
||||
frameworks: ["mocha"],
|
||||
files: [
|
||||
'test/vendor/*.js',
|
||||
'lib/*.js',
|
||||
'test/setup.coffee',
|
||||
'test/ansi-test.coffee',
|
||||
'test/jqconsole-test.coffee',
|
||||
'test/prompt-test.coffee',
|
||||
'test/shortcuts-test.coffee',
|
||||
'test/history-test.coffee',
|
||||
'test/matching-test.coffee',
|
||||
'test/misc-test.coffee',
|
||||
],
|
||||
browsers: ['Chrome'],
|
||||
reporters: ['dots', 'coverage'],
|
||||
preprocessors: {
|
||||
'lib/*.js': ['coverage'],
|
||||
'test/*.coffee': ['coffee']
|
||||
},
|
||||
coffeePreprocessor: {
|
||||
// options passed to the coffee compiler
|
||||
options: {
|
||||
bare: false,
|
||||
}
|
||||
},
|
||||
coverageReporter: {
|
||||
type : 'html',
|
||||
dir : 'coverage/'
|
||||
}
|
||||
});
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"name": "jq-console",
|
||||
"version": "2.10.0",
|
||||
"description": "Feature complete web terminal",
|
||||
"main": "jqconsole.min.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/karma/bin/karma start --single-run"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/replit/jq-console.git"
|
||||
},
|
||||
"keywords": [
|
||||
"jq-consoel",
|
||||
"console",
|
||||
"terminal"
|
||||
],
|
||||
"author": "amasad",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/replit/jq-console/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"karma-coffee-preprocessor": "~0.1.2",
|
||||
"mocha": "~1.17.1",
|
||||
"karma-script-launcher": "~0.1.0",
|
||||
"karma-chrome-launcher": "~0.1.2",
|
||||
"karma-firefox-launcher": "~0.1.3",
|
||||
"karma-html2js-preprocessor": "~0.1.0",
|
||||
"karma-jasmine": "~0.1.5",
|
||||
"requirejs": "~2.1.10",
|
||||
"karma-requirejs": "~0.2.1",
|
||||
"karma-phantomjs-launcher": "~0.1.1",
|
||||
"karma": "~0.10.9",
|
||||
"karma-mocha": "~0.1.1",
|
||||
"karma-coverage": "~0.1.5"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,50 +0,0 @@
|
|||
Ansi = $().jqconsole.Ansi
|
||||
|
||||
CssPre = 'jqconsole-ansi-'
|
||||
|
||||
describe 'Ansi', ->
|
||||
describe '#_style', ->
|
||||
ansi = null
|
||||
beforeEach -> ansi = new Ansi()
|
||||
|
||||
it 'applies and replaces font', ->
|
||||
ansi._style '11'
|
||||
assert.deepEqual ["#{CssPre}fonts-1"], ansi.klasses
|
||||
ansi._style '19'
|
||||
assert.deepEqual ["#{CssPre}fonts-9"], ansi.klasses
|
||||
|
||||
it 'applies and replaces color', ->
|
||||
ansi._style '31'
|
||||
assert.deepEqual ["#{CssPre}color-#{ansi._color(1)}"], ansi.klasses
|
||||
ansi._style '37'
|
||||
assert.deepEqual ["#{CssPre}color-#{ansi._color(7)}"], ansi.klasses
|
||||
ansi._style '39'
|
||||
assert.deepEqual [], ansi.klasses
|
||||
|
||||
it 'applies and replaces background-color', ->
|
||||
ansi._style '41'
|
||||
assert.deepEqual ["#{CssPre}background-color-#{ansi._color(1)}"], ansi.klasses
|
||||
ansi._style '47'
|
||||
assert.deepEqual ["#{CssPre}background-color-#{ansi._color(7)}"], ansi.klasses
|
||||
ansi._style '49'
|
||||
assert.deepEqual [], ansi.klasses
|
||||
|
||||
describe '#stylize', ->
|
||||
ansi = null
|
||||
beforeEach -> ansi = new Ansi()
|
||||
|
||||
it 'appends a styles', ->
|
||||
html = ansi.stylize 'test\x1B[1mhello'
|
||||
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold\">hello</span>"
|
||||
|
||||
it 'appends multiple styles', ->
|
||||
html = ansi.stylize 'test\x1B[1;2mhello'
|
||||
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold #{CssPre}lighter\">hello</span>"
|
||||
|
||||
it 'appends multiple styles at different intervals', ->
|
||||
html = ansi.stylize 'test\x1B[1mhello\x1B[2mhi'
|
||||
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold\">hello</span><span class=\"#{CssPre}bold #{CssPre}lighter\">hi</span>"
|
||||
html = ansi.stylize 'a\x1B[53mb\x1B[21mc\x1B[md'
|
||||
assert.equal html, "<span class=\"#{CssPre}bold #{CssPre}lighter\">a</span><span class=\"#{CssPre}bold #{CssPre}lighter #{CssPre}overline\">b</span><span class=\"#{CssPre}overline\">c</span><span class=\"\">d</span>"
|
||||
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
{jqconsole, typer: {typeA, keyDown, type}} = jqconsoleSetup()
|
||||
|
||||
describe 'History', ->
|
||||
describe '#GetHistory', ->
|
||||
it 'gets the history', ->
|
||||
jqconsole.Prompt true, ->
|
||||
typeA()
|
||||
keyDown 13
|
||||
deepEqual ['a'], jqconsole.GetHistory()
|
||||
|
||||
describe '#SetHistory', ->
|
||||
it 'sets history', ->
|
||||
h = ['a', 'b']
|
||||
jqconsole.SetHistory h
|
||||
deepEqual h, jqconsole.GetHistory()
|
||||
|
||||
describe '#ResetHistory', ->
|
||||
it 'resets the history', ->
|
||||
jqconsole.ResetHistory()
|
||||
deepEqual jqconsole.history, []
|
||||
|
||||
describe 'History interaction in the prompt', ->
|
||||
it 'gets the prev history item', ->
|
||||
jqconsole.Prompt true, ->
|
||||
type 'foo'
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
keyDown 13
|
||||
jqconsole.Prompt true, ->
|
||||
equal jqconsole.GetPromptText(), ''
|
||||
keyDown 38
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
jqconsole.AbortPrompt()
|
||||
|
||||
it 'gets the next history item', ->
|
||||
jqconsole.Prompt true, ->
|
||||
type 'foo'
|
||||
keyDown 13
|
||||
jqconsole.Prompt true, ->
|
||||
type 'bar'
|
||||
keyDown 13
|
||||
jqconsole.Prompt true, ->
|
||||
keyDown 38
|
||||
equal jqconsole.GetPromptText(), 'bar'
|
||||
keyDown 38
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
keyDown 40
|
||||
equal jqconsole.GetPromptText(), 'bar'
|
||||
keyDown 40
|
||||
equal jqconsole.GetPromptText(), ''
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Mocha</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="vendor/mocha.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="vendor/mocha.js"></script>
|
||||
<script>mocha.setup('bdd')</script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../lib/jqconsole.js"></script>
|
||||
<script src="vendor/assert.js"></script>
|
||||
<script src="vendor/coffeescript.js"></script>
|
||||
|
||||
<script>
|
||||
var tests = [ 'setup.coffee'
|
||||
, 'ansi-test.coffee'
|
||||
, 'jqconsole-test.coffee'
|
||||
, 'prompt-test.coffee'
|
||||
, 'shortcuts-test.coffee'
|
||||
, 'history-test.coffee'
|
||||
]
|
||||
tests.forEach(function (test) {
|
||||
CoffeeScript.load(test, start)
|
||||
})
|
||||
function start () {
|
||||
if (start.called == null) start.called = 0;
|
||||
if (++start.called == tests.length) {
|
||||
mocha.run();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
describe 'JQConsole', ->
|
||||
{$container, jqconsole} = jqconsoleSetup()
|
||||
describe '#constructor', ->
|
||||
|
||||
it 'instantiates', ->
|
||||
equal jqconsole.header, 'header'
|
||||
equal jqconsole.prompt_label_main, 'prompt_label'
|
||||
equal jqconsole.prompt_label_continue, 'prompt_continue'
|
||||
equal jqconsole.indent_width, 2
|
||||
equal jqconsole.GetState(), 'output'
|
||||
deepEqual jqconsole.input_queue, []
|
||||
deepEqual jqconsole.history, []
|
||||
ok jqconsole.$console.length
|
||||
ok jqconsole.$console instanceof jQuery
|
||||
equal $container.text().trim(), 'header'
|
||||
strictEqual $container.data('jqconsole'), jqconsole
|
||||
ok jqconsole.$prompt.length
|
||||
ok jqconsole.$input_source.length
|
||||
|
||||
it 'setup events', (done)->
|
||||
counter = 0
|
||||
jqconsole.$input_source.focus ->
|
||||
counter++
|
||||
jqconsole.$console.mouseup()
|
||||
fn = ->
|
||||
ok counter
|
||||
done()
|
||||
setTimeout fn, 10
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{jqconsole, createScroll, typer: {typeA, keyDown, type}} = jqconsoleSetup()
|
||||
|
||||
describe 'Matching', ->
|
||||
afterEach ->
|
||||
jqconsole.AbortPrompt()
|
||||
|
||||
describe '#RegisterMatching', ->
|
||||
it 'Adds matching', (done) ->
|
||||
jqconsole.Prompt true, ->
|
||||
jqconsole.RegisterMatching '(', ')', 'parens'
|
||||
type 'foo ( bar )'
|
||||
keyDown 39
|
||||
check = ->
|
||||
$parens = jqconsole.$prompt.find '.parens'
|
||||
assert.equal $parens.first().text(), '('
|
||||
assert.equal $parens.last().text(), ')'
|
||||
done()
|
||||
setTimeout check, 0
|
||||
|
||||
describe '#UnRegsiterMatching', ->
|
||||
it 'Removes matching', (done) ->
|
||||
jqconsole.Prompt true, ->
|
||||
jqconsole.UnRegisterMatching '(', ')'
|
||||
type 'foo ( bar )'
|
||||
keyDown 39
|
||||
check = ->
|
||||
assert.ok !jqconsole.$prompt.find('.parens').length
|
||||
done()
|
||||
setTimeout check, 0
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
jqconsole = type = keyDown = null
|
||||
|
||||
describe 'Misc methods', ->
|
||||
beforeEach ->
|
||||
{jqconsole, typer: {keyDown, type}} = jqconsoleSetup()
|
||||
jqconsole.Prompt true, ->
|
||||
|
||||
describe '#GetColumn', ->
|
||||
it 'should get the column number of the cursor', ->
|
||||
label_length = 'headerprompt_label'.length
|
||||
assert.equal jqconsole.GetColumn(), label_length
|
||||
type ' '
|
||||
assert.equal jqconsole.GetColumn(), label_length + 3
|
||||
|
||||
describe '#GetLine', ->
|
||||
it 'should get the line number of the cursor', ->
|
||||
assert.equal jqconsole.GetLine(), 0
|
||||
keyDown 13, shiftKey: on
|
||||
assert.equal jqconsole.GetLine(), 1
|
||||
keyDown 13, shiftKey: on
|
||||
assert.equal jqconsole.GetLine(), 2
|
||||
|
||||
describe '#SetIndentWidth', ->
|
||||
it 'changes the indent width', ->
|
||||
l = jqconsole.GetColumn()
|
||||
jqconsole.SetIndentWidth 10
|
||||
keyDown 9
|
||||
assert.equal jqconsole.GetColumn(), l + 10
|
||||
|
||||
describe '#GetIndentWidth', ->
|
||||
it 'gets the indent width', ->
|
||||
jqconsole.SetIndentWidth 20
|
||||
assert.equal jqconsole.GetIndentWidth(), 20
|
||||
|
||||
describe '#Dump', ->
|
||||
it 'dumps the console content', ->
|
||||
type 'foo'
|
||||
keyDown 13
|
||||
jqconsole.Write('wat')
|
||||
assert.equal jqconsole.Dump(), 'headerprompt_labelfoo\nwat'
|
||||
|
||||
describe '#SetPromptLabel', ->
|
||||
it 'Sets the prompt label for the next prompt', ->
|
||||
jqconsole.SetPromptLabel 'foobar123', 'shitmang'
|
||||
keyDown 13, shiftKey: on
|
||||
jqconsole.AbortPrompt()
|
||||
jqconsole.Prompt true, ->
|
||||
assert.ok jqconsole.Dump().indexOf 'foobar123' > -1
|
||||
assert.ok jqconsole.Dump().indexOf 'shitmang' > -1
|
||||
|
||||
describe '#Disable', ->
|
||||
it 'disables the console', ->
|
||||
jqconsole.Disable()
|
||||
assert.ok jqconsole.$input_source.attr 'disabled'
|
||||
|
||||
describe '#Enable', ->
|
||||
it 'enables the console', ->
|
||||
jqconsole.Disable()
|
||||
jqconsole.Enable()
|
||||
assert.ok not jqconsole.$input_source.attr 'disabled'
|
||||
|
||||
describe '#Clear', ->
|
||||
it 'clears the console', ->
|
||||
jqconsole.Clear()
|
||||
assert.equal jqconsole.Dump(), ''
|
||||
|
|
@ -1,400 +0,0 @@
|
|||
{jqconsole, createScroll, typer: {typeA, keyDown, type}} = jqconsoleSetup()
|
||||
|
||||
describe 'Prompt Interaction', ->
|
||||
describe '#Prompt', ->
|
||||
after ->
|
||||
jqconsole.AbortPrompt()
|
||||
|
||||
it 'inits prompt and auto-focuses', ->
|
||||
counter = 0
|
||||
jqconsole.$input_source.focus ->
|
||||
counter++
|
||||
resultCb = ->
|
||||
jqconsole.Prompt true, resultCb
|
||||
equal jqconsole.GetState(), 'prompt'
|
||||
ok counter
|
||||
ok jqconsole.history_active
|
||||
strictEqual jqconsole.input_callback, resultCb
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label'
|
||||
|
||||
describe '#AbortPrompt', ->
|
||||
it 'aborts the prompt', ->
|
||||
jqconsole.Prompt true, ->
|
||||
jqconsole.AbortPrompt()
|
||||
equal jqconsole.$prompt.text().trim(), ''
|
||||
|
||||
it 'restarts queued prompts', ->
|
||||
aCb = ->
|
||||
jqconsole.Prompt false, aCb
|
||||
bCb = ->
|
||||
jqconsole.Prompt true, bCb
|
||||
strictEqual jqconsole.input_callback, aCb
|
||||
strictEqual jqconsole.history_active, false
|
||||
jqconsole.AbortPrompt()
|
||||
strictEqual jqconsole.input_callback, bCb
|
||||
strictEqual jqconsole.history_active, true
|
||||
jqconsole.AbortPrompt()
|
||||
|
||||
describe '#GetPromptText', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'gets the current prompt text', ->
|
||||
type 'foo'
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_labelfoo'
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
|
||||
it 'gets the current prompt text with the label', ->
|
||||
type 'foo'
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_labelfoo'
|
||||
equal jqconsole.GetPromptText(true), 'prompt_labelfoo'
|
||||
|
||||
describe '#ClearPromptText', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'Clears the current prompt text', ->
|
||||
type 'foo'
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
jqconsole.ClearPromptText()
|
||||
equal jqconsole.GetPromptText(), ''
|
||||
|
||||
it 'Clears prompt text with label', ->
|
||||
type 'foo'
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
jqconsole.ClearPromptText true
|
||||
equal jqconsole.GetPromptText(true), ''
|
||||
|
||||
describe '#SetPromptText', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'sets the current prompt text', ->
|
||||
type 'bar'
|
||||
jqconsole.SetPromptText('foo')
|
||||
equal jqconsole.GetPromptText(), 'foo'
|
||||
|
||||
describe 'Moving', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'moves to the left', ->
|
||||
type 'xyz'
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xy'
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), 'x'
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), ''
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), ''
|
||||
|
||||
it 'moves to the right', ->
|
||||
type 'xyz'
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), 'x'
|
||||
keyDown 39
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xy'
|
||||
keyDown 39
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
keyDown 39
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
|
||||
it 'moves to the prev line when at the first char of the line moving left', ->
|
||||
type 'xyz'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'abc'
|
||||
equal jqconsole.$prompt_left.text().trim(), 'abc'
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
|
||||
it 'moves to the next line when at the last char of the line moving right', ->
|
||||
type 'xyz'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'abc'
|
||||
equal jqconsole.$prompt_left.text().trim(), 'abc'
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
keyDown 39
|
||||
equal jqconsole.$prompt_right.text().trim(), 'abc'
|
||||
|
||||
it 'moves to the start of the word', ->
|
||||
type 'xyz abc'
|
||||
keyDown 37, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'abc'
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
|
||||
it 'moves to the end of the word', ->
|
||||
type 'xyz abc'
|
||||
keyDown 37, metaKey: on
|
||||
keyDown 37, metaKey: on
|
||||
keyDown 39, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'abc'
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
|
||||
it 'moves to the end of the word', ->
|
||||
type 'xyz abc'
|
||||
keyDown 37, metaKey: on
|
||||
keyDown 37, metaKey: on
|
||||
keyDown 39, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'abc'
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz'
|
||||
|
||||
it 'moves to the start of the line', ->
|
||||
type 'xyz abc'
|
||||
keyDown 36
|
||||
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
|
||||
|
||||
it 'moves to the end of the line', ->
|
||||
type 'xyz abc'
|
||||
keyDown 36
|
||||
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
|
||||
keyDown 35
|
||||
equal jqconsole.$prompt_right.text().trim(), ''
|
||||
equal jqconsole.$prompt_left.text().trim(), 'xyz abc'
|
||||
|
||||
it 'moves to the start of the prompt', ->
|
||||
type 'xyz abc'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'hafm olim'
|
||||
keyDown 36, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
|
||||
equal jqconsole.$prompt_after.text().trim(), 'prompt_continuehafm olim'
|
||||
|
||||
it 'moves to the end of the prompt', ->
|
||||
type 'xyz abc'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'hafm olim'
|
||||
keyDown 36, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
|
||||
equal jqconsole.$prompt_after.text().trim(), 'prompt_continuehafm olim'
|
||||
keyDown 35, metaKey: on
|
||||
equal jqconsole.$prompt_left.text().trim(), 'hafm olim'
|
||||
equal jqconsole.$prompt_before.text().trim(), 'prompt_labelxyz abc'
|
||||
|
||||
it 'moves up one line', ->
|
||||
type 'xyz'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'a'
|
||||
keyDown 38, shiftKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'yz'
|
||||
|
||||
it 'moves down one line', ->
|
||||
type 'xyz'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'a'
|
||||
# Meta key also works.
|
||||
keyDown 38, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'yz'
|
||||
keyDown 40, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), ''
|
||||
|
||||
it 'respects the column when moving vertically', ->
|
||||
type 'xyz'
|
||||
keyDown 13, shiftKey: on
|
||||
type 'ab'
|
||||
keyDown 38, shiftKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'z'
|
||||
keyDown 40, shiftKey: on
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_right.text().trim(), 'ab'
|
||||
keyDown 38, shiftKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), 'xyz'
|
||||
|
||||
describe 'Control Keys', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'handles enter', ->
|
||||
jqconsole.AbortPrompt()
|
||||
counter = 0
|
||||
jqconsole.Prompt true, -> counter++
|
||||
typeA()
|
||||
keyDown 13
|
||||
ok counter
|
||||
equal jqconsole.$console.find('.jqconsole-old-prompt').last().text().trim(), 'prompt_labela'
|
||||
# Restart the prompt for other tests.
|
||||
jqconsole.Prompt true, ->
|
||||
|
||||
it 'handles shift+enter', ->
|
||||
keyDown 13, shiftKey: on
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label \nprompt_continue'
|
||||
|
||||
it 'handles tab', ->
|
||||
typeA()
|
||||
keyDown 9
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label a'
|
||||
|
||||
it 'handles shift+tab', ->
|
||||
typeA()
|
||||
keyDown 9, shiftKey: on
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_labela'
|
||||
|
||||
it 'backspace', ->
|
||||
typeA()
|
||||
keyDown 8
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label'
|
||||
|
||||
it 'cntrl+backspace', ->
|
||||
typeA()
|
||||
typeA()
|
||||
keyDown 8, metaKey: on
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label'
|
||||
|
||||
it 'deletes a char', ->
|
||||
type 'xyz'
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_right.text().trim(), 'z'
|
||||
keyDown 46
|
||||
equal jqconsole.$prompt_right.text().trim(), ''
|
||||
|
||||
it 'deletes a word', ->
|
||||
type 'xyz abc'
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
keyDown 37
|
||||
equal jqconsole.$prompt_right.text().trim(), 'abc'
|
||||
keyDown 46, metaKey: on
|
||||
equal jqconsole.$prompt_right.text().trim(), ''
|
||||
|
||||
describe 'scrolling', ->
|
||||
console_height = null
|
||||
_fast = null
|
||||
|
||||
before ->
|
||||
jQuery.fx.speeds.fast = 10
|
||||
after ->
|
||||
jQuery.fx.speeds.fast = _fast
|
||||
|
||||
beforeEach ->
|
||||
jqconsole.Reset()
|
||||
jqconsole.Prompt true, ->
|
||||
# Make sure the console has a scroll.
|
||||
{ console_height } = createScroll()
|
||||
|
||||
it 'scrolls up', (done) ->
|
||||
before = jqconsole.$container[0].scrollTop
|
||||
keyDown 33
|
||||
cb = ->
|
||||
equal jqconsole.$container[0].scrollTop, before - console_height
|
||||
done()
|
||||
# * 2 is some arbitrary number otherwise it fails.
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
|
||||
it 'scrolls up twice', (done) ->
|
||||
before = jqconsole.$container[0].scrollTop
|
||||
keyDown 33
|
||||
cb = ->
|
||||
keyDown 33
|
||||
cb = ->
|
||||
equal jqconsole.$container[0].scrollTop, before - (console_height * 2)
|
||||
done()
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
# * 2 is some arbitrary number otherwise it fails.
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
|
||||
it 'scrolls down', (done) ->
|
||||
before = jqconsole.$container[0].scrollTop
|
||||
keyDown 33
|
||||
cb = ->
|
||||
keyDown 34
|
||||
cb = ->
|
||||
equal jqconsole.$container[0].scrollTop, before
|
||||
done()
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
# * 2 is some arbitrary number otherwise it fails.
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
|
||||
describe 'Typing', ->
|
||||
beforeEach -> jqconsole.Prompt true, ->
|
||||
afterEach -> jqconsole.AbortPrompt()
|
||||
|
||||
it 'handles chars', ->
|
||||
str = ''
|
||||
test = (ch) ->
|
||||
str += ch
|
||||
e = $.Event('keypress')
|
||||
e.which = ch.charCodeAt(0)
|
||||
jqconsole.$input_source.trigger e
|
||||
equal jqconsole.$prompt.text().trim(), 'prompt_label' + str
|
||||
|
||||
test 'a'
|
||||
test 'Z'
|
||||
test '$'
|
||||
test 'ƒ'
|
||||
|
||||
it 'scrolls all the way down when typing', (done) ->
|
||||
createScroll()
|
||||
keyDown 33
|
||||
cb = ->
|
||||
before = jqconsole.$container[0].scrollTop
|
||||
type('a')
|
||||
cb = ->
|
||||
notEqual jqconsole.$container[0].scrollTop, before
|
||||
done()
|
||||
setTimeout cb, 0
|
||||
setTimeout cb, jQuery.fx.speeds.fast * 2
|
||||
|
||||
describe 'Multiline', ->
|
||||
beforeEach ->
|
||||
if jqconsole.GetState() is 'prompt'
|
||||
jqconsole.AbortPrompt()
|
||||
|
||||
it 'executes multiline callback', (done) ->
|
||||
jqconsole.Prompt true, (-> ), ->
|
||||
done()
|
||||
type('foo')
|
||||
keyDown 13
|
||||
|
||||
it 'indents', ->
|
||||
jqconsole.Prompt true, (-> ), ->
|
||||
return 2
|
||||
type('foo')
|
||||
keyDown 13
|
||||
equal jqconsole.GetState(), 'prompt'
|
||||
equal jqconsole.GetPromptText(), 'foo\n '
|
||||
|
||||
it 'keeps indentation on shift+enter', ->
|
||||
jqconsole.Prompt true, (-> ), ->
|
||||
return 2
|
||||
type('foo')
|
||||
keyDown 9
|
||||
keyDown 13, shiftKey: on
|
||||
equal jqconsole.GetState(), 'prompt'
|
||||
equal jqconsole.GetPromptText(), ' foo\n '
|
||||
|
||||
it 'unindents', ->
|
||||
jqconsole.Prompt true, (-> ), ->
|
||||
return -2
|
||||
type('foo')
|
||||
keyDown 9
|
||||
keyDown 13
|
||||
equal jqconsole.GetPromptText(), ' foo\n'
|
||||
|
||||
it 'skip indent callback', (done) ->
|
||||
jqconsole.Prompt true, done.bind(null, null), ->
|
||||
return false
|
||||
type('foo')
|
||||
keyDown 13
|
||||
|
||||
it 'handles async treatment', (done) ->
|
||||
jqconsole.Prompt true, done.bind(null, null), ((text, cb) -> cb false), on
|
||||
type('foo')
|
||||
keyDown 13
|
||||
|
||||
describe '#Input', ->
|
||||
it 'should enable history', (done) ->
|
||||
jqconsole.Prompt true, done.bind(null, null)
|
||||
jqconsole.Input (text) ->
|
||||
assert.equal text, 'foo'
|
||||
setTimeout (-> keyDown(13)), 0
|
||||
type 'foo'
|
||||
keyDown 13
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
window.equal = assert.equal
|
||||
window.notEqual = assert.notEqual
|
||||
window.deepEqual = assert.deepEqual
|
||||
window.strictEqual = assert.strictEqual
|
||||
window.ok = assert.ok
|
||||
JQConsole = $().jqconsole.JQConsole
|
||||
|
||||
window.jqconsoleSetup = ->
|
||||
$container = $('<div/>').css
|
||||
height: '100px'
|
||||
widht: '200px'
|
||||
position: 'relative'
|
||||
$container.appendTo('body')
|
||||
jqconsole = new JQConsole($container, 'header', 'prompt_label', 'prompt_continue')
|
||||
typer =
|
||||
typeA: ->
|
||||
e = $.Event('keypress')
|
||||
e.which = 'a'.charCodeAt(0)
|
||||
jqconsole.$input_source.trigger e
|
||||
|
||||
keyDown: (code, options = {}) ->
|
||||
e = $.Event('keydown')
|
||||
e.which = code
|
||||
e[k] = v for k, v of options
|
||||
jqconsole.$input_source.trigger e
|
||||
|
||||
type: (str) ->
|
||||
type = (chr) ->
|
||||
e = $.Event('keypress')
|
||||
e.which = chr.charCodeAt(0)
|
||||
jqconsole.$input_source.trigger(e)
|
||||
type chr for chr in str
|
||||
|
||||
createScroll = ->
|
||||
line_height = jqconsole.$prompt.height()
|
||||
console_height = jqconsole.$container.height()
|
||||
lines_per_page = Math.ceil(console_height / line_height)
|
||||
for i in [0..lines_per_page * 5]
|
||||
jqconsole.SetPromptText('foo')
|
||||
jqconsole._HandleEnter()
|
||||
jqconsole.Prompt true, ->
|
||||
{line_height, console_height, lines_per_page}
|
||||
|
||||
{$container, jqconsole, typer, createScroll}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{jqconsole, typer: {keyDown}} = jqconsoleSetup()
|
||||
|
||||
describe 'Shortcuts', ->
|
||||
describe '#RegisterShortcut', ->
|
||||
# Fails in v2.7.7
|
||||
it 'throws if callback not function', ->
|
||||
assert.throws ->
|
||||
jqconsole.RegisterShortcut 'b', 'c'
|
||||
|
||||
it 'registers shortcut by string', ->
|
||||
cb = ->
|
||||
jqconsole.RegisterShortcut 'a', cb
|
||||
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], [cb]
|
||||
deepEqual jqconsole.shortcuts['A'.charCodeAt(0)], [cb]
|
||||
|
||||
it 'registers shortcut by charcode', ->
|
||||
cb = ->
|
||||
jqconsole.RegisterShortcut 'c'.charCodeAt(0), cb
|
||||
deepEqual jqconsole.shortcuts['c'.charCodeAt(0)], [cb]
|
||||
deepEqual jqconsole.shortcuts['C'.charCodeAt(0)], [cb]
|
||||
|
||||
it 'shortcuts must be ascii', ->
|
||||
assert.throws ->
|
||||
jqconsole.RegisterShortcut 'ƒ', ->
|
||||
|
||||
describe '#UnRegisterShortcut', ->
|
||||
|
||||
it 'removes all callback for a shortcut', ->
|
||||
cb = ->
|
||||
jqconsole.RegisterShortcut 'a', cb
|
||||
jqconsole.UnRegisterShortcut 'a'
|
||||
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], undefined
|
||||
|
||||
it 'removes specific callback', ->
|
||||
aCb = ->
|
||||
bCb = ->
|
||||
jqconsole.RegisterShortcut 'a', aCb
|
||||
jqconsole.RegisterShortcut 'a', bCb
|
||||
jqconsole.UnRegisterShortcut 'a', aCb
|
||||
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], [bCb]
|
||||
|
||||
describe '#ResetShortcuts', ->
|
||||
|
||||
it 'resets all shortcuts', ->
|
||||
cb1 = ->
|
||||
cb2 = ->
|
||||
jqconsole.RegisterShortcut 'a', cb1
|
||||
jqconsole.RegisterShortcut 'b', cb2
|
||||
jqconsole.ResetShortcuts()
|
||||
deepEqual jqconsole.shortcuts, {}
|
||||
|
||||
describe 'Invoking Shortcuts', ->
|
||||
it 'invokes shortcuts', ->
|
||||
jqconsole.Prompt true, ->
|
||||
counter = 0
|
||||
jqconsole.RegisterShortcut 'a', ->
|
||||
strictEqual this, jqconsole
|
||||
counter++
|
||||
keyDown 'a'.charCodeAt(0), metaKey: on
|
||||
ok counter
|
||||
369
lib/client/console/test/vendor/assert.js
vendored
369
lib/client/console/test/vendor/assert.js
vendored
|
|
@ -1,369 +0,0 @@
|
|||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
||||
//
|
||||
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
||||
//
|
||||
// Copyright (c) 2011 Jxck
|
||||
//
|
||||
// Originally from node.js (http://nodejs.org)
|
||||
// Copyright Joyent, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the 'Software'), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
(function(global) {
|
||||
|
||||
// Object.create compatible in IE
|
||||
var create = Object.create || function(p) {
|
||||
if (!p) throw Error('no type');
|
||||
function f() {};
|
||||
f.prototype = p;
|
||||
return new f();
|
||||
};
|
||||
|
||||
// UTILITY
|
||||
var util = {
|
||||
inherits: function(ctor, superCtor) {
|
||||
ctor.super_ = superCtor;
|
||||
ctor.prototype = create(superCtor.prototype, {
|
||||
constructor: {
|
||||
value: ctor,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var pSlice = Array.prototype.slice;
|
||||
|
||||
// 1. The assert module provides functions that throw
|
||||
// AssertionError's when particular conditions are not met. The
|
||||
// assert module must conform to the following interface.
|
||||
|
||||
var assert = ok;
|
||||
|
||||
global['assert'] = assert;
|
||||
|
||||
if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
module.exports = assert;
|
||||
};
|
||||
|
||||
// 2. The AssertionError is defined in assert.
|
||||
// new assert.AssertionError({ message: message,
|
||||
// actual: actual,
|
||||
// expected: expected })
|
||||
|
||||
assert.AssertionError = function AssertionError(options) {
|
||||
this.name = 'AssertionError';
|
||||
this.message = options.message || (options.actual + ' ' + options.operator + ' ' +options.expected)
|
||||
this.actual = options.actual;
|
||||
this.expected = options.expected;
|
||||
this.operator = options.operator;
|
||||
var stackStartFunction = options.stackStartFunction || fail;
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, stackStartFunction);
|
||||
}
|
||||
};
|
||||
util.inherits(assert.AssertionError, Error);
|
||||
|
||||
function replacer(key, value) {
|
||||
if (value === undefined) {
|
||||
return '' + value;
|
||||
}
|
||||
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
|
||||
return value.toString();
|
||||
}
|
||||
if (typeof value === 'function' || value instanceof RegExp) {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function truncate(s, n) {
|
||||
if (typeof s == 'string') {
|
||||
return s.length < n ? s : s.slice(0, n);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
assert.AssertionError.prototype.toString = function() {
|
||||
if (this.message) {
|
||||
return [this.name + ':', this.message].join(' ');
|
||||
} else {
|
||||
return [
|
||||
this.name + ':',
|
||||
truncate(JSON.stringify(this.actual, replacer), 128),
|
||||
this.operator,
|
||||
truncate(JSON.stringify(this.expected, replacer), 128)
|
||||
].join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
// assert.AssertionError instanceof Error
|
||||
|
||||
assert.AssertionError.__proto__ = Error.prototype;
|
||||
|
||||
// At present only the three keys mentioned above are used and
|
||||
// understood by the spec. Implementations or sub modules can pass
|
||||
// other keys to the AssertionError's constructor - they will be
|
||||
// ignored.
|
||||
|
||||
// 3. All of the following functions must throw an AssertionError
|
||||
// when a corresponding condition is not met, with a message that
|
||||
// may be undefined if not provided. All assertion methods provide
|
||||
// both the actual and expected values to the assertion error for
|
||||
// display purposes.
|
||||
|
||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
||||
throw new assert.AssertionError({
|
||||
message: message,
|
||||
actual: actual,
|
||||
expected: expected,
|
||||
operator: operator,
|
||||
stackStartFunction: stackStartFunction
|
||||
});
|
||||
}
|
||||
|
||||
// EXTENSION! allows for well behaved errors defined elsewhere.
|
||||
assert.fail = fail;
|
||||
|
||||
// 4. Pure assertion tests whether a value is truthy, as determined
|
||||
// by !!guard.
|
||||
// assert.ok(guard, message_opt);
|
||||
// This statement is equivalent to assert.equal(true, !!guard,
|
||||
// message_opt);. To test strictly for the value true, use
|
||||
// assert.strictEqual(true, guard, message_opt);.
|
||||
|
||||
function ok(value, message) {
|
||||
if (!!!value) fail(value, true, message, '==', assert.ok);
|
||||
}
|
||||
assert.ok = ok;
|
||||
|
||||
// 5. The equality assertion tests shallow, coercive equality with
|
||||
// ==.
|
||||
// assert.equal(actual, expected, message_opt);
|
||||
|
||||
assert.equal = function equal(actual, expected, message) {
|
||||
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
||||
};
|
||||
|
||||
// 6. The non-equality assertion tests for whether two objects are not equal
|
||||
// with != assert.notEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notEqual = function notEqual(actual, expected, message) {
|
||||
if (actual == expected) {
|
||||
fail(actual, expected, message, '!=', assert.notEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 7. The equivalence assertion tests a deep equality relation.
|
||||
// assert.deepEqual(actual, expected, message_opt);
|
||||
|
||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
||||
if (!_deepEqual(actual, expected)) {
|
||||
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
||||
}
|
||||
};
|
||||
|
||||
function _deepEqual(actual, expected) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
|
||||
// } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
||||
// if (actual.length != expected.length) return false;
|
||||
//
|
||||
// for (var i = 0; i < actual.length; i++) {
|
||||
// if (actual[i] !== expected[i]) return false;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//
|
||||
// 7.2. If the expected value is a Date object, the actual value is
|
||||
// equivalent if it is also a Date object that refers to the same time.
|
||||
} else if (actual instanceof Date && expected instanceof Date) {
|
||||
return actual.getTime() === expected.getTime();
|
||||
|
||||
// 7.3 If the expected value is a RegExp object, the actual value is
|
||||
// equivalent if it is also a RegExp object with the same source and
|
||||
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
||||
} else if (actual instanceof RegExp && expected instanceof RegExp) {
|
||||
return actual.source === expected.source &&
|
||||
actual.global === expected.global &&
|
||||
actual.multiline === expected.multiline &&
|
||||
actual.lastIndex === expected.lastIndex &&
|
||||
actual.ignoreCase === expected.ignoreCase;
|
||||
|
||||
// 7.4. Other pairs that do not both pass typeof value == 'object',
|
||||
// equivalence is determined by ==.
|
||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
||||
return actual == expected;
|
||||
|
||||
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
function isArguments(object) {
|
||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
||||
}
|
||||
|
||||
function objEquiv(a, b) {
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
||||
return false;
|
||||
// an identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) return false;
|
||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
||||
// Converting to array solves the problem.
|
||||
if (isArguments(a)) {
|
||||
if (!isArguments(b)) {
|
||||
return false;
|
||||
}
|
||||
a = pSlice.call(a);
|
||||
b = pSlice.call(b);
|
||||
return _deepEqual(a, b);
|
||||
}
|
||||
try {
|
||||
var ka = Object.keys(a),
|
||||
kb = Object.keys(b),
|
||||
key, i;
|
||||
} catch (e) {//happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length != kb.length)
|
||||
return false;
|
||||
//the same set of keys (although not necessarily the same order),
|
||||
ka.sort();
|
||||
kb.sort();
|
||||
//~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
if (ka[i] != kb[i])
|
||||
return false;
|
||||
}
|
||||
//equivalent values for every corresponding key, and
|
||||
//~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
if (!_deepEqual(a[key], b[key])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 8. The non-equivalence assertion tests for any deep inequality.
|
||||
// assert.notDeepEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
||||
if (_deepEqual(actual, expected)) {
|
||||
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
||||
// assert.strictEqual(actual, expected, message_opt);
|
||||
|
||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
||||
if (actual !== expected) {
|
||||
fail(actual, expected, message, '===', assert.strictEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 10. The strict non-equality assertion tests for strict inequality, as
|
||||
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||
if (actual === expected) {
|
||||
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
||||
}
|
||||
};
|
||||
|
||||
function expectedException(actual, expected) {
|
||||
if (!actual || !expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected instanceof RegExp) {
|
||||
return expected.test(actual);
|
||||
} else if (actual instanceof expected) {
|
||||
return true;
|
||||
} else if (expected.call({}, actual) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function _throws(shouldThrow, block, expected, message) {
|
||||
var actual;
|
||||
|
||||
if (typeof expected === 'string') {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
try {
|
||||
block();
|
||||
} catch (e) {
|
||||
actual = e;
|
||||
}
|
||||
|
||||
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
||||
(message ? ' ' + message : '.');
|
||||
|
||||
if (shouldThrow && !actual) {
|
||||
fail('Missing expected exception' + message);
|
||||
}
|
||||
|
||||
if (!shouldThrow && expectedException(actual, expected)) {
|
||||
fail('Got unwanted exception' + message);
|
||||
}
|
||||
|
||||
if ((shouldThrow && actual && expected &&
|
||||
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
||||
throw actual;
|
||||
}
|
||||
}
|
||||
|
||||
// 11. Expected to throw an error:
|
||||
// assert.throws(block, Error_opt, message_opt);
|
||||
|
||||
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
||||
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
||||
};
|
||||
|
||||
// EXTENSION! This is annoying to write outside this module.
|
||||
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
||||
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
||||
};
|
||||
|
||||
assert.ifError = function(err) { if (err) {throw err;}};
|
||||
|
||||
})(this);
|
||||
12
lib/client/console/test/vendor/coffeescript.js
vendored
12
lib/client/console/test/vendor/coffeescript.js
vendored
File diff suppressed because one or more lines are too long
9111
lib/client/console/test/vendor/jquery-2.1.0.js
vendored
9111
lib/client/console/test/vendor/jquery-2.1.0.js
vendored
File diff suppressed because it is too large
Load diff
241
lib/client/console/test/vendor/mocha.css
vendored
241
lib/client/console/test/vendor/mocha.css
vendored
|
|
@ -1,241 +0,0 @@
|
|||
@charset "utf-8";
|
||||
|
||||
body {
|
||||
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
padding: 60px 50px;
|
||||
}
|
||||
|
||||
#mocha ul, #mocha li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#mocha ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#mocha h1, #mocha h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mocha h1 {
|
||||
margin-top: 15px;
|
||||
font-size: 1em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
#mocha h1 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha h1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#mocha .suite .suite h1 {
|
||||
margin-top: 0;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#mocha .suite {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test {
|
||||
margin-left: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#mocha .test.pending:hover h2::after {
|
||||
content: '(pending)';
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #C09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #B94A48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
content: '✓';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #00d6b2;
|
||||
}
|
||||
|
||||
#mocha .test.pass .duration {
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: white;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.pending::before {
|
||||
content: '◦';
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.fail {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test.fail pre {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha .test.fail::before {
|
||||
content: '✖';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre.error {
|
||||
color: #c00;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#mocha .test pre {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-border-radius: 3px;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
-moz-border-radius: 3px;
|
||||
-moz-box-shadow: 0 1px 3px #eee;
|
||||
}
|
||||
|
||||
#mocha .test h2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mocha .test a.replay {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 0;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
font-size: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
-webkit-transition: opacity 200ms;
|
||||
-moz-transition: opacity 200ms;
|
||||
transition: opacity 200ms;
|
||||
opacity: 0.3;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha .test:hover a.replay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#mocha-report.pass .test.fail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.fail .test.pass {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-error {
|
||||
color: #c00;
|
||||
font-size: 1.5 em;
|
||||
font-weight: 100;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#mocha-stats {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha-stats .progress {
|
||||
float: right;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#mocha-stats em {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha-stats a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha-stats a:hover {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#mocha-stats li {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
list-style: none;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
code .comment { color: #ddd }
|
||||
code .init { color: #2F6FAD }
|
||||
code .string { color: #5890AD }
|
||||
code .keyword { color: #8A6343 }
|
||||
code .number { color: #2F6FAD }
|
||||
|
||||
@media screen and (max-device-width: 480px) {
|
||||
body {
|
||||
padding: 60px 0px;
|
||||
}
|
||||
|
||||
#stats {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
5341
lib/client/console/test/vendor/mocha.js
vendored
5341
lib/client/console/test/vendor/mocha.js
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -277,7 +277,7 @@ var CloudCmd, Util, DOM;
|
|||
if (shift)
|
||||
obj = CloudCmd.Terminal;
|
||||
else
|
||||
obj = CloudCmd.Console;
|
||||
obj = CloudCmd.Konsole;
|
||||
|
||||
obj.show();
|
||||
Events.preventDefault(event);
|
||||
|
|
|
|||
84
lib/client/konsole.js
Normal file
84
lib/client/konsole.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
var CloudCmd, Util, join, DOM, Console;
|
||||
|
||||
(function(CloudCmd, Util, join, DOM) {
|
||||
'use strict';
|
||||
|
||||
CloudCmd.Konsole = ConsoleProto;
|
||||
|
||||
function ConsoleProto() {
|
||||
var Name = 'Konsole',
|
||||
Element,
|
||||
|
||||
Images = DOM.Images,
|
||||
Dialog = DOM.Dialog,
|
||||
|
||||
Konsole = this;
|
||||
|
||||
function init() {
|
||||
Images.showLoad({top:true});
|
||||
|
||||
Util.exec.series([
|
||||
DOM.loadJquery,
|
||||
CloudCmd.View,
|
||||
load,
|
||||
create,
|
||||
show,
|
||||
]);
|
||||
|
||||
Element = DOM.load({
|
||||
name : 'div',
|
||||
className : 'console'
|
||||
});
|
||||
}
|
||||
|
||||
this.hide = function() {
|
||||
CloudCmd.View.hide();
|
||||
};
|
||||
|
||||
this.clear = function() {
|
||||
Console.clear();
|
||||
};
|
||||
|
||||
function create(callback) {
|
||||
Console(Element, function() {
|
||||
Util.exec(callback);
|
||||
});
|
||||
|
||||
Console.addShortCuts({
|
||||
'P': function() {
|
||||
var command = Console.getPromptText();
|
||||
|
||||
command += DOM.getCurrentDirPath();
|
||||
Console.setPromptText(command);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function show(callback) {
|
||||
CloudCmd.View.show(Element, {
|
||||
afterShow: function() {
|
||||
Console.focus();
|
||||
Util.exec(callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function load(callback) {
|
||||
DOM.load.js('/console/console.js', function(error) {
|
||||
if (error) {
|
||||
Dialog.alert(error.message);
|
||||
Konsole.show = init;
|
||||
} else {
|
||||
Util.timeEnd(Name + ' load');
|
||||
Util.exec(callback);
|
||||
Konsole.show = show;
|
||||
}
|
||||
});
|
||||
|
||||
Util.time(Name + ' load');
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
})(CloudCmd, Util, join, DOM);
|
||||
|
|
@ -27,15 +27,36 @@
|
|||
|
||||
minify = require(DIR_SERVER + 'minify'),
|
||||
Socket = require(DIR_SERVER + 'socket'),
|
||||
Console = require(DIR_SERVER + 'console'),
|
||||
|
||||
Terminal = !WIN ? require(DIR_SERVER + 'terminal') : function() {},
|
||||
join = require(DIR_SERVER + 'join'),
|
||||
ponse = require(DIR_SERVER + 'ponse'),
|
||||
express = require(DIR_SERVER + 'express'),
|
||||
|
||||
expressApp,
|
||||
emptyFunc = function(req, res, next) {
|
||||
Util.exec(next);
|
||||
},
|
||||
|
||||
Rest, Route;
|
||||
Console, expressApp, Rest, Route;
|
||||
|
||||
emptyFunc.middle = function() {
|
||||
return emptyFunc;
|
||||
};
|
||||
|
||||
Console = tryRequire('console-io') || emptyFunc;
|
||||
|
||||
function tryRequire(name) {
|
||||
var module, error;
|
||||
|
||||
error = Util.exec.try(function() {
|
||||
module = require(name);
|
||||
});
|
||||
|
||||
if (error)
|
||||
Util.log(error.message);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* start server function
|
||||
|
|
@ -112,10 +133,13 @@
|
|||
funcs = [
|
||||
Rest,
|
||||
Route,
|
||||
|
||||
join({
|
||||
minify: isMinify
|
||||
}),
|
||||
|
||||
Console.middle('/console', isMinify),
|
||||
|
||||
minify({
|
||||
dir : DIR,
|
||||
log : true,
|
||||
|
|
@ -169,8 +193,12 @@
|
|||
|
||||
if (socket) {
|
||||
status = 'on';
|
||||
Console(socket);
|
||||
Terminal();
|
||||
|
||||
Console({
|
||||
socket: socket
|
||||
});
|
||||
|
||||
Terminal(socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
var DIR = '../',
|
||||
DIR_SERVER = './',
|
||||
|
||||
Util = require(DIR + 'util'),
|
||||
CloudFunc = require(DIR + 'cloudfunc'),
|
||||
|
||||
socket = require(DIR_SERVER + 'socket'),
|
||||
spawnify = require(DIR_SERVER + 'spawnify'),
|
||||
|
||||
Clients = [],
|
||||
addNewLine = CloudFunc.addNewLine,
|
||||
|
||||
ConNum = 0,
|
||||
|
||||
CWD = process.cwd(),
|
||||
|
||||
CHANNEL = CloudFunc.CHANNEL_CONSOLE;
|
||||
|
||||
module.exports = function(io, onMsg) {
|
||||
socket.on('connection', io, function(clientSocket) {
|
||||
onConnection(clientSocket, onMsg, function(error, json) {
|
||||
socket.emit(CHANNEL, json, clientSocket);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function onConnection(clientSocket, onMsg, callback) {
|
||||
var msg, onDisconnect, onMessage;
|
||||
|
||||
if (!callback) {
|
||||
callback = onMsg;
|
||||
onMsg = null;
|
||||
}
|
||||
|
||||
Util.checkArgs([clientSocket, callback], ['clientSocket', 'callback']);
|
||||
|
||||
++ConNum;
|
||||
|
||||
if (!Clients[ConNum]) {
|
||||
msg = log(ConNum, 'console connected');
|
||||
|
||||
if (onMsg)
|
||||
onMsg('cd .', callback);
|
||||
else
|
||||
callback(null, {
|
||||
stdout : addNewLine(msg),
|
||||
path : CWD
|
||||
});
|
||||
|
||||
Clients[ConNum] = {
|
||||
cwd : CWD
|
||||
},
|
||||
|
||||
onMessage = function(command) {
|
||||
log(ConNum, command);
|
||||
|
||||
if (onMsg)
|
||||
onMsg(command, callback);
|
||||
else
|
||||
spawnify(command, Clients[ConNum], callback);
|
||||
},
|
||||
onDisconnect = function(conNum) {
|
||||
Clients[conNum] = null;
|
||||
|
||||
log(conNum, 'console disconnected');
|
||||
|
||||
socket.removeListener(CHANNEL, clientSocket, onMessage);
|
||||
socket.removeListener('disconnect', clientSocket, onDisconnect);
|
||||
}.bind(null, ConNum);
|
||||
|
||||
socket.on(CHANNEL, clientSocket, onMessage);
|
||||
socket.on('disconnect', clientSocket, onDisconnect);
|
||||
} else {
|
||||
msg = log(ConNum, ' in use. Reconnecting...\n');
|
||||
|
||||
callback(null, {
|
||||
stdout: msg
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
function log(connNum, str, typeParam) {
|
||||
var ret,
|
||||
type = ' ';
|
||||
|
||||
if (str) {
|
||||
|
||||
if (typeParam)
|
||||
type += typeParam + ':';
|
||||
|
||||
ret = 'client #' + connNum + type + str;
|
||||
|
||||
Util.log(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
Util = require('../util');
|
||||
|
||||
module.exports = function(card, callback) {
|
||||
var dir = path.dirname(card),
|
||||
nameCard = path.basename(card),
|
||||
regExp = Util.getRegExp(nameCard);
|
||||
|
||||
if (!callback)
|
||||
throw(Error('Callback is absent!'));
|
||||
|
||||
fs.readdir(dir, function(error, names) {
|
||||
var result = [];
|
||||
|
||||
if (!error)
|
||||
names.forEach(function(name) {
|
||||
var is = name.match(regExp);
|
||||
|
||||
if (is)
|
||||
result.push(path.join(dir, name));
|
||||
|
||||
return is;
|
||||
});
|
||||
|
||||
callback(error, result);
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
var DIR = './',
|
||||
DIR_LIB = DIR + '../',
|
||||
|
||||
path = require('path'),
|
||||
child_process = require('child_process'),
|
||||
|
||||
exec = child_process.exec,
|
||||
|
||||
WIN = process.platform === 'win32',
|
||||
spawn = child_process.spawn,
|
||||
|
||||
Util = require(DIR_LIB + 'util'),
|
||||
CloudFunc = require(DIR_LIB + 'cloudfunc'),
|
||||
|
||||
addNewLine = CloudFunc.addNewLine,
|
||||
|
||||
find = require(DIR + 'find'),
|
||||
win = require(DIR + 'win');
|
||||
|
||||
Util.exec.try(function() {
|
||||
find = require('glob');
|
||||
});
|
||||
|
||||
module.exports = function(command, options, callback) {
|
||||
Util.checkArgs(arguments, ['command', 'callback']);
|
||||
|
||||
if (!callback) {
|
||||
callback = options;
|
||||
|
||||
options = {
|
||||
cwd: process.cwd()
|
||||
};
|
||||
}
|
||||
|
||||
onMessage(command, options, callback);
|
||||
};
|
||||
|
||||
function onMessage(command, options, callback) {
|
||||
var funcExec, firstChar,
|
||||
connName, ret,
|
||||
dir = options.cwd,
|
||||
isVolume = win.isChangeVolume(command),
|
||||
isCD = /^cd ?/.test(command),
|
||||
isCDWin = /^cd ?/i.test(command),
|
||||
|
||||
symbolsExec = ['*', '&', '{', '}', '|', '\'', '"', ';'],
|
||||
isSymbol = Util.isContainStr(command, symbolsExec);
|
||||
|
||||
Util.checkArgs(arguments, ['connNum', 'callback', 'command']);
|
||||
|
||||
if (isCD || isCDWin && WIN || isVolume) {
|
||||
ret = true;
|
||||
|
||||
onCD(command, dir, function(error, json) {
|
||||
var path;
|
||||
|
||||
if (!error && json.path) {
|
||||
path = json.path;
|
||||
options.cwd = path;
|
||||
}
|
||||
|
||||
callback(error, json);
|
||||
});
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
if (WIN)
|
||||
command = 'cmd /C ' + command;
|
||||
|
||||
funcExec = setExec.bind(null, callback);
|
||||
|
||||
firstChar = command[0];
|
||||
|
||||
if (firstChar === '#') {
|
||||
command = command.slice(1);
|
||||
command = connName + command;
|
||||
command = addNewLine(command);
|
||||
|
||||
Util.exec(callback, {
|
||||
stdout: command
|
||||
}, true);
|
||||
} else if (firstChar === ' ' || isSymbol)
|
||||
exec(command, options, funcExec);
|
||||
else
|
||||
setSpawn(command, options, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function send result of command to client
|
||||
* @param callback
|
||||
*/
|
||||
function setExec(callback, error, stdout, stderr) {
|
||||
var json,
|
||||
errorStr = '';
|
||||
|
||||
if (stderr)
|
||||
errorStr = stderr;
|
||||
else if (error)
|
||||
errorStr = error.message;
|
||||
|
||||
json = {
|
||||
stdout : stdout,
|
||||
stderr : errorStr
|
||||
};
|
||||
|
||||
callback(error, json);
|
||||
}
|
||||
|
||||
function setSpawn(сommand, options, callback) {
|
||||
var cmd, error,
|
||||
isSended = false,
|
||||
args = сommand.split(' '),
|
||||
func = function(error, stdout, stderr) {
|
||||
var errorStr = '';
|
||||
|
||||
isSended = true;
|
||||
|
||||
if (error)
|
||||
errorStr = error.message;
|
||||
else if (stderr)
|
||||
errorStr = stderr;
|
||||
|
||||
errorStr = addNewLine(errorStr);
|
||||
|
||||
callback(error, {
|
||||
stderr: errorStr,
|
||||
stdout: stdout
|
||||
});
|
||||
};
|
||||
|
||||
Util.checkArgs(arguments, ['command', 'callback']);
|
||||
|
||||
if (!callback) {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
сommand = args.shift();
|
||||
|
||||
error = Util.exec.tryLog(function() {
|
||||
cmd = spawn(сommand, args, options);
|
||||
});
|
||||
|
||||
if (error) {
|
||||
func(error);
|
||||
} else {
|
||||
cmd.stderr.setEncoding('utf8');
|
||||
cmd.stdout.setEncoding('utf8');
|
||||
|
||||
cmd.stdout.on('data', function(data) {
|
||||
func(null, data);
|
||||
});
|
||||
|
||||
cmd.stderr.on('data', function(error) {
|
||||
func(null, null, error);
|
||||
});
|
||||
|
||||
cmd.on('error', function(error) {
|
||||
func(error);
|
||||
});
|
||||
|
||||
cmd.on('close', function() {
|
||||
cmd = null;
|
||||
|
||||
if (!isSended)
|
||||
func();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onCD(command, currDir, callback) {
|
||||
var CD = 'cd ',
|
||||
HOME = process.env.HOME,
|
||||
|
||||
isChangeVolume = win.isChangeVolume(command),
|
||||
isVolume = win.isVolume(command),
|
||||
paramDir = Util.rmStrOnce(command, [CD, 'cd']),
|
||||
|
||||
regExpHome = new RegExp('^~'),
|
||||
regExpRoot = new RegExp('^[/\\\\]'),
|
||||
|
||||
isWildCard = Util.isContainStr(paramDir, ['*', '?']),
|
||||
isHome = regExpHome.test(paramDir) && !WIN,
|
||||
isRoot = regExpRoot.test(paramDir),
|
||||
|
||||
onExec = function (error, stdout, stderr) {
|
||||
var path = paramDir,
|
||||
errorStr = '';
|
||||
|
||||
if (stderr) {
|
||||
errorStr = stderr;
|
||||
} else if (error) {
|
||||
errorStr = error.message;
|
||||
path = '';
|
||||
}
|
||||
|
||||
callback(error, {
|
||||
stderr : addNewLine(errorStr),
|
||||
stdout : stdout,
|
||||
path : path
|
||||
});
|
||||
};
|
||||
|
||||
if (isHome) {
|
||||
command = command.replace('~', HOME);
|
||||
paramDir = paramDir.replace('~', HOME);
|
||||
}
|
||||
|
||||
if (!paramDir && !WIN)
|
||||
paramDir = '.';
|
||||
|
||||
if (!isChangeVolume || isVolume) {
|
||||
paramDir = getFirstWord(paramDir);
|
||||
paramDir = path.normalize(paramDir);
|
||||
|
||||
command = Util.rmStrOnce(command, [
|
||||
CD,
|
||||
paramDir,
|
||||
'\'' + paramDir + '\'',
|
||||
'"' + paramDir + '"',
|
||||
]);
|
||||
|
||||
if (!isHome && !isRoot)
|
||||
paramDir = path.join(currDir, paramDir);
|
||||
|
||||
if (isWildCard)
|
||||
command = CD + paramDir + ' ' + command;
|
||||
else
|
||||
command = CD + '"' + paramDir + '" ' + command;
|
||||
}
|
||||
|
||||
if (!isWildCard)
|
||||
exec(command, {cwd: paramDir}, onExec);
|
||||
else
|
||||
find(paramDir, function(error, dirs) {
|
||||
var dir;
|
||||
|
||||
if (!error)
|
||||
dir = dirs[0];
|
||||
|
||||
paramDir = dir;
|
||||
exec(command, {cwd: dir}, onExec);
|
||||
});
|
||||
}
|
||||
|
||||
function getFirstWord(str) {
|
||||
var word, result,
|
||||
regStrEnd = getRegStrEnd(),
|
||||
regStr = '^(.*?)',
|
||||
regStrQuotes = '^"(.*)"',
|
||||
regExp = new RegExp(regStr + regStrEnd),
|
||||
regExpQuotes = new RegExp(regStrQuotes + regStrEnd + '?'),
|
||||
is = Util.isString(str);
|
||||
|
||||
if (is) {
|
||||
result = str.match(regExpQuotes);
|
||||
|
||||
if (result) {
|
||||
word = result[1];
|
||||
} else {
|
||||
result = str.match(regExp);
|
||||
word = result && result[1];
|
||||
}
|
||||
|
||||
if (!word)
|
||||
word = str;
|
||||
}
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
function getRegStrEnd() {
|
||||
var regStrEnd = '(\\s|\\;|&&|\\|\\|)';
|
||||
|
||||
return regStrEnd;
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
"editor"
|
||||
],
|
||||
"bin": {
|
||||
"cloudcmd": "./bin/cloudcmd.js"
|
||||
"cloudcmd": "bin/cloudcmd.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "gulp default",
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
"dependencies": {
|
||||
"dropbox": "0.10.x",
|
||||
"express": "~4.8.2",
|
||||
"glob": "~4.0.5",
|
||||
"http-auth": "2.1.x",
|
||||
"marked": "~0.3.2",
|
||||
"minify": "~1.0.0",
|
||||
|
|
@ -35,7 +34,8 @@
|
|||
"morgan": "~1.2.x",
|
||||
"ncp": "~0.6.0",
|
||||
"rimraf": "~2.2.6",
|
||||
"socket.io": "~1.0.0"
|
||||
"socket.io": "~1.0.0",
|
||||
"console-io": "~1.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "~3.8.x",
|
||||
|
|
@ -45,8 +45,5 @@
|
|||
"should": "~4.0.x"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.x"
|
||||
},
|
||||
"main": "cloudcmd.js"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue