top | item 9566441

Fish shell

451 points| Aloha | 11 years ago |fishshell.com | reply

182 comments

order
[+] ridiculous_fish|11 years ago|reply
Hey, I'm the lead dev of the fish shell. There's some great discussion in this thread!

For those who are interested, the fish shell is about to release version 2.2, a very significant release that wraps up eighteen months of development. You can try the beta now: http://fishshell.com/beta/

A sampling of new features:

- vi mode (yay!)

- Abbreviations, fish's take on aliases. They expand as you type them.

- A new "inline" pager, inspired by zsh. It's searchable and supports progressive disclosure. See it in action: https://www.youtube.com/watch?v=ncVWbT-jWAw

- A redesigned theme and prompt chooser: http://fishshell.com/beta/assets/img/screenshots/web_config....

- Tons of new tab completions!

[+] barosl|11 years ago|reply
I definitely recommend fish to every newcomer to Unix. It has sane defaults, colorful output, and so many features that work out of the box.

That said, there is a long-standing issue regarding inline environment variables.[1] Briefly speaking, fish does not recognize the `NAME=value command` form. So you should use `env` to work around this. This may not be a deal breaker, but I'm a bit annoyed, and migrated to zsh.

I would call zsh the opposite to fish. It has insane defaults, is highly customizable, and has so many features that are initially disabled. After hours of configuring it, I loved it.[2] Since then whenever I set up a new Unix machine zsh has been the first thing to install.

So, I would recommend zsh for the people who are used to Unix. If not, or you don't bother to customize it, there's always fish. There is no place for bash.

[1] https://github.com/fish-shell/fish-shell/issues/438

[2] https://github.com/barosl/baroslized-settings/blob/master/.z...

[+] nilved|11 years ago|reply
Using `env` is very much a feature, not a bug. It's part of fish's philosophy to use programs rather than builtins wherever possible. It's good practice to use `env` even when using other shells.
[+] AceJohnny2|11 years ago|reply
> It has insane defaults, is highly customizable, and has so many features that are initially disabled.

Ah yes, the Emacs and Vim school of configuration.

[+] themodelplumber|11 years ago|reply
Fish is great. I used it for a couple of years, right up until I had to install a software system that made extensive use of bash scripts that were incompatible with it. At the time I was in too much of a hurry to figure out how to tell the software to explicitly use bash, or something along those lines.
[+] ddoolin|11 years ago|reply
Just to add to the first line, it also seems fairly well-commented in the code, at least the couple pieces I've looked at. This is really good for me as I often check the source first and helpful (or any) commenting is quite rare.
[+] diminishedprime|11 years ago|reply
>There is no place for bash.

Just curious, why do you say this? I've used bash for years for basic command line things and now it sounds like I've been missing out on great features that other shells have.

[+] 0942v8653|11 years ago|reply
I used to use fish, and emacs. But when I switched to vim, I had to switch away from fish as well because of its lack of vi bindings. It is a little disappointing to go back to using bash, but as long as bash-completion is working, it's not really a big issue. Of course, I do miss the syntax highlighting. (I would use zsh, but it provides little benefit over bash out of the box and is slower (oh-my-zsh is unbearably slow to start, too).)

There are a few things that, while I understand why fish is missing them, I wish would be added:

- vi-mode, obviously

- Control+R. It is annoying to have to guess how much you must type before hitting the up arrow, instead of having it dynamically displayed. Same goes for zsh vi-mode's ? command.

- Well more of a removal, but the backslash in single-quoted strings. I'm used to typing '\', and that's not possible with fish. Additionally, to get one backslash in any sort of regex (sed, grep), you need four backslashes.

- Goes without saying, but bash-completion. Fish's completion is mostly history-based, which is great for repeatedly running the same command, but terrible for discoverability

- "$()" and any non-splitting command substitution. Currently, it is impossible to pass a multi-line string from a command substitution as a single argument. Which, it may be argued, should be done by piping, but sometimes it is useful to have stdin.

- More extensibility in general. I'd like to be able to customize my shell just as much as I can customize my WM. Probably more.

