summaryrefslogtreecommitdiffstats
path: root/devtools/shared/gcli/source/docs
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/gcli/source/docs')
-rw-r--r--devtools/shared/gcli/source/docs/design.md102
-rw-r--r--devtools/shared/gcli/source/docs/developing-gcli.md213
-rw-r--r--devtools/shared/gcli/source/docs/index.md150
-rw-r--r--devtools/shared/gcli/source/docs/running-tests.md60
-rw-r--r--devtools/shared/gcli/source/docs/writing-commands.md757
-rw-r--r--devtools/shared/gcli/source/docs/writing-tests.md20
-rw-r--r--devtools/shared/gcli/source/docs/writing-types.md106
7 files changed, 1408 insertions, 0 deletions
diff --git a/devtools/shared/gcli/source/docs/design.md b/devtools/shared/gcli/source/docs/design.md
new file mode 100644
index 000000000..5e3c0a2f3
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/design.md
@@ -0,0 +1,102 @@
+
+# The Design of GCLI
+
+## Design Goals
+
+GCLI should be:
+
+- primarily for technical users.
+- as fast as a traditional CLI. It should be possible to put your head down,
+ and look at the keyboard and use GCLI 'blind' at full speed without making
+ mistakes.
+- principled about the way it encourages people to build commands. There is
+ benefit from unifying the underlying concepts.
+- automatically helpful.
+
+GCLI should not attempt to:
+
+- convert existing GUI users to a CLI.
+- use natural language input. The closest we should get to natural language is
+ thinking of commands as ```verb noun --adjective```.
+- gain a touch based interface. Whilst it's possible (even probable) that touch
+ can provide further benefits to command line users, that can wait while we
+ catch up with 1985.
+- slavishly follow the syntax of existing commands, predictability is more
+ important.
+- be a programming language. Shell scripts are mini programming languages but
+ we have JavaScript sat just next door. It's better to integrate than compete.
+
+
+## Design Challenges
+
+What has changed since 1970 that might cause us to make changes to the design
+of the command line?
+
+
+### Connection limitations
+
+Unix pre-dates the Internet and treats almost everything as a file. Since the
+Internet it could be more useful to use URIs as ways to identify sources of data.
+
+
+### Memory limitations
+
+Modern computers have something like 6 orders of magnitude more memory than the
+PDP-7 on which Unix was developed. Innovations like stdin/stdout and pipes are
+ways to connect systems without long-term storage of the results. The ability
+to store results for some time (potentially in more than one format)
+significantly reduces the need for these concepts. We should make the results
+of past commands addressable for re-use at a later time.
+
+There are a number of possible policies for eviction of items from the history.
+We should investigate options other than a simple stack.
+
+
+### Multi-tasking limitations
+
+Multi-tasking was a problem in 1970; the problem was getting a computer to do
+many jobs on 1 core. Today the problem is getting a computer to do one job on
+many cores. However we're stuck with this legacy in 2 ways. Firstly that the
+default is to force everything to wait until the previous job is finished, but
+more importantly that output from parallel jobs frequently collides
+
+ $ find / -ctime 5d -print &
+ $ find / -uid 0 -print &
+ // good luck working out what came from where
+
+ $ tail -f logfile.txt &
+ $ vi main.c
+ // have a nice time editing that file
+
+GCLI should allow commands to be asynchronous and will provide UI elements to
+inform the user of job completion. It will also keep asynchronous command
+output contained within it's own display area.
+
+
+### Output limitations
+
+The PDP-7 had a teletype. There is something like 4 orders of magnitude more
+information that can be displayed on a modern display than a 80x24 character
+based console. We can use this flexibility to provide better help to the user
+in entering their command.
+
+The additional display richness can also allow interaction with result output.
+Command output can include links to follow-up commands, and even ask for
+additional input. (e.g. "your search returned zero results do you want to try
+again with a different search string")
+
+There is no reason why output must be static. For example, it could be
+informative to see the results of an "ls" command alter given changes made by
+subsequent commands. (It should be noted that there are times when historical
+information is important too)
+
+
+### Integration limitations
+
+In 1970, command execution meant retrieving a program from storage, and running
+it. This required minimal interaction between the command line processor and
+the program being run, and was good for resource constrained systems.
+This lack of interaction resulted in the processing of command line arguments
+being done everywhere, when the task was better suited to command line.
+We should provide metadata about the commands being run, to allow the command
+line to process, interpret and provide help on the input.
diff --git a/devtools/shared/gcli/source/docs/developing-gcli.md b/devtools/shared/gcli/source/docs/developing-gcli.md
new file mode 100644
index 000000000..113712655
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/developing-gcli.md
@@ -0,0 +1,213 @@
+
+# Developing GCLI
+
+## About the code
+
+The majority of the GCLI source is stored in the ``lib`` directory.
+
+The ``docs`` directory contains documentation.
+The ``scripts`` directory contains RequireJS that GCLI uses.
+The ``build`` directory contains files used when creating builds.
+The ``mozilla`` directory contains the mercurial patch queue of patches to apply
+to mozilla-central.
+The ``selenium-tests`` directory contains selenium web-page integration tests.
+
+The source in the ``lib`` directory is split into 4 sections:
+
+- ``lib/demo`` contains commands used in the demo page. It is not needed except
+ for demo purposes.
+- ``lib/test`` contains a small test harness for testing GCLI.
+- ``lib/gclitest`` contains tests that run in the test harness
+- ``lib/gcli`` contains the actual meat
+
+GCLI is split into a UI portion and a Model/Controller portion.
+
+
+## The GCLI Model
+
+The heart of GCLI is a ``Requisition``, which is an AST for the input. A
+``Requisition`` is a command that we'd like to execute, and we're filling out
+all the inputs required to execute the command.
+
+A ``Requisition`` has a ``Command`` that is to be executed. Each Command has a
+number of ``Parameter``s, each of which has a name and a type as detailed
+above.
+
+As you type, your input is split into ``Argument``s, which are then assigned to
+``Parameter``s using ``Assignment``s. Each ``Assignment`` has a ``Conversion``
+which stores the input argument along with the value that is was converted into
+according to the type of the parameter.
+
+There are special assignments called ``CommandAssignment`` which the
+``Requisition`` uses to link to the command to execute, and
+``UnassignedAssignment``used to store arguments that do not have a parameter
+to be assigned to.
+
+
+## The GCLI UI
+
+There are several components of the GCLI UI. Each can have a script portion,
+some template HTML and a CSS file. The template HTML is processed by
+``domtemplate`` before use.
+
+DomTemplate is fully documented in [it's own repository]
+(https://github.com/joewalker/domtemplate).
+
+The components are:
+
+- ``Inputter`` controls the input field, processing special keyboard events and
+ making sure that it stays in sync with the Requisition.
+- ``Completer`` updates a div that is located behind the input field and used
+ to display completion advice and hint highlights. It is stored in
+ completer.js.
+- ``Display`` is responsible for containing the popup hints that are displayed
+ above the command line. Typically Display contains a Hinter and a RequestsView
+ although these are not both required. Display itself is optional, and isn't
+ planned for use in the first release of GCLI in Firefox.
+- ``Hinter`` Is used to display input hints. It shows either a Menu or an
+ ArgFetch component depending on the state of the Requisition
+- ``Menu`` is used initially to select the command to be executed. It can act
+ somewhat like the Start menu on windows.
+- ``ArgFetch`` Once the command to be executed has been selected, ArgFetch
+ shows a 'dialog' allowing the user to enter the parameters to the selected
+ command.
+- ``RequestsView`` Contains a set of ``RequestView`` components, each of which
+ displays a command that has been invoked. RequestsView is a poor name, and
+ should better be called ReportView
+
+ArgFetch displays a number of Fields. There are fields for most of the Types
+discussed earlier. See 'Writing Fields' above for more information.
+
+
+## Testing
+
+GCLI contains 2 test suites:
+
+- JS level testing is run with the ``test`` command. The tests are located in
+ ``lib/gclitest`` and they use the test runner in ``lib/test``. This is fairly
+ comprehensive, however it does not do UI level testing.
+ If writing a new test it needs to be registered in ``lib/gclitest/index``.
+ For an example of how to write tests, see ``lib/gclitest/testSplit.js``.
+ The test functions are implemented in ``lib/test/assert``.
+- Browser integration tests are included in ``browser_webconsole_gcli_*.js``,
+ in ``toolkit/components/console/hudservice/tests/browser``. These are
+ run with the rest of the Mozilla test suite.
+
+
+## Coding Conventions
+
+The coding conventions for the GCLI project come from the Bespin/Skywriter and
+Ace projects. They are roughly [Crockford]
+(http://javascript.crockford.com/code.html) with a few exceptions and
+additions:
+
+* ``var`` does not need to be at the top of each function, we'd like to move
+ to ``let`` when it's generally available, and ``let`` doesn't have the same
+ semantic twists as ``var``.
+
+* Strings are generally enclosed in single quotes.
+
+* ``eval`` is to be avoided, but we don't declare it evil.
+
+The [Google JavaScript conventions]
+(https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) are
+more detailed, we tend to deviate in:
+
+* Custom exceptions: We generally just use ``throw new Error('message');``
+
+* Multi-level prototype hierarchies: Allowed; we don't have ``goog.inherits()``
+
+* ``else`` begins on a line by itself:
+
+ if (thing) {
+ doThis();
+ }
+ else {
+ doThat();
+ }
+
+
+## Startup
+
+Internally GCLI modules have ``startup()``/``shutdown()`` functions which are
+called on module init from the top level ``index.js`` of that 'package'.
+
+In order to initialize a package all that is needed is to require the package
+index (e.g. ``require('package/index')``).
+
+The ``shutdown()`` function was useful when GCLI was used in Bespin as part of
+dynamic registration/de-registration. It is not known if this feature will be
+useful in the future. So it has not been entirely removed, it may be at some
+future date.
+
+
+## Running the Unit Tests
+
+Start the GCLI static server:
+
+ cd path/to/gcli
+ node gcli.js
+
+Now point your browser to http://localhost:9999/localtest.html. When the page
+loads the tests will be automatically run outputting to the console, or you can
+enter the ``test`` command to run the unit tests.
+
+
+## Contributing Code
+
+Please could you do the following to help minimize the amount of rework that we
+do:
+
+1. Check the unit tests run correctly (see **Running the Unit Tests** above)
+2. Check the code follows the style guide. At a minimum it should look like the
+ code around it. For more detailed notes, see **Coding Conventions** above
+3. Help me review your work by using good commit comments. Which means 2 things
+ * Well formatted messages, i.e. 50 char summary including bug tag, followed
+ by a blank line followed by a more in-depth message wrapped to 72 chars
+ per line. This is basically the format used by the Linux Kernel. See the
+ [commit log](https://github.com/joewalker/gcli/commits/master) for
+ examples. The be extra helpful, please use the "shortdesc-BUGNUM: " if
+ possible which also helps in reviews.
+ * Commit your changes as a story. Make it easy for me to understand the
+ changes that you've made.
+4. Sign your work. To improve tracking of who did what, we follow the sign-off
+ procedure used in the Linux Kernel.
+ The sign-off is a simple line at the end of the explanation for the
+ patch, which certifies that you wrote it or otherwise have the right to
+ pass it on as an open-source patch. The rules are pretty simple: if you
+ can certify the below:
+
+ Developer's Certificate of Origin 1.1
+
+ By making a contribution to this project, I certify that:
+
+ (a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+ (b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+ (c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
+ then you just add a line saying
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+ using your real name (sorry, no pseudonyms or anonymous contributions.)
+
+Thanks for wanting to contribute code.
+
diff --git a/devtools/shared/gcli/source/docs/index.md b/devtools/shared/gcli/source/docs/index.md
new file mode 100644
index 000000000..dce112e6d
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/index.md
@@ -0,0 +1,150 @@
+
+# About GCLI
+
+## GCLI is a Graphical Command Line Interpreter.
+
+GCLI is a command line for modern computers. When command lines were invented,
+computers were resource-limited, disconnected systems with slow multi-tasking
+and poor displays. The design of the Unix CLI made sense in 1970, but over 40
+years on, considering the pace of change, there are many improvements we can
+make.
+
+CLIs generally suffer from poor discoverability; It's hard when faced with a
+blank command line to work out what to do. As a result the majority of programs
+today use purely graphical user interfaces, however in doing so, they lose some
+of the benefits of CLIs. CLIs are still used because generally, in the hands of
+a skilled user they are faster, and have a wider range of available options.
+
+GCLI attempts to get the best of the GUI world and the CLI world to produce
+something that is both easy to use and learn as well as fast and powerful.
+
+GCLI has a type system to help ensure that users are inputting valid commands
+and to enable us to provide sensible context sensitive help. GCLI provides
+integration with JavaScript rather than being an alternative (like CoffeeScript).
+
+
+## History
+
+GCLI was born as part of the
+[Bespin](http://ajaxian.com/archives/canvas-for-a-text-editor) project and was
+[discussed at the time](http://j.mp/bespin-cli). The command line component
+survived the rename of Bepsin to Skywriter and the merger with Ace, got a name
+of it's own (Cockpit) which didn't last long before the project was named GCLI.
+It is now being used in the Firefox's web console where it doesn't have a
+separate identity but it's still called GCLI outside of Firefox. It is also
+used in [Eclipse Orion](http://www.eclipse.org/orion/).
+
+
+## Environments
+
+GCLI is designed to work in a number of environments:
+
+1. As a component of Firefox developer tools.
+2. As an adjunct to Orion/Ace and other online editors.
+3. As a plugin to any web-page wishing to provide its own set of commands.
+4. As part of a standalone web browser extension with it's own set of commands.
+
+
+## Related Pages
+
+Other sources of GCLI documentation:
+
+- [Writing Commands](writing-commands.md)
+- [Writing Types](writing-types.md)
+- [Developing GCLI](developing-gcli.md)
+- [Writing Tests](writing-tests.md) / [Running Tests](running-tests.md)
+- [The Design of GCLI](design.md)
+- Source
+ - The most up-to-date source is in [this Github repository](https://github.com/joewalker/gcli/).
+ - When a feature is 'done' it's merged into the [Mozilla clone](https://github.com/mozilla/gcli/).
+ - From which it flows into [Mozilla Central](https://hg.mozilla.org/mozilla-central/file/tip/devtools/client/commandline).
+- [Demo of GCLI](http://mozilla.github.com/gcli/) with an arbitrary set of demo
+ commands
+- Other Documentation
+ - [Embedding docs](https://github.com/mozilla/gcli/blob/master/docs/index.md)
+ - [Status page](http://mozilla.github.com/devtools/2011/status.html#gcli)
+
+
+## Accessibility
+
+GCLI uses ARIA roles to guide a screen-reader as to the important sections to
+voice. We welcome [feedback on how these roles are implemented](https://bugzilla.mozilla.org/enter_bug.cgi?product=Firefox&component=Developer+Tools:+Graphic+Commandline+and+Toolbar&rep_platform=All&op_sys=All&short_desc=GCLI).
+
+The command line uses TAB as a method of completing current input, this
+prevents use of TAB for keyboard navigation. Instead of using TAB to move to
+the next field you can use F6. In addition to F6, ALT+TAB, CTRL+TAB, META+TAB
+make an attempt to move the focus on. How well this works depends on your
+OS/browser combination.
+
+
+## Embedding GCLI
+
+There are 3 basic steps in using GCLI in your system.
+
+1. Import a GCLI JavaScript file.
+ For serious use of GCLI you are likely to be creating a custom build (see
+ below) however if you just want to have a quick play, you can use
+ ``gcli-uncompressed.js`` from [the gh-pages branch of GCLI]
+ (https://github.com/mozilla/gcli/tree/gh-pages)
+ Just place the following wherever you place your script files.
+
+ <script src="path/to/gcli-uncompressed.js" type="text/javascript"></script>
+
+2. Having imported GCLI, we need to tell it where to display. The simplest
+ method is to include an elements with the id of ``gcli-input`` and
+ ``gcli-display``.
+
+ <input id="gcli-input" type="text"/>
+ <div id="gcli-display"></div>
+
+3. Tell GCLI what commands to make available. See the sections on Writing
+ Commands, Writing Types and Writing Fields for more information.
+
+ GCLI uses the CommonJS AMD format for it's files, so a 'require' statement
+ is needed to get started.
+
+ require([ 'gcli/index' ], function(gcli) {
+ gcli.add(...); // Register custom commands/types/etc
+ gcli.createTerminal(); // Create a user interface
+ });
+
+ The createTerminal() function takes an ``options`` objects which allows
+ customization. At the current time the documentation of these object is left
+ to the source.
+
+
+## Backwards Compatibility
+
+The goals of the GCLI project are:
+
+- Aim for very good backwards compatibility with code required from an
+ 'index' module. This means we will not break code without a cycle of
+ deprecation warnings.
+
+ There are currently 3 'index' modules:
+ - gcli/index (all you need to get started with GCLI)
+ - demo/index (a number of demo commands)
+ - gclitest/index (GCLI test suite)
+
+ Code from these modules uses the module pattern to prevent access to internal
+ functions, so in essence, if you can get to it from an index module, you
+ should be ok.
+
+- We try to avoid needless change to other modules, however we don't make any
+ promises, and don't provide a deprecation cycle.
+
+ Code from other modules uses classes rather than modules, so member variables
+ are exposed. Many classes mark private members using the `_underscorePrefix`
+ pattern. Particular care should be taken if access is needed to a private
+ member.
+
+
+## Creating Custom Builds
+
+GCLI uses [DryIce](https://github.com/mozilla/dryice) to create custom builds.
+If dryice is installed (``npm install .``) then you can create a built
+version of GCLI simply using ``node gcli.js standard``. DryIce supplies a custom
+module loader to replace RequireJS for built applications.
+
+The build will be output to the ``built`` directory. The directory will be
+created if it doesn't exist.
diff --git a/devtools/shared/gcli/source/docs/running-tests.md b/devtools/shared/gcli/source/docs/running-tests.md
new file mode 100644
index 000000000..378c40837
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/running-tests.md
@@ -0,0 +1,60 @@
+
+# Running Tests
+
+GCLI has a test suite that can be run in a number of different environments.
+Some of the tests don't work in all environments. These should be automatically
+skipped when not applicable.
+
+
+## Web
+
+Running a limited set of test from the web is the easiest. Simply load
+'localtest.html' and the unit tests should be run automatically, with results
+displayed on the console. Tests can be re-run using the 'test' command.
+
+It also creates a function 'testCommands()' to be run at a JS prompt, which
+enables the test commands for debugging purposes.
+
+
+## Firefox
+
+GCLI's test suite integrates with Mochitest and runs automatically on each test
+run. Dryice packages the tests to format them for the Firefox build system.
+
+For more information about running Mochitest on Firefox (including GCLI) see
+[the MDN, Mochitest docs](https://developer.mozilla.org/en/Mochitest)
+
+
+# Node
+
+Running the test suite under node can be done as follows:
+
+ $ node gcli.js test
+
+Or, using the `test` command:
+
+ $ node gcli.js
+ Serving GCLI to http://localhost:9999/
+ This is also a limited GCLI prompt.
+ Type 'help' for a list of commands, CTRL+C twice to exit:
+ : test
+
+ testCli: Pass (funcs=9, checks=208)
+ testCompletion: Pass (funcs=1, checks=139)
+ testExec: Pass (funcs=1, checks=133)
+ testHistory: Pass (funcs=3, checks=13)
+ ....
+
+ Summary: Pass (951 checks)
+
+
+# Travis CI
+
+GCLI check-ins are automatically tested by [Travis CI](https://travis-ci.org/joewalker/gcli).
+
+
+# Test Case Generation
+
+GCLI can generate test cases automagically. Load ```localtest.html```, type a
+command to be tested into GCLI, and the press F2. GCLI will output to the
+console a template test case for the entered command.
diff --git a/devtools/shared/gcli/source/docs/writing-commands.md b/devtools/shared/gcli/source/docs/writing-commands.md
new file mode 100644
index 000000000..e73050279
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/writing-commands.md
@@ -0,0 +1,757 @@
+
+# Writing Commands
+
+## Basics
+
+GCLI has opinions about how commands should be written, and it encourages you
+to do The Right Thing. The opinions are based on helping users convert their
+intentions to commands and commands to what's actually going to happen.
+
+- Related commands should be sub-commands of a parent command. One of the goals
+ of GCLI is to support a large number of commands without things becoming
+ confusing, this will require some sort of namespacing or there will be
+ many people wanting to implement the ``add`` command. This style of
+ writing commands has become common place in Unix as the number of commands
+ has gone up.
+ The ```context``` command allows users to focus on a parent command, promoting
+ its sub-commands above others.
+
+- Each command should do exactly and only one thing. An example of a Unix
+ command that breaks this principle is the ``tar`` command
+
+ $ tar -zcf foo.tar.gz .
+ $ tar -zxf foo.tar.gz .
+
+ These 2 commands do exactly opposite things. Many a file has died as a result
+ of a x/c typo. In GCLI this would be better expressed:
+
+ $ tar create foo.tar.gz -z .
+ $ tar extract foo.tar.gz -z .
+
+ There may be commands (like tar) which have enough history behind them
+ that we shouldn't force everyone to re-learn a new syntax. The can be achieved
+ by having a single string parameter and parsing the input in the command)
+
+- Avoid errors. We try to avoid the user having to start again with a command
+ due to some problem. The majority of problems are simple typos which we can
+ catch using command metadata, but there are 2 things command authors can do
+ to prevent breakage.
+
+ - Where possible avoid the need to validate command line parameters in the
+ exec function. This can be done by good parameter design (see 'do exactly
+ and only one thing' above)
+
+ - If there is an obvious fix for an unpredictable problem, offer the
+ solution in the command output. So rather than use request.error (see
+ Request Object below) output some HTML which contains a link to a fixed
+ command line.
+
+Currently these concepts are not enforced at a code level, but they could be in
+the future.
+
+
+## How commands work
+
+This is how to create a basic ``greet`` command:
+
+ gcli.addItems([{
+ name: 'greet',
+ description: 'Show a greeting',
+ params: [
+ {
+ name: 'name',
+ type: 'string',
+ description: 'The name to greet'
+ }
+ ],
+ returnType: 'string',
+ exec: function(args, context) {
+ return 'Hello, ' + args.name;
+ }
+ }]);
+
+This command is used as follows:
+
+ : greet Joe
+ Hello, Joe
+
+Some terminology that isn't always obvious: a function has 'parameters', and
+when you call a function, you pass 'arguments' to it.
+
+
+## Internationalization (i18n)
+
+There are several ways that GCLI commands can be localized. The best method
+depends on what context you are writing your command for.
+
+### Firefox Embedding
+
+GCLI supports Mozilla style localization. To add a command that will only ever
+be used embedded in Firefox, this is the way to go. Your strings should be
+stored in ``toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties``,
+And you should access them using ``let l10n = require("gcli/l10n")`` and then
+``l10n.lookup(...)`` or ``l10n.lookupFormat()``
+
+For examples of existing commands, take a look in
+``devtools/client/webconsole/GcliCommands.jsm``, which contains most of the
+current GCLI commands. If you will be adding a number of new commands, then
+consider starting a new JSM.
+
+Your command will then look something like this:
+
+ gcli.addItems([{
+ name: 'greet',
+ description: gcli.lookup("greetDesc")
+ ...
+ }]);
+
+### Web Commands
+
+There are 2 ways to provide translated strings for web use. The first is to
+supply the translated strings in the description:
+
+ gcli.addItems([{
+ name: 'greet',
+ description: {
+ 'root': 'Show a greeting',
+ 'fr-fr': 'Afficher un message d'accueil',
+ 'de-de': 'Zeige einen Gruß',
+ 'gk-gk': 'Εμφάνιση ένα χαιρετισμό',
+ ...
+ }
+ ...
+ }]);
+
+Each description should contain at least a 'root' entry which is the
+default if no better match is found. This method has the benefit of being
+compact and simple, however it has the significant drawback of being wasteful
+of memory and bandwidth to transmit and store a significant number of strings,
+the majority of which will never be used.
+
+More efficient is to supply a lookup key and ask GCLI to lookup the key from an
+appropriate localized strings file:
+
+ gcli.addItems([{
+ name: 'greet',
+ description: { 'key': 'demoGreetingDesc' }
+ ...
+ }]);
+
+For web usage, the central store of localized strings is
+``lib/gcli/nls/strings.js``. Other string files can be added using the
+``l10n.registerStringsSource(...)`` function.
+
+This method can be used both in Firefox and on the Web (see the help command
+for an example). However this method has the drawback that it will not work
+with DryIce built files until we fix bug 683844.
+
+
+## Default argument values
+
+The ``greet`` command requires the entry of the ``name`` parameter. This
+parameter can be made optional with the addition of a ``defaultValue`` to the
+parameter:
+
+ gcli.addItems([{
+ name: 'greet',
+ description: 'Show a message to someone',
+ params: [
+ {
+ name: 'name',
+ type: 'string',
+ description: 'The name to greet',
+ defaultValue: 'World!'
+ }
+ ],
+ returnType: 'string',
+ exec: function(args, context) {
+ return "Hello, " + args.name;
+ }
+ }]);
+
+Now we can also use the ``greet`` command as follows:
+
+ : greet
+ Hello, World!
+
+
+## Positional vs. named arguments
+
+Arguments can be entered either positionally or as named arguments. Generally
+users will prefer to type the positional version, however the named alternative
+can be more self documenting.
+
+For example, we can also invoke the greet command as follows:
+
+ : greet --name Joe
+ Hello, Joe
+
+
+## Short argument names
+
+GCLI allows you to specify a 'short' character for any parameter:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ {
+ name: 'name',
+ short: 'n',
+ type: 'string',
+ ...
+ }
+ ],
+ ...
+ }]);
+
+This is used as follows:
+
+ : greet -n Fred
+ Hello, Fred
+
+Currently GCLI does not allow short parameter merging (i.e. ```ls -la```)
+however this is planned.
+
+
+## Parameter types
+
+Initially the available types are:
+
+- string
+- boolean
+- number
+- selection
+- delegate
+- date
+- array
+- file
+- node
+- nodelist
+- resource
+- command
+- setting
+
+This list can be extended. See [Writing Types](writing-types.md) on types for
+more information.
+
+The following examples assume the following definition of the ```greet```
+command:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'name', type: 'string' },
+ { name: 'repeat', type: 'number' }
+ ],
+ ...
+ }]);
+
+Parameters can be specified either with named arguments:
+
+ : greet --name Joe --repeat 2
+
+And sometimes positionally:
+
+ : greet Joe 2
+
+Parameters can be specified positionally if they are considered 'important'.
+Unimportant parameters must be specified with a named argument.
+
+Named arguments can be specified anywhere on the command line (after the
+command itself) however positional arguments must be in order. So
+these examples are the same:
+
+ : greet --name Joe --repeat 2
+ : greet --repeat 2 --name Joe
+
+However (obviously) these are not the same:
+
+ : greet Joe 2
+ : greet 2 Joe
+
+(The second would be an error because 'Joe' is not a number).
+
+Named arguments are assigned first, then the remaining arguments are assigned
+to the remaining parameters. So the following is valid and unambiguous:
+
+ : greet 2 --name Joe
+
+Positional parameters quickly become unwieldy with long parameter lists so we
+recommend only having 2 or 3 important parameters. GCLI provides hints for
+important parameters more obviously than unimportant ones.
+
+Parameters are 'important' if they are not in a parameter group. The easiest way
+to achieve this is to use the ```option: true``` property.
+
+For example, using:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'name', type: 'string' },
+ { name: 'repeat', type: 'number', option: true, defaultValue: 1 }
+ ],
+ ...
+ }]);
+
+Would mean that this is an error
+
+ : greet Joe 2
+
+You would instead need to do the following:
+
+ : greet Joe --repeat 2
+
+For more on parameter groups, see below.
+
+In addition to being 'important' and 'unimportant' parameters can also be
+optional. If is possible to be important and optional, but it is not possible
+to be unimportant and non-optional.
+
+Parameters are optional if they either:
+- Have a ```defaultValue``` property
+- Are of ```type=boolean``` (boolean arguments automatically default to being false)
+
+There is currently no way to make parameters mutually exclusive.
+
+
+## Selection types
+
+Parameters can have a type of ``selection``. For example:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'name', ... },
+ {
+ name: 'lang',
+ description: 'In which language should we greet',
+ type: { name: 'selection', data: [ 'en', 'fr', 'de', 'es', 'gk' ] },
+ defaultValue: 'en'
+ }
+ ],
+ ...
+ }]);
+
+GCLI will enforce that the value of ``arg.lang`` was one of the values
+specified. Alternatively ``data`` can be a function which returns an array of
+strings.
+
+The ``data`` property is useful when the underlying type is a string but it
+doesn't work when the underlying type is something else. For this use the
+``lookup`` property as follows:
+
+ type: {
+ name: 'selection',
+ lookup: {
+ 'en': Locale.EN,
+ 'fr': Locale.FR,
+ ...
+ }
+ },
+
+Similarly, ``lookup`` can be a function returning the data of this type.
+
+
+## Number types
+
+Number types are mostly self explanatory, they have one special property which
+is the ability to specify upper and lower bounds for the number:
+
+ gcli.addItems([{
+ name: 'volume',
+ params: [
+ {
+ name: 'vol',
+ description: 'How loud should we go',
+ type: { name: 'number', min: 0, max: 11 }
+ }
+ ],
+ ...
+ }]);
+
+You can also specify a ``step`` property which specifies by what amount we
+should increment and decrement the values. The ``min``, ``max``, and ``step``
+properties are used by the command line when up and down are pressed and in
+the input type of a dialog generated from this command.
+
+
+## Delegate types
+
+Delegate types are needed when the type of some parameter depends on the type
+of another parameter. For example:
+
+ : set height 100
+ : set name "Joe Walker"
+
+We can achieve this as follows:
+
+ gcli.addItems([{
+ name: 'set',
+ params: [
+ {
+ name: 'setting',
+ type: { name: 'selection', values: [ 'height', 'name' ] }
+ },
+ {
+ name: 'value',
+ type: {
+ name: 'delegate',
+ delegateType: function() { ... }
+ }
+ }
+ ],
+ ...
+ }]);
+
+Several details are left out of this example, like how the delegateType()
+function knows what the current setting is. See the ``pref`` command for an
+example.
+
+
+## Array types
+
+Parameters can have a type of ``array``. For example:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ {
+ name: 'names',
+ type: { name: 'array', subtype: 'string' },
+ description: 'The names to greet',
+ defaultValue: [ 'World!' ]
+ }
+ ],
+ ...
+ exec: function(args, context) {
+ return "Hello, " + args.names.join(', ') + '.';
+ }
+ }]);
+
+This would be used as follows:
+
+ : greet Fred Jim Shiela
+ Hello, Fred, Jim, Shiela.
+
+Or using named arguments:
+
+ : greet --names Fred --names Jim --names Shiela
+ Hello, Fred, Jim, Shiela.
+
+There can only be one ungrouped parameter with an array type, and it must be
+at the end of the list of parameters (i.e. just before any parameter groups).
+This avoids confusion as to which parameter an argument should be assigned.
+
+
+## Sub-commands
+
+It is common for commands to be groups into those with similar functionality.
+Examples include virtually all VCS commands, ``apt-get``, etc. There are many
+examples of commands that should be structured as in a sub-command style -
+``tar`` being the obvious example, but others include ``crontab``.
+
+Groups of commands are specified with the top level command not having an
+exec function:
+
+ gcli.addItems([
+ {
+ name: 'tar',
+ description: 'Commands to manipulate archives',
+ },
+ {
+ name: 'tar create',
+ description: 'Create a new archive',
+ exec: function(args, context) { ... },
+ ...
+ },
+ {
+ name: 'tar extract',
+ description: 'Extract from an archive',
+ exec: function(args, context) { ... },
+ ...
+ }
+ ]);
+
+
+## Parameter groups
+
+Parameters can be grouped into sections.
+
+There are 3 ways to assign a parameter to a group.
+
+The simplest uses ```option: true``` to put a parameter into the default
+'Options' group:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'repeat', type: 'number', option: true }
+ ],
+ ...
+ }]);
+
+The ```option``` property can also take a string to use an alternative parameter
+group:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'repeat', type: 'number', option: 'Advanced' }
+ ],
+ ...
+ }]);
+
+An example of how this can be useful is 'git' which categorizes parameters into
+'porcelain' and 'plumbing'.
+
+Finally, parameters can be grouped together as follows:
+
+ gcli.addItems([{
+ name: 'greet',
+ params: [
+ { name: 'name', type: 'string', description: 'The name to greet' },
+ {
+ group: 'Advanced Options',
+ params: [
+ { name: 'repeat', type: 'number', defaultValue: 1 },
+ { name: 'debug', type: 'boolean' }
+ ]
+ }
+ ],
+ ...
+ }]);
+
+This could be used as follows:
+
+ : greet Joe --repeat 2 --debug
+ About to send greeting
+ Hello, Joe
+ Hello, Joe
+ Done!
+
+Parameter groups must come after non-grouped parameters because non-grouped
+parameters can be assigned positionally, so their index is important. We don't
+want 'holes' in the order caused by parameter groups.
+
+
+## Command metadata
+
+Each command should have the following properties:
+
+- A string ``name``.
+- A short ``description`` string. Generally no more than 20 characters without
+ a terminating period/fullstop.
+- A function to ``exec``ute. (Optional for the parent containing sub-commands)
+ See below for more details.
+
+And optionally the following extra properties:
+
+- A declaration of the accepted ``params``.
+- A ``hidden`` property to stop the command showing up in requests for help.
+- A ``context`` property which defines the scope of the function that we're
+ calling. Rather than simply call ``exec()``, we do ``exec.call(context)``.
+- A ``manual`` property which allows a fuller description of the purpose of the
+ command.
+- A ``returnType`` specifying how we should handle the value returned from the
+ exec function.
+
+The ``params`` property is an array of objects, one for each parameter. Each
+parameter object should have the following 3 properties:
+
+- A string ``name``.
+- A short string ``description`` as for the command.
+- A ``type`` which refers to an existing Type (see Writing Types).
+
+Optionally each parameter can have these properties:
+
+- A ``defaultValue`` (which should be in the type specified in ``type``).
+ The defaultValue will be used when there is no argument supplied for this
+ parameter on the command line.
+ If the parameter has a ``defaultValue``, other than ``undefined`` then the
+ parameter is optional, and if unspecified on the command line, the matching
+ argument will have this value when the function is called.
+ If ``defaultValue`` is missing, or if it is set to ``undefined``, then the
+ system will ensure that a value is provided before anything is executed.
+ There are 2 special cases:
+ - If the type is ``selection``, then defaultValue must not be undefined.
+ The defaultValue must either be ``null`` (meaning that a value must be
+ supplied by the user) or one of the selection values.
+ - If the type is ``boolean``, then ``defaultValue:false`` is implied and
+ can't be changed. Boolean toggles are assumed to be off by default, and
+ should be named to match.
+- A ``manual`` property for parameters is exactly analogous to the ``manual``
+ property for commands - descriptive text that is longer than than 20
+ characters.
+
+
+## The Command Function (exec)
+
+The parameters to the exec function are designed to be useful when you have a
+large number of parameters, and to give direct access to the environment (if
+used).
+
+ gcli.addItems([{
+ name: 'echo',
+ description: 'The message to display.',
+ params: [
+ {
+ name: 'message',
+ type: 'string',
+ description: 'The message to display.'
+ }
+ ],
+ returnType: 'string',
+ exec: function(args, context) {
+ return args.message;
+ }
+ }]);
+
+The ``args`` object contains the values specified on the params section and
+provided on the command line. In this example it would contain the message for
+display as ``args.message``.
+
+The ``context`` object has the following signature:
+
+ {
+ environment: ..., // environment object passed to createTerminal()
+ exec: ..., // function to execute a command
+ update: ..., // function to alter the text of the input area
+ createView: ..., // function to help creating rich output
+ defer: ..., // function to create a deferred promise
+ }
+
+The ``environment`` object is opaque to GCLI. It can be used for providing
+arbitrary data to your commands about their environment. It is most useful
+when more than one command line exists on a page with similar commands in both
+which should act in their own ways.
+An example use for ``environment`` would be a page with several tabs, each
+containing an editor with a command line. Commands executed in those editors
+should apply to the relevant editor.
+The ``environment`` object is passed to GCLI at startup (probably in the
+``createTerminal()`` function).
+
+The ``document`` object is also passed to GCLI at startup. In some environments
+(e.g. embedded in Firefox) there is no global ``document``. This object
+provides a way to create DOM nodes.
+
+``defer()`` allows commands to execute asynchronously.
+
+
+## Returning data
+
+The command meta-data specifies the type of data returned by the command using
+the ``returnValue`` setting.
+
+``returnValue`` processing is currently functioning, but incomplete, and being
+tracked in [Bug 657595](http://bugzil.la/657595). Currently you should specify
+a ``returnType`` of ``string`` or ``html``. If using HTML, you can return
+either an HTML string or a DOM node.
+
+In the future, JSON will be strongly encouraged as the return type, with some
+formatting functions to convert the JSON to HTML.
+
+Asynchronous output is achieved using a promise created from the ``context``
+parameter: ``context.defer()``.
+
+Some examples of this is practice:
+
+ { returnType: "string" }
+ ...
+ return "example";
+
+GCLI interprets the output as a plain string. It will be escaped before display
+and available as input to other commands as a plain string.
+
+ { returnType: "html" }
+ ...
+ return "<p>Hello</p>";
+
+GCLI will interpret this as HTML, and parse it for display.
+
+ { returnType: "dom" }
+ ...
+ return util.createElement(context.document, 'div');
+
+``util.createElement`` is a utility to ensure use of the XHTML namespace in XUL
+and other XML documents. In an HTML document it's functionally equivalent to
+``context.document.createElement('div')``. If your command is likely to be used
+in Firefox or another XML environment, you should use it. You can import it
+with ``var util = require('util/util');``.
+
+GCLI will use the returned HTML element as returned. See notes on ``context``
+above.
+
+ { returnType: "number" }
+ ...
+ return 42;
+
+GCLI will display the element in a similar way to a string, but it the value
+will be available to future commands as a number.
+
+ { returnType: "date" }
+ ...
+ return new Date();
+
+ { returnType: "file" }
+ ...
+ return new File();
+
+Both these examples return data as a given type, for which a converter will
+be required before the value can be displayed. The type system is likely to
+change before this is finalized. Please contact the author for more
+information.
+
+ { returnType: "string" }
+ ...
+ var deferred = context.defer();
+ setTimeout(function() {
+ deferred.resolve("hello");
+ }, 500);
+ return deferred.promise;
+
+Errors can be signaled by throwing an exception. GCLI will display the message
+property (or the toString() value if there is no message property). (However
+see *3 principles for writing commands* above for ways to avoid doing this).
+
+
+## Specifying Types
+
+Types are generally specified by a simple string, e.g. ``'string'``. For most
+types this is enough detail. There are a number of exceptions:
+
+* Array types. We declare a parameter to be an array of things using ``[]``,
+ for example: ``number[]``.
+* Selection types. There are 3 ways to specify the options in a selection:
+ * Using a lookup map
+
+ type: {
+ name: 'selection',
+ lookup: { one:1, two:2, three:3 }
+ }
+
+ (The boolean type is effectively just a selection that uses
+ ``lookup:{ 'true': true, 'false': false }``)
+
+ * Using given strings
+
+ type: {
+ name: 'selection',
+ data: [ 'left', 'center', 'right' ]
+ }
+
+ * Using named objects, (objects with a ``name`` property)
+
+ type: {
+ name: 'selection',
+ data: [
+ { name: 'Google', url: 'http://www.google.com/' },
+ { name: 'Microsoft', url: 'http://www.microsoft.com/' },
+ { name: 'Yahoo', url: 'http://www.yahoo.com/' }
+ ]
+ }
+
+* Delegate type. It is generally best to inherit from Delegate in order to
+ provide a customization of this type. See settingValue for an example.
+
+See below for more information.
diff --git a/devtools/shared/gcli/source/docs/writing-tests.md b/devtools/shared/gcli/source/docs/writing-tests.md
new file mode 100644
index 000000000..4d42142cd
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/writing-tests.md
@@ -0,0 +1,20 @@
+
+# Writing Tests
+
+There are several sources of GCLI tests and several environments in which they
+are run.
+
+The majority of GCLI tests are stored in
+[this repository](https://github.com/joewalker/gcli/) in files named like
+```./lib/gclitest/test*.js```. These tests run in Firefox, Chrome, Opera,
+and NodeJS/JsDom
+
+See [Running Tests](running-tests.md) for further details.
+
+GCLI comes with a generic unit test harness (in ```./lib/test/```) and a
+set of helpers for creating GCLI tests (in ```./lib/gclitest/helpers.js```).
+
+# GCLI tests in Firefox
+
+The build process converts the GCLI tests to run under Mochitest inside the
+Firefox unit tests. It also adds some
diff --git a/devtools/shared/gcli/source/docs/writing-types.md b/devtools/shared/gcli/source/docs/writing-types.md
new file mode 100644
index 000000000..ed2f75438
--- /dev/null
+++ b/devtools/shared/gcli/source/docs/writing-types.md
@@ -0,0 +1,106 @@
+
+# Writing Types
+
+Commands are a fundamental building block because they are what the users
+directly interacts with, however they are built on ``Type``s. There are a
+number of built in types:
+
+* string. This is a JavaScript string
+* number. A JavaScript number
+* boolean. A JavaScript boolean
+* selection. This is an selection from a number of alternatives
+* delegate. This type could change depending on other factors, but is well
+ defined when one of the conversion routines is called.
+
+There are a number of additional types defined by Pilot and GCLI as
+extensions to the ``selection`` and ``delegate`` types
+
+* setting. One of the defined settings
+* settingValue. A value that can be applied to an associated setting.
+* command. One of the defined commands
+
+Most of our types are 'static' e.g. there is only one type of 'string', however
+some types like 'selection' and 'delegate' are customizable.
+
+All types must inherit from Type and have the following methods:
+
+ /**
+ * Convert the given <tt>value</tt> to a string representation.
+ * Where possible, there should be round-tripping between values and their
+ * string representations.
+ */
+ stringify: function(value) { return 'string version of value'; },
+
+ /**
+ * Convert the given <tt>str</tt> to an instance of this type.
+ * Where possible, there should be round-tripping between values and their
+ * string representations.
+ * @return Conversion
+ */
+ parse: function(str) { return new Conversion(...); },
+
+ /**
+ * The plug-in system, and other things need to know what this type is
+ * called. The name alone is not enough to fully specify a type. Types like
+ * 'selection' and 'delegate' need extra data, however this function returns
+ * only the name, not the extra data.
+ * <p>In old bespin, equality was based on the name. This may turn out to be
+ * important in Ace too.
+ */
+ name: 'example',
+
+In addition, defining the following function can be helpful, although Type
+contains default implementations:
+
+* nudge(value, by)
+
+Type, Conversion and Status are all declared by commands.js.
+
+The values produced by the parse function can be of any type, but if you are
+producing your own, you are strongly encouraged to include properties called
+``name`` and ``description`` where it makes sense. There are a number of
+places in GCLI where the UI will be able to provide better help to users if
+your values include these properties.
+
+
+# Writing Fields
+
+Fields are visual representations of types. For simple types like string it is
+enough to use ``<input type=...>``, however more complex types we may wish to
+provide a custom widget to allow the user to enter values of the given type.
+
+This is an example of a very simple new password field type:
+
+ function PasswordField(doc) {
+ this.doc = doc;
+ }
+
+ PasswordField.prototype = Object.create(Field.prototype);
+
+ PasswordField.prototype.createElement = function(assignment) {
+ this.assignment = assignment;
+ this.input = dom.createElement(this.doc, 'input');
+ this.input.type = 'password';
+ this.input.value = assignment.arg ? assignment.arg.text : '';
+
+ this.onKeyup = function() {
+ this.assignment.setValue(this.input.value);
+ }.bind(this);
+ this.input.addEventListener('keyup', this.onKeyup, false);
+
+ this.onChange = function() {
+ this.input.value = this.assignment.arg.text;
+ };
+ this.assignment.onAssignmentChange.add(this.onChange, this);
+
+ return this.input;
+ };
+
+ PasswordField.prototype.destroy = function() {
+ this.input.removeEventListener('keyup', this.onKeyup, false);
+ this.assignment.onAssignmentChange.remove(this.onChange, this);
+ };
+
+ PasswordField.claim = function(type) {
+ return type.name === 'password' ? Field.claim.MATCH : Field.claim.NO_MATCH;
+ };