Conditional to move forward depending on what shell is used

Viewed 76

I'm trying to write a .functions dotfile, with the purpose of loading it (source $HOME/.functions) in my bash, zsh and fish configuration files. I already did it with another (.aliases), successfully. However now I am facing a problem derived from fish not being posix-compliant.

The thing is that aliases share syntax among the three shells, but when it comes to functions fish has its own syntax (function my_func; #code; end instead of function my_func { #code; }). As an example, consider:

Fish:

function say_hello
    echo "hello";
end

Bash/Zsh:

say_hello() {
    echo "hello";
}

This disables me from just writing them in the file "as is", so I was thinking of writing a conditional such as if [ "$0" = "bash" ] || [ "$0" = "zsh" ]; then #functions_POSIX; else #functions_fish; fi. However, this conditional syntax is also not available in fish!

That's where I'm stuck rn. I would rather not have separate files for each shell.

Thank you in advance.

1 Answers

The only workable answer, in my opinion, is to separate the definitions.

Even if you figure out some way to hack around the fact that fish checks the syntax for the entire file (so wherever you put a bash function definition it will give a syntax error without executing anything), this won't yield a readable file that's nice to edit. You'll just be fighting the hacks.

And function definitions can't be shared anyway, as it's not just a simple search-and-replace of fi to end - the semantics are different, e.g. a command substitution will only be split on newlines, the various special variables ($@) work in different ways, arrays are entirely different, etc...

That means making it a single file isn't workable or helpful, so make your functions scripts instead (if they don't modify the shell's environment) or make a wrapper around a script that does the environment changing, or just write them twice.

Related