Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stringify: add new method #29

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Backward incompatibilities
* compile: rename stringify method to compile

New functionality
* stringify: new method, convert a parameters object to an arguments string
* options: new disabled property
* help: new plugin
* help: sort options
Expand Down
97 changes: 97 additions & 0 deletions doc/api/stringify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: API method `stringify`
description: How to use the `stringify` method to convert a parameters object to an arguments string.
keywords: ["parameters", "node.js", "cli", "api", "stringify", "arguments", "argv", "array"]
maturity: review
---

# Method `stringify(command, [options])`

Convert a parameters object to an arguments string.

* `params`: `object` The parameter object to be converted into an array of arguments, optional.
* `options`: `object` Options used to alter the behavior of the `compile` method.
* `extended`: `boolean` The value `true` indicates that the parameters are provided in extended format, default to the configuration `extended` value which is `false` by default.
* `script`: `string` The JavaScript file being executed by the engine, when present, the engine and the script names will prepend the returned arguments, optional, default is false.
* Returns: `string` The command line arguments.

## Description

The method converts a parameters object to an arguments string of a CLI command.

It supports both the default flatten mode and the extended mode. The `extended` property can be defined in the configuration or as an option of `stringify`. In flatten mode, the `command` argument is an object while in `extended` mode it is an array of object.

The bash characters in the result string are escaped.

## Examples

Considering a "server" application containing a "start" command and initialised with the following configuration:

```js
require("should")
const parameters = require("parameters")
const app = parameters(
{ name: "server",
description: "Manage a web server",
options:
{ "config":
{ shortcut: "c" } },
commands:
{ "start":
{ description: "Start a web server",
options:
{ "host":
{ shortcut: "h",
description: "Web server listen host"},
"port":
{ shortcut: "p", type: "integer",
description: "Web server listen port" } } } } })
```

The `stringify` method convert a literal object into a shell command:

```javascript
app.stringify({
command: ["start"],
config: "app.yaml"
})
.should.eql( "--config app.yaml start" )
```

In extended mode, the parameters input will be an array instead of an object:

```js
app.compile([{
config: "app.yaml"
}], {
extended: true
})
.should.eql( "--config app.yaml" )
```

Working with commands is quite similar:

```js
app.compile({
config: "app.yml",
command: ["start"],
host: "127.0.0.1",
port: 80
}).should.eql(
"--config app.yml start --host 127.0.0.1 --port 80"
);
```

In extended mode, the parameters input will be an array with 2 elements instead of an object:

```js
app.compile([{
config: "app.yml"
},{
command: "start",
host: "127.0.0.1",
port: 80
}]).should.eql(
["--config", "app.yml", "start", "--host", "127.0.0.1", "--port", "80"]
);
```
38 changes: 37 additions & 1 deletion lib/plugins/args.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 23 additions & 11 deletions samples/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,21 @@ require('should');
const command = parameters({
name: 'server',
description: 'Manage a web server',
commands: [{
name: 'start',
description: 'Start a web server',
options: [{
name: 'host', shortcut: 'h',
description: 'Web server listen host'
},{
name: 'port', shortcut: 'p', type: 'integer',
description: 'Web server listen port'
}]
}]
commands: {
'start': {
description: 'Start a web server',
options: {
'host': {
shortcut: 'h',
description: 'Web server listen host'
},
'port': {
shortcut: 'p', type: 'integer',
description: 'Web server listen port'
}
}
}
}
});
// Print help
console.log( command.help() );
Expand All @@ -55,3 +59,11 @@ command.compile({
}).should.eql(
['start', '--host', '127.0.0.1', '--port', '80']
);
// Make an argument string
command.stringify({
command: ['start'],
host: '127.0.0.1',
port: 80
}).should.eql(
'start --host 127.0.0.1 --port 80'
);
21 changes: 12 additions & 9 deletions samples/standard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

const parameters = require('..');
require('should');

Expand All @@ -16,16 +15,20 @@ require('should');
const command = parameters({
name: 'server',
description: 'Start a web server',
options: [{
name: 'host', shortcut: 'h',
description: 'Web server listen host'
},{
name: 'port', shortcut: 'p', type: 'integer',
description: 'Web server listen port'
}]
options: {
'host': {
shortcut: 'h',
description: 'Web server listen host'
},
'port': {
shortcut: 'p',
type: 'integer',
description: 'Web server listen port'
}
}
});
// Print help
console.log( command.help() );
console.log(command.help());
// Extract command arguments
// Note, if the argument array is undefined, it default to `process.argv`
// and is similar to running the command
Expand Down
30 changes: 30 additions & 0 deletions src/plugins/args.coffee.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,30 @@ Convert a parameters object to an arguments array.
argv.push "#{value}"
compile appconfig, if options.extended then params.shift() else params
argv

## Method `stringify(command, [options])`

Convert a parameters object to an arguments string.

* `params`: `object` The parameter object to be converted into an array of arguments, optional.
* `options`: `object` Options used to alter the behavior of the `compile` method.
* `extended`: `boolean` The value `true` indicates that the parameters are provided in extended format, default to the configuration `extended` value which is `false` by default.
* `script`: `string` The JavaScript file being executed by the engine, when present, the engine and the script names will prepend the returned arguments, optional, default is false.
* Returns: `string` The command line arguments.

Parameters::stringify = (params, options={}) ->
argv = ""
compile = @compile params, options
if options.script?
argv += compile.shift() + ' '
argv += compile.shift() + ' '
for arg in compile
arg = escape arg
if " " in arg
then argv += '"' + arg + '"'
else argv += arg
argv += ' '
argv.trim()

## Utils

Expand All @@ -278,3 +302,9 @@ Given a configuration, apply default values to the parameters
for _, option of config.options
params[option.name] ?= option.default if option.default?
params

Escape the bash characters

escape = (string) ->
string.toString().replace /[\\^$*+?()|[\]{}]/g, "\\$&"

54 changes: 54 additions & 0 deletions test/args/api.stringify.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

parameters = require '../../src'

describe 'api.stringify', ->

it 'should convert a parameters object to an arguments string', ->
parameters
commands: 'start':
options: 'myparam': {}
.stringify
command: 'start'
myparam: 'value'
.should.eql 'start --myparam value'

it 'should convert with node path and executed script', ->
parameters
commands: 'start' : {}
.stringify
command: 'start'
,
script: './bin/myscript'
.should.eql process.execPath + ' ./bin/myscript start'

it 'should convert in extended mode', ->
parameters
extended: true
options: 'myparam': {}
commands: 'start':
options: 'myparam': {}
.stringify [
myparam: 'value'
,
command: 'start'
myparam: 'value'
]
.should.eql '--myparam value start --myparam value'

it 'should escape bash characters of only parameters object', ->
parameters
options: 'myparam': {}
.stringify
myparam: '\\^$*+?()|[\]{}]'
,
script: './bin/myscript'
.should.eql process.execPath + ' ./bin/myscript --myparam \\\\\\^\\$\\*\\+\\?\\(\\)\\|\\[\\]\\{\\}\\]'

it 'does not lose the context', ->
parameters
commands: 'start':
main: 'leftover'
.stringify
command: 'start'
leftover: ['my value', 'here']
.should.eql 'start "my value" here'