Honestly, it was easier to go back to using bash than I thought it would be -- it was almost a relief. fish just feels more polished and clean, especially with regard to escaping, but it misses some very important features.

Edit: I heard that there is a vi-mode now. Sounds interesting, but I don't really feel like installing it at the moment, and if I ever try another shell it'll probably be zsh.

[+] eridius|11 years ago|reply
> vi-mode, obviously

As you said at the end, Fish does have this. I don't know if it's full-featured enough for you though.

> Control+R. It is annoying to have to guess how much you must type before hitting the up arrow, instead of having it dynamically displayed

When you start typing a command-line in Fish that matches a previously-typed command, it automatically shows the rest of the line as an available completion, and pressing ^F or the right arrow will complete it for you. The lack of this functionality actually really kills my ability to use any other shell.

> Currently, it is impossible to pass a multi-line string from a command substitution as a single argument

Not actually true. If you set IFS to '' then that disables command substitution line splitting. That said, it is not well-known and is rather awkward. This is a known pain point with Fish today.

> More extensibility in general. I'd like to be able to customize my shell just as much as I can customize my WM. Probably more.

It's really hard to know what you're asking for here. What isn't extensible enough for you? What do you wish you could do that you can't?

[+] apetrovic|11 years ago|reply
> - Control+R. It is annoying to have to guess how much you must type before hitting the up arrow, instead of having it dynamically displayed

It's not anyone's cup of tea, but I'm using percol to get similar functionality:

(taken from oh-my-fish)

* pip install percol

* make a function like this:

    function percol_select_history
       history|percol|read foo
       if [ $foo ]
           commandline $foo
       else
           commandline ''
       end
    end
* bind new function to Ctrl+r:

    function fish_user_key_bindings
        bind \cr percol_select_history
    end
... and you'll have a searchable history list. To me, together with fish's command completion, it's more powerful than ctrl+r in bash/zsh.
[+] pragone|11 years ago|reply
Someone's gotta explain to me how and why oh-my-zsh is slow. I've never once experienced it being slow for me. In fact, I switched to prezto and it was unbelievably slow. I switched back to oh-my-zsh. Maybe I'm just not using it right...
[+] tomphoolery|11 years ago|reply
ZSH only gets slow because of the customizations, which would be true in Bash as well. Both shells are relatively comparable, though there are still a few things you can do in ZSH that you can't do in Bash. If you keep your customizations relatively light-weight and don't iterate over too many files on each login session, you'll probably be OK.

I wrote a framework to help deal with the shell a little bit after getting fed up with OMZ's slowness: https://github.com/tubbo/homer

[+] thaumasiotes|11 years ago|reply
> I'm used to typing '\', and that's not possible with fish. Additionally, to get one backslash in any sort of regex (sed, grep), you need four backslashes.

This is a piece of technology we used to have and then somehow lost. Common Lisp uses ~ as the control character for format strings. C uses \ as the control charcter for raw strings, and % as the control character for format strings. HTML uses &. But regexps use \. JSON uses \. And JSON is a new format! \ was literally the worst possible choice. As soon as you have multiple formats sharing a control character, you start to need huge power-of-two runs of it in order to say what you mean.

Who thought it was a good idea to reuse control characters? \ is used in raw string definitions. It should not be used in any other format, if strings might be used to invoke that format. This is a clear case where every standard doing its own unique thing is the correct approach, but we seem to be moving in the other direction.

[+] nextos|11 years ago|reply
I run zsh barebones, and I've never been able to get some tab completions to work on bash as well as in zsh. But it's probably possible.

E.g. on some patterns involving *. Care to share your setup?

[+] oahziur|11 years ago|reply
I really miss Control+R when I use fish. I also prefer to click Control+R again instead of using the inconvenient up arrow key to search the history.
[+] hurin|11 years ago|reply
> Goes without saying, but bash-completion. Fish's completion is mostly history-based, which is great for repeatedly running the same command, but terrible for discoverability

Fish has both kinds of completion. You can hit tab to get a list of possible completions (command-list based) if there is more than one, if there is only one possible command it will tab-complete. You can also customize this list.

