kopia lustrzana https://github.com/c9/core
911 wiersze
34 KiB
JavaScript
911 wiersze
34 KiB
JavaScript
define(function(require, module, exports) {
|
|
main.consumes = [
|
|
"c9", "Plugin", "run", "settings", "menus", "tabbehavior", "ace",
|
|
"commands", "layout", "tabManager", "preferences", "ui", "fs",
|
|
"layout", "debugger", "tree", "dialog.error", "util", "console", "save"
|
|
];
|
|
main.provides = ["run.gui"];
|
|
return main;
|
|
|
|
function main(options, imports, register) {
|
|
var Plugin = imports.Plugin;
|
|
var settings = imports.settings;
|
|
var menus = imports.menus;
|
|
var commands = imports.commands;
|
|
var run = imports.run;
|
|
var util = imports.util;
|
|
var c9 = imports.c9;
|
|
var ui = imports.ui;
|
|
var fs = imports.fs;
|
|
var layout = imports.layout;
|
|
var tree = imports.tree;
|
|
var tabs = imports.tabManager;
|
|
var tabbehavior = imports.tabbehavior;
|
|
var debug = imports.debugger;
|
|
var prefs = imports.preferences;
|
|
var c9console = imports.console;
|
|
var ace = imports.ace;
|
|
var save = imports.save;
|
|
var showError = imports["dialog.error"].show;
|
|
var assert = require("c9/assert");
|
|
|
|
var Tree = require("ace_tree/tree");
|
|
var TreeData = require("./runcfgdp");
|
|
|
|
var basename = require("path").basename;
|
|
var uCaseFirst = require("c9/string").uCaseFirst;
|
|
|
|
/***** Initialization *****/
|
|
|
|
var plugin = new Plugin("Ajax.org", main.consumes);
|
|
var emit = plugin.getEmitter();
|
|
|
|
var defaultConfigs = options.defaultConfigs;
|
|
|
|
var btnRun, lastRun, mnuRunWith, process, mnuRunCfg;
|
|
var model, datagrid, defConfig;
|
|
|
|
var loaded = false;
|
|
function load() {
|
|
if (loaded) return false;
|
|
loaded = true;
|
|
|
|
// Commands
|
|
commands.addCommand({
|
|
name: "run",
|
|
group: "Run & Debug",
|
|
"hint": "run or debug an application",
|
|
bindKey: { mac: "Option-F5", win: "Alt-F5" },
|
|
exec: function(editor, args) {
|
|
runNow(null, null, null, args.callback);
|
|
}
|
|
}, plugin);
|
|
|
|
commands.addCommand({
|
|
name: "stop",
|
|
group: "Run & Debug",
|
|
"hint": "stop a running node program on the server",
|
|
bindKey: { mac: "Shift-F5", win: "Shift-F5" },
|
|
exec: function() { stop(function() {}); }
|
|
}, plugin);
|
|
|
|
commands.addCommand({
|
|
name: "runlast",
|
|
group: "Run & Debug",
|
|
"hint": "run or debug the last run file",
|
|
bindKey: { mac: "F5", win: "F5" },
|
|
exec: function() { runLastFile(); },
|
|
isAvailable: function() {
|
|
return lastRun ? true : false;
|
|
}
|
|
}, plugin);
|
|
|
|
// Tree context menu
|
|
// Needs to be hidden in readonly mode
|
|
var itemCtxTreeRunFile = new ui.item({
|
|
match: "file",
|
|
enabled: !c9.readonly,
|
|
caption: "Run",
|
|
isAvailable: function() {
|
|
return tree.selectedNode && !tree.selectedNode.isFolder;
|
|
},
|
|
onclick: function() {
|
|
runNow("auto", tree.selected.replace(/^\//, ""));
|
|
}
|
|
});
|
|
tree.getElement("mnuCtxTree", function(mnuCtxTree) {
|
|
menus.addItemToMenu(mnuCtxTree, itemCtxTreeRunFile, 150, plugin);
|
|
});
|
|
|
|
// Check after state.change
|
|
c9.on("stateChange", function(e) {
|
|
// @todo consider moving this to the run plugin
|
|
if (itemCtxTreeRunFile && !c9.readonly)
|
|
itemCtxTreeRunFile.setAttribute("disabled", !(e.state & c9.PROCESS));
|
|
}, plugin);
|
|
|
|
run.on("started", function() {
|
|
if (settings.getBool("user/preview/@running_app")) {
|
|
commands.exec("preview", null, {
|
|
server: true,
|
|
nocheck: true,
|
|
pane: tabs.getPanes(tabs.container)[0]
|
|
});
|
|
}
|
|
});
|
|
|
|
// Menus
|
|
var c = 1000;
|
|
menus.setRootMenu("Run", 600, plugin);
|
|
var itmRun = new ui.item({
|
|
isAvailable: function() {
|
|
var tab = tabs.focussedTab;
|
|
var path = tab && tab.path;
|
|
|
|
if (process && process.running) {
|
|
itmRun.setAttribute("caption", "Stop");
|
|
itmRun.setAttribute("command", "stop");
|
|
return true;
|
|
}
|
|
else {
|
|
var runner = path && getRunner(path);
|
|
if (runner) {
|
|
itmRun.setAttribute("command", "run");
|
|
itmRun.setAttribute("caption", "Run "
|
|
+ basename(path) + " with "
|
|
+ runner.caption);
|
|
return true;
|
|
}
|
|
else {
|
|
itmRun.setAttribute("command", "run");
|
|
itmRun.setAttribute("caption", "Run");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
menus.addItemByPath("Run/Run", itmRun, c += 100, plugin);
|
|
var itmRunLast = new ui.item({
|
|
command: "runlast",
|
|
isAvailable: function() {
|
|
if (process && process.running || !lastRun) {
|
|
itmRunLast.setAttribute("caption", "Run Last");
|
|
return false;
|
|
}
|
|
else {
|
|
var runner = lastRun[0] == "auto"
|
|
? getRunner(lastRun[1])
|
|
: lastRun[0];
|
|
|
|
itmRunLast.setAttribute("caption", "Run Last ("
|
|
+ basename(lastRun[1]) + ", "
|
|
+ (runner.caption || "auto") + ")");
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
menus.addItemByPath("Run/Run Last", itmRunLast, c += 100, plugin);
|
|
menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);
|
|
|
|
var lastOpener, preventLoop;
|
|
var mnuRunAs = new ui.menu({
|
|
id: "mnuRunAs",
|
|
"onprop.visible": function(e) {
|
|
if (e.value && !preventLoop) {
|
|
run.listRunners(function(err, names) {
|
|
var nodes = mnuRunAs.childNodes;
|
|
for (var i = nodes.length - 4; i >= 0; i--) {
|
|
mnuRunAs.removeChild(nodes[i]);
|
|
}
|
|
|
|
var c = 300;
|
|
names.sort().forEach(function(name) {
|
|
menus.addItemToMenu(mnuRunAs, new ui.item({
|
|
caption: uCaseFirst(name),
|
|
value: name
|
|
}), c++, plugin);
|
|
});
|
|
|
|
if (mnuRunAs.visible && mnuRunAs.opener
|
|
&& mnuRunAs.opener.localName == "button") {
|
|
preventLoop = true;
|
|
mnuRunAs.display(null,
|
|
null, true, mnuRunAs.opener);
|
|
preventLoop = false;
|
|
}
|
|
});
|
|
|
|
lastOpener = this.opener;
|
|
|
|
// Show edit menu only in Output tab
|
|
var editMenu = mnuRunAs.childNodes[mnuRunAs.childNodes.length - 1];
|
|
if (this.opener && this.opener.getAttribute("caption") !== "Run With") {
|
|
editMenu.setAttribute("visible", true);
|
|
// Make sure caption doesn't break edit-run-system
|
|
assert(this.opener.getAttribute("caption").match(/Runner: .*/));
|
|
}
|
|
else {
|
|
editMenu.setAttribute("visible", false);
|
|
}
|
|
}
|
|
},
|
|
"onitemclick": function(e) {
|
|
if (e.value == "new-run-system") {
|
|
tabs.open({
|
|
path: settings.get("project/run/@path")
|
|
+ "/My Runner.run",
|
|
active: true,
|
|
value: '// Create a custom Cloud9 runner - similar to the Sublime build system\n'
|
|
+ '// For more information see https://docs.c9.io/custom_runners.html\n'
|
|
+ '{\n'
|
|
+ ' "cmd" : ["ls", "$file", "$args"],\n'
|
|
+ ' "info" : "Started $project_path$file_name",\n'
|
|
+ ' "env" : {},\n'
|
|
+ ' "selector" : "source.ext"\n'
|
|
+ '}',
|
|
document: {
|
|
meta: {
|
|
newfile: true
|
|
},
|
|
ace: {
|
|
customSyntax: "javascript"
|
|
}
|
|
}
|
|
}, function() {});
|
|
return;
|
|
}
|
|
else if (e.value === "edit-run-system") {
|
|
var runnerName = lastOpener.getAttribute("caption").match(/Runner: (.*)/)[1];
|
|
var path = settings.get("project/run/@path") + "/" + runnerName + ".run";
|
|
run.getRunner(runnerName, function(err, runner) {
|
|
if (err) {
|
|
showError(err); // warn and continue
|
|
}
|
|
if (runner) {
|
|
delete runner.caption;
|
|
delete runner.$builtin;
|
|
}
|
|
fs.exists(path, function(exists) {
|
|
tabs.open({
|
|
path: path,
|
|
active: true,
|
|
value: exists
|
|
? undefined
|
|
: "// This file overrides the built-in " + runnerName + " runner\n"
|
|
+ '// For more information see http://docs.c9.io:8080/#!/api/run-method-run\n'
|
|
+ JSON.stringify(runner, null, 2),
|
|
document: !exists && {
|
|
meta: {
|
|
newfile: true
|
|
},
|
|
ace: {
|
|
customSyntax: "javascript"
|
|
}
|
|
}
|
|
}, function() {});
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (lastOpener && lastOpener.onitemclick)
|
|
return lastOpener.onitemclick(e.value);
|
|
|
|
run.getRunner(e.value, function(err, runner) {
|
|
if (err)
|
|
return showError(err);
|
|
|
|
runNow(runner);
|
|
});
|
|
|
|
settings.set("project/run/@runner", e.value);
|
|
}
|
|
});
|
|
mnuRunCfg = new ui.menu({
|
|
id: "mnuRunCfg",
|
|
"onprop.visible": function(e) {
|
|
if (e.value) {
|
|
var nodes = mnuRunCfg.childNodes;
|
|
for (var i = nodes.length - 4; i >= 0; i--) {
|
|
mnuRunCfg.removeChild(nodes[i]);
|
|
}
|
|
|
|
var configs = settings.getJson("project/run/configs") || {};
|
|
for (var name in configs) {
|
|
var c = 0;
|
|
menus.addItemToMenu(mnuRunCfg, new ui.item({
|
|
caption: name,
|
|
value: configs[name]
|
|
}), c++, plugin);
|
|
}
|
|
}
|
|
},
|
|
"onitemclick": function(e) {
|
|
if (e.value == "new-run-config") {
|
|
commands.exec("showoutput", null, {});
|
|
return;
|
|
}
|
|
else if (e.value == "manage") {
|
|
commands.exec("openpreferences", null, {
|
|
panel: "preferences.project",
|
|
section: "Run Configuration"
|
|
});
|
|
return;
|
|
}
|
|
|
|
commands.exec("showoutput", null, {
|
|
run: true,
|
|
config: e.value
|
|
});
|
|
}
|
|
});
|
|
plugin.addElement(mnuRunAs, mnuRunCfg);
|
|
|
|
menus.addItemByPath("Run/Run With/", mnuRunAs, c += 100, plugin);
|
|
menus.addItemByPath("Run/Run History/", new ui.item({
|
|
isAvailable: function() { return false; }
|
|
}), c += 100, plugin);
|
|
menus.addItemByPath("Run/Run Configurations/", mnuRunCfg, c += 100, plugin);
|
|
|
|
menus.addItemByPath("Run/~", new ui.divider(), c += 1000, plugin);
|
|
// menus.addItemByPath("Run/Enable Source Maps", new ui.item({
|
|
// type : "check",
|
|
// checked : "project/debug/@sourcemaps"
|
|
// }), c += 100, plugin);
|
|
menus.addItemByPath("Run/Show Debugger at Break", new ui.item({
|
|
type: "check",
|
|
checked: "user/debug/@autoshow"
|
|
}), c += 100, plugin);
|
|
|
|
c = 0;
|
|
menus.addItemByPath("Run/Run Configurations/~", new ui.divider(), c += 1000, plugin);
|
|
menus.addItemByPath("Run/Run Configurations/New Run Configuration", new ui.item({
|
|
value: "new-run-config"
|
|
}), c += 100, plugin);
|
|
menus.addItemByPath("Run/Run Configurations/Manage...", new ui.item({
|
|
value: "manage"
|
|
}), c += 100, plugin);
|
|
|
|
c = 0;
|
|
menus.addItemByPath("Run/Run With/~", new ui.divider(), c += 1000, plugin);
|
|
menus.addItemByPath("Run/Run With/New Runner", new ui.item({
|
|
value: "new-run-system"
|
|
}), c += 100, plugin);
|
|
menus.addItemByPath("Run/Run With/Edit Runner", new ui.item({
|
|
value: "edit-run-system"
|
|
}), c += 100, plugin);
|
|
|
|
// Other Menus
|
|
|
|
menus.addItemToMenu(tabs.getElement("mnuEditors"),
|
|
new ui.item({
|
|
caption: "New Run Configuration",
|
|
hotkey: "commands.showoutput",
|
|
onclick: function(e) {
|
|
commands.exec("showoutput", null, {
|
|
pane: this.parentNode.pane
|
|
});
|
|
}
|
|
}), 250, plugin);
|
|
|
|
var mnuContext = tabbehavior.contextMenu;
|
|
// menus.addItemByPath("~", new ui.divider(), 800, mnuContext, plugin);
|
|
menus.addItemByPath("Run This File", new ui.item({
|
|
onclick: function() {
|
|
var tab = mnuContext.$tab;
|
|
if (tab && tab.path)
|
|
runNow("auto", tab.path.replace(/^\//, ""));
|
|
},
|
|
isAvailable: function() {
|
|
var tab = mnuContext.$tab;
|
|
return tab && tab.path && (!process || !process.running);
|
|
}
|
|
}), 150, mnuContext, plugin);
|
|
|
|
// Draw
|
|
draw();
|
|
|
|
// Preferences
|
|
prefs.add({
|
|
"Run": {
|
|
position: 600,
|
|
"Run & Debug": {
|
|
position: 100,
|
|
"Save All Unsaved Tabs Before Running": {
|
|
type: "checkbox",
|
|
path: "user/runconfig/@saveallbeforerun",
|
|
position: 100
|
|
}
|
|
}
|
|
}
|
|
}, plugin);
|
|
|
|
prefs.add({
|
|
"Project": {
|
|
"Run & Debug": {
|
|
position: 300,
|
|
"Runner Path in Workspace": {
|
|
type: "textbox",
|
|
path: "project/run/@path",
|
|
position: 1000
|
|
}
|
|
},
|
|
"Run Configurations": {
|
|
position: 200,
|
|
"Run Configurations": {
|
|
type: "custom",
|
|
name: "runcfg",
|
|
title: "Run Configurations",
|
|
position: 120,
|
|
node: new ui.bar({
|
|
style: "padding:10px"
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}, plugin);
|
|
|
|
plugin.getElement("runcfg", function(hbox) {
|
|
model = new TreeData();
|
|
model.emptyMessage = "No run configurations";
|
|
|
|
model.columns = [{
|
|
caption: "Name",
|
|
value: "name",
|
|
width: "15%",
|
|
}, {
|
|
caption: "Command",
|
|
value: "command",
|
|
width: "30%",
|
|
}, {
|
|
caption: "CWD",
|
|
value: "cwd",
|
|
width: "15%"
|
|
}, {
|
|
caption: "Debug",
|
|
value: "debug",
|
|
width: "10%"
|
|
}, {
|
|
caption: "Runner",
|
|
value: "runner",
|
|
width: "20%"
|
|
}, {
|
|
caption: "Default",
|
|
value: "default",
|
|
width: "10%"
|
|
}];
|
|
|
|
layout.on("eachTheme", function(e) {
|
|
var height = parseInt(ui.getStyleRule(".bar-preferences .blackdg .tree-row", "height"), 10) || 24;
|
|
model.rowHeightInner = height;
|
|
model.rowHeight = height;
|
|
|
|
if (e.changed) (datagrid).resize(true);
|
|
});
|
|
|
|
var container = hbox.$ext.appendChild(document.createElement("div"));
|
|
container.style.width = "600px";
|
|
container.style.marginBottom = "30px";
|
|
|
|
datagrid = new Tree(container);
|
|
datagrid.setTheme({ cssClass: "blackdg" });
|
|
datagrid.setOption("maxLines", 200);
|
|
datagrid.setDataProvider(model);
|
|
|
|
datagrid.on("afterChoose", function() {
|
|
var nodes = datagrid.selection.getSelectedNodes();
|
|
var cfgs = settings.getJson("project/run/configs");
|
|
nodes.forEach(function (node) {
|
|
commands.exec("showoutput", null, {
|
|
config: cfgs[node.name]
|
|
});
|
|
});
|
|
});
|
|
|
|
datagrid.on("delete", function(e) {
|
|
var nodes = datagrid.selection.getSelectedNodes();
|
|
nodes.forEach(function (node) {
|
|
removeConfig(node.name);
|
|
datagrid.provider._signal("remove", node);
|
|
});
|
|
});
|
|
|
|
new ui.hbox({
|
|
htmlNode: container.parentNode,
|
|
style: "position:absolute;left:10px;bottom:10px",
|
|
childNodes: [
|
|
new ui.button({
|
|
caption: "Remove Selected Configs",
|
|
skin: "c9-toolbarbutton-glossy",
|
|
onclick: function() {
|
|
datagrid.execCommand("delete");
|
|
}
|
|
}),
|
|
new ui.button({
|
|
caption: "Add New Config",
|
|
skin: "c9-toolbarbutton-glossy",
|
|
onclick: function() {
|
|
commands.exec("showoutput", null, {});
|
|
}
|
|
}),
|
|
new ui.button({
|
|
caption: "Set As Default",
|
|
skin: "c9-toolbarbutton-glossy",
|
|
onclick: function() {
|
|
var node = datagrid.selection.getSelectedNodes()[0];
|
|
if (!node) return;
|
|
|
|
var json = settings.getJson("project/run/configs") || {};
|
|
var wasDefault = json[node.name]["default"];
|
|
for (var name in json) { delete json[name]["default"]; }
|
|
json[node.name]["default"] = !wasDefault;
|
|
settings.setJson("project/run/configs", json);
|
|
|
|
defConfig = wasDefault ? null : node.name;
|
|
|
|
reloadModel();
|
|
transformButton();
|
|
}
|
|
})
|
|
]
|
|
});
|
|
|
|
reloadModel();
|
|
}, plugin);
|
|
|
|
// settings
|
|
settings.on("read", function(e) {
|
|
settings.setDefaults("user/runconfig", [
|
|
["saveallbeforerun", "true"],
|
|
["debug", "true"],
|
|
["showruncfglist", "false"]
|
|
]);
|
|
|
|
if (!settings.getBool("project/run/configs/@inited")) {
|
|
settings.setJson("project/run/configs", defaultConfigs);
|
|
settings.set("project/run/configs/@inited", "true");
|
|
}
|
|
|
|
var json = settings.getJson("project/run/configs") || {};
|
|
for (var name in json) {
|
|
if (json[name]["default"]) {
|
|
defConfig = name;
|
|
break;
|
|
}
|
|
}
|
|
transformButton();
|
|
|
|
var state = settings.get("state/run/process");
|
|
if (state) {
|
|
run.on("create", function wait(e) {
|
|
if (e.process.name == state) {
|
|
process = e.process;
|
|
|
|
decorateProcess();
|
|
transformButton("stop");
|
|
|
|
run.off("create", wait);
|
|
}
|
|
});
|
|
}
|
|
}, plugin);
|
|
|
|
settings.on("project/run/configs", function() {
|
|
reloadModel();
|
|
}, plugin);
|
|
|
|
tabs.on("focus", function(e) {
|
|
if (process && process.running)
|
|
return;
|
|
|
|
transformButton();
|
|
}, plugin);
|
|
|
|
tabs.on("tabDestroy", function(e) {
|
|
if (e.last && !defConfig && !tabs.focussedTab) {
|
|
btnRun.disable();
|
|
btnRun.setAttribute("tooltip", "");
|
|
}
|
|
}, plugin);
|
|
|
|
var activateOutput = function(plugin) {
|
|
plugin.getTabs().forEach(function(tab) {
|
|
if (tab.editorType != "output") return;
|
|
if (tab.document.getSession()) return;
|
|
|
|
var state = tab.document.getState();
|
|
if ((state.output.running || false).debug) {
|
|
// Get editor and create it if it's not in the current pane
|
|
tab.pane.createEditor(tab.editorType, function(err, editor) {
|
|
editor.loadDocument(tab.document);
|
|
});
|
|
}
|
|
});
|
|
};
|
|
tabs.once("ready", activateOutput.bind(this, tabs));
|
|
c9console.once("ready", activateOutput.bind(this, c9console));
|
|
|
|
ace.getElement("menu", function(menu) {
|
|
menus.addItemToMenu(menu, new ui.item({
|
|
caption: "Run This File",
|
|
command: "run",
|
|
}), 800, plugin);
|
|
menus.addItemToMenu(menu, new ui.divider(), 900, plugin);
|
|
});
|
|
}
|
|
|
|
var drawn = false;
|
|
function draw() {
|
|
if (drawn) return;
|
|
drawn = true;
|
|
|
|
// Menus
|
|
btnRun = ui.insertByIndex(layout.findParent(plugin),
|
|
new ui.button({
|
|
id: "btnRun",
|
|
skin: "c9-toolbarbutton-glossy",
|
|
command: "run",
|
|
caption: "Run",
|
|
disabled: true,
|
|
class: "runbtn stopped",
|
|
icon: "run.png",
|
|
}), 100, plugin);
|
|
|
|
btnRun.on("contextmenu", function(e) {
|
|
mnuRunCfg.display(e.x, e.y);
|
|
return false;
|
|
});
|
|
|
|
emit("draw");
|
|
}
|
|
|
|
/***** Helper Methods *****/
|
|
|
|
function removeConfig(name) {
|
|
var cfgs = settings.getJson("project/run/configs");
|
|
if (!cfgs) return;
|
|
|
|
delete cfgs[name];
|
|
settings.setJson("project/run/configs", cfgs);
|
|
}
|
|
|
|
function reloadModel() {
|
|
if (!model) return;
|
|
|
|
var cfgs = settings.getJson("project/run/configs") || {};
|
|
var nodes = Object.keys(cfgs).map(function(name) {
|
|
return cfgs[name];
|
|
}).sort();
|
|
|
|
model.setRoot({ children: nodes });
|
|
|
|
defConfig = null;
|
|
for (var name in cfgs) {
|
|
if (cfgs[name]["default"]) {
|
|
defConfig = name;
|
|
break;
|
|
}
|
|
}
|
|
transformButton();
|
|
}
|
|
|
|
/***** Methods *****/
|
|
|
|
function getRunner(path) {
|
|
var ext = path && fs.getExtension(path);
|
|
for (var name in run.runners) {
|
|
if (run.runners[name].selector == "source." + ext)
|
|
return run.runners[name];
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function runNow(runner, path, isEscapedPath, callback) {
|
|
if (!path && !defConfig) {
|
|
path = findTabToRun() || "";
|
|
// if (!path) return;
|
|
}
|
|
|
|
if (settings.getBool("user/runconfig/@saveallbeforerun"))
|
|
save.saveAll({ skipNewFiles: true }, start);
|
|
else
|
|
start();
|
|
|
|
function start() {
|
|
if (process && process.running)
|
|
stop(done);
|
|
else
|
|
done();
|
|
}
|
|
|
|
function done() {
|
|
if (!runner)
|
|
runner = "auto";
|
|
|
|
var config;
|
|
if (defConfig && !path) {
|
|
var configs = settings.getJson("project/run/configs") || {};
|
|
config = configs[defConfig];
|
|
}
|
|
else {
|
|
config = {
|
|
runner: runner.caption || runner,
|
|
command: isEscapedPath ? path : util.escapeShell(path)
|
|
};
|
|
}
|
|
var id;
|
|
if (defConfig && config.name == defConfig) {
|
|
id = "output-default";
|
|
if (config.name) {
|
|
id += config.name.replace(/[^\w]/g, function(i) {
|
|
return "-" + i.charCodeAt(0).toString(36);
|
|
});
|
|
}
|
|
}
|
|
|
|
commands.exec("showoutput", null, {
|
|
runner: runner,
|
|
run: true,
|
|
config: config,
|
|
id: id,
|
|
callback: function(proc, tab) {
|
|
if (defConfig) {
|
|
process = proc;
|
|
decorateProcess();
|
|
transformButton("stop");
|
|
|
|
settings.set("state/run/process", process.name);
|
|
|
|
}
|
|
|
|
callback && callback(proc, tab);
|
|
}
|
|
});
|
|
}
|
|
|
|
lastRun = [runner, path];
|
|
}
|
|
|
|
function decorateProcess() {
|
|
process.on("away", function() {
|
|
btnRun.disable();
|
|
}, plugin);
|
|
process.on("back", function() {
|
|
btnRun.enable();
|
|
}, plugin);
|
|
process.on("stopping", function() {
|
|
btnRun.disable();
|
|
}, plugin);
|
|
process.on("stopped", function() {
|
|
btnRun.enable();
|
|
|
|
var path = transformButton();
|
|
if (path || lastRun || defConfig)
|
|
btnRun.enable();
|
|
else
|
|
btnRun.disable();
|
|
|
|
settings.set("state/run/process", "");
|
|
}, plugin);
|
|
}
|
|
|
|
function findTabToRun() {
|
|
var path = tabs.focussedTab && tabs.focussedTab.path;
|
|
if (path) return path.replace(/^\//, "");
|
|
|
|
var foundActive;
|
|
if (tabs.getPanes().every(function(pane) {
|
|
var tab = pane.activeTab;
|
|
if (tab && tab.path) {
|
|
if (foundActive) return false;
|
|
foundActive = tab;
|
|
}
|
|
return true;
|
|
}) && foundActive) {
|
|
return foundActive.path.replace(/^\//, "");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function transformButton(to) {
|
|
if (to == "stop") {
|
|
btnRun.setAttribute("command", "stop");
|
|
btnRun.setAttribute("caption", "Stop");
|
|
btnRun.setAttribute("tooltip", "");
|
|
btnRun.setAttribute("class", "runbtn running");
|
|
btnRun.enable();
|
|
|
|
return btnRun;
|
|
}
|
|
else {
|
|
btnRun.setAttribute("class", "runbtn stopped");
|
|
|
|
var path = findTabToRun();
|
|
if (path && emit("updateRunButton", {
|
|
path: /[~\/]/.test(path.charAt(0)) ? path : "/" + path,
|
|
button: btnRun
|
|
}) === false) {
|
|
return;
|
|
}
|
|
else if (defConfig) {
|
|
btnRun.setAttribute("caption", "Run Project");
|
|
btnRun.setAttribute("tooltip", "");
|
|
btnRun.setAttribute("command", "run");
|
|
btnRun.setAttribute("disabled", "false");
|
|
}
|
|
else if (path) {
|
|
btnRun.enable();
|
|
btnRun.setAttribute("command", "run");
|
|
btnRun.setAttribute("caption", "Run");
|
|
btnRun.setAttribute("tooltip", "Run "
|
|
+ basename(path));
|
|
}
|
|
else if (lastRun) {
|
|
var runner = lastRun[0] == "auto"
|
|
? getRunner(lastRun[1])
|
|
: lastRun[0];
|
|
|
|
btnRun.enable();
|
|
btnRun.setAttribute("command", "runlast");
|
|
btnRun.setAttribute("caption", "Run Last");
|
|
btnRun.setAttribute("tooltip", "Run Last ("
|
|
+ basename(lastRun[1]) + ", "
|
|
+ (runner && runner.caption || "auto") + ")");
|
|
}
|
|
else {
|
|
btnRun.disable();
|
|
btnRun.setAttribute("caption", "Run");
|
|
btnRun.setAttribute("tooltip", "");
|
|
}
|
|
}
|
|
}
|
|
|
|
function stop(callback) {
|
|
if (process)
|
|
process.stop(function(err) {
|
|
if (err) {
|
|
showError(err.message || err);
|
|
transformButton();
|
|
}
|
|
|
|
debug.stop();
|
|
|
|
callback(err);
|
|
});
|
|
}
|
|
|
|
function runLastFile() {
|
|
if (lastRun)
|
|
runNow(lastRun[0], lastRun[1], true);
|
|
}
|
|
|
|
/***** Lifecycle *****/
|
|
|
|
plugin.on("load", function() {
|
|
load();
|
|
});
|
|
plugin.on("enable", function() {
|
|
|
|
});
|
|
plugin.on("disable", function() {
|
|
|
|
});
|
|
plugin.on("unload", function() {
|
|
loaded = false;
|
|
drawn = false;
|
|
});
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
* UI for the {@link run} plugin. This plugin is responsible for the Run
|
|
* menu in the main menu bar, as well as the settings and the
|
|
* preferences UI for the run plugin.
|
|
* @singleton
|
|
*/
|
|
/**
|
|
* @command run Runs the currently focussed tab.
|
|
*/
|
|
/**
|
|
* @command stop Stops the running process.
|
|
*/
|
|
/**
|
|
* @command runlast Stops the last run file
|
|
*/
|
|
plugin.freezePublicAPI({
|
|
get lastRun() { return lastRun; },
|
|
set lastRun(lr) { lastRun = lr; },
|
|
|
|
/**
|
|
*
|
|
*/
|
|
transformButton: transformButton
|
|
});
|
|
|
|
register(null, {
|
|
"run.gui": plugin
|
|
});
|
|
}
|
|
});
|