From a9ffb88d46c7dce2de6498e891bceed43ebb0b7b Mon Sep 17 00:00:00 2001 From: johnhidey Date: Mon, 15 Dec 2014 17:24:21 -0500 Subject: [PATCH 1/9] Created shell.js which is the new Shell used strictly for executing commands relaying the result data. Also created a Tab, Tabs and modified the ShellDomain object. --- Gruntfile.js | 7 + main.js | 6 +- node/node_modules/ansi-webkit/LICENSE | 9 ++ node/node_modules/ansi-webkit/README.md | 53 +++++++ .../ansi-webkit/example/index.html | 9 ++ .../ansi-webkit/example/package.json | 17 +++ .../ansi-webkit/example/script.js | 21 +++ .../node_modules/ansi-webkit/example/spawn.js | 49 +++++++ node/node_modules/ansi-webkit/lib/ansi.json | 27 ++++ node/node_modules/ansi-webkit/lib/index.js | 77 ++++++++++ node/node_modules/ansi-webkit/lib/themes.json | 30 ++++ node/node_modules/ansi-webkit/package.json | 39 ++++++ node/node_modules/ansi-webkit/test/index.js | 127 +++++++++++++++++ node/node_modules/ansi-webkit/test/mocha.opts | 2 + node/{hdyShellDomain.js => shellDomain.js} | 20 ++- package.json | 4 +- shell.js | 103 ++++++++++++++ styles/shellPanel.css | 31 +++- tab.js | 31 ++++ tabs.js | 37 +++++ templates/commandTemplate.html | 3 +- templates/shellPanel.html | 10 +- tests/index.html | 23 +++ tests/shell/shell.tests.js | 17 +++ shellPanel.js => viewModels/shellPanelView.js | 132 ++++++++++++++---- 25 files changed, 834 insertions(+), 50 deletions(-) create mode 100644 node/node_modules/ansi-webkit/LICENSE create mode 100644 node/node_modules/ansi-webkit/README.md create mode 100644 node/node_modules/ansi-webkit/example/index.html create mode 100644 node/node_modules/ansi-webkit/example/package.json create mode 100644 node/node_modules/ansi-webkit/example/script.js create mode 100644 node/node_modules/ansi-webkit/example/spawn.js create mode 100644 node/node_modules/ansi-webkit/lib/ansi.json create mode 100644 node/node_modules/ansi-webkit/lib/index.js create mode 100644 node/node_modules/ansi-webkit/lib/themes.json create mode 100644 node/node_modules/ansi-webkit/package.json create mode 100644 node/node_modules/ansi-webkit/test/index.js create mode 100644 node/node_modules/ansi-webkit/test/mocha.opts rename node/{hdyShellDomain.js => shellDomain.js} (91%) create mode 100644 shell.js create mode 100644 tab.js create mode 100644 tabs.js create mode 100644 tests/index.html create mode 100644 tests/shell/shell.tests.js rename shellPanel.js => viewModels/shellPanelView.js (66%) diff --git a/Gruntfile.js b/Gruntfile.js index 78ce161..21ea1ed 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -37,6 +37,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/main.js b/main.js index 552e169..72928cb 100644 --- a/main.js +++ b/main.js @@ -32,18 +32,18 @@ define(function (require, exports, module) { AppInit.appReady(function () { var projectWatcher = require("projectWatcher"), - commandShell = require("shellPanel"); + ShellPanelView = require("viewModels/shellPanelView"), + commandShell = new ShellPanelView("My Title", projectWatcher.cleanPath(ProjectManager.getProjectRoot().fullPath)); ExtensionUtils.loadStyleSheet(module, "styles/shellPanel.css"); $icon.on("click", commandShell.toggle); commandShell.hide(); - commandShell.setDirectory(projectWatcher.cleanPath(ProjectManager.getProjectRoot().fullPath)); if (Preferences.get("trackProject")) { projectWatcher.register(function(cwd) { if (cwd) { - commandShell.setDirectory(cwd); + commandShell.cwd = cwd; } }); } 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 91% rename from node/hdyShellDomain.js rename to node/shellDomain.js index ce2c727..d405e81 100644 --- a/node/hdyShellDomain.js +++ b/node/shellDomain.js @@ -7,20 +7,14 @@ child, kill = require("tree-kill"); - /** - * @private - * Handler function for the simple.getMemory command. - * @param {boolean} total If true, return total memory; - if false, return free memory only. - * @return {number} The amount of memory. - */ function _execute(cmd, cwd, isWin) { var spawn = require("child_process").spawn, splitarps = require("splitargs"), args, enddir = cwd, - tempdir; + tempdir, + env = process.env; cmd = cmd.trim(); @@ -59,14 +53,18 @@ args.unshift("-c"); } - child = spawn(cmd, args, { cwd: cwd, env: process.env }); + child = spawn(cmd, args, { cwd: cwd, env: env }); child.stdout.on("data", function (data) { - _domainManager.emitEvent("hdyShellDomain", "stdout", [data.toString()]); + var parsedOutput = data.toString().trim(); + + _domainManager.emitEvent("hdyShellDomain", "stdout", [parsedOutput]); }); child.stderr.on("data", function (data) { - _domainManager.emitEvent("hdyShellDomain", "stderr", [data.toString()]); + var parsedOutput = data.toString().trim(); + + _domainManager.emitEvent("hdyShellDomain", "stderr", [parsedOutput]); }); child.on("close", function () { diff --git a/package.json b/package.json index b1a4abf..f92bd9b 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,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": { "splitargs": "^0.0.3", diff --git a/shell.js b/shell.js new file mode 100644 index 0000000..7c1c0ba --- /dev/null +++ b/shell.js @@ -0,0 +1,103 @@ +/*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(cwd, cmd, isWindows) { + + ShellDomain.exec("execute", cmd, cwd, isWindows); + + } + + 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.onStdErr = _onStdErr; + Shell.prototype.onClose = _onClose; + Shell.prototype.onClear = _onClear; + + module.exports = Shell; + +}); diff --git a/styles/shellPanel.css b/styles/shellPanel.css index d24f8a7..f5fd86b 100644 --- a/styles/shellPanel.css +++ b/styles/shellPanel.css @@ -2,8 +2,37 @@ 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-title { + padding-top: -10px; + margin-right: 20px; + display: inline-block; +} + +/* +.hdy-brackets-shell-logo { + background: + url(data:image/png;base64,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) + no-repeat left center; + + width: 27px; + height: 27px; +} +*/ + +.hdy-shell-tabs { + display: inline-block; +} + .hdy-command-groups { - height: calc(100% - 37px); + height: calc(100% - 41px); overflow: auto; } diff --git a/tab.js b/tab.js new file mode 100644 index 0000000..b452200 --- /dev/null +++ b/tab.js @@ -0,0 +1,31 @@ +/*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 self; + + function _rename(name) { + + self.name = name; + + } + + function _initialize() { } + + var Tab = function(name) { + + self = this; + self.name = name; + + _initialize(); + + }; + + Tab.prototype.rename = _rename; + + module.exports = Tab; + +}); diff --git a/tabs.js b/tabs.js new file mode 100644 index 0000000..e040e97 --- /dev/null +++ b/tabs.js @@ -0,0 +1,37 @@ +/*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 self; + + function _add(name) { + + self.name = name; + + } + + function _remove(name) { + + self.name = name; + + } + + function _initialize() { } + + var Tabs = function() { + + self = this; + + _initialize(); + + }; + + Tabs.prototype.add = _add; + Tabs.prototype.remove = _remove; + + module.exports = Tabs; + +}); 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/shellPanel.html b/templates/shellPanel.html index 61c3c20..bff543f 100644 --- a/templates/shellPanel.html +++ b/templates/shellPanel.html @@ -2,10 +2,14 @@
-
- +
+
Brackets Shell
+
-
+
-
-
- × -
+
{{title}}
+ ×
diff --git a/templates/tabs.html b/templates/tabs.html new file mode 100644 index 0000000..573defb --- /dev/null +++ b/templates/tabs.html @@ -0,0 +1,11 @@ +
+
+ +
+
+
+
+
+
diff --git a/vendor/ractive.js b/vendor/ractive.js new file mode 100644 index 0000000..b4f8789 --- /dev/null +++ b/vendor/ractive.js @@ -0,0 +1,14347 @@ +/* + ractive.js v0.6.1 + 2014-10-25 - commit 3a576eb3 + + http://ractivejs.org + http://twitter.com/RactiveJS + + Released under the MIT License. +*/ + +( function( global ) { + + 'use strict'; + + var noConflict = global.Ractive; + + /* config/defaults/options.js */ + var options = function() { + + var defaultOptions = { + // render placement: + el: void 0, + append: false, + // template: + template: { + v: 1, + t: [] + }, + yield: null, + // parse: + preserveWhitespace: false, + sanitize: false, + stripComments: true, + // data & binding: + data: {}, + computed: {}, + magic: false, + modifyArrays: true, + adapt: [], + isolated: false, + twoway: true, + lazy: false, + // transitions: + noIntro: false, + transitionsEnabled: true, + complete: void 0, + // css: + noCssTransform: false, + // debug: + debug: false + }; + return defaultOptions; + }(); + + /* config/defaults/easing.js */ + var easing = { + linear: function( pos ) { + return pos; + }, + easeIn: function( pos ) { + return Math.pow( pos, 3 ); + }, + easeOut: function( pos ) { + return Math.pow( pos - 1, 3 ) + 1; + }, + easeInOut: function( pos ) { + if ( ( pos /= 0.5 ) < 1 ) { + return 0.5 * Math.pow( pos, 3 ); + } + return 0.5 * ( Math.pow( pos - 2, 3 ) + 2 ); + } + }; + + /* circular.js */ + var circular = []; + + /* utils/hasOwnProperty.js */ + var hasOwn = Object.prototype.hasOwnProperty; + + /* utils/isArray.js */ + var isArray = function() { + + var toString = Object.prototype.toString; + // thanks, http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ + return function( thing ) { + return toString.call( thing ) === '[object Array]'; + }; + }(); + + /* utils/isObject.js */ + var isObject = function() { + + var toString = Object.prototype.toString; + return function( thing ) { + return thing && toString.call( thing ) === '[object Object]'; + }; + }(); + + /* utils/isNumeric.js */ + var isNumeric = function( thing ) { + return !isNaN( parseFloat( thing ) ) && isFinite( thing ); + }; + + /* config/defaults/interpolators.js */ + var interpolators = function( circular, hasOwnProperty, isArray, isObject, isNumeric ) { + + var interpolators, interpolate, cssLengthPattern; + circular.push( function() { + interpolate = circular.interpolate; + } ); + cssLengthPattern = /^([+-]?[0-9]+\.?(?:[0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/; + interpolators = { + number: function( from, to ) { + var delta; + if ( !isNumeric( from ) || !isNumeric( to ) ) { + return null; + } + from = +from; + to = +to; + delta = to - from; + if ( !delta ) { + return function() { + return from; + }; + } + return function( t ) { + return from + t * delta; + }; + }, + array: function( from, to ) { + var intermediate, interpolators, len, i; + if ( !isArray( from ) || !isArray( to ) ) { + return null; + } + intermediate = []; + interpolators = []; + i = len = Math.min( from.length, to.length ); + while ( i-- ) { + interpolators[ i ] = interpolate( from[ i ], to[ i ] ); + } + // surplus values - don't interpolate, but don't exclude them either + for ( i = len; i < from.length; i += 1 ) { + intermediate[ i ] = from[ i ]; + } + for ( i = len; i < to.length; i += 1 ) { + intermediate[ i ] = to[ i ]; + } + return function( t ) { + var i = len; + while ( i-- ) { + intermediate[ i ] = interpolators[ i ]( t ); + } + return intermediate; + }; + }, + object: function( from, to ) { + var properties, len, interpolators, intermediate, prop; + if ( !isObject( from ) || !isObject( to ) ) { + return null; + } + properties = []; + intermediate = {}; + interpolators = {}; + for ( prop in from ) { + if ( hasOwnProperty.call( from, prop ) ) { + if ( hasOwnProperty.call( to, prop ) ) { + properties.push( prop ); + interpolators[ prop ] = interpolate( from[ prop ], to[ prop ] ); + } else { + intermediate[ prop ] = from[ prop ]; + } + } + } + for ( prop in to ) { + if ( hasOwnProperty.call( to, prop ) && !hasOwnProperty.call( from, prop ) ) { + intermediate[ prop ] = to[ prop ]; + } + } + len = properties.length; + return function( t ) { + var i = len, + prop; + while ( i-- ) { + prop = properties[ i ]; + intermediate[ prop ] = interpolators[ prop ]( t ); + } + return intermediate; + }; + } + }; + return interpolators; + }( circular, hasOwn, isArray, isObject, isNumeric ); + + /* config/svg.js */ + var svg = function() { + + var svg; + if ( typeof document === 'undefined' ) { + svg = false; + } else { + svg = document && document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1' ); + } + return svg; + }(); + + /* utils/warn.js */ + var warn = function() { + + /* global console */ + var warn, warned = {}; + if ( typeof console !== 'undefined' && typeof console.warn === 'function' && typeof console.warn.apply === 'function' ) { + warn = function( message, allowDuplicates ) { + if ( !allowDuplicates ) { + if ( warned[ message ] ) { + return; + } + warned[ message ] = true; + } + console.warn( '%cRactive.js: %c' + message, 'color: rgb(114, 157, 52);', 'color: rgb(85, 85, 85);' ); + }; + } else { + warn = function() {}; + } + return warn; + }(); + + /* config/errors.js */ + var errors = { + missingParser: 'Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser', + mergeComparisonFail: 'Merge operation: comparison failed. Falling back to identity checking', + noComponentEventArguments: 'Components currently only support simple events - you cannot include arguments. Sorry!', + noTemplateForPartial: 'Could not find template for partial "{name}"', + noNestedPartials: 'Partials ({{>{name}}}) cannot contain nested inline partials', + evaluationError: 'Error evaluating "{uniqueString}": {err}', + badArguments: 'Bad arguments "{arguments}". I\'m not allowed to argue unless you\'ve paid.', + failedComputation: 'Failed to compute "{key}": {err}', + missingPlugin: 'Missing "{name}" {plugin} plugin. You may need to download a {plugin} via http://docs.ractivejs.org/latest/plugins#{plugin}s', + badRadioInputBinding: 'A radio input can have two-way binding on its name attribute, or its checked attribute - not both', + noRegistryFunctionReturn: 'A function was specified for "{name}" {registry}, but no {registry} was returned', + defaultElSpecified: 'The <{name}/> component has a default `el` property; it has been disregarded', + noElementProxyEventWildcards: 'Only component proxy-events may contain "*" wildcards, <{element} on-{event}/> is not valid.', + methodDeprecated: 'The method "{deprecated}" has been deprecated in favor of "{replacement}" and will likely be removed in a future release. See http://docs.ractivejs.org/latest/migrating for more information.' + }; + + /* utils/log.js */ + var log = function( consolewarn, errors ) { + + var log = { + warn: function( options, passthru ) { + if ( !options.debug && !passthru ) { + return; + } + this.warnAlways( options ); + }, + warnAlways: function( options ) { + this.logger( getMessage( options ), options.allowDuplicates ); + }, + error: function( options ) { + this.errorOnly( options ); + if ( !options.debug ) { + this.warn( options, true ); + } + }, + errorOnly: function( options ) { + if ( options.debug ) { + this.critical( options ); + } + }, + critical: function( options ) { + var err = options.err || new Error( getMessage( options ) ); + this.thrower( err ); + }, + logger: consolewarn, + thrower: function( err ) { + throw err; + } + }; + + function getMessage( options ) { + var message = errors[ options.message ] || options.message || ''; + return interpolate( message, options.args ); + } + // simple interpolation. probably quicker (and better) out there, + // but log is not in golden path of execution, only exceptions + function interpolate( message, args ) { + return message.replace( /{([^{}]*)}/g, function( a, b ) { + return args[ b ]; + } ); + } + return log; + }( warn, errors ); + + /* Ractive/prototype/shared/hooks/Hook.js */ + var Ractive$shared_hooks_Hook = function( log ) { + + var deprecations = { + construct: { + deprecated: 'beforeInit', + replacement: 'onconstruct' + }, + render: { + deprecated: 'init', + message: 'The "init" method has been deprecated ' + 'and will likely be removed in a future release. ' + 'You can either use the "oninit" method which will fire ' + 'only once prior to, and regardless of, any eventual ractive ' + 'instance being rendered, or if you need to access the ' + 'rendered DOM, use "onrender" instead. ' + 'See http://docs.ractivejs.org/latest/migrating for more information.' + }, + complete: { + deprecated: 'complete', + replacement: 'oncomplete' + } + }; + + function Hook( event ) { + this.event = event; + this.method = 'on' + event; + this.deprecate = deprecations[ event ]; + } + Hook.prototype.fire = function( ractive, arg ) { + function call( method ) { + if ( ractive[ method ] ) { + arg ? ractive[ method ]( arg ) : ractive[ method ](); + return true; + } + } + call( this.method ); + if ( !ractive[ this.method ] && this.deprecate && call( this.deprecate.deprecated ) ) { + log.warnAlways( { + debug: ractive.debug, + message: this.deprecate.message || 'methodDeprecated', + args: this.deprecate + } ); + } + arg ? ractive.fire( this.event, arg ) : ractive.fire( this.event ); + }; + return Hook; + }( log ); + + /* utils/removeFromArray.js */ + var removeFromArray = function( array, member ) { + var index = array.indexOf( member ); + if ( index !== -1 ) { + array.splice( index, 1 ); + } + }; + + /* utils/Promise.js */ + var Promise = function() { + + var __export; + var _Promise, PENDING = {}, + FULFILLED = {}, + REJECTED = {}; + if ( typeof Promise === 'function' ) { + // use native Promise + _Promise = Promise; + } else { + _Promise = function( callback ) { + var fulfilledHandlers = [], + rejectedHandlers = [], + state = PENDING, + result, dispatchHandlers, makeResolver, fulfil, reject, promise; + makeResolver = function( newState ) { + return function( value ) { + if ( state !== PENDING ) { + return; + } + result = value; + state = newState; + dispatchHandlers = makeDispatcher( state === FULFILLED ? fulfilledHandlers : rejectedHandlers, result ); + // dispatch onFulfilled and onRejected handlers asynchronously + wait( dispatchHandlers ); + }; + }; + fulfil = makeResolver( FULFILLED ); + reject = makeResolver( REJECTED ); + try { + callback( fulfil, reject ); + } catch ( err ) { + reject( err ); + } + promise = { + // `then()` returns a Promise - 2.2.7 + then: function( onFulfilled, onRejected ) { + var promise2 = new _Promise( function( fulfil, reject ) { + var processResolutionHandler = function( handler, handlers, forward ) { + // 2.2.1.1 + if ( typeof handler === 'function' ) { + handlers.push( function( p1result ) { + var x; + try { + x = handler( p1result ); + resolve( promise2, x, fulfil, reject ); + } catch ( err ) { + reject( err ); + } + } ); + } else { + // Forward the result of promise1 to promise2, if resolution handlers + // are not given + handlers.push( forward ); + } + }; + // 2.2 + processResolutionHandler( onFulfilled, fulfilledHandlers, fulfil ); + processResolutionHandler( onRejected, rejectedHandlers, reject ); + if ( state !== PENDING ) { + // If the promise has resolved already, dispatch the appropriate handlers asynchronously + wait( dispatchHandlers ); + } + } ); + return promise2; + } + }; + promise[ 'catch' ] = function( onRejected ) { + return this.then( null, onRejected ); + }; + return promise; + }; + _Promise.all = function( promises ) { + return new _Promise( function( fulfil, reject ) { + var result = [], + pending, i, processPromise; + if ( !promises.length ) { + fulfil( result ); + return; + } + processPromise = function( i ) { + promises[ i ].then( function( value ) { + result[ i ] = value; + if ( !--pending ) { + fulfil( result ); + } + }, reject ); + }; + pending = i = promises.length; + while ( i-- ) { + processPromise( i ); + } + } ); + }; + _Promise.resolve = function( value ) { + return new _Promise( function( fulfil ) { + fulfil( value ); + } ); + }; + _Promise.reject = function( reason ) { + return new _Promise( function( fulfil, reject ) { + reject( reason ); + } ); + }; + } + __export = _Promise; + // TODO use MutationObservers or something to simulate setImmediate + function wait( callback ) { + setTimeout( callback, 0 ); + } + + function makeDispatcher( handlers, result ) { + return function() { + var handler; + while ( handler = handlers.shift() ) { + handler( result ); + } + }; + } + + function resolve( promise, x, fulfil, reject ) { + // Promise Resolution Procedure + var then; + // 2.3.1 + if ( x === promise ) { + throw new TypeError( 'A promise\'s fulfillment handler cannot return the same promise' ); + } + // 2.3.2 + if ( x instanceof _Promise ) { + x.then( fulfil, reject ); + } else if ( x && ( typeof x === 'object' || typeof x === 'function' ) ) { + try { + then = x.then; + } catch ( e ) { + reject( e ); + // 2.3.3.2 + return; + } + // 2.3.3.3 + if ( typeof then === 'function' ) { + var called, resolvePromise, rejectPromise; + resolvePromise = function( y ) { + if ( called ) { + return; + } + called = true; + resolve( promise, y, fulfil, reject ); + }; + rejectPromise = function( r ) { + if ( called ) { + return; + } + called = true; + reject( r ); + }; + try { + then.call( x, resolvePromise, rejectPromise ); + } catch ( e ) { + if ( !called ) { + // 2.3.3.3.4.1 + reject( e ); + // 2.3.3.3.4.2 + called = true; + return; + } + } + } else { + fulfil( x ); + } + } else { + fulfil( x ); + } + } + return __export; + }(); + + /* utils/normaliseRef.js */ + var normaliseRef = function() { + + var regex = /\[\s*(\*|[0-9]|[1-9][0-9]+)\s*\]/g; + return function normaliseRef( ref ) { + return ( ref || '' ).replace( regex, '.$1' ); + }; + }(); + + /* shared/getInnerContext.js */ + var getInnerContext = function( fragment ) { + do { + if ( fragment.context !== undefined ) { + return fragment.context; + } + } while ( fragment = fragment.parent ); + return ''; + }; + + /* utils/isEqual.js */ + var isEqual = function( a, b ) { + if ( a === null && b === null ) { + return true; + } + if ( typeof a === 'object' || typeof b === 'object' ) { + return false; + } + return a === b; + }; + + /* shared/createComponentBinding.js */ + var createComponentBinding = function( circular, isEqual ) { + + var runloop; + circular.push( function() { + return runloop = circular.runloop; + } ); + var Binding = function( ractive, keypath, otherInstance, otherKeypath ) { + var this$0 = this; + this.root = ractive; + this.keypath = keypath; + this.otherInstance = otherInstance; + this.otherKeypath = otherKeypath; + this.lock = function() { + return this$0.updating = true; + }; + this.unlock = function() { + return this$0.updating = false; + }; + this.bind(); + this.value = this.root.viewmodel.get( this.keypath ); + }; + Binding.prototype = { + isLocked: function() { + return this.updating || this.counterpart && this.counterpart.updating; + }, + shuffle: function( newIndices, value ) { + this.propagateChange( value, newIndices ); + }, + setValue: function( value ) { + this.propagateChange( value ); + }, + propagateChange: function( value, newIndices ) { + var other; + // Only *you* can prevent infinite loops + if ( this.isLocked() ) { + this.value = value; + return; + } + if ( !isEqual( value, this.value ) ) { + this.lock(); + // TODO maybe the case that `value === this.value` - should that result + // in an update rather than a set? + // if the other viewmodel is already locked up, need to do a deferred update + if ( !runloop.addViewmodel( other = this.otherInstance.viewmodel ) && this.counterpart.value !== value ) { + runloop.scheduleTask( function() { + return runloop.addViewmodel( other ); + } ); + } + if ( newIndices ) { + other.smartUpdate( this.otherKeypath, value, newIndices ); + } else { + if ( isSettable( other, this.otherKeypath ) ) { + other.set( this.otherKeypath, value ); + } + } + this.value = value; + // TODO will the counterpart update after this line, during + // the runloop end cycle? may be a problem... + runloop.scheduleTask( this.unlock ); + } + }, + refineValue: function( keypaths ) { + var this$0 = this; + var other; + if ( this.isLocked() ) { + return; + } + this.lock(); + runloop.addViewmodel( other = this.otherInstance.viewmodel ); + keypaths.map( function( keypath ) { + return this$0.otherKeypath + keypath.substr( this$0.keypath.length ); + } ).forEach( function( keypath ) { + return other.mark( keypath ); + } ); + runloop.scheduleTask( this.unlock ); + }, + bind: function() { + this.root.viewmodel.register( this.keypath, this ); + }, + rebind: function( newKeypath ) { + this.unbind(); + this.keypath = newKeypath; + this.counterpart.otherKeypath = newKeypath; + this.bind(); + }, + unbind: function() { + this.root.viewmodel.unregister( this.keypath, this ); + } + }; + + function isSettable( viewmodel, keypath ) { + var computed = viewmodel.computations[ keypath ]; + return !computed || computed.setter; + } + return function createComponentBinding( component, parentInstance, parentKeypath, childKeypath ) { + var hash, childInstance, bindings, parentToChildBinding, childToParentBinding; + hash = parentKeypath + '=' + childKeypath; + bindings = component.bindings; + if ( bindings[ hash ] ) { + // TODO does this ever happen? + return; + } + childInstance = component.instance; + parentToChildBinding = new Binding( parentInstance, parentKeypath, childInstance, childKeypath ); + bindings.push( parentToChildBinding ); + if ( childInstance.twoway ) { + childToParentBinding = new Binding( childInstance, childKeypath, parentInstance, parentKeypath ); + bindings.push( childToParentBinding ); + parentToChildBinding.counterpart = childToParentBinding; + childToParentBinding.counterpart = parentToChildBinding; + } + bindings[ hash ] = parentToChildBinding; + }; + }( circular, isEqual ); + + /* shared/resolveRef.js */ + var resolveRef = function( normaliseRef, getInnerContext, createComponentBinding ) { + + var __export; + var ancestorErrorMessage, getOptions; + ancestorErrorMessage = 'Could not resolve reference - too many "../" prefixes'; + getOptions = { + evaluateWrapped: true + }; + __export = function resolveRef( ractive, ref, fragment, isParentLookup ) { + var context, key, index, keypath, parentValue, hasContextChain, parentKeys, childKeys, parentKeypath, childKeypath; + ref = normaliseRef( ref ); + // If a reference begins '~/', it's a top-level reference + if ( ref.substr( 0, 2 ) === '~/' ) { + return ref.substring( 2 ); + } + // If a reference begins with '.', it's either a restricted reference or + // an ancestor reference... + if ( ref.charAt( 0 ) === '.' ) { + return resolveAncestorReference( getInnerContext( fragment ), ref ); + } + // ...otherwise we need to find the keypath + key = ref.split( '.' )[ 0 ]; + // get() in viewmodel creation means no fragment (yet) + fragment = fragment || {}; + do { + context = fragment.context; + if ( !context ) { + continue; + } + hasContextChain = true; + parentValue = ractive.viewmodel.get( context, getOptions ); + if ( parentValue && ( typeof parentValue === 'object' || typeof parentValue === 'function' ) && key in parentValue ) { + return context + '.' + ref; + } + } while ( fragment = fragment.parent ); + // Root/computed property? + if ( key in ractive.data || key in ractive.viewmodel.computations ) { + return ref; + } + // If this is an inline component, and it's not isolated, we + // can try going up the scope chain + if ( ractive._parent && !ractive.isolated ) { + hasContextChain = true; + fragment = ractive.component.parentFragment; + // Special case - index refs + if ( fragment.indexRefs && ( index = fragment.indexRefs[ ref ] ) !== undefined ) { + // Create an index ref binding, so that it can be rebound letter if necessary. + // It doesn't have an alias since it's an implicit binding, hence `...[ ref ] = ref` + ractive.component.indexRefBindings[ ref ] = ref; + ractive.viewmodel.set( ref, index, true ); + return; + } + keypath = resolveRef( ractive._parent, ref, fragment, true ); + if ( keypath ) { + // We need to create an inter-component binding + // If parent keypath is 'one.foo' and child is 'two.foo', we bind + // 'one' to 'two' as it's more efficient and avoids edge cases + parentKeys = keypath.split( '.' ); + childKeys = ref.split( '.' ); + while ( parentKeys.length > 1 && childKeys.length > 1 && parentKeys[ parentKeys.length - 1 ] === childKeys[ childKeys.length - 1 ] ) { + parentKeys.pop(); + childKeys.pop(); + } + parentKeypath = parentKeys.join( '.' ); + childKeypath = childKeys.join( '.' ); + ractive.viewmodel.set( childKeypath, ractive._parent.viewmodel.get( parentKeypath ), true ); + createComponentBinding( ractive.component, ractive._parent, parentKeypath, childKeypath ); + return ref; + } + } + // If there's no context chain, and the instance is either a) isolated or + // b) an orphan, then we know that the keypath is identical to the reference + if ( !isParentLookup && !hasContextChain ) { + // the data object needs to have a property by this name, + // to prevent future failed lookups + ractive.viewmodel.set( ref, undefined ); + return ref; + } + if ( ractive.viewmodel.get( ref ) !== undefined ) { + return ref; + } + }; + + function resolveAncestorReference( baseContext, ref ) { + var contextKeys; + // {{.}} means 'current context' + if ( ref === '.' ) + return baseContext; + contextKeys = baseContext ? baseContext.split( '.' ) : []; + // ancestor references (starting "../") go up the tree + if ( ref.substr( 0, 3 ) === '../' ) { + while ( ref.substr( 0, 3 ) === '../' ) { + if ( !contextKeys.length ) { + throw new Error( ancestorErrorMessage ); + } + contextKeys.pop(); + ref = ref.substring( 3 ); + } + contextKeys.push( ref ); + return contextKeys.join( '.' ); + } + // not an ancestor reference - must be a restricted reference (prepended with "." or "./") + if ( !baseContext ) { + return ref.replace( /^\.\/?/, '' ); + } + return baseContext + ref.replace( /^\.\//, '.' ); + } + return __export; + }( normaliseRef, getInnerContext, createComponentBinding ); + + /* global/TransitionManager.js */ + var TransitionManager = function( removeFromArray ) { + + var TransitionManager = function( callback, parent ) { + this.callback = callback; + this.parent = parent; + this.intros = []; + this.outros = []; + this.children = []; + this.totalChildren = this.outroChildren = 0; + this.detachQueue = []; + this.outrosComplete = false; + if ( parent ) { + parent.addChild( this ); + } + }; + TransitionManager.prototype = { + addChild: function( child ) { + this.children.push( child ); + this.totalChildren += 1; + this.outroChildren += 1; + }, + decrementOutros: function() { + this.outroChildren -= 1; + check( this ); + }, + decrementTotal: function() { + this.totalChildren -= 1; + check( this ); + }, + add: function( transition ) { + var list = transition.isIntro ? this.intros : this.outros; + list.push( transition ); + }, + remove: function( transition ) { + var list = transition.isIntro ? this.intros : this.outros; + removeFromArray( list, transition ); + check( this ); + }, + init: function() { + this.ready = true; + check( this ); + }, + detachNodes: function() { + this.detachQueue.forEach( detach ); + this.children.forEach( detachNodes ); + } + }; + + function detach( element ) { + element.detach(); + } + + function detachNodes( tm ) { + tm.detachNodes(); + } + + function check( tm ) { + if ( !tm.ready || tm.outros.length || tm.outroChildren ) + return; + // If all outros are complete, and we haven't already done this, + // we notify the parent if there is one, otherwise + // start detaching nodes + if ( !tm.outrosComplete ) { + if ( tm.parent ) { + tm.parent.decrementOutros( tm ); + } else { + tm.detachNodes(); + } + tm.outrosComplete = true; + } + // Once everything is done, we can notify parent transition + // manager and call the callback + if ( !tm.intros.length && !tm.totalChildren ) { + if ( typeof tm.callback === 'function' ) { + tm.callback(); + } + if ( tm.parent ) { + tm.parent.decrementTotal(); + } + } + } + return TransitionManager; + }( removeFromArray ); + + /* global/runloop.js */ + var runloop = function( circular, Hook, removeFromArray, Promise, resolveRef, TransitionManager ) { + + var __export; + var batch, runloop, unresolved = [], + changeHook = new Hook( 'change' ); + runloop = { + start: function( instance, returnPromise ) { + var promise, fulfilPromise; + if ( returnPromise ) { + promise = new Promise( function( f ) { + return fulfilPromise = f; + } ); + } + batch = { + previousBatch: batch, + transitionManager: new TransitionManager( fulfilPromise, batch && batch.transitionManager ), + views: [], + tasks: [], + viewmodels: [], + instance: instance + }; + if ( instance ) { + batch.viewmodels.push( instance.viewmodel ); + } + return promise; + }, + end: function() { + flushChanges(); + batch.transitionManager.init(); + if ( !batch.previousBatch && !!batch.instance ) + batch.instance.viewmodel.changes = []; + batch = batch.previousBatch; + }, + addViewmodel: function( viewmodel ) { + if ( batch ) { + if ( batch.viewmodels.indexOf( viewmodel ) === -1 ) { + batch.viewmodels.push( viewmodel ); + return true; + } else { + return false; + } + } else { + viewmodel.applyChanges(); + return false; + } + }, + registerTransition: function( transition ) { + transition._manager = batch.transitionManager; + batch.transitionManager.add( transition ); + }, + addView: function( view ) { + batch.views.push( view ); + }, + addUnresolved: function( thing ) { + unresolved.push( thing ); + }, + removeUnresolved: function( thing ) { + removeFromArray( unresolved, thing ); + }, + // synchronise node detachments with transition ends + detachWhenReady: function( thing ) { + batch.transitionManager.detachQueue.push( thing ); + }, + scheduleTask: function( task, postRender ) { + var _batch; + if ( !batch ) { + task(); + } else { + _batch = batch; + while ( postRender && _batch.previousBatch ) { + // this can't happen until the DOM has been fully updated + // otherwise in some situations (with components inside elements) + // transitions and decorators will initialise prematurely + _batch = _batch.previousBatch; + } + _batch.tasks.push( task ); + } + } + }; + circular.runloop = runloop; + __export = runloop; + + function flushChanges() { + var i, thing, changeHash; + for ( i = 0; i < batch.viewmodels.length; i += 1 ) { + thing = batch.viewmodels[ i ]; + changeHash = thing.applyChanges(); + if ( changeHash ) { + changeHook.fire( thing.ractive, changeHash ); + } + } + batch.viewmodels.length = 0; + attemptKeypathResolution(); + // Now that changes have been fully propagated, we can update the DOM + // and complete other tasks + for ( i = 0; i < batch.views.length; i += 1 ) { + batch.views[ i ].update(); + } + batch.views.length = 0; + for ( i = 0; i < batch.tasks.length; i += 1 ) { + batch.tasks[ i ](); + } + batch.tasks.length = 0; + // If updating the view caused some model blowback - e.g. a triple + // containing