kopia lustrzana https://github.com/c9/core
178 wiersze
5.6 KiB
JavaScript
178 wiersze
5.6 KiB
JavaScript
|
define(function(require, exports, module) {
|
||
|
main.consumes = ["immediate", "settings", "Evaluator", "ui", "proc"];
|
||
|
main.provides = ["immediate.bash"];
|
||
|
return main;
|
||
|
|
||
|
|
||
|
function main(options, imports, register) {
|
||
|
var Evaluator = imports.Evaluator;
|
||
|
var settings = imports.settings;
|
||
|
var immediate = imports.immediate;
|
||
|
var proc = imports.proc;
|
||
|
var ui = imports.ui;
|
||
|
|
||
|
/***** Initialization *****/
|
||
|
|
||
|
var plugin = new Evaluator("Ajax.org", main.consumes, {
|
||
|
caption: "Bash",
|
||
|
id: "bash",
|
||
|
mode: "ace/mode/sh",
|
||
|
message: "# Welcome to the Bash REPL."
|
||
|
});
|
||
|
// var emit = plugin.getEmitter();
|
||
|
|
||
|
var bash;
|
||
|
|
||
|
function load() {
|
||
|
}
|
||
|
|
||
|
/***** Evaluator *****/
|
||
|
|
||
|
function canEvaluate(str) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function evaluate(expression, cell, cb) {
|
||
|
if (!expression.trim())
|
||
|
return cell.remove();
|
||
|
// cell.setValue("\n");
|
||
|
cell.setWaiting(true);
|
||
|
cell.setValue("");
|
||
|
scroll(cell);
|
||
|
getBash({}, function(err, bash) {
|
||
|
if (err)
|
||
|
return done(err);
|
||
|
if (bash.cell)
|
||
|
done(new Error("Stopped"));
|
||
|
bash.cell = cell;
|
||
|
cell.tokenizerState = "comment";
|
||
|
bash.stdout.on("data", bash.onData = function(data) {
|
||
|
if (bash.aborted) return;
|
||
|
|
||
|
if (data.indexOf("ß") != -1) {
|
||
|
data = data.replace(/ß\s*/, "");
|
||
|
done();
|
||
|
}
|
||
|
write(cell, data);
|
||
|
});
|
||
|
bash.stderr.on("data", bash.onErr = function(data) {
|
||
|
if (bash.aborted) return;
|
||
|
|
||
|
write(cell, data);
|
||
|
});
|
||
|
bash.on("exit", bash.onExit = function(code) {
|
||
|
bash.exited = true;
|
||
|
if (bash.aborted)
|
||
|
return done(new Error("Process aborted by user"));
|
||
|
else if (code)
|
||
|
return done(new Error("Process exited with code " + code));
|
||
|
done();
|
||
|
});
|
||
|
var code = expression.replace(/\r\n/g, "\n");
|
||
|
code = 'fcn() {\n' + code + '\n}\n'
|
||
|
+ 'sudo(){ /usr/bin/sudo -S -p "###[sudo] password for %p: " "$@" ; }\n'
|
||
|
+ 'exit() { if [ "$1" == "0" ]; then echo ß; else echo "exiting with $1"; fi; command exit $1; }\n'
|
||
|
+ 'fcn "$@" \n echo ß\n';
|
||
|
|
||
|
bash.stdin.write(code);
|
||
|
|
||
|
function done(err) {
|
||
|
var currentCell = bash.cell;
|
||
|
if (!currentCell || !currentCell.session)
|
||
|
currentCell = cell;
|
||
|
bash.stdout.off("data", bash.onData);
|
||
|
bash.stderr.off("data", bash.onErr);
|
||
|
bash.off("exit", bash.onExit);
|
||
|
if (err && err.message)
|
||
|
write(currentCell, "\n" + err.message);
|
||
|
currentCell.setWaiting(false);
|
||
|
bash.cell = null;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function write(cell, data) {
|
||
|
var range = cell.getRange();
|
||
|
if (range) {
|
||
|
cell.insert(range.end, data);
|
||
|
scroll(cell);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function abort() {
|
||
|
if (bash && !bash.exited) {
|
||
|
bash.aborted = true;
|
||
|
bash.kill();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function scroll(cell) {
|
||
|
var editor = cell.session.repl.editor;
|
||
|
if (!editor) // tab isn't active
|
||
|
return;
|
||
|
var renderer = editor.renderer;
|
||
|
// TODO add a better way to scroll ace cursor into view when rendered
|
||
|
setTimeout(function() {
|
||
|
renderer.scrollCursorIntoView();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getBash(opts, callback) {
|
||
|
if (bash && !bash.exited && !bash.aborted)
|
||
|
return callback(null, bash);
|
||
|
proc.spawn("bash", { args: []}, function(err, p) {
|
||
|
bash = p;
|
||
|
callback(err, bash);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getAllProperties(context, callback) {
|
||
|
callback();
|
||
|
}
|
||
|
|
||
|
/***** Lifecycle *****/
|
||
|
|
||
|
plugin.on("load", function() {
|
||
|
load();
|
||
|
});
|
||
|
plugin.on("canEvaluate", function(e) {
|
||
|
return canEvaluate(e.expression);
|
||
|
});
|
||
|
plugin.on("evaluate", function(e) {
|
||
|
return evaluate(e.expression, e.cell, e.callback);
|
||
|
});
|
||
|
plugin.on("enable", function() {
|
||
|
|
||
|
});
|
||
|
plugin.on("disable", function() {
|
||
|
|
||
|
});
|
||
|
plugin.on("unload", function() {
|
||
|
if (bash) {
|
||
|
bash.aborted = true;
|
||
|
bash.kill();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/***** Register and define API *****/
|
||
|
|
||
|
/**
|
||
|
* Simple bash evaluator example for testing
|
||
|
**/
|
||
|
plugin.freezePublicAPI({
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
getAllProperties: getAllProperties,
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
abort: abort
|
||
|
});
|
||
|
|
||
|
register(null, {
|
||
|
"immediate.bash": plugin
|
||
|
});
|
||
|
}
|
||
|
});
|