Repository navigation
Argparse : save list of 'consumed arguments' into additional variable #6466
Description
Presently, when writing wrapper scripts, it is necessary to first define which arguments need to be passed through:
argparse d/directory f/file 0/print0 c/count p/path= e/explicit s/sort i/ignore-case -- $argv
Then, for options which accept arguments, some additional mangling is required to restore a -flag which the program will recognize:
if test -n "$_flag_p"
set _flag_p -p $_flag_p
end
You must compile a list of options to pass along, which partially repeats the information stated in the call to argparse:
set -l newargs (set f _flag_{0,c,d,e,f,i,p,s}; printf %s\n $$f)
After the wrapper makes its particular modification to the arguments,
you can finally invoke the program you are wrapping:
tmsu files $newargs
This is overly involved and repetitive.
====
My suggested solution is that argparse should additionally save a list of consumed arguments, to a variable like _argparse_option_args. This allows to use argparse for wrapping in a way that is more precise and obviously-structured: 'sort options from non-options, then pass options in unmodified'
With this proposal, the process would instead look like this:
# parse, same as before:
argparse d/directory f/file 0/print0 c/count p/path= e/explicit s/sort i/ignore-case -- $argv
# wrapper-specific code generating a list of additional arguments goes here...
# [...]
# invoke wrapped program:
tmsu files $_argparse_option_args $generated_args
With no repetition of information or need to read through to determine which options are 'inherited' and which are generated by the wrapper.
Technical specifics:
If consumed arguments can be stored immediately after they are parsed, this would be ideal for two reasons:
- it preserves the exact ordering of options, which may be important if they are going to be shown to the user.
- it avoids some potential confusion that could be otherwise produced when 'reconstituting' options which accept multiple arguments or accept only the last instance of an argument (
=+and=?argspecs)
EDIT: Technically, it's possible to do something like this without having argparse's privileged access to variables. It's just kind of awkward and hacky:
function apwrap -w argparse
set sep_index (contains -i -- -- $argv)
set args_index (math $sep_index+1)
set old_args $argv[$args_index..-1]
argparse $argv
# store options in the order they were originally specified.
# technically, using sort, comm, and grep might be faster for long arg lists.
set option_args
set nonoption_args
for v in $old_args
if not contains -- $v $argv
set -a option_args "$v"
else
set -a nonoption_args "$v"
end
end
# 1. items present in old_args, but not modified argv
# 2. Abuse of control codes to create an identifiable separator
# 3. everything else
printf %s\n $option_args
printf \t\r\t\r\n
printf %s\n $nonoption_args
end
set optspec o/output=
# returns -o boot \t\r\t\r baz www
set a (apwrap $optspec -- -o boot baz www)
set asep (contains -i \t\r\t\r $a); set asep (math $asep-1) (math $asep+1)
# assigns the value '-o' 'boot'
set optargs $a[1..$asep[1]]
# assigns the value 'baz' 'www'
set nonoptargs $a[$asep[2]..-1]
# then if you want to be able to inspect _flag_o in the normal manner, you need to reparse optargs,
argparse $optspec -- $optargs
# overall, it avoids repetition of option information, but introduces tedious boilerplate.
Activity
Make argparse save parsed options in $argv_opts. (Fixing issue fish-s…
Make argparse save parsed options in $argv_opts. (Fixing issue fish-s…
Make argparse save parsed options in $argv_opts. (Fixes fish-shell#6466)
Make argparse save parsed options in $argv_opts. (Fixes fish-shell#6466)
Make argparse save parsed options in $argv_opts. (Fixes fish-shell#6466)