rack-webconsole-pry 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +1 -1
- data/lib/rack/webconsole/version.rb +1 -1
- data/public/webconsole.js +236 -59
- metadata +3 -3
data/Gemfile.lock
CHANGED
data/public/webconsole.js
CHANGED
@@ -1,5 +1,193 @@
|
|
1
1
|
(function($) {
|
2
2
|
|
3
|
+
/* AnsiParse */
|
4
|
+
ansiparse = function (str) {
|
5
|
+
//
|
6
|
+
// I'm terrible at writing parsers.
|
7
|
+
//
|
8
|
+
var matchingControl = null,
|
9
|
+
matchingData = null,
|
10
|
+
matchingText = '',
|
11
|
+
ansiState = [],
|
12
|
+
result = [],
|
13
|
+
state = {},
|
14
|
+
eraseChar;
|
15
|
+
|
16
|
+
//
|
17
|
+
// General workflow for this thing is:
|
18
|
+
// \033\[33mText
|
19
|
+
// | | |
|
20
|
+
// | | matchingText
|
21
|
+
// | matchingData
|
22
|
+
// matchingControl
|
23
|
+
//
|
24
|
+
// In further steps we hope it's all going to be fine. It usually is.
|
25
|
+
//
|
26
|
+
|
27
|
+
//
|
28
|
+
// Erases a char from the output
|
29
|
+
//
|
30
|
+
eraseChar = function () {
|
31
|
+
var index, text;
|
32
|
+
if (matchingText.length) {
|
33
|
+
matchingText = matchingText.substr(0, matchingText.length - 1);
|
34
|
+
}
|
35
|
+
else if (result.length) {
|
36
|
+
index = result.length - 1;
|
37
|
+
text = result[index].text;
|
38
|
+
if (text.length === 1) {
|
39
|
+
//
|
40
|
+
// A result bit was fully deleted, pop it out to simplify the final output
|
41
|
+
//
|
42
|
+
result.pop();
|
43
|
+
}
|
44
|
+
else {
|
45
|
+
result[index].text = text.substr(0, text.length - 1);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
for (var i = 0; i < str.length; i++) {
|
51
|
+
if (matchingControl != null) {
|
52
|
+
if (matchingControl == '\u001B' && str[i] == '\[') {
|
53
|
+
//
|
54
|
+
// We've matched full control code. Lets start matching formating data.
|
55
|
+
//
|
56
|
+
|
57
|
+
//
|
58
|
+
// "emit" matched text with correct state
|
59
|
+
//
|
60
|
+
if (matchingText) {
|
61
|
+
state.text = matchingText;
|
62
|
+
result.push(state);
|
63
|
+
state = {};
|
64
|
+
matchingText = "";
|
65
|
+
}
|
66
|
+
|
67
|
+
matchingControl = null;
|
68
|
+
matchingData = '';
|
69
|
+
}
|
70
|
+
else {
|
71
|
+
//
|
72
|
+
// We failed to match anything - most likely a bad control code. We
|
73
|
+
// go back to matching regular strings.
|
74
|
+
//
|
75
|
+
matchingText += matchingControl + str[i];
|
76
|
+
matchingControl = null;
|
77
|
+
}
|
78
|
+
continue;
|
79
|
+
}
|
80
|
+
else if (matchingData != null) {
|
81
|
+
if (str[i] == ';') {
|
82
|
+
//
|
83
|
+
// `;` separates many formatting codes, for example: `\033[33;43m`
|
84
|
+
// means that both `33` and `43` should be applied.
|
85
|
+
//
|
86
|
+
// TODO: this can be simplified by modifying state here.
|
87
|
+
//
|
88
|
+
ansiState.push(matchingData);
|
89
|
+
matchingData = '';
|
90
|
+
}
|
91
|
+
else if (str[i] == 'm') {
|
92
|
+
//
|
93
|
+
// `m` finished whole formatting code. We can proceed to matching
|
94
|
+
// formatted text.
|
95
|
+
//
|
96
|
+
ansiState.push(matchingData);
|
97
|
+
matchingData = null;
|
98
|
+
matchingText = '';
|
99
|
+
|
100
|
+
//
|
101
|
+
// Convert matched formatting data into user-friendly state object.
|
102
|
+
//
|
103
|
+
// TODO: DRY.
|
104
|
+
//
|
105
|
+
ansiState.forEach(function (ansiCode) {
|
106
|
+
if (ansiparse.foregroundColors[ansiCode]) {
|
107
|
+
state.foreground = ansiparse.foregroundColors[ansiCode];
|
108
|
+
}
|
109
|
+
else if (ansiparse.backgroundColors[ansiCode]) {
|
110
|
+
state.background = ansiparse.backgroundColors[ansiCode];
|
111
|
+
}
|
112
|
+
else if (ansiCode == 39) {
|
113
|
+
delete state.foreground;
|
114
|
+
}
|
115
|
+
else if (ansiCode == 49) {
|
116
|
+
delete state.background;
|
117
|
+
}
|
118
|
+
else if (ansiparse.styles[ansiCode]) {
|
119
|
+
state[ansiparse.styles[ansiCode]] = true;
|
120
|
+
}
|
121
|
+
else if (ansiCode == 22) {
|
122
|
+
state.bold = false;
|
123
|
+
}
|
124
|
+
else if (ansiCode == 23) {
|
125
|
+
state.italic = false;
|
126
|
+
}
|
127
|
+
else if (ansiCode == 24) {
|
128
|
+
state.underline = false;
|
129
|
+
}
|
130
|
+
});
|
131
|
+
ansiState = [];
|
132
|
+
}
|
133
|
+
else {
|
134
|
+
matchingData += str[i];
|
135
|
+
}
|
136
|
+
continue;
|
137
|
+
}
|
138
|
+
|
139
|
+
if (str[i] == '\u001B') {
|
140
|
+
matchingControl = str[i];
|
141
|
+
}
|
142
|
+
else if (str[i] == '\u0008') {
|
143
|
+
eraseChar();
|
144
|
+
}
|
145
|
+
else {
|
146
|
+
matchingText += str[i];
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
if (matchingText) {
|
151
|
+
state.text = matchingText + (matchingControl ? matchingControl : '');
|
152
|
+
result.push(state);
|
153
|
+
}
|
154
|
+
return result;
|
155
|
+
}
|
156
|
+
|
157
|
+
ansiparse.foregroundColors = {
|
158
|
+
'30': 'black',
|
159
|
+
'31': 'red',
|
160
|
+
'32': 'green',
|
161
|
+
'33': 'yellow',
|
162
|
+
'34': 'blue',
|
163
|
+
'35': 'magenta',
|
164
|
+
'36': 'cyan',
|
165
|
+
'37': 'white',
|
166
|
+
'90': 'grey'
|
167
|
+
};
|
168
|
+
|
169
|
+
ansiparse.backgroundColors = {
|
170
|
+
'40': 'black',
|
171
|
+
'41': 'red',
|
172
|
+
'42': 'green',
|
173
|
+
'43': 'yellow',
|
174
|
+
'44': 'blue',
|
175
|
+
'45': 'magenta',
|
176
|
+
'46': 'cyan',
|
177
|
+
'47': 'white'
|
178
|
+
};
|
179
|
+
|
180
|
+
ansiparse.styles = {
|
181
|
+
'1': 'bold',
|
182
|
+
'3': 'italic',
|
183
|
+
'4': 'underline'
|
184
|
+
};
|
185
|
+
|
186
|
+
if (typeof module == "object" && typeof window == "undefined") {
|
187
|
+
module.exports = ansiparse;
|
188
|
+
}
|
189
|
+
|
190
|
+
/* app */
|
3
191
|
var webconsole = {
|
4
192
|
history:[],
|
5
193
|
pointer:0,
|
@@ -10,72 +198,59 @@
|
|
10
198
|
e.preventDefault();
|
11
199
|
});
|
12
200
|
|
13
|
-
var prevStyle = {
|
14
|
-
color: "#ffffff",
|
15
|
-
bold: false,
|
16
|
-
underline: false
|
17
|
-
}
|
18
|
-
|
19
201
|
// colors
|
20
202
|
var colors = {
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
203
|
+
'black': "#eeeeee",
|
204
|
+
'red': "#ff6c60",
|
205
|
+
'green': "#a8ff60",
|
206
|
+
'yellow': "#ffffb6",
|
207
|
+
'blue': "#96cbfe",
|
208
|
+
'magenta': "#ff73fd",
|
209
|
+
'cyan': "#c6c5fe",
|
210
|
+
'white': "#eeeeee"
|
29
211
|
}
|
30
212
|
var boldColors = {
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
213
|
+
'black': "#7c7c7c",
|
214
|
+
'red': "#ffb6b0",
|
215
|
+
'green': "#ceffac",
|
216
|
+
'yellow': "#ffffcb",
|
217
|
+
'blue': "#b5dcfe",
|
218
|
+
'magenta': "#ff9cfe",
|
219
|
+
'cyan': "#dfdffe",
|
220
|
+
'white': "#ffffff"
|
39
221
|
}
|
40
222
|
|
41
|
-
function
|
223
|
+
function subColor(color, elem)
|
42
224
|
{
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
225
|
+
if (color == undefined) color = 'white';
|
226
|
+
if (elem.bold && boldColors[color] != undefined) {
|
227
|
+
color = boldColors[color];
|
228
|
+
} else if (!elem.bold && colors[color] != undefined) {
|
229
|
+
color = colors[color];
|
230
|
+
}
|
231
|
+
return color;
|
48
232
|
}
|
49
|
-
function
|
233
|
+
function parseBashString(str, into)
|
50
234
|
{
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
235
|
+
$.each(ansiparse(str), function(idx, elem) {
|
236
|
+
if (elem.text.length == 1 && elem.text[0] == '\n') {
|
237
|
+
into.append("<br>");
|
238
|
+
return true;
|
239
|
+
}
|
240
|
+
var domElem = $('<span></span>');
|
241
|
+
domElem.text(elem.text);
|
242
|
+
domElem.html(domElem.text().replace(/\n/g, "<br>"));
|
243
|
+
domElem.css('color', subColor(elem.foreground, elem));
|
244
|
+
if (elem.bold)
|
245
|
+
domElem.css('font-weight', 'bold');
|
246
|
+
if (elem.italic)
|
247
|
+
domElem.css('font-style', 'italic');
|
248
|
+
if (elem.underline)
|
249
|
+
domElem.css('text-decoration', 'underline');
|
250
|
+
if (elem.background)
|
251
|
+
domElem.css('background-color', subColor(elem.background, elem));
|
252
|
+
into.append(domElem);
|
69
253
|
});
|
70
|
-
return 'color:'+prevStyle['color']+';font-weight:'+prevStyle['bold']+
|
71
|
-
';text-decoration:'+prevStyle['underline'];
|
72
|
-
}
|
73
|
-
function parseBashString(str)
|
74
|
-
{
|
75
|
-
str = str.replace(/\u001B\[([0-9;]+)m/g, function(fm, sm) {
|
76
|
-
return '</span><span style="'+bashColorToHtml(sm)+'">';
|
77
|
-
}).replace(/\n/g, "<br>");
|
78
|
-
return '<span>'+str+'</span>';
|
79
254
|
}
|
80
255
|
$("#rack-webconsole form input").keyup(function(event) {
|
81
256
|
function escapeHTML(string) {
|
@@ -97,10 +272,12 @@
|
|
97
272
|
data: ({query: webconsole.query.val(), token: "$TOKEN"}),
|
98
273
|
success: function (data) {
|
99
274
|
var query_class = data.previous_multi_line ? 'query_multiline' : 'query';
|
100
|
-
var result = "<div class='" + query_class + "'>"
|
101
|
-
|
275
|
+
var result = $("<div class='" + query_class + "'></div>");
|
276
|
+
parseBashString(escapeHTML(data.prompt), result);
|
102
277
|
if (!data.multi_line) {
|
103
|
-
|
278
|
+
var mresult = $("<div class='result'></div>");
|
279
|
+
parseBashString(escapeHTML(data.result), mresult);
|
280
|
+
result.append(mresult);
|
104
281
|
}
|
105
282
|
$("#rack-webconsole .results").append(result);
|
106
283
|
$("#rack-webconsole .results_wrapper").scrollTop(
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-webconsole-pry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -203,7 +203,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
203
203
|
version: '0'
|
204
204
|
segments:
|
205
205
|
- 0
|
206
|
-
hash:
|
206
|
+
hash: 1992267155081239539
|
207
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
208
|
none: false
|
209
209
|
requirements:
|
@@ -212,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
212
|
version: '0'
|
213
213
|
segments:
|
214
214
|
- 0
|
215
|
-
hash:
|
215
|
+
hash: 1992267155081239539
|
216
216
|
requirements: []
|
217
217
|
rubyforge_project: rack-webconsole-pry
|
218
218
|
rubygems_version: 1.8.24
|