--help-all now working, still undocumented...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-01-24 19:42:33 +03:00
parent d9afd341de
commit 1c9b2024c3
2 changed files with 62 additions and 32 deletions

92
argv.js
View File

@ -712,6 +712,18 @@ object.Constructor('Parser', {
[a +'\t'.repeat(opts_width - Math.floor((a.strip || a).length/8))+ prefix + b] [a +'\t'.repeat(opts_width - Math.floor((a.strip || a).length/8))+ prefix + b]
: [a, '\t'.repeat(opts_width)+ prefix + b]) : [a, '\t'.repeat(opts_width)+ prefix + b])
: [a] }, : [a] },
getFieldValue: function(src, name){
name = arguments.length == 1 ?
src
: name
src = arguments.length == 1 ?
this
: src
return src[name] ?
['', typeof(src[name]) == 'function' ?
src[name].call(this)
: src[name]]
: [] },
// NOTE: if var value is not defined here we'll try and get it from // NOTE: if var value is not defined here we'll try and get it from
// parent... // parent...
// NOTE: this tries to be smart with spaces around $REQUIRED so // NOTE: this tries to be smart with spaces around $REQUIRED so
@ -755,21 +767,34 @@ object.Constructor('Parser', {
.replace(/\$VERSION/g, get(that, 'version', '0.0.0')) .replace(/\$VERSION/g, get(that, 'version', '0.0.0'))
.replace(/\$SCRIPTNAME/g, this.scriptName || 'SCRIPT') }, .replace(/\$SCRIPTNAME/g, this.scriptName || 'SCRIPT') },
//
// --help
// --help=<options>
//
// Supported options:
// noUsage - do not print usage info
// noFooter - do not print help footer
//
// NOTE: the options are for internal use mostly...
// NOTE: this will set .quiet to false... // NOTE: this will set .quiet to false...
'-h': '-help', '-h': '-help',
'-help': { '-help': {
doc: 'print this message and exit', doc: 'print this message and exit',
priority: 90, priority: 90,
handler: function(argv, key, value){ handler: function(argv, key, value){
var options = {}
if(value){
for(var opt of value.split(/\s*,\s*/g)){
options[opt] = true } }
var that = this var that = this
var sep = this.helpArgumentSeparator || ', ' var sep = this.helpArgumentSeparator || ', '
var short = this.helpShortOptionSize || 1 var short = this.helpShortOptionSize || 1
var expandVars = this.expandTextVars.bind(this) var expandVars = this.expandTextVars.bind(this)
var formDoc = function(doc, handler, arg){ var formDoc = function(doc, handler, arg){
var dfl = getValue(handler, 'default')[1] var dfl = that.getFieldValue(handler, 'default')[1]
var req = getValue(handler, 'required')[1] var req = that.getFieldValue(handler, 'required')[1]
var val_req = getValue(handler, 'valueRequired')[1] var val_req = that.getFieldValue(handler, 'valueRequired')[1]
var env = getValue(handler, 'env')[1] var env = that.getFieldValue(handler, 'env')[1]
doc = (doc instanceof Array ? doc = (doc instanceof Array ?
doc doc
@ -800,18 +825,6 @@ object.Constructor('Parser', {
...(info.length > 0 ? ...(info.length > 0 ?
['('+ info +')'] ['('+ info +')']
: [])] } : [])] }
var getValue = function(src, name){
name = arguments.length == 1 ?
src
: name
src = arguments.length == 1 ?
that
: src
return src[name] ?
['', typeof(src[name]) == 'function' ?
src[name].call(that)
: src[name]]
: [] }
var section = function(title, items){ var section = function(title, items){
items = items instanceof Array ? items : [items] items = items instanceof Array ? items : [items]
return items.length > 0 ? return items.length > 0 ?
@ -823,9 +836,11 @@ object.Constructor('Parser', {
this.print( this.print(
expandVars([ expandVars([
`Usage: ${ getValue('usage').join('') }`, ...(options.noUsage ?
[]
: [`Usage: ${ that.getFieldValue('usage').join('') }`]),
// doc (optional)... // doc (optional)...
...getValue('doc'), ...that.getFieldValue('doc'),
// options... // options...
// XXX add option groups... // XXX add option groups...
// ....or: 'Group title': 'section', items that // ....or: 'Group title': 'section', items that
@ -868,7 +883,7 @@ object.Constructor('Parser', {
// dynamic options... // dynamic options...
...section('Dynamic options', ...section('Dynamic options',
(this['-*'] && this['-*'].section_doc) ? (this['-*'] && this['-*'].section_doc) ?
getValue(this['-*'], 'section_doc') || [] that.getFieldValue(this['-*'], 'section_doc') || []
: []), : []),
// commands (optional)... // commands (optional)...
...section('Commands', ...section('Commands',
@ -888,7 +903,7 @@ object.Constructor('Parser', {
// dynamic commands... // dynamic commands...
...section('Dynamic commands', ...section('Dynamic commands',
(this['@*'] && this['@*'].section_doc) ? (this['@*'] && this['@*'].section_doc) ?
getValue(this['@*'], 'section_doc') || [] that.getFieldValue(this['@*'], 'section_doc') || []
: []), : []),
// examples (optional)... // examples (optional)...
...section('Examples', ...section('Examples',
@ -896,16 +911,19 @@ object.Constructor('Parser', {
this.examples this.examples
.map(function(e){ .map(function(e){
return e instanceof Array ? e : [e] }) return e instanceof Array ? e : [e] })
: getValue('examples') ), : that.getFieldValue('examples') ),
// footer (optional)... // footer (optional)...
...getValue('footer') ] ...(options.noFooter ?
[]
: that.getFieldValue('footer')) ]
// expand/align columns... // expand/align columns...
.map(function(e){ .map(function(e){
return e instanceof Array ? return e instanceof Array ?
// NOTE: we need to expandVars(..) here so as to // NOTE: we need to expandVars(..) here so as to
// be able to calculate actual widths... // be able to calculate actual widths...
that.alignColumns(...e.map(expandVars)) that.alignColumns(...e.map(expandVars))
.map(function(s){ return '\t'+ s }) .map(function(s){
return '\t'+ s })
: e }) : e })
.flat() .flat()
.join('\n'))) .join('\n')))
@ -913,24 +931,36 @@ object.Constructor('Parser', {
// XXX might also be a good idea to do this as --help and the do the // XXX might also be a good idea to do this as --help and the do the
// short version as -h... // short version as -h...
'-help-all': { '-help-all': {
// XXX REMOVE WHEN DONE... // XXX should this be hidden???
//doc: 'print help for all nested commands supporting customization',
doc: false, doc: false,
handler: function(){ handler: function(argv, key, value){
// XXX print header but skip footer... var options = {}
// XXX do we pass args here??? if(value){
var res = this.handle('-help', ...arguments) for(var opt of value.split(/\s*,\s*/g)){
options[opt] = true } }
// main help...
var res = this.handle('-help', argv, '-help', 'noFooter')
// print help for nested parsers... // print help for nested parsers...
for(var n in this){ for(var n in this){
if(this[n] instanceof Parser){ if(this[n] instanceof Parser){
// XXX print different header and skip footer...
this.print([ this.print([
'', '',
'', '',
'Command: '+ n.slice(1), 'Command: '+ n.slice(1),
'', '',
].join('\n')) ].join('\n'))
// XXX skip footer... this.handle(n, ['-help=noFooter'], n.slice(1)) } }
this.handle(n, ['-help'], n.slice(1)) } }
// footer...
options.noFooter
|| this.footer
&& this.print(
this.expandTextVars(
this.getFieldValue('footer')
.join('\n')))
return res } }, return res } },
// alias for convenience (not documented)... // alias for convenience (not documented)...
'-?': { '-?': {

View File

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