I have a number of cases where I need to pass free-form (i.e. containing white space and symbols as well as alphabetical symbols) strings as parameters to a function in fish shell.
Here's an example where I try to use getopts (to no avail):
function create_a_note --description 'create a new text note'
set -l title ''
set -l tags ''
getopts $argv | while read -l key value
switch $key
case t title
set title $value
case g tags
set tags $value
end
end
if test -z $title
error "title must be set (use the -t option)" >&2
return 1
end
# do something interesting with the title and tags
end
I invoke it like this:
create_a_note -t 'my very interesting note' -g '@blah @rhubarb'
Whenever I use this kind of approach, the variables $title
and $tags
get the first word of the strings (i.e. $title == 'my'
and $tags == '@blah'
) rather than the whole string. I get why this is happening, where the string is converted to a list and the first element of the list is returned.
My question is - is there a way around this within fish shell? I don't want to just pass in $argv
and parse it myself unless there is no other option.
Use of getopts
is optional, if you'll pardon the pun.
My suggestion is to stop using getopts
, an interface which I can never get right, and instead use fish's built-in argument parsing tool, argparse
.
function create_a_note --description 'create a new text note'
set -l title ''
set -l tags ''
argparse 't/=+' 'g/=+' -- $argv
if test -z "$_flag_t"
echo "title must be set (use the -t option)" >&2
return 1
end
echo $_flag_t; echo $_flag_g
end
In particular, argparse 't/=+' 'g/=+'
means "a -t
option which requires an argument, and a -g
option which requires an argument". These arguments are stored in $_flag_t
and $_flag_g
respectively. There's more information in the argparse manual.