added real pattern args...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-10 21:51:34 +03:00
parent 9d09eb220c
commit e3ffd4bc5f
5 changed files with 72 additions and 5 deletions

View File

@ -62,6 +62,7 @@ This code is an evolution of that parser.
- [Basic options](#basic-options) - [Basic options](#basic-options)
- [Commands](#commands) - [Commands](#commands)
- [Active options/commands](#active-optionscommands) - [Active options/commands](#active-optionscommands)
- [Pattern options](#pattern-options)
- [Nested parsers](#nested-parsers) - [Nested parsers](#nested-parsers)
- [Stopping](#stopping) - [Stopping](#stopping)
- [Error reporting](#error-reporting) - [Error reporting](#error-reporting)
@ -335,6 +336,7 @@ For more info on available `.type` and `.collect` handlers see:
respectively. respectively.
### Commands ### Commands
The only difference between an _option_ and a _command_ is the prefix (`"-"` vs. `"@"`) The only difference between an _option_ and a _command_ is the prefix (`"-"` vs. `"@"`)
@ -383,6 +385,26 @@ it expects), `argv.js` poses no restrictions on full or partial manual handling
of arguments by options/commands. of arguments by options/commands.
### Pattern options
Pattern option/command keys enable partial input key matching.
```javascript
'-prefix-*': {
doc: 'Pattern option',
handler: function(rest, key){
// ...
} },
```
The above code will match any _unhandled_ input option starting with
`-prefix-`/`--prefix-` and push the explicitly `false` value back to the option
queue.
A pattern option/command is any option with a key containing `"*"`.
### Nested parsers ### Nested parsers
An options/command handler can also be a full fledged parser. An options/command handler can also be a full fledged parser.
@ -551,6 +573,7 @@ Options:
-c - command -c - command
--active - basic active option --active - basic active option
-s, --shorthand-active - shorthand-active -s, --shorthand-active - shorthand-active
--prefix-* - Pattern option
--then - then --then - then
--stop - stop --stop - stop
--error - error --error - error

38
argv.js
View File

@ -429,10 +429,11 @@ object.Constructor('Parser', {
prefix = prefix.length == 0 ? prefix = prefix.length == 0 ?
[OPTION_PREFIX] [OPTION_PREFIX]
: prefix : prefix
var attrs = object.deepKeys(that, Parser.prototype)
return prefix return prefix
.map(function(prefix){ .map(function(prefix){
var handlers = {} var handlers = {}
object.deepKeys(that, Parser.prototype) attrs
.forEach(function(opt){ .forEach(function(opt){
if(!opt.startsWith(prefix)){ if(!opt.startsWith(prefix)){
return } return }
@ -496,6 +497,28 @@ object.Constructor('Parser', {
requiredArguments: function(){ requiredArguments: function(){
return this.requiredOptions('allArguments') }, return this.requiredOptions('allArguments') },
//
// .patternArguments()
// -> list
//
// Get list of pattern args that key matches...
// .patternArguments(key)
// -> list
//
// NOTE: list is sorted by option length...
// NOTE: pattern->pattern aliases are not currently supported...
// NOTE: output is of the same format as .options(..)
// NOTE: when changing this revise a corresponding section in .handler(..)
patternArguments: function(key){
return this.allArguments()
.filter(function([[opt]]){
return opt.includes('*')
&& (key == null
|| (new RegExp(`^${ opt.split('*').join('.*') }$`)).test(key)) })
// sort longest first...
.sort(function(a, b){
return b[0][0].length - a[0][0].length }) },
// Get handler... // Get handler...
// //
// .handler(key) // .handler(key)
@ -523,6 +546,19 @@ object.Constructor('Parser', {
// report loop... // report loop...
'loop', [...seen, key]] } 'loop', [...seen, key]] }
seen.add(key) } seen.add(key) }
// check pattern options...
// NOTE: we are not using .patternArguments(..) because .options(..)
// used there uses .handler(..) and this breaks things...
if(!(key in this) && key != '-*'){
key = object.deepKeys(this, Parser.prototype)
.filter(function(opt){
return opt.includes('*')
&& (key == null
|| (new RegExp(`^${ opt.split('*').join('.*') }$`))
.test(key)) })
.sort(function(a, b){
return b[0][0].length - a[0][0].length })[0]
|| key }
return [key, this[key], return [key, this[key],
// report dead-end if this[key] is undefined... // report dead-end if this[key] is undefined...
...(this[key] ? ...(this[key] ?

View File

@ -120,6 +120,12 @@ argv.Parser({
// ... // ...
}, },
'-prefix-*': {
doc: 'Pattern option',
handler: function(rest, key){
// ...
},
},
'@nested': argv.Parser({ '@nested': argv.Parser({
// ... // ...

View File

@ -1,6 +1,6 @@
{ {
"name": "ig-argv", "name": "ig-argv",
"version": "2.15.7", "version": "2.16.0",
"description": "simple argv parser", "description": "simple argv parser",
"main": "argv.js", "main": "argv.js",
"scripts": { "scripts": {

View File

@ -28,14 +28,14 @@ var setups =
test.Setups({ test.Setups({
bare: function(){ bare: function(){
return require('./examples/bare').parser }, return require('./examples/bare').parser },
options: function(){ opts: function(){
return require('./examples/options').parser }, return require('./examples/options').parser },
lang: function(){ lang: function(){
return require('./examples/lang').parser }, return require('./examples/lang').parser },
chain: function(){ chain: function(){
return require('./examples/chain').parser }, return require('./examples/chain').parser },
// NOTE: this will also load .bare, .options and .lang // NOTE: this will also load .bare, .opts and .lang
basic: function(assert){ basic: function(assert){
return argv.Parser({ return argv.Parser({
// disable exit on error... // disable exit on error...
@ -175,13 +175,15 @@ test.Setups({
'@bare': setups.bare(assert), '@bare': setups.bare(assert),
'@opts': setups.options(assert), '@opts': setups.opts(assert),
'@lang': setups.lang(assert), '@lang': setups.lang(assert),
'@chain': setups.chain(assert), '@chain': setups.chain(assert),
// collision test... // collision test...
// NOTE: values of these will shadow the API... // NOTE: values of these will shadow the API...
// XXX need to either warn the user of this or think of a
// way to avoid this...
'@options': {}, '@options': {},
'-handler': {}, '-handler': {},
}) })