mirror of
https://github.com/flynx/argv.js.git
synced 2025-10-28 18:30:07 +00:00
added experimental chaining, still has issues...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
33e4afce60
commit
191790edeb
26
ADVANCED.md
26
ADVANCED.md
@ -54,6 +54,7 @@ For basics see [README.md](./README.md)
|
|||||||
- [`<parser>.error(..)`](#parsererror-1)
|
- [`<parser>.error(..)`](#parsererror-1)
|
||||||
- [`<parser>.off(..)`](#parseroff)
|
- [`<parser>.off(..)`](#parseroff)
|
||||||
- [`<parser>(..)`](#parser-1)
|
- [`<parser>(..)`](#parser-1)
|
||||||
|
- [`Parser.chain(..)` (EXPERIMENTAL)](#parserchain-experimental)
|
||||||
- [Advanced parser API](#advanced-parser-api)
|
- [Advanced parser API](#advanced-parser-api)
|
||||||
- [`<parser>.print(..)` / `<parser>.printError(..)`](#parserprint--parserprinterror)
|
- [`<parser>.print(..)` / `<parser>.printError(..)`](#parserprint--parserprinterror)
|
||||||
- [`<parser>.handlerDefault(..)`](#parserhandlerdefault)
|
- [`<parser>.handlerDefault(..)`](#parserhandlerdefault)
|
||||||
@ -763,6 +764,31 @@ be ignored, otherwise the whole list is processed as if `<main>` was
|
|||||||
its head.
|
its head.
|
||||||
|
|
||||||
|
|
||||||
|
### `Parser.chain(..)` (EXPERIMENTAL)
|
||||||
|
|
||||||
|
Chain several parsers for staggering option/command processing.
|
||||||
|
```
|
||||||
|
Parser.chain(<spec>, <spec>, ..)
|
||||||
|
-> <parser>
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a chain of parsers, each processing only the arguments it defines
|
||||||
|
and passes the rest to the next in chain. This is useful for defining arguments
|
||||||
|
that need to be processed out of order and before anything else.
|
||||||
|
|
||||||
|
This is similar to chaining parsers via `.then(..)` but with additional setup:
|
||||||
|
- all parsers except the last will have:
|
||||||
|
- `.splitOptions` set to `false`
|
||||||
|
- `"-help"` set to `undefined` enabling `-help` pass-through
|
||||||
|
- `"-*"` and `"@*"` set to `undefined` enabling arguments pass-through
|
||||||
|
- the last parser will have all the options from the other parsers merged into
|
||||||
|
it for complete docs/`-help`
|
||||||
|
|
||||||
|
|
||||||
|
XXX the resulting `<parsed>` object will only contain data from the last parser,
|
||||||
|
this may change in the future.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Advanced parser API
|
## Advanced parser API
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ This code is an evolution of that parser.
|
|||||||
- `-version` – print version
|
- `-version` – print version
|
||||||
- `-quiet` – suppress printing
|
- `-quiet` – suppress printing
|
||||||
- `-` – stop argument processing
|
- `-` – stop argument processing
|
||||||
- Extensible
|
- Extensible and self-applicable
|
||||||
|
|
||||||
|
|
||||||
### Planned
|
### Planned
|
||||||
|
|||||||
63
argv.js
63
argv.js
@ -319,6 +319,44 @@ object.Constructor('Parser', {
|
|||||||
toggle: function(v, cur){ return !cur },
|
toggle: function(v, cur){ return !cur },
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// XXX this does not merge the parse results... (???)
|
||||||
|
// XXX EXPERIMENTAL...
|
||||||
|
chain: function(...parsers){
|
||||||
|
var Parser = this
|
||||||
|
var [post, ...pre] = parsers.reverse()
|
||||||
|
pre.reverse()
|
||||||
|
|
||||||
|
// prepare the final parser for merged doc...
|
||||||
|
// XXX object.deepKeys(..) ???
|
||||||
|
var final = Parser(Object.assign({},
|
||||||
|
// set attribute order...
|
||||||
|
// NOTE: this is here to set the attribute order according
|
||||||
|
// to priority...
|
||||||
|
...pre,
|
||||||
|
// set the correct values...
|
||||||
|
post,
|
||||||
|
...pre))
|
||||||
|
|
||||||
|
return pre
|
||||||
|
// setup the chain for arg pass-through...
|
||||||
|
.map(function(e){
|
||||||
|
// XXX object.deepKeys(..) ???
|
||||||
|
return Parser(Object.assign({},
|
||||||
|
e,
|
||||||
|
{
|
||||||
|
splitOptions: false,
|
||||||
|
'-help': undefined,
|
||||||
|
'-*': undefined,
|
||||||
|
'@*': undefined,
|
||||||
|
})) })
|
||||||
|
.concat([final])
|
||||||
|
// chain...
|
||||||
|
.reduce(function(res, cur){
|
||||||
|
return res ?
|
||||||
|
// NOTE: need to call .then(..) on each of the parsers,
|
||||||
|
// so we return cur to be next...
|
||||||
|
(res.then(cur), cur)
|
||||||
|
: cur }, null) },
|
||||||
}, {
|
}, {
|
||||||
// config...
|
// config...
|
||||||
//
|
//
|
||||||
@ -1096,8 +1134,10 @@ object.Constructor('Parser', {
|
|||||||
return res }
|
return res }
|
||||||
// NOTE: if successful this needs to modify the arg, thus it
|
// NOTE: if successful this needs to modify the arg, thus it
|
||||||
// returns both the new first arg and the handler...
|
// returns both the new first arg and the handler...
|
||||||
// XXX if no handler is found this should return the original
|
// NOTE: if the first letter is a fail the whole arg will get
|
||||||
// input arg...
|
// reported...
|
||||||
|
// XXX do we need to report the specific fail or the whole
|
||||||
|
// unsplit arg??? (see below)
|
||||||
var splitArgs = function(arg, rest){
|
var splitArgs = function(arg, rest){
|
||||||
var [arg, value] = arg.split(/=/)
|
var [arg, value] = arg.split(/=/)
|
||||||
// skip single letter unknown or '--' options...
|
// skip single letter unknown or '--' options...
|
||||||
@ -1111,9 +1151,18 @@ object.Constructor('Parser', {
|
|||||||
// push the value to the last arg...
|
// push the value to the last arg...
|
||||||
value !== undefined
|
value !== undefined
|
||||||
&& r.push(r.pop() +'='+ value)
|
&& r.push(r.pop() +'='+ value)
|
||||||
// push new options back to option "stack"...
|
var h = parsed.handler(a)[1]
|
||||||
rest.splice(0, 0, ...r)
|
// XXX do we need to report the specific fail or the whole
|
||||||
return [ a, parsed.handler(a)[1] ] }
|
// unsplit arg???
|
||||||
|
// check the rest of the args...
|
||||||
|
//if(h && r.reduce(function(r, a){
|
||||||
|
// return r && parsed.handler(a)[1] }, true)){
|
||||||
|
if(h){
|
||||||
|
// push new options back to option "stack"...
|
||||||
|
rest.splice(0, 0, ...r)
|
||||||
|
return [ a, h ] }
|
||||||
|
// no handler found -> return undefined
|
||||||
|
return [ arg, undefined ] }
|
||||||
|
|
||||||
try{
|
try{
|
||||||
// parse/interpret the arguments and call handlers...
|
// parse/interpret the arguments and call handlers...
|
||||||
@ -1139,6 +1188,7 @@ object.Constructor('Parser', {
|
|||||||
: parsed.isCommand(arg) ?
|
: parsed.isCommand(arg) ?
|
||||||
['cmd', COMMAND_PREFIX +'*']
|
['cmd', COMMAND_PREFIX +'*']
|
||||||
: ['unhandled']
|
: ['unhandled']
|
||||||
|
// no handler is found...
|
||||||
if(type == 'unhandled'){
|
if(type == 'unhandled'){
|
||||||
unhandled.push(arg)
|
unhandled.push(arg)
|
||||||
continue }
|
continue }
|
||||||
@ -1156,9 +1206,6 @@ object.Constructor('Parser', {
|
|||||||
// dynamic or error...
|
// dynamic or error...
|
||||||
|| parsed.handler(dfl)[1]
|
|| parsed.handler(dfl)[1]
|
||||||
// no handler found and '-*' or '@*' not defined...
|
// no handler found and '-*' or '@*' not defined...
|
||||||
// XXX if nether the whole arg nor it split are found
|
|
||||||
// we need to push the original to unhandled...
|
|
||||||
// ...or is setting .splitOptions to false enough???
|
|
||||||
if(handler == null){
|
if(handler == null){
|
||||||
unhandled.push(arg)
|
unhandled.push(arg)
|
||||||
continue }
|
continue }
|
||||||
|
|||||||
@ -52,8 +52,34 @@ argv.Parser({
|
|||||||
'any other options']},
|
'any other options']},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
var parser2 =
|
||||||
|
exports.parser2 =
|
||||||
|
argv.Parser.chain({
|
||||||
|
'-a': {
|
||||||
|
doc: [
|
||||||
|
'high priority option',
|
||||||
|
'this will get processed before',
|
||||||
|
'any other options'],
|
||||||
|
handler: function(){
|
||||||
|
console.log('### high priority option') }},
|
||||||
|
},{
|
||||||
|
'-b': {
|
||||||
|
doc: 'medium priority option',
|
||||||
|
handler: function(){
|
||||||
|
console.log('### normal priority option') }},
|
||||||
|
},{
|
||||||
|
'-c': {
|
||||||
|
doc: 'normal priority option',
|
||||||
|
handler: function(){
|
||||||
|
console.log('### normal priority option') }},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// run the parser...
|
// run the parser...
|
||||||
__filename == (require.main || {}).filename
|
__filename == (require.main || {}).filename
|
||||||
&& parser(process.argv)
|
&& parser2()
|
||||||
|
|
||||||
|
|
||||||
// vim:set ts=4 sw=4 spell :
|
// vim:set ts=4 sw=4 spell :
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ig-argv",
|
"name": "ig-argv",
|
||||||
"version": "2.14.0",
|
"version": "2.15.0",
|
||||||
"description": "simple argv parser",
|
"description": "simple argv parser",
|
||||||
"main": "argv.js",
|
"main": "argv.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user