4
votes

Question: Is there a Fish equivalent of Bash's alias substitution or what's the recommended best practice to keep the code clean and DRY?

Background: There's a very useful feature of aliases in Bash called alias substitution. It's mentioned briefly in the man page:

alias [-p] [name[=value] ...]
    ...
    A trailing space in value causes the next word to be checked for alias substitution when the alias is expanded.
    ...

The power of this functionality may easily be conveyed with an example. Consider that many users define a grep alias. Here's mine:

# extended regex, skip binaries, devices, sockets, & dirs, colored, & line
# -buffered. use a non- canonical alias instead of GREP_OPTIONS which may wreck
# poorly written scripts
alias g='grep -EID skip -d skip --color=auto --line-buffered'

Similarly, many of those same users define an alias for xargs. Here's mine without alias substitution:

alias x='xargs -rd\\n' # \n delimited, don't run on empty in

And finally, here's how I might want to use it but it doesn't work:

$ find|x g foo
xargs: g: No such file or directory

This command fails because x is expanded to xargs and it can't find an executable called g. There are a number of workarounds for this but I think most are awful. However, by just adding a trailing space, the shell will perform alias substitution on our behalf and the command will work as intended:

alias x='xargs -rd\\n ' # \n delimited, don't run on empty in, + expansion
#                    ^-- this space is for expanding a subsequent alias

Please keep in mind that this is just an example, not necessarily the actual use case.

Update 2015-05-06

I never found a Fishism solution but I felt the alternative was worth a comment. I took the approach of creating shell scripts in ~/bin. The downsides are:

  • The shell configuration is now multiple files.
  • The interpreter loses inspection of otherwise simple aliases and functions.

However, I felt the upsides were pretty huge:

  • The scripts may be written in any language.
  • The scripts are completely independent of the shell choice. Trying new shells is extremely painless. It's been a joy to have a single prompt script that doesn't have to be rewritten or maintained in multiple languages.
1
First reaction: no. Next reaction: since fish aliases are just functions in disguise, you can create an xg function to combine the bash x and g aliases.glenn jackman
@glennjackman when you say combine, do you mean function xg; xargs -rd\\n grep -EID skip -d skip --color=auto --line-buffered $argv; end? This is exactly what I want to avoid since I'd need to define the "g" and x functionalities in two places each, g, xg, x.Stephen Niedzielski
That's exactly what I meant. fish has no equivalent to bash's alias substitution (or zsh's global aliases), so I don't think you have much of a choice. I suppose you could say something like function x; xargs -rd\\n fish -c "$argv"; end, but that's likely full of pitfallsglenn jackman
@glennjackman Thanks, that's one of the Bash workarounds I want to avoid using. I think I'll stick a silly "g" script in my path instead.Stephen Niedzielski

1 Answers

3
votes

This isn't a Fish based solution -- but I suspect the fish answer is going to be it's not possible.

You could create your aliases as .fish or .sh scripts and symlink them to /usr/local/bin -- this will give you the equivalent behaviour.