SFbay007
SFbay007

Reputation: 2027

How to define a function that either takes arguments or doesnt?

I am using Fish shell.... Basically, to do something like this:

if (first argument == --r) {
  do something
} else {
  Do something
  if (first argument == --n) {
    do more 
  }
}

To achieve the first if statement I tried:

 if test (count $argv) -eq 1 -a $argv[1] = '--r'

But that gives a message: test: Missing argument at index 6

Upvotes: 1

Views: 2134

Answers (4)

Kurtis Rader
Kurtis Rader

Reputation: 7459

Let's start with the error you get when executing this:

if test (count $argv) -eq 1 -a $argv[1] = '--r'

That happens because fish first expands $argv[1] then executes test. If argv has no values then that statement turns into

if test 0 -eq 1 -a  = '--r'

Which isn't valid syntax for the test command. It doesn't matter that the first sub-expression evaluates to false since test parses the entire expression before evaluating it.

Rather than doing test (count $argv) -eq 1 just do set -q argv[1] to test if argv has at least one argument. Note the lack of a dollar-sign.

If you're using fish 2.7.0 or newer I recommend the new argparse builtin for handling arguments. Several of the standard functions that ship with fish use it so you can look at them, as well as man argparse, for examples of how to use it. Using argparse is almost always safer, less likely to result in bugs due to sloppy argument parsing using hand written fish script, and will provide argument parsing semantics identical to most commands including all the fish builtins. Including correctly handling short and long flags.

Upvotes: 0

CJK
CJK

Reputation: 6092

Functions in Fish don't require their parameters to be specified when you define the function. Any arguments sent to the function by the user are automatically stored in an array called argv. In order to determine whether arguments were sent, you can either count the number of elements in the array, or determine the length of the array as a string. I do the latter:

    function my_func
        if [ -z "$argv" ]; # No arguments
            echo "No arguments supplied"
            return
        else # At least one argument
            if [ "$argv[1]" = "--r" ];
                echo "Excellent!"
                return
            end
        end
    end

If you prefer to use count, then it will look more like this:

    function my_func
        if [ (count $argv) -eq 1 -a "$argv[1]" = "--r" ];
            # Exactly one argument with specified value "--r"
            echo "Excellent!"
            return
        else # May have arguments, but none equal to "--r"
            echo "Give me the right arguments"
            return
        end
    end

Your use of set -q argv[1] is also a good option. But when you're checking for string equality, don't forget to surround your variable in quotes, like this: test "$argv[1]" = "--r".

Here's another method, using the switch...case conditional test:

    function my_func
        # No arguments
        if [ -z "$argv" ]; and return

        # At least one argument
        switch $argv[1];
            case --r;
                # do some stuff
                return
            case "*";
                # Any other arguments passed
                return
            end
        end
    end

Upvotes: 2

SFbay007
SFbay007

Reputation: 2027

This worked for me:

if set -q argv[1] ;and test $argv[1] = "--r"

Upvotes: 0

ali sanad
ali sanad

Reputation: 9

well if the argument is optional then you can do this by:

//check if variable exists
if (typeof variable === 'undefined'){
}
else{
if(typeof variable){}
}

Upvotes: -1

Related Questions