Skip to content

Instantly share code, notes, and snippets.

@dschnare
Last active April 2, 2020 21:27
Show Gist options
  • Save dschnare/7baa2c6ef521f20578081f25a22ea1b3 to your computer and use it in GitHub Desktop.
Save dschnare/7baa2c6ef521f20578081f25a22ea1b3 to your computer and use it in GitHub Desktop.
Read a command line option
/**
* Read a command line option. Option names must start with '-'.
*
* Options:
*
* `required` Determines if the option must appear on the command line.
*
* `multi` Determines if the option can be specified more than once on the
* command line. Causes the return value to be an array.
*
* `converter` The conversion function to use to convert an option's value.
*
* @example
* const args = process.args.slice(2)
* const flavors = readOption([ '--flavor' ], args, { multi: true })
* @template T
* @param {string[]} names The valid option names on the command line
* @param {string[]} args The command line arguments without the program and script name
* @param {{ required?: boolean, multi?: boolean, converter: (value:string) => T }} [options]
* @return {T|T[]}
*/
const readOption = (names, args, { required = false, multi = false, converter = x => x } = {}) => {
const values = []
names.forEach(name => {
const index = args.findIndex(arg => arg.split('=')[0] === name)
if (index >= 0) {
let value = args[index].indexOf('=') > 0
? args[index].split('=').slice(1).join('=')
: (args[index + 1] || '')
if (value.startsWith('-')) {
value = ''
}
values.push(value)
}
})
if (required && !values.length) {
throw new Error(`Command line option ${names[0]} is required`)
}
if (!multi && values.length > 1) {
throw new Error(`Command line option ${names[0]} does not support mulitple values`)
}
const convertedValues = values.map(converter)
const value = multi ? convertedValues : convertedValues.pop()
return value
}
/**
* Read a command line flag. Flag names must start with '-'.
*
* @example
* const args = process.args.slice(2)
* const reportOnly = readOption.flag([ '--reportyOnly' ], args)
* @param {string[]} names The valid option names on the command line
* @param {string[]} args The command line arguments without the program and script name
* @param {{ required?: boolean }} [options]
* @return {boolean}
*/
readOption.flag = (names, args, { required = false } = {}) => {
const converter = value => {
if (value) {
throw new Error(`Command line option ${names[0]} is a flag and cannot have a value`)
}
return true
}
const options = { required, multi: false, converter }
return readOption(names, args, options) || false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment