Skip to content

double hyphen is parsed as an argument when defaultOption is set #119

@bakkot

Description

@bakkot

The wiki discusses how to correctly handle a double hyphen / double dash (--), but the suggested solution doesn't work when defaultOption is set, particularly alongside multiple:

'use strict';

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

const optionDefinitions = [
  { name: 'verbose', alias: 'v', type: Boolean },
  { name: 'src', type: String, defaultOption: true, multiple: true },
  { name: 'timeout', alias: 't', type: Number }
]

const options = commandLineArgs(optionDefinitions, { stopAtFirstUnknown: true })

console.log(options)

run with

node main.js one -t 0 -- --verbose two

produces

{ src: [ 'one', '--', 'two' ], timeout: 0, verbose: true }

That's not what -- means: the whole point is that encountering -- should mean that --verbose is interpreted as a positional argument rather than as a flag.

On the other hand, if you have defaultOption: false, then it will stop when it encounters the first positional argument, and the above invocation will result in

{ _unknown: [ 'one', '-t', '0', '--', '--verbose', 'two' ] }

i.e. it will fail to parse -t.

So neither approach actually allows you to correctly handle --.


For now, I'm working around it by manually splicing out the -- part before invoking commandLineArgs:

'use strict';

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

const optionDefinitions = [
  { name: 'verbose', alias: 'v', type: Boolean },
  { name: 'src', type: String, defaultOption: true, multiple: true },
  { name: 'timeout', alias: 't', type: Number }
]

const { argv } = process

let notParsed = []
const dashDashIndex = argv.indexOf('--')
if (dashDashIndex !== -1) {
  notParsed = argv.splice(dashDashIndex + 1)
  argv.pop()
}

const options = commandLineArgs(optionDefinitions, { argv })

options.src = (options.src || []).concat(notParsed);

console.log(options)

which gives for the above invocation

{ src: [ 'one', '--verbose', 'two' ], timeout: 0 }

which is the right thing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions