Search code examples
fish

Fish shell creating functions using eval'd output from another exe


On Ubuntu Server 16.10 x64 with fish 2.3.1, my uru_rt exe generates this function on stdout

function uru
  set -x URU_INVOKER fish

  # uru_rt must already be on PATH
  uru_rt $argv

  if test -d "$URU_HOME" -a -f "$URU_HOME/uru_lackee.fish"
    source "$URU_HOME/uru_lackee.fish"
  else if test -f "$HOME/.uru/uru_lackee.fish"
    source "$HOME/.uru/uru_lackee.fish"
  end
end

when run via uru_rt admin install. The uru function provides the golang-based cross-platform ruby version manager tool https://bitbucket.org/jonforums/uru

On bash systems, I inject the uru function by placing eval "$(uru_rt admin install)" in a startup file so that uru is present in the shell.

On fish, running eval (uru_rt admin install) rewards me with this failure

$ eval (uru_rt admin install)
Missing end to balance this begin
- (line 1): begin; function uru   set -x URU_INVOKER fish    # uru_rt must already be on PATH   uru_rt $argv    if test -d "$URU_HOME" -a -f "$URU_HOME/uru_lackee.fish"     source "$URU_HOME/uru_lackee.fish"   else if test -f "$HOME/.uru/uru_lackee.fish"     source "$HOME/.uru/uru_lackee.fish"   end end
            ^
from sourcing file -
    called on line 60 of file /usr/share/fish/functions/eval.fish

in function “eval”
    called on standard input

source: Error while reading file “-”

I've also tried set u1 (uru_rt admin install); eval "$u1" with the same result.

As expected, when I do uru_rt admin install > ~/.config/fish/functions/uru.fish the uru function becomes persistently available. While this is an option, my preference is to use eval in ~/.config/fish/config.fish

As a noob to fish, how do I dynamically inject this uru function into the environment using eval similar to bash's eval "$(uru_rt admin install)"?


Solution

  • Fish's eval is a wrapper function around its source builtin, and it seems there's some weirdness (maybe even a bug) going on with it's argument splitting when you pass multiple lines..

    However, in this case it's simpler, faster and actually working if you just use source, like uru_rt admin install | source.

    That assumes though that uru_rt admin install really needs to be called - if all it does is print that code to stdout, without changing it, you can also simply save the function, e.g. in ~/.config/fish/functions/uru.fish.