Search code examples
parametersparameter-passingfish

passing whole strings as arguments in fish shell


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.


Solution

  • 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.