├── .coverignore ├── .coverrc ├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── docs ├── design.md ├── developing-gcli.md ├── index.md ├── running-tests.md ├── writing-commands.md ├── writing-tests.md └── writing-types.md ├── gcli.js ├── index.html ├── lib └── gcli │ ├── cli.js │ ├── commands │ ├── clear.js │ ├── commands.js │ ├── connect.js │ ├── context.js │ ├── demo │ │ ├── alert.js │ │ ├── demo.js │ │ ├── echo.js │ │ └── sleep.js │ ├── global.js │ ├── help.js │ ├── intro.js │ ├── lang.js │ ├── mocks.js │ ├── pref.js │ ├── preflist.js │ ├── server │ │ ├── exec.js │ │ ├── exit.js │ │ ├── firefox.js │ │ ├── orion.js │ │ ├── server.js │ │ └── standard.js │ └── test.js │ ├── connectors │ ├── connectors.js │ ├── front.js │ ├── index.js │ ├── protocol.js │ ├── remoted.js │ ├── websocket.js │ ├── websocketserver.js │ └── xhr.js │ ├── converters │ ├── basic.js │ ├── converters.js │ ├── html.js │ └── terminal.js │ ├── fields │ ├── delegate.js │ ├── fields.js │ └── selection.js │ ├── index.js │ ├── items │ ├── basic.js │ ├── demo.js │ ├── remote.js │ ├── server.js │ ├── standard.js │ └── ui.js │ ├── languages │ ├── command.html │ ├── command.js │ ├── javascript.js │ └── languages.js │ ├── nls │ └── strings.js │ ├── settings.js │ ├── system.js │ ├── test │ ├── automators │ │ ├── requisition.js │ │ └── terminal.js │ ├── helpers.js │ ├── index.js │ ├── mockCommands.js │ ├── mockDocument.js │ ├── mockFileCommands.js │ ├── mockSettings.js │ ├── suite.js │ ├── testAsync.js │ ├── testCanon.js │ ├── testCli1.js │ ├── testCli2.js │ ├── testCompletion1.js │ ├── testCompletion2.js │ ├── testContext.js │ ├── testDate.js │ ├── testExec.js │ ├── testFail.js │ ├── testFile.js │ ├── testFileparser.js │ ├── testFilesystem.js │ ├── testFocus.js │ ├── testHelp.js │ ├── testHistory.js │ ├── testIncomplete.js │ ├── testInputter.js │ ├── testIntro.js │ ├── testJs.js │ ├── testKeyboard1.js │ ├── testKeyboard2.js │ ├── testKeyboard3.js │ ├── testKeyboard4.js │ ├── testKeyboard5.js │ ├── testKeyboard6.js │ ├── testMenu.js │ ├── testNode.js │ ├── testPref1.js │ ├── testPref2.js │ ├── testRemoteWs.js │ ├── testRemoteXhr.js │ ├── testResource.js │ ├── testSettings.js │ ├── testShort.js │ ├── testSpell.js │ ├── testSplit.js │ ├── testString.js │ ├── testTokenize.js │ ├── testTooltip.js │ ├── testTypes.js │ ├── testUnion.js │ └── testUrl.js │ ├── testharness │ ├── assert.js │ ├── examiner.js │ └── status.js │ ├── types │ ├── array.js │ ├── boolean.js │ ├── command.js │ ├── date.js │ ├── delegate.js │ ├── file.js │ ├── fileparser.js │ ├── javascript.js │ ├── node.js │ ├── number.js │ ├── resource.js │ ├── selection.js │ ├── setting.js │ ├── string.js │ ├── types.js │ ├── union.js │ └── url.js │ ├── ui │ ├── focus.js │ ├── history.js │ ├── intro.js │ ├── menu.css │ ├── menu.html │ ├── menu.js │ ├── terminal.css │ ├── terminal.html │ ├── terminal.js │ └── view.js │ └── util │ ├── domtemplate.js │ ├── fileparser.js │ ├── filesystem.js │ ├── host.js │ ├── l10n.js │ ├── legacy.js │ ├── prism.js │ ├── spell.js │ └── util.js ├── package.json ├── phantom-test.js ├── remote.html ├── scripts ├── i18n.js ├── require.js ├── shim.js └── text.js ├── webpack.config.js ├── wp-index.html └── wp-index.js /.coverignore: -------------------------------------------------------------------------------- 1 | 2 | lib/server 3 | 4 | node_modules/connect 5 | node_modules/dryice 6 | node_modules/express 7 | node_modules/formidable 8 | node_modules/gclitest 9 | node_modules/socket.io 10 | node_modules/test 11 | 12 | node_modules/util/promise.js 13 | 14 | node_modules/gcli/index.js 15 | -------------------------------------------------------------------------------- /.coverrc: -------------------------------------------------------------------------------- 1 | { 2 | "dataDirectory": "built/coverage_data", 3 | "modules": true, 4 | "html": { 5 | "directory": "built/coverage_html", 6 | "generateIndex": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Junk that could exist anywhere: 3 | .DS_Store 4 | *.swp 5 | *.tmp 6 | .*.gz 7 | 8 | # Editor junk 9 | /.project 10 | /.pydevproject 11 | /.settings/ 12 | /.settings.xml 13 | /.settings.xml.old 14 | /.idea/ 15 | /.externalToolBuilders/ 16 | /gcli.iml 17 | 18 | # A handy place to put stuff that git should ignore: 19 | /ignore 20 | 21 | # Build artifacts 22 | /built 23 | 24 | # Manually installed node packages should be ignored 25 | /node_modules/ 26 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "undef": true, 3 | "camelcase": false, 4 | "curly": true, 5 | "noarg": true, 6 | "quotmark": "single", 7 | "strict": true, 8 | "eqnull": true, 9 | "evil": true, 10 | "eqnull": true, 11 | "browser": true, 12 | "devel": true, 13 | "node": true, 14 | "phantom": true, 15 | "laxbreak": true, 16 | "iterator": true, 17 | "unused":"vars", 18 | "globals": { 19 | "define": false, 20 | "Components": false, 21 | "Event": false, 22 | "CSSRule": false, 23 | "Proxy": false, 24 | "info": false, 25 | "io": false, 26 | "ok": false 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | sudo: false 4 | node_js: 5 | - "4.1" 6 | script: 7 | - "node gcli.js test" 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | GCLI - Graphic Command Line 3 | =========================== 4 | 5 | GCLI is a graphical command line component. It is being integrated with 6 | Firefox developer tools and with editors like Orion and Ace. It can be embedded 7 | in web pages and JavaScript applications. 8 | 9 | 10 | Why? 11 | ---- 12 | 13 | Command lines have advantages over graphical UIs in speed of entry and the 14 | ability to contain an almost unlimited set of commands without becoming 15 | cluttered. On the other hand GUIs typically come with better discoverability. 16 | GCLI is an experiment to see if we can improve the discoverability of command 17 | lines whilst retaining the speed and powerful command set of traditional CLIs. 18 | 19 | There are a number of problems with the design of traditional command lines: 20 | 21 | * They assume a curses-style 80x24 (or similar) character array for output. 22 | Even system consoles are capable of graphics these days. It ought to be 23 | possible to have richer output. 24 | * They assume serial access to the output - one command at a time. 25 | This made sense when multi-tasking was expensive, however with modern 26 | processors single-tasking is starting to look expensive. 27 | * They are so loosely coupled that the integration is typically nothing more 28 | than argv/stdout/stderr/stdin. 29 | That level of integration made sense on memory constrained devices, but with 30 | more resources, we can provide much richer integration. 31 | 32 | 33 | Getting Started 34 | --------------- 35 | 36 | $ git clone git://github.com/joewalker/gcli.git 37 | $ cd gcli 38 | -> Load index.html into your web browser (except Chrome) 39 | For Chrome: 40 | install node (http://nodejs.org/download/) 41 | $ npm install . 42 | $ node ./gcli.js 43 | -> Load http://localhost:9999/ 44 | 45 | When you see the ':' prompt, type 'help' to see a list of commands. 46 | 47 | 48 | Related Links 49 | ------------- 50 | 51 | * **Bug reports**: http://j.mp/gclibug 52 | * **GCLI in Firefox**: https://developer.mozilla.org/en-US/docs/Tools/GCLI 53 | * **GCLI on the Web**: https://github.com/joewalker/gcli/blob/master/docs/index.md 54 | 55 | -------------------------------------------------------------------------------- /docs/design.md: -------------------------------------------------------------------------------- 1 | 2 | # The Design of GCLI 3 | 4 | ## Design Goals 5 | 6 | GCLI should be: 7 | 8 | - primarily for technical users. 9 | - as fast as a traditional CLI. It should be possible to put your head down, 10 | and look at the keyboard and use GCLI 'blind' at full speed without making 11 | mistakes. 12 | - principled about the way it encourages people to build commands. There is 13 | benefit from unifying the underlying concepts. 14 | - automatically helpful. 15 | 16 | GCLI should not attempt to: 17 | 18 | - convert existing GUI users to a CLI. 19 | - use natural language input. The closest we should get to natural language is 20 | thinking of commands as ```verb noun --adjective```. 21 | - gain a touch based interface. Whilst it's possible (even probable) that touch 22 | can provide further benefits to command line users, that can wait while we 23 | catch up with 1985. 24 | - slavishly follow the syntax of existing commands, predictability is more 25 | important. 26 | - be a programming language. Shell scripts are mini programming languages but 27 | we have JavaScript sat just next door. It's better to integrate than compete. 28 | 29 | 30 | ## Design Challenges 31 | 32 | What has changed since 1970 that might cause us to make changes to the design 33 | of the command line? 34 | 35 | 36 | ### Connection limitations 37 | 38 | Unix pre-dates the Internet and treats almost everything as a file. Since the 39 | Internet it could be more useful to use URIs as ways to identify sources of data. 40 | 41 | 42 | ### Memory limitations 43 | 44 | Modern computers have something like 6 orders of magnitude more memory than the 45 | PDP-7 on which Unix was developed. Innovations like stdin/stdout and pipes are 46 | ways to connect systems without long-term storage of the results. The ability 47 | to store results for some time (potentially in more than one format) 48 | significantly reduces the need for these concepts. We should make the results 49 | of past commands addressable for re-use at a later time. 50 | 51 | There are a number of possible policies for eviction of items from the history. 52 | We should investigate options other than a simple stack. 53 | 54 | 55 | ### Multi-tasking limitations 56 | 57 | Multi-tasking was a problem in 1970; the problem was getting a computer to do 58 | many jobs on 1 core. Today the problem is getting a computer to do one job on 59 | many cores. However we're stuck with this legacy in 2 ways. Firstly that the 60 | default is to force everything to wait until the previous job is finished, but 61 | more importantly that output from parallel jobs frequently collides 62 | 63 | $ find / -ctime 5d -print & 64 | $ find / -uid 0 -print & 65 | // good luck working out what came from where 66 | 67 | $ tail -f logfile.txt & 68 | $ vi main.c 69 | // have a nice time editing that file 70 | 71 | GCLI should allow commands to be asynchronous and will provide UI elements to 72 | inform the user of job completion. It will also keep asynchronous command 73 | output contained within it's own display area. 74 | 75 | 76 | ### Output limitations 77 | 78 | The PDP-7 had a teletype. There is something like 4 orders of magnitude more 79 | information that can be displayed on a modern display than a 80x24 character 80 | based console. We can use this flexibility to provide better help to the user 81 | in entering their command. 82 | 83 | The additional display richness can also allow interaction with result output. 84 | Command output can include links to follow-up commands, and even ask for 85 | additional input. (e.g. "your search returned zero results do you want to try 86 | again with a different search string") 87 | 88 | There is no reason why output must be static. For example, it could be 89 | informative to see the results of an "ls" command alter given changes made by 90 | subsequent commands. (It should be noted that there are times when historical 91 | information is important too) 92 | 93 | 94 | ### Integration limitations 95 | 96 | In 1970, command execution meant retrieving a program from storage, and running 97 | it. This required minimal interaction between the command line processor and 98 | the program being run, and was good for resource constrained systems. 99 | This lack of interaction resulted in the processing of command line arguments 100 | being done everywhere, when the task was better suited to command line. 101 | We should provide metadata about the commands being run, to allow the command 102 | line to process, interpret and provide help on the input. 103 | -------------------------------------------------------------------------------- /docs/running-tests.md: -------------------------------------------------------------------------------- 1 | 2 | # Running Tests 3 | 4 | GCLI has a test suite that can be run in a number of different environments. 5 | Some of the tests don't work in all environments. These should be automatically 6 | skipped when not applicable. 7 | 8 | 9 | ## Web 10 | 11 | Running a limited set of test from the web is the easiest. Simply load 12 | 'localtest.html' and the unit tests should be run automatically, with results 13 | displayed on the console. Tests can be re-run using the 'test' command. 14 | 15 | It also creates a function 'testCommands()' to be run at a JS prompt, which 16 | enables the test commands for debugging purposes. 17 | 18 | 19 | ## Firefox 20 | 21 | GCLI's test suite integrates with Mochitest and runs automatically on each test 22 | run. Dryice packages the tests to format them for the Firefox build system. 23 | 24 | For more information about running Mochitest on Firefox (including GCLI) see 25 | [the MDN, Mochitest docs](https://developer.mozilla.org/en/Mochitest) 26 | 27 | 28 | # Node 29 | 30 | Running the test suite under node can be done as follows: 31 | 32 | $ node gcli.js test 33 | 34 | Or, using the `test` command: 35 | 36 | $ node gcli.js 37 | Serving GCLI to http://localhost:9999/ 38 | This is also a limited GCLI prompt. 39 | Type 'help' for a list of commands, CTRL+C twice to exit: 40 | : test 41 | 42 | testCli: Pass (funcs=9, checks=208) 43 | testCompletion: Pass (funcs=1, checks=139) 44 | testExec: Pass (funcs=1, checks=133) 45 | testHistory: Pass (funcs=3, checks=13) 46 | .... 47 | 48 | Summary: Pass (951 checks) 49 | 50 | 51 | # Travis CI 52 | 53 | GCLI check-ins are automatically tested by [Travis CI](https://travis-ci.org/joewalker/gcli). 54 | 55 | 56 | # Test Case Generation 57 | 58 | GCLI can generate test cases automagically. Load ```localtest.html```, type a 59 | command to be tested into GCLI, and the press F2. GCLI will output to the 60 | console a template test case for the entered command. 61 | -------------------------------------------------------------------------------- /docs/writing-tests.md: -------------------------------------------------------------------------------- 1 | 2 | # Writing Tests 3 | 4 | There are several sources of GCLI tests and several environments in which they 5 | are run. 6 | 7 | The majority of GCLI tests are stored in 8 | [this repository](https://github.com/joewalker/gcli/) in files named like 9 | ```./lib/gclitest/test*.js```. These tests run in Firefox, Chrome, Opera, 10 | and NodeJS/JsDom 11 | 12 | See [Running Tests](running-tests.md) for further details. 13 | 14 | GCLI comes with a generic unit test harness (in ```./lib/test/```) and a 15 | set of helpers for creating GCLI tests (in ```./lib/gclitest/helpers.js```). 16 | 17 | # GCLI tests in Firefox 18 | 19 | The build process converts the GCLI tests to run under Mochitest inside the 20 | Firefox unit tests. It also adds some 21 | -------------------------------------------------------------------------------- /docs/writing-types.md: -------------------------------------------------------------------------------- 1 | 2 | # Writing Types 3 | 4 | Commands are a fundamental building block because they are what the users 5 | directly interacts with, however they are built on ``Type``s. There are a 6 | number of built in types: 7 | 8 | * string. This is a JavaScript string 9 | * number. A JavaScript number 10 | * boolean. A JavaScript boolean 11 | * selection. This is an selection from a number of alternatives 12 | * delegate. This type could change depending on other factors, but is well 13 | defined when one of the conversion routines is called. 14 | 15 | There are a number of additional types defined by Pilot and GCLI as 16 | extensions to the ``selection`` and ``delegate`` types 17 | 18 | * setting. One of the defined settings 19 | * settingValue. A value that can be applied to an associated setting. 20 | * command. One of the defined commands 21 | 22 | Most of our types are 'static' e.g. there is only one type of 'string', however 23 | some types like 'selection' and 'delegate' are customizable. 24 | 25 | All types must inherit from Type and have the following methods: 26 | 27 | /** 28 | * Convert the given value to a string representation. 29 | * Where possible, there should be round-tripping between values and their 30 | * string representations. 31 | */ 32 | stringify: function(value) { return 'string version of value'; }, 33 | 34 | /** 35 | * Convert the given str to an instance of this type. 36 | * Where possible, there should be round-tripping between values and their 37 | * string representations. 38 | * @return Conversion 39 | */ 40 | parse: function(str) { return new Conversion(...); }, 41 | 42 | /** 43 | * The plug-in system, and other things need to know what this type is 44 | * called. The name alone is not enough to fully specify a type. Types like 45 | * 'selection' and 'delegate' need extra data, however this function returns 46 | * only the name, not the extra data. 47 | *

In old bespin, equality was based on the name. This may turn out to be 48 | * important in Ace too. 49 | */ 50 | name: 'example', 51 | 52 | In addition, defining the following function can be helpful, although Type 53 | contains default implementations: 54 | 55 | * nudge(value, by) 56 | 57 | Type, Conversion and Status are all declared by commands.js. 58 | 59 | The values produced by the parse function can be of any type, but if you are 60 | producing your own, you are strongly encouraged to include properties called 61 | ``name`` and ``description`` where it makes sense. There are a number of 62 | places in GCLI where the UI will be able to provide better help to users if 63 | your values include these properties. 64 | 65 | 66 | # Writing Fields 67 | 68 | Fields are visual representations of types. For simple types like string it is 69 | enough to use ````, however more complex types we may wish to 70 | provide a custom widget to allow the user to enter values of the given type. 71 | 72 | This is an example of a very simple new password field type: 73 | 74 | function PasswordField(doc) { 75 | this.doc = doc; 76 | } 77 | 78 | PasswordField.prototype = Object.create(Field.prototype); 79 | 80 | PasswordField.prototype.createElement = function(assignment) { 81 | this.assignment = assignment; 82 | this.input = dom.createElement(this.doc, 'input'); 83 | this.input.type = 'password'; 84 | this.input.value = assignment.arg ? assignment.arg.text : ''; 85 | 86 | this.onKeyup = function() { 87 | this.assignment.setValue(this.input.value); 88 | }.bind(this); 89 | this.input.addEventListener('keyup', this.onKeyup, false); 90 | 91 | this.onChange = function() { 92 | this.input.value = this.assignment.arg.text; 93 | }; 94 | this.assignment.onAssignmentChange.add(this.onChange, this); 95 | 96 | return this.input; 97 | }; 98 | 99 | PasswordField.prototype.destroy = function() { 100 | this.input.removeEventListener('keyup', this.onKeyup, false); 101 | this.assignment.onAssignmentChange.remove(this.onChange, this); 102 | }; 103 | 104 | PasswordField.claim = function(type) { 105 | return type.name === 'password' ? Field.claim.MATCH : Field.claim.NO_MATCH; 106 | }; 107 | -------------------------------------------------------------------------------- /gcli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * Copyright 2012, Mozilla Foundation and contributors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | 'use strict'; 19 | 20 | var system = require('./lib/gcli/system').createSystem(); 21 | 22 | var items = [ 23 | require('./lib/gcli/items/basic').items, 24 | require('./lib/gcli/items/ui').items, 25 | require('./lib/gcli/items/remote').items, 26 | require('./lib/gcli/items/standard').items, 27 | require('./lib/gcli/items/demo').items, 28 | require('./lib/gcli/items/server').items, 29 | 30 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 31 | 32 | system.addItems(items); 33 | 34 | var util = require('./lib/gcli/util/util'); 35 | var Requisition = require('./lib/gcli/cli').Requisition; 36 | 37 | var requisition = new Requisition(system); 38 | var command, extraActions; 39 | 40 | if (process.argv.length < 3) { 41 | // No command passed in. Serve GCLI over http and start a local REPL 42 | command = 'server start'; 43 | extraActions = function(output) { 44 | if (!output.error) { 45 | startRepl(); 46 | } 47 | }; 48 | } 49 | else { 50 | // Command passed in. No server/REPL and a process.exit(1) on failure to 51 | // propagate test errors 52 | command = process.argv.slice(2).join(' '); 53 | extraActions = function(output) { 54 | if (output.error) { 55 | process.exit(1); 56 | } 57 | }; 58 | } 59 | 60 | /** 61 | * Convert an Output object to a string, and then log that to stdout/stderr 62 | * depending on the error status 63 | */ 64 | function logResults(output) { 65 | var context = requisition.conversionContext; 66 | return output.convert('string', context).then(function(message) { 67 | if (output.error) { 68 | console.error(message); 69 | } 70 | else { 71 | console.log(message); 72 | } 73 | return output; 74 | }); 75 | } 76 | 77 | requisition.updateExec(command) 78 | .then(logResults) 79 | .then(extraActions) 80 | .catch(util.errorHandler); 81 | 82 | /** 83 | * Start a NodeJS REPL to execute commands 84 | */ 85 | function startRepl() { 86 | var repl = require('repl'); 87 | 88 | var gcliEval = function(command, scope, file, callback) { 89 | // Why does node wrap the command in '(...)\n'? 90 | command = command.replace(/^\((.*)\n\)$/, function(all, part) { 91 | return part; 92 | }); 93 | 94 | if (command.length !== 0) { 95 | requisition.updateExec(command) 96 | .then(logResults) 97 | .then(function() { callback(); }) 98 | .catch(function(ex) { util.errorHandler(ex); callback(); }); 99 | } 100 | }; 101 | 102 | console.log('This is also a limited GCLI REPL. ' + 103 | 'Type \'help\' for a list of commands, CTRL+C 3 times to exit:'); 104 | repl.start(': ', process, gcliEval, false, true); 105 | } 106 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GCLI: Graphical Command Line 7 | 15 | 16 | 17 | 18 | 19 |

20 | 21 | 22 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /lib/gcli/commands/clear.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | 21 | exports.items = [ 22 | { 23 | // A command to clear the output area 24 | item: 'command', 25 | name: 'clear', 26 | description: l10n.lookup('clearDesc'), 27 | returnType: 'clearoutput', 28 | exec: function(args, context) { } 29 | }, 30 | { 31 | item: 'converter', 32 | from: 'clearoutput', 33 | to: 'view', 34 | exec: function(ignore, conversionContext) { 35 | return { 36 | html: '', 37 | data: { 38 | onload: function(ev) { 39 | // element starts off being the span above, and we walk up the 40 | // tree looking for the terminal 41 | var element = ev.target; 42 | while (element != null && element.terminal == null) { 43 | element = element.parentElement; 44 | } 45 | 46 | if (element == null) { 47 | // This is only an event handler on a completed command 48 | // So we're relying on this showing up in the console 49 | throw new Error('Failed to find clear'); 50 | } 51 | 52 | element.terminal.clear(); 53 | } 54 | } 55 | }; 56 | } 57 | } 58 | ]; 59 | -------------------------------------------------------------------------------- /lib/gcli/commands/context.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | var cli = require('../cli'); 21 | 22 | /** 23 | * 'context' command 24 | */ 25 | var context = { 26 | item: 'command', 27 | name: 'context', 28 | description: l10n.lookup('contextDesc'), 29 | manual: l10n.lookup('contextManual'), 30 | params: [ 31 | { 32 | name: 'prefix', 33 | type: 'command', 34 | description: l10n.lookup('contextPrefixDesc'), 35 | defaultValue: null 36 | } 37 | ], 38 | returnType: 'string', 39 | // The context command is client only because it's essentially sugar for 40 | // typing commands. When there is a command prefix in action, it is the job 41 | // of the remoter to add the prefix to the typed strings that are sent for 42 | // remote execution 43 | noRemote: true, 44 | exec: function echo(args, context) { 45 | var requisition = cli.getMapping(context).requisition; 46 | 47 | if (args.prefix == null) { 48 | requisition.prefix = null; 49 | return l10n.lookup('contextEmptyReply'); 50 | } 51 | 52 | if (args.prefix.exec != null) { 53 | throw new Error(l10n.lookupFormat('contextNotParentError', 54 | [ args.prefix.name ])); 55 | } 56 | 57 | requisition.prefix = args.prefix.name; 58 | return l10n.lookupFormat('contextReply', [ args.prefix.name ]); 59 | } 60 | }; 61 | 62 | exports.items = [ context ]; 63 | -------------------------------------------------------------------------------- /lib/gcli/commands/demo/alert.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.items = [ 20 | { 21 | // Arm window.alert with metadata 22 | item: 'command', 23 | name: 'alert', 24 | description: 'Show an alert dialog', 25 | params: [ 26 | { 27 | name: 'message', 28 | type: 'string', 29 | description: 'Message to display' 30 | } 31 | ], 32 | exec: function(args, context) { 33 | window.alert(args.message); 34 | } 35 | } 36 | ]; 37 | -------------------------------------------------------------------------------- /lib/gcli/commands/demo/echo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.items = [ 20 | { 21 | item: 'command', 22 | name: 'echo', 23 | description: { 24 | root: 'Show a message', 25 | fr_fr: 'Afficher un message' 26 | }, 27 | params: [ 28 | { 29 | name: 'message', 30 | type: 'string', 31 | description: { 32 | root: 'The message to output', 33 | fr_fr: 'Le message à afficher' 34 | } 35 | } 36 | ], 37 | returnType: 'string', 38 | exec: function(args, context) { 39 | return args.message; 40 | } 41 | } 42 | ]; 43 | -------------------------------------------------------------------------------- /lib/gcli/commands/demo/sleep.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.items = [ 20 | { 21 | item: 'command', 22 | name: 'sleep', 23 | description: 'Wait for a while', 24 | params: [ 25 | { 26 | name: 'length', 27 | type: { name: 'number', min: 1 }, 28 | description: 'How long to wait (s)' 29 | } 30 | ], 31 | returnType: 'string', 32 | exec: function(args, context) { 33 | return new Promise(function(resolve, reject) { 34 | setTimeout(function() { 35 | resolve('Done'); 36 | }, args.length * 1000); 37 | }); 38 | } 39 | } 40 | ]; 41 | -------------------------------------------------------------------------------- /lib/gcli/commands/global.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | 21 | exports.items = [ 22 | { 23 | // A type for selecting a known setting 24 | item: 'type', 25 | name: 'global', 26 | parent: 'selection', 27 | remote: true, 28 | lookup: function(context) { 29 | var knownWindows = context.environment.window == null ? 30 | [ ] : [ context.environment.window ]; 31 | 32 | this.last = findWindows(knownWindows).map(function(window) { 33 | return { name: windowToString(window), value: window }; 34 | }); 35 | 36 | return this.last; 37 | } 38 | }, 39 | { 40 | // A command to switch JS globals 41 | item: 'command', 42 | name: 'global', 43 | description: l10n.lookup('globalDesc'), 44 | params: [ 45 | { 46 | name: 'window', 47 | type: 'global', 48 | description: l10n.lookup('globalWindowDesc'), 49 | } 50 | ], 51 | returnType: 'string', 52 | exec: function(args, context) { 53 | context.shell.global = args.window; 54 | return l10n.lookupFormat('globalOutput', [ windowToString(args.window) ]); 55 | } 56 | } 57 | ]; 58 | 59 | function windowToString(win) { 60 | return win.location ? win.location.href : 'NodeJS-Global'; 61 | } 62 | 63 | function findWindows(knownWindows) { 64 | knownWindows.forEach(function(window) { 65 | addChildWindows(window, knownWindows); 66 | }); 67 | return knownWindows; 68 | } 69 | 70 | function addChildWindows(win, knownWindows) { 71 | var iframes = win.document.querySelectorAll('iframe'); 72 | [].forEach.call(iframes, function(iframe) { 73 | var iframeWin = iframe.contentWindow; 74 | if (knownWindows.indexOf(iframeWin) === -1) { 75 | knownWindows.push(iframeWin); 76 | addChildWindows(iframeWin, knownWindows); 77 | } 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /lib/gcli/commands/intro.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | var intro = require('../ui/intro'); 21 | 22 | exports.items = [ 23 | { 24 | item: 'converter', 25 | from: 'intro', 26 | to: 'view', 27 | exec: intro.createView 28 | }, 29 | { 30 | item: 'command', 31 | name: 'intro', 32 | description: l10n.lookup('introDesc'), 33 | manual: l10n.lookup('introManual'), 34 | returnType: 'intro', 35 | exec: function(args, context) { 36 | // The intro command is pure formatting - no data 37 | } 38 | } 39 | ]; 40 | -------------------------------------------------------------------------------- /lib/gcli/commands/lang.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | var cli = require('../cli'); 21 | 22 | exports.items = [ 23 | { 24 | // A type that lists available languages 25 | item: 'type', 26 | name: 'language', 27 | parent: 'selection', 28 | lookup: function(context) { 29 | return context.system.languages.getAll().map(function(language) { 30 | return { name: language.name, value: language }; 31 | }); 32 | } 33 | }, 34 | { 35 | // A command to switch languages 36 | item: 'command', 37 | name: 'lang', 38 | description: l10n.lookup('langDesc'), 39 | params: [ 40 | { 41 | name: 'language', 42 | type: 'language' 43 | } 44 | ], 45 | returnType: 'view', 46 | exec: function(args, context) { 47 | var terminal = cli.getMapping(context).terminal; 48 | 49 | context.environment.window.setTimeout(function() { 50 | terminal.switchLanguage(args.language); 51 | }, 10); 52 | 53 | return { 54 | html: 55 | '
' + 56 | ' ${langOutput}' + 57 | '
', 58 | data: { 59 | langOutput: l10n.lookupFormat('langOutput', [ args.language.name ]), 60 | style: args.language.proportionalFonts ? '' : 'gcli-row-script' 61 | } 62 | }; 63 | } 64 | } 65 | ]; 66 | -------------------------------------------------------------------------------- /lib/gcli/commands/mocks.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var cli = require('../cli'); 20 | var mockCommands = require('../test/mockCommands'); 21 | var mockFileCommands = require('../test/mockFileCommands'); 22 | var mockSettings = require('../test/mockSettings'); 23 | var mockDocument = require('../test/mockDocument'); 24 | 25 | var isNode = (typeof(process) !== 'undefined' && 26 | process.title.indexOf('node') != -1); 27 | 28 | exports.items = [ 29 | { 30 | item: 'command', 31 | name: 'mocks', 32 | description: 'Add/remove mock commands', 33 | params: [ 34 | { 35 | name: 'included', 36 | type: { 37 | name: 'selection', 38 | data: [ 'on', 'off' ] 39 | }, 40 | description: 'Turn mock commands on or off', 41 | } 42 | ], 43 | returnType: 'string', 44 | 45 | exec: function(args, context) { 46 | var requisition = cli.getMapping(context).requisition; 47 | this[args.included](requisition); 48 | return 'Mock commands are now ' + args.included; 49 | }, 50 | 51 | on: function(requisition) { 52 | mockCommands.setup(requisition); 53 | mockSettings.setup(requisition.system); 54 | mockDocument.setup(requisition); 55 | 56 | if (isNode) { 57 | mockFileCommands.setup(requisition); 58 | } 59 | }, 60 | 61 | off: function(requisition) { 62 | mockCommands.shutdown(requisition); 63 | mockSettings.shutdown(requisition.system); 64 | mockDocument.shutdown(requisition); 65 | 66 | if (isNode) { 67 | mockFileCommands.shutdown(requisition); 68 | } 69 | } 70 | } 71 | ]; 72 | -------------------------------------------------------------------------------- /lib/gcli/commands/pref.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | 21 | exports.items = [ 22 | { 23 | // 'pref' command 24 | item: 'command', 25 | name: 'pref', 26 | description: l10n.lookup('prefDesc'), 27 | manual: l10n.lookup('prefManual') 28 | }, 29 | { 30 | // 'pref show' command 31 | item: 'command', 32 | name: 'pref show', 33 | description: l10n.lookup('prefShowDesc'), 34 | manual: l10n.lookup('prefShowManual'), 35 | params: [ 36 | { 37 | name: 'setting', 38 | type: 'setting', 39 | description: l10n.lookup('prefShowSettingDesc'), 40 | manual: l10n.lookup('prefShowSettingManual') 41 | } 42 | ], 43 | exec: function(args, context) { 44 | return l10n.lookupFormat('prefShowSettingValue', 45 | [ args.setting.name, args.setting.value ]); 46 | } 47 | }, 48 | { 49 | // 'pref set' command 50 | item: 'command', 51 | name: 'pref set', 52 | description: l10n.lookup('prefSetDesc'), 53 | manual: l10n.lookup('prefSetManual'), 54 | params: [ 55 | { 56 | name: 'setting', 57 | type: 'setting', 58 | description: l10n.lookup('prefSetSettingDesc'), 59 | manual: l10n.lookup('prefSetSettingManual') 60 | }, 61 | { 62 | name: 'value', 63 | type: 'settingValue', 64 | description: l10n.lookup('prefSetValueDesc'), 65 | manual: l10n.lookup('prefSetValueManual') 66 | } 67 | ], 68 | exec: function(args, context) { 69 | args.setting.value = args.value; 70 | } 71 | }, 72 | { 73 | // 'pref reset' command 74 | item: 'command', 75 | name: 'pref reset', 76 | description: l10n.lookup('prefResetDesc'), 77 | manual: l10n.lookup('prefResetManual'), 78 | params: [ 79 | { 80 | name: 'setting', 81 | type: 'setting', 82 | description: l10n.lookup('prefResetSettingDesc'), 83 | manual: l10n.lookup('prefResetSettingManual') 84 | } 85 | ], 86 | exec: function(args, context) { 87 | args.setting.setDefault(); 88 | } 89 | } 90 | ]; 91 | -------------------------------------------------------------------------------- /lib/gcli/commands/server/exec.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var host = require('../../util/host'); 20 | var l10n = require('../../util/l10n'); 21 | var cli = require('../../cli'); 22 | 23 | exports.items = [ 24 | { 25 | // 'cd' command 26 | item: 'command', 27 | name: 'cd', 28 | description: l10n.lookup('cdDesc'), 29 | manual: l10n.lookup('cdManual'), 30 | params: [ 31 | { 32 | name: 'directory', 33 | type: { 34 | name: 'file', 35 | filetype: 'directory', 36 | existing: 'yes' 37 | }, 38 | description: l10n.lookup('cdDirectoryDesc') 39 | } 40 | ], 41 | returnType: 'string', 42 | exec: function(args, context) { 43 | context.shell.cwd = args.directory; 44 | return l10n.lookupFormat('cdOutput', [ context.shell.cwd ]); 45 | } 46 | }, 47 | { 48 | // 'exec' command 49 | item: 'command', 50 | name: 'exec', 51 | description: l10n.lookup('execDesc'), 52 | manual: l10n.lookup('execManual'), 53 | params: [ 54 | { 55 | name: 'command', 56 | type: 'string', 57 | description: l10n.lookup('execCommandDesc') 58 | } 59 | ], 60 | returnType: 'output', 61 | exec: function(args, context) { 62 | var cmdArgs = cli.tokenize(args.command).map(function(arg) { 63 | return arg.text; 64 | }); 65 | var cmd = cmdArgs.shift(); 66 | 67 | var spawnSpec = { 68 | cmd: cmd, 69 | args: cmdArgs, 70 | env: context.shell.env, 71 | cwd: context.shell.cwd 72 | }; 73 | 74 | return host.spawn(context, spawnSpec).then(function(output) { 75 | if (output.code === 0) { 76 | return output; 77 | } 78 | 79 | throw output.data; 80 | }, function(output) { 81 | throw output.data; 82 | }); 83 | } 84 | }, 85 | { 86 | // How we display the output of a generic exec command: we have to assume 87 | // that it is a string to be displayed in a monospaced font 88 | item: 'converter', 89 | from: 'output', 90 | to: 'view', 91 | exec: function(output, context) { 92 | return { 93 | html: '
${output.data}
', 94 | data: { output: output } 95 | }; 96 | } 97 | }, 98 | { 99 | item: 'converter', 100 | from: 'output', 101 | to: 'string', 102 | exec: function(output, context) { 103 | return output.data; 104 | } 105 | } 106 | ]; 107 | -------------------------------------------------------------------------------- /lib/gcli/commands/server/exit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.items = [ 20 | { 21 | item: 'command', 22 | name: 'exit', 23 | description: 'Quit from GCLI', 24 | exec: function(args, context) { 25 | process.exit(0); 26 | } 27 | } 28 | ]; 29 | -------------------------------------------------------------------------------- /lib/gcli/commands/server/orion.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var copy = require('dryice').copy; 20 | var fs = require('fs'); 21 | var path = require('path'); 22 | 23 | /** 24 | * 'orion' build command 25 | */ 26 | exports.items = [ 27 | { 28 | item: 'command', 29 | name: 'orion', 30 | description: 'Build the Orion-GCLI target', 31 | params: [ 32 | { 33 | name: 'location', 34 | type: { 35 | name: 'file', 36 | filetype: 'directory', 37 | existing: 'yes' 38 | }, 39 | defaultValue: process.env.ORION_HOME || undefined, 40 | description: 'The location of the org.eclipse.orion.client checkout' 41 | } 42 | ], 43 | returnType: 'string', 44 | exec: function(args, context) { 45 | var gcliHome = path.dirname(require.main.filename); 46 | var root = path.normalize(args.location); 47 | var dest = path.join(root, 'bundles/org.eclipse.orion.client.ui/web/gcli'); 48 | var count = 0; 49 | 50 | if (!fs.existsSync(dest)) { 51 | throw new Error('\'' + dest + '\' does not exist.'); 52 | } 53 | 54 | var stats = fs.statSync(dest); 55 | if (!stats.isDirectory()) { 56 | throw new Error('\'' + dest + '\' is not a directory.'); 57 | } 58 | 59 | var output = 'Building GCLI files for Orion'; 60 | output += '\n Source = ' + gcliHome; 61 | output += '\n Dest = ' + dest; 62 | 63 | var logCopy = function(filename) { 64 | output += '\n ' + filename.substr(dest.length + 1); 65 | count++; 66 | return filename; 67 | }; 68 | 69 | output += '\nCopying:'; 70 | copy({ 71 | source: gcliHome + '/LICENSE', 72 | dest: dest + '/LICENSE' 73 | }); 74 | logCopy(dest + '/LICENSE'); 75 | 76 | output += '\nCopying (and adding AMD headers):'; 77 | copy({ 78 | source: { root: gcliHome + '/lib/gcli' }, 79 | filenameFilter: logCopy, 80 | filter: defineFilter, 81 | dest: dest + '/gcli' 82 | }); 83 | 84 | output += '\nCopying (and adding AMD headers):'; 85 | copy({ 86 | source: { root: gcliHome + '/web/gcli' }, 87 | filenameFilter: logCopy, 88 | filter: defineFilter, 89 | dest: dest + '/gcli' 90 | }); 91 | 92 | output += '\nCopied ' + count + ' files'; 93 | 94 | return output; 95 | } 96 | } 97 | ]; 98 | 99 | /** 100 | * A filter to munge CommonJS headers 101 | */ 102 | var defineFilter = function(input, source) { 103 | var output = input.toString(); 104 | 105 | if (source.path.match(/\.js$/)) { 106 | output = output.replace(/(["'](do not )?use strict[\"\'];)/, 107 | 'define(function(require, exports, module) {\n\n$1'); 108 | output += '\n\n});\n'; 109 | } 110 | 111 | return output; 112 | }; 113 | defineFilter.onRead = true; 114 | -------------------------------------------------------------------------------- /lib/gcli/commands/server/standard.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var copy = require('dryice').copy; 20 | var path = require('path'); 21 | 22 | exports.items = [ 23 | { 24 | // 'standard' build command 25 | // There are 2 important ways to build GCLI. 26 | // The first is for use within a normal web page. 27 | // It has compressed and uncompressed versions of the output script file. 28 | item: 'command', 29 | name: 'standard', 30 | description: 'Build the basic GCLI web target', 31 | returnType: 'terminal', 32 | exec: function(args, context) { 33 | var log = 'Building standard outputs to built/gcli[-uncompressed].js\n'; 34 | 35 | copy.mkdirSync(path.dirname(require.main.filename) + '/built', 493 /*0755*/); 36 | var project = copy.createCommonJsProject({ 37 | roots: [ path.dirname(require.main.filename) + '/lib' ] 38 | }); 39 | var sources = copy.createDataObject(); 40 | 41 | copy({ 42 | source: { 43 | project: project, 44 | // This list of dependencies should reflect index.html 45 | require: [ 'gcli/index', 'gcli/demo' ] 46 | }, 47 | filter: copy.filter.moduleDefines, 48 | dest: sources 49 | }); 50 | copy({ 51 | source: { root: project, include: /.*\.png$|.*\.gif$/ }, 52 | filter: copy.filter.base64, 53 | dest: sources 54 | }); 55 | log += project.report() + '\n'; 56 | 57 | // Create a GraphML dependency report. Directions: 58 | // - Install yEd (http://www.yworks.com/en/products_yed_about.htm) 59 | // - Load gcli/built/gcli.graphml 60 | // - Resize the nodes (Tools->Fit Node to Label) 61 | // - Apply a layout (Layout->Hierarchical) 62 | log += 'Outputting dependency graph to built/gcli.graphml\n'; 63 | if (project.getDependencyGraphML) { 64 | copy({ 65 | source: { value:project.getDependencyGraphML() }, 66 | dest: 'built/gcli.graphml' 67 | }); 68 | } 69 | 70 | // Create the output scripts, compressed and uncompressed 71 | copy({ source: 'index.html', filter: tweakIndex, dest: 'built/index.html' }); 72 | copy({ 73 | source: [ copy.getMiniRequire(), sources ], 74 | dest: 'built/gcli-uncompressed.js' 75 | }); 76 | try { 77 | copy({ 78 | source: [ copy.getMiniRequire(), sources ], 79 | filter: copy.filter.uglifyjs, 80 | dest: 'built/gcli.js' 81 | }); 82 | } 83 | catch (ex) { 84 | log += 'ERROR: Uglify compression fails on windows/linux. ' + 85 | 'Skipping creation of built/gcli.js\n'; 86 | } 87 | return log; 88 | } 89 | } 90 | ]; 91 | 92 | /** 93 | * Filter index.html to: 94 | * - Make links relative, we flatten out the scripts directory 95 | * - Replace require.js with the built GCLI script file 96 | * - Remove the RequireJS configuration 97 | */ 98 | function tweakIndex(data) { 99 | return data 100 | .replace(/scripts\/require.js/, 'gcli-uncompressed.js') 101 | .replace(/\s*requirejs.config\([^;]*;\n/, ''); 102 | } 103 | -------------------------------------------------------------------------------- /lib/gcli/connectors/connectors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is how to implement a connector 21 | * var baseConnector = { 22 | * item: 'connector', 23 | * name: 'foo', 24 | * 25 | * connect: function(url) { 26 | * return Promise.resolve(new FooConnection(url)); 27 | * } 28 | * }; 29 | */ 30 | 31 | /** 32 | * A prototype base for Connectors 33 | */ 34 | function Connection() { 35 | } 36 | 37 | /** 38 | * Add an event listener 39 | */ 40 | Connection.prototype.on = function(event, action) { 41 | if (!this._listeners) { 42 | this._listeners = {}; 43 | } 44 | if (!this._listeners[event]) { 45 | this._listeners[event] = []; 46 | } 47 | this._listeners[event].push(action); 48 | }; 49 | 50 | /** 51 | * Remove an event listener 52 | */ 53 | Connection.prototype.off = function(event, action) { 54 | if (!this._listeners) { 55 | return; 56 | } 57 | var actions = this._listeners[event]; 58 | if (actions) { 59 | this._listeners[event] = actions.filter(function(li) { 60 | return li !== action; 61 | }.bind(this)); 62 | } 63 | }; 64 | 65 | /** 66 | * Emit an event. For internal use only 67 | */ 68 | Connection.prototype._emit = function(event, data) { 69 | if (this._listeners == null || this._listeners[event] == null) { 70 | return; 71 | } 72 | 73 | var listeners = this._listeners[event]; 74 | listeners.forEach(function(listener) { 75 | // Fail fast if we mutate the list of listeners while emitting 76 | if (listeners !== this._listeners[event]) { 77 | throw new Error('Listener list changed while emitting'); 78 | } 79 | 80 | try { 81 | listener.call(null, data); 82 | } 83 | catch (ex) { 84 | console.log('Error calling listeners to ' + event); 85 | console.error(ex); 86 | } 87 | }.bind(this)); 88 | }; 89 | 90 | /** 91 | * Send a message to the other side of the connection 92 | */ 93 | Connection.prototype.call = function(feature, data) { 94 | throw new Error('Not implemented'); 95 | }; 96 | 97 | /** 98 | * Disconnecting a Connection destroys the resources it holds. There is no 99 | * common route back to being connected once this has been called 100 | */ 101 | Connection.prototype.disconnect = function() { 102 | return Promise.resolve(); 103 | }; 104 | 105 | exports.Connection = Connection; 106 | 107 | /** 108 | * A manager for the registered Connectors 109 | */ 110 | function Connectors() { 111 | // This is where we cache the connectors that we know about 112 | this._registered = {}; 113 | } 114 | 115 | /** 116 | * Add a new connector to the cache 117 | */ 118 | Connectors.prototype.add = function(connector) { 119 | this._registered[connector.name] = connector; 120 | }; 121 | 122 | /** 123 | * Remove an existing connector from the cache 124 | */ 125 | Connectors.prototype.remove = function(connector) { 126 | var name = typeof connector === 'string' ? connector : connector.name; 127 | delete this._registered[name]; 128 | }; 129 | 130 | /** 131 | * Get access to the list of known connectors 132 | */ 133 | Connectors.prototype.getAll = function() { 134 | return Object.keys(this._registered).map(function(name) { 135 | return this._registered[name]; 136 | }.bind(this)); 137 | }; 138 | 139 | var defaultConnectorName; 140 | 141 | /** 142 | * Get access to a connector by name. If name is undefined then first try to 143 | * use the same connector that we used last time, and if there was no last 144 | * time, then just use the first registered connector as a default. 145 | */ 146 | Connectors.prototype.get = function(name) { 147 | if (name == null) { 148 | name = (defaultConnectorName == null) ? 149 | Object.keys(this._registered)[0] : 150 | defaultConnectorName; 151 | } 152 | 153 | defaultConnectorName = name; 154 | return this._registered[name]; 155 | }; 156 | 157 | exports.Connectors = Connectors; 158 | -------------------------------------------------------------------------------- /lib/gcli/connectors/front.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * Asynchronous construction. Use GcliFront(); 21 | * @private 22 | */ 23 | function GcliFront() { 24 | throw new Error('Use GcliFront.create().then(front => ...)'); 25 | } 26 | 27 | /** 28 | * 29 | */ 30 | GcliFront.create = function(connector, url) { 31 | return connector.connect(url).then(function(connection) { 32 | var front = Object.create(GcliFront.prototype); 33 | return front._init(connection); 34 | }); 35 | }; 36 | 37 | /** 38 | * Asynchronous construction. Use GcliFront(); 39 | * @private 40 | */ 41 | GcliFront.prototype._init = function(connection) { 42 | this.connection = connection; 43 | return this; 44 | }; 45 | 46 | GcliFront.prototype.on = function(eventName, action) { 47 | this.connection.on(eventName, action); 48 | }; 49 | 50 | GcliFront.prototype.off = function(eventName, action) { 51 | this.connection.off(eventName, action); 52 | }; 53 | 54 | 55 | GcliFront.prototype.specs = function() { 56 | var data = { 57 | }; 58 | return this.connection.call('specs', data); 59 | }; 60 | 61 | GcliFront.prototype.execute = function(typed) { 62 | var data = { 63 | typed: typed 64 | }; 65 | return this.connection.call('execute', data); 66 | }; 67 | 68 | GcliFront.prototype.parseFile = function(typed, filetype, existing, matches) { 69 | var data = { 70 | typed: typed, 71 | filetype: filetype, 72 | existing: existing, 73 | matches: matches 74 | }; 75 | return this.connection.call('parseFile', data); 76 | }; 77 | 78 | GcliFront.prototype.parseType = function(typed, paramName) { 79 | var data = { 80 | typed: typed, 81 | paramName: paramName 82 | }; 83 | return this.connection.call('parseType', data); 84 | }; 85 | 86 | GcliFront.prototype.nudgeType = function(typed, by, paramName) { 87 | var data = { 88 | typed: typed, 89 | by: by, 90 | paramName: paramName 91 | }; 92 | return this.connection.call('nudgeType', by, data); 93 | }; 94 | 95 | GcliFront.prototype.getSelectionLookup = function(commandName, paramName) { 96 | var data = { 97 | commandName: commandName, 98 | paramName: paramName 99 | }; 100 | return this.connection.call('getSelectionLookup', data); 101 | }; 102 | 103 | GcliFront.prototype.system = function(cmd, args, cwd, env) { 104 | var data = { 105 | cmd: cmd, 106 | args: args, 107 | cwd: cwd, 108 | env: env 109 | }; 110 | return this.connection.call('system', data); 111 | }; 112 | 113 | exports.GcliFront = GcliFront; 114 | -------------------------------------------------------------------------------- /lib/gcli/connectors/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var createSystem = require('../system').createSystem; 20 | var connectFront = require('../system').connectFront; 21 | var GcliFront = require('./front').GcliFront; 22 | 23 | // Patch-up IE9 24 | require('../util/legacy'); 25 | 26 | /** 27 | * Connect to a remote system and setup the commands/types/converters etc needed 28 | * to make it all work 29 | */ 30 | exports.createSystem = function(options) { 31 | options = options || {}; 32 | 33 | var system = createSystem(); 34 | 35 | // The items that are always needed on the client 36 | var items = [ 37 | require('../items/basic').items, 38 | require('../items/ui').items, 39 | require('../items/remote').items, 40 | // The context command makes no sense on the server 41 | require('../commands/context').items, 42 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 43 | system.addItems(items); 44 | 45 | // These are the commands stored on the remote side that have converters which 46 | // we'll need to present the data. Ideally front.specs() would transfer these, 47 | // that doesn't happen yet so we add them manually 48 | var requiredConverters = [ 49 | require('../cli').items, 50 | require('../commands/clear').items, 51 | require('../commands/connect').items, 52 | require('../commands/global').items, 53 | require('../commands/help').items, 54 | require('../commands/intro').items, 55 | require('../commands/lang').items, 56 | require('../commands/preflist').items, 57 | require('../commands/pref').items, 58 | require('../commands/test').items, 59 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []) 60 | .filter(function(item) { return item.item === 'converter'; }); 61 | system.addItems(requiredConverters); 62 | 63 | var connector = system.connectors.get(options.method); 64 | return GcliFront.create(connector, options.url).then(function(front) { 65 | return connectFront(system, front).then(function() { 66 | return system; 67 | }); 68 | }); 69 | }; 70 | -------------------------------------------------------------------------------- /lib/gcli/connectors/protocol.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a quick and dirty stub that allows us to write code in remoted.js 21 | * that looks like gcli.js 22 | */ 23 | exports.method = function(func, spec) { 24 | // An array of strings, being the names of the parameters 25 | var argSpecs = []; 26 | if (spec.request != null) { 27 | Object.keys(spec.request).forEach(function(name) { 28 | var arg = spec.request[name]; 29 | argSpecs[arg.index] = name; 30 | }); 31 | } 32 | 33 | return function(data) { 34 | var args = (data == null) ? 35 | [] : 36 | argSpecs.map(function(name) { return data[name]; }); 37 | return func.apply(this, args); 38 | }; 39 | }; 40 | 41 | var Arg = exports.Arg = function(index, type) { 42 | if (this == null) { 43 | return new Arg(index, type); 44 | } 45 | 46 | this.index = index; 47 | this.type = type; 48 | }; 49 | 50 | var RetVal = exports.RetVal = function(type) { 51 | if (this == null) { 52 | return new RetVal(type); 53 | } 54 | 55 | this.type = type; 56 | }; 57 | -------------------------------------------------------------------------------- /lib/gcli/connectors/websocket.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var Connection = require('./connectors').Connection; 20 | 21 | exports.items = [ 22 | { 23 | // Communicate with a remote server over XMLHttpRequest 24 | item: 'connector', 25 | name: 'websocket', 26 | 27 | connect: function(url) { 28 | url = url || exports.document.location.origin; 29 | 30 | if (connections[url] == null) { 31 | connections[url] = new Promise(function(resolve, reject) { 32 | var io = require('socket.io-client'); 33 | var socket = io.connect(url); 34 | var wsc = new WebsocketConnection(socket, url); 35 | 36 | // What to do when a reply is received 37 | socket.on('reply', wsc.onReply); 38 | 39 | socket.on('event', wsc.onEvent); 40 | 41 | socket.on('connected', function() { 42 | resolve(wsc); 43 | }); 44 | 45 | socket.on('connect_error', function() { 46 | reject(wsc); 47 | }); 48 | }.bind(this)); 49 | } 50 | return connections[url]; 51 | } 52 | } 53 | ]; 54 | 55 | /** 56 | * We only connect once to each URL 57 | */ 58 | var connections = {}; 59 | 60 | /** 61 | * The ability to add functionality by adding a new script tag is specific to 62 | * a browser, so this code is not going to work in NodeJS/Firefox etc. 63 | * We export the document that we are using so multi-frame environments can 64 | * update the default document 65 | */ 66 | exports.document = typeof document !== 'undefined' ? document : undefined; 67 | 68 | /** 69 | * Handle a 'session' in which we make a number of calls 70 | */ 71 | function WebsocketConnection(socket, url) { 72 | this.socket = socket; 73 | this.url = url; 74 | 75 | this.deferreds = {}; 76 | this.nextRequestId = 0; 77 | 78 | this.onReply = this.onReply.bind(this); 79 | this.onEvent = this.onEvent.bind(this); 80 | } 81 | 82 | WebsocketConnection.prototype = Object.create(Connection.prototype); 83 | 84 | /** 85 | * Connect a websocket reply to the request that caused it 86 | */ 87 | WebsocketConnection.prototype.onReply = function(res) { 88 | var deferred = this.deferreds[res.id]; 89 | if (deferred == null) { 90 | throw new Error('Unknown id \'' + res.id + '\''); 91 | } 92 | 93 | if (res.reply) { 94 | deferred.resolve(res.reply); 95 | } 96 | else { 97 | deferred.reject(res.exception); 98 | } 99 | 100 | delete this.deferreds[res.id]; 101 | }; 102 | 103 | /** 104 | * Connect a websocket reply to the request that caused it 105 | */ 106 | WebsocketConnection.prototype.onEvent = function(res) { 107 | this._emit(res.name, res.data); 108 | }; 109 | 110 | /** 111 | * Kill this connection 112 | */ 113 | WebsocketConnection.prototype.disconnect = function() { 114 | Object.keys(this.deferreds).forEach(function(id) { 115 | this.deferreds[id].reject('Disconnected'); 116 | }.bind(this)); 117 | 118 | return Promise.resolve(undefined); 119 | }; 120 | 121 | /** 122 | * Initiate a websocket call using socket.io 123 | * @param command The name of the exposed feature. See server.js:remoted for 124 | * the remoted function 125 | * @param data The block of data to pass to the exposed feature. See the docs 126 | * for the exposed feature for what properties are required 127 | * @return A promise of the data returned by the remote feature 128 | */ 129 | WebsocketConnection.prototype.call = function(command, data) { 130 | return new Promise(function(resolve, reject) { 131 | var id = this.nextRequestId++; 132 | this.deferreds[id] = { resolve: resolve, reject: reject }; 133 | 134 | this.socket.emit(command, { id: id, data: data }); 135 | }.bind(this)); 136 | }; 137 | -------------------------------------------------------------------------------- /lib/gcli/connectors/websocketserver.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var socketio = require('socket.io'); 4 | 5 | var util = require('../util/util'); 6 | var cli = require('../cli'); 7 | var Remoter = require('./remoted').Remoter; 8 | 9 | /** 10 | * Start a web-socket server from an existing express server 11 | */ 12 | exports.init = function(server, context) { 13 | // To debug socket.io: 14 | // DEBUG=* node yourfile.js 15 | // or in the browser: 16 | // localStorage.debug='*'; 17 | // And then filter by the scopes you’re interested in. 18 | // You can use , to separate them. 19 | var io = socketio.listen(server); 20 | exports.useSocket(io, context); 21 | }; 22 | 23 | /** 24 | * Link to an existing web-socket server 25 | */ 26 | exports.useSocket = function(io, context) { 27 | io.sockets.on('connection', function(socket) { 28 | // Tell the browser that we're up and running 29 | socket.emit('connected'); 30 | 31 | var requisition = cli.getMapping(context).requisition; 32 | var remoter = new Remoter(requisition); 33 | 34 | remoter.addListener(function(name, data) { 35 | // console.log('EMIT ' + name + ' ' + debugStr(data, 30)); 36 | socket.emit('event', { name: name, data: data }); 37 | }); 38 | 39 | Object.keys(remoter.exposed).forEach(function(command) { 40 | socket.on(command, function(request) { 41 | // Handle errors from exceptions an promise rejections 42 | var onError = function(err) { 43 | console.log('SOCKET ' + command + 44 | '(' + debugStr(request.data, 30) + ') Exception'); 45 | util.errorHandler(err); 46 | 47 | socket.emit('reply', { 48 | id: request.id, 49 | exception: '' + err 50 | }); 51 | }; 52 | 53 | try { 54 | var func = remoter.exposed[command]; 55 | var reply = func.call(remoter, request.data); 56 | Promise.resolve(reply).then(function(data) { 57 | console.log('SOCKET ' + command + 58 | '(' + debugStr(request.data, 30) + ') → ' + 59 | debugStr(data, 20) + ')'); 60 | 61 | socket.emit('reply', { 62 | id: request.id, 63 | reply: data 64 | }); 65 | }, onError); 66 | } 67 | catch (ex) { 68 | onError(ex); 69 | } 70 | }); 71 | }); 72 | }); 73 | }; 74 | 75 | /** 76 | * Get a quick one line debug summary of an object 77 | */ 78 | function debugStr(obj) { 79 | var summary = JSON.stringify(obj) || ''; 80 | return summary.length > 40 ? summary.substr(0, 39) + '…' : summary; 81 | } 82 | -------------------------------------------------------------------------------- /lib/gcli/connectors/xhr.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var Connection = require('./connectors').Connection; 20 | 21 | exports.items = [ 22 | { 23 | // Communicate with a remote server over XMLHttpRequest 24 | item: 'connector', 25 | name: 'xhr', 26 | 27 | connect: function(url) { 28 | // TODO: store the url and use it 29 | // Ignore host and port for now. Assume local connection 30 | return Promise.resolve(new XhrConnection()); 31 | } 32 | } 33 | ]; 34 | 35 | /** 36 | * Make remote calls using XMLHttpRequest. 37 | * Note this connection method does not support server initiated events. Use 38 | * WebsocketConnection if you need that. 39 | */ 40 | function XhrConnection() { 41 | } 42 | 43 | XhrConnection.prototype = Object.create(Connection.prototype); 44 | 45 | /** 46 | * Initiate an XHR call 47 | * See server.js:remoted for details on the remoted functions 48 | * @param command The name of the exposed feature. 49 | * @param data The block of data to pass to the exposed feature 50 | * @return Promise of the data returned by the remote feature 51 | */ 52 | XhrConnection.prototype.call = function(command, data) { 53 | return new Promise(function(resolve, reject) { 54 | var xhr = new XMLHttpRequest(); 55 | xhr.open('POST', '/' + command, true); 56 | xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); 57 | 58 | xhr.onreadystatechange = function(event) { 59 | if (xhr.readyState === 4) { 60 | if (xhr.status >= 300 || xhr.status < 200) { 61 | reject({ 62 | data: xhr.responseText, 63 | code: xhr.status 64 | }); 65 | } 66 | else { 67 | var output = JSON.parse(xhr.responseText); 68 | resolve(output); 69 | } 70 | } 71 | }.bind(this); 72 | 73 | xhr.send(JSON.stringify(data)); 74 | }.bind(this)); 75 | }; 76 | -------------------------------------------------------------------------------- /lib/gcli/converters/basic.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | 21 | /** 22 | * Several converters are just data.toString inside a 'p' element 23 | */ 24 | function nodeFromDataToString(data, conversionContext) { 25 | var node = util.createElement(conversionContext.document, 'p'); 26 | node.textContent = data.toString(); 27 | return node; 28 | } 29 | 30 | exports.items = [ 31 | { 32 | item: 'converter', 33 | from: 'string', 34 | to: 'dom', 35 | exec: nodeFromDataToString 36 | }, 37 | { 38 | item: 'converter', 39 | from: 'number', 40 | to: 'dom', 41 | exec: nodeFromDataToString 42 | }, 43 | { 44 | item: 'converter', 45 | from: 'boolean', 46 | to: 'dom', 47 | exec: nodeFromDataToString 48 | }, 49 | { 50 | item: 'converter', 51 | from: 'undefined', 52 | to: 'dom', 53 | exec: function(data, conversionContext) { 54 | return util.createElement(conversionContext.document, 'span'); 55 | } 56 | }, 57 | { 58 | item: 'converter', 59 | from: 'json', 60 | to: 'view', 61 | exec: function(json, context) { 62 | var html = JSON.stringify(json, null, ' ').replace(/\n/g, '
'); 63 | return { 64 | html: '
' + html + '
' 65 | }; 66 | } 67 | }, 68 | { 69 | item: 'converter', 70 | from: 'number', 71 | to: 'string', 72 | exec: function(data) { return '' + data; } 73 | }, 74 | { 75 | item: 'converter', 76 | from: 'boolean', 77 | to: 'string', 78 | exec: function(data) { return '' + data; } 79 | }, 80 | { 81 | item: 'converter', 82 | from: 'undefined', 83 | to: 'string', 84 | exec: function(data) { return ''; } 85 | }, 86 | { 87 | item: 'converter', 88 | from: 'json', 89 | to: 'string', 90 | exec: function(json, conversionContext) { 91 | return JSON.stringify(json, null, ' '); 92 | } 93 | } 94 | ]; 95 | -------------------------------------------------------------------------------- /lib/gcli/converters/html.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | 21 | /** 22 | * 'html' means a string containing HTML markup. We use innerHTML to inject 23 | * this into a DOM which has security implications, so this module will not 24 | * be used in all implementations. 25 | */ 26 | exports.items = [ 27 | { 28 | item: 'converter', 29 | from: 'html', 30 | to: 'dom', 31 | exec: function(html, conversionContext) { 32 | var div = util.createElement(conversionContext.document, 'div'); 33 | div.innerHTML = html; 34 | return div; 35 | } 36 | }, 37 | { 38 | item: 'converter', 39 | from: 'html', 40 | to: 'string', 41 | exec: function(html, conversionContext) { 42 | var div = util.createElement(conversionContext.document, 'div'); 43 | div.innerHTML = html; 44 | return div.textContent; 45 | } 46 | } 47 | ]; 48 | -------------------------------------------------------------------------------- /lib/gcli/converters/terminal.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | 21 | /** 22 | * A 'terminal' object is a string or an array of strings, which are typically 23 | * the output from a shell command 24 | */ 25 | exports.items = [ 26 | { 27 | item: 'converter', 28 | from: 'terminal', 29 | to: 'dom', 30 | createTextArea: function(text, conversionContext) { 31 | var node = util.createElement(conversionContext.document, 'textarea'); 32 | node.classList.add('gcli-row-subterminal'); 33 | node.readOnly = true; 34 | node.textContent = text; 35 | return node; 36 | }, 37 | exec: function(data, conversionContext) { 38 | if (Array.isArray(data)) { 39 | var node = util.createElement(conversionContext.document, 'div'); 40 | data.forEach(function(member) { 41 | node.appendChild(this.createTextArea(member, conversionContext)); 42 | }); 43 | return node; 44 | } 45 | return this.createTextArea(data); 46 | } 47 | }, 48 | { 49 | item: 'converter', 50 | from: 'terminal', 51 | to: 'string', 52 | exec: function(data, conversionContext) { 53 | return Array.isArray(data) ? data.join('') : '' + data; 54 | } 55 | } 56 | ]; 57 | -------------------------------------------------------------------------------- /lib/gcli/fields/delegate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | var Field = require('./fields').Field; 21 | 22 | /** 23 | * A field that works with delegate types by delaying resolution until that 24 | * last possible time 25 | */ 26 | function DelegateField(type, options) { 27 | Field.call(this, type, options); 28 | this.options = options; 29 | 30 | this.element = util.createElement(this.document, 'div'); 31 | this.update(); 32 | 33 | this.onFieldChange = util.createEvent('DelegateField.onFieldChange'); 34 | } 35 | 36 | DelegateField.prototype = Object.create(Field.prototype); 37 | 38 | DelegateField.prototype.update = function() { 39 | var subtype = this.type.getType(this.options.requisition.executionContext); 40 | if (typeof subtype.parse !== 'function') { 41 | subtype = this.options.requisition.system.types.createType(subtype); 42 | } 43 | 44 | // It's not clear that we can compare subtypes in this way. 45 | // Perhaps we need a type.equals(...) function 46 | if (subtype === this.subtype) { 47 | return; 48 | } 49 | 50 | if (this.field) { 51 | this.field.destroy(); 52 | } 53 | 54 | this.subtype = subtype; 55 | var fields = this.options.requisition.system.fields; 56 | this.field = fields.get(subtype, this.options); 57 | 58 | util.clearElement(this.element); 59 | this.element.appendChild(this.field.element); 60 | }; 61 | 62 | DelegateField.claim = function(type, context) { 63 | return type.isDelegate ? Field.MATCH : Field.NO_MATCH; 64 | }; 65 | 66 | DelegateField.prototype.destroy = function() { 67 | this.element = undefined; 68 | this.options = undefined; 69 | if (this.field) { 70 | this.field.destroy(); 71 | } 72 | this.subtype = undefined; 73 | Field.prototype.destroy.call(this); 74 | }; 75 | 76 | DelegateField.prototype.setConversion = function(conversion) { 77 | this.field.setConversion(conversion); 78 | }; 79 | 80 | DelegateField.prototype.getConversion = function() { 81 | return this.field.getConversion(); 82 | }; 83 | 84 | Object.defineProperty(DelegateField.prototype, 'isImportant', { 85 | get: function() { 86 | return this.field.isImportant; 87 | }, 88 | enumerable: true 89 | }); 90 | 91 | /** 92 | * Exported items 93 | */ 94 | exports.items = [ 95 | DelegateField 96 | ]; 97 | -------------------------------------------------------------------------------- /lib/gcli/fields/selection.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | var Menu = require('../ui/menu').Menu; 21 | 22 | var Argument = require('../types/types').Argument; 23 | var Conversion = require('../types/types').Conversion; 24 | var Field = require('./fields').Field; 25 | 26 | /** 27 | * A field that allows selection of one of a number of options 28 | */ 29 | function SelectionField(type, options) { 30 | Field.call(this, type, options); 31 | 32 | this.arg = new Argument(); 33 | 34 | this.menu = new Menu({ 35 | document: this.document, 36 | maxPredictions: Conversion.maxPredictions 37 | }); 38 | this.element = this.menu.element; 39 | 40 | this.onFieldChange = util.createEvent('SelectionField.onFieldChange'); 41 | 42 | // i.e. Register this.onItemClick as the default action for a menu click 43 | this.menu.onItemClick.add(this.itemClicked, this); 44 | } 45 | 46 | SelectionField.prototype = Object.create(Field.prototype); 47 | 48 | SelectionField.claim = function(type, context) { 49 | if (context == null) { 50 | return Field.NO_MATCH; 51 | } 52 | return type.getType(context).hasPredictions ? Field.DEFAULT : Field.NO_MATCH; 53 | }; 54 | 55 | SelectionField.prototype.destroy = function() { 56 | this.menu.onItemClick.remove(this.itemClicked, this); 57 | this.menu.destroy(); 58 | this.menu = undefined; 59 | this.element = undefined; 60 | Field.prototype.destroy.call(this); 61 | }; 62 | 63 | SelectionField.prototype.setConversion = function(conversion) { 64 | this.arg = conversion.arg; 65 | this.setMessage(conversion.message); 66 | 67 | var context = this.requisition.executionContext; 68 | conversion.getPredictions(context).then(function(predictions) { 69 | var items = predictions.map(function(prediction) { 70 | // If the prediction value is an 'item' (that is an object with a name and 71 | // description) then use that, otherwise use the prediction itself, because 72 | // at least that has a name. 73 | return prediction.value && prediction.value.description ? 74 | prediction.value : 75 | prediction; 76 | }, this); 77 | if (this.menu != null) { 78 | this.menu.show(items, conversion.arg.text); 79 | } 80 | }.bind(this)).catch(util.errorHandler); 81 | }; 82 | 83 | SelectionField.prototype.itemClicked = function(ev) { 84 | var arg = new Argument(ev.name, '', ' '); 85 | var context = this.requisition.executionContext; 86 | 87 | this.type.parse(arg, context).then(function(conversion) { 88 | this.onFieldChange({ conversion: conversion }); 89 | this.setMessage(conversion.message); 90 | }.bind(this)).catch(util.errorHandler); 91 | }; 92 | 93 | SelectionField.prototype.getConversion = function() { 94 | // This tweaks the prefix/suffix of the argument to fit 95 | this.arg = this.arg.beget({ text: this.input.value }); 96 | return this.type.parse(this.arg, this.requisition.executionContext); 97 | }; 98 | 99 | /** 100 | * Allow the terminal to use RETURN to chose the current menu item when 101 | * it can't execute the command line 102 | * @return true if an item was 'clicked', false otherwise 103 | */ 104 | SelectionField.prototype.selectChoice = function() { 105 | var selected = this.menu.selected; 106 | if (selected == null) { 107 | return false; 108 | } 109 | 110 | this.itemClicked({ name: selected }); 111 | return true; 112 | }; 113 | 114 | Object.defineProperty(SelectionField.prototype, 'isImportant', { 115 | get: function() { 116 | return this.type.name !== 'command'; 117 | }, 118 | enumerable: true 119 | }); 120 | 121 | /** 122 | * Allow registration and de-registration. 123 | */ 124 | exports.items = [ SelectionField ]; 125 | -------------------------------------------------------------------------------- /lib/gcli/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /* 20 | * The intent of this module is to pull together all the parts needed to start 21 | * a command line to make it easier to get started. 22 | * 23 | * Basic usage is like this: 24 | * 25 | * var gcli = require('gcli/index'); 26 | * 27 | * // A system is a set of commands/types/etc that the command line uses 28 | * var system = gcli.createSystem(); 29 | * system.addItems(gcli.items); 30 | * system.addItems(gcli.commandItems); 31 | * system.addItems([ 32 | * // Your own commands go here 33 | * ]); 34 | * 35 | * // Create the UI 36 | * gcli.createTerminal(system).then(function(terminal) { 37 | * // Take any actions when the command line starts for example 38 | * terminal.language.showIntro(); 39 | * }); 40 | */ 41 | 42 | // Patch-up old browsers 43 | require('./util/legacy'); 44 | 45 | exports.createSystem = require('./system').createSystem; 46 | 47 | var Terminal = require('./ui/terminal').Terminal; 48 | exports.createTerminal = Terminal.create.bind(Terminal); 49 | 50 | /** 51 | * This is all the items we need for a basic GCLI (except for the commands) 52 | */ 53 | exports.items = [ 54 | require('./items/basic').items, 55 | require('./items/ui').items, 56 | require('./items/remote').items, 57 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 58 | 59 | exports.commandItems = require('./items/standard').items; 60 | -------------------------------------------------------------------------------- /lib/gcli/items/basic.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of the types and converters that will be needed in almost all 21 | * command lines. The types are listed in 2 sets because delegate and selection 22 | * are depended on by others, (e.g boolean depends on selection) and array is 23 | * built into cli.js parsing somewhat. 24 | * 25 | * Keeping this module small helps reduce bringing in unwanted dependencies. 26 | */ 27 | exports.items = [ 28 | require('../types/delegate').items, 29 | require('../types/selection').items, 30 | require('../types/array').items, 31 | 32 | require('../types/boolean').items, 33 | require('../types/command').items, 34 | require('../types/date').items, 35 | require('../types/javascript').items, 36 | require('../types/node').items, 37 | require('../types/number').items, 38 | require('../types/resource').items, 39 | require('../types/setting').items, 40 | require('../types/string').items, 41 | require('../types/union').items, 42 | require('../types/url').items, 43 | 44 | require('../converters/converters').items, 45 | require('../converters/basic').items, 46 | require('../converters/html').items, 47 | require('../converters/terminal').items, 48 | 49 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 50 | -------------------------------------------------------------------------------- /lib/gcli/items/demo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of demo commands. 21 | * 22 | * Keeping this module small helps reduce bringing in unwanted dependencies. 23 | */ 24 | exports.items = [ 25 | require('../commands/demo/alert').items, 26 | require('../commands/demo/demo').items, 27 | require('../commands/demo/echo').items, 28 | require('../commands/demo/sleep').items, 29 | 30 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 31 | -------------------------------------------------------------------------------- /lib/gcli/items/remote.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of the available connectors when linking to GCLIs together 21 | * 22 | * Keeping this module small helps reduce bringing in unwanted dependencies. 23 | */ 24 | exports.items = [ 25 | require('../connectors/websocket').items, 26 | require('../connectors/xhr').items, 27 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 28 | -------------------------------------------------------------------------------- /lib/gcli/items/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of the commands designed to run in nodejs / io.js. 21 | * 22 | * Keeping this module small helps reduce bringing in unwanted dependencies. 23 | */ 24 | exports.items = [ 25 | require('../types/file').items, 26 | 27 | require('../commands/server/exec').items, 28 | require('../commands/server/exit').items, 29 | require('../commands/server/firefox').items, 30 | require('../commands/server/orion').items, 31 | require('../commands/server/server').items, 32 | require('../commands/server/standard').items 33 | 34 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 35 | -------------------------------------------------------------------------------- /lib/gcli/items/standard.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of the standard commands that are likely to be in most 21 | * command lines. 22 | * 23 | * Keeping this module small helps reduce bringing in unwanted dependencies. 24 | */ 25 | exports.items = [ 26 | require('../cli').items, 27 | require('../commands/clear').items, 28 | require('../commands/connect').items, 29 | require('../commands/context').items, 30 | require('../commands/global').items, 31 | require('../commands/help').items, 32 | require('../commands/intro').items, 33 | require('../commands/lang').items, 34 | require('../commands/mocks').items, 35 | require('../commands/pref').items, 36 | require('../commands/preflist').items, 37 | require('../commands/test').items, 38 | 39 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 40 | -------------------------------------------------------------------------------- /lib/gcli/items/ui.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This is a list of the fields, settings and languages that we need to build 21 | * a user interface. 22 | * 23 | * Keeping this module small helps reduce bringing in unwanted dependencies. 24 | */ 25 | exports.items = [ 26 | require('../fields/fields').items, 27 | require('../fields/delegate').items, 28 | require('../fields/selection').items, 29 | 30 | require('../ui/focus').items, 31 | require('../ui/intro').items, 32 | 33 | require('../languages/command').items, 34 | require('../languages/javascript').items, 35 | 36 | ].reduce(function(prev, curr) { return prev.concat(curr); }, []); 37 | -------------------------------------------------------------------------------- /lib/gcli/languages/command.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
6 | :${output.typed} 10 |
11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /lib/gcli/languages/javascript.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var host = require('../util/host'); 20 | var prism = require('../util/prism').Prism; 21 | 22 | function isMultiline(text) { 23 | return typeof text === 'string' && text.indexOf('\n') > -1; 24 | } 25 | 26 | exports.items = [ 27 | { 28 | // Language implementation for Javascript 29 | item: 'language', 30 | name: 'javascript', 31 | prompt: '>', 32 | 33 | constructor: function(terminal) { 34 | this.document = terminal.document; 35 | this.focusManager = terminal.focusManager; 36 | 37 | this.updateHints(); 38 | }, 39 | 40 | destroy: function() { 41 | this.document = undefined; 42 | }, 43 | 44 | exec: function(input) { 45 | return this.evaluate(input).then(function(response) { 46 | var output = (response.exception != null) ? 47 | response.exception.class : 48 | response.output; 49 | 50 | var isSameString = typeof output === 'string' && 51 | input.substr(1, input.length - 2) === output; 52 | var isSameOther = typeof output !== 'string' && 53 | input === '' + output; 54 | 55 | // Place strings in quotes 56 | if (typeof output === 'string' && response.exception == null) { 57 | if (output.indexOf('\'') === -1) { 58 | output = '\'' + output + '\''; 59 | } 60 | else { 61 | output = output.replace(/\\/, '\\').replace(/"/, '"').replace(/'/, '\''); 62 | output = '"' + output + '"'; 63 | } 64 | } 65 | 66 | var line; 67 | if (isSameString || isSameOther || output === undefined) { 68 | line = input; 69 | } 70 | else if (isMultiline(output)) { 71 | line = input + '\n/*\n' + output + '\n*/'; 72 | } 73 | else { 74 | line = input + ' // ' + output; 75 | } 76 | 77 | var grammar = prism.languages[this.name]; 78 | return prism.highlight(line, grammar, this.name); 79 | }.bind(this)); 80 | }, 81 | 82 | evaluate: function(input) { 83 | return host.script.evaluate(input); 84 | } 85 | } 86 | ]; 87 | -------------------------------------------------------------------------------- /lib/gcli/test/automators/requisition.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var KeyEvent = require('../../util/util').KeyEvent; 20 | 21 | /** 22 | * See notes in helpers.checkOptions() 23 | */ 24 | exports.createRequisitionAutomator = function(requisition) { 25 | var cursor = { start: 0, end: 0 }; 26 | var typed = ''; 27 | var index = 0; 28 | 29 | var updateCursor = function() { 30 | cursor.start = typed.length; 31 | cursor.end = typed.length; 32 | }; 33 | 34 | var automator = { 35 | setInput: function(t) { 36 | typed = t; 37 | updateCursor(); 38 | return requisition.update(t); 39 | }, 40 | 41 | setCursor: function(c) { 42 | cursor.start = c.start; 43 | cursor.end = c.end; 44 | }, 45 | 46 | focus: function() { 47 | }, 48 | 49 | getInputState: function() { 50 | return { 51 | typed: typed, 52 | cursor: { start: cursor.start, end: cursor.end } 53 | }; 54 | }, 55 | 56 | getErrorMessage: function() { 57 | return requisition.getStatusMessage(); 58 | }, 59 | 60 | getCompleterTemplateData: function() { 61 | // See also language/command:getCompleterTemplateData 62 | return requisition.getStateData(cursor.start, index); 63 | }, 64 | 65 | fakeKey: function(keyCode) { 66 | if (keyCode === KeyEvent.DOM_VK_BACK_SPACE) { 67 | typed = typed.slice(0, -1); 68 | } 69 | if (keyCode === KeyEvent.DOM_VK_TAB) { 70 | return requisition.complete(cursor, index).then(function(updated) { 71 | // Abort UI changes if this UI update has been overtaken 72 | if (updated) { 73 | index = 0; 74 | } 75 | }); 76 | } 77 | if (keyCode === KeyEvent.DOM_VK_UP) { 78 | index++; 79 | } 80 | if (keyCode === KeyEvent.DOM_VK_DOWN) { 81 | index--; 82 | } 83 | if (keyCode === KeyEvent.DOM_VK_RETURN) { 84 | throw new Error('Fake DOM_VK_RETURN not supported'); 85 | } 86 | typed = requisition.toString(); 87 | updateCursor(); 88 | }, 89 | 90 | destroy: function() { 91 | } 92 | }; 93 | 94 | Object.defineProperty(automator, 'focusManager', { 95 | get: function() { return null; }, 96 | enumerable: true 97 | }); 98 | 99 | Object.defineProperty(automator, 'field', { 100 | get: function() { return null; }, 101 | enumerable: true 102 | }); 103 | 104 | return automator; 105 | }; 106 | -------------------------------------------------------------------------------- /lib/gcli/test/automators/terminal.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * See notes in helpers.checkOptions() 21 | */ 22 | exports.createTerminalAutomator = function(terminal) { 23 | var automator = { 24 | setInput: function(typed) { 25 | return terminal.setInput(typed); 26 | }, 27 | 28 | setCursor: function(cursor) { 29 | return terminal.language.setCursor(cursor); 30 | }, 31 | 32 | focus: function() { 33 | return terminal.focus(); 34 | }, 35 | 36 | getInputState: function() { 37 | return terminal.getInputState(); 38 | }, 39 | 40 | getErrorMessage: function() { 41 | return terminal.errorEle.textContent; 42 | }, 43 | 44 | getCompleterTemplateData: function() { 45 | return terminal.language.getCompleterTemplateData(); 46 | }, 47 | 48 | fakeKey: function(keyCode) { 49 | var fakeEvent = { 50 | keyCode: keyCode, 51 | preventDefault: function() { }, 52 | timeStamp: new Date().getTime() 53 | }; 54 | 55 | terminal.onKeyDown(fakeEvent); 56 | 57 | if (keyCode === 8 /*KeyEvent.DOM_VK_BACK_SPACE*/) { 58 | terminal.inputElement.value = terminal.inputElement.value.slice(0, -1); 59 | } 60 | 61 | return terminal.handleKeyUp(fakeEvent); 62 | } 63 | }; 64 | 65 | Object.defineProperty(automator, 'focusManager', { 66 | get: function() { return terminal.focusManager; }, 67 | enumerable: true 68 | }); 69 | 70 | Object.defineProperty(automator, 'field', { 71 | get: function() { return terminal.field; }, 72 | enumerable: true 73 | }); 74 | 75 | return automator; 76 | }; 77 | -------------------------------------------------------------------------------- /lib/gcli/test/mockDocument.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var usingMockDocument = false; 20 | 21 | /** 22 | * Registration and de-registration. 23 | */ 24 | exports.setup = function(requisition) { 25 | if (requisition.environment.window == null) { 26 | var jsdom = require('jsdom').jsdom; 27 | var document = jsdom('' + 28 | '' + 29 | '' + 30 | ' ' + 31 | ' ' + 32 | '' + 33 | '' + 34 | '
' + 35 | '' + 36 | ''); 37 | requisition.environment.window = document.defaultView; 38 | 39 | usingMockDocument = true; 40 | } 41 | }; 42 | 43 | exports.shutdown = function(requisition) { 44 | if (usingMockDocument) { 45 | requisition.environment.window = undefined; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /lib/gcli/test/mockSettings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.tempTBoolSpec = { 20 | name: 'tempTBool', 21 | type: 'boolean', 22 | description: 'temporary default true boolean', 23 | defaultValue: true 24 | }; 25 | exports.tempTBool = undefined; 26 | 27 | var tempFBoolSpec = { 28 | name: 'tempFBool', 29 | type: 'boolean', 30 | description: 'temporary default false boolean', 31 | defaultValue: false 32 | }; 33 | exports.tempFBool = undefined; 34 | 35 | var tempUStringSpec = { 36 | name: 'tempUString', 37 | type: 'string', 38 | description: 'temporary default undefined string' 39 | }; 40 | exports.tempUString = undefined; 41 | 42 | var tempNStringSpec = { 43 | name: 'tempNString', 44 | type: 'string', 45 | description: 'temporary default undefined string', 46 | defaultValue: null 47 | }; 48 | exports.tempNString = undefined; 49 | 50 | var tempQStringSpec = { 51 | name: 'tempQString', 52 | type: 'string', 53 | description: 'temporary default "q" string', 54 | defaultValue: 'q' 55 | }; 56 | exports.tempQString = undefined; 57 | 58 | var tempNumberSpec = { 59 | name: 'tempNumber', 60 | type: 'number', 61 | description: 'temporary number', 62 | defaultValue: 42 63 | }; 64 | exports.tempNumber = undefined; 65 | 66 | var tempSelectionSpec = { 67 | name: 'tempSelection', 68 | type: { name: 'selection', data: [ 'a', 'b', 'c' ] }, 69 | description: 'temporary selection', 70 | defaultValue: 'a' 71 | }; 72 | exports.tempSelection = undefined; 73 | 74 | /** 75 | * Registration and de-registration. 76 | */ 77 | exports.setup = function(system) { 78 | exports.tempTBool = system.settings.add(exports.tempTBoolSpec); 79 | exports.tempFBool = system.settings.add(tempFBoolSpec); 80 | exports.tempUString = system.settings.add(tempUStringSpec); 81 | exports.tempNString = system.settings.add(tempNStringSpec); 82 | exports.tempQString = system.settings.add(tempQStringSpec); 83 | exports.tempNumber = system.settings.add(tempNumberSpec); 84 | exports.tempSelection = system.settings.add(tempSelectionSpec); 85 | }; 86 | 87 | exports.shutdown = function(system) { 88 | system.settings.remove(exports.tempTBoolSpec); 89 | system.settings.remove(tempFBoolSpec); 90 | system.settings.remove(tempUStringSpec); 91 | system.settings.remove(tempNStringSpec); 92 | system.settings.remove(tempQStringSpec); 93 | system.settings.remove(tempNumberSpec); 94 | system.settings.remove(tempSelectionSpec); 95 | 96 | exports.tempTBool = undefined; 97 | exports.tempFBool = undefined; 98 | exports.tempUString = undefined; 99 | exports.tempNString = undefined; 100 | exports.tempQString = undefined; 101 | exports.tempNumber = undefined; 102 | exports.tempSelection = undefined; 103 | }; 104 | -------------------------------------------------------------------------------- /lib/gcli/test/suite.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | // We need to make sure GCLI is initialized before we begin testing it 20 | require('../index'); 21 | var examiner = require('../testharness/examiner'); 22 | 23 | exports.init = function(isNode) { 24 | // It's tempting to want to unify these strings and make addSuite() do the 25 | // call to require(), however that breaks the build system which looks for 26 | // the strings passed to require 27 | examiner.addSuite('testAsync', require('./testAsync')); 28 | examiner.addSuite('testCanon', require('./testCanon')); 29 | examiner.addSuite('testCli1', require('./testCli1')); 30 | examiner.addSuite('testCli2', require('./testCli2')); 31 | examiner.addSuite('testCompletion1', require('./testCompletion1')); 32 | examiner.addSuite('testCompletion2', require('./testCompletion2')); 33 | examiner.addSuite('testContext', require('./testContext')); 34 | examiner.addSuite('testDate', require('./testDate')); 35 | examiner.addSuite('testExec', require('./testExec')); 36 | examiner.addSuite('testFail', require('./testFail')); 37 | 38 | if (isNode) { 39 | examiner.addSuite('testFile', require('./testFile')); 40 | examiner.addSuite('testFileparser', require('./testFileparser')); 41 | examiner.addSuite('testFilesystem', require('./testFilesystem')); 42 | } 43 | 44 | examiner.addSuite('testFocus', require('./testFocus')); 45 | examiner.addSuite('testHelp', require('./testHelp')); 46 | examiner.addSuite('testHistory', require('./testHistory')); 47 | examiner.addSuite('testInputter', require('./testInputter')); 48 | examiner.addSuite('testIncomplete', require('./testIncomplete')); 49 | examiner.addSuite('testIntro', require('./testIntro')); 50 | examiner.addSuite('testJs', require('./testJs')); 51 | examiner.addSuite('testKeyboard1', require('./testKeyboard1')); 52 | examiner.addSuite('testKeyboard2', require('./testKeyboard2')); 53 | examiner.addSuite('testKeyboard3', require('./testKeyboard3')); 54 | examiner.addSuite('testKeyboard4', require('./testKeyboard4')); 55 | examiner.addSuite('testKeyboard5', require('./testKeyboard5')); 56 | examiner.addSuite('testMenu', require('./testMenu')); 57 | examiner.addSuite('testNode', require('./testNode')); 58 | examiner.addSuite('testPref1', require('./testPref1')); 59 | examiner.addSuite('testPref2', require('./testPref2')); 60 | examiner.addSuite('testRemoteXhr', require('./testRemoteXhr')); 61 | // Loading 2 different remoting systems at a time breaks 62 | //examiner.addSuite('testRemoteWs', require('./testRemoteWs')); 63 | examiner.addSuite('testResource', require('./testResource')); 64 | examiner.addSuite('testSettings', require('./testSettings')); 65 | examiner.addSuite('testShort', require('./testShort')); 66 | examiner.addSuite('testSpell', require('./testSpell')); 67 | examiner.addSuite('testSplit', require('./testSplit')); 68 | examiner.addSuite('testString', require('./testString')); 69 | examiner.addSuite('testTokenize', require('./testTokenize')); 70 | examiner.addSuite('testTooltip', require('./testTooltip')); 71 | examiner.addSuite('testTypes', require('./testTypes')); 72 | examiner.addSuite('testUnion', require('./testUnion')); 73 | examiner.addSuite('testUrl', require('./testUrl')); 74 | }; 75 | -------------------------------------------------------------------------------- /lib/gcli/test/testAsync.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testBasic = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | setup: 'tsslo', 25 | check: { 26 | input: 'tsslo', 27 | hints: 'w', 28 | markup: 'IIIII', 29 | cursor: 5, 30 | current: '__command', 31 | status: 'ERROR', 32 | predictions: ['tsslow'], 33 | unassigned: [ ] 34 | } 35 | }, 36 | { 37 | setup: 'tsslo', 38 | check: { 39 | input: 'tsslow ', 40 | hints: 'Shalom', 41 | markup: 'VVVVVVV', 42 | cursor: 7, 43 | current: 'hello', 44 | status: 'ERROR', 45 | predictions: [ 46 | 'Shalom', 'Namasté', 'Hallo', 'Dydd-da', 'Chào', 'Hej', 47 | 'Saluton', 'Sawubona' 48 | ], 49 | unassigned: [ ], 50 | args: { 51 | command: { name: 'tsslow' }, 52 | hello: { 53 | arg: '', 54 | status: 'INCOMPLETE' 55 | }, 56 | } 57 | } 58 | }, 59 | { 60 | setup: 'tsslow S', 61 | check: { 62 | input: 'tsslow S', 63 | hints: 'halom', 64 | markup: 'VVVVVVVI', 65 | cursor: 8, 66 | current: 'hello', 67 | status: 'ERROR', 68 | predictions: [ 'Shalom', 'Saluton', 'Sawubona', 'Namasté' ], 69 | unassigned: [ ], 70 | args: { 71 | command: { name: 'tsslow' }, 72 | hello: { 73 | arg: ' S', 74 | status: 'INCOMPLETE' 75 | }, 76 | } 77 | } 78 | }, 79 | { 80 | setup: 'tsslow S', 81 | check: { 82 | input: 'tsslow Shalom ', 83 | hints: '', 84 | markup: 'VVVVVVVVVVVVVV', 85 | cursor: 14, 86 | current: 'hello', 87 | status: 'VALID', 88 | predictions: [ 'Shalom' ], 89 | unassigned: [ ], 90 | args: { 91 | command: { name: 'tsslow' }, 92 | hello: { 93 | arg: ' Shalom ', 94 | status: 'VALID', 95 | message: '' 96 | }, 97 | } 98 | } 99 | } 100 | ]); 101 | }; 102 | -------------------------------------------------------------------------------- /lib/gcli/test/testFail.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testBasic = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | setup: 'tsfail reject', 25 | exec: { 26 | output: 'rejected promise', 27 | type: 'error', 28 | error: true 29 | } 30 | }, 31 | { 32 | setup: 'tsfail rejecttyped', 33 | exec: { 34 | output: '54', 35 | type: 'number', 36 | error: true 37 | } 38 | }, 39 | { 40 | setup: 'tsfail throwerror', 41 | exec: { 42 | output: /thrown error$/, 43 | type: 'error', 44 | error: true 45 | } 46 | }, 47 | { 48 | setup: 'tsfail throwstring', 49 | exec: { 50 | output: 'thrown string', 51 | type: 'error', 52 | error: true 53 | } 54 | }, 55 | { 56 | setup: 'tsfail noerror', 57 | exec: { 58 | output: 'no error', 59 | type: 'string', 60 | error: false 61 | } 62 | } 63 | ]); 64 | }; 65 | -------------------------------------------------------------------------------- /lib/gcli/test/testFileparser.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var fileparser = require('../util/fileparser'); 21 | 22 | var local = false; 23 | 24 | exports.testGetPredictor = function(options) { 25 | if (!options.isNode || !local) { 26 | assert.log('Skipping tests due to install differences.'); 27 | return; 28 | } 29 | 30 | var opts = { filetype: 'file', existing: 'yes' }; 31 | var predictor = fileparser.getPredictor('/usr/locl/bin/nmp', opts); 32 | return predictor().then(function(replies) { 33 | assert.is(replies[0].name, 34 | '/usr/local/bin/npm', 35 | 'predict npm'); 36 | }); 37 | }; 38 | -------------------------------------------------------------------------------- /lib/gcli/test/testFilesystem.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var helpers = require('./helpers'); 21 | var filesystem = require('../util/filesystem'); 22 | 23 | exports.testSplit = function(options) { 24 | if (!options.isNode) { 25 | return; 26 | } 27 | 28 | helpers.arrayIs(filesystem.split('', '/'), 29 | [ '.' ], 30 | 'split '); 31 | 32 | helpers.arrayIs(filesystem.split('a', '/'), 33 | [ 'a' ], 34 | 'split a'); 35 | 36 | helpers.arrayIs(filesystem.split('a/b/c', '/'), 37 | [ 'a', 'b', 'c' ], 38 | 'split a/b/c'); 39 | 40 | helpers.arrayIs(filesystem.split('/a/b/c/', '/'), 41 | [ 'a', 'b', 'c' ], 42 | 'split a/b/c'); 43 | 44 | helpers.arrayIs(filesystem.split('/a/b///c/', '/'), 45 | [ 'a', 'b', 'c' ], 46 | 'split a/b/c'); 47 | }; 48 | 49 | exports.testJoin = function(options) { 50 | if (!options.isNode) { 51 | return; 52 | } 53 | 54 | assert.is(filesystem.join('usr', 'local', 'bin'), 55 | 'usr/local/bin', 56 | 'join to usr/local/bin'); 57 | }; 58 | -------------------------------------------------------------------------------- /lib/gcli/test/testFocus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testBasic = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | name: 'exec setup', 25 | setup: function() { 26 | // Just check that we've got focus, and everything is clear 27 | helpers.focusInput(options); 28 | return helpers.setInput(options, 'echo hi'); 29 | }, 30 | check: { }, 31 | exec: { } 32 | }, 33 | { 34 | setup: 'tsn deep', 35 | check: { 36 | input: 'tsn deep', 37 | hints: ' down nested cmd', 38 | markup: 'IIIVIIII', 39 | cursor: 8, 40 | status: 'ERROR', 41 | outputState: 'false:default', 42 | tooltipState: 'false:default' 43 | } 44 | }, 45 | { 46 | setup: 'tsn deep', 47 | check: { 48 | input: 'tsn deep down nested cmd ', 49 | hints: '', 50 | markup: 'VVVVVVVVVVVVVVVVVVVVVVVVV', 51 | cursor: 25, 52 | status: 'VALID', 53 | outputState: 'false:default', 54 | tooltipState: 'false:default' 55 | } 56 | } 57 | ]); 58 | }; 59 | -------------------------------------------------------------------------------- /lib/gcli/test/testHistory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var History = require('../ui/history').History; 21 | 22 | exports.testSimpleHistory = function (options) { 23 | var history = new History({}); 24 | history.add('foo'); 25 | history.add('bar'); 26 | assert.is(history.backward(), 'bar'); 27 | assert.is(history.backward(), 'foo'); 28 | 29 | // Adding to the history again moves us back to the start of the history. 30 | history.add('quux'); 31 | assert.is(history.backward(), 'quux'); 32 | assert.is(history.backward(), 'bar'); 33 | assert.is(history.backward(), 'foo'); 34 | }; 35 | 36 | exports.testBackwardsPastIndex = function (options) { 37 | var history = new History({}); 38 | history.add('foo'); 39 | history.add('bar'); 40 | assert.is(history.backward(), 'bar'); 41 | assert.is(history.backward(), 'foo'); 42 | 43 | // Moving backwards past recorded history just keeps giving you the last 44 | // item. 45 | assert.is(history.backward(), 'foo'); 46 | }; 47 | 48 | exports.testForwardsPastIndex = function (options) { 49 | var history = new History({}); 50 | history.add('foo'); 51 | history.add('bar'); 52 | assert.is(history.backward(), 'bar'); 53 | assert.is(history.backward(), 'foo'); 54 | 55 | // Going forward through the history again. 56 | assert.is(history.forward(), 'bar'); 57 | 58 | // 'Present' time. 59 | assert.is(history.forward(), ''); 60 | 61 | // Going to the 'future' just keeps giving us the empty string. 62 | assert.is(history.forward(), ''); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/gcli/test/testInputter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var KeyEvent = require('../util/util').KeyEvent; 21 | 22 | var latestEvent; 23 | var latestData; 24 | 25 | var outputted = function(ev) { 26 | latestEvent = ev; 27 | 28 | ev.output.promise.then(function() { 29 | latestData = ev.output.data; 30 | }); 31 | }; 32 | 33 | 34 | exports.setup = function(options) { 35 | options.requisition.commandOutputManager.onOutput.add(outputted); 36 | }; 37 | 38 | exports.shutdown = function(options) { 39 | options.requisition.commandOutputManager.onOutput.remove(outputted); 40 | }; 41 | 42 | exports.testOutput = function(options) { 43 | latestEvent = undefined; 44 | latestData = undefined; 45 | 46 | var terminal = options.terminal; 47 | if (!terminal) { 48 | assert.log('Skipping testInputter.testOutput due to lack of terminal.'); 49 | return; 50 | } 51 | 52 | var focusManager = terminal.focusManager; 53 | 54 | terminal.setInput('tss'); 55 | 56 | var ev0 = { keyCode: KeyEvent.DOM_VK_RETURN }; 57 | terminal.onKeyDown(ev0); 58 | 59 | assert.is(terminal.getInputState().typed, 60 | 'tss', 61 | 'terminal should do nothing on RETURN keyDown'); 62 | assert.is(latestEvent, undefined, 'no events this test'); 63 | assert.is(latestData, undefined, 'no data this test'); 64 | 65 | var ev1 = { keyCode: KeyEvent.DOM_VK_RETURN }; 66 | return terminal.handleKeyUp(ev1).then(function() { 67 | assert.ok(latestEvent != null, 'events this test'); 68 | assert.is(latestData.name, 'tss', 'last command is tss'); 69 | 70 | assert.is(terminal.getInputState().typed, 71 | '', 72 | 'terminal should exec on RETURN keyUp'); 73 | 74 | assert.ok(focusManager._recentOutput, 'recent output happened'); 75 | 76 | var ev2 = { keyCode: KeyEvent.DOM_VK_F1 }; 77 | return terminal.handleKeyUp(ev2).then(function() { 78 | assert.ok(!focusManager._recentOutput, 'no recent output happened post F1'); 79 | assert.ok(focusManager._helpRequested, 'F1 = help'); 80 | 81 | var ev3 = { keyCode: KeyEvent.DOM_VK_ESCAPE }; 82 | return terminal.handleKeyUp(ev3).then(function() { 83 | assert.ok(!focusManager._helpRequested, 'ESCAPE = anti help'); 84 | }); 85 | }); 86 | 87 | }); 88 | }; 89 | -------------------------------------------------------------------------------- /lib/gcli/test/testIntro.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testIntroStatus = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | skipRemainingIf: function commandIntroMissing() { 25 | return options.requisition.system.commands.get('intro') == null; 26 | }, 27 | setup: 'intro', 28 | check: { 29 | typed: 'intro', 30 | markup: 'VVVVV', 31 | status: 'VALID', 32 | hints: '' 33 | } 34 | }, 35 | { 36 | setup: 'intro foo', 37 | check: { 38 | typed: 'intro foo', 39 | markup: 'VVVVVVEEE', 40 | status: 'ERROR', 41 | hints: '' 42 | } 43 | }, 44 | { 45 | setup: 'intro', 46 | check: { 47 | typed: 'intro', 48 | markup: 'VVVVV', 49 | status: 'VALID', 50 | hints: '' 51 | }, 52 | exec: { 53 | output: [ 54 | /command\s*line/, 55 | /help/, 56 | /F1/, 57 | /Escape/ 58 | ] 59 | } 60 | } 61 | ]); 62 | }; 63 | -------------------------------------------------------------------------------- /lib/gcli/test/testKeyboard1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var javascript = require('../types/javascript'); 20 | var helpers = require('./helpers'); 21 | 22 | exports.testSimple = function(options) { 23 | return helpers.audit(options, [ 24 | { 25 | setup: 'tsela', 26 | check: { input: 'tselarr ', cursor: 8 } 27 | }, 28 | { 29 | setup: 'tsn di', 30 | check: { input: 'tsn dif ', cursor: 8 } 31 | }, 32 | { 33 | setup: 'tsg a', 34 | check: { input: 'tsg aaa ', cursor: 8 } 35 | } 36 | ]); 37 | }; 38 | 39 | exports.testScript = function(options) { 40 | return helpers.audit(options, [ 41 | { 42 | skipRemainingIf: options.isRemote || 43 | options.requisition.system.commands.get('{') == null, 44 | setup: '{ wind', 45 | check: { input: '{ window' } 46 | }, 47 | { 48 | setup: '{ window.docum', 49 | check: { input: '{ window.document' } 50 | } 51 | ]); 52 | }; 53 | 54 | exports.testJsdom = function(options) { 55 | return helpers.audit(options, [ 56 | { 57 | skipIf: options.isRemote || 58 | options.requisition.system.commands.get('{') == null, 59 | setup: '{ window.document.titl', 60 | check: { input: '{ window.document.title ' } 61 | } 62 | ]); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/gcli/test/testKeyboard2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testIncr = function(options) { 22 | return helpers.audit(options, [ 23 | /* 24 | // We currently refuse to increment/decrement things with a non-valid 25 | // status which makes sense for many cases, and is a decent default. 26 | // However in theory we could do better, these tests are there for then 27 | { 28 | setup: 'tsu -70', 29 | check: { input: 'tsu -5' } 30 | }, 31 | { 32 | setup: 'tsu -7', 33 | check: { input: 'tsu -5' } 34 | }, 35 | { 36 | setup: 'tsu -6', 37 | check: { input: 'tsu -5' } 38 | }, 39 | */ 40 | { 41 | setup: 'tsu -5', 42 | check: { input: 'tsu -3' } 43 | }, 44 | { 45 | setup: 'tsu -4', 46 | check: { input: 'tsu -3' } 47 | }, 48 | { 49 | setup: 'tsu -3', 50 | check: { input: 'tsu 0' } 51 | }, 52 | { 53 | setup: 'tsu -2', 54 | check: { input: 'tsu 0' } 55 | }, 56 | { 57 | setup: 'tsu -1', 58 | check: { input: 'tsu 0' } 59 | }, 60 | { 61 | setup: 'tsu 0', 62 | check: { input: 'tsu 3' } 63 | }, 64 | { 65 | setup: 'tsu 1', 66 | check: { input: 'tsu 3' } 67 | }, 68 | { 69 | setup: 'tsu 2', 70 | check: { input: 'tsu 3' } 71 | }, 72 | { 73 | setup: 'tsu 3', 74 | check: { input: 'tsu 6' } 75 | }, 76 | { 77 | setup: 'tsu 4', 78 | check: { input: 'tsu 6' } 79 | }, 80 | { 81 | setup: 'tsu 5', 82 | check: { input: 'tsu 6' } 83 | }, 84 | { 85 | setup: 'tsu 6', 86 | check: { input: 'tsu 9' } 87 | }, 88 | { 89 | setup: 'tsu 7', 90 | check: { input: 'tsu 9' } 91 | }, 92 | { 93 | setup: 'tsu 8', 94 | check: { input: 'tsu 9' } 95 | }, 96 | { 97 | setup: 'tsu 9', 98 | check: { input: 'tsu 10' } 99 | }, 100 | { 101 | setup: 'tsu 10', 102 | check: { input: 'tsu 10' } 103 | } 104 | /* 105 | // See notes above 106 | { 107 | setup: 'tsu 100', 108 | check: { input: 'tsu 10' } 109 | } 110 | */ 111 | ]); 112 | }; 113 | -------------------------------------------------------------------------------- /lib/gcli/test/testKeyboard3.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testDecr = function(options) { 22 | return helpers.audit(options, [ 23 | /* 24 | // See notes at top of testIncr in testKeyboard2.js 25 | { 26 | setup: 'tsu -70', 27 | check: { input: 'tsu -5' } 28 | }, 29 | { 30 | setup: 'tsu -7', 31 | check: { input: 'tsu -5' } 32 | }, 33 | { 34 | setup: 'tsu -6', 35 | check: { input: 'tsu -5' } 36 | }, 37 | */ 38 | { 39 | setup: 'tsu -5', 40 | check: { input: 'tsu -5' } 41 | }, 42 | { 43 | setup: 'tsu -4', 44 | check: { input: 'tsu -5' } 45 | }, 46 | { 47 | setup: 'tsu -3', 48 | check: { input: 'tsu -5' } 49 | }, 50 | { 51 | setup: 'tsu -2', 52 | check: { input: 'tsu -3' } 53 | }, 54 | { 55 | setup: 'tsu -1', 56 | check: { input: 'tsu -3' } 57 | }, 58 | { 59 | setup: 'tsu 0', 60 | check: { input: 'tsu -3' } 61 | }, 62 | { 63 | setup: 'tsu 1', 64 | check: { input: 'tsu 0' } 65 | }, 66 | { 67 | setup: 'tsu 2', 68 | check: { input: 'tsu 0' } 69 | }, 70 | { 71 | setup: 'tsu 3', 72 | check: { input: 'tsu 0' } 73 | }, 74 | { 75 | setup: 'tsu 4', 76 | check: { input: 'tsu 3' } 77 | }, 78 | { 79 | setup: 'tsu 5', 80 | check: { input: 'tsu 3' } 81 | }, 82 | { 83 | setup: 'tsu 6', 84 | check: { input: 'tsu 3' } 85 | }, 86 | { 87 | setup: 'tsu 7', 88 | check: { input: 'tsu 6' } 89 | }, 90 | { 91 | setup: 'tsu 8', 92 | check: { input: 'tsu 6' } 93 | }, 94 | { 95 | setup: 'tsu 9', 96 | check: { input: 'tsu 6' } 97 | }, 98 | { 99 | setup: 'tsu 10', 100 | check: { input: 'tsu 9' } 101 | } 102 | /* 103 | // See notes at top of testIncr 104 | { 105 | setup: 'tsu 100', 106 | check: { input: 'tsu 9' } 107 | } 108 | */ 109 | ]); 110 | }; 111 | -------------------------------------------------------------------------------- /lib/gcli/test/testKeyboard5.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testCompleteDown = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | setup: 'tsn e', 25 | check: { input: 'tsn exte ' } 26 | }, 27 | { 28 | setup: 'tsn e', 29 | check: { input: 'tsn ext ' } 30 | }, 31 | { 32 | setup: 'tsn e', 33 | check: { input: 'tsn extend ' } 34 | }, 35 | { 36 | setup: 'tsn e', 37 | check: { input: 'tsn exten ' } 38 | }, 39 | { 40 | setup: 'tsn e', 41 | check: { input: 'tsn exte ' } 42 | }, 43 | { 44 | setup: 'tsn e', 45 | check: { input: 'tsn ext ' } 46 | } 47 | ]); 48 | }; 49 | -------------------------------------------------------------------------------- /lib/gcli/test/testKeyboard6.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testCompleteUp = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | setup: 'tsn e', 25 | check: { input: 'tsn extend ' } 26 | }, 27 | { 28 | setup: 'tsn e', 29 | check: { input: 'tsn exten ' } 30 | }, 31 | { 32 | setup: 'tsn e', 33 | check: { input: 'tsn exte ' } 34 | }, 35 | { 36 | setup: 'tsn e', 37 | check: { input: 'tsn ext ' } 38 | }, 39 | { 40 | setup: 'tsn e', 41 | check: { input: 'tsn extend ' } 42 | }, 43 | { 44 | setup: 'tsn e', 45 | check: { input: 'tsn exten ' } 46 | }, 47 | { 48 | setup: 'tsn e', 49 | check: { input: 'tsn exte ' } 50 | }, 51 | { 52 | setup: 'tsn e', 53 | check: { input: 'tsn ext ' } 54 | } 55 | ]); 56 | }; 57 | -------------------------------------------------------------------------------- /lib/gcli/test/testMenu.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testOptions = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | setup: 'tslong', 25 | check: { 26 | input: 'tslong', 27 | markup: 'VVVVVV', 28 | status: 'ERROR', 29 | hints: ' [options]', 30 | args: { 31 | msg: { value: undefined, status: 'INCOMPLETE' }, 32 | num: { value: undefined, status: 'VALID' }, 33 | sel: { value: undefined, status: 'VALID' }, 34 | bool: { value: false, status: 'VALID' }, 35 | bool2: { value: false, status: 'VALID' }, 36 | sel2: { value: undefined, status: 'VALID' }, 37 | num2: { value: undefined, status: 'VALID' } 38 | } 39 | } 40 | } 41 | ]); 42 | }; 43 | -------------------------------------------------------------------------------- /lib/gcli/test/testPref1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var helpers = require('./helpers'); 20 | 21 | exports.testPrefShowStatus = function(options) { 22 | return helpers.audit(options, [ 23 | { 24 | skipRemainingIf: options.requisition.system.commands.get('pref') == null, 25 | setup: 'pref s', 26 | check: { 27 | typed: 'pref s', 28 | hints: 'et', 29 | markup: 'IIIIVI', 30 | status: 'ERROR' 31 | } 32 | }, 33 | { 34 | setup: 'pref show', 35 | check: { 36 | typed: 'pref show', 37 | hints: ' ', 38 | markup: 'VVVVVVVVV', 39 | status: 'ERROR' 40 | } 41 | }, 42 | { 43 | setup: 'pref show ', 44 | check: { 45 | typed: 'pref show ', 46 | hints: 'eagerHelper', 47 | markup: 'VVVVVVVVVV', 48 | status: 'ERROR' 49 | } 50 | }, 51 | { 52 | setup: 'pref show tempTBo', 53 | check: { 54 | typed: 'pref show tempTBo', 55 | hints: 'ol', 56 | markup: 'VVVVVVVVVVIIIIIII', 57 | status: 'ERROR' 58 | } 59 | }, 60 | { 61 | setup: 'pref show tempTBool', 62 | check: { 63 | typed: 'pref show tempTBool', 64 | markup: 'VVVVVVVVVVVVVVVVVVV', 65 | status: 'VALID', 66 | hints: '' 67 | } 68 | }, 69 | { 70 | setup: 'pref show tempTBool 4', 71 | check: { 72 | typed: 'pref show tempTBool 4', 73 | markup: 'VVVVVVVVVVVVVVVVVVVVE', 74 | status: 'ERROR', 75 | hints: '' 76 | } 77 | }, 78 | { 79 | setup: 'pref show tempNumber 4', 80 | check: { 81 | typed: 'pref show tempNumber 4', 82 | markup: 'VVVVVVVVVVVVVVVVVVVVVE', 83 | status: 'ERROR', 84 | hints: '' 85 | } 86 | } 87 | ]); 88 | }; 89 | 90 | exports.testPrefSetStatus = function(options) { 91 | return helpers.audit(options, [ 92 | { 93 | skipRemainingIf: options.requisition.system.commands.get('pref') == null, 94 | setup: 'pref s', 95 | check: { 96 | typed: 'pref s', 97 | hints: 'et', 98 | markup: 'IIIIVI', 99 | status: 'ERROR' 100 | } 101 | }, 102 | { 103 | setup: 'pref set', 104 | check: { 105 | typed: 'pref set', 106 | hints: ' ', 107 | markup: 'VVVVVVVV', 108 | status: 'ERROR' 109 | } 110 | }, 111 | { 112 | setup: 'pref xxx', 113 | check: { 114 | typed: 'pref xxx', 115 | markup: 'IIIIVIII', 116 | status: 'ERROR' 117 | } 118 | }, 119 | { 120 | setup: 'pref set ', 121 | check: { 122 | typed: 'pref set ', 123 | hints: 'eagerHelper ', 124 | markup: 'VVVVVVVVV', 125 | status: 'ERROR' 126 | } 127 | }, 128 | { 129 | setup: 'pref set tempTBo', 130 | check: { 131 | typed: 'pref set tempTBo', 132 | hints: 'ol ', 133 | markup: 'VVVVVVVVVIIIIIII', 134 | status: 'ERROR' 135 | } 136 | }, 137 | { 138 | skipIf: options.isRemote, 139 | setup: 'pref set tempTBool 4', 140 | check: { 141 | typed: 'pref set tempTBool 4', 142 | markup: 'VVVVVVVVVVVVVVVVVVVE', 143 | status: 'ERROR', 144 | hints: '' 145 | } 146 | }, 147 | { 148 | setup: 'pref set tempNumber 4', 149 | check: { 150 | typed: 'pref set tempNumber 4', 151 | markup: 'VVVVVVVVVVVVVVVVVVVVV', 152 | status: 'VALID', 153 | hints: '' 154 | } 155 | } 156 | ]); 157 | }; 158 | -------------------------------------------------------------------------------- /lib/gcli/test/testPref2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var helpers = require('./helpers'); 21 | var mockSettings = require('./mockSettings'); 22 | 23 | exports.testPrefExec = function(options) { 24 | if (options.requisition.system.commands.get('pref') == null) { 25 | assert.log('Skipping test; missing pref command.'); 26 | return; 27 | } 28 | 29 | if (options.isRemote) { 30 | assert.log('Skipping test which assumes local settings.'); 31 | return; 32 | } 33 | 34 | assert.is(mockSettings.tempNumber.value, 42, 'set to 42'); 35 | 36 | return helpers.audit(options, [ 37 | { 38 | // Delegated remote types can't transfer value types so we only test for 39 | // the value of 'value' when we're local 40 | skipIf: options.isRemote, 41 | setup: 'pref set tempNumber 4', 42 | check: { 43 | setting: { value: mockSettings.tempNumber }, 44 | args: { value: { value: 4 } } 45 | } 46 | }, 47 | { 48 | setup: 'pref set tempNumber 4', 49 | check: { 50 | input: 'pref set tempNumber 4', 51 | hints: '', 52 | markup: 'VVVVVVVVVVVVVVVVVVVVV', 53 | cursor: 21, 54 | current: 'value', 55 | status: 'VALID', 56 | predictions: [ ], 57 | unassigned: [ ], 58 | args: { 59 | command: { name: 'pref set' }, 60 | setting: { 61 | arg: ' tempNumber', 62 | status: 'VALID', 63 | message: '' 64 | }, 65 | value: { 66 | arg: ' 4', 67 | status: 'VALID', 68 | message: '' 69 | } 70 | } 71 | }, 72 | exec: { 73 | output: '' 74 | }, 75 | post: function() { 76 | assert.is(mockSettings.tempNumber.value, 4, 'set to 4'); 77 | } 78 | }, 79 | { 80 | setup: 'pref reset tempNumber', 81 | check: { 82 | args: { 83 | command: { name: 'pref reset' }, 84 | setting: { value: mockSettings.tempNumber } 85 | } 86 | }, 87 | exec: { 88 | output: '' 89 | }, 90 | post: function() { 91 | assert.is(mockSettings.tempNumber.value, 42, 'reset to 42'); 92 | } 93 | }, 94 | { 95 | skipRemainingIf: function commandPrefListMissing() { 96 | return options.requisition.system.commands.get('pref list') == null; 97 | }, 98 | setup: 'pref list tempNum', 99 | check: { 100 | args: { 101 | command: { name: 'pref list' }, 102 | search: { value: 'tempNum' } 103 | } 104 | }, 105 | exec: { 106 | output: /tempNum/ 107 | } 108 | }, 109 | ]); 110 | }; 111 | -------------------------------------------------------------------------------- /lib/gcli/test/testSpell.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Panagiotis Astithas 3 | * Permission to use, copy, modify, and distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | 'use strict'; 17 | 18 | var assert = require('../testharness/assert'); 19 | var spell = require('../util/spell'); 20 | 21 | exports.testSpellerSimple = function(options) { 22 | var alternatives = [ 23 | 'window', 'document', 'InstallTrigger', 'requirejs', 'require','define', 24 | 'console', 'location', 'constructor', 'getInterface', 'external', 'sidebar' 25 | ]; 26 | 27 | assert.is(spell.correct('document', alternatives), 'document'); 28 | assert.is(spell.correct('documen', alternatives), 'document'); 29 | assert.is(spell.correct('ocument', alternatives), 'document'); 30 | assert.is(spell.correct('odcument', alternatives), 'document'); 31 | 32 | assert.is(spell.correct('=========', alternatives), undefined); 33 | }; 34 | 35 | exports.testRank = function(options) { 36 | var distances = spell.rank('fred', [ 'banana', 'fred', 'ed', 'red', 'FRED' ]); 37 | 38 | assert.is(distances.length, 5, 'rank length'); 39 | 40 | assert.is(distances[0].name, 'fred', 'fred name #0'); 41 | assert.is(distances[1].name, 'FRED', 'FRED name #1'); 42 | assert.is(distances[2].name, 'red', 'red name #2'); 43 | assert.is(distances[3].name, 'ed', 'ed name #3'); 44 | assert.is(distances[4].name, 'banana', 'banana name #4'); 45 | 46 | assert.is(distances[0].dist, 0, 'fred dist 0'); 47 | assert.is(distances[1].dist, 4, 'FRED dist 4'); 48 | assert.is(distances[2].dist, 10, 'red dist 10'); 49 | assert.is(distances[3].dist, 20, 'ed dist 20'); 50 | assert.is(distances[4].dist, 100, 'banana dist 100'); 51 | }; 52 | 53 | exports.testRank2 = function(options) { 54 | var distances = spell.rank('caps', [ 'CAPS', 'false' ]); 55 | assert.is(JSON.stringify(distances), 56 | '[{"name":"CAPS","dist":4},{"name":"false","dist":50}]', 57 | 'spell.rank("caps", [ "CAPS", "false" ]'); 58 | }; 59 | 60 | exports.testDistancePrefix = function(options) { 61 | assert.is(spell.distancePrefix('fred', 'freddy'), 0, 'distancePrefix fred'); 62 | assert.is(spell.distancePrefix('FRED', 'freddy'), 4, 'distancePrefix FRED'); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/gcli/test/testSplit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | 21 | var cli = require('../cli'); 22 | 23 | exports.testSplitSimple = function(options) { 24 | var args = cli.tokenize('s'); 25 | options.requisition._split(args); 26 | assert.is(args.length, 0); 27 | assert.is(options.requisition.commandAssignment.arg.text, 's'); 28 | }; 29 | 30 | exports.testFlatCommand = function(options) { 31 | var args = cli.tokenize('tsv'); 32 | options.requisition._split(args); 33 | assert.is(args.length, 0); 34 | assert.is(options.requisition.commandAssignment.value.name, 'tsv'); 35 | 36 | args = cli.tokenize('tsv a b'); 37 | options.requisition._split(args); 38 | assert.is(options.requisition.commandAssignment.value.name, 'tsv'); 39 | assert.is(args.length, 2); 40 | assert.is(args[0].text, 'a'); 41 | assert.is(args[1].text, 'b'); 42 | }; 43 | 44 | exports.testJavascript = function(options) { 45 | if (!options.requisition.system.commands.get('{')) { 46 | assert.log('Skipping testJavascript because { is not registered'); 47 | return; 48 | } 49 | 50 | var args = cli.tokenize('{'); 51 | options.requisition._split(args); 52 | assert.is(args.length, 1); 53 | assert.is(args[0].text, ''); 54 | assert.is(options.requisition.commandAssignment.arg.text, ''); 55 | assert.is(options.requisition.commandAssignment.value.name, '{'); 56 | }; 57 | 58 | // BUG 663081 - add tests for sub commands 59 | -------------------------------------------------------------------------------- /lib/gcli/test/testTooltip.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var helpers = require('./helpers'); 21 | 22 | exports.testActivate = function(options) { 23 | return helpers.audit(options, [ 24 | { 25 | setup: ' ', 26 | check: { 27 | input: ' ', 28 | hints: '', 29 | markup: 'V', 30 | cursor: 1, 31 | current: '__command', 32 | status: 'ERROR', 33 | message: '', 34 | unassigned: [ ], 35 | outputState: 'false:default', 36 | tooltipState: 'false:default' 37 | } 38 | }, 39 | { 40 | setup: 'tsb ', 41 | check: { 42 | input: 'tsb ', 43 | hints: 'false', 44 | markup: 'VVVV', 45 | cursor: 4, 46 | current: 'toggle', 47 | status: 'VALID', 48 | options: [ 'false', 'true' ], 49 | message: '', 50 | predictions: [ 'false', 'true' ], 51 | unassigned: [ ], 52 | outputState: 'false:default', 53 | tooltipState: 'true:importantFieldFlag' 54 | } 55 | }, 56 | { 57 | setup: 'tsb t', 58 | check: { 59 | input: 'tsb t', 60 | hints: 'rue', 61 | markup: 'VVVVI', 62 | cursor: 5, 63 | current: 'toggle', 64 | status: 'ERROR', 65 | options: [ 'true' ], 66 | message: '', 67 | predictions: [ 'true' ], 68 | unassigned: [ ], 69 | outputState: 'false:default', 70 | tooltipState: 'true:importantFieldFlag' 71 | } 72 | }, 73 | { 74 | setup: 'tsb tt', 75 | check: { 76 | input: 'tsb tt', 77 | hints: ' -> true', 78 | markup: 'VVVVII', 79 | cursor: 6, 80 | current: 'toggle', 81 | status: 'ERROR', 82 | options: [ 'true' ], 83 | message: '', 84 | predictions: [ 'true' ], 85 | unassigned: [ ], 86 | outputState: 'false:default', 87 | tooltipState: 'true:importantFieldFlag' 88 | } 89 | }, 90 | { 91 | setup: 'wxqy', 92 | check: { 93 | input: 'wxqy', 94 | hints: '', 95 | markup: 'EEEE', 96 | cursor: 4, 97 | current: '__command', 98 | status: 'ERROR', 99 | options: [ ], 100 | message: 'Can\'t use \'wxqy\'.', 101 | predictions: [ ], 102 | unassigned: [ ], 103 | outputState: 'false:default', 104 | tooltipState: 'true:isError' 105 | } 106 | }, 107 | { 108 | setup: '', 109 | check: { 110 | input: '', 111 | hints: '', 112 | markup: '', 113 | cursor: 0, 114 | current: '__command', 115 | status: 'ERROR', 116 | message: '', 117 | unassigned: [ ], 118 | outputState: 'false:default', 119 | tooltipState: 'false:default' 120 | } 121 | } 122 | ]); 123 | }; 124 | -------------------------------------------------------------------------------- /lib/gcli/test/testTypes.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var util = require('../util/util'); 21 | 22 | function forEachType(options, templateTypeSpec, callback) { 23 | var types = options.requisition.system.types; 24 | return util.promiseEach(types.getTypeNames(), function(name) { 25 | var typeSpec = {}; 26 | util.copyProperties(templateTypeSpec, typeSpec); 27 | typeSpec.name = name; 28 | typeSpec.requisition = options.requisition; 29 | 30 | // Provide some basic defaults to help selection/delegate/array work 31 | if (name === 'selection') { 32 | typeSpec.data = [ 'a', 'b' ]; 33 | } 34 | else if (name === 'delegate') { 35 | typeSpec.delegateType = function() { 36 | return 'string'; 37 | }; 38 | } 39 | else if (name === 'array') { 40 | typeSpec.subtype = 'string'; 41 | } 42 | else if (name === 'remote') { 43 | return; 44 | } 45 | else if (name === 'union') { 46 | typeSpec.alternatives = [{ name: 'string' }]; 47 | } 48 | else if (options.isRemote) { 49 | if (name === 'node' || name === 'nodelist') { 50 | return; 51 | } 52 | } 53 | 54 | var type = types.createType(typeSpec); 55 | var reply = callback(type); 56 | return Promise.resolve(reply); 57 | }); 58 | } 59 | 60 | exports.testDefault = function(options) { 61 | return forEachType(options, {}, function(type) { 62 | var context = options.requisition.executionContext; 63 | var blank = type.getBlank(context).value; 64 | 65 | // boolean and array types are exempt from needing undefined blank values 66 | if (type.name === 'boolean') { 67 | assert.is(blank, false, 'blank boolean is false'); 68 | } 69 | else if (type.name === 'array') { 70 | assert.ok(Array.isArray(blank), 'blank array is array'); 71 | assert.is(blank.length, 0, 'blank array is empty'); 72 | } 73 | else if (type.name === 'nodelist') { 74 | assert.ok(typeof blank.item, 'function', 'blank.item is function'); 75 | assert.is(blank.length, 0, 'blank nodelist is empty'); 76 | } 77 | else { 78 | assert.is(blank, undefined, 'default defined for ' + type.name); 79 | } 80 | }); 81 | }; 82 | 83 | exports.testNullDefault = function(options) { 84 | var context = null; // Is this test still valid with a null context? 85 | 86 | return forEachType(options, { defaultValue: null }, function(type) { 87 | var reply = type.stringify(null, context); 88 | return Promise.resolve(reply).then(function(str) { 89 | assert.is(str, '', 'stringify(null) for ' + type.name); 90 | }); 91 | }); 92 | }; 93 | 94 | exports.testGetSpec = function(options) { 95 | return forEachType(options, {}, function(type) { 96 | if (type.name === 'param') { 97 | return; 98 | } 99 | 100 | var spec = type.getSpec('cmd', 'param'); 101 | assert.ok(spec != null, 'non null spec for ' + type.name); 102 | 103 | var str = JSON.stringify(spec); 104 | assert.ok(str != null, 'serializable spec for ' + type.name); 105 | 106 | var example = options.requisition.system.types.createType(spec); 107 | assert.ok(example != null, 'creatable spec for ' + type.name); 108 | }); 109 | }; 110 | -------------------------------------------------------------------------------- /lib/gcli/test/testUrl.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var assert = require('../testharness/assert'); 20 | var helpers = require('./helpers'); 21 | 22 | exports.testDefault = function(options) { 23 | return helpers.audit(options, [ 24 | { 25 | skipRemainingIf: options.isPhantomjs, // PhantomJS URL type is broken 26 | setup: 'urlc', 27 | check: { 28 | input: 'urlc', 29 | markup: 'VVVV', 30 | hints: ' ', 31 | status: 'ERROR', 32 | args: { 33 | url: { 34 | value: undefined, 35 | arg: '', 36 | status: 'INCOMPLETE' 37 | } 38 | } 39 | } 40 | }, 41 | { 42 | setup: 'urlc example', 43 | check: { 44 | input: 'urlc example', 45 | markup: 'VVVVVIIIIIII', 46 | hints: ' -> http://example/', 47 | predictions: [ 48 | 'http://example/', 49 | 'https://example/', 50 | 'http://localhost:9999/example' 51 | ], 52 | status: 'ERROR', 53 | args: { 54 | url: { 55 | value: undefined, 56 | arg: ' example', 57 | status: 'INCOMPLETE' 58 | } 59 | } 60 | }, 61 | }, 62 | { 63 | setup: 'urlc example.com/', 64 | check: { 65 | input: 'urlc example.com/', 66 | markup: 'VVVVVIIIIIIIIIIII', 67 | hints: ' -> http://example.com/', 68 | status: 'ERROR', 69 | args: { 70 | url: { 71 | value: undefined, 72 | arg: ' example.com/', 73 | status: 'INCOMPLETE' 74 | } 75 | } 76 | }, 77 | }, 78 | { 79 | setup: 'urlc http://example.com/index?q=a#hash', 80 | check: { 81 | input: 'urlc http://example.com/index?q=a#hash', 82 | markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV', 83 | hints: '', 84 | status: 'VALID', 85 | args: { 86 | url: { 87 | value: function(data) { 88 | assert.is(data.hash, '#hash', 'url hash'); 89 | }, 90 | arg: ' http://example.com/index?q=a#hash', 91 | status: 'VALID' 92 | } 93 | } 94 | }, 95 | exec: { output: /"url": ?/ } 96 | } 97 | ]); 98 | }; 99 | -------------------------------------------------------------------------------- /lib/gcli/testharness/assert.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * Module dependency loop resolution 21 | * examiner/assert both want to depend on each other, and we'd rather not 22 | * depend on util.createEvent (which could make matters worse) so we just 23 | * have examiner record the current test here. 24 | */ 25 | exports.currentTest = null; 26 | 27 | /** 28 | * To we log what's going on with the tests. Useful for when something is going 29 | * bizarrely wrong, and we want to know what. 30 | */ 31 | exports.testLogging = false; 32 | 33 | /** 34 | * Record a test failure if |value| is not truthy 35 | * Failure is marked by a record being added to the failure list with a message 36 | * property containing the passed message. 37 | */ 38 | exports.ok = function(value, message) { 39 | if (!exports.currentTest) { 40 | console.error('No currentTest for ' + message); 41 | return; 42 | } 43 | 44 | if (!value) { 45 | console.error('Failure: ' + message); 46 | 47 | exports.currentTest.failures.push({ message: message }); 48 | } 49 | else { 50 | exports.currentTest.checks++; 51 | } 52 | }; 53 | 54 | /** 55 | * Record a test failure if |p1 !== p2| 56 | * Failure is marked by a record being added to the failure list with the 57 | * following properties: 58 | * - message: The string passed in to the |is| function 59 | * - params: (true) To distinguish from an |ok| failure 60 | * - p1: The first parameter to compare 61 | * - p2: The second parameter to compare against 62 | */ 63 | exports.is = function(p1, p2, message) { 64 | if (!exports.currentTest) { 65 | console.error('No currentTest for ' + message); 66 | return; 67 | } 68 | 69 | if (p1 !== p2) { 70 | console.error('Failure: ' + message + ' (in ' + exports.currentTest + ')'); 71 | console.error('- (Actual) P1: ', typeof p1 === 'string' ? '"' + p1 + '"' : p1); 72 | console.error('- (Expected) P2: ', typeof p2 === 'string' ? '"' + p2 + '"' : p2); 73 | 74 | exports.currentTest.failures.push({ message: message, params: true, p1: p1, p2: p2 }); 75 | } 76 | else { 77 | exports.currentTest.checks++; 78 | } 79 | }; 80 | 81 | /** 82 | * Add some extra information to the test logs 83 | */ 84 | exports.log = function(message) { 85 | if (!exports.currentTest) { 86 | console.error('No currentTest for ' + message); 87 | return; 88 | } 89 | 90 | exports.currentTest.skipped.push({ message: message }); 91 | }; 92 | -------------------------------------------------------------------------------- /lib/gcli/testharness/status.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * This should really be inside assert.js, however that is over-ridden by 21 | * a custom assert.js for mozilla, so we keep it separate to avoid 22 | * duplicating it in 2 places. 23 | */ 24 | exports.stati = { 25 | notrun: { index: 0, name: 'Skipped' }, 26 | executing: { index: 1, name: 'Executing' }, 27 | pass: { index: 2, name: 'Pass' }, 28 | fail: { index: 3, name: 'Fail' }, 29 | }; 30 | -------------------------------------------------------------------------------- /lib/gcli/types/array.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var ArrayConversion = require('./types').ArrayConversion; 20 | var ArrayArgument = require('./types').ArrayArgument; 21 | 22 | exports.items = [ 23 | { 24 | // A set of objects of the same type 25 | item: 'type', 26 | name: 'array', 27 | subtype: undefined, 28 | 29 | constructor: function() { 30 | if (!this.subtype) { 31 | console.error('Array.typeSpec is missing subtype. Assuming string.' + 32 | this.name); 33 | this.subtype = 'string'; 34 | } 35 | this.subtype = this.types.createType(this.subtype); 36 | }, 37 | 38 | getSpec: function(commandName, paramName) { 39 | return { 40 | name: 'array', 41 | subtype: this.subtype.getSpec(commandName, paramName), 42 | }; 43 | }, 44 | 45 | stringify: function(values, context) { 46 | if (values == null) { 47 | return ''; 48 | } 49 | // BUG 664204: Check for strings with spaces and add quotes 50 | return values.join(' '); 51 | }, 52 | 53 | parse: function(arg, context) { 54 | if (arg.type !== 'ArrayArgument') { 55 | console.error('non ArrayArgument to ArrayType.parse', arg); 56 | throw new Error('non ArrayArgument to ArrayType.parse'); 57 | } 58 | 59 | // Parse an argument to a conversion 60 | // Hack alert. ArrayConversion needs to be able to answer questions about 61 | // the status of individual conversions in addition to the overall state. 62 | // |subArg.conversion| allows us to do that easily. 63 | var subArgParse = function(subArg) { 64 | return this.subtype.parse(subArg, context).then(function(conversion) { 65 | subArg.conversion = conversion; 66 | return conversion; 67 | }.bind(this)); 68 | }.bind(this); 69 | 70 | var conversionPromises = arg.getArguments().map(subArgParse); 71 | return Promise.all(conversionPromises).then(function(conversions) { 72 | return new ArrayConversion(conversions, arg); 73 | }); 74 | }, 75 | 76 | getBlank: function(context) { 77 | return new ArrayConversion([], new ArrayArgument()); 78 | } 79 | }, 80 | ]; 81 | -------------------------------------------------------------------------------- /lib/gcli/types/boolean.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var Status = require('./types').Status; 20 | var Conversion = require('./types').Conversion; 21 | var BlankArgument = require('./types').BlankArgument; 22 | var SelectionType = require('./selection').SelectionType; 23 | 24 | exports.items = [ 25 | { 26 | // 'boolean' type 27 | item: 'type', 28 | name: 'boolean', 29 | parent: 'selection', 30 | 31 | getSpec: function() { 32 | return 'boolean'; 33 | }, 34 | 35 | lookup: [ 36 | { name: 'false', value: false }, 37 | { name: 'true', value: true } 38 | ], 39 | 40 | parse: function(arg, context) { 41 | if (arg.type === 'TrueNamedArgument') { 42 | return Promise.resolve(new Conversion(true, arg)); 43 | } 44 | if (arg.type === 'FalseNamedArgument') { 45 | return Promise.resolve(new Conversion(false, arg)); 46 | } 47 | return SelectionType.prototype.parse.call(this, arg, context); 48 | }, 49 | 50 | stringify: function(value, context) { 51 | if (value == null) { 52 | return ''; 53 | } 54 | return '' + value; 55 | }, 56 | 57 | getBlank: function(context) { 58 | return new Conversion(false, new BlankArgument(), Status.VALID, '', 59 | Promise.resolve(this.lookup)); 60 | } 61 | } 62 | ]; 63 | -------------------------------------------------------------------------------- /lib/gcli/types/file.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /* 20 | * The file type is a bit of a spiders-web, but there isn't a nice solution 21 | * yet. The core of the problem is that the modules used by Firefox and NodeJS 22 | * intersect with the modules used by the web, but not each other. Except here. 23 | * So we have to do something fancy to get the sharing but not mess up the web. 24 | * 25 | * This file requires 'gcli/types/fileparser', and there are 4 implementations 26 | * of this: 27 | * - '/lib/gcli/types/fileparser.js', the default web version that uses XHR to 28 | * talk to the node server 29 | * - '/lib/server/gcli/types/fileparser.js', an NodeJS stub, and ... 30 | * - '/mozilla/gcli/types/fileparser.js', the Firefox implementation both of 31 | * these are shims which import 32 | * - 'gcli/util/fileparser', does the real work, except the actual file access 33 | * 34 | * The file access comes from the 'gcli/util/filesystem' module, and there are 35 | * 2 implementations of this: 36 | * - '/lib/server/gcli/util/filesystem.js', which uses NodeJS APIs 37 | * - '/mozilla/gcli/util/filesystem.js', which uses OS.File APIs 38 | */ 39 | 40 | var fileparser = require('./fileparser'); 41 | var Conversion = require('./types').Conversion; 42 | 43 | exports.items = [ 44 | { 45 | item: 'type', 46 | name: 'file', 47 | 48 | filetype: 'any', // One of 'file', 'directory', 'any' 49 | existing: 'maybe', // Should be one of 'yes', 'no', 'maybe' 50 | matches: undefined, // RegExp to match the file part of the path 51 | 52 | hasPredictions: true, 53 | 54 | constructor: function() { 55 | if (this.filetype !== 'any' && this.filetype !== 'file' && 56 | this.filetype !== 'directory') { 57 | throw new Error('filetype must be one of [any|file|directory]'); 58 | } 59 | 60 | if (this.existing !== 'yes' && this.existing !== 'no' && 61 | this.existing !== 'maybe') { 62 | throw new Error('existing must be one of [yes|no|maybe]'); 63 | } 64 | }, 65 | 66 | getSpec: function(commandName, paramName) { 67 | return { 68 | name: 'remote', 69 | commandName: commandName, 70 | paramName: paramName 71 | }; 72 | }, 73 | 74 | stringify: function(file) { 75 | if (file == null) { 76 | return ''; 77 | } 78 | 79 | return file.toString(); 80 | }, 81 | 82 | parse: function(arg, context) { 83 | var options = { 84 | filetype: this.filetype, 85 | existing: this.existing, 86 | matches: this.matches 87 | }; 88 | var promise = fileparser.parse(context, arg.text, options); 89 | 90 | return promise.then(function(reply) { 91 | return new Conversion(reply.value, arg, reply.status, 92 | reply.message, reply.predictor); 93 | }); 94 | } 95 | } 96 | ]; 97 | -------------------------------------------------------------------------------- /lib/gcli/types/fileparser.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.parse = require('../util/fileparser').parse; 20 | -------------------------------------------------------------------------------- /lib/gcli/types/setting.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | exports.items = [ 20 | { 21 | // A type for selecting a known setting 22 | item: 'type', 23 | name: 'setting', 24 | parent: 'selection', 25 | cacheable: true, 26 | lookup: function(context) { 27 | var settings = context.system.settings; 28 | 29 | // Lazily add a settings.onChange listener to clear the cache 30 | if (!this._registeredListener) { 31 | settings.onChange.add(function(ev) { 32 | this.clearCache(); 33 | }, this); 34 | this._registeredListener = true; 35 | } 36 | 37 | return settings.getAll().map(function(setting) { 38 | return { name: setting.name, value: setting }; 39 | }); 40 | } 41 | }, 42 | { 43 | // A type for entering the value of a known setting 44 | // Customizations: 45 | // - settingParamName The name of the setting parameter so we can customize 46 | // the type that we are expecting to read 47 | item: 'type', 48 | name: 'settingValue', 49 | parent: 'delegate', 50 | settingParamName: 'setting', 51 | delegateType: function(context) { 52 | if (context != null) { 53 | var setting = context.getArgsObject()[this.settingParamName]; 54 | if (setting != null) { 55 | return setting.type; 56 | } 57 | } 58 | 59 | return 'blank'; 60 | } 61 | } 62 | ]; 63 | -------------------------------------------------------------------------------- /lib/gcli/types/string.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var Status = require('./types').Status; 20 | var Conversion = require('./types').Conversion; 21 | 22 | exports.items = [ 23 | { 24 | // 'string' the most basic string type where all we need to do is to take 25 | // care of converting escaped characters like \t, \n, etc. 26 | // For the full list see 27 | // https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Values,_variables,_and_literals 28 | // The exception is that we ignore \b because replacing '\b' characters in 29 | // stringify() with their escaped version injects '\\b' all over the place 30 | // and the need to support \b seems low) 31 | // Customizations: 32 | // allowBlank: Allow a blank string to be counted as valid 33 | item: 'type', 34 | name: 'string', 35 | allowBlank: false, 36 | 37 | getSpec: function() { 38 | return this.allowBlank ? 39 | { name: 'string', allowBlank: true } : 40 | 'string'; 41 | }, 42 | 43 | stringify: function(value, context) { 44 | if (value == null) { 45 | return ''; 46 | } 47 | 48 | return value 49 | .replace(/\\/g, '\\\\') 50 | .replace(/\f/g, '\\f') 51 | .replace(/\n/g, '\\n') 52 | .replace(/\r/g, '\\r') 53 | .replace(/\t/g, '\\t') 54 | .replace(/\v/g, '\\v') 55 | .replace(/\n/g, '\\n') 56 | .replace(/\r/g, '\\r') 57 | .replace(/ /g, '\\ ') 58 | .replace(/'/g, '\\\'') 59 | .replace(/"/g, '\\"') 60 | .replace(/{/g, '\\{') 61 | .replace(/}/g, '\\}'); 62 | }, 63 | 64 | parse: function(arg, context) { 65 | if (!this.allowBlank && (arg.text == null || arg.text === '')) { 66 | return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, '')); 67 | } 68 | 69 | // The string '\\' (i.e. an escaped \ (represented here as '\\\\' because it 70 | // is double escaped)) is first converted to a private unicode character and 71 | // then at the end from \uF000 to a single '\' to avoid the string \\n being 72 | // converted first to \n and then to a 73 | var value = arg.text 74 | .replace(/\\\\/g, '\uF000') 75 | .replace(/\\f/g, '\f') 76 | .replace(/\\n/g, '\n') 77 | .replace(/\\r/g, '\r') 78 | .replace(/\\t/g, '\t') 79 | .replace(/\\v/g, '\v') 80 | .replace(/\\n/g, '\n') 81 | .replace(/\\r/g, '\r') 82 | .replace(/\\ /g, ' ') 83 | .replace(/\\'/g, '\'') 84 | .replace(/\\"/g, '"') 85 | .replace(/\\{/g, '{') 86 | .replace(/\\}/g, '}') 87 | .replace(/\uF000/g, '\\'); 88 | 89 | return Promise.resolve(new Conversion(value, arg)); 90 | } 91 | } 92 | ]; 93 | -------------------------------------------------------------------------------- /lib/gcli/types/union.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | var Conversion = require('./types').Conversion; 21 | var Status = require('./types').Status; 22 | 23 | exports.items = [ 24 | { 25 | // The union type allows for a combination of different parameter types. 26 | item: 'type', 27 | name: 'union', 28 | hasPredictions: true, 29 | 30 | constructor: function() { 31 | // Get the properties of the type. Later types in the list should always 32 | // be more general, so 'catch all' types like string must be last 33 | this.alternatives = this.alternatives.map(function(typeData) { 34 | return this.types.createType(typeData); 35 | }.bind(this)); 36 | }, 37 | 38 | getSpec: function(command, param) { 39 | var spec = { name: 'union', alternatives: [] }; 40 | this.alternatives.forEach(function(type) { 41 | spec.alternatives.push(type.getSpec(command, param)); 42 | }.bind(this)); 43 | return spec; 44 | }, 45 | 46 | stringify: function(value, context) { 47 | if (value == null) { 48 | return ''; 49 | } 50 | 51 | var type = this.alternatives.find(function(typeData) { 52 | return typeData.name === value.type; 53 | }); 54 | 55 | return type.stringify(value[value.type], context); 56 | }, 57 | 58 | parse: function(arg, context) { 59 | var conversionPromises = this.alternatives.map(function(type) { 60 | return type.parse(arg, context); 61 | }.bind(this)); 62 | 63 | return Promise.all(conversionPromises).then(function(conversions) { 64 | // Find a list of the predictions made by any conversion 65 | var predictionPromises = conversions.map(function(conversion) { 66 | return conversion.getPredictions(context); 67 | }.bind(this)); 68 | 69 | return Promise.all(predictionPromises).then(function(allPredictions) { 70 | // Take one prediction from each set of predictions, ignoring 71 | // duplicates, until we've got up to Conversion.maxPredictions 72 | var maxIndex = allPredictions.reduce(function(prev, prediction) { 73 | return Math.max(prev, prediction.length); 74 | }.bind(this), 0); 75 | var predictions = []; 76 | 77 | indexLoop: 78 | for (var index = 0; index < maxIndex; index++) { 79 | for (var p = 0; p <= allPredictions.length; p++) { 80 | if (predictions.length >= Conversion.maxPredictions) { 81 | break indexLoop; 82 | } 83 | 84 | if (allPredictions[p] != null) { 85 | var prediction = allPredictions[p][index]; 86 | if (prediction != null && predictions.indexOf(prediction) === -1) { 87 | predictions.push(prediction); 88 | } 89 | } 90 | } 91 | } 92 | 93 | var bestStatus = Status.ERROR; 94 | var value; 95 | for (var i = 0; i < conversions.length; i++) { 96 | var conversion = conversions[i]; 97 | var thisStatus = conversion.getStatus(arg); 98 | if (thisStatus < bestStatus) { 99 | bestStatus = thisStatus; 100 | } 101 | if (bestStatus === Status.VALID) { 102 | var type = this.alternatives[i].name; 103 | value = { type: type }; 104 | value[type] = conversion.value; 105 | break; 106 | } 107 | } 108 | 109 | var msg = (bestStatus === Status.VALID) ? 110 | '' : 111 | l10n.lookupFormat('typesSelectionNomatch', [ arg.text ]); 112 | return new Conversion(value, arg, bestStatus, msg, predictions); 113 | }.bind(this)); 114 | }.bind(this)); 115 | }, 116 | } 117 | ]; 118 | -------------------------------------------------------------------------------- /lib/gcli/types/url.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var host = require('../util/host'); 20 | var Status = require('./types').Status; 21 | var Conversion = require('./types').Conversion; 22 | 23 | exports.items = [ 24 | { 25 | item: 'type', 26 | name: 'url', 27 | 28 | getSpec: function() { 29 | return 'url'; 30 | }, 31 | 32 | stringify: function(value, context) { 33 | if (value == null) { 34 | return ''; 35 | } 36 | return value.href; 37 | }, 38 | 39 | parse: function(arg, context) { 40 | var conversion; 41 | 42 | try { 43 | var url = host.createUrl(arg.text); 44 | conversion = new Conversion(url, arg); 45 | } 46 | catch (ex) { 47 | var predictions = []; 48 | var status = Status.ERROR; 49 | 50 | // Maybe the URL was missing a scheme? 51 | if (arg.text.indexOf('://') === -1) { 52 | [ 'http', 'https' ].forEach(function(scheme) { 53 | try { 54 | var http = host.createUrl(scheme + '://' + arg.text); 55 | predictions.push({ name: http.href, value: http }); 56 | } 57 | catch (ex) { 58 | // Ignore 59 | } 60 | }.bind(this)); 61 | 62 | // Try to create a URL with the current page as a base ref 63 | if ('window' in context.environment) { 64 | try { 65 | var base = context.environment.window.location.href; 66 | var localized = host.createUrl(arg.text, base); 67 | predictions.push({ name: localized.href, value: localized }); 68 | } 69 | catch (ex) { 70 | // Ignore 71 | } 72 | } 73 | } 74 | 75 | if (predictions.length > 0) { 76 | status = Status.INCOMPLETE; 77 | } 78 | 79 | conversion = new Conversion(undefined, arg, status, 80 | ex.message, predictions); 81 | } 82 | 83 | return Promise.resolve(conversion); 84 | } 85 | } 86 | ]; 87 | -------------------------------------------------------------------------------- /lib/gcli/ui/history.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | /** 20 | * A History object remembers commands that have been entered in the past and 21 | * provides an API for accessing them again. 22 | * See Bug 681340: Search through history (like C-r in bash)? 23 | */ 24 | function History() { 25 | // This is the actual buffer where previous commands are kept. 26 | // 'this._buffer[0]' should always be equal the empty string. This is so 27 | // that when you try to go in to the "future", you will just get an empty 28 | // command. 29 | this._buffer = ['']; 30 | 31 | // This is an index in to the history buffer which points to where we 32 | // currently are in the history. 33 | this._current = 0; 34 | } 35 | 36 | /** 37 | * Avoid memory leaks 38 | */ 39 | History.prototype.destroy = function() { 40 | this._buffer = undefined; 41 | }; 42 | 43 | /** 44 | * Record and save a new command in the history. 45 | */ 46 | History.prototype.add = function(command) { 47 | this._buffer.splice(1, 0, command); 48 | this._current = 0; 49 | }; 50 | 51 | /** 52 | * Get the next (newer) command from history. 53 | */ 54 | History.prototype.forward = function() { 55 | if (this._current > 0 ) { 56 | this._current--; 57 | } 58 | return this._buffer[this._current]; 59 | }; 60 | 61 | /** 62 | * Get the previous (older) item from history. 63 | */ 64 | History.prototype.backward = function() { 65 | if (this._current < this._buffer.length - 1) { 66 | this._current++; 67 | } 68 | return this._buffer[this._current]; 69 | }; 70 | 71 | exports.History = History; 72 | -------------------------------------------------------------------------------- /lib/gcli/ui/intro.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var l10n = require('../util/l10n'); 20 | var Output = require('../cli').Output; 21 | var view = require('./view'); 22 | 23 | /** 24 | * Record if the user has clicked on 'Got It!' 25 | */ 26 | exports.items = [ 27 | { 28 | item: 'setting', 29 | name: 'hideIntro', 30 | type: 'boolean', 31 | description: l10n.lookup('hideIntroDesc'), 32 | defaultValue: false 33 | } 34 | ]; 35 | 36 | /** 37 | * Called when the UI is ready to add a welcome message to the output 38 | */ 39 | exports.maybeShowIntro = function(commandOutputManager, conversionContext) { 40 | var hideIntro = conversionContext.system.settings.get('hideIntro'); 41 | if (hideIntro.value) { 42 | return; 43 | } 44 | 45 | var output = new Output(conversionContext); 46 | output.type = 'view'; 47 | commandOutputManager.onOutput({ output: output }); 48 | 49 | var viewData = this.createView(null, conversionContext, true); 50 | 51 | output.complete({ isTypedData: true, type: 'view', data: viewData }); 52 | }; 53 | 54 | /** 55 | * Called when the UI is ready to add a welcome message to the output 56 | */ 57 | exports.createView = function(ignoreArgs, conversionContext, showHideButton) { 58 | return view.createView({ 59 | html: 60 | '
\n' + 61 | '

${l10n.introTextOpening3}

\n' + 62 | '\n' + 63 | '

\n' + 64 | ' ${l10n.introTextCommands}\n' + 65 | ' help${l10n.introTextKeys2}\n' + 68 | ' ${l10n.introTextF1Escape}.\n' + 69 | '

\n' + 70 | '\n' + 71 | ' \n' + 73 | '
', 74 | options: { stack: 'intro.html' }, 75 | data: { 76 | l10n: l10n.propertyLookup, 77 | onclick: conversionContext.update, 78 | ondblclick: conversionContext.updateExec, 79 | showHideButton: showHideButton, 80 | onGotIt: function(ev) { 81 | var settings = conversionContext.system.settings; 82 | var hideIntro = settings.get('hideIntro'); 83 | hideIntro.value = true; 84 | this.mainDiv.style.display = 'none'; 85 | } 86 | } 87 | }); 88 | }; 89 | -------------------------------------------------------------------------------- /lib/gcli/ui/menu.css: -------------------------------------------------------------------------------- 1 | 2 | .gcli-menu { 3 | overflow: hidden; 4 | font-size: 90%; 5 | } 6 | 7 | .gcli-menu:not(:first-of-type) { 8 | padding-top: 5px; 9 | } 10 | 11 | .gcli-menu-vert { 12 | white-space: nowrap; 13 | max-width: 22em; 14 | display: inline-flex; 15 | -moz-padding-end: 20px; 16 | -webkit-padding-end: 20px; 17 | } 18 | 19 | .gcli-menu-names { 20 | white-space: nowrap; 21 | flex-grow: 0; 22 | flex-shrink: 0; 23 | } 24 | 25 | .gcli-menu-descs { 26 | flex-grow: 1; 27 | flex-shrink: 1; 28 | } 29 | 30 | .gcli-menu-name, 31 | .gcli-menu-desc { 32 | white-space: nowrap; 33 | } 34 | 35 | .gcli-menu-name { 36 | -moz-padding-start: 2px; 37 | -webkit-padding-start: 2px; 38 | -moz-padding-end: 8px; 39 | -webkit-padding-end: 8px; 40 | } 41 | 42 | .gcli-menu-desc { 43 | -moz-padding-end: 2px; 44 | -webkit-padding-end: 2px; 45 | color: #777; 46 | text-overflow: ellipsis; 47 | overflow: hidden; 48 | } 49 | 50 | .gcli-menu-name:hover, 51 | .gcli-menu-desc:hover { 52 | background-color: rgba(0, 0, 0, 0.05); 53 | } 54 | 55 | .gcli-menu-highlight, 56 | .gcli-menu-highlight.gcli-menu-option:hover { 57 | background-color: rgba(0, 0, 0, 0.1); 58 | } 59 | 60 | .gcli-menu-typed { 61 | color: #FF6600; 62 | } 63 | 64 | .gcli-menu-more { 65 | font-size: 80%; 66 | width: 8em; 67 | display: inline-flex; 68 | vertical-align: bottom; 69 | } 70 | -------------------------------------------------------------------------------- /lib/gcli/ui/menu.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
${item.highlight}
10 |
11 |
12 |
${item.description}
17 |
18 |
19 |
${l10n.fieldMenuMore}
20 |
21 | -------------------------------------------------------------------------------- /lib/gcli/ui/terminal.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | 6 |
7 | 8 |
9 | 10 | ${member.string} 11 | 12 | ${directTabText} 13 | ${param} 14 | ${arrowTabText} 15 | } 16 |
17 |
18 |
19 |
20 |
21 |
22 | 23 |
24 | ${language.description} 25 | ${language.message} 26 | ${field.element} 27 |
28 |
29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /lib/gcli/ui/view.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var util = require('../util/util'); 20 | var host = require('../util/host'); 21 | var domtemplate = require('../util/domtemplate'); 22 | 23 | 24 | /** 25 | * We want to avoid commands having to create DOM structures because that's 26 | * messy and because we're going to need to have command output displayed in 27 | * different documents. A View is a way to wrap an HTML template (for 28 | * domtemplate) in with the data and options to render the template, so anyone 29 | * can later run the template in the context of any document. 30 | * View also cuts out a chunk of boiler place code. 31 | * @param options The information needed to create the DOM from HTML. Includes: 32 | * - html (required): The HTML source, probably from a call to require 33 | * - options (default={}): The domtemplate options. See domtemplate for details 34 | * - data (default={}): The data to domtemplate. See domtemplate for details. 35 | * - css (default=none): Some CSS to be added to the final document. If 'css' 36 | * is used, use of cssId is strongly recommended. 37 | * - cssId (default=none): An ID to prevent multiple CSS additions. See 38 | * util.importCss for more details. 39 | * @return An object containing a single function 'appendTo()' which runs the 40 | * template adding the result to the specified element. Takes 2 parameters: 41 | * - element (required): the element to add to 42 | * - clear (default=false): if clear===true then remove all pre-existing 43 | * children of 'element' before appending the results of this template. 44 | */ 45 | exports.createView = function(options) { 46 | if (options.html == null) { 47 | throw new Error('options.html is missing'); 48 | } 49 | 50 | return { 51 | /** 52 | * RTTI. Yeah. 53 | */ 54 | isView: true, 55 | 56 | /** 57 | * Run the template against the document to which element belongs. 58 | * @param element The element to append the result to 59 | * @param clear Set clear===true to remove all children of element 60 | */ 61 | appendTo: function(element, clear) { 62 | // Strict check on the off-chance that we later think of other options 63 | // and want to replace 'clear' with an 'options' parameter, but want to 64 | // support backwards compat. 65 | if (clear === true) { 66 | util.clearElement(element); 67 | } 68 | 69 | element.appendChild(this.toDom(element.ownerDocument)); 70 | }, 71 | 72 | /** 73 | * Actually convert the view data into a DOM suitable to be appended to 74 | * an element 75 | * @param document to use in realizing the template 76 | */ 77 | toDom: function(document) { 78 | if (options.css) { 79 | util.importCss(options.css, document, options.cssId); 80 | } 81 | 82 | var child = host.toDom(document, options.html); 83 | domtemplate.template(child, options.data || {}, options.options || {}); 84 | return child; 85 | } 86 | }; 87 | }; 88 | -------------------------------------------------------------------------------- /lib/gcli/util/filesystem.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var fs = require('fs'); 20 | var path = require('path'); 21 | 22 | var util = require('./util'); 23 | 24 | /** 25 | * A set of functions defining a filesystem API for fileparser.js 26 | */ 27 | 28 | exports.join = function() { 29 | return path.join.apply(path, arguments); 30 | }; 31 | 32 | exports.dirname = function() { 33 | return path.dirname.apply(path, arguments); 34 | }; 35 | 36 | exports.sep = path.sep; 37 | 38 | exports.home = typeof process !== 'undefined' ? process.env.HOME : ''; 39 | 40 | /** 41 | * The NodeJS docs suggest using ``pathname.split(path.sep)`` to cut a path 42 | * into a number of components. But this doesn't take into account things like 43 | * path normalization and removing the initial (or trailing) blanks from 44 | * absolute (or / terminated) paths. 45 | * http://www.nodejs.org/api/path.html#path_path_sep 46 | * @param pathname (string) The part to cut up 47 | * @return An array of path components 48 | */ 49 | exports.split = function(pathname) { 50 | pathname = path.normalize(pathname); 51 | var parts = pathname.split(exports.sep); 52 | return parts.filter(function(part) { 53 | return part !== ''; 54 | }); 55 | }; 56 | 57 | /** 58 | * @param pathname string, path of an existing directory 59 | * @param matches optional regular expression - filter output to include only 60 | * the files that match the regular expression. The regexp is applied to the 61 | * filename only not to the full path 62 | * @return A promise of an array of stat objects for each member of the 63 | * directory pointed to by ``pathname``, each containing 2 extra properties: 64 | * - pathname: The full pathname of the file 65 | * - filename: The final filename part of the pathname 66 | */ 67 | exports.ls = function(pathname, matches) { 68 | return new Promise(function(resolve, reject) { 69 | fs.readdir(pathname, function(err, files) { 70 | if (err) { 71 | reject(err); 72 | } 73 | else { 74 | if (matches) { 75 | files = files.filter(function(file) { 76 | return matches.test(file); 77 | }); 78 | } 79 | 80 | var statsPromise = util.promiseEach(files, function(filename) { 81 | var filepath = path.join(pathname, filename); 82 | return exports.stat(filepath).then(function(stats) { 83 | stats.filename = filename; 84 | stats.pathname = filepath; 85 | return stats; 86 | }); 87 | }); 88 | 89 | statsPromise.then(resolve, reject); 90 | } 91 | }); 92 | }.bind(this)); 93 | }; 94 | 95 | /** 96 | * stat() is annoying because it considers stat('/doesnt/exist') to be an 97 | * error, when the point of stat() is to *find* *out*. So this wrapper just 98 | * converts 'ENOENT' i.e. doesn't exist to { exists:false } and adds 99 | * exists:true to stat blocks from existing paths 100 | */ 101 | exports.stat = function(pathname) { 102 | return new Promise(function(resolve, reject) { 103 | fs.stat(pathname, function(err, stats) { 104 | if (err) { 105 | if (err.code === 'ENOENT') { 106 | resolve({ 107 | exists: false, 108 | isDir: false, 109 | isFile: false 110 | }); 111 | } 112 | else { 113 | reject(err); 114 | } 115 | } 116 | else { 117 | resolve({ 118 | exists: true, 119 | isDir: stats.isDirectory(), 120 | isFile: stats.isFile() 121 | }); 122 | } 123 | }); 124 | }.bind(this)); 125 | }; 126 | 127 | /** 128 | * We may read the first line of a file to describe it? 129 | * Right now, however, we do nothing. 130 | */ 131 | exports.describe = function(pathname) { 132 | return Promise.resolve(''); 133 | }; 134 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcli", 3 | "description": "JavaScript Command Line", 4 | "version": "0.6.4", 5 | "homepage": "http://github.com/joewalker/gcli", 6 | "engines": { 7 | "node": ">= 4.1.0" 8 | }, 9 | "dependencies": { 10 | "body-parser": "1.14.0", 11 | "dom-urls": "1.0.0", 12 | "dryice": "0.4.11", 13 | "es6-promise": "3.0.2", 14 | "express": "4.13.3", 15 | "jsdom": "6.5.1", 16 | "json-loader": "0.5.3", 17 | "morgan": "1.6.1", 18 | "node-libs-browser": "0.5.3", 19 | "raw-loader": "0.5.1", 20 | "socket.io": "1.3.7", 21 | "socket.io-client": "1.3.7", 22 | "webpack": "1.12.2" 23 | }, 24 | "author": "Joe Walker ", 25 | "main": "lib/gcli", 26 | "repository": { 27 | "type": "git", 28 | "url": "http://github.com/joewalker/gcli.git" 29 | }, 30 | "scripts": { 31 | "test": "node gcli.js test" 32 | }, 33 | "licenses": [ 34 | { 35 | "type": "Apache-2.0", 36 | "url": "http://www.apache.org/licenses/LICENSE-2.0" 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /phantom-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var page = require('webpage').create(); 20 | var system = require('system'); 21 | 22 | var exitOnComplete = function() { 23 | var complete = page.evaluate(function() { 24 | return document.complete; 25 | }); 26 | var status = page.evaluate(function() { 27 | return document.testStatus; 28 | }); 29 | 30 | if (complete === true) { 31 | var exitValue = (status == 'Pass' ? 0 : -1); 32 | phantom.exit(exitValue); 33 | } 34 | }; 35 | 36 | var pageLoaded = function(status) { 37 | setInterval(exitOnComplete, 50); 38 | }; 39 | 40 | page.onConsoleMessage = function() { 41 | console.log.apply(console, arguments); 42 | }; 43 | 44 | if (system.args.length === 1) { 45 | page.open('http://localhost:9999/index.html', pageLoaded); 46 | } else { 47 | if (system.args[1] === '--shutdown') { 48 | page.open('http://localhost:9999/index.html?shutdown=true', pageLoaded); 49 | } 50 | else { 51 | console.error('Options: --shutdown'); 52 | phantom.exit(-1); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /remote.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GCLI: Graphical Command Line 7 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /scripts/shim.js: -------------------------------------------------------------------------------- 1 | 2 | // Only needed for PhantomJS 3 | if (!Function.prototype.bind) { 4 | Function.prototype.bind = function (oThis) { 5 | if (typeof this !== "function") { 6 | // closest thing possible to the ECMAScript 5 internal IsCallable function 7 | throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); 8 | } 9 | 10 | var aArgs = Array.prototype.slice.call(arguments, 1), 11 | fToBind = this, 12 | fNOP = function () {}, 13 | fBound = function () { 14 | return fToBind.apply(this instanceof fNOP && oThis 15 | ? this 16 | : oThis, 17 | aArgs.concat(Array.prototype.slice.call(arguments))); 18 | }; 19 | 20 | fNOP.prototype = this.prototype; 21 | fBound.prototype = new fNOP(); 22 | 23 | return fBound; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | /* eslint no-var: 0 */ 19 | 20 | var path = require('path'); 21 | var webpack = require('webpack'); 22 | 23 | module.exports = { 24 | entry: { 25 | 'wp-index': [ './wp-index.js' ], 26 | }, 27 | output: { 28 | path: path.join(__dirname, 'built'), 29 | filename: '[name].js', 30 | sourceMapFilename: '[file].map', 31 | publicPath: 'http://localhost:3000/', 32 | }, 33 | module: { 34 | loaders: [ 35 | { test: /\.css$/, loader: 'raw' }, 36 | { test: /\.html$/, loader: 'raw' }, 37 | { test: /\.json$/, loader: 'json' }, 38 | ], 39 | }, 40 | plugins: [ 41 | new webpack.IgnorePlugin(/child_process$/), 42 | new webpack.IgnorePlugin(/dom-urls$/), 43 | new webpack.IgnorePlugin(/fs$/), 44 | new webpack.IgnorePlugin(/jsdom$/), 45 | new webpack.IgnorePlugin(/path$/), 46 | ], 47 | }; 48 | -------------------------------------------------------------------------------- /wp-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GCLI: Graphical Command Line 7 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /wp-index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Mozilla Foundation and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | var gcli = require('./lib/gcli/index'); 20 | var demo = require('./lib/gcli/items/demo'); 21 | var test = require('./lib/gcli/test/index'); 22 | 23 | // Add the commands/types/converters as required 24 | var system = gcli.createSystem(); 25 | system.addItems(gcli.items); // Common infrastructure: types, etc 26 | system.addItems(gcli.commandItems); // Common set of useful commands 27 | system.addItems(demo.items); // Extra demo commands 28 | 29 | gcli.createTerminal(system).then(function(terminal) { 30 | terminal.language.showIntro(); // Intro text 31 | test.run(terminal, false); // Run the unit test at each startup 32 | }).catch(console.error.bind(console)); 33 | --------------------------------------------------------------------------------