|
1 |
|
2 # Writing Commands |
|
3 |
|
4 ## Basics |
|
5 |
|
6 GCLI has opinions about how commands should be written, and it encourages you |
|
7 to do The Right Thing. The opinions are based on helping users convert their |
|
8 intentions to commands and commands to what's actually going to happen. |
|
9 |
|
10 - Related commands should be sub-commands of a parent command. One of the goals |
|
11 of GCLI is to support a large number of commands without things becoming |
|
12 confusing, this will require some sort of namespacing or there will be |
|
13 many people wanting to implement the ``add`` command. This style of |
|
14 writing commands has become common place in Unix as the number of commands |
|
15 has gone up. |
|
16 The ```context``` command allows users to focus on a parent command, promoting |
|
17 its sub-commands above others. |
|
18 |
|
19 - Each command should do exactly and only one thing. An example of a Unix |
|
20 command that breaks this principle is the ``tar`` command |
|
21 |
|
22 $ tar -zcf foo.tar.gz . |
|
23 $ tar -zxf foo.tar.gz . |
|
24 |
|
25 These 2 commands do exactly opposite things. Many a file has died as a result |
|
26 of a x/c typo. In GCLI this would be better expressed: |
|
27 |
|
28 $ tar create foo.tar.gz -z . |
|
29 $ tar extract foo.tar.gz -z . |
|
30 |
|
31 There may be commands (like tar) which have enough history behind them |
|
32 that we shouldn't force everyone to re-learn a new syntax. The can be achieved |
|
33 by having a single string parameter and parsing the input in the command) |
|
34 |
|
35 - Avoid errors. We try to avoid the user having to start again with a command |
|
36 due to some problem. The majority of problems are simple typos which we can |
|
37 catch using command metadata, but there are 2 things command authors can do |
|
38 to prevent breakage. |
|
39 |
|
40 - Where possible avoid the need to validate command line parameters in the |
|
41 exec function. This can be done by good parameter design (see 'do exactly |
|
42 and only one thing' above) |
|
43 |
|
44 - If there is an obvious fix for an unpredictable problem, offer the |
|
45 solution in the command output. So rather than use request.error (see |
|
46 Request Object below) output some HTML which contains a link to a fixed |
|
47 command line. |
|
48 |
|
49 Currently these concepts are not enforced at a code level, but they could be in |
|
50 the future. |
|
51 |
|
52 |
|
53 ## How commands work |
|
54 |
|
55 This is how to create a basic ``greet`` command: |
|
56 |
|
57 gcli.addCommand({ |
|
58 name: 'greet', |
|
59 description: 'Show a greeting', |
|
60 params: [ |
|
61 { |
|
62 name: 'name', |
|
63 type: 'string', |
|
64 description: 'The name to greet' |
|
65 } |
|
66 ], |
|
67 returnType: 'string', |
|
68 exec: function(args, context) { |
|
69 return 'Hello, ' + args.name; |
|
70 } |
|
71 }); |
|
72 |
|
73 This command is used as follows: |
|
74 |
|
75 : greet Joe |
|
76 Hello, Joe |
|
77 |
|
78 Some terminology that isn't always obvious: a function has 'parameters', and |
|
79 when you call a function, you pass 'arguments' to it. |
|
80 |
|
81 |
|
82 ## Internationalization (i18n) |
|
83 |
|
84 There are several ways that GCLI commands can be localized. The best method |
|
85 depends on what context you are writing your command for. |
|
86 |
|
87 ### Firefox Embedding |
|
88 |
|
89 GCLI supports Mozilla style localization. To add a command that will only ever |
|
90 be used embedded in Firefox, this is the way to go. Your strings should be |
|
91 stored in ``browser/locales/en-US/chrome/browser/devtools/gclicommands.properties``, |
|
92 And you should access them using ``gcli.lookup(...)`` or ``gcli.lookupFormat()`` |
|
93 |
|
94 For examples of existing commands, take a look in |
|
95 ``browser/devtools/webconsole/GcliCommands.jsm``, which contains most of the |
|
96 current GCLI commands. If you will be adding a number of new commands, then |
|
97 consider starting a new JSM. |
|
98 |
|
99 Your command will then look something like this: |
|
100 |
|
101 gcli.addCommand({ |
|
102 name: 'greet', |
|
103 description: gcli.lookup("greetDesc") |
|
104 ... |
|
105 }); |
|
106 |
|
107 ### Web Commands |
|
108 |
|
109 There are 2 ways to provide translated strings for web use. The first is to |
|
110 supply the translated strings in the description: |
|
111 |
|
112 gcli.addCommand({ |
|
113 name: 'greet', |
|
114 description: { |
|
115 'root': 'Show a greeting', |
|
116 'fr-fr': 'Afficher un message d'accueil', |
|
117 'de-de': 'Zeige einen Gruß', |
|
118 'gk-gk': 'Εμφάνιση ένα χαιρετισμό', |
|
119 ... |
|
120 } |
|
121 ... |
|
122 }); |
|
123 |
|
124 Each description should contain at least a 'root' entry which is the |
|
125 default if no better match is found. This method has the benefit of being |
|
126 compact and simple, however it has the significant drawback of being wasteful |
|
127 of memory and bandwidth to transmit and store a significant number of strings, |
|
128 the majority of which will never be used. |
|
129 |
|
130 More efficient is to supply a lookup key and ask GCLI to lookup the key from an |
|
131 appropriate localized strings file: |
|
132 |
|
133 gcli.addCommand({ |
|
134 name: 'greet', |
|
135 description: { 'key': 'demoGreetingDesc' } |
|
136 ... |
|
137 }); |
|
138 |
|
139 For web usage, the central store of localized strings is |
|
140 ``lib/gcli/nls/strings.js``. Other string files can be added using the |
|
141 ``l10n.registerStringsSource(...)`` function. |
|
142 |
|
143 This method can be used both in Firefox and on the Web (see the help command |
|
144 for an example). However this method has the drawback that it will not work |
|
145 with DryIce built files until we fix bug 683844. |
|
146 |
|
147 |
|
148 ## Default argument values |
|
149 |
|
150 The ``greet`` command requires the entry of the ``name`` parameter. This |
|
151 parameter can be made optional with the addition of a ``defaultValue`` to the |
|
152 parameter: |
|
153 |
|
154 gcli.addCommand({ |
|
155 name: 'greet', |
|
156 description: 'Show a message to someone', |
|
157 params: [ |
|
158 { |
|
159 name: 'name', |
|
160 type: 'string', |
|
161 description: 'The name to greet', |
|
162 defaultValue: 'World!' |
|
163 } |
|
164 ], |
|
165 returnType: 'string', |
|
166 exec: function(args, context) { |
|
167 return "Hello, " + args.name; |
|
168 } |
|
169 }); |
|
170 |
|
171 Now we can also use the ``greet`` command as follows: |
|
172 |
|
173 : greet |
|
174 Hello, World! |
|
175 |
|
176 |
|
177 ## Positional vs. named arguments |
|
178 |
|
179 Arguments can be entered either positionally or as named arguments. Generally |
|
180 users will prefer to type the positional version, however the named alternative |
|
181 can be more self documenting. |
|
182 |
|
183 For example, we can also invoke the greet command as follows: |
|
184 |
|
185 : greet --name Joe |
|
186 Hello, Joe |
|
187 |
|
188 |
|
189 ## Short argument names |
|
190 |
|
191 GCLI allows you to specify a 'short' character for any parameter: |
|
192 |
|
193 gcli.addCommand({ |
|
194 name: 'greet', |
|
195 params: [ |
|
196 { |
|
197 name: 'name', |
|
198 short: 'n', |
|
199 type: 'string', |
|
200 ... |
|
201 } |
|
202 ], |
|
203 ... |
|
204 }); |
|
205 |
|
206 This is used as follows: |
|
207 |
|
208 : greet -n Fred |
|
209 Hello, Fred |
|
210 |
|
211 Currently GCLI does not allow short parameter merging (i.e. ```ls -la```) |
|
212 however this is planned. |
|
213 |
|
214 |
|
215 ## Parameter types |
|
216 |
|
217 Initially the available types are: |
|
218 |
|
219 - string |
|
220 - boolean |
|
221 - number |
|
222 - selection |
|
223 - delegate |
|
224 - date |
|
225 - array |
|
226 - file |
|
227 - node |
|
228 - nodelist |
|
229 - resource |
|
230 - command |
|
231 - setting |
|
232 |
|
233 This list can be extended. See [Writing Types](writing-types.md) on types for |
|
234 more information. |
|
235 |
|
236 The following examples assume the following definition of the ```greet``` |
|
237 command: |
|
238 |
|
239 gcli.addCommand({ |
|
240 name: 'greet', |
|
241 params: [ |
|
242 { name: 'name', type: 'string' }, |
|
243 { name: 'repeat', type: 'number' } |
|
244 ], |
|
245 ... |
|
246 }); |
|
247 |
|
248 Parameters can be specified either with named arguments: |
|
249 |
|
250 : greet --name Joe --repeat 2 |
|
251 |
|
252 And sometimes positionally: |
|
253 |
|
254 : greet Joe 2 |
|
255 |
|
256 Parameters can be specified positionally if they are considered 'important'. |
|
257 Unimportant parameters must be specified with a named argument. |
|
258 |
|
259 Named arguments can be specified anywhere on the command line (after the |
|
260 command itself) however positional arguments must be in order. So |
|
261 these examples are the same: |
|
262 |
|
263 : greet --name Joe --repeat 2 |
|
264 : greet --repeat 2 --name Joe |
|
265 |
|
266 However (obviously) these are not the same: |
|
267 |
|
268 : greet Joe 2 |
|
269 : greet 2 Joe |
|
270 |
|
271 (The second would be an error because 'Joe' is not a number). |
|
272 |
|
273 Named arguments are assigned first, then the remaining arguments are assigned |
|
274 to the remaining parameters. So the following is valid and unambiguous: |
|
275 |
|
276 : greet 2 --name Joe |
|
277 |
|
278 Positional parameters quickly become unwieldy with long parameter lists so we |
|
279 recommend only having 2 or 3 important parameters. GCLI provides hints for |
|
280 important parameters more obviously than unimportant ones. |
|
281 |
|
282 Parameters are 'important' if they are not in a parameter group. The easiest way |
|
283 to achieve this is to use the ```option: true``` property. |
|
284 |
|
285 For example, using: |
|
286 |
|
287 gcli.addCommand({ |
|
288 name: 'greet', |
|
289 params: [ |
|
290 { name: 'name', type: 'string' }, |
|
291 { name: 'repeat', type: 'number', option: true, defaultValue: 1 } |
|
292 ], |
|
293 ... |
|
294 }); |
|
295 |
|
296 Would mean that this is an error |
|
297 |
|
298 : greet Joe 2 |
|
299 |
|
300 You would instead need to do the following: |
|
301 |
|
302 : greet Joe --repeat 2 |
|
303 |
|
304 For more on parameter groups, see below. |
|
305 |
|
306 In addition to being 'important' and 'unimportant' parameters can also be |
|
307 optional. If is possible to be important and optional, but it is not possible |
|
308 to be unimportant and non-optional. |
|
309 |
|
310 Parameters are optional if they either: |
|
311 - Have a ```defaultValue``` property |
|
312 - Are of ```type=boolean``` (boolean arguments automatically default to being false) |
|
313 |
|
314 There is currently no way to make parameters mutually exclusive. |
|
315 |
|
316 |
|
317 ## Selection types |
|
318 |
|
319 Parameters can have a type of ``selection``. For example: |
|
320 |
|
321 gcli.addCommand({ |
|
322 name: 'greet', |
|
323 params: [ |
|
324 { name: 'name', ... }, |
|
325 { |
|
326 name: 'lang', |
|
327 description: 'In which language should we greet', |
|
328 type: { name: 'selection', data: [ 'en', 'fr', 'de', 'es', 'gk' ] }, |
|
329 defaultValue: 'en' |
|
330 } |
|
331 ], |
|
332 ... |
|
333 }); |
|
334 |
|
335 GCLI will enforce that the value of ``arg.lang`` was one of the values |
|
336 specified. Alternatively ``data`` can be a function which returns an array of |
|
337 strings. |
|
338 |
|
339 The ``data`` property is useful when the underlying type is a string but it |
|
340 doesn't work when the underlying type is something else. For this use the |
|
341 ``lookup`` property as follows: |
|
342 |
|
343 type: { |
|
344 name: 'selection', |
|
345 lookup: { |
|
346 'en': Locale.EN, |
|
347 'fr': Locale.FR, |
|
348 ... |
|
349 } |
|
350 }, |
|
351 |
|
352 Similarly, ``lookup`` can be a function returning the data of this type. |
|
353 |
|
354 |
|
355 ## Number types |
|
356 |
|
357 Number types are mostly self explanatory, they have one special property which |
|
358 is the ability to specify upper and lower bounds for the number: |
|
359 |
|
360 gcli.addCommand({ |
|
361 name: 'volume', |
|
362 params: [ |
|
363 { |
|
364 name: 'vol', |
|
365 description: 'How loud should we go', |
|
366 type: { name: 'number', min: 0, max: 11 } |
|
367 } |
|
368 ], |
|
369 ... |
|
370 }); |
|
371 |
|
372 You can also specify a ``step`` property which specifies by what amount we |
|
373 should increment and decrement the values. The ``min``, ``max``, and ``step`` |
|
374 properties are used by the command line when up and down are pressed and in |
|
375 the input type of a dialog generated from this command. |
|
376 |
|
377 |
|
378 ## Delegate types |
|
379 |
|
380 Delegate types are needed when the type of some parameter depends on the type |
|
381 of another parameter. For example: |
|
382 |
|
383 : set height 100 |
|
384 : set name "Joe Walker" |
|
385 |
|
386 We can achieve this as follows: |
|
387 |
|
388 gcli.addCommand({ |
|
389 name: 'set', |
|
390 params: [ |
|
391 { |
|
392 name: 'setting', |
|
393 type: { name: 'selection', values: [ 'height', 'name' ] } |
|
394 }, |
|
395 { |
|
396 name: 'value', |
|
397 type: { |
|
398 name: 'delegate', |
|
399 delegateType: function() { ... } |
|
400 } |
|
401 } |
|
402 ], |
|
403 ... |
|
404 }); |
|
405 |
|
406 Several details are left out of this example, like how the delegateType() |
|
407 function knows what the current setting is. See the ``pref`` command for an |
|
408 example. |
|
409 |
|
410 |
|
411 ## Array types |
|
412 |
|
413 Parameters can have a type of ``array``. For example: |
|
414 |
|
415 gcli.addCommand({ |
|
416 name: 'greet', |
|
417 params: [ |
|
418 { |
|
419 name: 'names', |
|
420 type: { name: 'array', subtype: 'string' }, |
|
421 description: 'The names to greet', |
|
422 defaultValue: [ 'World!' ] |
|
423 } |
|
424 ], |
|
425 ... |
|
426 exec: function(args, context) { |
|
427 return "Hello, " + args.names.join(', ') + '.'; |
|
428 } |
|
429 }); |
|
430 |
|
431 This would be used as follows: |
|
432 |
|
433 : greet Fred Jim Shiela |
|
434 Hello, Fred, Jim, Shiela. |
|
435 |
|
436 Or using named arguments: |
|
437 |
|
438 : greet --names Fred --names Jim --names Shiela |
|
439 Hello, Fred, Jim, Shiela. |
|
440 |
|
441 There can only be one ungrouped parameter with an array type, and it must be |
|
442 at the end of the list of parameters (i.e. just before any parameter groups). |
|
443 This avoids confusion as to which parameter an argument should be assigned. |
|
444 |
|
445 |
|
446 ## Sub-commands |
|
447 |
|
448 It is common for commands to be groups into those with similar functionality. |
|
449 Examples include virtually all VCS commands, ``apt-get``, etc. There are many |
|
450 examples of commands that should be structured as in a sub-command style - |
|
451 ``tar`` being the obvious example, but others include ``crontab``. |
|
452 |
|
453 Groups of commands are specified with the top level command not having an |
|
454 exec function: |
|
455 |
|
456 gcli.addCommand({ |
|
457 name: 'tar', |
|
458 description: 'Commands to manipulate archives', |
|
459 }); |
|
460 gcli.addCommand({ |
|
461 name: 'tar create', |
|
462 description: 'Create a new archive', |
|
463 exec: function(args, context) { ... }, |
|
464 ... |
|
465 }); |
|
466 gcli.addCommand({ |
|
467 name: 'tar extract', |
|
468 description: 'Extract from an archive', |
|
469 exec: function(args, context) { ... }, |
|
470 ... |
|
471 }); |
|
472 |
|
473 |
|
474 ## Parameter groups |
|
475 |
|
476 Parameters can be grouped into sections. |
|
477 |
|
478 There are 3 ways to assign a parameter to a group. |
|
479 |
|
480 The simplest uses ```option: true``` to put a parameter into the default |
|
481 'Options' group: |
|
482 |
|
483 gcli.addCommand({ |
|
484 name: 'greet', |
|
485 params: [ |
|
486 { name: 'repeat', type: 'number', option: true } |
|
487 ], |
|
488 ... |
|
489 }); |
|
490 |
|
491 The ```option``` property can also take a string to use an alternative parameter |
|
492 group: |
|
493 |
|
494 gcli.addCommand({ |
|
495 name: 'greet', |
|
496 params: [ |
|
497 { name: 'repeat', type: 'number', option: 'Advanced' } |
|
498 ], |
|
499 ... |
|
500 }); |
|
501 |
|
502 An example of how this can be useful is 'git' which categorizes parameters into |
|
503 'porcelain' and 'plumbing'. |
|
504 |
|
505 Finally, parameters can be grouped together as follows: |
|
506 |
|
507 gcli.addCommand({ |
|
508 name: 'greet', |
|
509 params: [ |
|
510 { name: 'name', type: 'string', description: 'The name to greet' }, |
|
511 { |
|
512 group: 'Advanced Options', |
|
513 params: [ |
|
514 { name: 'repeat', type: 'number', defaultValue: 1 }, |
|
515 { name: 'debug', type: 'boolean' } |
|
516 ] |
|
517 } |
|
518 ], |
|
519 ... |
|
520 }); |
|
521 |
|
522 This could be used as follows: |
|
523 |
|
524 : greet Joe --repeat 2 --debug |
|
525 About to send greeting |
|
526 Hello, Joe |
|
527 Hello, Joe |
|
528 Done! |
|
529 |
|
530 Parameter groups must come after non-grouped parameters because non-grouped |
|
531 parameters can be assigned positionally, so their index is important. We don't |
|
532 want 'holes' in the order caused by parameter groups. |
|
533 |
|
534 |
|
535 ## Command metadata |
|
536 |
|
537 Each command should have the following properties: |
|
538 |
|
539 - A string ``name``. |
|
540 - A short ``description`` string. Generally no more than 20 characters without |
|
541 a terminating period/fullstop. |
|
542 - A function to ``exec``ute. (Optional for the parent containing sub-commands) |
|
543 See below for more details. |
|
544 |
|
545 And optionally the following extra properties: |
|
546 |
|
547 - A declaration of the accepted ``params``. |
|
548 - A ``hidden`` property to stop the command showing up in requests for help. |
|
549 - A ``context`` property which defines the scope of the function that we're |
|
550 calling. Rather than simply call ``exec()``, we do ``exec.call(context)``. |
|
551 - A ``manual`` property which allows a fuller description of the purpose of the |
|
552 command. |
|
553 - A ``returnType`` specifying how we should handle the value returned from the |
|
554 exec function. |
|
555 |
|
556 The ``params`` property is an array of objects, one for each parameter. Each |
|
557 parameter object should have the following 3 properties: |
|
558 |
|
559 - A string ``name``. |
|
560 - A short string ``description`` as for the command. |
|
561 - A ``type`` which refers to an existing Type (see Writing Types). |
|
562 |
|
563 Optionally each parameter can have these properties: |
|
564 |
|
565 - A ``defaultValue`` (which should be in the type specified in ``type``). |
|
566 The defaultValue will be used when there is no argument supplied for this |
|
567 parameter on the command line. |
|
568 If the parameter has a ``defaultValue``, other than ``undefined`` then the |
|
569 parameter is optional, and if unspecified on the command line, the matching |
|
570 argument will have this value when the function is called. |
|
571 If ``defaultValue`` is missing, or if it is set to ``undefined``, then the |
|
572 system will ensure that a value is provided before anything is executed. |
|
573 There are 2 special cases: |
|
574 - If the type is ``selection``, then defaultValue must not be undefined. |
|
575 The defaultValue must either be ``null`` (meaning that a value must be |
|
576 supplied by the user) or one of the selection values. |
|
577 - If the type is ``boolean``, then ``defaultValue:false`` is implied and |
|
578 can't be changed. Boolean toggles are assumed to be off by default, and |
|
579 should be named to match. |
|
580 - A ``manual`` property for parameters is exactly analogous to the ``manual`` |
|
581 property for commands - descriptive text that is longer than than 20 |
|
582 characters. |
|
583 |
|
584 |
|
585 ## The Command Function (exec) |
|
586 |
|
587 The parameters to the exec function are designed to be useful when you have a |
|
588 large number of parameters, and to give direct access to the environment (if |
|
589 used). |
|
590 |
|
591 gcli.addCommand({ |
|
592 name: 'echo', |
|
593 description: 'The message to display.', |
|
594 params: [ |
|
595 { |
|
596 name: 'message', |
|
597 type: 'string', |
|
598 description: 'The message to display.' |
|
599 } |
|
600 ], |
|
601 returnType: 'string', |
|
602 exec: function(args, context) { |
|
603 return args.message; |
|
604 } |
|
605 }); |
|
606 |
|
607 The ``args`` object contains the values specified on the params section and |
|
608 provided on the command line. In this example it would contain the message for |
|
609 display as ``args.message``. |
|
610 |
|
611 The ``context`` object has the following signature: |
|
612 |
|
613 { |
|
614 environment: ..., // environment object passed to createTerminal() |
|
615 exec: ..., // function to execute a command |
|
616 update: ..., // function to alter the text of the input area |
|
617 createView: ..., // function to help creating rich output |
|
618 defer: ..., // function to create a deferred promise |
|
619 } |
|
620 |
|
621 The ``environment`` object is opaque to GCLI. It can be used for providing |
|
622 arbitrary data to your commands about their environment. It is most useful |
|
623 when more than one command line exists on a page with similar commands in both |
|
624 which should act in their own ways. |
|
625 An example use for ``environment`` would be a page with several tabs, each |
|
626 containing an editor with a command line. Commands executed in those editors |
|
627 should apply to the relevant editor. |
|
628 The ``environment`` object is passed to GCLI at startup (probably in the |
|
629 ``createTerminal()`` function). |
|
630 |
|
631 The ``document`` object is also passed to GCLI at startup. In some environments |
|
632 (e.g. embedded in Firefox) there is no global ``document``. This object |
|
633 provides a way to create DOM nodes. |
|
634 |
|
635 ``defer()`` allows commands to execute asynchronously. |
|
636 |
|
637 |
|
638 ## Returning data |
|
639 |
|
640 The command meta-data specifies the type of data returned by the command using |
|
641 the ``returnValue`` setting. |
|
642 |
|
643 ``returnValue`` processing is currently functioning, but incomplete, and being |
|
644 tracked in [Bug 657595](http://bugzil.la/657595). Currently you should specify |
|
645 a ``returnType`` of ``string`` or ``html``. If using HTML, you can return |
|
646 either an HTML string or a DOM node. |
|
647 |
|
648 In the future, JSON will be strongly encouraged as the return type, with some |
|
649 formatting functions to convert the JSON to HTML. |
|
650 |
|
651 Asynchronous output is achieved using a promise created from the ``context`` |
|
652 parameter: ``context.defer()``. |
|
653 |
|
654 Some examples of this is practice: |
|
655 |
|
656 { returnType: "string" } |
|
657 ... |
|
658 return "example"; |
|
659 |
|
660 GCLI interprets the output as a plain string. It will be escaped before display |
|
661 and available as input to other commands as a plain string. |
|
662 |
|
663 { returnType: "html" } |
|
664 ... |
|
665 return "<p>Hello</p>"; |
|
666 |
|
667 GCLI will interpret this as HTML, and parse it for display. |
|
668 |
|
669 { returnType: "dom" } |
|
670 ... |
|
671 return util.createElement(context.document, 'div'); |
|
672 |
|
673 ``util.createElement`` is a utility to ensure use of the XHTML namespace in XUL |
|
674 and other XML documents. In an HTML document it's functionally equivalent to |
|
675 ``context.document.createElement('div')``. If your command is likely to be used |
|
676 in Firefox or another XML environment, you should use it. You can import it |
|
677 with ``var util = require('util/util');``. |
|
678 |
|
679 GCLI will use the returned HTML element as returned. See notes on ``context`` |
|
680 above. |
|
681 |
|
682 { returnType: "number" } |
|
683 ... |
|
684 return 42; |
|
685 |
|
686 GCLI will display the element in a similar way to a string, but it the value |
|
687 will be available to future commands as a number. |
|
688 |
|
689 { returnType: "date" } |
|
690 ... |
|
691 return new Date(); |
|
692 |
|
693 { returnType: "file" } |
|
694 ... |
|
695 return new File(); |
|
696 |
|
697 Both these examples return data as a given type, for which a converter will |
|
698 be required before the value can be displayed. The type system is likely to |
|
699 change before this is finalized. Please contact the author for more |
|
700 information. |
|
701 |
|
702 { returnType: "string" } |
|
703 ... |
|
704 var deferred = context.defer(); |
|
705 setTimeout(function() { |
|
706 deferred.resolve("hello"); |
|
707 }, 500); |
|
708 return deferred.promise; |
|
709 |
|
710 Errors can be signaled by throwing an exception. GCLI will display the message |
|
711 property (or the toString() value if there is no message property). (However |
|
712 see *3 principles for writing commands* above for ways to avoid doing this). |
|
713 |
|
714 |
|
715 ## Specifying Types |
|
716 |
|
717 Types are generally specified by a simple string, e.g. ``'string'``. For most |
|
718 types this is enough detail. There are a number of exceptions: |
|
719 |
|
720 * Array types. We declare a parameter to be an array of things using ``[]``, |
|
721 for example: ``number[]``. |
|
722 * Selection types. There are 3 ways to specify the options in a selection: |
|
723 * Using a lookup map |
|
724 |
|
725 type: { |
|
726 name: 'selection', |
|
727 lookup: { one:1, two:2, three:3 } |
|
728 } |
|
729 |
|
730 (The boolean type is effectively just a selection that uses |
|
731 ``lookup:{ 'true': true, 'false': false }``) |
|
732 |
|
733 * Using given strings |
|
734 |
|
735 type: { |
|
736 name: 'selection', |
|
737 data: [ 'left', 'center', 'right' ] |
|
738 } |
|
739 |
|
740 * Using named objects, (objects with a ``name`` property) |
|
741 |
|
742 type: { |
|
743 name: 'selection', |
|
744 data: [ |
|
745 { name: 'Google', url: 'http://www.google.com/' }, |
|
746 { name: 'Microsoft', url: 'http://www.microsoft.com/' }, |
|
747 { name: 'Yahoo', url: 'http://www.yahoo.com/' } |
|
748 ] |
|
749 } |
|
750 |
|
751 * Delegate type. It is generally best to inherit from Delegate in order to |
|
752 provide a customization of this type. See settingValue for an example. |
|
753 |
|
754 See below for more information. |
|
755 |