In Fish shell I have two functions:

function be
  bundle exec $argv
end

function rdbm
  rake db:migrate
end

I typically use them together, i.e. bundle exec rake db:migrate but not always, so I'd like to keep them separate.

The problem is that I cannot do this with the aliases I have currently defined:

To say be rdbm expands the first function (be) but passes rdbm as a literal string (non-expanded).

I have also tried abbr:

abbr be 'bundle exec'
abbr rdbm 'rake db:migrate'

But only the first expands.

I've figured out that it's possible to call functions from other functions:

function be_rdbm
  echo (be rake db:migrate)
end

but this doesn't decouple the two functions, since the second is not being used.

By the way, I'd like to know if that last example can be improved. I don't see why the echo should be necessary (or what alternatives there are), but I cannot put the parenthesis as the entire content of the function.

up vote 2 down vote accepted

Personally I would just define another abbreviation for the combined case. However, you can define your rdbms function as follows to allow you to combine it with your be function as be (rdbm):

function rdbm
    if status --is-command-substitution
        echo rake db:migrate
    else
        rake db:migrate
    end
end

You could also modify your be function so that you can type just type be rdbm when used with the previous change:

function be
    if test "$argv" = "rdbm"
        bundle exec (rdbm)
    else
        bundle exec $argv
    end
end
  • This is cool and thanks. But its not true concatenation of the commands. Its not necessarily sufficient to pass the second result through echo. What if its an interactive script for instance. – max pleaner Dec 20 '16 at 21:00
  • It's impossible to concatenate commands in the manner you're suggesting in any shell without using a trick like I posted. – Kurtis Rader Dec 21 '16 at 22:51
  • Oh, thats too bad. Thats just what I was wondering – max pleaner Dec 21 '16 at 22:53
  • To be honest I really hoped that would be possible though. Like after all this time terminals still lack this functionality. Is there a reason its not done? – max pleaner Dec 21 '16 at 22:55
  • By "terminal" I assume you mean shell since your terminal has nothing to do with this. As Glenn Jackman pointed out in his answer zsh does allow this if you enable its "global alias" feature. But that behavior is dangerous so fish does not have an equivalent. Note that what zsh calls an alias fish calls an abbreviation. In fish abbreviations are only expanded in the command position (which is the default zsh behavior). – Kurtis Rader Dec 22 '16 at 0:28

zsh has a "global alias" feature, where the alias is substituted anywhere in the line. But fish only substitutes the first word in the command line.

You could do this:

function rdbm
  if [ (count $argv) = 1 ]; and [ $argv[1] = "-n" ]
    echo "rake db:migrate"
  else
    rake db:migrate
  end
end

Then you would have to type

be (rdbm -n)
  • Thanks very much. But like the other answer, this isnt true concatenation of commands. What if the second command is an interactive script? Then echo wont work – max pleaner Dec 20 '16 at 21:48

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.