electron 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +1 -0
- package/History.md +55 -0
- package/README.md +150 -3
- package/examples/clean.js +38 -0
- package/examples/simple.js +24 -0
- package/lib/electron/args.js +235 -0
- package/lib/electron/command.js +129 -6
- package/lib/electron/program.js +553 -0
- package/lib/electron/themes/clean.js +63 -0
- package/lib/electron/themes/index.js +17 -0
- package/lib/electron/themes/simple.js +71 -0
- package/lib/electron.js +46 -5
- package/package.json +6 -3
- package/examples/basic.js +0 -20
- package/lib/electron/cli.js +0 -169
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Electron - process.argv parsing
|
|
3
|
+
* Copyright (c) 2012 Jake Luer <jake@alogicalparadox.com>
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* External dependancies
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var Drip = require('drip')
|
|
12
|
+
, tty = require('tty')
|
|
13
|
+
, util = require('util');
|
|
14
|
+
|
|
15
|
+
/*!
|
|
16
|
+
* Electron dependancies
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
var Args = require('./args')
|
|
20
|
+
, Command = require('./command')
|
|
21
|
+
, themes = require('./themes');
|
|
22
|
+
|
|
23
|
+
/*!
|
|
24
|
+
* isTTY (can support color)
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
var istty = tty.isatty(1) && tty.isatty(2);
|
|
28
|
+
|
|
29
|
+
/*!
|
|
30
|
+
* defaults (a, b)
|
|
31
|
+
*
|
|
32
|
+
* Helper function to merge one object to another
|
|
33
|
+
* using the first object as default values.
|
|
34
|
+
*
|
|
35
|
+
* @param {Object} subject
|
|
36
|
+
* @param {Object} defaults
|
|
37
|
+
* @name defaults
|
|
38
|
+
* @api private
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
function defaults (a, b) {
|
|
42
|
+
if (a && b) {
|
|
43
|
+
for (var key in b) {
|
|
44
|
+
if ('undefined' == typeof a[key]) a[key] = b[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return a;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/*!
|
|
51
|
+
* Main export
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
module.exports = Program;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* ## Program Framework
|
|
58
|
+
*
|
|
59
|
+
* The primary export of the electron module is a function
|
|
60
|
+
* that composes a new program framework. The returned
|
|
61
|
+
* `program` is a chainable api that allow you to change
|
|
62
|
+
* settings, define commands, and start launch the program.
|
|
63
|
+
*
|
|
64
|
+
* The primary argument provided on construction is the base
|
|
65
|
+
* name used through the help documentation. In a majority of
|
|
66
|
+
* of cases, this would be the command executed from your terminal
|
|
67
|
+
* used launch the program.
|
|
68
|
+
*
|
|
69
|
+
* In the case of scripts with the header of `#!/usr/bin/env node`,
|
|
70
|
+
* you should use a variant of the following.
|
|
71
|
+
*
|
|
72
|
+
* var program = electron('microscope');
|
|
73
|
+
*
|
|
74
|
+
* If you are however launching your program from a `.js` file,
|
|
75
|
+
* the recommended construction pattern is the following.
|
|
76
|
+
*
|
|
77
|
+
* var program = electrong('node microscope.js');
|
|
78
|
+
*
|
|
79
|
+
* You can then chain any of the following commands to further
|
|
80
|
+
* define your application and commands.
|
|
81
|
+
*
|
|
82
|
+
* @header Program Framework
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
function Program (base, opts) {
|
|
86
|
+
/*!
|
|
87
|
+
* @param {String} base name
|
|
88
|
+
* @param {Object} options
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
Drip.call(this, { delimeter: ' ' });
|
|
92
|
+
this.commands = [];
|
|
93
|
+
this._colorized = false;
|
|
94
|
+
this.opts = defaults(opts || {}, {
|
|
95
|
+
useColors: istty
|
|
96
|
+
, version: null
|
|
97
|
+
, desc: null
|
|
98
|
+
, name: base || 'Electron'
|
|
99
|
+
, base: base || 'electron'
|
|
100
|
+
, cwd: process.cwd()
|
|
101
|
+
, theme: {
|
|
102
|
+
name: 'clean'
|
|
103
|
+
, spec: {
|
|
104
|
+
noColor: false
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*!
|
|
111
|
+
* Inherit from Drip event emitter.
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
util.inherits(Program, Drip);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* ### .command (name)
|
|
118
|
+
*
|
|
119
|
+
* The most important aspect of an application is defining
|
|
120
|
+
* the different commands that can be executed for it. Some
|
|
121
|
+
* people prefer a CLI tool that does one thing based on a
|
|
122
|
+
* set of options. Others prefer a command line tool that
|
|
123
|
+
* can pivot based on a command string. Electron supports both.
|
|
124
|
+
*
|
|
125
|
+
* When using the `command` method, it will return a constructed
|
|
126
|
+
* command object with a different set of methods for chaining.
|
|
127
|
+
* Please read the "Constructing Commands" section for all available
|
|
128
|
+
* chainable methods and their respective purpose.
|
|
129
|
+
*
|
|
130
|
+
* ##### Single Command
|
|
131
|
+
*
|
|
132
|
+
* As you understand how Electron parses command-line options,
|
|
133
|
+
* you know that a command is any option that does
|
|
134
|
+
* not start with `-` or `--`. Therefor, a single-command electron
|
|
135
|
+
* application is one that does not require any `commands`, but
|
|
136
|
+
* will execute a single action. Best demonstrated...
|
|
137
|
+
*
|
|
138
|
+
* $ node app.js -p 8080
|
|
139
|
+
*
|
|
140
|
+
* In the case of single-command applications, we will define
|
|
141
|
+
* a `default` command for electron to run.
|
|
142
|
+
*
|
|
143
|
+
* program
|
|
144
|
+
* .command('default')
|
|
145
|
+
* .action(function (argv) {
|
|
146
|
+
* var port = argv.param('p', 'port');
|
|
147
|
+
* // something cool
|
|
148
|
+
* });
|
|
149
|
+
*
|
|
150
|
+
* The `default` command will run when no commands are passed in,
|
|
151
|
+
* but it will not run if a command is provided.
|
|
152
|
+
*
|
|
153
|
+
* ##### Multiple Commands
|
|
154
|
+
*
|
|
155
|
+
* You can also create many different commands for your application
|
|
156
|
+
* based on a simple string. These can be used in conjunction
|
|
157
|
+
* with `default` if you would like.
|
|
158
|
+
*
|
|
159
|
+
* $ node app.js hello --universe
|
|
160
|
+
*
|
|
161
|
+
* In this case we want to only run an action when the comamnd
|
|
162
|
+
* `hello` is present. This can easily be achieved.
|
|
163
|
+
*
|
|
164
|
+
* program
|
|
165
|
+
* .command('hello')
|
|
166
|
+
* .action(fn);
|
|
167
|
+
*
|
|
168
|
+
* There are also cases where you might want to have multipe layers
|
|
169
|
+
* of commands.
|
|
170
|
+
*
|
|
171
|
+
* $ node app.js hello universe
|
|
172
|
+
*
|
|
173
|
+
* Using the same mechanism, we can easily define this action.
|
|
174
|
+
*
|
|
175
|
+
* program
|
|
176
|
+
* .command('hello universe')
|
|
177
|
+
* .action(fn);
|
|
178
|
+
*
|
|
179
|
+
* One final option to explore with multiple commands is wildcards.
|
|
180
|
+
* Wildcards can exist at any level in a multi-word command, but they
|
|
181
|
+
* only work for entire words, not substrings.
|
|
182
|
+
*
|
|
183
|
+
* program
|
|
184
|
+
* .command('hello *')
|
|
185
|
+
* .action(function (argv) {
|
|
186
|
+
* var where = argv.commands[1];
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* Would respond for any command starting with `hello` and is two
|
|
190
|
+
* commands long, such as...
|
|
191
|
+
*
|
|
192
|
+
* $ node app.js hello world
|
|
193
|
+
* $ node app.js hello universe
|
|
194
|
+
*
|
|
195
|
+
* ##### Absent Commands
|
|
196
|
+
*
|
|
197
|
+
* Should you want to notify your users when they attempt to use
|
|
198
|
+
* a command is not support, you may use the `absent` command. This
|
|
199
|
+
* is also useful if you want to have a single command app but
|
|
200
|
+
* support a list of items as "options", such as a list of files or
|
|
201
|
+
* directories.
|
|
202
|
+
*
|
|
203
|
+
* $ node build.js file1.js files2.js
|
|
204
|
+
*
|
|
205
|
+
* program
|
|
206
|
+
* .command('absent')
|
|
207
|
+
* .action(function (argv) {
|
|
208
|
+
* var files = argv.commands.slice(0);
|
|
209
|
+
* // something cool
|
|
210
|
+
* });
|
|
211
|
+
*
|
|
212
|
+
* @param {String} command name
|
|
213
|
+
* @returns chainable constructed command
|
|
214
|
+
* @name command
|
|
215
|
+
* @api public
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
Program.prototype.command = function (name) {
|
|
219
|
+
var cmd = new Command(name);
|
|
220
|
+
this.commands.push(cmd);
|
|
221
|
+
return cmd;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* ### .parse (process.argv)
|
|
226
|
+
*
|
|
227
|
+
* The `parse` method will initiate the program with
|
|
228
|
+
* selection of arguments and run a matching action. It
|
|
229
|
+
* should be used once all commands and settings have
|
|
230
|
+
* been propogated.
|
|
231
|
+
*
|
|
232
|
+
* program.parse();
|
|
233
|
+
* program.parse(process.argv);
|
|
234
|
+
* program.parse([ 'node', 'app.js', '--hello', '--universe' ]);
|
|
235
|
+
*
|
|
236
|
+
* If no parameter is provided, `parse` will default to using
|
|
237
|
+
* the current processes `process.argv` array. You may alse
|
|
238
|
+
* provide your own array of commands if you like. Note that
|
|
239
|
+
* argv parsing expectes the first item to be the executing program
|
|
240
|
+
* and the second argument to be the script (as is with all node argv).
|
|
241
|
+
* These will be discarded.
|
|
242
|
+
*
|
|
243
|
+
* @param {Array} process.argv or compable array
|
|
244
|
+
* @name parse
|
|
245
|
+
* @api public
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
Program.prototype.parse = function (args) {
|
|
249
|
+
args = args || process.argv;
|
|
250
|
+
var argv = new Args(args)
|
|
251
|
+
, cmds = mountCommands.call(this)
|
|
252
|
+
, command = argv.commands.slice(0);
|
|
253
|
+
|
|
254
|
+
argv.cwd = this.opts.cwd;
|
|
255
|
+
if (argv.mode('help', 'h')) {
|
|
256
|
+
displayHelp.call(this);
|
|
257
|
+
} else if (argv.mode('version', 'v')) {
|
|
258
|
+
displayVersion.call(this);
|
|
259
|
+
} else if (!command.length) {
|
|
260
|
+
if (cmds.def) cmds.def(argv);
|
|
261
|
+
} else if (!this.hasListener(command)) {
|
|
262
|
+
if (cmds.absent) cmds.absent(argv);
|
|
263
|
+
} else {
|
|
264
|
+
this.emit(command, argv);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return this;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* ### .name (name)
|
|
272
|
+
*
|
|
273
|
+
* Provide a formal name to be used when displaying
|
|
274
|
+
* the help for the given program. Returns the program
|
|
275
|
+
* for chaining.
|
|
276
|
+
*
|
|
277
|
+
* program.name('Electron Framework');
|
|
278
|
+
*
|
|
279
|
+
* @param {String} formal name
|
|
280
|
+
* @returns `this` for chaining
|
|
281
|
+
* @name name
|
|
282
|
+
* @api public
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
Program.prototype.name = function (name) {
|
|
286
|
+
this.opts.name = name;
|
|
287
|
+
return this;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* ### .version (version)
|
|
292
|
+
*
|
|
293
|
+
* Provide a program version to be used when displaying
|
|
294
|
+
* the version for the given program. Returns the program
|
|
295
|
+
* for chaining.
|
|
296
|
+
*
|
|
297
|
+
* program.version(electron.version);
|
|
298
|
+
*
|
|
299
|
+
* @param {String} application version
|
|
300
|
+
* @returns `this` for chaining
|
|
301
|
+
* @name version
|
|
302
|
+
* @api public
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
Program.prototype.version = function (v) {
|
|
306
|
+
this.opts.version = v;
|
|
307
|
+
return this;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* ### .desc (description)
|
|
312
|
+
*
|
|
313
|
+
* Provide a program discription to be used when displaying
|
|
314
|
+
* the the help for the given program. Returns the program
|
|
315
|
+
* for chaining.
|
|
316
|
+
*
|
|
317
|
+
* program.desc('https://github.com/logicalparadox/electron');
|
|
318
|
+
*
|
|
319
|
+
* @param {String} application description
|
|
320
|
+
* @returns `this` for chaining
|
|
321
|
+
* @name desc
|
|
322
|
+
* @api public
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
Program.prototype.desc = function (desc) {
|
|
326
|
+
this.opts.desc = desc;
|
|
327
|
+
return this;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* ### .cwd (fqp)
|
|
332
|
+
*
|
|
333
|
+
* Provide an alternative current working directory to be
|
|
334
|
+
* passed as part of the `argv` parameter to the action that has
|
|
335
|
+
* been executed. Returns the program for chaining.
|
|
336
|
+
*
|
|
337
|
+
* // set
|
|
338
|
+
* program.cwd(__dirname);
|
|
339
|
+
*
|
|
340
|
+
* // get
|
|
341
|
+
* program
|
|
342
|
+
* .command('universe')
|
|
343
|
+
* .action(function (argv) {
|
|
344
|
+
* var cwd = argv.cwd;
|
|
345
|
+
* // something cool
|
|
346
|
+
* });
|
|
347
|
+
*
|
|
348
|
+
* @param {String} fully quialified path
|
|
349
|
+
* @returns `this` for chaining
|
|
350
|
+
* @name cwd
|
|
351
|
+
* @api public
|
|
352
|
+
*/
|
|
353
|
+
|
|
354
|
+
Program.prototype.cwd = function (p) {
|
|
355
|
+
this.opts.cwd = p;
|
|
356
|
+
return this;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* ### .theme (theme, specifications)
|
|
361
|
+
*
|
|
362
|
+
* You may change the appearance of the `--help` using
|
|
363
|
+
* a simple theming mechanism. Electron comes bundled with
|
|
364
|
+
* two themes. Each theme also supports minor tweaks. Returns
|
|
365
|
+
* the program for chaining.
|
|
366
|
+
*
|
|
367
|
+
* ##### clean (default)
|
|
368
|
+
*
|
|
369
|
+
* A colorful and verbose theme useful for multi-command applications.
|
|
370
|
+
*
|
|
371
|
+
* program
|
|
372
|
+
* .theme('clean', {
|
|
373
|
+
* noColor: false // set to true to disable color coding
|
|
374
|
+
* , prefix: '' // prefix written before each line, such as 'help:'
|
|
375
|
+
* });
|
|
376
|
+
*
|
|
377
|
+
* <img alt="Electron Clean Theme" src="http://f.cl.ly/items/10283V3e2o1R0f2d2x32/electron-clean-theme.png" />
|
|
378
|
+
*
|
|
379
|
+
* ##### simple
|
|
380
|
+
*
|
|
381
|
+
* An "options only" theme useful for single command applications.
|
|
382
|
+
*
|
|
383
|
+
* program
|
|
384
|
+
* .theme('simple', {
|
|
385
|
+
* noColor: false // set to true to disable color coding
|
|
386
|
+
* , command: 'default' // which command to show options for
|
|
387
|
+
* , usage: '<options>' // special usage instructions
|
|
388
|
+
* });
|
|
389
|
+
*
|
|
390
|
+
* <img alt="Electron Simple Theme" src="http://f.cl.ly/items/3z3l162D101e0016320G/electron-simple-theme.png" />
|
|
391
|
+
*
|
|
392
|
+
* ##### Use Your Own Function
|
|
393
|
+
*
|
|
394
|
+
* You may also provide a function to `theme` to provide your own output.
|
|
395
|
+
* The following example will list all of the commands present in your
|
|
396
|
+
* program.
|
|
397
|
+
*
|
|
398
|
+
* program.theme(function () {
|
|
399
|
+
* this.colorize();
|
|
400
|
+
* console.log('Usage: %s <command>', this.opts.base);
|
|
401
|
+
* this.commands.forEach(functioni (cmd) {
|
|
402
|
+
* console.log(' %s - %s', cmd.cmd, cmd.desc);
|
|
403
|
+
* });
|
|
404
|
+
* });
|
|
405
|
+
*
|
|
406
|
+
* Those interesting in building custom themes should view Electron
|
|
407
|
+
* on GitHub and explore
|
|
408
|
+
* [lib/electron/themes](https://github.com/logicalparadox/electron/tree/master/lib/electron/themes).
|
|
409
|
+
*
|
|
410
|
+
* @param {String|Function} name of electron theme or custom function
|
|
411
|
+
* @param {Object} options for electron themes
|
|
412
|
+
* @returns `this` for chaining
|
|
413
|
+
* @name theme
|
|
414
|
+
* @api public
|
|
415
|
+
*/
|
|
416
|
+
|
|
417
|
+
Program.prototype.theme = function (name, spec) {
|
|
418
|
+
if ('function' === typeof name) {
|
|
419
|
+
this.opts.theme = name;
|
|
420
|
+
} else {
|
|
421
|
+
var theme = {};
|
|
422
|
+
theme.name = name || 'clean';
|
|
423
|
+
theme.spec = defaults(spec || {}, { noColor: false });
|
|
424
|
+
this.opts.theme = theme;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return this;
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* ### .colorize ()
|
|
432
|
+
*
|
|
433
|
+
* The `colorize` helper is available if you wish you implement
|
|
434
|
+
* a colorized but lightweight logging mechanism in your actions,
|
|
435
|
+
* or if you are building a custom help theme. `colorize` works
|
|
436
|
+
* by extending `String.prototype` with a number of color options.
|
|
437
|
+
* Just in case, if the current program is not running as a TTY,
|
|
438
|
+
* no string changes will be made.
|
|
439
|
+
*
|
|
440
|
+
* program.colorize();
|
|
441
|
+
* console.log('hello universe'.green);
|
|
442
|
+
*
|
|
443
|
+
* ##### Colors
|
|
444
|
+
*
|
|
445
|
+
* - red
|
|
446
|
+
* - green
|
|
447
|
+
* - yellow
|
|
448
|
+
* - blue
|
|
449
|
+
* - magenta
|
|
450
|
+
* - cyan
|
|
451
|
+
* - gray
|
|
452
|
+
*
|
|
453
|
+
* @name colorize
|
|
454
|
+
* @api public
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
Program.prototype.colorize = function (noColors) {
|
|
458
|
+
if (this._colorized) return this;
|
|
459
|
+
var self = this
|
|
460
|
+
, colors = {
|
|
461
|
+
'red': 31
|
|
462
|
+
, 'green': 32
|
|
463
|
+
, 'yellow': 33
|
|
464
|
+
, 'blue': 34
|
|
465
|
+
, 'magenta': 35
|
|
466
|
+
, 'cyan': 36
|
|
467
|
+
, 'gray': 90
|
|
468
|
+
, 'reset': 0
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
Object.keys(colors).forEach(function (color) {
|
|
472
|
+
Object.defineProperty(String.prototype, color,
|
|
473
|
+
{ get: function () {
|
|
474
|
+
if (noColors || !self.opts.useColors) return this;
|
|
475
|
+
return '\033[' + colors[color] + 'm' + this + '\033[0m';
|
|
476
|
+
}
|
|
477
|
+
, configurable: true
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
this._colorized = true;
|
|
482
|
+
return this;
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
/*!
|
|
486
|
+
* mountCommands ()
|
|
487
|
+
*
|
|
488
|
+
* For each constructed command added to the the program
|
|
489
|
+
* mount as a listener. If the command is special, return
|
|
490
|
+
* it for futher inspection.
|
|
491
|
+
*
|
|
492
|
+
* @ctx program
|
|
493
|
+
* @api private
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
function mountCommands () {
|
|
497
|
+
var self = this
|
|
498
|
+
, res = {}
|
|
499
|
+
, arr = [];
|
|
500
|
+
|
|
501
|
+
this.commands.forEach(function (command) {
|
|
502
|
+
var fn = command.opts.action
|
|
503
|
+
, ev = Array.isArray(command.opts.cmd)
|
|
504
|
+
? command.opts.cmd.join(' ')
|
|
505
|
+
: command.opts.cmd;
|
|
506
|
+
|
|
507
|
+
if (ev === 'default') res.def = fn;
|
|
508
|
+
else if (ev === 'absent') res.absent = fn;
|
|
509
|
+
else if (!~arr.indexOf(ev)) {
|
|
510
|
+
arr.push(ev);
|
|
511
|
+
self.on(ev, fn);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
return res;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/*!
|
|
519
|
+
* displayVersion ()
|
|
520
|
+
*
|
|
521
|
+
* Display the current program version and exit
|
|
522
|
+
* process. Used when called with `-v` or `--version`
|
|
523
|
+
*
|
|
524
|
+
* @ctx program
|
|
525
|
+
* @api private
|
|
526
|
+
*/
|
|
527
|
+
|
|
528
|
+
function displayVersion () {
|
|
529
|
+
process.stdout.write(this.opts.version + '\n');
|
|
530
|
+
process.exit();
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/*!
|
|
534
|
+
* displayHelp ()
|
|
535
|
+
*
|
|
536
|
+
* Execute the custom help theme or find the respective
|
|
537
|
+
* electron theme and execute.
|
|
538
|
+
*
|
|
539
|
+
* @ctx program
|
|
540
|
+
* @api private
|
|
541
|
+
*/
|
|
542
|
+
|
|
543
|
+
function displayHelp () {
|
|
544
|
+
if ('function' === typeof this.opts.theme)
|
|
545
|
+
return this.opts.theme.call(this);
|
|
546
|
+
|
|
547
|
+
var name = this.opts.theme.name
|
|
548
|
+
, theme = themes[name]
|
|
549
|
+
, spec = this.opts.theme.spec || {};
|
|
550
|
+
|
|
551
|
+
if (!theme) throw new Error('Electron: Invalid help theme defined.');
|
|
552
|
+
else theme.call(this, spec);
|
|
553
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Electron - clean theme
|
|
3
|
+
* Copyright (c) 2012 Jake Luer <jake@alogicalparadox.com>
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* main export - theme display
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
module.exports = function cleanHelp (spec) {
|
|
12
|
+
// parse specs
|
|
13
|
+
spec = spec || {};
|
|
14
|
+
spec.prefix = spec.prefix || '';
|
|
15
|
+
|
|
16
|
+
// colors
|
|
17
|
+
this.colorize(spec.noColor || false);
|
|
18
|
+
|
|
19
|
+
// helper function and variables
|
|
20
|
+
var l = function (s) { console.log(spec.prefix.cyan+ ' ' + (s || '')); }
|
|
21
|
+
, pad = function (s, w) { return Array(w - s.length - 1).join(' ') + s; }
|
|
22
|
+
, name = this.opts.name
|
|
23
|
+
, base = this.opts.base;
|
|
24
|
+
|
|
25
|
+
// header
|
|
26
|
+
l();
|
|
27
|
+
l(name.cyan + ' ' + this.opts.version);
|
|
28
|
+
if (this.opts.desc) l(this.opts.desc.gray);
|
|
29
|
+
|
|
30
|
+
// commmand display
|
|
31
|
+
this.commands.forEach(function (cmd) {
|
|
32
|
+
// we don't display absent command
|
|
33
|
+
if (cmd.opts.cmd === 'absent') return;
|
|
34
|
+
|
|
35
|
+
// hlper variables
|
|
36
|
+
var c = cmd.opts
|
|
37
|
+
, command = c.cmd !== 'default' ? c.cmd + ' ' : ''
|
|
38
|
+
, opts = c.options.length ? '<options>' : '';
|
|
39
|
+
|
|
40
|
+
// main lines
|
|
41
|
+
l();
|
|
42
|
+
l(base.gray + ' ' + command.green + opts);
|
|
43
|
+
if (c.desc.length) l(pad('', 4) + c.desc.blue);
|
|
44
|
+
if (!c.options.length) return;
|
|
45
|
+
|
|
46
|
+
// if there are options ...
|
|
47
|
+
c.options.forEach(function (opt) {
|
|
48
|
+
var n = c.desc.length ? 6 : 4
|
|
49
|
+
, opts = opt.opts.flags.map(function (flag) {
|
|
50
|
+
if (flag.length === 1) return '-' + flag;
|
|
51
|
+
else return '--' + flag;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
l(pad('', n) + opts.join(', ')
|
|
55
|
+
+ (opt.opts.def ? ' [' + opt.opts.def + ']' : '' )
|
|
56
|
+
+ ' ' + opt.desc.gray);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// all done
|
|
61
|
+
l();
|
|
62
|
+
process.exit();
|
|
63
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Electron - theme loader
|
|
3
|
+
* Copyright (c) 2012 Jake Luer <jake@alogicalparadox.com>
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* expose clean theme
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
exports.clean = require('./clean');
|
|
12
|
+
|
|
13
|
+
/*!
|
|
14
|
+
* expose simple theme
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
exports.simple = require('./simple');
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Electron - simple theme
|
|
3
|
+
* Copyright (c) 2012 Jake Luer <jake@alogicalparadox.com>
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* main export - theme display
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
module.exports = function cleanHelp (spec) {
|
|
12
|
+
// parse specs
|
|
13
|
+
spec = spec || {};
|
|
14
|
+
spec.prefix = spec.prefix || '';
|
|
15
|
+
spec.command = spec.command || 'default';
|
|
16
|
+
spec.usage = spec.usage || '<options>';
|
|
17
|
+
|
|
18
|
+
// colors!
|
|
19
|
+
this.colorize(spec.noColor || false);
|
|
20
|
+
|
|
21
|
+
// helper function and variables
|
|
22
|
+
var l = function (s) { console.log(spec.prefix.cyan + ' ' + (s || '')); }
|
|
23
|
+
, pad = function (s, w) { return s + Array(w - s.length - 1).join(' '); }
|
|
24
|
+
, name = this.opts.name
|
|
25
|
+
, base = this.opts.base;
|
|
26
|
+
|
|
27
|
+
// header
|
|
28
|
+
l();
|
|
29
|
+
l(name.cyan + ' ' + this.opts.version);
|
|
30
|
+
if (this.opts.desc) l(this.opts.desc.gray);
|
|
31
|
+
|
|
32
|
+
// get the command
|
|
33
|
+
var command = this.commands.filter(function (cmd) {
|
|
34
|
+
return (cmd.opts.cmd === spec.command) ? true : false;
|
|
35
|
+
})[0];
|
|
36
|
+
|
|
37
|
+
// check for command
|
|
38
|
+
if (!command) {
|
|
39
|
+
l('Invalid command identified for help.'.red);
|
|
40
|
+
l();
|
|
41
|
+
process.exit();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// comamnd usage
|
|
45
|
+
l();
|
|
46
|
+
l('Usage: '.green + base.gray + ' ' + spec.usage);
|
|
47
|
+
l();
|
|
48
|
+
l('Options:'.magenta);
|
|
49
|
+
l();
|
|
50
|
+
|
|
51
|
+
// iterate through options
|
|
52
|
+
command.opts.options.forEach(function (opt) {
|
|
53
|
+
var opts = opt.opts.flags.map(function (flag) {
|
|
54
|
+
if (flag.length === 1) return '-' + flag;
|
|
55
|
+
else return '--' + flag;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
l(pad('', 4)
|
|
59
|
+
+ pad(
|
|
60
|
+
opts.join(', ')
|
|
61
|
+
+ (opt.opts.def ? ' [' + opt.opts.def + ']' : '' )
|
|
62
|
+
, 26)
|
|
63
|
+
+ ' ' + opt.desc.gray);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// all done
|
|
67
|
+
l();
|
|
68
|
+
l(command.opts.desc.blue);
|
|
69
|
+
l();
|
|
70
|
+
process.exit();
|
|
71
|
+
}
|