command_proposal 1.0.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +77 -0
- data/Rakefile +18 -0
- data/app/assets/config/command_proposal_manifest.js +1 -0
- data/app/assets/javascripts/command_proposal/_codemirror.js +9814 -0
- data/app/assets/javascripts/command_proposal/_helpers.js +9 -0
- data/app/assets/javascripts/command_proposal/codemirror-addon-searchcursor.js +296 -0
- data/app/assets/javascripts/command_proposal/codemirror-keymap-sublime.js +720 -0
- data/app/assets/javascripts/command_proposal/codemirror-mode-ruby.js +303 -0
- data/app/assets/javascripts/command_proposal/console.js +195 -0
- data/app/assets/javascripts/command_proposal/feed.js +51 -0
- data/app/assets/javascripts/command_proposal/terminal.js +40 -0
- data/app/assets/javascripts/command_proposal.js +1 -0
- data/app/assets/stylesheets/command_proposal/_variables.scss +0 -0
- data/app/assets/stylesheets/command_proposal/codemirror-rubyblue.scss +27 -0
- data/app/assets/stylesheets/command_proposal/codemirror.scss +367 -0
- data/app/assets/stylesheets/command_proposal/command_proposal.scss +1 -0
- data/app/assets/stylesheets/command_proposal/components.scss +31 -0
- data/app/assets/stylesheets/command_proposal/containers.scss +4 -0
- data/app/assets/stylesheets/command_proposal/icons.scss +12 -0
- data/app/assets/stylesheets/command_proposal/tables.scss +76 -0
- data/app/assets/stylesheets/command_proposal/terminal.scss +72 -0
- data/app/assets/stylesheets/command_proposal.scss +5 -0
- data/app/controllers/command_proposal/engine_controller.rb +6 -0
- data/app/controllers/command_proposal/iterations_controller.rb +83 -0
- data/app/controllers/command_proposal/runner_controller.rb +86 -0
- data/app/controllers/command_proposal/tasks_controller.rb +97 -0
- data/app/helpers/command_proposal/application_helper.rb +58 -0
- data/app/helpers/command_proposal/icons_helper.rb +15 -0
- data/app/helpers/command_proposal/params_helper.rb +63 -0
- data/app/helpers/command_proposal/permissions_helper.rb +42 -0
- data/app/jobs/command_proposal/application_job.rb +4 -0
- data/app/jobs/command_proposal/command_runner_job.rb +11 -0
- data/app/models/command_proposal/comment.rb +14 -0
- data/app/models/command_proposal/iteration.rb +78 -0
- data/app/models/command_proposal/service/external_belong.rb +48 -0
- data/app/models/command_proposal/service/json_wrapper.rb +18 -0
- data/app/models/command_proposal/service/proposal_presenter.rb +39 -0
- data/app/models/command_proposal/task.rb +106 -0
- data/app/views/command_proposal/tasks/_console_show.html.erb +44 -0
- data/app/views/command_proposal/tasks/_function_show.html.erb +54 -0
- data/app/views/command_proposal/tasks/_lines.html.erb +8 -0
- data/app/views/command_proposal/tasks/_module_show.html.erb +33 -0
- data/app/views/command_proposal/tasks/_past_iterations_list.html.erb +20 -0
- data/app/views/command_proposal/tasks/_task_detail_table.html.erb +31 -0
- data/app/views/command_proposal/tasks/_task_show.html.erb +55 -0
- data/app/views/command_proposal/tasks/error.html.erb +4 -0
- data/app/views/command_proposal/tasks/form.html.erb +64 -0
- data/app/views/command_proposal/tasks/index.html.erb +44 -0
- data/app/views/command_proposal/tasks/show.html.erb +10 -0
- data/config/routes.rb +11 -0
- data/lib/command_proposal/configuration.rb +41 -0
- data/lib/command_proposal/engine.rb +6 -0
- data/lib/command_proposal/services/command_interpreter.rb +108 -0
- data/lib/command_proposal/services/runner.rb +157 -0
- data/lib/command_proposal/version.rb +3 -0
- data/lib/command_proposal.rb +27 -0
- data/lib/generators/command_proposal/install/install_generator.rb +28 -0
- data/lib/generators/command_proposal/install/templates/initializer.rb +47 -0
- data/lib/generators/command_proposal/install/templates/install_command_proposal.rb +40 -0
- data/lib/tasks/command_proposal_tasks.rake +4 -0
- metadata +167 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
3
|
+
|
4
|
+
(function(mod) {
|
5
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
6
|
+
mod(require("../../lib/codemirror"));
|
7
|
+
else if (typeof define == "function" && define.amd) // AMD
|
8
|
+
define(["../../lib/codemirror"], mod);
|
9
|
+
else // Plain browser env
|
10
|
+
mod(CodeMirror);
|
11
|
+
})(function(CodeMirror) {
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
function wordObj(words) {
|
15
|
+
var o = {};
|
16
|
+
for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
|
17
|
+
return o;
|
18
|
+
}
|
19
|
+
|
20
|
+
var keywordList = [
|
21
|
+
"alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
|
22
|
+
"elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
|
23
|
+
"redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
|
24
|
+
"until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
|
25
|
+
"caller", "lambda", "proc", "public", "protected", "private", "require", "load",
|
26
|
+
"require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
|
27
|
+
], keywords = wordObj(keywordList);
|
28
|
+
|
29
|
+
var indentWords = wordObj(["def", "class", "case", "for", "while", "until", "module", "then",
|
30
|
+
"catch", "loop", "proc", "begin"]);
|
31
|
+
var dedentWords = wordObj(["end", "until"]);
|
32
|
+
var opening = {"[": "]", "{": "}", "(": ")"};
|
33
|
+
var closing = {"]": "[", "}": "{", ")": "("};
|
34
|
+
|
35
|
+
CodeMirror.defineMode("ruby", function(config) {
|
36
|
+
var curPunc;
|
37
|
+
|
38
|
+
function chain(newtok, stream, state) {
|
39
|
+
state.tokenize.push(newtok);
|
40
|
+
return newtok(stream, state);
|
41
|
+
}
|
42
|
+
|
43
|
+
function tokenBase(stream, state) {
|
44
|
+
if (stream.sol() && stream.match("=begin") && stream.eol()) {
|
45
|
+
state.tokenize.push(readBlockComment);
|
46
|
+
return "comment";
|
47
|
+
}
|
48
|
+
if (stream.eatSpace()) return null;
|
49
|
+
var ch = stream.next(), m;
|
50
|
+
if (ch == "`" || ch == "'" || ch == '"') {
|
51
|
+
return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
|
52
|
+
} else if (ch == "/") {
|
53
|
+
if (regexpAhead(stream))
|
54
|
+
return chain(readQuoted(ch, "string-2", true), stream, state);
|
55
|
+
else
|
56
|
+
return "operator";
|
57
|
+
} else if (ch == "%") {
|
58
|
+
var style = "string", embed = true;
|
59
|
+
if (stream.eat("s")) style = "atom";
|
60
|
+
else if (stream.eat(/[WQ]/)) style = "string";
|
61
|
+
else if (stream.eat(/[r]/)) style = "string-2";
|
62
|
+
else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; }
|
63
|
+
var delim = stream.eat(/[^\w\s=]/);
|
64
|
+
if (!delim) return "operator";
|
65
|
+
if (opening.propertyIsEnumerable(delim)) delim = opening[delim];
|
66
|
+
return chain(readQuoted(delim, style, embed, true), stream, state);
|
67
|
+
} else if (ch == "#") {
|
68
|
+
stream.skipToEnd();
|
69
|
+
return "comment";
|
70
|
+
} else if (ch == "<" && (m = stream.match(/^<([-~])[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) {
|
71
|
+
return chain(readHereDoc(m[2], m[1]), stream, state);
|
72
|
+
} else if (ch == "0") {
|
73
|
+
if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
|
74
|
+
else if (stream.eat("b")) stream.eatWhile(/[01]/);
|
75
|
+
else stream.eatWhile(/[0-7]/);
|
76
|
+
return "number";
|
77
|
+
} else if (/\d/.test(ch)) {
|
78
|
+
stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
|
79
|
+
return "number";
|
80
|
+
} else if (ch == "?") {
|
81
|
+
while (stream.match(/^\\[CM]-/)) {}
|
82
|
+
if (stream.eat("\\")) stream.eatWhile(/\w/);
|
83
|
+
else stream.next();
|
84
|
+
return "string";
|
85
|
+
} else if (ch == ":") {
|
86
|
+
if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
|
87
|
+
if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
|
88
|
+
|
89
|
+
// :> :>> :< :<< are valid symbols
|
90
|
+
if (stream.eat(/[\<\>]/)) {
|
91
|
+
stream.eat(/[\<\>]/);
|
92
|
+
return "atom";
|
93
|
+
}
|
94
|
+
|
95
|
+
// :+ :- :/ :* :| :& :! are valid symbols
|
96
|
+
if (stream.eat(/[\+\-\*\/\&\|\:\!]/)) {
|
97
|
+
return "atom";
|
98
|
+
}
|
99
|
+
|
100
|
+
// Symbols can't start by a digit
|
101
|
+
if (stream.eat(/[a-zA-Z$@_\xa1-\uffff]/)) {
|
102
|
+
stream.eatWhile(/[\w$\xa1-\uffff]/);
|
103
|
+
// Only one ? ! = is allowed and only as the last character
|
104
|
+
stream.eat(/[\?\!\=]/);
|
105
|
+
return "atom";
|
106
|
+
}
|
107
|
+
return "operator";
|
108
|
+
} else if (ch == "@" && stream.match(/^@?[a-zA-Z_\xa1-\uffff]/)) {
|
109
|
+
stream.eat("@");
|
110
|
+
stream.eatWhile(/[\w\xa1-\uffff]/);
|
111
|
+
return "variable-2";
|
112
|
+
} else if (ch == "$") {
|
113
|
+
if (stream.eat(/[a-zA-Z_]/)) {
|
114
|
+
stream.eatWhile(/[\w]/);
|
115
|
+
} else if (stream.eat(/\d/)) {
|
116
|
+
stream.eat(/\d/);
|
117
|
+
} else {
|
118
|
+
stream.next(); // Must be a special global like $: or $!
|
119
|
+
}
|
120
|
+
return "variable-3";
|
121
|
+
} else if (/[a-zA-Z_\xa1-\uffff]/.test(ch)) {
|
122
|
+
stream.eatWhile(/[\w\xa1-\uffff]/);
|
123
|
+
stream.eat(/[\?\!]/);
|
124
|
+
if (stream.eat(":")) return "atom";
|
125
|
+
return "ident";
|
126
|
+
} else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
|
127
|
+
curPunc = "|";
|
128
|
+
return null;
|
129
|
+
} else if (/[\(\)\[\]{}\\;]/.test(ch)) {
|
130
|
+
curPunc = ch;
|
131
|
+
return null;
|
132
|
+
} else if (ch == "-" && stream.eat(">")) {
|
133
|
+
return "arrow";
|
134
|
+
} else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
|
135
|
+
var more = stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
|
136
|
+
if (ch == "." && !more) curPunc = ".";
|
137
|
+
return "operator";
|
138
|
+
} else {
|
139
|
+
return null;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
function regexpAhead(stream) {
|
144
|
+
var start = stream.pos, depth = 0, next, found = false, escaped = false
|
145
|
+
while ((next = stream.next()) != null) {
|
146
|
+
if (!escaped) {
|
147
|
+
if ("[{(".indexOf(next) > -1) {
|
148
|
+
depth++
|
149
|
+
} else if ("]})".indexOf(next) > -1) {
|
150
|
+
depth--
|
151
|
+
if (depth < 0) break
|
152
|
+
} else if (next == "/" && depth == 0) {
|
153
|
+
found = true
|
154
|
+
break
|
155
|
+
}
|
156
|
+
escaped = next == "\\"
|
157
|
+
} else {
|
158
|
+
escaped = false
|
159
|
+
}
|
160
|
+
}
|
161
|
+
stream.backUp(stream.pos - start)
|
162
|
+
return found
|
163
|
+
}
|
164
|
+
|
165
|
+
function tokenBaseUntilBrace(depth) {
|
166
|
+
if (!depth) depth = 1;
|
167
|
+
return function(stream, state) {
|
168
|
+
if (stream.peek() == "}") {
|
169
|
+
if (depth == 1) {
|
170
|
+
state.tokenize.pop();
|
171
|
+
return state.tokenize[state.tokenize.length-1](stream, state);
|
172
|
+
} else {
|
173
|
+
state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1);
|
174
|
+
}
|
175
|
+
} else if (stream.peek() == "{") {
|
176
|
+
state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1);
|
177
|
+
}
|
178
|
+
return tokenBase(stream, state);
|
179
|
+
};
|
180
|
+
}
|
181
|
+
function tokenBaseOnce() {
|
182
|
+
var alreadyCalled = false;
|
183
|
+
return function(stream, state) {
|
184
|
+
if (alreadyCalled) {
|
185
|
+
state.tokenize.pop();
|
186
|
+
return state.tokenize[state.tokenize.length-1](stream, state);
|
187
|
+
}
|
188
|
+
alreadyCalled = true;
|
189
|
+
return tokenBase(stream, state);
|
190
|
+
};
|
191
|
+
}
|
192
|
+
function readQuoted(quote, style, embed, unescaped) {
|
193
|
+
return function(stream, state) {
|
194
|
+
var escaped = false, ch;
|
195
|
+
|
196
|
+
if (state.context.type === 'read-quoted-paused') {
|
197
|
+
state.context = state.context.prev;
|
198
|
+
stream.eat("}");
|
199
|
+
}
|
200
|
+
|
201
|
+
while ((ch = stream.next()) != null) {
|
202
|
+
if (ch == quote && (unescaped || !escaped)) {
|
203
|
+
state.tokenize.pop();
|
204
|
+
break;
|
205
|
+
}
|
206
|
+
if (embed && ch == "#" && !escaped) {
|
207
|
+
if (stream.eat("{")) {
|
208
|
+
if (quote == "}") {
|
209
|
+
state.context = {prev: state.context, type: 'read-quoted-paused'};
|
210
|
+
}
|
211
|
+
state.tokenize.push(tokenBaseUntilBrace());
|
212
|
+
break;
|
213
|
+
} else if (/[@\$]/.test(stream.peek())) {
|
214
|
+
state.tokenize.push(tokenBaseOnce());
|
215
|
+
break;
|
216
|
+
}
|
217
|
+
}
|
218
|
+
escaped = !escaped && ch == "\\";
|
219
|
+
}
|
220
|
+
return style;
|
221
|
+
};
|
222
|
+
}
|
223
|
+
function readHereDoc(phrase, mayIndent) {
|
224
|
+
return function(stream, state) {
|
225
|
+
if (mayIndent) stream.eatSpace()
|
226
|
+
if (stream.match(phrase)) state.tokenize.pop();
|
227
|
+
else stream.skipToEnd();
|
228
|
+
return "string";
|
229
|
+
};
|
230
|
+
}
|
231
|
+
function readBlockComment(stream, state) {
|
232
|
+
if (stream.sol() && stream.match("=end") && stream.eol())
|
233
|
+
state.tokenize.pop();
|
234
|
+
stream.skipToEnd();
|
235
|
+
return "comment";
|
236
|
+
}
|
237
|
+
|
238
|
+
return {
|
239
|
+
startState: function() {
|
240
|
+
return {tokenize: [tokenBase],
|
241
|
+
indented: 0,
|
242
|
+
context: {type: "top", indented: -config.indentUnit},
|
243
|
+
continuedLine: false,
|
244
|
+
lastTok: null,
|
245
|
+
varList: false};
|
246
|
+
},
|
247
|
+
|
248
|
+
token: function(stream, state) {
|
249
|
+
curPunc = null;
|
250
|
+
if (stream.sol()) state.indented = stream.indentation();
|
251
|
+
var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
|
252
|
+
var thisTok = curPunc;
|
253
|
+
if (style == "ident") {
|
254
|
+
var word = stream.current();
|
255
|
+
style = state.lastTok == "." ? "property"
|
256
|
+
: keywords.propertyIsEnumerable(stream.current()) ? "keyword"
|
257
|
+
: /^[A-Z]/.test(word) ? "tag"
|
258
|
+
: (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
|
259
|
+
: "variable";
|
260
|
+
if (style == "keyword") {
|
261
|
+
thisTok = word;
|
262
|
+
if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
|
263
|
+
else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
|
264
|
+
else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
|
265
|
+
kwtype = "indent";
|
266
|
+
else if (word == "do" && state.context.indented < state.indented)
|
267
|
+
kwtype = "indent";
|
268
|
+
}
|
269
|
+
}
|
270
|
+
if (curPunc || (style && style != "comment")) state.lastTok = thisTok;
|
271
|
+
if (curPunc == "|") state.varList = !state.varList;
|
272
|
+
|
273
|
+
if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
|
274
|
+
state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
|
275
|
+
else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
|
276
|
+
state.context = state.context.prev;
|
277
|
+
|
278
|
+
if (stream.eol())
|
279
|
+
state.continuedLine = (curPunc == "\\" || style == "operator");
|
280
|
+
return style;
|
281
|
+
},
|
282
|
+
|
283
|
+
indent: function(state, textAfter) {
|
284
|
+
if (state.tokenize[state.tokenize.length-1] != tokenBase) return CodeMirror.Pass;
|
285
|
+
var firstChar = textAfter && textAfter.charAt(0);
|
286
|
+
var ct = state.context;
|
287
|
+
var closed = ct.type == closing[firstChar] ||
|
288
|
+
ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
|
289
|
+
return ct.indented + (closed ? 0 : config.indentUnit) +
|
290
|
+
(state.continuedLine ? config.indentUnit : 0);
|
291
|
+
},
|
292
|
+
|
293
|
+
electricInput: /^\s*(?:end|rescue|elsif|else|\})$/,
|
294
|
+
lineComment: "#",
|
295
|
+
fold: "indent"
|
296
|
+
};
|
297
|
+
});
|
298
|
+
|
299
|
+
CodeMirror.defineMIME("text/x-ruby", "ruby");
|
300
|
+
|
301
|
+
CodeMirror.registerHelper("hintWords", "ruby", keywordList);
|
302
|
+
|
303
|
+
});
|
@@ -0,0 +1,195 @@
|
|
1
|
+
// Add tab / shift-tab for changing indents
|
2
|
+
docReady(function() {
|
3
|
+
var cmdconsole = document.querySelector(".cmd-console")
|
4
|
+
|
5
|
+
if (cmdconsole) {
|
6
|
+
var console_input = document.querySelector(".cmd-console .cmd-entry")
|
7
|
+
var lines = document.querySelector(".cmd-console .lines")
|
8
|
+
var queue = Promise.resolve()
|
9
|
+
var history_cmd_idx = undefined
|
10
|
+
var stored_entry = undefined
|
11
|
+
var commands = getPrevCommands()
|
12
|
+
|
13
|
+
cmdconsole.addEventListener("click", function(evt) {
|
14
|
+
if (!window.getSelection().toString().length && console_input) {
|
15
|
+
console_input.focus()
|
16
|
+
}
|
17
|
+
})
|
18
|
+
|
19
|
+
cmdconsole.addEventListener("keydown", function(evt) {
|
20
|
+
// evt.shiftKey
|
21
|
+
// evt.ctrlKey
|
22
|
+
// evt.altKey
|
23
|
+
// evt.metaKey (windows key or CMD key)
|
24
|
+
|
25
|
+
if (evt.key == "Enter" && !evt.shiftKey) {
|
26
|
+
evt.preventDefault()
|
27
|
+
submitConsoleCode()
|
28
|
+
return false
|
29
|
+
}
|
30
|
+
|
31
|
+
if (evt.ctrlKey && evt.key == "c") {
|
32
|
+
history_cmd_idx = undefined
|
33
|
+
stored_entry = console_input.textContent
|
34
|
+
console_input.textContent = ""
|
35
|
+
}
|
36
|
+
|
37
|
+
if (isNaN(history_cmd_idx)) { history_cmd_idx = undefined }
|
38
|
+
if (evt.key == "ArrowUp" && getCaretIndex(console_input) == 0) {
|
39
|
+
handleUpKey(evt)
|
40
|
+
}
|
41
|
+
if (evt.key == "ArrowDown" && getCaretIndex(console_input) == console_input.textContent.length) {
|
42
|
+
handleDownKey()
|
43
|
+
}
|
44
|
+
})
|
45
|
+
|
46
|
+
function handleUpKey() {
|
47
|
+
if (history_cmd_idx == undefined) {
|
48
|
+
// Not scrolling through history
|
49
|
+
if (console_input.textContent) {
|
50
|
+
// Text has been entered
|
51
|
+
stored_entry = console_input.textContent
|
52
|
+
}
|
53
|
+
// Set history index to begin scrolling
|
54
|
+
history_cmd_idx = commands.length
|
55
|
+
} else if (history_cmd_idx == 0) {
|
56
|
+
return
|
57
|
+
}
|
58
|
+
|
59
|
+
history_cmd_idx -= 1
|
60
|
+
console_input.textContent = commands[history_cmd_idx]
|
61
|
+
}
|
62
|
+
|
63
|
+
function handleDownKey() {
|
64
|
+
if (history_cmd_idx != undefined) {
|
65
|
+
var cmd = ""
|
66
|
+
if (history_cmd_idx < commands.length - 1) {
|
67
|
+
history_cmd_idx += 1
|
68
|
+
cmd = commands[history_cmd_idx]
|
69
|
+
} else if (stored_entry && history_cmd_idx == commands.length - 1) {
|
70
|
+
history_cmd_idx += 1
|
71
|
+
cmd = stored_entry
|
72
|
+
} else {
|
73
|
+
history_cmd_idx = undefined
|
74
|
+
}
|
75
|
+
|
76
|
+
console_input.textContent = cmd
|
77
|
+
if (cmd) {
|
78
|
+
setCaretIndex(console_input, console_input.textContent.length)
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
function getCaretIndex(element) {
|
84
|
+
var position = 0
|
85
|
+
if (window.getSelection) {
|
86
|
+
var selection = window.getSelection()
|
87
|
+
if (selection.rangeCount !== 0) {
|
88
|
+
var range = window.getSelection().getRangeAt(0)
|
89
|
+
var preCaretRange = range.cloneRange()
|
90
|
+
preCaretRange.selectNodeContents(element)
|
91
|
+
preCaretRange.setEnd(range.endContainer, range.endOffset)
|
92
|
+
position = preCaretRange.toString().length
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
return position
|
97
|
+
}
|
98
|
+
|
99
|
+
function setCaretIndex(element, idx) {
|
100
|
+
var setpos = document.createRange()
|
101
|
+
var set = window.getSelection()
|
102
|
+
|
103
|
+
// Set start position of range
|
104
|
+
setpos.setStart(element.childNodes[0], idx)
|
105
|
+
|
106
|
+
// Collapse range within its boundary points
|
107
|
+
// Returns boolean
|
108
|
+
setpos.collapse(true)
|
109
|
+
|
110
|
+
// Remove all ranges set
|
111
|
+
set.removeAllRanges()
|
112
|
+
|
113
|
+
// Add range with respect to range object.
|
114
|
+
set.addRange(setpos)
|
115
|
+
|
116
|
+
// Set cursor on focus
|
117
|
+
element.focus()
|
118
|
+
}
|
119
|
+
|
120
|
+
function getOffset(el) {
|
121
|
+
const rect = el.getBoundingClientRect()
|
122
|
+
return {
|
123
|
+
left: rect.left,
|
124
|
+
top: rect.top
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
function getPrevCommands() {
|
129
|
+
return Array.prototype.map.call(document.querySelectorAll(".line:not(.cmd-input)"), function(line) {
|
130
|
+
var text_node = Array.prototype.find.call(line.childNodes, function(node) {
|
131
|
+
return node.nodeName == "#text"
|
132
|
+
})
|
133
|
+
|
134
|
+
return text_node ? text_node.textContent : ""
|
135
|
+
})
|
136
|
+
}
|
137
|
+
|
138
|
+
function submitConsoleCode() {
|
139
|
+
var line = document.createElement("div")
|
140
|
+
line.classList.add("line")
|
141
|
+
line.textContent = console_input.textContent
|
142
|
+
|
143
|
+
console_input.textContent = ""
|
144
|
+
lines.appendChild(line)
|
145
|
+
stored_entry = undefined
|
146
|
+
history_cmd_idx = undefined
|
147
|
+
|
148
|
+
runConsoleCode(line)
|
149
|
+
}
|
150
|
+
|
151
|
+
function runConsoleCode(line) {
|
152
|
+
if (/^[\s\n]*$/.test(line.textContent)) { return }
|
153
|
+
|
154
|
+
commands.push(line.textContent)
|
155
|
+
queue = queue.then(async function() {
|
156
|
+
$.rails.refreshCSRFTokens()
|
157
|
+
|
158
|
+
var params = { code: line.textContent, task_id: cmdconsole.dataset.task }
|
159
|
+
|
160
|
+
var res = await fetch(cmdconsole.dataset.exeUrl, {
|
161
|
+
method: "POST",
|
162
|
+
headers: {
|
163
|
+
"Content-Type": "application/json",
|
164
|
+
"X-CSRF-Token": $.rails.csrfToken()
|
165
|
+
},
|
166
|
+
body: JSON.stringify(params)
|
167
|
+
}).then(function(res) {
|
168
|
+
if (res.ok) {
|
169
|
+
return res.json()
|
170
|
+
} else {
|
171
|
+
throw new Error("Server error")
|
172
|
+
}
|
173
|
+
}).catch(function(err) {
|
174
|
+
return {
|
175
|
+
error: err,
|
176
|
+
}
|
177
|
+
})
|
178
|
+
|
179
|
+
var json = await res
|
180
|
+
|
181
|
+
var result = document.createElement("div")
|
182
|
+
result.classList.add("result")
|
183
|
+
|
184
|
+
if (json.error) {
|
185
|
+
result.classList.add("cmd-error")
|
186
|
+
result.textContent = json.error
|
187
|
+
} else {
|
188
|
+
result.textContent = json.result
|
189
|
+
}
|
190
|
+
|
191
|
+
line.appendChild(result)
|
192
|
+
})
|
193
|
+
}
|
194
|
+
}
|
195
|
+
})
|