parade 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +542 -0
- data/Rakefile +15 -0
- data/bin/parade +138 -0
- data/lib/parade.rb +43 -0
- data/lib/parade/commands/commands.rb +84 -0
- data/lib/parade/commands/generate_outline.rb +34 -0
- data/lib/parade/commands/generate_presentation.rb +34 -0
- data/lib/parade/commands/generate_rackup.rb +32 -0
- data/lib/parade/commands/html_output.rb +47 -0
- data/lib/parade/commands/render_from_template.rb +50 -0
- data/lib/parade/commands/static_html.rb +38 -0
- data/lib/parade/commands/static_pdf.rb +39 -0
- data/lib/parade/commands/unknown.rb +23 -0
- data/lib/parade/features/live_ruby.rb +18 -0
- data/lib/parade/features/pdf_presentation.rb +24 -0
- data/lib/parade/features/preshow.rb +11 -0
- data/lib/parade/helpers/encode_image.rb +24 -0
- data/lib/parade/helpers/template_generator.rb +130 -0
- data/lib/parade/metadata.rb +73 -0
- data/lib/parade/metadata/assignment.rb +38 -0
- data/lib/parade/metadata/css_classes.rb +22 -0
- data/lib/parade/metadata/html_id.rb +35 -0
- data/lib/parade/metadata/template.rb +31 -0
- data/lib/parade/parsers/dsl.rb +138 -0
- data/lib/parade/parsers/dsl_file_parser.rb +17 -0
- data/lib/parade/parsers/json_file_parser.rb +67 -0
- data/lib/parade/parsers/markdown_image_paths.rb +44 -0
- data/lib/parade/parsers/markdown_slide_splitter.rb +63 -0
- data/lib/parade/parsers/presentation_directory_parser.rb +36 -0
- data/lib/parade/parsers/presentation_file_parser.rb +27 -0
- data/lib/parade/parsers/presentation_filepath_parser.rb +35 -0
- data/lib/parade/parsers/slides_file_content_parser.rb +27 -0
- data/lib/parade/renderers/columns_renderer.rb +68 -0
- data/lib/parade/renderers/command_line_renderer.rb +142 -0
- data/lib/parade/renderers/html_with_pygments.rb +42 -0
- data/lib/parade/renderers/inline_images.rb +31 -0
- data/lib/parade/renderers/special_paragraph_renderer.rb +23 -0
- data/lib/parade/renderers/update_image_paths.rb +75 -0
- data/lib/parade/section.rb +183 -0
- data/lib/parade/server.rb +139 -0
- data/lib/parade/slide.rb +128 -0
- data/lib/parade/version.rb +3 -0
- data/lib/public/css/960.css +653 -0
- data/lib/public/css/fg.menu.css +114 -0
- data/lib/public/css/ghf_marked.css +180 -0
- data/lib/public/css/jquery-terminal.css +73 -0
- data/lib/public/css/onepage.css +62 -0
- data/lib/public/css/parade.css +450 -0
- data/lib/public/css/pdf.css +13 -0
- data/lib/public/css/reset.css +53 -0
- data/lib/public/css/spinner_bar.gif +0 -0
- data/lib/public/css/theme/images/ui-bg_diagonals-small_100_f0efea_40x40.png +0 -0
- data/lib/public/css/theme/images/ui-bg_flat_35_f0f0f0_40x100.png +0 -0
- data/lib/public/css/theme/images/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
- data/lib/public/css/theme/images/ui-bg_glow-ball_25_2e2e28_600x600.png +0 -0
- data/lib/public/css/theme/images/ui-bg_highlight-soft_100_f0efea_1x100.png +0 -0
- data/lib/public/css/theme/images/ui-bg_highlight-soft_25_327E04_1x100.png +0 -0
- data/lib/public/css/theme/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png +0 -0
- data/lib/public/css/theme/images/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
- data/lib/public/css/theme/images/ui-bg_inset-soft_22_3b3b35_1x100.png +0 -0
- data/lib/public/css/theme/images/ui-icons_808080_256x240.png +0 -0
- data/lib/public/css/theme/images/ui-icons_8DC262_256x240.png +0 -0
- data/lib/public/css/theme/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/public/css/theme/images/ui-icons_e7e6e4_256x240.png +0 -0
- data/lib/public/css/theme/images/ui-icons_eeeeee_256x240.png +0 -0
- data/lib/public/css/theme/images/ui-icons_ffffff_256x240.png +0 -0
- data/lib/public/css/theme/ui.accordion.css +9 -0
- data/lib/public/css/theme/ui.all.css +2 -0
- data/lib/public/css/theme/ui.base.css +9 -0
- data/lib/public/css/theme/ui.core.css +37 -0
- data/lib/public/css/theme/ui.datepicker.css +62 -0
- data/lib/public/css/theme/ui.dialog.css +13 -0
- data/lib/public/css/theme/ui.progressbar.css +4 -0
- data/lib/public/css/theme/ui.resizable.css +13 -0
- data/lib/public/css/theme/ui.slider.css +17 -0
- data/lib/public/css/theme/ui.tabs.css +9 -0
- data/lib/public/css/theme/ui.theme.css +245 -0
- data/lib/public/favicon.ico +0 -0
- data/lib/public/js/coffee-script.js +8 -0
- data/lib/public/js/fg.menu.js +645 -0
- data/lib/public/js/jTypeWriter.js +26 -0
- data/lib/public/js/jquery-1.4.2.js +6240 -0
- data/lib/public/js/jquery-print.js +109 -0
- data/lib/public/js/jquery-pubsub.js +27 -0
- data/lib/public/js/jquery-terminal.js +2712 -0
- data/lib/public/js/jquery.batchImageLoad.js +56 -0
- data/lib/public/js/jquery.cycle.all.js +1284 -0
- data/lib/public/js/keyboard.js +733 -0
- data/lib/public/js/parade-code-execution.js +122 -0
- data/lib/public/js/parade-command-input.js +16 -0
- data/lib/public/js/parade-command-visor.js +92 -0
- data/lib/public/js/parade-keyboard-input.js +54 -0
- data/lib/public/js/parade.js +675 -0
- data/lib/public/js/spine.js +904 -0
- data/lib/templates/config.ru.erb +4 -0
- data/lib/templates/showoff.erb +27 -0
- data/lib/templates/slides.md.erb +25 -0
- data/lib/views/header.erb +73 -0
- data/lib/views/index.erb +53 -0
- data/lib/views/inline_css.erb +3 -0
- data/lib/views/inline_js.erb +3 -0
- data/lib/views/onepage.erb +17 -0
- data/lib/views/pdf.erb +17 -0
- data/lib/views/slide.erb +5 -0
- metadata +317 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
(function($) {
|
2
|
+
|
3
|
+
function print_array(obj, opts) {
|
4
|
+
var result = [];
|
5
|
+
for (var i = 0; i < Math.min(opts.max_array, obj.length); i++)
|
6
|
+
result.push($.print(obj[i], $.extend({}, opts, { max_array: 3, max_string: 40 })));
|
7
|
+
|
8
|
+
if (obj.length > opts.max_array)
|
9
|
+
result.push((obj.length - opts.max_array) + ' more...');
|
10
|
+
if (result.length == 0) return "[]"
|
11
|
+
return "[ " + result.join(", ") + " ]";
|
12
|
+
}
|
13
|
+
|
14
|
+
function print_element(obj) {
|
15
|
+
if (obj.nodeType == 1) {
|
16
|
+
var result = [];
|
17
|
+
var properties = [ 'className', 'id' ];
|
18
|
+
var extra = {
|
19
|
+
'input': ['type', 'name', 'value'],
|
20
|
+
'a': ['href', 'target'],
|
21
|
+
'form': ['method', 'action'],
|
22
|
+
'script': ['src'],
|
23
|
+
'link': ['href'],
|
24
|
+
'img': ['src']
|
25
|
+
};
|
26
|
+
|
27
|
+
$.each(properties.concat(extra[obj.tagName.toLowerCase()] || []), function(){
|
28
|
+
if (obj[this])
|
29
|
+
result.push(' ' + this.replace('className', 'class') + "=" + $.print(obj[this]))
|
30
|
+
});
|
31
|
+
return "<" + obj.tagName.toLowerCase()
|
32
|
+
+ result.join('') + ">";
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
function print_object(obj, opts) {
|
37
|
+
var seen = opts.seen || [ obj ];
|
38
|
+
|
39
|
+
var result = [], key, value;
|
40
|
+
for (var k in obj) {
|
41
|
+
if (obj.hasOwnProperty(k) && $.inArray(obj[k], seen) < 0) {
|
42
|
+
seen.push(obj[k]);
|
43
|
+
value = $.print(obj[k], $.extend({}, opts, { max_array: 6, max_string: 40, seen: seen }));
|
44
|
+
} else
|
45
|
+
value = "...";
|
46
|
+
result.push(k + ": " + value);
|
47
|
+
}
|
48
|
+
if (result.length == 0) return "{}";
|
49
|
+
return "{ " + result.join(", ") + " }";
|
50
|
+
}
|
51
|
+
|
52
|
+
function print_string(value, opts) {
|
53
|
+
var character_substitutions = {
|
54
|
+
'\b': '\\b',
|
55
|
+
'\t': '\\t',
|
56
|
+
'\n': '\\n',
|
57
|
+
'\f': '\\f',
|
58
|
+
'\r': '\\r',
|
59
|
+
'"' : '\\"',
|
60
|
+
'\\': '\\\\'
|
61
|
+
};
|
62
|
+
var r = /["\\\x00-\x1f\x7f-\x9f]/g;
|
63
|
+
|
64
|
+
var str = r.test(value)
|
65
|
+
? value.replace(r, function (a) {
|
66
|
+
var c = character_substitutions[a];
|
67
|
+
if (c) return c;
|
68
|
+
c = a.charCodeAt();
|
69
|
+
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
|
70
|
+
})
|
71
|
+
: value ;
|
72
|
+
if (str.length > opts.max_string)
|
73
|
+
return str.slice(0, opts.max_string + 1) + '..."';
|
74
|
+
else
|
75
|
+
return str;
|
76
|
+
}
|
77
|
+
|
78
|
+
$.print = function(obj, options) {
|
79
|
+
var opts = $.extend({}, { max_array: 10, max_string: 100 }, options);
|
80
|
+
|
81
|
+
if (typeof obj == 'undefined')
|
82
|
+
return "undefined";
|
83
|
+
else if (typeof obj == 'boolean')
|
84
|
+
return obj.toString();
|
85
|
+
else if (typeof obj == 'number')
|
86
|
+
return obj.toString();
|
87
|
+
else if (!obj)
|
88
|
+
return "null";
|
89
|
+
else if (typeof obj == 'string')
|
90
|
+
return print_string(obj, opts);
|
91
|
+
else if (obj instanceof RegExp)
|
92
|
+
return obj.toString();
|
93
|
+
else if (obj instanceof Array || obj.callee || obj.item)
|
94
|
+
return print_array(obj, opts);
|
95
|
+
else if (typeof obj == 'function' || obj instanceof Function)
|
96
|
+
return obj.toString().match(/^([^)]*\))/)[1];
|
97
|
+
else if (obj.nodeType)
|
98
|
+
return print_element(obj);
|
99
|
+
else if (obj instanceof jQuery)
|
100
|
+
return "$(" + $.print(obj.get()) + ")";
|
101
|
+
else if (obj instanceof Error)
|
102
|
+
return print_object(obj, $.extend({}, options, { max_string: 200 }));
|
103
|
+
else if (obj instanceof Object)
|
104
|
+
return print_object(obj, opts);
|
105
|
+
else
|
106
|
+
return obj.toString().replace(/\n\s*/g, '');
|
107
|
+
}
|
108
|
+
|
109
|
+
})(jQuery);
|
@@ -0,0 +1,27 @@
|
|
1
|
+
/*!
|
2
|
+
* jQuery Tiny Pub/Sub - v0.3 - 11/4/2010
|
3
|
+
* http://benalman.com/
|
4
|
+
*
|
5
|
+
* Copyright (c) 2010 "Cowboy" Ben Alman
|
6
|
+
* Dual licensed under the MIT and GPL licenses.
|
7
|
+
* http://benalman.com/about/license/
|
8
|
+
*/
|
9
|
+
|
10
|
+
(function($){
|
11
|
+
|
12
|
+
var o = $({});
|
13
|
+
|
14
|
+
$.subscribe = function() {
|
15
|
+
o.bind.apply( o, arguments );
|
16
|
+
};
|
17
|
+
|
18
|
+
$.unsubscribe = function() {
|
19
|
+
o.unbind.apply( o, arguments );
|
20
|
+
};
|
21
|
+
|
22
|
+
$.publish = function() {
|
23
|
+
console.log("Publish: " + arguments[0]);
|
24
|
+
o.trigger.apply( o, arguments );
|
25
|
+
};
|
26
|
+
|
27
|
+
})(jQuery);
|
@@ -0,0 +1,2712 @@
|
|
1
|
+
/**@license
|
2
|
+
*| __ _____ ________ __
|
3
|
+
*| / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
4
|
+
*| __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
5
|
+
*| / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
6
|
+
*| \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
7
|
+
*| \/ /____/ version 0.4.22
|
8
|
+
* http://terminal.jcubic.pl
|
9
|
+
*
|
10
|
+
* Licensed under GNU LGPL Version 3 license
|
11
|
+
* Copyright (c) 2011-2012 Jakub Jankiewicz <http://jcubic.pl>
|
12
|
+
*
|
13
|
+
* Includes:
|
14
|
+
*
|
15
|
+
* Storage plugin Distributed under the MIT License
|
16
|
+
* Copyright (c) 2010 Dave Schindler
|
17
|
+
*
|
18
|
+
* jQuery Timers licenced with the WTFPL
|
19
|
+
* <http://jquery.offput.ca/every/>
|
20
|
+
*
|
21
|
+
* Cross-Browser Split 1.1.1
|
22
|
+
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
|
23
|
+
* Available under the MIT License
|
24
|
+
*
|
25
|
+
* Date: Thu, 15 Nov 2012 07:12:21 +0000
|
26
|
+
*/
|
27
|
+
|
28
|
+
/*
|
29
|
+
|
30
|
+
TODO:
|
31
|
+
add destroy method to terminal (cmd alrady have it)
|
32
|
+
|
33
|
+
add support for - $(...).each(function() { ... });
|
34
|
+
|
35
|
+
$.fn.pluginname = function(options) {
|
36
|
+
var settings = $.extend({}, $.fn.pluginname.defaultOptions, options);
|
37
|
+
|
38
|
+
return this.each(function() {
|
39
|
+
var $this = $(this);
|
40
|
+
});
|
41
|
+
$.fn.pluginname.defaultOptions = {
|
42
|
+
};
|
43
|
+
};
|
44
|
+
|
45
|
+
distinguish between paused and disabled
|
46
|
+
paused should block keydown in terminal it should disable command line
|
47
|
+
disable
|
48
|
+
|
49
|
+
*/
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
(function($, undefined) {
|
54
|
+
"use strict";
|
55
|
+
|
56
|
+
// map object to object
|
57
|
+
$.omap = function(o, fn) {
|
58
|
+
var result = {};
|
59
|
+
$.each(o, function(k, v) {
|
60
|
+
result[k] = fn.call(o, k, v);
|
61
|
+
});
|
62
|
+
return result;
|
63
|
+
};
|
64
|
+
// debug function
|
65
|
+
function get_stack(caller) {
|
66
|
+
"use strict";
|
67
|
+
if (caller) {
|
68
|
+
return [caller.toString().match(/.*\n.*\n/)].
|
69
|
+
concat(get_stack(caller.caller));
|
70
|
+
} else {
|
71
|
+
return [];
|
72
|
+
}
|
73
|
+
}
|
74
|
+
// ----------------------------------------
|
75
|
+
// START Storage plugin
|
76
|
+
// ----------------------------------------
|
77
|
+
// Private data
|
78
|
+
var isLS = typeof window.localStorage !== 'undefined';
|
79
|
+
// Private functions
|
80
|
+
function wls(n, v) {
|
81
|
+
var c;
|
82
|
+
if (typeof n === 'string' && typeof v === 'string') {
|
83
|
+
localStorage[n] = v;
|
84
|
+
return true;
|
85
|
+
} else if (typeof n === 'object' && typeof v === 'undefined') {
|
86
|
+
for (c in n) {
|
87
|
+
if (n.hasOwnProperty(c)) {
|
88
|
+
localStorage[c] = n[c];
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return true;
|
92
|
+
}
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
function wc(n, v) {
|
96
|
+
var dt, e, c;
|
97
|
+
dt = new Date();
|
98
|
+
dt.setTime(dt.getTime() + 31536000000);
|
99
|
+
e = '; expires=' + dt.toGMTString();
|
100
|
+
if (typeof n === 'string' && typeof v === 'string') {
|
101
|
+
document.cookie = n + '=' + v + e + '; path=/';
|
102
|
+
return true;
|
103
|
+
} else if (typeof n === 'object' && typeof v === 'undefined') {
|
104
|
+
for (c in n) {
|
105
|
+
if (n.hasOwnProperty(c)) {
|
106
|
+
document.cookie = c + '=' + n[c] + e + '; path=/';
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return true;
|
110
|
+
}
|
111
|
+
return false;
|
112
|
+
}
|
113
|
+
function rls(n) {
|
114
|
+
return localStorage[n];
|
115
|
+
}
|
116
|
+
function rc(n) {
|
117
|
+
var nn, ca, i, c;
|
118
|
+
nn = n + '=';
|
119
|
+
ca = document.cookie.split(';');
|
120
|
+
for (i = 0; i < ca.length; i++) {
|
121
|
+
c = ca[i];
|
122
|
+
while (c.charAt(0) === ' ') {
|
123
|
+
c = c.substring(1, c.length);
|
124
|
+
}
|
125
|
+
if (c.indexOf(nn) === 0) {
|
126
|
+
return c.substring(nn.length, c.length);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return null;
|
130
|
+
}
|
131
|
+
function dls(n) {
|
132
|
+
return delete localStorage[n];
|
133
|
+
}
|
134
|
+
function dc(n) {
|
135
|
+
return wc(n, '', -1);
|
136
|
+
}
|
137
|
+
/**
|
138
|
+
* Public API
|
139
|
+
* $.Storage.set("name", "value")
|
140
|
+
* $.Storage.set({"name1":"value1", "name2":"value2", etc})
|
141
|
+
* $.Storage.get("name")
|
142
|
+
* $.Storage.remove("name")
|
143
|
+
*/
|
144
|
+
$.extend({
|
145
|
+
Storage: {
|
146
|
+
set: isLS ? wls : wc,
|
147
|
+
get: isLS ? rls : rc,
|
148
|
+
remove: isLS ? dls : dc
|
149
|
+
}
|
150
|
+
});
|
151
|
+
// ----------------------------------------
|
152
|
+
// END Storage plugin
|
153
|
+
// ----------------------------------------
|
154
|
+
// START jQuery Timers
|
155
|
+
// ----------------------------------------
|
156
|
+
jQuery.fn.extend({
|
157
|
+
everyTime: function(interval, label, fn, times, belay) {
|
158
|
+
return this.each(function() {
|
159
|
+
jQuery.timer.add(this, interval, label, fn, times, belay);
|
160
|
+
});
|
161
|
+
},
|
162
|
+
oneTime: function(interval, label, fn) {
|
163
|
+
return this.each(function() {
|
164
|
+
jQuery.timer.add(this, interval, label, fn, 1);
|
165
|
+
});
|
166
|
+
},
|
167
|
+
stopTime: function(label, fn) {
|
168
|
+
return this.each(function() {
|
169
|
+
jQuery.timer.remove(this, label, fn);
|
170
|
+
});
|
171
|
+
}
|
172
|
+
});
|
173
|
+
|
174
|
+
jQuery.extend({
|
175
|
+
timer: {
|
176
|
+
guid: 1,
|
177
|
+
global: {},
|
178
|
+
regex: /^([0-9]+)\s*(.*s)?$/,
|
179
|
+
powers: {
|
180
|
+
// Yeah this is major overkill...
|
181
|
+
'ms': 1,
|
182
|
+
'cs': 10,
|
183
|
+
'ds': 100,
|
184
|
+
's': 1000,
|
185
|
+
'das': 10000,
|
186
|
+
'hs': 100000,
|
187
|
+
'ks': 1000000
|
188
|
+
},
|
189
|
+
timeParse: function(value) {
|
190
|
+
if (value === undefined || value === null) {
|
191
|
+
return null;
|
192
|
+
}
|
193
|
+
var result = this.regex.exec(jQuery.trim(value.toString()));
|
194
|
+
if (result[2]) {
|
195
|
+
var num = parseInt(result[1], 10);
|
196
|
+
var mult = this.powers[result[2]] || 1;
|
197
|
+
return num * mult;
|
198
|
+
} else {
|
199
|
+
return value;
|
200
|
+
}
|
201
|
+
},
|
202
|
+
add: function(element, interval, label, fn, times, belay) {
|
203
|
+
var counter = 0;
|
204
|
+
|
205
|
+
if (jQuery.isFunction(label)) {
|
206
|
+
if (!times) {
|
207
|
+
times = fn;
|
208
|
+
}
|
209
|
+
fn = label;
|
210
|
+
label = interval;
|
211
|
+
}
|
212
|
+
|
213
|
+
interval = jQuery.timer.timeParse(interval);
|
214
|
+
|
215
|
+
if (typeof interval !== 'number' ||
|
216
|
+
isNaN(interval) ||
|
217
|
+
interval <= 0) {
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
if (times && times.constructor !== Number) {
|
221
|
+
belay = !!times;
|
222
|
+
times = 0;
|
223
|
+
}
|
224
|
+
|
225
|
+
times = times || 0;
|
226
|
+
belay = belay || false;
|
227
|
+
|
228
|
+
if (!element.$timers) {
|
229
|
+
element.$timers = {};
|
230
|
+
}
|
231
|
+
if (!element.$timers[label]) {
|
232
|
+
element.$timers[label] = {};
|
233
|
+
}
|
234
|
+
fn.$timerID = fn.$timerID || this.guid++;
|
235
|
+
|
236
|
+
var handler = function() {
|
237
|
+
if (belay && handler.inProgress) {
|
238
|
+
return;
|
239
|
+
}
|
240
|
+
handler.inProgress = true;
|
241
|
+
if ((++counter > times && times !== 0) ||
|
242
|
+
fn.call(element, counter) === false) {
|
243
|
+
jQuery.timer.remove(element, label, fn);
|
244
|
+
}
|
245
|
+
handler.inProgress = false;
|
246
|
+
};
|
247
|
+
|
248
|
+
handler.$timerID = fn.$timerID;
|
249
|
+
|
250
|
+
if (!element.$timers[label][fn.$timerID]) {
|
251
|
+
element.$timers[label][fn.$timerID] = window.setInterval(handler, interval);
|
252
|
+
}
|
253
|
+
|
254
|
+
if (!this.global[label]) {
|
255
|
+
this.global[label] = [];
|
256
|
+
}
|
257
|
+
this.global[label].push(element);
|
258
|
+
|
259
|
+
},
|
260
|
+
remove: function(element, label, fn) {
|
261
|
+
var timers = element.$timers, ret;
|
262
|
+
|
263
|
+
if (timers) {
|
264
|
+
|
265
|
+
if (!label) {
|
266
|
+
for (var lab in timers) {
|
267
|
+
if (timers.hasOwnProperty(lab)) {
|
268
|
+
this.remove(element, lab, fn);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
} else if (timers[label]) {
|
272
|
+
if (fn) {
|
273
|
+
if (fn.$timerID) {
|
274
|
+
window.clearInterval(timers[label][fn.$timerID]);
|
275
|
+
delete timers[label][fn.$timerID];
|
276
|
+
}
|
277
|
+
} else {
|
278
|
+
for (var _fn in timers[label]) {
|
279
|
+
if (timers[label].hasOwnProperty(_fn)) {
|
280
|
+
window.clearInterval(timers[label][_fn]);
|
281
|
+
delete timers[label][_fn];
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
for (ret in timers[label]) {
|
287
|
+
if (timers[label].hasOwnProperty(ret)) {
|
288
|
+
break;
|
289
|
+
}
|
290
|
+
}
|
291
|
+
if (!ret) {
|
292
|
+
ret = null;
|
293
|
+
delete timers[label];
|
294
|
+
}
|
295
|
+
}
|
296
|
+
|
297
|
+
for (ret in timers) {
|
298
|
+
if (timers.hasOwnProperty(ret)) {
|
299
|
+
break;
|
300
|
+
}
|
301
|
+
}
|
302
|
+
if (!ret) {
|
303
|
+
element.$timers = null;
|
304
|
+
}
|
305
|
+
}
|
306
|
+
}
|
307
|
+
}
|
308
|
+
});
|
309
|
+
|
310
|
+
if (jQuery.browser.msie) {
|
311
|
+
jQuery(window).one('unload', function() {
|
312
|
+
var global = jQuery.timer.global;
|
313
|
+
for (var label in global) {
|
314
|
+
if (global.hasOwnProperty(label)) {
|
315
|
+
var els = global[label], i = els.length;
|
316
|
+
while (--i) {
|
317
|
+
jQuery.timer.remove(els[i], label);
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
});
|
322
|
+
}
|
323
|
+
// ----------------------------------------
|
324
|
+
// START CROSS BROWSER SPLIT
|
325
|
+
// ----------------------------------------
|
326
|
+
|
327
|
+
(function(undef) {
|
328
|
+
|
329
|
+
// prevent double include
|
330
|
+
|
331
|
+
if (!String.prototype.split.toString().match(/\[native/)) {
|
332
|
+
return;
|
333
|
+
}
|
334
|
+
|
335
|
+
var nativeSplit = String.prototype.split,
|
336
|
+
compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group
|
337
|
+
self;
|
338
|
+
|
339
|
+
self = function (str, separator, limit) {
|
340
|
+
// If `separator` is not a regex, use `nativeSplit`
|
341
|
+
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
|
342
|
+
return nativeSplit.call(str, separator, limit);
|
343
|
+
}
|
344
|
+
var output = [],
|
345
|
+
flags = (separator.ignoreCase ? "i" : "") +
|
346
|
+
(separator.multiline ? "m" : "") +
|
347
|
+
(separator.extended ? "x" : "") + // Proposed for ES6
|
348
|
+
(separator.sticky ? "y" : ""), // Firefox 3+
|
349
|
+
lastLastIndex = 0,
|
350
|
+
// Make `global` and avoid `lastIndex` issues by working with a copy
|
351
|
+
separator2, match, lastIndex, lastLength;
|
352
|
+
separator = new RegExp(separator.source, flags + "g");
|
353
|
+
str += ""; // Type-convert
|
354
|
+
if (!compliantExecNpcg) {
|
355
|
+
// Doesn't need flags gy, but they don't hurt
|
356
|
+
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
|
357
|
+
}
|
358
|
+
/* Values for `limit`, per the spec:
|
359
|
+
* If undefined: 4294967295 // Math.pow(2, 32) - 1
|
360
|
+
* If 0, Infinity, or NaN: 0
|
361
|
+
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
|
362
|
+
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
|
363
|
+
* If other: Type-convert, then use the above rules
|
364
|
+
*/
|
365
|
+
// ? Math.pow(2, 32) - 1 : ToUint32(limit)
|
366
|
+
limit = limit === undef ? -1 >>> 0 : limit >>> 0;
|
367
|
+
while (match = separator.exec(str)) {
|
368
|
+
// `separator.lastIndex` is not reliable cross-browser
|
369
|
+
lastIndex = match.index + match[0].length;
|
370
|
+
if (lastIndex > lastLastIndex) {
|
371
|
+
output.push(str.slice(lastLastIndex, match.index));
|
372
|
+
// Fix browsers whose `exec` methods don't consistently return `undefined` for
|
373
|
+
// nonparticipating capturing groups
|
374
|
+
if (!compliantExecNpcg && match.length > 1) {
|
375
|
+
match[0].replace(separator2, function () {
|
376
|
+
for (var i = 1; i < arguments.length - 2; i++) {
|
377
|
+
if (arguments[i] === undef) {
|
378
|
+
match[i] = undef;
|
379
|
+
}
|
380
|
+
}
|
381
|
+
});
|
382
|
+
}
|
383
|
+
if (match.length > 1 && match.index < str.length) {
|
384
|
+
Array.prototype.push.apply(output, match.slice(1));
|
385
|
+
}
|
386
|
+
lastLength = match[0].length;
|
387
|
+
lastLastIndex = lastIndex;
|
388
|
+
if (output.length >= limit) {
|
389
|
+
break;
|
390
|
+
}
|
391
|
+
}
|
392
|
+
if (separator.lastIndex === match.index) {
|
393
|
+
separator.lastIndex++; // Avoid an infinite loop
|
394
|
+
}
|
395
|
+
}
|
396
|
+
if (lastLastIndex === str.length) {
|
397
|
+
if (lastLength || !separator.test("")) {
|
398
|
+
output.push("");
|
399
|
+
}
|
400
|
+
} else {
|
401
|
+
output.push(str.slice(lastLastIndex));
|
402
|
+
}
|
403
|
+
return output.length > limit ? output.slice(0, limit) : output;
|
404
|
+
};
|
405
|
+
|
406
|
+
// For convenience
|
407
|
+
String.prototype.split = function (separator, limit) {
|
408
|
+
return self(this, separator, limit);
|
409
|
+
};
|
410
|
+
|
411
|
+
return self;
|
412
|
+
|
413
|
+
})();
|
414
|
+
|
415
|
+
// -----------------------------------------------------------------------
|
416
|
+
/*
|
417
|
+
function decodeHTML(str) {
|
418
|
+
if (typeof str === 'string') {
|
419
|
+
str = str.replace(/&/g, '&');
|
420
|
+
str = str.replace(/</g, '<').replace(/>/g, '>');
|
421
|
+
str = str.replace(/	/g, '\t');
|
422
|
+
str = str.replace(/<br\/?>/g, '\n').replace(/ /g, ' ');
|
423
|
+
return str;
|
424
|
+
} else {
|
425
|
+
return '';
|
426
|
+
}
|
427
|
+
}
|
428
|
+
*/
|
429
|
+
//split string to array of strings with the same length
|
430
|
+
function str_parts(str, length) {
|
431
|
+
var result = [];
|
432
|
+
var len = str.length;
|
433
|
+
if (len < length) {
|
434
|
+
return [str];
|
435
|
+
}
|
436
|
+
for (var i = 0; i < len; i += length) {
|
437
|
+
result.push(str.substring(i, i + length));
|
438
|
+
}
|
439
|
+
return result;
|
440
|
+
}
|
441
|
+
|
442
|
+
|
443
|
+
// -----------------------------------------------------------------------
|
444
|
+
|
445
|
+
function skipFormattingCount(string) {
|
446
|
+
return $('<div>' + $.terminal.strip(string) + '</div>').text().length;
|
447
|
+
}
|
448
|
+
|
449
|
+
// -----------------------------------------------------------------------
|
450
|
+
function formattingCount(string) {
|
451
|
+
return string.length - skipFormattingCount(string);
|
452
|
+
}
|
453
|
+
|
454
|
+
// -----------------------------------------------------------------------
|
455
|
+
// CYCLE DATA STRUCTURE
|
456
|
+
// -----------------------------------------------------------------------
|
457
|
+
function Cycle(init) {
|
458
|
+
var data = init ? [init] : [];
|
459
|
+
var pos = 0;
|
460
|
+
$.extend(this, {
|
461
|
+
rotate: function() {
|
462
|
+
if (data.length === 1) {
|
463
|
+
return data[0];
|
464
|
+
} else {
|
465
|
+
if (pos === data.length - 1) {
|
466
|
+
pos = 0;
|
467
|
+
} else {
|
468
|
+
++pos;
|
469
|
+
}
|
470
|
+
return data[pos];
|
471
|
+
}
|
472
|
+
},
|
473
|
+
length: function() {
|
474
|
+
return data.length;
|
475
|
+
},
|
476
|
+
set: function(item) {
|
477
|
+
for (var i = data.length; i--;) {
|
478
|
+
if (data[i] === item) {
|
479
|
+
pos = i;
|
480
|
+
return;
|
481
|
+
}
|
482
|
+
}
|
483
|
+
this.append(item);
|
484
|
+
},
|
485
|
+
front: function() {
|
486
|
+
return data[pos];
|
487
|
+
},
|
488
|
+
append: function(item) {
|
489
|
+
data.push(item);
|
490
|
+
}
|
491
|
+
});
|
492
|
+
}
|
493
|
+
// -----------------------------------------------------------------------
|
494
|
+
// :: BCYCLE DATA STRUCTURE // Two way cycle
|
495
|
+
// -----------------------------------------------------------------------
|
496
|
+
function BCycle(init) {
|
497
|
+
var data = init instanceof Array ? init : init ? [init] : [];
|
498
|
+
var pos = 0;
|
499
|
+
$.extend(this, {
|
500
|
+
left: function() {
|
501
|
+
if (pos === 0) {
|
502
|
+
pos = data.length - 1;
|
503
|
+
} else {
|
504
|
+
--pos;
|
505
|
+
}
|
506
|
+
return data[pos];
|
507
|
+
},
|
508
|
+
right: function() {
|
509
|
+
if (pos === data.length - 1) {
|
510
|
+
pos = 0;
|
511
|
+
} else {
|
512
|
+
++pos;
|
513
|
+
}
|
514
|
+
return data[pos];
|
515
|
+
},
|
516
|
+
current: function() {
|
517
|
+
return data[pos];
|
518
|
+
},
|
519
|
+
data: function() {
|
520
|
+
return data;
|
521
|
+
},
|
522
|
+
length: function() {
|
523
|
+
return data.length;
|
524
|
+
},
|
525
|
+
reset: function() {
|
526
|
+
pos = 0;
|
527
|
+
},
|
528
|
+
append: function(item) {
|
529
|
+
data.push(item);
|
530
|
+
this.reset();
|
531
|
+
}
|
532
|
+
});
|
533
|
+
}
|
534
|
+
// -----------------------------------------------------------------------
|
535
|
+
// :: STACK DATA STRUCTURE
|
536
|
+
// -----------------------------------------------------------------------
|
537
|
+
function Stack(init) {
|
538
|
+
var data = init ? [init] : [];
|
539
|
+
$.extend(this, {
|
540
|
+
size: function() {
|
541
|
+
return data.length;
|
542
|
+
},
|
543
|
+
pop: function() {
|
544
|
+
if (data.length === 0) {
|
545
|
+
return null;
|
546
|
+
} else {
|
547
|
+
var value = data[data.length - 1];
|
548
|
+
data = data.slice(0, data.length - 1);
|
549
|
+
return value;
|
550
|
+
}
|
551
|
+
},
|
552
|
+
push: function(value) {
|
553
|
+
data = data.concat([value]);
|
554
|
+
return value;
|
555
|
+
},
|
556
|
+
top: function() {
|
557
|
+
return data.length > 0 ? data[data.length - 1] : null;
|
558
|
+
}
|
559
|
+
});
|
560
|
+
}
|
561
|
+
// serialize object myself (biwascheme or prototype library do something
|
562
|
+
// wiked with JSON serialization for Arrays)
|
563
|
+
$.json_stringify = function(object, level) {
|
564
|
+
var result = '', i;
|
565
|
+
level = level === undefined ? 1 : level;
|
566
|
+
var type = typeof object;
|
567
|
+
switch (type) {
|
568
|
+
case 'function':
|
569
|
+
result += object;
|
570
|
+
break;
|
571
|
+
case 'boolean':
|
572
|
+
result += object ? 'true' : 'false';
|
573
|
+
break;
|
574
|
+
case 'object':
|
575
|
+
if (object === null) {
|
576
|
+
result += 'null';
|
577
|
+
} else if (object instanceof Array) {
|
578
|
+
result += '[';
|
579
|
+
var len = object.length;
|
580
|
+
for (i = 0; i < len - 1; ++i) {
|
581
|
+
result += $.json_stringify(object[i], level + 1);
|
582
|
+
}
|
583
|
+
result += $.json_stringify(object[len - 1], level + 1) + ']';
|
584
|
+
} else {
|
585
|
+
result += '{';
|
586
|
+
for (var property in object) {
|
587
|
+
if (object.hasOwnProperty(property)) {
|
588
|
+
result += '"' + property + '":' +
|
589
|
+
$.json_stringify(object[property], level + 1);
|
590
|
+
}
|
591
|
+
}
|
592
|
+
result += '}';
|
593
|
+
}
|
594
|
+
break;
|
595
|
+
case 'string':
|
596
|
+
var str = object;
|
597
|
+
var repl = {
|
598
|
+
'\\\\': '\\\\',
|
599
|
+
'"': '\\"',
|
600
|
+
'/': '\\/',
|
601
|
+
'\\n': '\\n',
|
602
|
+
'\\r': '\\r',
|
603
|
+
'\\t': '\\t'};
|
604
|
+
for (i in repl) {
|
605
|
+
if (repl.hasOwnProperty(i)) {
|
606
|
+
str = str.replace(new RegExp(i, 'g'), repl[i]);
|
607
|
+
}
|
608
|
+
}
|
609
|
+
result += '"' + str + '"';
|
610
|
+
break;
|
611
|
+
case 'number':
|
612
|
+
result += String(object);
|
613
|
+
break;
|
614
|
+
}
|
615
|
+
result += (level > 1 ? ',' : '');
|
616
|
+
// quick hacks below
|
617
|
+
if (level === 1) {
|
618
|
+
// fix last comma
|
619
|
+
result = result.replace(/,([\]}])/g, '$1');
|
620
|
+
}
|
621
|
+
// fix comma before array or object
|
622
|
+
return result.replace(/([\[{]),/g, '$1');
|
623
|
+
};
|
624
|
+
// -----------------------------------------------------------------------
|
625
|
+
// :: HISTORY CLASS
|
626
|
+
// -----------------------------------------------------------------------
|
627
|
+
function History(name) {
|
628
|
+
var enabled = true;
|
629
|
+
if (typeof name === 'string' && name !== '') {
|
630
|
+
name += '_';
|
631
|
+
}
|
632
|
+
var data = $.Storage.get(name + 'commands');
|
633
|
+
var bc = new BCycle(data ? eval('(' + data + ')') : ['']);
|
634
|
+
|
635
|
+
$.extend(this, {
|
636
|
+
append: function(item) {
|
637
|
+
if (enabled) {
|
638
|
+
bc.append(item);
|
639
|
+
$.Storage.set(name + 'commands', $.json_stringify(bc.data()));
|
640
|
+
}
|
641
|
+
},
|
642
|
+
data: function() {
|
643
|
+
return bc.data();
|
644
|
+
},
|
645
|
+
next: function() {
|
646
|
+
return bc.right();
|
647
|
+
},
|
648
|
+
last: function() {
|
649
|
+
bc.reset();
|
650
|
+
},
|
651
|
+
previous: function() {
|
652
|
+
return bc.left();
|
653
|
+
},
|
654
|
+
clear: function() {
|
655
|
+
bc = new BCycle();
|
656
|
+
$.Storage.remove(name + 'commands');
|
657
|
+
},
|
658
|
+
enable: function() {
|
659
|
+
enabled = true;
|
660
|
+
},
|
661
|
+
disable: function() {
|
662
|
+
enabled = false;
|
663
|
+
}
|
664
|
+
});
|
665
|
+
}
|
666
|
+
// -----------------------------------------------------------------------
|
667
|
+
// :: COMMAND LINE PLUGIN
|
668
|
+
// -----------------------------------------------------------------------
|
669
|
+
$.fn.cmd = function(options) {
|
670
|
+
var self = this;
|
671
|
+
self.addClass('cmd');
|
672
|
+
self.append('<span class="prompt"></span><span></span>' +
|
673
|
+
'<span class="cursor"> </span><span></span>');
|
674
|
+
var clip = $('<textarea/>').addClass('clipboard').appendTo(self);
|
675
|
+
if (options.width) {
|
676
|
+
self.width(options.width);
|
677
|
+
}
|
678
|
+
var num_chars; // calculates by draw_prompt
|
679
|
+
var prompt_len;
|
680
|
+
var reverse_search = false;
|
681
|
+
var reverse_search_string = '';
|
682
|
+
var reverse_search_position = null;
|
683
|
+
var backup_prompt;
|
684
|
+
var mask = options.mask || false;
|
685
|
+
var command = '';
|
686
|
+
var position = 0;
|
687
|
+
var prompt;
|
688
|
+
var enabled = options.enabled;
|
689
|
+
var name, history;
|
690
|
+
var cursor = self.find('.cursor');
|
691
|
+
|
692
|
+
function blink(i) {
|
693
|
+
cursor.toggleClass('inverted');
|
694
|
+
}
|
695
|
+
function draw_reverse_prompt() {
|
696
|
+
prompt = "(reverse-i-search)`" + reverse_search_string + "': ";
|
697
|
+
draw_prompt();
|
698
|
+
}
|
699
|
+
function clear_reverse_state() {
|
700
|
+
prompt = backup_prompt;
|
701
|
+
reverse_search = false;
|
702
|
+
reverse_search_position = null;
|
703
|
+
reverse_search_string = '';
|
704
|
+
}
|
705
|
+
// if next is not defined or false it search for first item from the end
|
706
|
+
// if true it search for next item
|
707
|
+
function reverse_history_search(next) {
|
708
|
+
var history_data = history.data();
|
709
|
+
var regex = new RegExp('^' + reverse_search_string);
|
710
|
+
var len = history_data.length;
|
711
|
+
if (next && reverse_search_position > 0) {
|
712
|
+
len -= reverse_search_position;
|
713
|
+
}
|
714
|
+
for (var i=len; i--;) {
|
715
|
+
if (regex.test(history_data[i])) {
|
716
|
+
reverse_search_position = history_data.length - i;
|
717
|
+
position = 0;
|
718
|
+
self.set(history_data[i], true);
|
719
|
+
redraw();
|
720
|
+
break;
|
721
|
+
}
|
722
|
+
}
|
723
|
+
}
|
724
|
+
|
725
|
+
function change_num_chars() {
|
726
|
+
var W = self.width();
|
727
|
+
var w = cursor.innerWidth();
|
728
|
+
num_chars = Math.floor(W / w);
|
729
|
+
}
|
730
|
+
function str_repeat(str, n) {
|
731
|
+
var result = '';
|
732
|
+
for (var i = n; i--;) {
|
733
|
+
result += str;
|
734
|
+
}
|
735
|
+
return result;
|
736
|
+
}
|
737
|
+
function get_splited_command_line(string) {
|
738
|
+
/*
|
739
|
+
string = str_repeat('x', prompt_len) + string;
|
740
|
+
var result = $.terminal.split_equal(string);
|
741
|
+
result[0] = result[0].substring(prompt_len);
|
742
|
+
return result;
|
743
|
+
*/
|
744
|
+
var first = string.substring(0, num_chars - prompt_len);
|
745
|
+
var rest = string.substring(num_chars - prompt_len);
|
746
|
+
return [first].concat(str_parts(rest, num_chars));
|
747
|
+
}
|
748
|
+
var redraw = (function(self) {
|
749
|
+
var before = cursor.prev();
|
750
|
+
var after = cursor.next();
|
751
|
+
function draw_cursor_line(string, position) {
|
752
|
+
var len = string.length;
|
753
|
+
if (position === len) {
|
754
|
+
before.html($.terminal.encode(string));
|
755
|
+
cursor.html(' ');
|
756
|
+
after.html('');
|
757
|
+
} else if (position === 0) {
|
758
|
+
before.html('');
|
759
|
+
//fix for tilda in IE
|
760
|
+
cursor.html($.terminal.encode(string.slice(0, 1)));
|
761
|
+
//cursor.html($.terminal.encode(string[0]));
|
762
|
+
after.html($.terminal.encode(string.slice(1)));
|
763
|
+
} else {
|
764
|
+
var before_str = $.terminal.encode(string.slice(0, position));
|
765
|
+
before.html(before_str);
|
766
|
+
//fix for tilda in IE
|
767
|
+
var c = string.slice(position, position + 1);
|
768
|
+
//cursor.html(string[position]));
|
769
|
+
cursor.html(c === ' ' ? ' ' : $.terminal.encode(c));
|
770
|
+
if (position === string.length - 1) {
|
771
|
+
after.html('');
|
772
|
+
} else {
|
773
|
+
after.html($.terminal.encode(string.slice(position + 1)));
|
774
|
+
}
|
775
|
+
}
|
776
|
+
}
|
777
|
+
function div(string) {
|
778
|
+
return '<div>' + $.terminal.encode(string) + '</div>';
|
779
|
+
}
|
780
|
+
function lines_after(lines) {
|
781
|
+
var last_ins = after;
|
782
|
+
$.each(lines, function(i, line) {
|
783
|
+
last_ins = $(div(line)).insertAfter(last_ins).
|
784
|
+
addClass('clear');
|
785
|
+
});
|
786
|
+
}
|
787
|
+
function lines_before(lines) {
|
788
|
+
$.each(lines, function(i, line) {
|
789
|
+
before.before(div(line));
|
790
|
+
});
|
791
|
+
}
|
792
|
+
var count = 0;
|
793
|
+
return function() {
|
794
|
+
var string = mask ? command.replace(/./g, '*') : command;
|
795
|
+
var i, first_len;
|
796
|
+
self.find('div').remove();
|
797
|
+
before.html('');
|
798
|
+
// long line
|
799
|
+
if (string.length > num_chars - prompt_len - 1 ||
|
800
|
+
string.match(/\n/)) {
|
801
|
+
var array;
|
802
|
+
var tabs = string.match(/\t/g);
|
803
|
+
var tabs_rm = tabs ? tabs.length * 3 : 0;
|
804
|
+
//quick tabulation hack
|
805
|
+
if (tabs) {
|
806
|
+
string = string.replace(/\t/g, '\x00\x00\x00\x00');
|
807
|
+
}
|
808
|
+
// command contain new line characters
|
809
|
+
if (string.match(/\n/)) {
|
810
|
+
var tmp = string.split("\n");
|
811
|
+
first_len = num_chars - prompt_len - 1;
|
812
|
+
// empty character after each line
|
813
|
+
for (i=0; i<tmp.length-1; ++i) {
|
814
|
+
tmp[i] += ' ';
|
815
|
+
}
|
816
|
+
// split first line
|
817
|
+
if (tmp[0].length > first_len) {
|
818
|
+
array = [tmp[0].substring(0, first_len)];
|
819
|
+
array = array.concat(str_parts(tmp[0].substring(first_len), num_chars));
|
820
|
+
} else {
|
821
|
+
array = [tmp[0]];
|
822
|
+
}
|
823
|
+
// process rest of the lines
|
824
|
+
for (i=1; i<tmp.length; ++i) {
|
825
|
+
if (tmp[i].length > num_chars) {
|
826
|
+
array = array.concat(str_parts(tmp[i], num_chars));
|
827
|
+
} else {
|
828
|
+
array.push(tmp[i]);
|
829
|
+
}
|
830
|
+
}
|
831
|
+
} else {
|
832
|
+
array = get_splited_command_line(string);
|
833
|
+
}
|
834
|
+
if (tabs) {
|
835
|
+
array = $.map(array, function(line) {
|
836
|
+
return line.replace(/\x00\x00\x00\x00/g, '\t');
|
837
|
+
});
|
838
|
+
}
|
839
|
+
first_len = array[0].length;
|
840
|
+
//cursor in first line
|
841
|
+
if (position < first_len) {
|
842
|
+
draw_cursor_line(array[0], position);
|
843
|
+
lines_after(array.slice(1));
|
844
|
+
} else if (position === first_len) {
|
845
|
+
before.before(div(array[0]));
|
846
|
+
draw_cursor_line(array[1], 0);
|
847
|
+
lines_after(array.slice(2));
|
848
|
+
} else {
|
849
|
+
var num_lines = array.length;
|
850
|
+
var offset = 0;
|
851
|
+
if (position < first_len) {
|
852
|
+
draw_cursor_line(array[0], position);
|
853
|
+
lines_after(array.slice(1));
|
854
|
+
} else if (position === first_len) {
|
855
|
+
before.before(div(array[0]));
|
856
|
+
draw_cursor_line(array[1], 0);
|
857
|
+
lines_after(array.slice(2));
|
858
|
+
} else {
|
859
|
+
var last = array.slice(-1)[0];
|
860
|
+
var from_last = string.length - position;
|
861
|
+
var last_len = last.length;
|
862
|
+
var pos = 0;
|
863
|
+
if (from_last <= last_len) {
|
864
|
+
lines_before(array.slice(0, -1));
|
865
|
+
pos = last_len === from_last ? 0 : last_len-from_last;
|
866
|
+
draw_cursor_line(last, pos+tabs_rm);
|
867
|
+
} else {
|
868
|
+
// in the middle
|
869
|
+
if (num_lines === 3) {
|
870
|
+
before.before('<div>' + $.terminal.encode(array[0]) +
|
871
|
+
'</div>');
|
872
|
+
draw_cursor_line(array[1], position-first_len-1);
|
873
|
+
after.after('<div class="clear">' +
|
874
|
+
$.terminal.encode(array[2]) +
|
875
|
+
'</div>');
|
876
|
+
} else {
|
877
|
+
// more lines, cursor in the middle
|
878
|
+
var line_index;
|
879
|
+
var current;
|
880
|
+
pos = position;
|
881
|
+
for (i=0; i<array.length; ++i) {
|
882
|
+
var current_len = array[i].length;
|
883
|
+
if (pos > current_len) {
|
884
|
+
pos -= current_len;
|
885
|
+
} else {
|
886
|
+
break;
|
887
|
+
}
|
888
|
+
}
|
889
|
+
current = array[i];
|
890
|
+
line_index = i;
|
891
|
+
// cursor on first character in line
|
892
|
+
if (pos === current.length) {
|
893
|
+
pos = 0;
|
894
|
+
current = array[++line_index];
|
895
|
+
}
|
896
|
+
draw_cursor_line(current, pos);
|
897
|
+
lines_before(array.slice(0, line_index));
|
898
|
+
lines_after(array.slice(line_index+1));
|
899
|
+
}
|
900
|
+
}
|
901
|
+
}
|
902
|
+
}
|
903
|
+
} else {
|
904
|
+
if (string === '') {
|
905
|
+
before.html('');
|
906
|
+
cursor.html(' ');
|
907
|
+
after.html('');
|
908
|
+
} else {
|
909
|
+
draw_cursor_line(string, position);
|
910
|
+
}
|
911
|
+
}
|
912
|
+
};
|
913
|
+
})(self);
|
914
|
+
|
915
|
+
var draw_prompt = (function() {
|
916
|
+
var prompt_node = self.find('.prompt');
|
917
|
+
return function() {
|
918
|
+
if (typeof prompt === 'string') {
|
919
|
+
prompt_len = skipFormattingCount(prompt);
|
920
|
+
prompt_node.html($.terminal.format(prompt));
|
921
|
+
} else {
|
922
|
+
prompt(function(string) {
|
923
|
+
prompt_len = skipFormattingCount(string);
|
924
|
+
prompt_node.html($.terminal.format(string));
|
925
|
+
});
|
926
|
+
}
|
927
|
+
//change_num_chars();
|
928
|
+
};
|
929
|
+
})();
|
930
|
+
// paste content to terminal using hidden textarea
|
931
|
+
function paste() {
|
932
|
+
clip.focus();
|
933
|
+
//wait until Browser insert text to textarea
|
934
|
+
self.oneTime(1, function() {
|
935
|
+
self.insert(clip.val());
|
936
|
+
clip.blur().val('');
|
937
|
+
});
|
938
|
+
}
|
939
|
+
function keydown_event(e) {
|
940
|
+
if (options.keydown && options.keydown(e) === false) {
|
941
|
+
return false;
|
942
|
+
}
|
943
|
+
if (enabled) {
|
944
|
+
var pos, len, result;
|
945
|
+
// arrows / Home / End / ENTER
|
946
|
+
if (reverse_search && (e.which === 35 || e.which === 36 ||
|
947
|
+
e.which === 37 || e.which === 38 ||
|
948
|
+
e.which === 39 || e.which === 40 ||
|
949
|
+
e.which === 66 || e.which === 13 ||
|
950
|
+
e.which === 27)) {
|
951
|
+
clear_reverse_state();
|
952
|
+
draw_prompt();
|
953
|
+
if (e.which === 27) { // ESC
|
954
|
+
command = '';
|
955
|
+
}
|
956
|
+
redraw();
|
957
|
+
// finish reverse search and execute normal event handler
|
958
|
+
keydown_event.call(this, e);
|
959
|
+
} else if (e.altKey) {
|
960
|
+
// Chrome on Windows set ctrlKey and altKey for alt
|
961
|
+
// need to check for alt first
|
962
|
+
//if (e.which === 18) { // press ALT
|
963
|
+
if (e.which === 68) { //ALT+D
|
964
|
+
var regex = /[^ ]+ |[^ ]+$/;
|
965
|
+
self.set(command.slice(0, position) +
|
966
|
+
command.slice(position).replace(regex, ''),
|
967
|
+
true);
|
968
|
+
// chrome jump to address bar
|
969
|
+
return false;
|
970
|
+
}
|
971
|
+
return true;
|
972
|
+
} else if (e.keyCode === 13) { //enter
|
973
|
+
if ((history && command) &&
|
974
|
+
((options.historyFilter &&
|
975
|
+
options.historyFilter(command)) ||
|
976
|
+
!options.historyFilter)) {
|
977
|
+
if (history.data().slice(-1)[0] !== command) {
|
978
|
+
history.append(command);
|
979
|
+
}
|
980
|
+
}
|
981
|
+
history.last();
|
982
|
+
var tmp = command;
|
983
|
+
self.set('');
|
984
|
+
if (options.commands) {
|
985
|
+
options.commands(tmp);
|
986
|
+
}
|
987
|
+
if (typeof prompt === 'function') {
|
988
|
+
draw_prompt();
|
989
|
+
}
|
990
|
+
} else if (e.which === 32) { //space
|
991
|
+
if (reverse_search) {
|
992
|
+
reverse_search_string += ' ';
|
993
|
+
draw_reverse_prompt();
|
994
|
+
} else {
|
995
|
+
self.insert(' ');
|
996
|
+
}
|
997
|
+
} else if (e.which === 8) { //backspace
|
998
|
+
if (reverse_search) {
|
999
|
+
reverse_search_string = reverse_search_string.slice(0, -1);
|
1000
|
+
draw_reverse_prompt();
|
1001
|
+
} else {
|
1002
|
+
if (command !== '' && position > 0) {
|
1003
|
+
command = command.slice(0, position - 1) +
|
1004
|
+
command.slice(position, command.length);
|
1005
|
+
--position;
|
1006
|
+
redraw();
|
1007
|
+
}
|
1008
|
+
}
|
1009
|
+
} else if (e.which === 9 && !(e.ctrlKey || e.altKey)) { // TAB
|
1010
|
+
self.insert('\t');
|
1011
|
+
} else if (e.which === 46) {
|
1012
|
+
//DELETE
|
1013
|
+
if (command !== '' && position < command.length) {
|
1014
|
+
command = command.slice(0, position) +
|
1015
|
+
command.slice(position + 1, command.length);
|
1016
|
+
redraw();
|
1017
|
+
}
|
1018
|
+
return true;
|
1019
|
+
} else if (history && e.which === 38 ||
|
1020
|
+
(e.which === 80 && e.ctrlKey)) {
|
1021
|
+
//UP ARROW or CTRL+P
|
1022
|
+
self.set(history.previous());
|
1023
|
+
} else if (history && e.which === 40 ||
|
1024
|
+
(e.which === 78 && e.ctrlKey)) {
|
1025
|
+
//DOWN ARROW or CTRL+N
|
1026
|
+
self.set(history.next());
|
1027
|
+
} else if (e.which === 37 ||
|
1028
|
+
(e.which === 66 && e.ctrlKey)) {
|
1029
|
+
//CTRL+LEFT ARROW or CTRL+B
|
1030
|
+
if (e.ctrlKey && e.which !== 66) {
|
1031
|
+
len = position - 1;
|
1032
|
+
pos = 0;
|
1033
|
+
if (command[len] === ' ') {
|
1034
|
+
--len;
|
1035
|
+
}
|
1036
|
+
for (var i = len; i > 0; --i) {
|
1037
|
+
if (command[i] === ' ' && command[i+1] !== ' ') {
|
1038
|
+
pos = i + 1;
|
1039
|
+
break;
|
1040
|
+
} else if (command[i] === '\n' && command[i+1] !== '\n') {
|
1041
|
+
pos = i;
|
1042
|
+
break;
|
1043
|
+
}
|
1044
|
+
}
|
1045
|
+
self.position(pos);
|
1046
|
+
} else {
|
1047
|
+
//LEFT ARROW or CTRL+B
|
1048
|
+
if (position > 0) {
|
1049
|
+
--position;
|
1050
|
+
redraw();
|
1051
|
+
}
|
1052
|
+
}
|
1053
|
+
} else if (e.which === 82 && e.ctrlKey) { // CTRL+R
|
1054
|
+
if (reverse_search) {
|
1055
|
+
reverse_history_search(true);
|
1056
|
+
} else {
|
1057
|
+
backup_prompt = prompt;
|
1058
|
+
draw_reverse_prompt();
|
1059
|
+
command = '';
|
1060
|
+
redraw();
|
1061
|
+
reverse_search = true;
|
1062
|
+
}
|
1063
|
+
} else if (e.which === 39 ||
|
1064
|
+
(e.which === 70 && e.ctrlKey)) {
|
1065
|
+
//RIGHT ARROW OR CTRL+F
|
1066
|
+
if (e.ctrlKey && e.which !== 70) {
|
1067
|
+
// jump to beginig or end of the word
|
1068
|
+
if (command[position] === ' ') {
|
1069
|
+
++position;
|
1070
|
+
}
|
1071
|
+
var match = command.slice(position).match(/\S[\n\s]{2,}|[\n\s]+\S?/);
|
1072
|
+
if (!match || match[0].match(/^\s+$/)) {
|
1073
|
+
position = command.length;
|
1074
|
+
} else {
|
1075
|
+
if (match[0][0] !== ' ') {
|
1076
|
+
position += match.index + 1;
|
1077
|
+
} else {
|
1078
|
+
position += match.index + match[0].length - 1;
|
1079
|
+
if (match[0][match[0].length-1] !== ' ') {
|
1080
|
+
--position;
|
1081
|
+
}
|
1082
|
+
}
|
1083
|
+
}
|
1084
|
+
redraw();
|
1085
|
+
} else {
|
1086
|
+
if (position < command.length) {
|
1087
|
+
++position;
|
1088
|
+
redraw();
|
1089
|
+
}
|
1090
|
+
}
|
1091
|
+
} else if (e.which === 123) { //F12 - Allow Firebug
|
1092
|
+
return true;
|
1093
|
+
} else if (e.which === 36) { //HOME
|
1094
|
+
self.position(0);
|
1095
|
+
} else if (e.which === 35) {
|
1096
|
+
//END
|
1097
|
+
self.position(command.length);
|
1098
|
+
} else if (e.ctrlKey || e.metaKey) {
|
1099
|
+
if (e.shiftKey) { // CTRL+SHIFT+??
|
1100
|
+
if (e.which === 84) {
|
1101
|
+
//CTRL+SHIFT+T open closed tab
|
1102
|
+
return true;
|
1103
|
+
}
|
1104
|
+
//} else if (e.altKey) { //ALT+CTRL+??
|
1105
|
+
} else {
|
1106
|
+
//NOTE: in opera charCode is undefined
|
1107
|
+
if (e.which === 65) {
|
1108
|
+
//CTRL+A
|
1109
|
+
self.position(0);
|
1110
|
+
} else if (e.which === 69) {
|
1111
|
+
//CTRL+E
|
1112
|
+
self.position(command.length);
|
1113
|
+
} else if (e.which === 88 || e.which === 67 ||
|
1114
|
+
e.which === 87 || e.which === 84) {
|
1115
|
+
//CTRL+X CTRL+C CTRL+W CTRL+T
|
1116
|
+
return true;
|
1117
|
+
} else if (e.which === 86) {
|
1118
|
+
//CTRL+V
|
1119
|
+
paste();
|
1120
|
+
return true;
|
1121
|
+
} else if (e.which === 75) {
|
1122
|
+
//CTRL+K
|
1123
|
+
if (position === 0) {
|
1124
|
+
self.set('');
|
1125
|
+
} else if (position !== command.length) {
|
1126
|
+
self.set(command.slice(0, position));
|
1127
|
+
}
|
1128
|
+
} else if (e.which === 85) { // CTRL+U
|
1129
|
+
self.set(command.slice(position, command.length));
|
1130
|
+
self.position(0);
|
1131
|
+
} else if (e.which === 17) { //CTRL+TAB switch tab
|
1132
|
+
return true;
|
1133
|
+
}
|
1134
|
+
}
|
1135
|
+
} else {
|
1136
|
+
return true;
|
1137
|
+
}
|
1138
|
+
return false;
|
1139
|
+
} /*else {
|
1140
|
+
if ((e.altKey && e.which === 68) ||
|
1141
|
+
(e.ctrlKey &&
|
1142
|
+
$.inArray(e.which, [65, 66, 68, 69, 80, 78, 70]) > -1) ||
|
1143
|
+
// 68 === D
|
1144
|
+
[35, 36, 37, 38, 39, 40].has(e.which)) {
|
1145
|
+
return false;
|
1146
|
+
}
|
1147
|
+
} */
|
1148
|
+
}
|
1149
|
+
$.extend(self, {
|
1150
|
+
name: function(string) {
|
1151
|
+
if (string !== undefined) {
|
1152
|
+
name = string;
|
1153
|
+
history = new History(string);
|
1154
|
+
} else {
|
1155
|
+
return name;
|
1156
|
+
}
|
1157
|
+
},
|
1158
|
+
history: function() {
|
1159
|
+
return history;
|
1160
|
+
},
|
1161
|
+
set: function(string, stay) {
|
1162
|
+
if (string !== undefined) {
|
1163
|
+
command = string;
|
1164
|
+
if (!stay) {
|
1165
|
+
position = command.length;
|
1166
|
+
}
|
1167
|
+
redraw();
|
1168
|
+
if (typeof options.onCommandChange === 'function') {
|
1169
|
+
options.onCommandChange(command);
|
1170
|
+
}
|
1171
|
+
}
|
1172
|
+
},
|
1173
|
+
insert: function(string, stay) {
|
1174
|
+
if (position === command.length) {
|
1175
|
+
command += string;
|
1176
|
+
} else if (position === 0) {
|
1177
|
+
command = string + command;
|
1178
|
+
} else {
|
1179
|
+
command = command.slice(0, position) +
|
1180
|
+
string + command.slice(position);
|
1181
|
+
}
|
1182
|
+
if (!stay) {
|
1183
|
+
position += string.length;
|
1184
|
+
}
|
1185
|
+
redraw();
|
1186
|
+
if (typeof options.onCommandChange === 'function') {
|
1187
|
+
options.onCommandChange(command);
|
1188
|
+
}
|
1189
|
+
},
|
1190
|
+
get: function() {
|
1191
|
+
return command;
|
1192
|
+
},
|
1193
|
+
commands: function(commands) {
|
1194
|
+
if (commands) {
|
1195
|
+
options.commands = commands;
|
1196
|
+
} else {
|
1197
|
+
return commands;
|
1198
|
+
}
|
1199
|
+
},
|
1200
|
+
destroy: function() {
|
1201
|
+
$(document.documentElement).unbind('.commandline');
|
1202
|
+
self.find('.prompt').remove();
|
1203
|
+
},
|
1204
|
+
prompt: function(user_prompt) {
|
1205
|
+
if (user_prompt === undefined) {
|
1206
|
+
return prompt;
|
1207
|
+
} else {
|
1208
|
+
if (typeof user_prompt === 'string' ||
|
1209
|
+
typeof user_prompt === 'function') {
|
1210
|
+
prompt = user_prompt;
|
1211
|
+
} else {
|
1212
|
+
throw 'prompt must be a function or string';
|
1213
|
+
}
|
1214
|
+
draw_prompt();
|
1215
|
+
// we could check if command is longer then numchars-new prompt
|
1216
|
+
redraw();
|
1217
|
+
}
|
1218
|
+
},
|
1219
|
+
position: function(n) {
|
1220
|
+
if (typeof n === 'number') {
|
1221
|
+
position = n < 0 ? 0 : n > command.length ? command.length : n;
|
1222
|
+
redraw();
|
1223
|
+
} else {
|
1224
|
+
return position;
|
1225
|
+
}
|
1226
|
+
},
|
1227
|
+
visible: (function() {
|
1228
|
+
var visible = self.visible;
|
1229
|
+
return function() {
|
1230
|
+
visible.apply(self, []);
|
1231
|
+
redraw();
|
1232
|
+
draw_prompt();
|
1233
|
+
};
|
1234
|
+
})(),
|
1235
|
+
show: (function() {
|
1236
|
+
var show = self.show;
|
1237
|
+
return function() {
|
1238
|
+
show.apply(self, []);
|
1239
|
+
redraw();
|
1240
|
+
draw_prompt();
|
1241
|
+
};
|
1242
|
+
})(),
|
1243
|
+
resize: function(num) {
|
1244
|
+
if (num) {
|
1245
|
+
num_chars = num;
|
1246
|
+
} else {
|
1247
|
+
change_num_chars();
|
1248
|
+
}
|
1249
|
+
redraw();
|
1250
|
+
},
|
1251
|
+
enable: function() {
|
1252
|
+
if (!enabled) {
|
1253
|
+
cursor.addClass('inverted');
|
1254
|
+
self.everyTime(500, 'blink', blink);
|
1255
|
+
enabled = true;
|
1256
|
+
}
|
1257
|
+
},
|
1258
|
+
isenabled: function() {
|
1259
|
+
return enabled;
|
1260
|
+
},
|
1261
|
+
disable: function() {
|
1262
|
+
if (enabled) {
|
1263
|
+
self.stopTime('blink', blink);
|
1264
|
+
cursor.removeClass('inverted');
|
1265
|
+
enabled = false;
|
1266
|
+
}
|
1267
|
+
},
|
1268
|
+
mask: function(display) {
|
1269
|
+
if (typeof display === 'boolean') {
|
1270
|
+
mask = display;
|
1271
|
+
redraw();
|
1272
|
+
} else {
|
1273
|
+
return mask;
|
1274
|
+
}
|
1275
|
+
}
|
1276
|
+
});
|
1277
|
+
// INIT
|
1278
|
+
self.name(options.name || '');
|
1279
|
+
prompt = options.prompt || '> ';
|
1280
|
+
draw_prompt();
|
1281
|
+
if (options.enabled === undefined || options.enabled === true) {
|
1282
|
+
self.enable();
|
1283
|
+
}
|
1284
|
+
// Keystrokes
|
1285
|
+
//document.documentElement
|
1286
|
+
var object;
|
1287
|
+
if ($.browser.msie) {
|
1288
|
+
object = document.documentElement;
|
1289
|
+
} else {
|
1290
|
+
object = window;
|
1291
|
+
}
|
1292
|
+
$(object).keypress(function(e) {
|
1293
|
+
var result;
|
1294
|
+
if (e.ctrlKey && e.which === 99) {
|
1295
|
+
return true;
|
1296
|
+
}
|
1297
|
+
if (!reverse_search && options.keypress) {
|
1298
|
+
result = options.keypress(e);
|
1299
|
+
}
|
1300
|
+
if (result === undefined || result) {
|
1301
|
+
if (enabled) {
|
1302
|
+
if ($.inArray(e.which, [38, 32, 13, 0, 8]) > -1 &&
|
1303
|
+
e.keyCode !== 123 && // for F12 which === 0
|
1304
|
+
//!(e.which === 40 && e.shiftKey ||
|
1305
|
+
!(e.which === 38 && e.shiftKey)) {
|
1306
|
+
return false;
|
1307
|
+
} else if (!e.ctrlKey && !(e.altKey && e.which === 100)) {
|
1308
|
+
// TODO: this should be in one statement
|
1309
|
+
if (reverse_search) {
|
1310
|
+
reverse_search_string += String.fromCharCode(e.which);
|
1311
|
+
draw_reverse_prompt();
|
1312
|
+
reverse_history_search();
|
1313
|
+
} else {
|
1314
|
+
self.insert(String.fromCharCode(e.which));
|
1315
|
+
}
|
1316
|
+
return false;
|
1317
|
+
} else if (e.altKey) {
|
1318
|
+
if (reverse_search) {
|
1319
|
+
reverse_search_string += String.fromCharCode(e.which);
|
1320
|
+
draw_reverse_prompt();
|
1321
|
+
reverse_history_search();
|
1322
|
+
} else {
|
1323
|
+
self.insert(String.fromCharCode(e.which));
|
1324
|
+
}
|
1325
|
+
}
|
1326
|
+
}
|
1327
|
+
} else {
|
1328
|
+
return result;
|
1329
|
+
}
|
1330
|
+
}).keydown(keydown_event);
|
1331
|
+
// characters
|
1332
|
+
return self;
|
1333
|
+
};
|
1334
|
+
|
1335
|
+
// -------------------------------------------------------------------------
|
1336
|
+
// :: TOOLS
|
1337
|
+
// -------------------------------------------------------------------------
|
1338
|
+
|
1339
|
+
var format_split_re = /(\[\[[gbius]*;[^;]*;[^\]]*\](?:[^\]\[]*|\[*(?!\[)[^\]]*\][^\]]*)\])/g;
|
1340
|
+
var format_re = /\[\[([gbius]*);([^;]*);([^;\]]*;|[^\]]*);?([^\]]*)\]([^\]\[]*|[^\[]*\[(?!\[)*[^\]]*\][^\]]*)\]/g;
|
1341
|
+
var color_hex_re = /#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})/;
|
1342
|
+
var url_re = /(https?:((?!&[^;]+;)[^\s:"'<)])+)/g;
|
1343
|
+
var email_regex = /((([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})))/g;
|
1344
|
+
$.terminal = {
|
1345
|
+
// split text into lines with equal width and make each line be renderd
|
1346
|
+
// separatly (text formating can be longer then a line).
|
1347
|
+
split_equal: function(str, length) {
|
1348
|
+
var array = str.split(/\n/g);
|
1349
|
+
var re_format = /(\[\[[gbius]*;[^;]*;[^\]]*\][^\]\[]*\]?)/g;
|
1350
|
+
var re_begin = /(\[\[[gbius]*;[^;]*;[^\]]*\])/;
|
1351
|
+
var re_last = /\[\[[gbius]*;?[^;]*;?[^\]]*\]?$/;
|
1352
|
+
var formatting = false;
|
1353
|
+
var in_text = false;
|
1354
|
+
var braket = 0;
|
1355
|
+
var prev_format = '';
|
1356
|
+
var result = [];
|
1357
|
+
for (var i = 0, len = array.length; i < len; ++i) {
|
1358
|
+
if (prev_format !== '') {
|
1359
|
+
if (array[i] === '') {
|
1360
|
+
result.push(prev_format + ']');
|
1361
|
+
continue;
|
1362
|
+
} else {
|
1363
|
+
array[i] = prev_format + array[i];
|
1364
|
+
prev_format = '';
|
1365
|
+
}
|
1366
|
+
} else {
|
1367
|
+
if (array[i] === '') {
|
1368
|
+
result.push('');
|
1369
|
+
continue;
|
1370
|
+
}
|
1371
|
+
}
|
1372
|
+
var line = array[i];
|
1373
|
+
var first_index = 0;
|
1374
|
+
var count = 0;
|
1375
|
+
for (var j=0, jlen=line.length; j<jlen; ++j) {
|
1376
|
+
if (line[j] === '[' && line[j+1] === '[') {
|
1377
|
+
formatting = true;
|
1378
|
+
} else if (formatting && line[j] === ']') {
|
1379
|
+
if (in_text) {
|
1380
|
+
formatting = false;
|
1381
|
+
in_text = false;
|
1382
|
+
} else {
|
1383
|
+
in_text = true;
|
1384
|
+
}
|
1385
|
+
} else if ((formatting && in_text) || !formatting) {
|
1386
|
+
++count;
|
1387
|
+
}
|
1388
|
+
if (count === length || j === jlen-1) {
|
1389
|
+
var output_line = line.substring(first_index, j+1);
|
1390
|
+
if (prev_format) {
|
1391
|
+
output_line = prev_format + output_line;
|
1392
|
+
if (output_line.match(']')) {
|
1393
|
+
prev_format = '';
|
1394
|
+
}
|
1395
|
+
}
|
1396
|
+
first_index = j+1;
|
1397
|
+
count = 0;
|
1398
|
+
var matched = output_line.match(re_format);
|
1399
|
+
if (matched) {
|
1400
|
+
var last = matched[matched.length-1];
|
1401
|
+
if (last[last.length-1] !== ']') {
|
1402
|
+
prev_format = last.match(re_begin)[1];
|
1403
|
+
output_line += ']';
|
1404
|
+
} else if (output_line.match(re_last)) {
|
1405
|
+
var line_len = output_line.length;
|
1406
|
+
var f_len = line_len - last[last.length-1].length;
|
1407
|
+
output_line = output_line.replace(re_last, '');
|
1408
|
+
prev_format = last.match(re_begin)[1];
|
1409
|
+
}
|
1410
|
+
}
|
1411
|
+
result.push(output_line);
|
1412
|
+
}
|
1413
|
+
}
|
1414
|
+
}
|
1415
|
+
return result;
|
1416
|
+
},
|
1417
|
+
// encode formating as html for inserto into DOM
|
1418
|
+
encode: function(str) {
|
1419
|
+
// don't escape entities
|
1420
|
+
return str.replace(/&(?!#[0-9]+;|[a-zA-Z]+;)/g, '&')
|
1421
|
+
.replace(/</g, '<').replace(/>/g, '>')
|
1422
|
+
// I don't think that it find \n
|
1423
|
+
.replace(/\n/g, '<br/>')
|
1424
|
+
.replace(/ /g, ' ')
|
1425
|
+
.replace(/\t/g, ' ');
|
1426
|
+
},
|
1427
|
+
format: function(str) {
|
1428
|
+
if (typeof str === 'string') {
|
1429
|
+
str = $.terminal.encode($.terminal.from_ansi(str));
|
1430
|
+
//support for formating foo[[u;;]bar]baz[[b;#fff;]quux]zzz
|
1431
|
+
var splited = str.split(format_split_re);
|
1432
|
+
if (splited && splited.length > 1) {
|
1433
|
+
str = $.map(splited, function(text) {
|
1434
|
+
if (text === '') {
|
1435
|
+
return text;
|
1436
|
+
} else if (text.substring(0,1) === '[') {
|
1437
|
+
// use substring for IE quirks mode - [0] don't work
|
1438
|
+
return text.replace(format_re, function(s,
|
1439
|
+
style,
|
1440
|
+
color,
|
1441
|
+
background,
|
1442
|
+
_class,
|
1443
|
+
text) {
|
1444
|
+
if (text === '') {
|
1445
|
+
return '<span> </span>';
|
1446
|
+
}
|
1447
|
+
var style_str = '';
|
1448
|
+
if (style.indexOf('b') !== -1) {
|
1449
|
+
style_str += 'font-weight:bold;';
|
1450
|
+
}
|
1451
|
+
var text_decoration = 'text-decoration:';
|
1452
|
+
if (style.indexOf('u') !== -1) {
|
1453
|
+
text_decoration += 'underline ';
|
1454
|
+
}
|
1455
|
+
if (style.indexOf('s') !== -1) {
|
1456
|
+
text_decoration += 'line-through';
|
1457
|
+
}
|
1458
|
+
if (style.indexOf('s') !== -1 ||
|
1459
|
+
style.indexOf('u') !== -1) {
|
1460
|
+
style_str += text_decoration + ';';
|
1461
|
+
}
|
1462
|
+
if (style.indexOf('i') !== -1) {
|
1463
|
+
style_str += 'font-style:italic;';
|
1464
|
+
}
|
1465
|
+
if (color.match(color_hex_re)) {
|
1466
|
+
style_str += 'color:' + color + ';';
|
1467
|
+
if (style.indexOf('g') !== -1) {
|
1468
|
+
style_str += 'text-shadow: 0 0 5px ' + color + ';';
|
1469
|
+
}
|
1470
|
+
}
|
1471
|
+
if (background.match(color_hex_re)) {
|
1472
|
+
style_str += 'background-color:' + background;
|
1473
|
+
}
|
1474
|
+
var result = '<span style="' + style_str + '"' +
|
1475
|
+
(_class != '' ? ' class="' + _class + '"' : '') +
|
1476
|
+
'>' + text + '</span>';
|
1477
|
+
return result;
|
1478
|
+
});
|
1479
|
+
} else {
|
1480
|
+
return '<span>' + text + '</span>';
|
1481
|
+
}
|
1482
|
+
}).join('');
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
return str.replace(url_re, function(link) {
|
1486
|
+
var comma = link.match(/\.$/);
|
1487
|
+
link = link.replace(/\.$/, '');
|
1488
|
+
return '<a target="_blank" href="' + link + '">' + link + '</a>' +
|
1489
|
+
(comma ? '.' : '');
|
1490
|
+
}).replace(email_regex, '<a href="mailto:$1">$1</a>').
|
1491
|
+
replace(/<span><br\/?><\/span>/g, '<br/>');
|
1492
|
+
} else {
|
1493
|
+
return '';
|
1494
|
+
}
|
1495
|
+
},
|
1496
|
+
// remove formatting from text
|
1497
|
+
strip: function(str) {
|
1498
|
+
return str.replace(format_re, '$5');
|
1499
|
+
},
|
1500
|
+
// return active terminal
|
1501
|
+
active: function() {
|
1502
|
+
return terminals.front();
|
1503
|
+
},
|
1504
|
+
ansi_colors: {
|
1505
|
+
normal: {
|
1506
|
+
black: '#000',
|
1507
|
+
red: '#AA0000',
|
1508
|
+
green: '#008400',
|
1509
|
+
yellow: '#AA5500',
|
1510
|
+
blue: '#0000AA',
|
1511
|
+
magenta: '#AA00AA',
|
1512
|
+
cyan: '#00AAAA',
|
1513
|
+
white: '#fff'
|
1514
|
+
},
|
1515
|
+
bold: {
|
1516
|
+
white: '#fff',
|
1517
|
+
red: '#FF5555',
|
1518
|
+
green: '#44D544',
|
1519
|
+
yellow: '#FFFF55',
|
1520
|
+
blue: '#5555FF',
|
1521
|
+
magenta: '#FF55FF',
|
1522
|
+
cyan: '#55FFFF',
|
1523
|
+
black: '#000'
|
1524
|
+
}
|
1525
|
+
},
|
1526
|
+
from_ansi: (function() {
|
1527
|
+
var color = {
|
1528
|
+
30: 'black',
|
1529
|
+
31: 'red',
|
1530
|
+
32: 'green',
|
1531
|
+
33: 'yellow',
|
1532
|
+
34: 'blue',
|
1533
|
+
35: 'magenta',
|
1534
|
+
36: 'cyan',
|
1535
|
+
37: 'white'
|
1536
|
+
};
|
1537
|
+
var background = {
|
1538
|
+
40: 'black',
|
1539
|
+
41: 'red',
|
1540
|
+
42: 'green',
|
1541
|
+
43: 'yellow',
|
1542
|
+
44: 'blue',
|
1543
|
+
45: 'magenta',
|
1544
|
+
46: 'cyan',
|
1545
|
+
47: 'white'
|
1546
|
+
};
|
1547
|
+
function format_ansi(code) {
|
1548
|
+
var controls = code.split(';');
|
1549
|
+
var num;
|
1550
|
+
var styles = [];
|
1551
|
+
var output_color = '';
|
1552
|
+
var output_background = '';
|
1553
|
+
for(var i in controls) {
|
1554
|
+
num = parseInt(controls[i], 10);
|
1555
|
+
if (num === 1) {
|
1556
|
+
styles.push('b');
|
1557
|
+
}
|
1558
|
+
if (num === 4) {
|
1559
|
+
styles.push('u');
|
1560
|
+
}
|
1561
|
+
if (background[num]) {
|
1562
|
+
output_background = background[num];
|
1563
|
+
}
|
1564
|
+
if (color[num]) {
|
1565
|
+
output_color = color[num];
|
1566
|
+
}
|
1567
|
+
}
|
1568
|
+
var normal = $.terminal.ansi_colors.normal;
|
1569
|
+
var colors = normal;
|
1570
|
+
for (var i=styles.length;i--;) {
|
1571
|
+
if (styles[i] == 'b') {
|
1572
|
+
if (output_color == '') {
|
1573
|
+
output_color = 'white';
|
1574
|
+
}
|
1575
|
+
colors = $.terminal.ansi_colors.bold;
|
1576
|
+
break;
|
1577
|
+
}
|
1578
|
+
}
|
1579
|
+
return '[[' + [styles.join(''),
|
1580
|
+
colors[output_color],
|
1581
|
+
normal[output_background]
|
1582
|
+
].join(';') + ']';
|
1583
|
+
}
|
1584
|
+
return function(input) {
|
1585
|
+
var splitted = input.split(/(\[[0-9;]*m)/g);
|
1586
|
+
if (splitted.length == 1) {
|
1587
|
+
return input;
|
1588
|
+
}
|
1589
|
+
var output = [];
|
1590
|
+
//skip closing at the begining
|
1591
|
+
if (splitted.length > 3 && splitted.slice(0,3).join('') == '[0m') {
|
1592
|
+
splitted = splitted.slice(3);
|
1593
|
+
}
|
1594
|
+
var inside = false;
|
1595
|
+
for (var i=0; i<splitted.length; ++i) {
|
1596
|
+
var match = splitted[i].match(/^\[([0-9;]*)m$/);
|
1597
|
+
if (match) {
|
1598
|
+
if (match[1] == '') {
|
1599
|
+
continue;
|
1600
|
+
}
|
1601
|
+
if (inside) {
|
1602
|
+
output.push(']');
|
1603
|
+
if (match[1] == '0') {
|
1604
|
+
//just closing
|
1605
|
+
inside = false;
|
1606
|
+
} else {
|
1607
|
+
// someone forget to close - process
|
1608
|
+
output.push(format_ansi(match[1]));
|
1609
|
+
}
|
1610
|
+
} else {
|
1611
|
+
inside = true;
|
1612
|
+
output.push(format_ansi(match[1]));
|
1613
|
+
}
|
1614
|
+
} else {
|
1615
|
+
output.push(splitted[i]);
|
1616
|
+
}
|
1617
|
+
}
|
1618
|
+
if (inside) {
|
1619
|
+
output.push(']');
|
1620
|
+
}
|
1621
|
+
return output.join('');
|
1622
|
+
};
|
1623
|
+
})()
|
1624
|
+
};
|
1625
|
+
|
1626
|
+
// -----------------------------------------------------------------------
|
1627
|
+
// Helpers
|
1628
|
+
// -----------------------------------------------------------------------
|
1629
|
+
$.fn.visible = function() {
|
1630
|
+
return this.css('visibility', 'visible');
|
1631
|
+
};
|
1632
|
+
$.fn.hidden = function() {
|
1633
|
+
return this.css('visibility', 'hidden');
|
1634
|
+
};
|
1635
|
+
// -----------------------------------------------------------------------
|
1636
|
+
// JSON-RPC CALL
|
1637
|
+
// -----------------------------------------------------------------------
|
1638
|
+
$.jrpc = function(url, id, method, params, success, error) {
|
1639
|
+
var request = $.json_stringify({
|
1640
|
+
'jsonrpc': '2.0', 'method': method,
|
1641
|
+
'params': params, 'id': id});
|
1642
|
+
return $.ajax({
|
1643
|
+
url: url,
|
1644
|
+
data: request,
|
1645
|
+
success: success,
|
1646
|
+
error: error,
|
1647
|
+
contentType: 'application/json',
|
1648
|
+
dataType: 'json',
|
1649
|
+
async: true,
|
1650
|
+
cache: false,
|
1651
|
+
//timeout: 1,
|
1652
|
+
type: 'POST'});
|
1653
|
+
};
|
1654
|
+
|
1655
|
+
// -----------------------------------------------------------------------
|
1656
|
+
// :: TERMINAL PLUGIN CODE
|
1657
|
+
// -----------------------------------------------------------------------
|
1658
|
+
var version = '0.4.22';
|
1659
|
+
var copyright = 'Copyright (c) 2011-2012 Jakub Jankiewicz <http://jcubic.pl>';
|
1660
|
+
var version_string = 'version ' + version;
|
1661
|
+
//regex is for placing version string aligned to the right
|
1662
|
+
var reg = new RegExp(" {" + version_string.length + "}$");
|
1663
|
+
var signatures = [
|
1664
|
+
['jQuery Terminal', '(c) 2011-2012 jcubic'],
|
1665
|
+
['jQuery Terminal Emulator v. ' + version,
|
1666
|
+
copyright.replace(/ *<.*>/, '')],
|
1667
|
+
['jQuery Terminal Emulator version ' + version_string,
|
1668
|
+
copyright],
|
1669
|
+
[' _______ ________ __',
|
1670
|
+
' / / _ /_ ____________ _/__ ___/______________ _____ / /',
|
1671
|
+
' __ / / // / // / _ / _/ // / / / _ / _/ / / \\/ / _ \\/ /',
|
1672
|
+
'/ / / // / // / ___/ // // / / / ___/ // / / / / /\\ / // / /__',
|
1673
|
+
'\\___/____ \\\\__/____/_/ \\__ / /_/____/_//_/ /_/ /_/ \\/\\__\\_\\___/',
|
1674
|
+
' \\/ /____/ '.replace(reg, '') +
|
1675
|
+
version_string,
|
1676
|
+
copyright],
|
1677
|
+
[' __ _____ ________ __',
|
1678
|
+
' / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /',
|
1679
|
+
' __ / // // // // // _ // _// // / / // _ // _// // // \\/ // _ \\/ /',
|
1680
|
+
'/ / // // // // // ___// / / // / / // ___// / / / / // // /\\ // // / /__',
|
1681
|
+
'\\___//____ \\\\___//____//_/ _\\_ / /_//____//_/ /_/ /_//_//_/ /_/ \\__\\_\\___/',
|
1682
|
+
' \\/ /____/ '.replace(reg, '') +
|
1683
|
+
version_string,
|
1684
|
+
copyright]
|
1685
|
+
];
|
1686
|
+
// for canceling on CTRL+D
|
1687
|
+
var requests = [];
|
1688
|
+
var terminals = new Cycle(); //list of terminals global in this scope
|
1689
|
+
$.fn.terminal = function(init_eval, options) {
|
1690
|
+
var self = this;
|
1691
|
+
var lines = [];
|
1692
|
+
var output;
|
1693
|
+
var terminal_id = terminals.length();
|
1694
|
+
var num_chars; // numer of chars in line
|
1695
|
+
var command_list = []; // for tab completion
|
1696
|
+
var settings = $.extend({
|
1697
|
+
name: '',
|
1698
|
+
prompt: '> ',
|
1699
|
+
history: true,
|
1700
|
+
exit: true,
|
1701
|
+
clear: true,
|
1702
|
+
enabled: true,
|
1703
|
+
displayExceptions: true,
|
1704
|
+
cancelableAjax: true,
|
1705
|
+
login: null,
|
1706
|
+
tabcompletion: null,
|
1707
|
+
historyFilter: null,
|
1708
|
+
onInit: $.noop,
|
1709
|
+
onClear: $.noop,
|
1710
|
+
onBlur: $.noop,
|
1711
|
+
onFocus: $.noop,
|
1712
|
+
onTerminalChange: $.noop,
|
1713
|
+
onExit: $.noop,
|
1714
|
+
keypress: $.noop,
|
1715
|
+
keydown: $.noop
|
1716
|
+
}, options || {});
|
1717
|
+
|
1718
|
+
if (settings.width) {
|
1719
|
+
self.width(settings.width);
|
1720
|
+
}
|
1721
|
+
if (settings.height) {
|
1722
|
+
self.height(settings.height);
|
1723
|
+
}
|
1724
|
+
|
1725
|
+
var pause = !settings.enabled;
|
1726
|
+
if (self.length === 0) {
|
1727
|
+
throw 'Sorry, but terminal said that "' + self.selector +
|
1728
|
+
'" is not valid selector!';
|
1729
|
+
}
|
1730
|
+
// register ajaxSend for cancel requests on CTRL+D
|
1731
|
+
self.ajaxSend(function(e, xhr, opt) {
|
1732
|
+
requests.push(xhr);
|
1733
|
+
});
|
1734
|
+
// terminal already exist
|
1735
|
+
if (self.data('terminal')) {
|
1736
|
+
return self.data('terminal');
|
1737
|
+
}
|
1738
|
+
output = $('<div>').addClass('terminal-output').appendTo(self);
|
1739
|
+
self.addClass('terminal').append('<div/>');
|
1740
|
+
self.click(function() {
|
1741
|
+
self.find('textarea').focus();
|
1742
|
+
});
|
1743
|
+
/*
|
1744
|
+
self.bind('touchstart.touchScroll', function() {
|
1745
|
+
|
1746
|
+
});
|
1747
|
+
self.bind('touchmove.touchScroll', function() {
|
1748
|
+
|
1749
|
+
});
|
1750
|
+
*/
|
1751
|
+
//$('<input type="text"/>').hide().focus().appendTo(self);
|
1752
|
+
//calculate numbers of characters
|
1753
|
+
function haveScrollbars() {
|
1754
|
+
return self.get(0).scrollHeight > self.innerHeight();
|
1755
|
+
}
|
1756
|
+
function get_num_chars() {
|
1757
|
+
var cursor = self.find('.cursor');
|
1758
|
+
var cur_width = cursor.width();
|
1759
|
+
var result = Math.floor(self.width() / cur_width);
|
1760
|
+
if (haveScrollbars()) {
|
1761
|
+
// assume that scrollbars are 20px - in my Laptop with
|
1762
|
+
// Linux/Chrome they are 16px
|
1763
|
+
var margins = self.innerWidth() - self.width();
|
1764
|
+
result -= Math.ceil((20 - margins / 2) / (cur_width-1));
|
1765
|
+
}
|
1766
|
+
return result;
|
1767
|
+
}
|
1768
|
+
|
1769
|
+
function escape_brackets(string) {
|
1770
|
+
return string.replace(/\[/g, '[').replace(/\]/g, ']');
|
1771
|
+
}
|
1772
|
+
|
1773
|
+
// display Exception on terminal
|
1774
|
+
function display_exception(e, label) {
|
1775
|
+
if (settings.displayExceptions) {
|
1776
|
+
var message;
|
1777
|
+
if (typeof e === 'string') {
|
1778
|
+
message = e;
|
1779
|
+
} else {
|
1780
|
+
if (typeof e.fileName === 'string') {
|
1781
|
+
message = e.fileName + ': ' + e.message;
|
1782
|
+
} else {
|
1783
|
+
message = e.message;
|
1784
|
+
}
|
1785
|
+
}
|
1786
|
+
self.error('[' + label + ']: ' + message);
|
1787
|
+
if (typeof e.fileName === 'string') {
|
1788
|
+
//display filename and line which throw exeption
|
1789
|
+
self.pause();
|
1790
|
+
$.get(e.fileName, function(file) {
|
1791
|
+
self.resume();
|
1792
|
+
var num = e.lineNumber - 1;
|
1793
|
+
var line = file.split('\n')[num];
|
1794
|
+
if (line) {
|
1795
|
+
self.error('[' + e.lineNumber + ']: ' + line);
|
1796
|
+
}
|
1797
|
+
});
|
1798
|
+
}
|
1799
|
+
if (e.stack) {
|
1800
|
+
self.error(e.stack);
|
1801
|
+
}
|
1802
|
+
}
|
1803
|
+
}
|
1804
|
+
|
1805
|
+
//validating if object is string or function, call that function and
|
1806
|
+
//display exeption if any
|
1807
|
+
function validate(label, object) {
|
1808
|
+
try {
|
1809
|
+
if (typeof object === 'function') {
|
1810
|
+
object(function() {
|
1811
|
+
// don't care
|
1812
|
+
});
|
1813
|
+
} else if (typeof object !== 'string') {
|
1814
|
+
var msg = label + ' must be string or function';
|
1815
|
+
throw msg;
|
1816
|
+
}
|
1817
|
+
} catch (e) {
|
1818
|
+
display_exception(e, label.toUpperCase());
|
1819
|
+
return false;
|
1820
|
+
}
|
1821
|
+
return true;
|
1822
|
+
}
|
1823
|
+
|
1824
|
+
function scroll_to_bottom() {
|
1825
|
+
var scrollHeight = self.prop ? self.prop('scrollHeight') :
|
1826
|
+
self.attr('scrollHeight');
|
1827
|
+
self.scrollTop(scrollHeight);
|
1828
|
+
}
|
1829
|
+
|
1830
|
+
function draw_line(string) {
|
1831
|
+
string = typeof string === 'string' ? string : String(string);
|
1832
|
+
var div, i, len;
|
1833
|
+
if (string.length > num_chars) {
|
1834
|
+
// string can have line break
|
1835
|
+
//var array = string.split('\n');
|
1836
|
+
// TODO: the way it should work
|
1837
|
+
var array = $.terminal.split_equal(string, num_chars);
|
1838
|
+
|
1839
|
+
div = $('<div></div>');
|
1840
|
+
for (i = 0, len = array.length; i < len; ++i) {
|
1841
|
+
if (array[i] === '' || array[i] === '\r') {
|
1842
|
+
div.append('<div> </div>');
|
1843
|
+
} else {
|
1844
|
+
$('<div/>').html($.terminal.format(array[i])).appendTo(div);
|
1845
|
+
}
|
1846
|
+
}
|
1847
|
+
} else {
|
1848
|
+
div = $('<div/>').html($.terminal.format(string));
|
1849
|
+
}
|
1850
|
+
output.append(div);
|
1851
|
+
div.width('100%');
|
1852
|
+
scroll_to_bottom();
|
1853
|
+
return div;
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
function show_greetings() {
|
1857
|
+
if (options.greetings === undefined) {
|
1858
|
+
self.echo(self.signature);
|
1859
|
+
} else if (options.greetings) {
|
1860
|
+
self.echo(options.greetings);
|
1861
|
+
}
|
1862
|
+
}
|
1863
|
+
|
1864
|
+
function is_scrolled_into_view(elem) {
|
1865
|
+
var docViewTop = $(window).scrollTop();
|
1866
|
+
var docViewBottom = docViewTop + $(window).height();
|
1867
|
+
|
1868
|
+
var elemTop = $(elem).offset().top;
|
1869
|
+
var elemBottom = elemTop + $(elem).height();
|
1870
|
+
|
1871
|
+
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
|
1872
|
+
}
|
1873
|
+
|
1874
|
+
// ----------------------------------------------------------
|
1875
|
+
// TERMINAL METHODS
|
1876
|
+
// ----------------------------------------------------------
|
1877
|
+
|
1878
|
+
var dalyed_commands = [];
|
1879
|
+
$.extend(self, $.omap({
|
1880
|
+
clear: function() {
|
1881
|
+
output.html('');
|
1882
|
+
command_line.set('');
|
1883
|
+
lines = [];
|
1884
|
+
try {
|
1885
|
+
settings.onClear(self);
|
1886
|
+
} catch (e) {
|
1887
|
+
display_exception(e, 'onClear');
|
1888
|
+
throw e;
|
1889
|
+
}
|
1890
|
+
self.attr({ scrollTop: 0});
|
1891
|
+
return self;
|
1892
|
+
},
|
1893
|
+
exec: function(command, silent) {
|
1894
|
+
if (pause) {
|
1895
|
+
dalyed_commands.push([command, silent]);
|
1896
|
+
} else {
|
1897
|
+
commands(command, silent);
|
1898
|
+
}
|
1899
|
+
return self;
|
1900
|
+
},
|
1901
|
+
commands: function() {
|
1902
|
+
return interpreters.top().eval;
|
1903
|
+
},
|
1904
|
+
greetings: function() {
|
1905
|
+
show_greetings();
|
1906
|
+
return self;
|
1907
|
+
},
|
1908
|
+
paused: function() {
|
1909
|
+
return pause;
|
1910
|
+
},
|
1911
|
+
pause: function() {
|
1912
|
+
if (command_line) {
|
1913
|
+
pause = true;
|
1914
|
+
self.disable();
|
1915
|
+
command_line.hidden();
|
1916
|
+
}
|
1917
|
+
return self;
|
1918
|
+
},
|
1919
|
+
resume: function() {
|
1920
|
+
if (command_line) {
|
1921
|
+
self.enable();
|
1922
|
+
var original = dalyed_commands;
|
1923
|
+
dalyed_commands = [];
|
1924
|
+
while (original.length) {
|
1925
|
+
var command = original.shift();
|
1926
|
+
self.exec.apply(self, command);
|
1927
|
+
}
|
1928
|
+
command_line.visible();
|
1929
|
+
scroll_to_bottom();
|
1930
|
+
}
|
1931
|
+
return self;
|
1932
|
+
},
|
1933
|
+
cols: function() {
|
1934
|
+
return num_chars;
|
1935
|
+
},
|
1936
|
+
rows: function() {
|
1937
|
+
return lines.length;
|
1938
|
+
},
|
1939
|
+
history: function() {
|
1940
|
+
return command_line.history();
|
1941
|
+
},
|
1942
|
+
next: function() {
|
1943
|
+
if (terminals.length() === 1) {
|
1944
|
+
return self;
|
1945
|
+
} else {
|
1946
|
+
var offsetTop = self.offset().top;
|
1947
|
+
var height = self.height();
|
1948
|
+
var scrollTop = self.scrollTop();
|
1949
|
+
if (!is_scrolled_into_view(self)) {
|
1950
|
+
self.enable();
|
1951
|
+
$('html,body').animate({scrollTop: offsetTop-50}, 500);
|
1952
|
+
return self;
|
1953
|
+
} else {
|
1954
|
+
terminals.front().disable();
|
1955
|
+
var next = terminals.rotate().enable();
|
1956
|
+
// 100 provides buffer in viewport
|
1957
|
+
var x = next.offset().top - 50;
|
1958
|
+
$('html,body').animate({scrollTop: x}, 500);
|
1959
|
+
try {
|
1960
|
+
settings.onTerminalChange(next);
|
1961
|
+
} catch (e) {
|
1962
|
+
display_exception(e, 'onTerminalChange');
|
1963
|
+
throw e;
|
1964
|
+
}
|
1965
|
+
return next;
|
1966
|
+
}
|
1967
|
+
}
|
1968
|
+
},
|
1969
|
+
// silent used so events are not fired on init
|
1970
|
+
focus: function(toggle, silent) {
|
1971
|
+
self.oneTime(1, function() {
|
1972
|
+
if (terminals.length() === 1) {
|
1973
|
+
if (toggle === false) {
|
1974
|
+
try {
|
1975
|
+
if (!silent && settings.onBlur(self) !== false) {
|
1976
|
+
self.disable();
|
1977
|
+
}
|
1978
|
+
} catch (e) {
|
1979
|
+
display_exception(e, 'onBlur');
|
1980
|
+
throw e;
|
1981
|
+
}
|
1982
|
+
} else {
|
1983
|
+
try {
|
1984
|
+
if (!silent && settings.onFocus(self) !== false) {
|
1985
|
+
self.enable();
|
1986
|
+
}
|
1987
|
+
} catch (e) {
|
1988
|
+
display_exception(e, 'onFocus');
|
1989
|
+
throw e;
|
1990
|
+
}
|
1991
|
+
}
|
1992
|
+
} else {
|
1993
|
+
if (toggle === false) {
|
1994
|
+
self.next();
|
1995
|
+
} else {
|
1996
|
+
var front = terminals.front();
|
1997
|
+
if (front != self) {
|
1998
|
+
front.disable();
|
1999
|
+
if (!silent) {
|
2000
|
+
try {
|
2001
|
+
settings.onTerminalChange(self);
|
2002
|
+
} catch (e) {
|
2003
|
+
display_exception(e, 'onTerminalChange');
|
2004
|
+
throw e;
|
2005
|
+
}
|
2006
|
+
}
|
2007
|
+
}
|
2008
|
+
terminals.set(self);
|
2009
|
+
self.enable();
|
2010
|
+
}
|
2011
|
+
|
2012
|
+
}
|
2013
|
+
});
|
2014
|
+
return self;
|
2015
|
+
},
|
2016
|
+
enable: function() {
|
2017
|
+
if (num_chars === undefined) {
|
2018
|
+
//enabling first time
|
2019
|
+
self.resize();
|
2020
|
+
}
|
2021
|
+
if (pause) {
|
2022
|
+
if (command_line) {
|
2023
|
+
command_line.enable();
|
2024
|
+
pause = false;
|
2025
|
+
}
|
2026
|
+
}
|
2027
|
+
return self;
|
2028
|
+
},
|
2029
|
+
disable: function() {
|
2030
|
+
if (command_line) {
|
2031
|
+
pause = true;
|
2032
|
+
command_line.disable();
|
2033
|
+
}
|
2034
|
+
return self;
|
2035
|
+
},
|
2036
|
+
enabled: function() {
|
2037
|
+
return pause;
|
2038
|
+
},
|
2039
|
+
signature: function() {
|
2040
|
+
var cols = self.cols();
|
2041
|
+
var i = cols < 15 ? null : cols < 35 ? 0 : cols < 55 ? 1 : cols < 64 ? 2 : cols < 75 ? 3 : 4;
|
2042
|
+
if (i !== null) {
|
2043
|
+
return signatures[i].join('\n') + '\n';
|
2044
|
+
} else {
|
2045
|
+
return '';
|
2046
|
+
}
|
2047
|
+
},
|
2048
|
+
version: function() {
|
2049
|
+
return version;
|
2050
|
+
},
|
2051
|
+
/* COMMAND LINE FUNCTIONS */
|
2052
|
+
get_command: function() {
|
2053
|
+
return command_line.get();
|
2054
|
+
},
|
2055
|
+
insert: function(string) {
|
2056
|
+
if (typeof string === 'string') {
|
2057
|
+
command_line.insert(string);
|
2058
|
+
return self;
|
2059
|
+
} else {
|
2060
|
+
throw "insert function argument is not a string";
|
2061
|
+
}
|
2062
|
+
},
|
2063
|
+
set_prompt: function(prompt) {
|
2064
|
+
if (validate('prompt', prompt)) {
|
2065
|
+
if (typeof prompt == 'function') {
|
2066
|
+
command_line.prompt(function(command) {
|
2067
|
+
prompt(command, self);
|
2068
|
+
});
|
2069
|
+
} else {
|
2070
|
+
command_line.prompt(prompt);
|
2071
|
+
}
|
2072
|
+
interpreters.top().prompt = prompt;
|
2073
|
+
}
|
2074
|
+
return self;
|
2075
|
+
},
|
2076
|
+
get_prompt: function() {
|
2077
|
+
return interpreters.top().prompt;
|
2078
|
+
// command_line.prompt(); - can be a wrapper
|
2079
|
+
//return command_line.prompt();
|
2080
|
+
},
|
2081
|
+
set_command: function(command) {
|
2082
|
+
command_line.set(command);
|
2083
|
+
return self;
|
2084
|
+
},
|
2085
|
+
set_mask: function(display) {
|
2086
|
+
command_line.mask(display);
|
2087
|
+
return self;
|
2088
|
+
},
|
2089
|
+
get_output: function(raw) {
|
2090
|
+
if (raw) {
|
2091
|
+
return lines;
|
2092
|
+
} else {
|
2093
|
+
return $.map(lines, function(i, item) {
|
2094
|
+
return typeof item == 'function' ? item() : item;
|
2095
|
+
}).join('\n');
|
2096
|
+
}
|
2097
|
+
},
|
2098
|
+
resize: function(width, height) {
|
2099
|
+
if (width && height) {
|
2100
|
+
self.width(width);
|
2101
|
+
self.height(height);
|
2102
|
+
}
|
2103
|
+
num_chars = get_num_chars();
|
2104
|
+
command_line.resize(num_chars);
|
2105
|
+
var o = output.detach();
|
2106
|
+
output.html('');
|
2107
|
+
$.each(lines, function(i, line) {
|
2108
|
+
draw_line(line && typeof line == 'function' ? line() : line);
|
2109
|
+
});
|
2110
|
+
self.prepend(o);
|
2111
|
+
scroll_to_bottom();
|
2112
|
+
return self;
|
2113
|
+
},
|
2114
|
+
echo: function(line) {
|
2115
|
+
lines.push(line);
|
2116
|
+
draw_line(typeof line === 'function' ? line() : line);
|
2117
|
+
on_scrollbar_show_resize();
|
2118
|
+
return self;
|
2119
|
+
},
|
2120
|
+
error: function(message) {
|
2121
|
+
//echo red message
|
2122
|
+
return self.echo('[[;#f00;]' + escape_brackets(message) + ']');
|
2123
|
+
},
|
2124
|
+
scroll: function(amount) {
|
2125
|
+
var pos;
|
2126
|
+
amount = Math.round(amount);
|
2127
|
+
if (self.prop) {
|
2128
|
+
if (amount > self.prop('scrollTop') && amount > 0) {
|
2129
|
+
self.prop('scrollTop', 0);
|
2130
|
+
}
|
2131
|
+
pos = self.prop('scrollTop');
|
2132
|
+
self.prop('scrollTop', pos + amount);
|
2133
|
+
return self;
|
2134
|
+
} else {
|
2135
|
+
if (amount > self.attr('scrollTop') && amount > 0) {
|
2136
|
+
self.attr('scrollTop', 0);
|
2137
|
+
}
|
2138
|
+
pos = self.attr('scrollTop');
|
2139
|
+
self.attr('scrollTop', pos + amount);
|
2140
|
+
return self;
|
2141
|
+
}
|
2142
|
+
},
|
2143
|
+
logout: settings.login ? function() {
|
2144
|
+
while (interpreters.size() > 1) {
|
2145
|
+
interpreters.pop();
|
2146
|
+
}
|
2147
|
+
logout();
|
2148
|
+
return self;
|
2149
|
+
} : function() {
|
2150
|
+
throw "You don't have login function";
|
2151
|
+
},
|
2152
|
+
token: settings.login ? function() {
|
2153
|
+
var name = settings.name;
|
2154
|
+
return $.Storage.get('token' + (name ? '_' + name : ''));
|
2155
|
+
} : $.noop,
|
2156
|
+
login_name: settings.login ? function() {
|
2157
|
+
var name = settings.name;
|
2158
|
+
return $.Storage.get('login' + (name ? '_' + name : ''));
|
2159
|
+
} : $.noop,
|
2160
|
+
name: function() {
|
2161
|
+
return settings.name;
|
2162
|
+
},
|
2163
|
+
push: function(_eval, options) {
|
2164
|
+
if (options && (!options.prompt || validate('prompt', options.prompt)) || !options) {
|
2165
|
+
if (typeof _eval === 'string') {
|
2166
|
+
_eval = make_json_rpc_eval_fun(options['eval'], self);
|
2167
|
+
}
|
2168
|
+
interpreters.push($.extend({'eval': _eval}, options));
|
2169
|
+
prepare_top_interpreter();
|
2170
|
+
}
|
2171
|
+
return self;
|
2172
|
+
},
|
2173
|
+
reset: function() {
|
2174
|
+
self.clear();
|
2175
|
+
while(interpreters.size() > 1) {
|
2176
|
+
interpreters.pop();
|
2177
|
+
}
|
2178
|
+
initialize();
|
2179
|
+
},
|
2180
|
+
pop: function(string) {
|
2181
|
+
if (string !== undefined) {
|
2182
|
+
echo_command(string);
|
2183
|
+
}
|
2184
|
+
if (interpreters.top().name === settings.name) {
|
2185
|
+
if (settings.login) {
|
2186
|
+
logout();
|
2187
|
+
if (typeof settings.onExit === 'function') {
|
2188
|
+
try {
|
2189
|
+
settings.onExit(self);
|
2190
|
+
} catch (e) {
|
2191
|
+
display_exception(e, 'onExit');
|
2192
|
+
throw e;
|
2193
|
+
}
|
2194
|
+
}
|
2195
|
+
}
|
2196
|
+
} else {
|
2197
|
+
var current = interpreters.pop();
|
2198
|
+
prepare_top_interpreter();
|
2199
|
+
if (typeof current.onExit === 'function') {
|
2200
|
+
try {
|
2201
|
+
current.onExit(self);
|
2202
|
+
} catch (e) {
|
2203
|
+
display_exception(e, 'onExit');
|
2204
|
+
throw e;
|
2205
|
+
}
|
2206
|
+
}
|
2207
|
+
}
|
2208
|
+
return self;
|
2209
|
+
}
|
2210
|
+
}, function(_, fun) {
|
2211
|
+
// wrap all functions and display execptions
|
2212
|
+
return function() {
|
2213
|
+
try {
|
2214
|
+
return fun.apply(this, Array.prototype.slice.apply(arguments));
|
2215
|
+
} catch(e) {
|
2216
|
+
display_exception(e, 'TERMINAL');
|
2217
|
+
}
|
2218
|
+
};
|
2219
|
+
}));
|
2220
|
+
|
2221
|
+
//function constructor for eval
|
2222
|
+
function make_json_rpc_eval_fun(url, terminal) {
|
2223
|
+
var id = 1;
|
2224
|
+
var service = function(method, params) {
|
2225
|
+
terminal.pause();
|
2226
|
+
$.jrpc(url, id++, method, params, function(json) {
|
2227
|
+
if (!json.error) {
|
2228
|
+
if (typeof json.result === 'string') {
|
2229
|
+
terminal.echo(json.result);
|
2230
|
+
} else if (json.result instanceof Array) {
|
2231
|
+
terminal.echo(json.result.join(' '));
|
2232
|
+
} else if (typeof json.result === 'object') {
|
2233
|
+
var string = '';
|
2234
|
+
for (var f in json.result) {
|
2235
|
+
if (json.result.hasOwnProperty(f)) {
|
2236
|
+
string += f + ': ' + json.result[f] + '\n';
|
2237
|
+
}
|
2238
|
+
}
|
2239
|
+
terminal.echo(string);
|
2240
|
+
}
|
2241
|
+
} else {
|
2242
|
+
terminal.error('[RPC] ' + json.error.message);
|
2243
|
+
}
|
2244
|
+
terminal.resume();
|
2245
|
+
}, function(xhr, status, error) {
|
2246
|
+
terminal.error('[AJAX] ' + status +
|
2247
|
+
' - Server reponse is: \n' +
|
2248
|
+
xhr.responseText);
|
2249
|
+
terminal.resume();
|
2250
|
+
});
|
2251
|
+
};
|
2252
|
+
//this is eval function
|
2253
|
+
return function(command, terminal) {
|
2254
|
+
if (command === '') {
|
2255
|
+
return;
|
2256
|
+
}
|
2257
|
+
var method, params;
|
2258
|
+
if (!command.match(/[^ ]* /)) {
|
2259
|
+
method = command;
|
2260
|
+
params = [];
|
2261
|
+
} else {
|
2262
|
+
command = command.split(/ +/);
|
2263
|
+
method = command[0];
|
2264
|
+
params = command.slice(1);
|
2265
|
+
}
|
2266
|
+
if (!settings.login || method === 'help') {
|
2267
|
+
service(method, params);
|
2268
|
+
} else {
|
2269
|
+
var token = terminal.token();
|
2270
|
+
if (token) {
|
2271
|
+
service(method, [token].concat(params));
|
2272
|
+
} else {
|
2273
|
+
//should never happen
|
2274
|
+
terminal.error('[AUTH] Access denied (no token)');
|
2275
|
+
}
|
2276
|
+
}
|
2277
|
+
};
|
2278
|
+
}
|
2279
|
+
|
2280
|
+
//display prompt and last command
|
2281
|
+
function echo_command(command) {
|
2282
|
+
command = command.replace(/\[/g, '[').replace(/\]/g, ']');
|
2283
|
+
var prompt = command_line.prompt();
|
2284
|
+
if (command_line.mask()) {
|
2285
|
+
command = command.replace(/./g, '*');
|
2286
|
+
}
|
2287
|
+
if (typeof prompt === 'function') {
|
2288
|
+
prompt(function(string) {
|
2289
|
+
self.echo(string + command);
|
2290
|
+
});
|
2291
|
+
} else {
|
2292
|
+
self.echo(prompt + command);
|
2293
|
+
}
|
2294
|
+
}
|
2295
|
+
|
2296
|
+
// wrapper over eval it implements exit and catch all exeptions
|
2297
|
+
// from user code and display them on terminal
|
2298
|
+
function commands(command, silent) {
|
2299
|
+
try {
|
2300
|
+
var interpreter = interpreters.top();
|
2301
|
+
if (command === 'exit' && settings.exit) {
|
2302
|
+
if (interpreters.size() === 1) {
|
2303
|
+
if (settings.login) {
|
2304
|
+
logout();
|
2305
|
+
} else {
|
2306
|
+
var msg = 'You can exit from main interpeter';
|
2307
|
+
if (!silent) {
|
2308
|
+
echo_command(command);
|
2309
|
+
}
|
2310
|
+
self.echo(msg);
|
2311
|
+
}
|
2312
|
+
} else {
|
2313
|
+
self.pop('exit');
|
2314
|
+
}
|
2315
|
+
} else {
|
2316
|
+
if (!silent) {
|
2317
|
+
echo_command(command);
|
2318
|
+
}
|
2319
|
+
if (command === 'clear' && settings.clear) {
|
2320
|
+
self.clear();
|
2321
|
+
} else {
|
2322
|
+
interpreter['eval'](command, self);
|
2323
|
+
}
|
2324
|
+
}
|
2325
|
+
|
2326
|
+
} catch (e) {
|
2327
|
+
display_exception(e, 'USER');
|
2328
|
+
self.resume();
|
2329
|
+
throw e;
|
2330
|
+
}
|
2331
|
+
}
|
2332
|
+
|
2333
|
+
// functions change prompt of command line to login to password
|
2334
|
+
// and call user login function with callback that set token
|
2335
|
+
// if user call it with value that is true
|
2336
|
+
function login() {
|
2337
|
+
var user = null;
|
2338
|
+
command_line.prompt('login: ');
|
2339
|
+
// don't stor logins in history
|
2340
|
+
if (settings.history) {
|
2341
|
+
command_line.history().disable();
|
2342
|
+
}
|
2343
|
+
command_line.commands(function(command) {
|
2344
|
+
try {
|
2345
|
+
echo_command(command);
|
2346
|
+
if (!user) {
|
2347
|
+
user = command;
|
2348
|
+
command_line.prompt('password: ');
|
2349
|
+
command_line.mask(true);
|
2350
|
+
} else {
|
2351
|
+
command_line.mask(false);
|
2352
|
+
self.pause();
|
2353
|
+
if (typeof settings.login !== 'function') {
|
2354
|
+
throw "Value of login property must be a function";
|
2355
|
+
}
|
2356
|
+
var passwd = command;
|
2357
|
+
settings.login(user, passwd, function(token) {
|
2358
|
+
if (token) {
|
2359
|
+
var name = settings.name;
|
2360
|
+
name = (name ? '_' + name : '');
|
2361
|
+
$.Storage.set('token' + name, token);
|
2362
|
+
$.Storage.set('login' + name, user);
|
2363
|
+
//restore commands and run interpreter
|
2364
|
+
command_line.commands(commands);
|
2365
|
+
// move this to one function init.
|
2366
|
+
initialize();
|
2367
|
+
} else {
|
2368
|
+
self.error('Wrong password try again');
|
2369
|
+
command_line.prompt('login: ');
|
2370
|
+
user = null;
|
2371
|
+
}
|
2372
|
+
self.resume();
|
2373
|
+
if (settings.history) {
|
2374
|
+
command_line.history().enable();
|
2375
|
+
}
|
2376
|
+
});
|
2377
|
+
}
|
2378
|
+
} catch (e) {
|
2379
|
+
display_exception(e, 'LOGIN', self);
|
2380
|
+
throw e;
|
2381
|
+
}
|
2382
|
+
});
|
2383
|
+
}
|
2384
|
+
|
2385
|
+
//logout function remove Storage, disable history and run login function
|
2386
|
+
//this function is call only when options.login function is defined
|
2387
|
+
//check for this is in self.pop method
|
2388
|
+
function logout() {
|
2389
|
+
if (typeof settings.onBeforelogout === 'function') {
|
2390
|
+
try {
|
2391
|
+
if (settings.onBeforelogout(self) == false) {
|
2392
|
+
return;
|
2393
|
+
}
|
2394
|
+
} catch (e) {
|
2395
|
+
display_exception(e, 'onBeforelogout');
|
2396
|
+
throw e;
|
2397
|
+
}
|
2398
|
+
}
|
2399
|
+
var name = settings.name;
|
2400
|
+
name = (name ? '_' + name : '');
|
2401
|
+
$.Storage.remove('token' + name, null);
|
2402
|
+
$.Storage.remove('login' + name, null);
|
2403
|
+
if (settings.history) {
|
2404
|
+
command_line.history().disable();
|
2405
|
+
}
|
2406
|
+
login();
|
2407
|
+
if (typeof settings.onAfterlogout === 'function') {
|
2408
|
+
try {
|
2409
|
+
settings.onAfterlogout(self);
|
2410
|
+
} catch (e) {
|
2411
|
+
display_exception(e, 'onAfterlogout');
|
2412
|
+
throw e;
|
2413
|
+
}
|
2414
|
+
}
|
2415
|
+
}
|
2416
|
+
|
2417
|
+
//function enable history, set prompt, run eval function
|
2418
|
+
function prepare_top_interpreter() {
|
2419
|
+
var interpreter = interpreters.top();
|
2420
|
+
var name = '';
|
2421
|
+
if (interpreter.name !== undefined &&
|
2422
|
+
interpreter.name !== '') {
|
2423
|
+
name += interpreter.name + '_';
|
2424
|
+
}
|
2425
|
+
name += terminal_id;
|
2426
|
+
command_line.name(name);
|
2427
|
+
if (typeof interpreter.prompt == 'function') {
|
2428
|
+
command_line.prompt(function(command) {
|
2429
|
+
interpreter.prompt(command, self);
|
2430
|
+
});
|
2431
|
+
} else {
|
2432
|
+
command_line.prompt(interpreter.prompt);
|
2433
|
+
}
|
2434
|
+
if (settings.history) {
|
2435
|
+
command_line.history().enable();
|
2436
|
+
}
|
2437
|
+
command_line.set('');
|
2438
|
+
if (typeof interpreter.onStart === 'function') {
|
2439
|
+
interpreter.onStart(self);
|
2440
|
+
}
|
2441
|
+
}
|
2442
|
+
function initialize() {
|
2443
|
+
prepare_top_interpreter();
|
2444
|
+
show_greetings();
|
2445
|
+
if (typeof settings.onInit === 'function') {
|
2446
|
+
try {
|
2447
|
+
settings.onInit(self);
|
2448
|
+
} catch (e) {
|
2449
|
+
display_exception(e, 'OnInit');
|
2450
|
+
throw e;
|
2451
|
+
}
|
2452
|
+
}
|
2453
|
+
}
|
2454
|
+
|
2455
|
+
// ---------------------------------------------------------------------
|
2456
|
+
var on_scrollbar_show_resize = (function() {
|
2457
|
+
var scrollBars = haveScrollbars();
|
2458
|
+
return function() {
|
2459
|
+
if (scrollBars !== haveScrollbars()) {
|
2460
|
+
// if scollbars appearance change we will have different
|
2461
|
+
// number of chars
|
2462
|
+
self.resize();
|
2463
|
+
scrollBars = haveScrollbars();
|
2464
|
+
}
|
2465
|
+
};
|
2466
|
+
})();
|
2467
|
+
// ---------------------------------------------------------------------
|
2468
|
+
// KEYDOWN EVENT HANDLER
|
2469
|
+
// ---------------------------------------------------------------------
|
2470
|
+
var tab_count = 0;
|
2471
|
+
|
2472
|
+
function key_down(e) {
|
2473
|
+
var i;
|
2474
|
+
// after text pasted into textarea in cmd plugin
|
2475
|
+
self.oneTime(5, function() {
|
2476
|
+
on_scrollbar_show_resize();
|
2477
|
+
});
|
2478
|
+
if (settings.keydown && settings.keydown(e, self) === false) {
|
2479
|
+
return false;
|
2480
|
+
}
|
2481
|
+
if (!self.paused()) {
|
2482
|
+
|
2483
|
+
if (e.which !== 9) { // not a TAB
|
2484
|
+
tab_count = 0;
|
2485
|
+
}
|
2486
|
+
if (e.which === 68 && e.ctrlKey) { // CTRL+D
|
2487
|
+
if (command_line.get() === '') {
|
2488
|
+
if (interpreters.size() > 1 ||
|
2489
|
+
settings.login !== undefined) {
|
2490
|
+
self.pop('');
|
2491
|
+
} else {
|
2492
|
+
self.resume();
|
2493
|
+
self.echo('');
|
2494
|
+
}
|
2495
|
+
} else {
|
2496
|
+
self.set_command('');
|
2497
|
+
}
|
2498
|
+
return false;
|
2499
|
+
} else if (settings.tabcompletion && e.which === 9) { // TAB
|
2500
|
+
// TODO: move this to cmd plugin
|
2501
|
+
// add tabcompletion = array | function
|
2502
|
+
++tab_count;
|
2503
|
+
var command = command_line.get();
|
2504
|
+
if (!command.match(' ')) { // complete only first word
|
2505
|
+
var reg = new RegExp('^' + command);
|
2506
|
+
var commands = interpreters.top().command_list;
|
2507
|
+
var matched = [];
|
2508
|
+
for (i=commands.length; i--;) {
|
2509
|
+
if (reg.test(commands[i])) {
|
2510
|
+
matched.push(commands[i]);
|
2511
|
+
}
|
2512
|
+
}
|
2513
|
+
if (matched.length === 1) {
|
2514
|
+
self.set_command(matched[0]);
|
2515
|
+
} else if (matched.length > 1) {
|
2516
|
+
if (tab_count >= 2) {
|
2517
|
+
echo_command(command);
|
2518
|
+
self.echo(matched.join('\t'));
|
2519
|
+
tab_count = 0;
|
2520
|
+
}
|
2521
|
+
}
|
2522
|
+
}
|
2523
|
+
return false;
|
2524
|
+
} else if (e.which === 86 && e.ctrlKey) { // CTRL+V
|
2525
|
+
self.oneTime(1, function() {
|
2526
|
+
scroll_to_bottom();
|
2527
|
+
});
|
2528
|
+
return true;
|
2529
|
+
} else if (e.which === 9 && e.ctrlKey) { // CTRL+TAB
|
2530
|
+
if (terminals.length() > 1) {
|
2531
|
+
self.focus(false);
|
2532
|
+
}
|
2533
|
+
return false;
|
2534
|
+
} else if (e.which === 34) { // PAGE DOWN
|
2535
|
+
self.scroll(self.height());
|
2536
|
+
} else if (e.which === 33) { // PAGE UP
|
2537
|
+
self.scroll(-self.height());
|
2538
|
+
} else {
|
2539
|
+
self.attr({scrollTop: self.attr('scrollHeight')});
|
2540
|
+
}
|
2541
|
+
} else {
|
2542
|
+
if (e.which === 68 && e.ctrlKey) { // CTRL+D
|
2543
|
+
for (i=requests.length; i--;) {
|
2544
|
+
var r = requests[i];
|
2545
|
+
if (4 !== r.readyState) {
|
2546
|
+
try {
|
2547
|
+
r.abort();
|
2548
|
+
} catch(e) {
|
2549
|
+
self.error('error in aborting ajax');
|
2550
|
+
}
|
2551
|
+
}
|
2552
|
+
}
|
2553
|
+
self.resume();
|
2554
|
+
return false;
|
2555
|
+
}
|
2556
|
+
}
|
2557
|
+
}
|
2558
|
+
// ---------------------------------------------------------------------
|
2559
|
+
// INIT CODE
|
2560
|
+
// ---------------------------------------------------------------------
|
2561
|
+
var url;
|
2562
|
+
if (settings.login && typeof settings.onBeforeLogin === 'function') {
|
2563
|
+
try {
|
2564
|
+
settings.onBeforeLogin(self);
|
2565
|
+
} catch (e) {
|
2566
|
+
display_exception(e, 'onBeforeLogin');
|
2567
|
+
throw e;
|
2568
|
+
}
|
2569
|
+
}
|
2570
|
+
if (typeof init_eval == 'string') {
|
2571
|
+
url = init_eval; //url variable is use when making login function
|
2572
|
+
init_eval = make_json_rpc_eval_fun(init_eval, self);
|
2573
|
+
} else if (typeof init_eval == 'object' && init_eval.constructor === Array) {
|
2574
|
+
throw "You can't use array as eval";
|
2575
|
+
} else if (typeof init_eval === 'object') {
|
2576
|
+
// top commands
|
2577
|
+
for (var i in init_eval) {
|
2578
|
+
if (init_eval.hasOwnProperty(i)) {
|
2579
|
+
command_list.push(i);
|
2580
|
+
}
|
2581
|
+
}
|
2582
|
+
init_eval = (function make_eval(object) {
|
2583
|
+
// function that maps commands to object methods
|
2584
|
+
// it keeps terminal context
|
2585
|
+
return function(command, terminal) {
|
2586
|
+
if (command === '') {
|
2587
|
+
return;
|
2588
|
+
}
|
2589
|
+
command = command.split(/ +/);
|
2590
|
+
var method = command[0];
|
2591
|
+
var params = command.slice(1);
|
2592
|
+
var val = object[method];
|
2593
|
+
var type = typeof val;
|
2594
|
+
if (type === 'function') {
|
2595
|
+
val.apply(self, params);
|
2596
|
+
} else if (type === 'object' || type === 'string') {
|
2597
|
+
var commands = [];
|
2598
|
+
if (type === 'object') {
|
2599
|
+
for (var m in val) {
|
2600
|
+
if (val.hasOwnProperty(m)) {
|
2601
|
+
commands.push(m);
|
2602
|
+
}
|
2603
|
+
}
|
2604
|
+
val = make_eval(val);
|
2605
|
+
}
|
2606
|
+
self.push(val, {
|
2607
|
+
prompt: method + '> ',
|
2608
|
+
name: method,
|
2609
|
+
command_list: commands
|
2610
|
+
});
|
2611
|
+
} else {
|
2612
|
+
self.error("Command '" + method + "' Not Found");
|
2613
|
+
}
|
2614
|
+
};
|
2615
|
+
})(init_eval);
|
2616
|
+
} else if (typeof init_eval !== 'function') {
|
2617
|
+
throw 'Unknow object "' + String(init_eval) + '" passed as eval';
|
2618
|
+
}
|
2619
|
+
|
2620
|
+
// create json-rpc authentication function
|
2621
|
+
if (url && (typeof settings.login === 'string' || settings.login)) {
|
2622
|
+
settings.login = (function(method) {
|
2623
|
+
var id = 1;
|
2624
|
+
return function(user, passwd, callback) {
|
2625
|
+
self.pause();
|
2626
|
+
$.jrpc(url,
|
2627
|
+
id++,
|
2628
|
+
method,
|
2629
|
+
[user, passwd],
|
2630
|
+
function(response) {
|
2631
|
+
self.resume();
|
2632
|
+
if (!response.error && response.result) {
|
2633
|
+
callback(response.result);
|
2634
|
+
} else {
|
2635
|
+
callback(null);
|
2636
|
+
}
|
2637
|
+
}, function(xhr, status, error) {
|
2638
|
+
self.resume();
|
2639
|
+
self.error('[AJAX\ Response: ' +
|
2640
|
+
status + '\n' +
|
2641
|
+
xhr.responseText);
|
2642
|
+
});
|
2643
|
+
};
|
2644
|
+
//default name is login so you can pass true
|
2645
|
+
})(typeof settings.login === 'boolean' ? 'login' : settings.login);
|
2646
|
+
}
|
2647
|
+
if (validate('prompt', settings.prompt)) {
|
2648
|
+
var interpreters = new Stack({
|
2649
|
+
name: settings.name,
|
2650
|
+
'eval': init_eval,
|
2651
|
+
prompt: settings.prompt,
|
2652
|
+
command_list: command_list,
|
2653
|
+
greetings: settings.greetings
|
2654
|
+
});
|
2655
|
+
var command_line = self.find('.terminal-output').next().cmd({
|
2656
|
+
prompt: settings.prompt,
|
2657
|
+
history: settings.history,
|
2658
|
+
historyFilter: settings.historyFilter,
|
2659
|
+
width: '100%',
|
2660
|
+
keydown: key_down,
|
2661
|
+
keypress: settings.keypress ? function(e) {
|
2662
|
+
return settings.keypress(e, self);
|
2663
|
+
} : null,
|
2664
|
+
onCommandChange: function(command) {
|
2665
|
+
if (typeof settings.onCommandChange === 'function') {
|
2666
|
+
try {
|
2667
|
+
settings.onCommandChange(command, self);
|
2668
|
+
} catch (e) {
|
2669
|
+
display_exception(e, 'onCommandChange');
|
2670
|
+
throw e;
|
2671
|
+
}
|
2672
|
+
}
|
2673
|
+
scroll_to_bottom();
|
2674
|
+
},
|
2675
|
+
commands: commands
|
2676
|
+
});
|
2677
|
+
//num_chars = get_num_chars();
|
2678
|
+
terminals.append(self);
|
2679
|
+
if (settings.enabled === true) {
|
2680
|
+
self.focus(undefined, true);
|
2681
|
+
} else {
|
2682
|
+
self.disable();
|
2683
|
+
}
|
2684
|
+
$(window).resize(self.resize);
|
2685
|
+
self.click(function() {
|
2686
|
+
if (!(pause && terminals.length() > 1 && self === $.terminal.active())) {
|
2687
|
+
self.focus();
|
2688
|
+
}
|
2689
|
+
});
|
2690
|
+
if (options.login && self.token && !self.token() && self.login_name &&
|
2691
|
+
!self.login_name()) {
|
2692
|
+
login();
|
2693
|
+
} else {
|
2694
|
+
initialize();
|
2695
|
+
}
|
2696
|
+
if (typeof $.fn.init.prototype.mousewheel === 'function') {
|
2697
|
+
self.mousewheel(function(event, delta) {
|
2698
|
+
//self.echo(dir(event));
|
2699
|
+
if (delta > 0) {
|
2700
|
+
self.scroll(-40);
|
2701
|
+
} else {
|
2702
|
+
self.scroll(40);
|
2703
|
+
}
|
2704
|
+
return false;
|
2705
|
+
}, true);
|
2706
|
+
}
|
2707
|
+
}
|
2708
|
+
self.data('terminal', self);
|
2709
|
+
return self;
|
2710
|
+
|
2711
|
+
}; //terminal plugin
|
2712
|
+
})(jQuery);
|