diff --git a/.jslintrc b/.jslintrc new file mode 100644 index 0000000..db06c8e --- /dev/null +++ b/.jslintrc @@ -0,0 +1,14 @@ +{ + "node": true, + "nomen": true, + "regexp": true, + "todo": true, + "vars": true, + "unparam": true, + "globals": { + "$": true, + "document": true, + "brackets": true, + "define": true + } +} diff --git a/Gruntfile.js b/Gruntfile.js index 0b3cd7a..17bd29b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -30,6 +30,13 @@ module.exports = function(grunt) { src: ["**/*"], dest: "node/node_modules/tree-kill/", filter: "isFile" + }, + { + expand: true, + cwd: "node_modules/ansi-webkit/", + src: ["**/*"], + dest: "node/node_modules/ansi-webkit/", + filter: "isFile" } ] } diff --git a/images/hdy.brackets.shell.logo.png b/images/hdy.brackets.shell.logo.png deleted file mode 100644 index 5ce155e..0000000 Binary files a/images/hdy.brackets.shell.logo.png and /dev/null differ diff --git a/images/hdy.brackets.shell.svg b/images/hdy.brackets.shell.svg new file mode 100644 index 0000000..6e78b34 --- /dev/null +++ b/images/hdy.brackets.shell.svg @@ -0,0 +1,20 @@ + + + Brackets Shell Icon + + + + + + + + + + + + + + diff --git a/images/hdy.brackets.shell.toolbar.on.png b/images/hdy.brackets.shell.toolbar.on.png deleted file mode 100644 index aca0123..0000000 Binary files a/images/hdy.brackets.shell.toolbar.on.png and /dev/null differ diff --git a/images/hdy.brackets.shell.toolbar.png b/images/hdy.brackets.shell.toolbar.png deleted file mode 100644 index 6116bcd..0000000 Binary files a/images/hdy.brackets.shell.toolbar.png and /dev/null differ diff --git a/main.js b/main.js index 963b852..5cb5b36 100644 --- a/main.js +++ b/main.js @@ -1,67 +1,68 @@ /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */ -/*global define, $, brackets */ +/*global define, brackets */ define(function (require, exports, module) { "use strict"; - var AppInit = brackets.getModule("utils/AppInit"), - ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), - ProjectManager = brackets.getModule("project/ProjectManager"), - PreferencesManager = brackets.getModule("preferences/PreferencesManager"), - Preferences = PreferencesManager.getExtensionPrefs("hdy.brackets-shell"), - $icon = $(" ") - .attr("title", "Shell") - .appendTo($("#main-toolbar .buttons")); + var ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + Application = require("application"), + OnlineUsers = require("online"); - // Default theme if not defined - if(Preferences.get("dark") === undefined) { - Preferences.definePreference("dark", "boolean", false); - Preferences.set("dark", false); - Preferences.save(); - } - - // Default projectTracking if not defined - if(Preferences.get("trackProject") === undefined) { - Preferences.definePreference("trackProject", "boolean", true); - Preferences.set("trackProject", true); - Preferences.save(); - } - - if(Preferences.get("shell") === undefined) { - Preferences.definePreference("shell", "string", "cmd.exe"); - if (brackets.platform === "win") { - Preferences.set("shell", "cmd.exe"); - } else { - Preferences.set("shell", "/bin/sh"); - } - Preferences.save(); - } + ExtensionUtils.loadStyleSheet(module, "styles/bracketsShell.less"); - AppInit.appReady(function () { + Application.boot(); - var projectWatcher = require("projectWatcher"), - commandShell = require("shellPanel"); + OnlineUsers.init(); - require('./online').init(); - - ExtensionUtils.loadStyleSheet(module, "styles/shellPanel.css"); - $icon.on("click", commandShell.toggle); - - commandShell.hide(); - commandShell.setDirectory(projectWatcher.cleanPath(ProjectManager.getProjectRoot().fullPath)); + // Default theme if not defined +// if(Preferences.get("dark") === undefined) { +// Preferences.definePreference("dark", "boolean", false); +// Preferences.set("dark", false); +// Preferences.save(); +// } - if (Preferences.get("trackProject")) { - projectWatcher.register(function(cwd) { - if (cwd) { - commandShell.setDirectory(cwd); - } - }); - } + // Default projectTracking if not defined +// if(Preferences.get("trackProject") === undefined) { +// Preferences.definePreference("trackProject", "boolean", true); +// Preferences.set("trackProject", true); +// Preferences.save(); +// } - projectWatcher.watch(); +// if(Preferences.get("shell") === undefined) { +// Preferences.definePreference("shell", "string", "cmd.exe"); +// if (brackets.platform === "win") { +// Preferences.set("shell", "cmd.exe"); +// } else { +// Preferences.set("shell", "/bin/sh"); +// } +// Preferences.save(); +// } - }); +// AppInit.appReady(function () { +// +// var projectWatcher = require("projectWatcher"), +// ShellPanelView = require("views/shellPanelView"), +// commandShell = new ShellPanelView("My Title", projectWatcher.cleanPath(ProjectManager.getProjectRoot().fullPath)); +// +// require('./online').init(); +// +// ExtensionUtils.loadStyleSheet(module, "styles/shellPanel.css"); +// $icon.on("click", commandShell.toggle); +// +// commandShell.hide(); +// +// if (Preferences.get("trackProject")) { +// projectWatcher.register(function(cwd) { +// if (cwd) { +// commandShell.cwd = cwd; +// } +// }); +// } +// +// projectWatcher.watch(); +// +// }); }); diff --git a/modules/application.js b/modules/application.js new file mode 100644 index 0000000..5d0f076 --- /dev/null +++ b/modules/application.js @@ -0,0 +1,50 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, brackets */ + +define(function (require, exports, module) { + "use strict"; + + var Menus = brackets.getModule("command/Menus"), + + Strings = require("strings"), + MenuItem = require("menuItem"), + CommandId = require("commandId"), + ExtensionBarButton = require("extensionBarButton"), + Panel = require("panel"), + PanelState = require("panelState"), + Tabs = require("tabs"), + + _viewShellMenuItem, + _viewShellButton, + _panel, + _tabs; + + module.exports.boot = function() { + + _panel = new Panel("hdy-brackets-shell-panel", + Strings.APPLICATION_TITLE, + "shellTemplate", + PanelState.Closed); + + _viewShellButton = new ExtensionBarButton("hdy-shell-toolbar-icon", + Strings.TOOLTIP_TOOLBAR_ICON); + + _viewShellMenuItem = new MenuItem(CommandId.VIEW_SHELL_COMMAND, + Strings.MENU_VIEW_SHELL, + Menus.AppMenuBar.VIEW_MENU, + Menus.LAST_IN_SECTION, + Menus.MenuSection.VIEW_HIDESHOW_COMMANDS); + + _tabs = new Tabs("hdy-brackets-shell-tabs", "tabsTemplate"); + + _panel.register(_viewShellButton); + _panel.register(_viewShellMenuItem); + _panel.controls.push(_tabs); + + _panel.draw(); + + + }; + +}); diff --git a/modules/commandId.js b/modules/commandId.js new file mode 100644 index 0000000..e356473 --- /dev/null +++ b/modules/commandId.js @@ -0,0 +1,14 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define */ + +define(function (require, exports, module) { + "use strict"; + + module.exports = { + + "VIEW_SHELL_COMMAND": "hdy.brackets.shell" + + }; + +}); diff --git a/modules/control.js b/modules/control.js new file mode 100644 index 0000000..d25c1cd --- /dev/null +++ b/modules/control.js @@ -0,0 +1,45 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define */ + +define(function (require, exports, module) { + "use strict"; + + var Control = function(id) { + + this.children = []; + this.id = id; + + }; + + Control.prototype = { + + add: function (child) { + + this.children.push(child); + + }, + + remove: function (child) { + + var length = this.children.length; + for (var i = 0; i < length; i++) { + if (this.children[i] === child) { + this.children.splice(i, 1); + return; + } + } + }, + + getChild: function (i) { + return this.children[i]; + }, + + hasChildren: function () { + return this.children.length > 0; + } + }; + + module.exports = Control; + +}); diff --git a/modules/exception.js b/modules/exception.js new file mode 100644 index 0000000..7b820d0 --- /dev/null +++ b/modules/exception.js @@ -0,0 +1,16 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define */ + +define(function (require, exports, module) { + "use strict"; + + var Exception = function(message) { + + this.message = "hdyException: " + message; + + }; + + module.exports = Exception; + +}); diff --git a/modules/extensionBarButton.js b/modules/extensionBarButton.js new file mode 100644 index 0000000..4526acd --- /dev/null +++ b/modules/extensionBarButton.js @@ -0,0 +1,43 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, $ */ + +define(function (require, exports, module) { + "use strict"; + + var PanelState = require("panelState"); + + function ExtensionBarButton(id, tooltip) { + + var self = this, + _state = PanelState.Closed; + + self.id = id; + self.panel = undefined; + self.$icon = $("") + .attr("title", tooltip); + self.$icon.appendTo($("#main-toolbar .buttons")); + + self.setState = function(state) { + + _state = state; + self.$icon.removeClass(); + self.$icon.addClass(state); + + }; + + self.$icon.on("click", function() { + + var state = (_state === PanelState.Closed) ? PanelState.Open : PanelState.Closed; + + if (self.panel) { + self.panel.setState(state); + } + }); + + } + + module.exports = ExtensionBarButton; + +}); + diff --git a/modules/menuItem.js b/modules/menuItem.js new file mode 100644 index 0000000..04f3ac4 --- /dev/null +++ b/modules/menuItem.js @@ -0,0 +1,43 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, brackets */ + +define(function (require, exports, module) { + "use strict"; + + var CommandManager = brackets.getModule("command/CommandManager"), + Menus = brackets.getModule("command/Menus"), + + PanelState = require("panelState"); + + function MenuItem(id, name, menu, position, section) { + + var self = this, + _command, + _commandCallback = function() { + + var state = !_command.getChecked() ? PanelState.Open : PanelState.Closed; + + if (self.panel) { + self.panel.setState(state); + } + + }; + + self.id = id; + self.panel = undefined; + self.setState = function(state) { + + _command.setChecked(state === PanelState.Open); + + }; + + _command = CommandManager.register(name, id, _commandCallback); + var viewMenu = Menus.getMenu(menu); + viewMenu.addMenuItem(id, "F4", position, section); + + } + + module.exports = MenuItem; + +}); diff --git a/modules/panel.js b/modules/panel.js new file mode 100644 index 0000000..cf5abd4 --- /dev/null +++ b/modules/panel.js @@ -0,0 +1,91 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, $, brackets, Mustache */ + +define(function (require, exports, module) { + "use strict"; + + var WorkspaceManager = brackets.getModule("view/WorkspaceManager"), + ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + + PanelState = require("panelState"); + + + ExtensionUtils.loadStyleSheet(module, "../styles/panel.less"); + + function Panel(id, title, panelTemplate, state) { + + var self = this, + _observers = {}, + _panel; + + if (!state) { + state = PanelState.Closed; + } + + self.id = id; + self.state = state; + self.title = title; + self.controls = []; + + self.draw = function() { + + require(["text!" + panelTemplate], function(templateHtml) { + + var compiledTemplate = Mustache.render(templateHtml, self), + control; + + _panel = WorkspaceManager.createBottomPanel(self.id, + $(compiledTemplate), + 100); + + if (_panel) { + _panel.setVisible(state === PanelState.Open); + + $(".hdy-brackets-shell-panel .close").on("click", function() { + self.setState(PanelState.Closed); + }); + + } + + for (var controlIndex in self.controls) { + control = self.controls[controlIndex]; + + if (control && control.draw) { + control.draw(); + } + } + + }); + }; + + self.register = function(observer) { + + _observers[observer.id] = observer; + observer.panel = { + 'setState': self.setState + }; + + observer.setState(self.state); + + }; + + self.setState = function(state) { + + if (_panel) { + _panel.setVisible(state === PanelState.Open); + } + + for (var subscriber in _observers) { + _observers[subscriber].setState(state); + } + + }; + + self.setState(state); + + } + + module.exports = Panel; + +}); diff --git a/modules/panelState.js b/modules/panelState.js new file mode 100644 index 0000000..4f43f74 --- /dev/null +++ b/modules/panelState.js @@ -0,0 +1,16 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define */ + +define(function (require, exports, module) { + "use strict"; + + module.exports = { + + "Closed": "closed", + + "Open": "open" + + }; + +}); diff --git a/projectWatcher.js b/modules/projectWatcher.js similarity index 100% rename from projectWatcher.js rename to modules/projectWatcher.js diff --git a/modules/shell.js b/modules/shell.js new file mode 100644 index 0000000..4148ef2 --- /dev/null +++ b/modules/shell.js @@ -0,0 +1,102 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, $, brackets */ + +define(function (require, exports, module) { + "use strict"; + + var ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + NodeDomain = brackets.getModule("utils/NodeDomain"), + ShellDomain = new NodeDomain("ShellDomain", + ExtensionUtils.getModulePath(module, + "node/shellDomain")), + self; + + function _execute(cmd) { + + ShellDomain.exec("execute", cmd); + + } + + function _onStdOut(callback) { + + self._onStdOutCallback = callback; + + } + + function _onStdErr(callback) { + + self._onStdErrCallback = callback; + + } + + function _onClose(callback) { + + self._onCloseCallback = callback; + + } + + function _onClear(callback) { + + self._onClearCallback = callback; + + } + + function _kill() { + + ShellDomain.exec("kill"); + + } + + function _initialize() { + + $(ShellDomain).on("stdout", function(evt, data) { + + if (self._onStdOutCallback) { + self._onStdOutCallback(data); + } + + }); + + $(ShellDomain).on("stderr", function(evt, data) { + + if (self._onStdErrCallback) { + self._onStdErrCallback(data); + } + + }); + + $(ShellDomain).on("close", function(evt, dir) { + + if (self._onCloseCallback) { + self._onCloseCallback(dir); + } + + }); + + $(ShellDomain).on("clear", function() { + + if (self._onClearCallback) { + self._onClearCallback(); + } + + }); + } + + var Shell = function() { + + self = this; + + _initialize(); + + }; + + Shell.prototype.execute = _execute; + Shell.prototype.kill = _kill; + Shell.prototype.onStdOut = _onStdOut; + Shell.prototype.onClose = _onClose; + Shell.prototype.onClear = _onClear; + + module.exports = Shell; + +}); diff --git a/shellAnsiFormat.js b/modules/shellAnsiFormat.js similarity index 100% rename from shellAnsiFormat.js rename to modules/shellAnsiFormat.js diff --git a/modules/tab.js b/modules/tab.js new file mode 100644 index 0000000..6ab5d94 --- /dev/null +++ b/modules/tab.js @@ -0,0 +1,42 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, Mustache */ + +define(function (require, exports, module) { + "use strict"; + + var Tab = function(name, tabTemplate) { + + var self = this; + + self.name = name; + + self.rename = function(name) { + self.name = name; + }; + + self.draw = function() { + + var control; + + require(["text!" + tabTemplate], function(templateHtml) { + + var compiledTemplate = Mustache.render(templateHtml, self); + + for (var controlIndex in self.controls) { + control = self.controls[controlIndex]; + + if (control && control.draw) { + control.draw(); + } + } + + }); + + }; + + }; + + module.exports = Tab; + +}); diff --git a/modules/tabs.js b/modules/tabs.js new file mode 100644 index 0000000..49ddca5 --- /dev/null +++ b/modules/tabs.js @@ -0,0 +1,84 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, + indent: 4, maxerr: 50 */ +/*global define, $, brackets, Mustache */ + +define(function (require, exports, module) { + "use strict"; + + var ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + + Tab = require("tab"); + + + ExtensionUtils.loadStyleSheet(module, "../styles/tabs.less"); + require("droptabs"); + + function Tabs(id, tabsTemplate) { + + var self = this, + _tabs = []; + + function _renderTab(tab) { + +// var compiledTemplate = Mustache.render(templateHtml, self), +// $compiledTemplate = $(compiledTemplate), +// $toolbar = $("#hdy-brackets-shell-panel .toolbar"), +// $title = $("#hdy-brackets-shell-panel .title"), +// $close = $("#hdy-brackets-shell-panel .close"); +// +// $title.remove(); +// $close.remove(); +// +// $compiledTemplate.find(".span9").prepend($title); +// $compiledTemplate.append($close); +// +// $toolbar.append($compiledTemplate); + + } + + self.id = id; + + self.add = function(tab) { + _tabs.push(tab); + _renderTab(tab); + }; + + self.draw = function() { + + var control; + + require(["text!" + tabsTemplate], function(templateHtml) { + + var compiledTemplate = Mustache.render(templateHtml, self), + $compiledTemplate = $(compiledTemplate), + $toolbar = $("#hdy-brackets-shell-panel .toolbar"), + $title = $("#hdy-brackets-shell-panel .title"), + $close = $("#hdy-brackets-shell-panel .close"); + + $title.remove(); + $close.remove(); + +// $compiledTemplate.find(".span9").prepend($title); + + $toolbar.append($compiledTemplate); + $compiledTemplate.append($close); + + $("#hdy-brackets-shell-panel .droptabs").droptabs(); + + for (var controlIndex in self.controls) { + control = self.controls[controlIndex]; + + if (control && control.draw) { + control.draw(); + } + } + + }); + + }; + + } + + module.exports = Tabs; + +}); diff --git a/nls/root/strings.js b/nls/root/strings.js new file mode 100644 index 0000000..f71a0d1 --- /dev/null +++ b/nls/root/strings.js @@ -0,0 +1,16 @@ +/*jshint maxlen:false */ +/*global define */ + +define({ + + APPLICATION_TITLE: "Brackets Shell", + + EXCEPTION_PANEL_INITIALIZED: "Panel init method should only be called once", + + MENU_VIEW_SHELL: "Brackets Shell", + + TITLE_SHELL_PANEL: "Shell", + + TOOLTIP_TOOLBAR_ICON: "Brackets Shell" + +}); diff --git a/nls/strings.js b/nls/strings.js new file mode 100644 index 0000000..c4ff6b2 --- /dev/null +++ b/nls/strings.js @@ -0,0 +1,15 @@ +/* + * @see: https://github.com/adobe/brackets/tree/master/src/extensions/samples/LocalizationExample + */ +define(function (require, exports, module) { + // Code that needs to display user strings should call require("strings") to load + // strings.js. This file will dynamically load strings.js for the specified by bracketes.locale. + // + // Translations for other locales should be placed in nls/>/strings.js + // Localization is provided via the i18n plugin. + // All other bundles for languages need to add a prefix to the exports below so i18n can find them. + module.exports = { + root: true + }; + +}); diff --git a/node/node_modules/ansi-webkit/LICENSE b/node/node_modules/ansi-webkit/LICENSE new file mode 100644 index 0000000..1fe8f7d --- /dev/null +++ b/node/node_modules/ansi-webkit/LICENSE @@ -0,0 +1,9 @@ +(The MIT License) + +Copyright (c) 2014 simov + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node/node_modules/ansi-webkit/README.md b/node/node_modules/ansi-webkit/README.md new file mode 100644 index 0000000..a7079db --- /dev/null +++ b/node/node_modules/ansi-webkit/README.md @@ -0,0 +1,53 @@ + +# ANSI-WebKit + +## turns this + +![ansi][1] + + +## into this + +![webkit][2] + + +## how + +```js +var aw = require('ansi-webkit'); +var str = '[42mspawn '; +console.log.apply(console, aw.parse(str)); +``` + + +## example + +```js +// show the dev tools by default +require('nw.gui').Window.get().showDevTools().resizeTo(800, 1000); +var aw = require('ansi-webkit'); + +var spawn = require('child_process').spawn, + child = spawn('node', ['spawn.js']); + +child.stdout.on('data', function (e) { + var str = e.toString().trim(); + // ansi + console.log(str); + // parsed + console.log.apply(console, aw.parse(str)); +}); + +child.stderr.on('data', function (e) { + var str = e.toString().trim(); + console.log(str); +}); +``` + +## license + +MIT + + + [1]: http://i.imgur.com/gyPudQz.png + [2]: http://i.imgur.com/hZJxhID.png diff --git a/node/node_modules/ansi-webkit/example/index.html b/node/node_modules/ansi-webkit/example/index.html new file mode 100644 index 0000000..a9d7ccf --- /dev/null +++ b/node/node_modules/ansi-webkit/example/index.html @@ -0,0 +1,9 @@ + + + + + ansi-webkit + + + + diff --git a/node/node_modules/ansi-webkit/example/package.json b/node/node_modules/ansi-webkit/example/package.json new file mode 100644 index 0000000..6f371ea --- /dev/null +++ b/node/node_modules/ansi-webkit/example/package.json @@ -0,0 +1,17 @@ +{ + "name": "ansi-webkit", + "private": true, + + "dependencies": { + "colors" : "*", + "express" : "4.4.4", + "morgan" : "1.1.1", + "request" : "2.27.0" + }, + + "main": "index.html", + "window": { + "width": 800, + "height": 1000 + } +} diff --git a/node/node_modules/ansi-webkit/example/script.js b/node/node_modules/ansi-webkit/example/script.js new file mode 100644 index 0000000..6a999dc --- /dev/null +++ b/node/node_modules/ansi-webkit/example/script.js @@ -0,0 +1,21 @@ + +// show the dev tools by default +require('nw.gui').Window.get().showDevTools().resizeTo(800, 1000); + + +var aw = require('../lib'); + +var spawn = require('child_process').spawn, + child = spawn('node', ['spawn.js']); + + +child.stdout.on('data', function (e) { + var str = e.toString().trim(); + console.log(str); + console.log.apply(console, aw.parse(str)); +}); + +child.stderr.on('data', function (e) { + var str = e.toString().trim(); + console.log(str); +}); diff --git a/node/node_modules/ansi-webkit/example/spawn.js b/node/node_modules/ansi-webkit/example/spawn.js new file mode 100644 index 0000000..06bc910 --- /dev/null +++ b/node/node_modules/ansi-webkit/example/spawn.js @@ -0,0 +1,49 @@ + +var express = require('express'), + logger = require('morgan'); +var request = require('request'); +require('colors'); +var c = require('cli-color'); + + +var app = express() + .use(logger('dev')); + +app.get('/', function (req, res) { + console.log('Hello World'.rainbow); + res.end(); +}); + +app.listen(3000, function () { + // colors + console.log( + 'Test'.red, + 'app'.yellowBG, + 'listening'.underline, + 'on'.italic, + 'port'.strikethrough, + '3000'.green.bold + ); + // cli-color + console.log( + c.red('Test'), + c.bgYellow('app'), + c.underline('listening'), + c.italic('on'), + c.strike('port'), + c.green.bold('3000') + ); +}); + + +// colors +console.log('spawn'.bold.red.greenBG); +console.log('str1'.red + 'str2'.blueBG + 'str3'.red + 'str4'.bold.green + 'str5'); +// cli-color +console.log(c.bold.red.bgGreen('spawn')); +console.log(c.red('str1') + c.bgBlue('str2') + c.red('str3') + c.bold.green('str4') + 'str5'); + +request.get('http://localhost:3000', function (err, res, body) { + console.log('DONE!'.italic); + console.log(c.italic('DONE!')); +}); diff --git a/node/node_modules/ansi-webkit/lib/ansi.json b/node/node_modules/ansi-webkit/lib/ansi.json new file mode 100644 index 0000000..a447ef2 --- /dev/null +++ b/node/node_modules/ansi-webkit/lib/ansi.json @@ -0,0 +1,27 @@ +{ + "bold" : ["[1m", "[22m"], + "italic" : ["[3m", "[23m"], + "underline" : ["[4m", "[24m"], + "inverse" : ["[7m", "[27m"], + "strikethrough" : ["[9m", "[29m"], + + "black" : ["[30m", "[39m"], + "red" : ["[31m", "[39m"], + "green" : ["[32m", "[39m"], + "yellow" : ["[33m", "[39m"], + "blue" : ["[34m", "[39m"], + "magenta" : ["[35m", "[39m"], + "cyan" : ["[36m", "[39m"], + "white" : ["[37m", "[39m"], + "grey" : ["[90m", "[39m"], + + "bg-black" : ["[40m", "[49m"], + "bg-red" : ["[41m", "[49m"], + "bg-green" : ["[42m", "[49m"], + "bg-yellow" : ["[43m", "[49m"], + "bg-blue" : ["[44m", "[49m"], + "bg-magenta" : ["[45m", "[49m"], + "bg-cyan" : ["[46m", "[49m"], + "bg-white" : ["[47m", "[49m"], + "bg-grey" : ["[49;5;8m", "[49m"] +} diff --git a/node/node_modules/ansi-webkit/lib/index.js b/node/node_modules/ansi-webkit/lib/index.js new file mode 100644 index 0000000..9cb991d --- /dev/null +++ b/node/node_modules/ansi-webkit/lib/index.js @@ -0,0 +1,77 @@ + +var ansi = require('./ansi'), + themes = require('./themes'); + + +exports.tokenize = function (str) { + for (var key in ansi) { + var open = ansi[key][0], + close = ansi[key][1]; + + str = str.replace( + new RegExp('\\'+open, 'g'), + '<~'+key+'~>' + ); + str = str.replace( + new RegExp('\\'+close, 'g'), + '<~off~>' + ); + } + + return str + .replace(new RegExp('','g'), '') + .replace(new RegExp('\\[0m','g'), '<~off~>') + .replace(/(?:\<~off~\>){2,}/g, '<~off~>') + .trim(); +} + +exports.detokenize = function (str) { + str = this.tokenize(str); + + var arr = str.split('<~'), result = [], tmp = []; + + for (var i=0; i < arr.length; i++) { + if (!arr[i]) continue; + + var part = arr[i].split('~>'); + tmp.push(part[0]); + + if (part.length > 0 && part[1]) { + result.push({keys:tmp, str:part[1]}); + tmp = []; + } + } + + return result; +} + +exports.css = function (keys, theme) { + theme = theme||'default'; + + var result = []; + for (var i=0; i < keys.length; i++) { + result.push(themes[theme][keys[i]]); + } + + return result.join(' '); +} + +exports.stringify = function (data) { + var result = []; + for (var i=0; i < data.length; i++) { + result.push('%c'+data[i].str); + } + return result.join(''); +} + +exports.parse = function (str, theme) { + var data = this.detokenize(this.tokenize(str)); + + var args = []; + for (var i=0; i < data.length; i++) { + args.push(this.css(data[i].keys, theme)); + } + args.splice(0,0,this.stringify(data)); + + return args; +} diff --git a/node/node_modules/ansi-webkit/lib/themes.json b/node/node_modules/ansi-webkit/lib/themes.json new file mode 100644 index 0000000..5506682 --- /dev/null +++ b/node/node_modules/ansi-webkit/lib/themes.json @@ -0,0 +1,30 @@ +{ + "default": { + "bold" : "font-weight: bold;", + "italic" : "font-style: italic;", + "underline" : "text-decoration: underline;", + "strikethrough" : "text-decoration: line-through;", + + "black" : "color: black;", + "red" : "color: red;", + "green" : "color: green;", + "yellow" : "color: yellow;", + "blue" : "color: blue;", + "magenta" : "color: magenta;", + "cyan" : "color: cyan;", + "white" : "color: white;", + "grey" : "color: grey;", + + "bg-black" : "background-color: black;", + "bg-red" : "background-color: red;", + "bg-green" : "background-color: green;", + "bg-yellow" : "background-color: yellow;", + "bg-blue" : "background-color: blue;", + "bg-magenta" : "background-color: magenta;", + "bg-cyan" : "background-color: cyan;", + "bg-white" : "background-color: white;", + "bg-grey" : "background-color: grey;", + + "off": "font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black;" + } +} diff --git a/node/node_modules/ansi-webkit/package.json b/node/node_modules/ansi-webkit/package.json new file mode 100644 index 0000000..5a441ad --- /dev/null +++ b/node/node_modules/ansi-webkit/package.json @@ -0,0 +1,39 @@ +{ + "name": "ansi-webkit", + "version": "1.0.1", + "description": "Print ANSI escaped colors in a browser console", + "keywords": [ + "ansi", + "colors", + "console", + "log", + "browser", + "webkit" + ], + "license": "MIT", + "homepage": "https://github.com/simov/ansi-webkit", + "author": { + "name": "simo", + "email": "simeonvelichkov@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/simov/ansi-webkit.git" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "colors": "*", + "cli-color": "*" + }, + "main": "./lib", + "readme": "\n# ANSI-WebKit\n\n## turns this\n\n![ansi][1]\n\n\n## into this\n\n![webkit][2]\n\n\n## how\n\n```js\nvar aw = require('ansi-webkit');\nvar str = '[42m\u001b[31m\u001b[1mspawn\u001b[22m\u001b[39m\u001b[49m ';\nconsole.log.apply(console, aw.parse(str));\n```\n\n\n## example\n\n```js\n// show the dev tools by default\nrequire('nw.gui').Window.get().showDevTools().resizeTo(800, 1000);\nvar aw = require('ansi-webkit');\n\nvar spawn = require('child_process').spawn,\n child = spawn('node', ['spawn.js']);\n\nchild.stdout.on('data', function (e) {\n var str = e.toString().trim();\n // ansi\n console.log(str);\n // parsed\n console.log.apply(console, aw.parse(str));\n});\n\nchild.stderr.on('data', function (e) {\n var str = e.toString().trim();\n console.log(str);\n});\n```\n\n## license\n\nMIT\n\n\n [1]: http://i.imgur.com/gyPudQz.png\n [2]: http://i.imgur.com/hZJxhID.png\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/simov/ansi-webkit/issues" + }, + "_id": "ansi-webkit@1.0.1", + "_shasum": "338f7dece0a29cad76e983e6b8f00554c0924bf4", + "_from": "ansi-webkit@", + "_resolved": "https://registry.npmjs.org/ansi-webkit/-/ansi-webkit-1.0.1.tgz" +} diff --git a/node/node_modules/ansi-webkit/test/index.js b/node/node_modules/ansi-webkit/test/index.js new file mode 100644 index 0000000..61d5061 --- /dev/null +++ b/node/node_modules/ansi-webkit/test/index.js @@ -0,0 +1,127 @@ + +var should = require('should'); +var aw = require('../lib') +require('colors'); +var c = require('cli-color'); + +var str = [ + // colors + { + input: 'str1'.red + 'str2'.blueBG + 'str3'.red + 'str4'.bold.green + 'str5', + tokenized: '<~red~>str1<~off~><~bg-blue~>str2<~off~><~red~>str3<~off~><~green~><~bold~>str4<~off~>str5', + stringified: '%cstr1%cstr2%cstr3%cstr4%cstr5' + }, + // cli-color + { + input: c.red('str1') + c.bgBlue('str2') + c.red('str3') + c.bold.green('str4') + 'str5', + tokenized: '<~red~>str1<~off~><~bg-blue~>str2<~off~><~red~>str3<~off~><~bold~><~green~>str4<~off~>str5', + stringified: '%cstr1%cstr2%cstr3%cstr4%cstr5' + }, + // express + { + input: '[90mPOST /tbl/1 200 49.359 ms - 33137 ', + tokenized: '<~grey~>POST /tbl/1 <~green~>200 <~grey~>49.359 ms - 33137<~off~>', + stringified: '%cPOST /tbl/1 %c200 %c49.359 ms - 33137' + } +]; +var obj = [ + { + parsed: [ + { keys: [ 'red' ], str: 'str1' }, + { keys: [ 'off', 'bg-blue' ], str: 'str2' }, + { keys: [ 'off', 'red' ], str: 'str3' }, + { keys: [ 'off', 'green', 'bold' ], str: 'str4' }, + { keys: [ 'off' ], str: 'str5' } + ], + args: [ + '%cstr1%cstr2%cstr3%cstr4%cstr5', + 'color: red;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; background-color: blue;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; color: red;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; color: green; font-weight: bold;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black;' + ] + }, + { + parsed: [ + { keys: [ 'red' ], str: 'str1' }, + { keys: [ 'off', 'bg-blue' ], str: 'str2' }, + { keys: [ 'off', 'red' ], str: 'str3' }, + { keys: [ 'off', 'bold', 'green' ], str: 'str4' }, + { keys: [ 'off' ], str: 'str5' } + ], + args: [ + '%cstr1%cstr2%cstr3%cstr4%cstr5', + 'color: red;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; background-color: blue;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; color: red;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black; font-weight: bold; color: green;', + 'font-weight: normal; font-style: normal; text-decoration: none; background-color: none; color: black;' + ] + }, + { + parsed: [ + { keys: [ 'grey' ], str: 'POST /tbl/1 ' }, + { keys: [ 'green' ], str: '200 ' }, + { keys: [ 'grey' ], str: '49.359 ms - 33137' } + ], + args: [ + '%cPOST /tbl/1 %c200 %c49.359 ms - 33137', + 'color: grey;', + 'color: green;', + 'color: grey;' + ] + } +]; + +var log = false; + + +describe('ansi-webkit', function () { + + describe('tokenize', function () { + it('tokenize', function () { + for (var i=0; i < str.length; i++) { + var result = aw.tokenize(str[i].input); + log && console.log(result); + result.should.equal(str[i].tokenized); + } + }); + }); + + describe('detokenize', function () { + it('detokenize', function () { + for (var i=0; i < str.length; i++) { + var result = aw.detokenize(str[i].input); + log && console.log(result); + should.deepEqual(result, obj[i].parsed); + } + }); + }); + + describe('css', function () { + it('css', function () { + aw.css(['green','bold']).should.equal('color: green; font-weight: bold;') + }); + }); + + describe('stringify', function () { + it('stringify', function () { + for (var i=0; i < obj.length; i++) { + var result = aw.stringify(obj[i].parsed); + log && console.log(result); + result.should.equal(str[i].stringified); + } + }); + }); + + describe('parse', function () { + it('parse', function () { + for (var i=0; i < str.length; i++) { + var result = aw.parse(str[i].input); + log && console.log(result); + should.deepEqual(result, obj[i].args); + } + }); + }); +}); diff --git a/node/node_modules/ansi-webkit/test/mocha.opts b/node/node_modules/ansi-webkit/test/mocha.opts new file mode 100644 index 0000000..35a00c1 --- /dev/null +++ b/node/node_modules/ansi-webkit/test/mocha.opts @@ -0,0 +1,2 @@ +--require should +--reporter spec \ No newline at end of file diff --git a/node/hdyShellDomain.js b/node/shellDomain.js similarity index 78% rename from node/hdyShellDomain.js rename to node/shellDomain.js index 8ac403b..1bf0e16 100644 --- a/node/hdyShellDomain.js +++ b/node/shellDomain.js @@ -3,9 +3,11 @@ (function() { "use strict"; + var _domainManager, child, - kill = require("tree-kill"); + kill = require("tree-kill"), + ansi = require("ansi-webkit"); /** * @private @@ -14,32 +16,32 @@ if false, return free memory only. * @return {number} The amount of memory. */ - function _execute(cmd, cwd, isWin, shell) { - - var spawn = require("child_process").spawn, - args, - enddir = cwd, - tempdir; + function _execute(cmd) { - cmd = cmd.trim(); + var spawn = require("child_process").spawn, + dir = cmd.cwd, + text = cmd.cmd, + args = cmd.cmd ? "/c" : "-c", + shell = cmd.shell ? "cmd.exe" : cmd.shell, + isWin = !cmd.shell || cmd.shell.trim().toLowerCase() === "cmd.exe"; // Are we changing directories? If so we need // to handle that in a special way. - if (cmd.slice(0, 3).toLowerCase() === "cd ") { + // TODO: Might need to change this. + if (text.slice(0, 3).toLowerCase() === "cd ") { try { - process.chdir(cwd); - tempdir = cmd.substring(2).trim(); - process.chdir(tempdir); - enddir = process.cwd(); + process.chdir(dir); + process.chdir(text.substring(2).trim()); + dir = process.cwd(); } catch (e) {} } // clearing the console with clear or clr? - if ((cmd.toLowerCase() === "clear" && !isWin) || - (cmd.toLowerCase() === "cls" && isWin)) { + if ((text.toLowerCase() === "clear" && !isWin) || + (text.toLowerCase() === "cls" && isWin)) { _domainManager.emitEvent("hdyShellDomain", "clear"); } @@ -53,19 +55,23 @@ cmd = shell; } - child = spawn(cmd, args, { cwd: cwd, env: process.env }); + child = spawn(cmd, args, { cwd: dir, env: process.env }); - child.stdout.on("data", function (data) { - _domainManager.emitEvent("hdyShellDomain", "stdout", [data.toString()]); + process.stdout.on("data", function (data) { + var parsedOutput = ansi.parse(data.toString().trim()); + + _domainManager.emitEvent("hdyShellDomain", "stdout", [parsedOutput]); }); - child.stderr.on("data", function (data) { - _domainManager.emitEvent("hdyShellDomain", "stderr", [data.toString()]); + process.stderr.on("data", function (data) { + var parsedOutput = ansi.parse(data.toString().trim()); + + _domainManager.emitEvent("hdyShellDomain", "stderr", [parsedOutput]); }); child.on("close", function () { child.kill(); - _domainManager.emitEvent("hdyShellDomain", "close", [enddir]); + _domainManager.emitEvent("hdyShellDomain", "close", [dir]); }); } diff --git a/package.json b/package.json index 1deb580..74e7c12 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,13 @@ "brackets": ">=0.40.0" }, "devDependencies": { + "ansi-webkit": "^1.0.1", "chai": "^1.10.0", "grunt": "^0.4.5", "grunt-contrib-compress": "^0.12.0", "grunt-contrib-copy": "^0.7.0", - "mocha": "^2.0.1" + "mocha": "^2.0.1", + "requirejs": "^2.1.15" }, "dependencies": { "tree-kill": "^0.0.6" diff --git a/requirejs-config.json b/requirejs-config.json new file mode 100644 index 0000000..8c106b6 --- /dev/null +++ b/requirejs-config.json @@ -0,0 +1,25 @@ +{ + "baseUrl": ".", + "paths": { + + "application": "modules/application", + "control": "modules/control", + "panel": "modules/panel", + "menuItem": "modules/menuItem", + "extensionBarButton": "modules/extensionBarButton", + "exception": "modules/exception", + "strings": "strings", + "tabs": "modules/tabs", + "tab": "modules/tab", + + "commandId": "modules/commandId", + "panelState": "modules/panelState", + + "online": "vendor/online", + "droptabs": "vendor/jquery.droptabs", + + "shellTemplate": "templates/panel.html", + "tabsTemplate": "templates/tabs.html" + + } +} diff --git a/strings.js b/strings.js new file mode 100644 index 0000000..0dde9b2 --- /dev/null +++ b/strings.js @@ -0,0 +1,9 @@ +/** + * This file provides the interface to user visible strings in Brackets. Code that needs + * to display strings should should load this module by calling var Strings = require("strings"). + * The i18n plugin will dynamically load the strings for the right locale and populate + * the exports variable. See nls/root/strings.js for the master file of English strings. + */ +define(function (require, exports, module) { + module.exports = require("i18n!nls/strings"); +}); diff --git a/styles/BracketsShell.less b/styles/BracketsShell.less new file mode 100644 index 0000000..42e9826 --- /dev/null +++ b/styles/BracketsShell.less @@ -0,0 +1,9 @@ +#hdy-shell-toolbar-icon { + background: url("../images/hdy.brackets.shell.svg") no-repeat 0 0; + &.closed { + background-position: 0 0; + } + &.open { + background-position: 0 -24px; + } +} diff --git a/styles/Shell.less b/styles/Shell.less new file mode 100644 index 0000000..e69de29 diff --git a/styles/Tabs.less b/styles/Tabs.less new file mode 100644 index 0000000..352686a --- /dev/null +++ b/styles/Tabs.less @@ -0,0 +1,17 @@ +.hdy-brackets-shell-panel { + + .hdy-tabs { + + display: inline-block; + + li { + height: 20px; + } + + } + + .simple-toolbar-layout.toolbar { + overflow: inherit; + } + +} diff --git a/styles/panel.less b/styles/panel.less new file mode 100644 index 0000000..f6df6ff --- /dev/null +++ b/styles/panel.less @@ -0,0 +1,17 @@ +@import "variables.less"; + +.hdy-brackets-shell-panel { + + &.bottom-panel { + /* Add background-color here with !important */ + border-top: inherit; + } + + .hdy-panel-title { + margin-right: 20px; + vertical-align: middle; + display: inline-block; + + } + +} diff --git a/styles/shellPanel.css b/styles/shellPanel.old.css similarity index 84% rename from styles/shellPanel.css rename to styles/shellPanel.old.css index 72339f0..7578e65 100644 --- a/styles/shellPanel.css +++ b/styles/shellPanel.old.css @@ -2,8 +2,25 @@ margin-right: 20px; } +.hdy-command-group:nth-of-type(1) { + margin-top: 10px; +} + +.hdy-current:nth-last-of-type(1) { + margin-bottom: 30px; +} + +.hdy-brackets-shell-panel-title { + margin-right: 20px; + display: inline-block; +} + +.hdy-shell-tabs { + display: inline-block; +} + .hdy-command-groups { - height: calc(100% - 37px); + height: calc(100% - 41px); margin-left: 5px; overflow: auto; } @@ -44,14 +61,6 @@ div:focus { border-color: transparent; } -.hdy-shell-icon-off { - background: url(../images/hdy.brackets.shell.toolbar.png); -} - -.hdy-shell-icon-on { - background: url(../images/hdy.brackets.shell.toolbar.on.png); -} - .hdy-dark-theme { color:#AAAAAA; } diff --git a/styles/variables.less b/styles/variables.less new file mode 100644 index 0000000..1b69ed9 --- /dev/null +++ b/styles/variables.less @@ -0,0 +1,9 @@ +@red: rgb(170, 000, 000); +@yellow: rgb(170, 170, 000); +@black: rgb(000, 000, 000); +@green: rgb(000, 170, 000); +@blue: rgb(000, 000, 170); +@magenta: rgb(170, 000, 170); +@cyan: rgb(000, 170, 128); +@white: rgb(255, 255, 255); +@gray: rgb(170, 170, 170); diff --git a/templates/commandTemplate.html b/templates/commandTemplate.html index 3c9412b..bdfbe0b 100644 --- a/templates/commandTemplate.html +++ b/templates/commandTemplate.html @@ -1,5 +1,4 @@ -
+
 
-
diff --git a/templates/panel.html b/templates/panel.html new file mode 100644 index 0000000..0ec312f --- /dev/null +++ b/templates/panel.html @@ -0,0 +1,7 @@ +
+
+
{{title}}
+ × +
+
+
diff --git a/templates/shellPanel.html b/templates/shellPanel.html deleted file mode 100644 index 61c3c20..0000000 --- a/templates/shellPanel.html +++ /dev/null @@ -1,20 +0,0 @@ -
-
- -
-
- -
-
-
- -
-
- × -
-
-
-
diff --git a/templates/tabs.html b/templates/tabs.html new file mode 100644 index 0000000..77783dc --- /dev/null +++ b/templates/tabs.html @@ -0,0 +1,20 @@ + diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..30245ff --- /dev/null +++ b/tests/index.html @@ -0,0 +1,23 @@ + + + + + hdy Brackets Shell Tests + + + + + +
+
+ + + + + + + + + + + diff --git a/tests/shell/shell.tests.js b/tests/shell/shell.tests.js new file mode 100644 index 0000000..44a205c --- /dev/null +++ b/tests/shell/shell.tests.js @@ -0,0 +1,17 @@ +/* global describe, it, require */ + +//define(['../shell'], function (Shell) { + describe('Shell', function(){ + describe('#Constructor', function(){ + it('should create Shell object which is not undefined or null', function(){ + + var s = require(""); + var shell = new Shell(); + + shell.should.not.equal(undefined); + shell.should.not.equal(null); + + }); + }); + }); +//}); diff --git a/vendor/jquery.droptabs.js b/vendor/jquery.droptabs.js new file mode 100644 index 0000000..ca51ac3 --- /dev/null +++ b/vendor/jquery.droptabs.js @@ -0,0 +1,160 @@ +/* Copyright (c) 2014 Alexandru Boboc + * Droptabs v.1.1 Jquery Plugin + * Tested with JQuery 1.11.1 + */ + +(function($) { + + $.fn.droptabs = function(o) { + + //Default options + var s = $.extend({ + dropdownSelector : "li.dropdown", + dropdownMenuSelector : "ul.dropdown-menu", + dropdownTabsSelector : "li", + visibleTabsSelector : ">li:not(.dropdown)", + developmentId : "dt-devInfo", + autoArrangeTabs : true, + development : false + }, o); + + return this.each( function( ) { + + var $container = $(this); + var dropdown = $(s.dropdownSelector, this); + var dropdownMenu = $(s.dropdownMenuSelector, dropdown); + + var $dropdownTabs = function () { + return $(s.dropdownTabsSelector, dropdownMenu); + } + + var $visibleTabs = function () { + return $(s.visibleTabsSelector, $container); + } + + function getFirstHiddenElementWidth() { + var tempElem=$dropdownTabs().first().clone().appendTo($container).css("position","fixed"); + var hiddenElementWidth = $(tempElem).outerWidth(); + $(tempElem).remove(); + return hiddenElementWidth; + } + + function getHiddenElementWidth(elem) { + var tempElem=$(elem).clone().appendTo($container).css("position","fixed"); + var hiddenElementWidth = $(tempElem).outerWidth(); + $(tempElem).remove(); + return hiddenElementWidth; + } + + function manageActive(elem) { + //fixes a bug where Bootstrap can't remove the 'active' class on elements after they've been hidden inside the dropdown + $('a', $(elem)).on('show.bs.tab', function (e) { + $(e.relatedTarget).parent().removeClass('active'); + }) + $('a', $(elem)).on('shown.bs.tab', function (e) { + if ($(dropdown).hasClass('active')) { + $('>a', dropdown).html(($('>li.active>a', dropdownMenu).html()).substring(0,10) + '... '); + } else { + $('>a', dropdown).html('Dropdown '); + } + }) + + } + + //Start Development info + if ( s.development ) { + $('body').append('
'); + var $developmentDiv = $('#' + s.developmentId); + $($developmentDiv).css('position','fixed').css('right','20px').css('bottom','20px'); + function devPrint(label, elem) { + var labelId = label.replace(/\s+/g, '-').toLowerCase(); + if ($('#'+labelId).length > 0) { + $('#'+labelId).text(label + ': ' + elem); + } else { + $('#dt-devInfo').append('
' + label + ': ' + elem + '
'); + } + return true; + } + } + //End Development info + + var visibleTabsWidth = function () { + var visibleTabsWidth = 0; + $($visibleTabs()).each(function( index ) { + visibleTabsWidth += parseInt($(this).outerWidth(), 10); + }); + visibleTabsWidth = visibleTabsWidth + parseInt($(dropdown).outerWidth(), 10); + return visibleTabsWidth; + } + + var availableSpace = function () { + return $container.outerWidth()-visibleTabsWidth(); + } + + var arrangeTabs = function () { + //Start Development info + if ( s.development ) { + devPrint("Container width", $container.outerWidth()); + devPrint("Visible tabs width", visibleTabsWidth()); + devPrint("Available space", availableSpace()); + devPrint("First hidden", getFirstHiddenElementWidth()); + } + //End Development info + + if (availableSpace()<0) {//we will hide tabs here + var x = availableSpace(); + $($visibleTabs().get().reverse()).each(function( index ){ + if (!($(this).hasClass('always-visible'))){ + $(this).prependTo(dropdownMenu); + x=x+$(this).outerWidth(); + } + if (x>=0) {return false;} + }); + } + + if (availableSpace()>getFirstHiddenElementWidth()) { //and here we bring the tabs out + var x = availableSpace(); + $($dropdownTabs()).each(function( index ){ + if (getHiddenElementWidth(this) < x && !($(this).hasClass('always-dropdown'))){ + $(this).appendTo($container); + x = x-$(this).outerWidth(); + } else {return false;} + }); + } + + if ($dropdownTabs().length <= 0) {dropdown.hide();} else {dropdown.show();} + } + + //init + + if (s.autoArrangeTabs) { + var tempTabs = []; + $($visibleTabs().get().reverse()).each(function( index ){ + if ($(this).hasClass('always-visible')) { + tempTabs.push($(this)); + $(this).remove(); + } + }); + for (var i = 0; i < tempTabs.length; i++ ) { + $container.prepend(tempTabs[i]); + } + } + + $(document).ready(function(){ + arrangeTabs(); + $dropdownTabs().each( function() { + manageActive($(this)); + }); + + $visibleTabs().each( function() { + manageActive($(this)); + }); + }); + + $( window ).resize(function() { + arrangeTabs(); + }); + return this; + }); + } +}(jQuery)); diff --git a/online.js b/vendor/online.js similarity index 100% rename from online.js rename to vendor/online.js diff --git a/shellPanel.js b/views/shellPanelView.js similarity index 79% rename from shellPanel.js rename to views/shellPanelView.js index a76d388..edf73ec 100644 --- a/shellPanel.js +++ b/views/shellPanelView.js @@ -6,27 +6,53 @@ define(function (require, exports, module) { "use strict"; var WorkspaceManager = brackets.getModule("view/WorkspaceManager"), + Shell = require("shell"), AppInit = brackets.getModule("utils/AppInit"), KeyEvent = brackets.getModule("utils/KeyEvent"), _shellPanelHtml = require("text!templates/shellPanel.html"), $commandTemplateHtml = $(require("text!templates/commandTemplate.html")), - ShellPanel = WorkspaceManager.createBottomPanel("hdy.brackets.shell.panel", + ShellPanelBottom = WorkspaceManager.createBottomPanel("hdy.brackets.shell.panel", $(_shellPanelHtml), 100), ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), NodeDomain = brackets.getModule("utils/NodeDomain"), ShellDomain = new NodeDomain("hdyShellDomain", ExtensionUtils.getModulePath(module, - "node/hdyShellDomain")), + "../node/shellDomain")), CommandRoll = [], CommandRollIndex = -1, KillProcess = $('.hdy-brackets-shell-kill'), - ansiFormat = require("shellAnsiFormat"), _preferencesManager = brackets.getModule("preferences/PreferencesManager"), _preferences = _preferencesManager.getExtensionPrefs("hdy.brackets-shell"), PROMPT_TERMINATOR = ">"; + function ShellPanelView(title, cwd) { + + this.watch('title', function(prop, oldValue, newValue) { + + return newValue; + }); + + this.watch('cwd', function(prop, oldValue, newValue) { + _addShellLine(newValue); + + return newValue; + }); + + this.shell = new Shell(); + + this.shell.kill(); + + this.title = title; + this.cwd = cwd; + } + + ShellPanelView.prototype.toggle = _toggle; + ShellPanelView.prototype.show = _show; + ShellPanelView.prototype.hide = _hide; + ShellPanelView.prototype.isVisible = _isVisible; + function _toggle() { - if (ShellPanel.isVisible()) { + if (ShellPanelBottom.isVisible()) { _hide(); } else { @@ -35,7 +61,7 @@ define(function (require, exports, module) { } function _show() { - ShellPanel.show(); + ShellPanelBottom.show(); $("a.hdy-shell-icon").removeClass("hdy-shell-icon-off"); $("a.hdy-shell-icon").addClass("hdy-shell-icon-on"); _focus(); @@ -44,11 +70,11 @@ define(function (require, exports, module) { function _hide() { $("a.hdy-shell-icon").removeClass("hdy-shell-icon-on"); $("a.hdy-shell-icon").addClass("hdy-shell-icon-off"); - ShellPanel.hide(); + ShellPanelBottom.hide(); } function _isVisible() { - return ShellPanel.isVisible(); + return ShellPanelBottom.isVisible(); } function _executeCommand(e) { @@ -148,7 +174,6 @@ define(function (require, exports, module) { _clearOutput(); }); - function _clearOutput() { var commandGroups = $(".hdy-command-groups"), @@ -180,16 +205,16 @@ define(function (require, exports, module) { $("pre", currentCommandResult).addClass('hdy-dark-theme'); } - if(ansiFormat.hasAceptedAnsiFormat(data)){ - ansiFormat.formattedText(data, currentCommandResult); - } else { - for (var i = 0; i < data.length; i++) { - if (data.charCodeAt(i) === 65533) { - data = replaceCharAtIndex(data, i, "."); - } - } +// if(ansiFormat.hasAceptedAnsiFormat(data)){ +// ansiFormat.formattedText(data, currentCommandResult); +// } else { +// for (var i = 0; i < data.length; i++) { +// if (data.charCodeAt(i) === 65533) { +// data = replaceCharAtIndex(data, i, "."); +// } +// } $("pre", currentCommandResult).append(document.createTextNode(data)); - } +// } _scrollToBottom(); } @@ -205,10 +230,10 @@ define(function (require, exports, module) { currentCommandGroup.removeClass("hdy-current"); } - var element = $(".scrollPoint", currentCommandGroup); - if (element.length) { - currentCommandGroup[0].removeChild(element[0]); - } +// var element = $(".hdy-command-result:nth-last-of-type(1)", currentCommandGroup); +// if (element.length) { +// currentCommandGroup[0].removeChild(element[0]); +// } newCommand.attr("data-cwd", cwd + PROMPT_TERMINATOR); commandGroups.append(newCommandGroup); @@ -226,22 +251,20 @@ define(function (require, exports, module) { function _focus() { var commandInput = $(".hdy-current .hdy-command")[0]; - var scrollPoint = $(".scrollPoint")[0]; - if (scrollPoint) { - scrollPoint.scrollIntoView(false); - commandInput.focus(); - } + commandInput.focus(); + commandInput.scrollIntoView(false); + } - // Initialize the shellPanel + // Initialize the ShellPanelBottom AppInit.appReady(function () { KillProcess.click(function() { ShellDomain.exec("kill"); }); KillProcess.attr('disabled', 'disabled'); - $(".close", ShellPanel.$panel).click(_toggle); + $(".close", ShellPanelBottom.$panel).click(_toggle); // $(".hdy-command-groups .hdy-current .hdy-command") // .attr("data-cwd", cwd); @@ -278,9 +301,11 @@ define(function (require, exports, module) { _addShellLine(cwd); } - exports.toggle = _toggle; - exports.hide = _hide; - exports.show = _show; - exports.isVisible = _isVisible; - exports.setDirectory = _setDirectory; + module.exports = ShellPanelView; + +// exports.toggle = _toggle; +// exports.hide = _hide; +// exports.show = _show; +// exports.isVisible = _isVisible; +// exports.setDirectory = _setDirectory; });