kopia lustrzana https://github.com/c9/core
Merge pull request +6898 from c9/fix/terminal
Improved UX & flows for the installerpull/85/head
commit
40648d045f
|
@ -240,6 +240,7 @@ module.exports = function(options) {
|
|||
},
|
||||
"plugins/c9.ide.ui/widgets.tree",
|
||||
"plugins/c9.ide.ui/widgets.datagrid",
|
||||
"plugins/c9.ide.ui/widgets.terminal",
|
||||
"plugins/c9.ide.ui/focus",
|
||||
"plugins/c9.ide.ui/lib_apf",
|
||||
|
||||
|
|
12
package.json
12
package.json
|
@ -59,14 +59,14 @@
|
|||
"c9.ide.language.javascript.eslint": "#8832423ad1",
|
||||
"c9.ide.language.javascript.tern": "#7aab8b0b6a",
|
||||
"c9.ide.language.javascript.infer": "#cfec494a3c",
|
||||
"c9.ide.language.jsonalyzer": "#a1057f20db",
|
||||
"c9.ide.collab": "#7b09419b5c",
|
||||
"c9.ide.language.jsonalyzer": "#21b64e5820",
|
||||
"c9.ide.collab": "#504750d8f0",
|
||||
"c9.ide.local": "#cf624506cc",
|
||||
"c9.ide.find": "#bd9f11c08f",
|
||||
"c9.ide.find": "#6cc6d3379d",
|
||||
"c9.ide.find.infiles": "#72582de3cd",
|
||||
"c9.ide.find.replace": "#e4daf722b8",
|
||||
"c9.ide.run.debug": "#638e6b00b3",
|
||||
"c9.automate": "#86bf1ee1ca",
|
||||
"c9.automate": "#b1b0cca13a",
|
||||
"c9.ide.ace.emmet": "#e5f1a92ac3",
|
||||
"c9.ide.ace.gotoline": "#4d1a93172c",
|
||||
"c9.ide.ace.keymaps": "#43445d6306",
|
||||
|
@ -77,13 +77,13 @@
|
|||
"c9.ide.behaviors": "#6aad7006a0",
|
||||
"c9.ide.closeconfirmation": "#a28bfd8272",
|
||||
"c9.ide.configuration": "#f309bb47d2",
|
||||
"c9.ide.dialog.wizard": "#c6401bdd13",
|
||||
"c9.ide.dialog.wizard": "#ea640aa5a1",
|
||||
"c9.ide.fontawesome": "#781602c5d8",
|
||||
"c9.ide.format": "#f51451ac57",
|
||||
"c9.ide.help.support": "#60e88f5680",
|
||||
"c9.ide.imgeditor": "#08bbc53578",
|
||||
"c9.ide.immediate": "#6845a93705",
|
||||
"c9.ide.installer": "#38f5840924",
|
||||
"c9.ide.installer": "#75413dd79a",
|
||||
"c9.ide.mount": "#cb45b621f1",
|
||||
"c9.ide.navigate": "#64156c7f4a",
|
||||
"c9.ide.newresource": "#f1f0624768",
|
||||
|
|
|
@ -631,7 +631,7 @@ define(function(require, exports, module) {
|
|||
additional.push({
|
||||
id: path,
|
||||
source: 'define("' + path + '", [],' +
|
||||
JSON.stringify(packedConfig, null, 4) + ')',
|
||||
JSON.stringify(packedConfig, null, 4) + ');',
|
||||
literal : true,
|
||||
order: -1
|
||||
});
|
||||
|
|
|
@ -130,6 +130,9 @@ define(function(require, module, exports) {
|
|||
if (allowClose && e.keyCode == 27)
|
||||
dialog.hide();
|
||||
});
|
||||
dialog.on("resize", function(){
|
||||
emit("resize");
|
||||
});
|
||||
|
||||
commands.addCommand({
|
||||
name: plugin.name,
|
||||
|
@ -254,7 +257,7 @@ define(function(require, module, exports) {
|
|||
|
||||
// @todo this looks very similar to forms.js. Perhaps able to merge?
|
||||
function createItem(heading, name, options) {
|
||||
var position = options.position || count++;
|
||||
var position = options.position || (count += 100);
|
||||
var node;
|
||||
|
||||
switch(options.type) {
|
||||
|
@ -511,6 +514,13 @@ define(function(require, module, exports) {
|
|||
*/
|
||||
"hide"
|
||||
],
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
createElement: function(options){
|
||||
createItem(null, null, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates form elements with new values. This method currently
|
||||
|
|
|
@ -1606,8 +1606,8 @@
|
|||
@installer-text-shadow: none;
|
||||
@installer-font-family: Arial;
|
||||
|
||||
@installer-log-color: #fff;
|
||||
@installer-log-gradient: linear-gradient(top,rgba(0, 0, 0, 0.29) 0%, rgba(0, 0, 0, 0.11) 8px, rgba(0, 0, 0, 0.01) 13px, transparent 15px);
|
||||
@installer-log-color: #333;
|
||||
@installer-log-gradient: linear-gradient(top, #DFEFF9 0%, #DFEFF9 100%);
|
||||
@installer-log-border: 1px solid white;
|
||||
@installer-log-border-color: rgba(255,255,255,0.06) rgba(0,0,0,0.3) rgba(0,0,0,0.3) rgba(255,255,255,0.06);
|
||||
@installer-log-border-radius: 0;
|
||||
|
|
|
@ -1606,8 +1606,8 @@
|
|||
@installer-text-shadow: none;
|
||||
@installer-font-family: Arial;
|
||||
|
||||
@installer-log-color: #fff;
|
||||
@installer-log-gradient: linear-gradient(top,rgba(0, 0, 0, 0.29) 0%, rgba(0, 0, 0, 0.11) 8px, rgba(0, 0, 0, 0.01) 13px, transparent 15px);
|
||||
@installer-log-color: #333;
|
||||
@installer-log-gradient: linear-gradient(top, #DFEFF9 0%, #DFEFF9 100%);
|
||||
@installer-log-border: 1px solid white;
|
||||
@installer-log-border-color: rgba(255,255,255,0.06) rgba(0,0,0,0.3) rgba(0,0,0,0.3) rgba(255,255,255,0.06);
|
||||
@installer-log-border-radius: 0;
|
||||
|
|
|
@ -55,7 +55,14 @@ define(function(require, exports, module) {
|
|||
var install = [];
|
||||
|
||||
if (loadFromDisk) {
|
||||
fs.readdir("~/.c9/plugins", function(error, files){
|
||||
fs.readdir("~/.c9/plugins", function handle(err, files){
|
||||
if (err) {
|
||||
if (err.code == "EDISCONNECT")
|
||||
fs.readdir("~/.c9/plugins", handle);
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
files.forEach(function(f) {
|
||||
if (!/^[_.]/.test(f.name)) {
|
||||
fs.exists("~/.c9/plugins/" + f.name + "/__installed__.js", function(exists) {
|
||||
|
|
|
@ -20275,6 +20275,9 @@ apf.Interactive = function(){
|
|||
|
||||
doResize(e);
|
||||
|
||||
if (_self.dispatchEvent)
|
||||
_self.dispatchEvent("resize");
|
||||
|
||||
//overThreshold = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -509,6 +509,12 @@ define(function(require, exports, module) {
|
|||
focus: function(){
|
||||
return acetree.focus();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
blur: function(){
|
||||
return acetree.blur();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,402 @@
|
|||
define(function(require, exports, module) {
|
||||
main.consumes = ["Plugin", "ui", "util", "commands"];
|
||||
main.provides = ["Terminal"];
|
||||
return main;
|
||||
|
||||
function main(options, imports, register) {
|
||||
var Plugin = imports.Plugin;
|
||||
var commands = imports.commands;
|
||||
|
||||
var Aceterm = require("../c9.ide.terminal/aceterm/aceterm");
|
||||
|
||||
/***** Constructors *****/
|
||||
|
||||
/*
|
||||
plugin.on("copy", function(e) {
|
||||
if (e.native) return; // Ace handles this herself
|
||||
|
||||
var data = aceterm.getCopyText();
|
||||
e.clipboardData.setData("text/plain", data);
|
||||
});
|
||||
plugin.on("paste", function(e) {
|
||||
if (e.native) return; // Ace handles this herself
|
||||
|
||||
var data = e.clipboardData.getData("text/plain");
|
||||
if (data !== false)
|
||||
aceterm.onPaste(data);
|
||||
});
|
||||
*/
|
||||
|
||||
function Terminal(options, forPlugin, baseclass) {
|
||||
if (!options) throw new Error("options are required");
|
||||
|
||||
var plugin = new Plugin("Ajax.org", main.consumes);
|
||||
var emit = plugin.getEmitter();
|
||||
if (baseclass) plugin.baseclass();
|
||||
|
||||
var rows = options.rows || 0;
|
||||
var cols = options.cols || 0;
|
||||
|
||||
var aceterm, terminal;
|
||||
var redirectEvents;
|
||||
var meta = {};
|
||||
|
||||
var excludedEvents = {
|
||||
"draw": 1, "load":1, "unload":1, "resize":1,
|
||||
"addListener":1, "removeListener":1, "input":1
|
||||
};
|
||||
var renameEvents = {
|
||||
"select": "changeSelection",
|
||||
"scroll": "changeScrollTop"
|
||||
};
|
||||
|
||||
/***** Methods *****/
|
||||
|
||||
function send(data) {
|
||||
emit("input", { data: data });
|
||||
}
|
||||
|
||||
function _resize(force){
|
||||
var ace = terminal.aceSession.ace;
|
||||
|
||||
var size = ace.renderer.$size;
|
||||
var config = ace.renderer.layerConfig;
|
||||
|
||||
var h = size.scrollerHeight;
|
||||
var w = size.scrollerWidth - 2 * config.padding;
|
||||
|
||||
if (!h || config.lineHeight <= 1)
|
||||
return false;
|
||||
|
||||
// top 1px is for cursor outline
|
||||
var _rows = Math.floor((h - 1) / config.lineHeight);
|
||||
if (_rows <= 2 && !ace.renderer.scrollBarV.isVisible)
|
||||
w -= ace.renderer.scrollBarV.width;
|
||||
var _cols = Math.floor(w / config.characterWidth);
|
||||
|
||||
if (!_cols || !_rows)
|
||||
return;
|
||||
|
||||
// Don't do anything if the size remains the same
|
||||
if (!force && _cols == terminal.cols && _rows == terminal.rows)
|
||||
return;
|
||||
|
||||
if (_cols > 1000 || _rows > 1000) {
|
||||
console.error("invalid terminal size");
|
||||
return;
|
||||
}
|
||||
|
||||
// do not resize terminal to very small heights during initialization
|
||||
rows = Math.max(_rows, 2);
|
||||
cols = Math.max(_cols, 2);
|
||||
|
||||
terminal.resize(_cols, _rows);
|
||||
|
||||
emit("resize", { cols: cols, rows: rows });
|
||||
}
|
||||
|
||||
/***** Life Cycle *****/
|
||||
|
||||
var drawn = false;
|
||||
function draw(htmlNode) {
|
||||
if (drawn) return;
|
||||
drawn = true;
|
||||
|
||||
aceterm = Aceterm.createEditor(htmlNode, "ace/theme/idle_fingers");
|
||||
|
||||
terminal = new Aceterm(cols, rows, send);
|
||||
aceterm.setSession(terminal.aceSession);
|
||||
|
||||
aceterm.renderer.on("resize", function(){
|
||||
_resize();
|
||||
});
|
||||
|
||||
var cm = commands;
|
||||
// TODO find better way for terminal and ace commands to coexist
|
||||
aceterm.commands.addCommands(cm.getExceptionList());
|
||||
cm.on("update", function() {
|
||||
aceterm.commands.addCommands(cm.getExceptionList());
|
||||
}, plugin);
|
||||
|
||||
aceterm.commands.exec = function(command) {
|
||||
return cm.exec(command);
|
||||
};
|
||||
|
||||
// Set Default Theme
|
||||
// if (!options.theme)
|
||||
// options.theme = "custom-tree ace-tree-" + (options.baseName || "list");
|
||||
|
||||
// Set properties
|
||||
for (var prop in options) {
|
||||
if (prop == "container") continue;
|
||||
if (plugin.hasOwnProperty(prop))
|
||||
plugin[prop] = options[prop];
|
||||
}
|
||||
|
||||
// Configure redirected events
|
||||
redirectEvents = {
|
||||
afterRender: aceterm.renderer,
|
||||
title: terminal,
|
||||
afterWrite: terminal
|
||||
};
|
||||
|
||||
emit.sticky("draw");
|
||||
}
|
||||
|
||||
plugin.on("load", function(){
|
||||
if (options.container)
|
||||
plugin.attachTo(options.container);
|
||||
|
||||
forPlugin.once("unload", function(){
|
||||
plugin.unload();
|
||||
});
|
||||
});
|
||||
plugin.on("unload", function(){
|
||||
if (aceterm) {
|
||||
var container = aceterm.container;
|
||||
aceterm.destroy();
|
||||
|
||||
container.innerHTML = "";
|
||||
container.parentNode.removeChild(container);
|
||||
}
|
||||
|
||||
aceterm = null;
|
||||
container = null;
|
||||
meta = {};
|
||||
});
|
||||
plugin.on("newListener", function(type, fn){
|
||||
if (excludedEvents[type]) return;
|
||||
|
||||
if (renameEvents[type])
|
||||
type = renameEvents[type];
|
||||
|
||||
if (redirectEvents[type])
|
||||
redirectEvents[type].on(type, fn);
|
||||
else
|
||||
aceterm.on(type, fn);
|
||||
});
|
||||
plugin.on("removeListener", function(type, fn){
|
||||
if (excludedEvents[type]) return;
|
||||
|
||||
if (renameEvents[type])
|
||||
type = renameEvents[type];
|
||||
|
||||
if (redirectEvents[type])
|
||||
redirectEvents[type].removeListener(type, fn);
|
||||
else
|
||||
aceterm.removeListener(type, fn);
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* Creates a new List instance.
|
||||
* @param {Object} options
|
||||
* @param {Plugin} plugin The plugin responsible for creating this list.
|
||||
*/
|
||||
plugin.freezePublicAPI({
|
||||
// Getter Properties
|
||||
/**
|
||||
* @ignore
|
||||
* @readonly
|
||||
*/
|
||||
get aceterm(){ return aceterm; },
|
||||
/**
|
||||
* A meta data object that allows you to store whatever you want
|
||||
* in relation to this menu.
|
||||
* @property {Object} meta
|
||||
* @readonly
|
||||
*/
|
||||
get meta(){ return meta; },
|
||||
// /**
|
||||
// *
|
||||
// */
|
||||
// get scrollTop(){ return model.getScrollTop(); },
|
||||
// set scrollTop(value){ return model.setScrollTop(value); },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get focussed(){ return aceterm.isFocussed(); },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get container(){ return aceterm.container; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get renderer(){ return aceterm.renderer; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get selection(){ return aceterm.selection; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get commands(){ return aceterm.commands; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get cols(){ return cols; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get rows(){ return rows; },
|
||||
|
||||
// Getters and Setters for Properties
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get textInput(){ return aceterm.textInput; },
|
||||
set textInput(value){ return aceterm.textInput = value; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get scrollMargin(){ return aceterm.renderer.scrollMargin; },
|
||||
set scrollMargin(value){
|
||||
aceterm.renderer.setScrollMargin(value[0], value[1]);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get theme(){ return aceterm.renderer.theme.cssClass; },
|
||||
set theme(value){ aceterm.renderer.setTheme({cssClass: value}); },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get convertEol(){ return terminal.convertEol || false; },
|
||||
set convertEol(value){ terminal.convertEol = value; },
|
||||
|
||||
// Events
|
||||
_events: [
|
||||
/**
|
||||
* @event draw Fires
|
||||
*/
|
||||
"draw",
|
||||
/**
|
||||
* @event click Fires
|
||||
*/
|
||||
"click",
|
||||
/**
|
||||
* @event userSelect Fires
|
||||
*/
|
||||
"userSelect",
|
||||
/**
|
||||
* @event focus Fires
|
||||
*/
|
||||
"focus",
|
||||
/**
|
||||
* @event blur Fires
|
||||
*/
|
||||
"blur",
|
||||
/**
|
||||
* @event select Fires
|
||||
*/
|
||||
"select",
|
||||
/**
|
||||
* @event scroll Fires
|
||||
*/
|
||||
"scroll",
|
||||
/**
|
||||
* @event scrollbarVisibilityChanged Fires
|
||||
*/
|
||||
"scrollbarVisibilityChanged",
|
||||
/**
|
||||
* @event resize Fires
|
||||
*/
|
||||
"resize",
|
||||
/**
|
||||
* @event afterRender Fires
|
||||
*/
|
||||
"afterRender",
|
||||
/**
|
||||
* @event title Fires
|
||||
*/
|
||||
"title",
|
||||
/**
|
||||
* @event afterWrite Fires
|
||||
*/
|
||||
"afterWrite"
|
||||
],
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
resize: function(){
|
||||
return aceterm.resize(true);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
focus: function(){
|
||||
return aceterm.focus();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
blur: function(){
|
||||
return aceterm.blur();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
execCommand: function(cmd){
|
||||
return aceterm.execCommand(cmd);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
scrollIntoView: function(anchor, lead, offset){
|
||||
return aceterm.renderer.scrollCaretIntoView(anchor, lead, offset);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
enable: function(){
|
||||
return aceterm.enable();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
disable: function(){
|
||||
return aceterm.enable();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
write: function(data){
|
||||
return terminal.write(data);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
clear: function(data){
|
||||
terminal.clear();
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
attachTo: function(htmlNode, beforeNode){
|
||||
var container;
|
||||
if (drawn)
|
||||
container = aceterm.container;
|
||||
else {
|
||||
container = document.createElement("div");
|
||||
container.style.height = "100%";
|
||||
}
|
||||
|
||||
htmlNode.insertBefore(container, beforeNode);
|
||||
|
||||
if (!drawn)
|
||||
draw(container);
|
||||
}
|
||||
});
|
||||
|
||||
plugin.load(null, options.baseName || "list");
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
register(null, {
|
||||
Terminal: Terminal
|
||||
});
|
||||
}
|
||||
});
|
|
@ -94,8 +94,7 @@ define(function(require, exports, module) {
|
|||
if (code == 127) {
|
||||
err = new error.PreconditionFailed(
|
||||
"Your instance seems to be missing the 'nak' utility\n" +
|
||||
"If you are using an SSH workspace, please do:\n" +
|
||||
" 'curl https://raw.github.com/c9/install/master/install.sh | bash'");
|
||||
"Please re-install nak.");
|
||||
} else if (code) {
|
||||
err = new error.InternalServerError(
|
||||
"'nak' utility failed with exit code " + code +
|
||||
|
|
|
@ -400,7 +400,7 @@ require([
|
|||
console.warn(msg);
|
||||
}
|
||||
},
|
||||
"installer": { createSession : function(){}, reinstall: function(){} },
|
||||
"installer": { createSession : function(){}, reinstall: function(){}, isInstalled: function(){ return true; } },
|
||||
"run.gui": { getElement : function(){} },
|
||||
"debugger": {debug: function() {}, stop: function(){}},
|
||||
"focusManager": {
|
||||
|
|
Ładowanie…
Reference in New Issue