[+] VieElm|11 years ago|reply
> I had to switch away from fish as well because of its lack of vi bindings.

No you didn't. I use vim and fish just fine. Just put this in your .vimrc:

  set shell=/bin/bash
[+] WD-42|11 years ago|reply
Fish is great. For those wondering what advantages is has over zsh+ohmyzsh, I can say is that by default it provides most the functionality you want without having to install/tweak anything. Git support is built in (you get a nice git prompt) there's syntax highlighting, amazing history completion, predictive commands, man page completions... and so on. To try it on linux, just install fish and then run "fish", to get back to to bash/zsh just "exit"

Only problem is it's not POSIX so there is some weirdness in command substitution, logical operators and stuff. So you still script in sh.

[+] jasonmp85|11 years ago|reply
That was precisely my first question, so thanks for the answer, but I don't really see how that's enough to switch… I've been using this "cleaned up/opinionated" fork 'Prezto' for a while now: https://github.com/sorin-ionescu/prezto

If I'm motivated enough to download and install a shell, why wouldn't I just clone Prezto and change one config file to turn on syntax highlighting and git support? Especially when it doesn't bring any "weirdness in command substitution" and I get the great zsh expansions and completions?

Anyways, I'll try it out (why not?) but the benefit to me wasn't clear from the page, and even with your direct clarification here I'm seeing more downsides than zsh + Prezto and not a significant upside.

[+] gizi|11 years ago|reply
I do quite a bit of programming in bash. One construct in bash is absolutely super: process substitution. You can read the output of a program as if it were a file with the construct: <(myprogram).

Bash is a fine tool, but it has a number of flaws that prevent me from using it for certain tasks.

* Functions can only return a status number. Functions are always subshells.

* The hashtable (associative array) syntax is unpalatable, unreadable, and a real abomination. I simply don't use it, because it gives me a headache.

* I can never remember the horrible syntax for most string functions.

* You cannot reasonably store an arbitrary json structure in memory. Embedded lists and hashtables are absolutely unwieldy.

* Bash has no concept of FFI (Foreign-function interface). So, you cannot load an external library and invoke functions it it.

These problems are not particularly impossible to solve, but the Bash authors will probably never do it. Therefore, the final reproach against bash is that they do not publish their source code in an environment similar to github, where users can file their issues and improvement requests. In other words, the bash authors are not in communion with their users.

In what way can the fish shell address these problems?

[+] e12e|11 years ago|reply
> One construct in bash is absolutely super: process substitution. You can read the output of a program as if it were a file with the construct: <(myprogram)

Actually had to look that one up[1] -- unfortunately you're right, it's not posix (I don't think I would've tried it in a [ed: non-interactive] script, but I agree it is very nice).

I wonder if you could make a function as a work-around, something like:

    r() {
      #r(first some args <(second other args))
      # Use a fifo:
      ff=$(mktemp fifo)

      # might as well use that for parsing the commands...
      echo "$*" > $ff
      first=`sed -re 's/\((.*) <\(.*/\1/p' < ${ff}`
      echo "$*" > $ff
      second=`sed -re 's/\(.* <\((.*)\)/\1/p' < ${ff}`
      ${second} > $ff &
      ${first} < $ff
    }
      
Adjust for parsing the direction of the <() vs >() etc... Not particularly robust, and the above is un-tested... Just an idea.

I'm not convinced trying to parse shell command lines for macro functionality is a good idea in general...

[1] http://mywiki.wooledge.org/Bashism

[+] rlpb|11 years ago|reply
> * Functions can only return a status number.

[In Bourne shell] A function can just print to stdout, and the caller can capture it. In this way, a function has two outputs: an exit status, and a (normally text) result.

It's unusual to go any further, but if you really wanted to you could make a function return any number of outputs by writing to different file descriptors and having the caller capture them all separately.

[+] donatj|11 years ago|reply
Fish not being bash compliant was a deal breaker for me.

I use zsh with https://github.com/zsh-users/zsh-syntax-highlighting zsh fish like syntax hilighting and am much more happy.

[+] saidajigumi|11 years ago|reply
> Fish not being bash compliant was a deal breaker for me.

