diff --git a/node_modules/vfs-local/localfs.js b/node_modules/vfs-local/localfs.js index b93e1d75..8aefb4b2 100644 --- a/node_modules/vfs-local/localfs.js +++ b/node_modules/vfs-local/localfs.js @@ -1673,7 +1673,26 @@ module.exports = function setup(fsOptions) { var tmuxName = options.tmuxName || TMUXNAME; var session = options.session; - function fetchPid(callback, retries){ + function getFormatString(map) { + return Object.keys(map).filter(function(x) { + return x[0] == "#"; + }).join("\x01"); + } + + function getFormatObject(map, str) { + var data = str.split("\x01"); + var result = {}; + Object.keys(map).forEach(function(key, i) { + if (key[0] != "#") return; + var val = data[i]; + if (i >= map.numberDataIndex) + val = parseInt(val, 10) || 0; + result[map[key]] = val; + }); + return result; + } + + function fetchPid(callback, retries) { if (!retries) retries = 0; _execFile(TMUX, [ "-u2", "-L", tmuxName, "-C", @@ -1681,7 +1700,7 @@ module.exports = function setup(fsOptions) { "-t", session ], { maxBuffer: 1000 * 1024 - }, function(err, stdout){ + }, function(err, stdout) { var matches = /c9-pid-(\d+)-(\d)-/.exec(stdout); var isDead = parseInt(matches && matches[2], 10); var pid = isDead ? 0 : parseInt(matches && matches[1], 10); @@ -1701,6 +1720,7 @@ module.exports = function setup(fsOptions) { if (options.fetchpid) return fetchPid(callback); + // Capture the scrollback of a pane if (options.capturePane) { options = options.capturePane; @@ -1734,7 +1754,35 @@ module.exports = function setup(fsOptions) { return; } - if (options.getStatus) { + if (options.listSessions) { + args = ["-u2", "-L", tmuxName]; + + var sessionFormat = { + "#S": "name", + "#{session_id}": "id", + "#{session_attached}": "clientCount", + "#{session_activity}": "activity", + "#{session_created}": "created", + "#{session_height}": "height", + "#{session_width}": "width", + numberDataIndex: 2, + }; + + args.push("list-sessions", "-F", getFormatString(sessionFormat)); + + return _execFile(TMUX, args, function(e, data) { + var sessions = []; + (data || "").split("\n").forEach(function(str) { + if (!str) + return; + var session = getFormatObject(sessionFormat, str); + sessions.push(session); + }); + callback(e, {sessions: sessions}); + }); + } + + else if (options.getStatus) { options = options.getStatus; var sessionId = options.id; var args = ["-u2", "-L", tmuxName]; @@ -1764,23 +1812,6 @@ module.exports = function setup(fsOptions) { "#{client_height}" : "height", numberDataIndex : 1, }; - function getFormatString(map) { - return Object.keys(map).filter(function(x) { - return x[0] == "#"; - }).join("\x01"); - } - function getFormatObject(map, str) { - var data = str.split("\x01"); - var result = {}; - Object.keys(map).forEach(function(key, i) { - if (key[0] != "#") return; - var val = data[i]; - if (i >= map.numberDataIndex) - val = parseInt(val, 10); - result[map[key]] = val; - }); - return result; - } args.push("list-panes", "-F", getFormatString(paneFormat)); if (sessionId) @@ -1821,7 +1852,7 @@ module.exports = function setup(fsOptions) { } // Kill the session with the same name before starting a new one - if (options.kill) { + else if (options.kill) { if (!options.session) return callback(new Error("Missing session name")); diff --git a/plugins/c9.ide.plugins/gui.js b/plugins/c9.ide.plugins/gui.js index cc0bf006..c83b3fc5 100644 --- a/plugins/c9.ide.plugins/gui.js +++ b/plugins/c9.ide.plugins/gui.js @@ -880,6 +880,7 @@ define(function(require, exports, module) { } function updateReloadLastButton() { + if (!btnReloadLast) return; var last = getLastReloaded(); if (last) { btnReloadLast.visible = true; diff --git a/plugins/c9.ide.terminal/menu.xml b/plugins/c9.ide.terminal/menu.xml deleted file mode 100644 index 4bf60def..00000000 --- a/plugins/c9.ide.terminal/menu.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - New Terminal Tab - - Copy - Paste - Select All - Clear Buffer - - Close Active Pane - Split Active Pane - - Horizontal Layout (even) - Vertical Layout (even) - Horizonal Layout (main) - Vertical Layout (main) - - Toggle Status Bar - - Restart All Terminal Sessions - Detach Other Clients - Show More Terminal Commands... - Hint: Use Alt To Toggle Mouse Mode - - \ No newline at end of file diff --git a/plugins/c9.ide.terminal/terminal.js b/plugins/c9.ide.terminal/terminal.js index 6fcbcda4..e0151bcb 100644 --- a/plugins/c9.ide.terminal/terminal.js +++ b/plugins/c9.ide.terminal/terminal.js @@ -29,7 +29,6 @@ define(function(require, exports, module) { // Disabled: bad performance, openshift specific, possibly unreliable // var Monitor = require("./monitor.js"); var markup = require("text!./terminal.xml"); - var markupMenu = require("text!./menu.xml"); var Aceterm = require("./aceterm/aceterm"); var libterm = require("./aceterm/libterm"); @@ -120,7 +119,7 @@ define(function(require, exports, module) { group: "Terminal", hint: "Clears the terminal buffer", isAvailable: function(editor) { - return editor && editor.type == "terminal"; + return editor && editor.ace && editor.ace.session && editor.ace.session.term; }, exec: function (editor) { tabs.focussedTab.editor.clear(); @@ -129,16 +128,6 @@ define(function(require, exports, module) { var meta = '\x1b'; [ - ["close_term_pane", "x", "x"], - ["split_term_pane", '"', '"'], - ["layout_term_hor_even", "Meta-1", meta + "1"], - ["layout_term_ver_even", "Meta-2", meta + "2"], - ["layout_term_hor_main", "Meta-3", meta + "3"], - ["layout_term_ver_main", "Meta-4", meta + "4"], - ["move_term_paneup", "Up", '\x1b[A'], - ["move_term_panedown", "Down", '\x1b[B'], - ["move_term_paneright", "Right", '\x1b[C'], - ["move_term_paneleft", "Left", '\x1b[D'], ["term_help", "?", '?'], ["term_restart", "", ":kill-server\r"], ["term_detach", "", ":detach -a\r"], @@ -368,15 +357,78 @@ define(function(require, exports, module) { }); handle.draw = function() { - ui.insertMarkup(null, markupMenu, handle); - mnuTerminal = handle.getElement("mnuTerminal"); + menus.addItemByPath("context/terminal/", new ui.menu(), handle); + var c = 100; + menus.addItemByPath("context/terminal/New Terminal Tab", new ui.item({ command: "openterminal" }), c += 100, handle); + menus.addItemByPath("context/terminal/~", new ui.divider({}), c += 100, handle); + menus.addItemByPath("context/terminal/Copy", new ui.item({ command: "copy" }), c += 100, handle); + menus.addItemByPath("context/terminal/Paste", new ui.item({ command: "paste" }), c += 100, handle); + menus.addItemByPath("context/terminal/Select All", new ui.item({ command: "selectall" }), c += 100, handle); + menus.addItemByPath("context/terminal/Clear Buffer", new ui.item({ command: "clearterm" }), c += 100, handle); + menus.addItemByPath("context/terminal/~", new ui.divider({}), c += 100, handle); - if (c9.platform == "win32") { - var nodes = mnuTerminal.childNodes; - while (nodes[6]) { - mnuTerminal.removeChild(nodes[6]); - } + if (c9.platform != "win32") { + menus.addItemByPath("context/terminal/Tmux/", new ui.menu(), c += 100, handle); + menus.addItemByPath("context/terminal/~", new ui.divider({}), c += 100, handle); + menus.addItemByPath("context/terminal/Detach Other Clients", new ui.item({ + command: "term_detach" }), c += 100, handle); + menus.addItemByPath("context/terminal/Hint: Use Alt To Toggle Mouse Mode", new ui.item({ + disabled: "true" }), c += 100, handle); + + var c1 = 0; + var SESSIONS_MENU = "context/terminal/Tmux/Other sessions/"; + menus.addItemByPath(SESSIONS_MENU, new ui.menu({ + "onprop.visible": function(e) { + if (e.value) { + var currentName = tabs.focussedTab.document.getSession().id; + proc.tmux("", { listSessions: true }, function(err, pty, pid, meta) { + menus.remove(SESSIONS_MENU); + if (err || !meta.sessions) { + return menus.addItemByPath(SESSIONS_MENU + "Error loading session list:(", + new ui.item({ disabled: true }), handle); + } + meta.sessions.forEach(function(x) { + if (/output/.test(x.name)) return; + var label = x.name + "\t(" + x.width + "x" + x.height + ")\t" + x.clientCount + " connected clients"; + menus.addItemByPath(SESSIONS_MENU + menus.escape(label), + new ui.item({ value: x, class: x.name == currentName ? "strong" : "" }), handle); + }); + }); + } + }, + "onitemclick": function(e) { + var options = e.relatedNode.value; + if (options) { + var id = options.name; + tabs.getTabs().some(function(tab) { + if (tab.editorType == "terminal" || tab.editorType == "output") { + if (tab.document.getSession() && tab.document.getSession().id == id) { + tabs.focusTab(tab); + return true; + } + } + }) || tabs.open({ + editorType: /output/.test(id) ? "output" : "terminal", + document: { terminal: { id: id } }, + focus: true, + pane: tabs.focussedTab.pane + }); + } + } + }), c1 += 100, handle); + menus.addItemByPath(SESSIONS_MENU + "Loading...", new ui.item({ disabled: "true" }), 0, handle); + menus.addItemByPath("context/terminal/Tmux/~", new ui.divider({}), c1 += 100, handle); + + menus.addItemByPath("context/terminal/Tmux/Toggle Status Bar", new ui.item({ + command: "toggle_term_status" }), c1 += 100, handle); + menus.addItemByPath("context/terminal/Tmux/~", new ui.divider({}), c1 += 100, handle); + menus.addItemByPath("context/terminal/Tmux/Restart All Terminal Sessions", new ui.item({ + command: "term_restart" }), c1 += 100, handle); + menus.addItemByPath("context/terminal/Tmux/Show More Terminal Commands...", new ui.item({ + command: "term_help" }), c1 += 100, handle); } + menus.addItemByPath("context/terminal/Hint: Use Alt To Toggle Mouse Mode", new ui.item({ disabled: "true" }), c += 100, handle); + mnuTerminal = menus.get("context/terminal").menu; handle.draw = function() {}; }; @@ -1095,9 +1147,7 @@ define(function(require, exports, module) { plugin.on("clear", function() { if (currentSession) { var t = currentSession.terminal; - if (!t) return; - t.ybase = 0; - t.lines = t.lines.slice(-(t.ybase + t.rows)); + if (t) t.clear(); } }); diff --git a/plugins/c9.ide.tree/favorites.js b/plugins/c9.ide.tree/favorites.js index 71aa8a18..c9e385db 100644 --- a/plugins/c9.ide.tree/favorites.js +++ b/plugins/c9.ide.tree/favorites.js @@ -57,7 +57,7 @@ define(function(require, exports, module) { name: "removefavorite", isAvailable: function() { return tree && tree.selectedNode - && isFavoriteNode(tree.selectedNode); + && isFavoritePath(tree.selectedNode.path); }, exec: function() { tree.selectedNodes.forEach(function(node) {