Spaces:
Sleeping
Sleeping
File size: 3,753 Bytes
be5030f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
'use strict'
const argvTools = require('argv-tools')
/**
* @module argv-parser
*/
/**
* @alias module:argv-parser
*/
class ArgvParser {
/**
* @param {OptionDefinitions} - Definitions array
* @param {object} [options] - Options
* @param {string[]} [options.argv] - Overrides `process.argv`
* @param {boolean} [options.stopAtFirstUnknown] -
*/
constructor (definitions, options) {
this.options = Object.assign({}, options)
const Definitions = require('./option-definitions')
/**
* Option Definitions
*/
this.definitions = Definitions.from(definitions)
/**
* Argv
*/
this.argv = argvTools.ArgvArray.from(this.options.argv)
if (this.argv.hasCombinedShortOptions()) {
const findReplace = require('find-replace')
findReplace(this.argv, argvTools.re.combinedShort, arg => {
arg = arg.slice(1)
return arg.split('').map(letter => ({ origArg: `-${arg}`, arg: '-' + letter }))
})
}
}
/**
* Yields one `{ event, name, value, arg, def }` argInfo object for each arg in `process.argv` (or `options.argv`).
*/
* [Symbol.iterator] () {
const definitions = this.definitions
const t = require('typical')
let def
let value
let name
let event
let singularDefaultSet = false
let unknownFound = false
let origArg
for (let arg of this.argv) {
if (t.isPlainObject(arg)) {
origArg = arg.origArg
arg = arg.arg
}
if (unknownFound && this.options.stopAtFirstUnknown) {
yield { event: 'unknown_value', arg, name: '_unknown', value: undefined }
continue
}
/* handle long or short option */
if (argvTools.isOption(arg)) {
def = definitions.get(arg)
value = undefined
if (def) {
value = def.isBoolean() ? true : null
event = 'set'
} else {
event = 'unknown_option'
}
/* handle --option-value notation */
} else if (argvTools.isOptionEqualsNotation(arg)) {
const matches = arg.match(argvTools.re.optEquals)
def = definitions.get(matches[1])
if (def) {
if (def.isBoolean()) {
yield { event: 'unknown_value', arg, name: '_unknown', value, def }
event = 'set'
value = true
} else {
event = 'set'
value = matches[2]
}
} else {
event = 'unknown_option'
}
/* handle value */
} else if (argvTools.isValue(arg)) {
if (def) {
value = arg
event = 'set'
} else {
/* get the defaultOption */
def = this.definitions.getDefault()
if (def && !singularDefaultSet) {
value = arg
event = 'set'
} else {
event = 'unknown_value'
def = undefined
}
}
}
name = def ? def.name : '_unknown'
const argInfo = { event, arg, name, value, def }
if (origArg) {
argInfo.subArg = arg
argInfo.arg = origArg
}
yield argInfo
/* unknownFound logic */
if (name === '_unknown') unknownFound = true
/* singularDefaultSet logic */
if (def && def.defaultOption && !def.isMultiple() && event === 'set') singularDefaultSet = true
/* reset values once consumed and yielded */
if (def && def.isBoolean()) def = undefined
/* reset the def if it's a singular which has been set */
if (def && !def.multiple && t.isDefined(value) && value !== null) {
def = undefined
}
value = undefined
event = undefined
name = undefined
origArg = undefined
}
}
}
module.exports = ArgvParser
|