Skip to content

Implement multiple command parsing (docker style)

Lloyd Brookes edited this page Jan 19, 2018 · 5 revisions

We can use stopAtFirstUnknown to parse an input argv array several times making complex scenarios possible.

As an example we'll recreate the docker run command. The command line syntax for docker accepts not one but multiple commands (run in this example plus a second, arbitrary command to pass to the image).

$ docker <command> [options] <image> <sub-command> [options]

Example

This is the full example script. After each commandLineArgs() invocation, the _unknown list is used as input to the next invocation.

const commandLineArgs = require('command-line-args')

/* first - parse the main command */
let optionDefinitions = [
  { name: 'command', type: String, defaultOption: true }
]
const mainOptions = commandLineArgs(optionDefinitions, { stopAtFirstUnknown: true })
let argv = mainOptions._unknown || []

console.log('mainOptions')
console.log('===========')
console.log(mainOptions)

/* second - parse the main command options */
if (mainOptions.command === 'run') {
  optionDefinitions = [
    { name: 'detached', alias: 'd', type: Boolean },
    { name: 'target', type: String, defaultOption: true }
  ]
  const runOptions = commandLineArgs(optionDefinitions, { argv, stopAtFirstUnknown: true })
  argv = runOptions._unknown || []

  console.log('\nrunOptions')
  console.log('==========')
  console.log(runOptions)

  /* third - parse the command to run on the target image */
  optionDefinitions = [
    { name: 'target-command', type: String, defaultOption: true }
  ]
  const targetOptions = commandLineArgs(optionDefinitions, { argv, stopAtFirstUnknown: true })

  console.log('\ntargetOptions')
  console.log('=============')
  console.log(targetOptions)
}

Running this command produces the following output.

$ node example.js run -d centos bash -c yum install -y httpd
mainOptions
===========
{ _unknown: [ '-d', 'centos', 'bash', '-c', 'yum', 'install', '-y', 'httpd' ],
  command: 'run' }

runOptions
==========
{ _unknown: [ 'bash', '-c', 'yum', 'install', '-y', 'httpd' ],
  detached: true,
  target: 'centos' }

targetOptions
=============
{ _unknown: [ '-c', 'yum', 'install', '-y', 'httpd' ],
  'target-command': 'bash' }