c9-core/plugins/c9.ide.immediate/evaluators/bash.js

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
});
}
});