Would you mind elaborating here? I'm very honestly curious how the deal gets broken for you.

To explain my curiosity, I've long since come to the opinion that we're in the midst of a long, somewhat painful split caused by a design dissonance over improving the interactive shell UX versus creating a better environment for scripting.

We've been building alternatives around the scripting problem for ages now, perhaps most notably starting with Perl's ascendance. That legacy continues with Python, Ruby, and now many other tools. I'll still reach for bash/zsh as a scripting tool, but only when the situation absolutely will not admit an extra dependency. In my experience, the pain factor goes up far more quickly with code complexity when it's all just gotta be done in POSIX/bash land.

As for the interactive shell UX, fish is notable for simply putting its foot down and just saying "no" to the scripting side. It pushes out POSIX scripting compatibility as an external feature. Calling bash is now on the same level as calling out to {Perl, et. al.}. Whether or not fish is your cup of tea, it's inspired a bunch of competing work in the traditional interactive shells.

At the current time, the above efforts are simply going in different directions. We have numerous better options for rich automation than POSIX shell scripting. Likewise, shell scripting just gets in the way of creating better, extensible developer/admin CLI environments. It has too many quirks (hi, quoting hell!) and limitations (real data structures, please) to work well for an extensibility platform.

[+] ori_b|11 years ago|reply
The problem is that bash syntax for anything beyond the basics is awful and error prone. It's really hard to make significant progress while still being bash compliant.
[+] eddieplan9|11 years ago|reply
Fish is optimized for interactive (the i in "fish") use. Not exactly the same as bash-compliance, but if you have bash-based tools (like virtualenv but without counterpart in fish land), check out https://github.com/edc/bass. Bass allows you to use a bash tool in fish, by running the tool in bash and transporting changes in environment variables back to fish shell.
[+] joeyspn|11 years ago|reply
Same for me... When I saw that I was going to lose all my scripts in .bash_profile and .bashrc that was a no-no. I've got plenty of custom stuff there, so instead I just installed fish completion and several of its functionalities in oh-my-zsh and... ready to go!
[+] Sphax|11 years ago|reply
Fish is great. I've been using it for close to 3 months now, was using zsh with prezto before.

I find Fish to be simpler to use and more powerful by default. You can probably have a zsh or maybe even bash setup which does the same fish does, but I don't want to do that.

[+] talex5|11 years ago|reply
I've been using fish for a few months now (switched from zsh). Really nice to have good defaults and minimal configuration, and the suggestions based on previously entered commands are great.

The main issues I have compared to zsh are:

- No bracketed paste mode. If I select multiple lines of text and middle-click-paste into zsh, it adds the whole lot as a multi-line input and lets me review the commands before pressing Return. fish just starts blindly executing them, which can cause accidents.

- Chaining commands is harder. In zsh `foo |& less` pipes stdout and stderr. Also, fish's `foo; and bar` is longer than `foo && bar`.

- Hashes in words start a comment in fish. e.g. `opam pin repo#branch` is treated as `opam pin repo`, pinning the wrong branch. zsh only treats # as a comment at the start of a new word.

- While completion history and `set -U` are really useful, it sometimes forgets everything and I have to start again, which is quite annoying.

On the whole, very happy with it though!

[+] tambourine_man|11 years ago|reply
Since Apple seems forever stuck on an ancient Bash version (due to GPL 3, I believe), I keep hoping they switch to Fish (or a home built solution, à la Swift, which could be interesting) with every OS release.
[+] robin_reala|11 years ago|reply
Fish does feel very Appley to me. I wouldn’t be surprised.
[+] distracteddev90|11 years ago|reply
I can clearly see the difference between Fish and regular ol' bash, but struggling to see what value Fish adds above prezto/zsh. Could anyone help me out here?
[+] ufo|11 years ago|reply
Fish breaks compatibility with traditional shell languages. The syntax is a bit different, the variable expansion rules are a bit different, etc. It also gets rid of a bunch of features and configuration options, such history expansion ("$!!").

The positive side of this is that fish is very simple and has a very pleasant experience out of the box. And this is not just about having "good defaults" - its also about having a good design that encourages having one way to do things. That said, an interactive shell is a very personal thing. The only way to really get a good feeling is to install and check it out.

[+] bentruyman|11 years ago|reply
I used Fish for about of year. But I ended up recently switching back to zsh. Stock Fish is far more useful than stock zsh. However, the community around zsh is far more active and I found that most of the functionality that Fish contains and zsh lacks that there are plugins to achieve the same effects.

I'd encourage you to check it out. The scripting language in Fish is the best I've ever used for a shell. But it's also incompatible with Bash/zsh.

[+] lloeki|11 years ago|reply
> what value Fish adds above prezto/zsh. Could anyone help me out here?

- not assuming you're using an outdated terminal so doesn't waste a column when using a right-hand prompt?

- lots of async calls, thus really fast.

[+] bajsejohannes|11 years ago|reply
I've used fish shell for about a year and I love it. I recently stumbled upon the design document, which summarizes well why I like it so much: http://fishshell.com/docs/2.0/design.html

I actually think that design document could be a good start for a lot of projects.

[+] cabalamat|11 years ago|reply
>Sane Scripting -- fish is fully scriptable, and its syntax is simple, clean, and consistent. You'll never write esac again.

I can already do sane scripting, with Python. I suspect that as soon as I try to to anything slightly complicated, Python leaves fish scripting behind.

[+] kolev|11 years ago|reply
Fish is definitely good, but not great enough to justify a switch from Bash. I maintain tens of thousands of lines of Bash scripts and was considering switching to Fish once, but decided it wasn't worth it.

When you compare the *nix shells to PowerShell, they feel prehistoric. We all use grep, sed, awk, and the likes, but don't you get tired of having to deal with unstructured data and gross limitations of the shell like basic data structures. Yes, the purpose of the shell is to be quick and dirty, but it doesn't take that much to add some programming sanity and some standards for structured data! There's a port of PowerShell to Mono, Pash [0], but it's so heavy in terms of requirements and has somewhat unclear future. Of course, there's also Xonsh [1] and Xiki [2], but they are pretty new.

[0] https://pash-project.github.io/

[1] http://xonsh.org/

[2] http://xiki.org/

P.S. One of my favorite Fish feature is Event Handling [3].

[3] http://fishshell.com/docs/current/#event

[+] Alupis|11 years ago|reply
Seems like their slogan might be a little limiting.

> fish is a smart and user-friendly command line shell for OS X, Linux, and the rest of the family.

I'd wager majority of OSX users are not going to be changing shells, but by specifically enumerating OSX as the first example use, it feels like the others are mere afterthoughts.

Would be better put:

> fish is a smart and user-friendly command line shell for the entire *nix family.

[+] cheese1756|11 years ago|reply
While that wording is more precise, the current wording is better for promoting the software. Ordering by market share makes sense, and users who are quickly scanning the page for compatability information don't need to make the connection between OS X or Linux and *nix, and can instead recognize their current system easily.

If this were documentation the change should be made, but it's probably not the right move on a website focused on promotion.

[+] mturmon|11 years ago|reply
The lead developer is on the Apple AppKit team.
[+] shirro|11 years ago|reply
I tried really hard to use Fish for awhile and if the shell was just history, completion and sane defaults (and it is for some people) it would have a very good case. But not being even remotely compatible with bash drove me nuts as the shell is my REPL.
[+] samspot|11 years ago|reply
Is there a way to use this in the excellent Git Bash for Windows? Because Git Bash is amazing and I don't see myself going back to cygwin anytime soon. I understand how they could be very incompatible because of the way Git Bash is built.
[+] _jomo|11 years ago|reply
I've been using fish for at least a year now and I absolutely love it, altogether with oh-my-fish [0].

I don't mind the incompatibility to bash, but using "; and" instead of "&&" is a little annoying.

Everything else is great.

It actually auto-completes remote hosts and paths when you type ssh or scp commands! It also fuzzy-completes filenames when you're lazy (or have typos in them) and a bunch of other neat things.

The up-key function after typing in parts of a command and ^F have probably saved me hours of time wasted in bash.

0: https://github.com/bpinto/oh-my-fish