Fish: A command line shell for the 90s
fishshell.com
fishshell.com
I love Fish. I'm likely not their target audience.
I've been using it for years. Since the early days in 1.x land for sure. The homepage has never changed and I still laugh at the tagline. I find it's auto-completion, history and niceties indispensable. I'm the person who asks you what the command is to rerun the tests. With Fish I never have to ask you again. I just remember part of it, and suddenly I've got it.
I find its scripting language much simpler to follow than bash. I don't have a lot of scripts, but the ones I do are easy to manage. The only hiccup I get into is when I have to look up something on stack exchange, and of course the example is in Bash. These days though, with Bass and fisherman and so many other tools, i have options.
Years ago I would explain to other code friendly designers, I'm weird, don't use this stuff. Go grab zsh. Lately though it's gotten very friendly. Really the only downside for a light scripter like myself is that need to convert bash examples to fish problem. Beyond that I feel it's actually a much nicer shell for new to terminal folks.
Anyways, just an anecdote to add to the pile. Thank you to the devs that have supported it over the years.
Until you raised this point I didn't think if fish as something you'd script with.
#!/usr/bin/env fish
swaymsg 'output "*" background ~/Pictures/Wallpaper/'(ls ~/Pictures/Wallpaper | shuf -n 1)' fill'
I really love fish shell and find its multi-line input extremely valuable, I think it has a much saner syntax (I have no meaningful experience writing bash scripts), if you are like me in this regard I highly recommend writing your personal scripts in fish instead and if you are worried about posix compliance, it is not that different from a bash script with bashisms in that regard.[0] https://github.com/swaywm/sway/issues/1269#issuecomment-4316... [1] https://git.sr.ht/%7Esircmpwn/dotfiles/tree/master/bin/wallp...
Are you referring to something other than cycling through history?
In bash, hit `Ctrl+R`, then type whatever part of the command to cycle through history.
You may choose to adjust the size of the history file in `.bashrc` as needed.
A good reference: https://www.digitalocean.com/community/tutorials/how-to-use-...
[1] https://github.com/zsh-users/zsh-autosuggestions
[2] https://github.com/zsh-users/zsh-history-substring-search
"\e[A": history-search-backward
"\e[B": history-search-forward(cd dir; make) &
To start some stuff in the background, but with fish directory and variable changes in () don't stay inside the ().
Up arrow scrolls back through history. With the enormous caveat that it doesn't show you the most recent one, which is usually the correct one; the list is physically split into head and tail by two different keys and two different UIs, so you can't just use it like a list, you have to remember what the top is so you can choose whether to read the ghost entry or to up-arrow and read that. If you know what the most recent one is, you shouldn't have to read anything to check, you should just be able to press the right sequence of buttons that does what you want to do. (I can never be certain that the ghost entry is actually the most recent one, because I've always thought it was frecency-based, probably because that's what similar-looking search tools (Google) have taught me. That's mostly my fault, but it's not something the UI was actually capable of teaching properly because without having to press up-arrow to see it, it is not linked to any particular list ordering; it is conceptually distinct and users are within reason not to see it as part of that list at all.)
Up-arrow works differently depending on whether you have entered text in the line or not; no text and it show you the most recent, add text and it won't. And perhaps worst of all, up-arrow actually does show the most recently typed command, but only if the matching sequence of characters was not at the start of the line. Actually that's inaccurate -- if a command matches in the middle, but also as a prefix, you can't just remember that it matched in the middle and blindly press up-arrow. That's ghost-only.
So there are in fact three different lists that up-arrow could be scrolling you through. Actual history (includes most recent); filtered history where last command did not have search term as a prefix (includes most recent); and filtered history where last command had search term as a prefix (does not include most recent). This is no longer a job for muscle memory. It's an active thinking exercise. So you have to remember the history stack yourself, including where in each line your search text will match, so you can stop and pause to think whether to press up or right at any given moment. I cannot think of another search UI that requires knowing where in a string your search term will appear, just for basic use.
Ultimately, dozens of times a day, I stop to think about which button to press, and am reminded of this spectacularly poor UI, for which apparently nobody was able to express these sentiments in the four years that the GitHub issue was open. I don't believe the behaviour can be configured.
I struggle to imagine making use of it however. My normal flow just doesn't seem to need that power. I think I would benefit most from simplicity. Although, I could definitely see this benefiting from things being predictable, guessable, etc. Ie, when I rarely need more advanced features I'm less likely to need to look up documentation to figure out how to do something - as I often do.
The wonderful community made plugins that add these features to zsh (which IS compatible with bash), and it it's really great. My understanding is that there are still a couple fish features not implemented for zsh yet, but if you care about such things as bash compatibility then I'd suggest you give it a try instead.
Because of that on every computer I have to work with for some time one of the first things is installing ZSH (and prezto).
I'd love to know which ones! I was a bash user for 10 years, ZSH defaults put me off and it wasn't till I ran oh-my-zsh that I really learnt what I was missing, the following make me feel like a 10x-er ;) :
- zsh-autosuggetions - zsh-syntax-highlighting - colored-man-pages
Edit: And the `zstyle ':completion:*' menu select` autocomplete
https://github.com/oh-my-fish/oh-my-fish/blob/master/docs/Th...
I noticed fish has:
* extensive syntax highlighting
* "global" variables shared by all instances of fish, persisting past reboots.
what are other important features?
That's not true. There are a few other shells out there that do. The issue is the popular shells tend to be the ones that go for POSIX (or Bash) compatibility and those that do go for a syntax redesign (for example) often get criticised for not being POSIX compatible. There is comment further down in this discussion describing those syntax differences as "bugs" rather than "features"; which just goes to demonstrate how ingrained Bash et al are to Linux/UNIX command line users.
Personally I see Fish and other non-POSIX shells like another programming language (arguably that's literally what they are). So switching from Bash to Fish - or whatever else - should be like switching from C++ to C#, Java, Rust, whatever. Sure there will be a lot of commonalities but it is the differences what makes the shift worthwhile.
That all said, I can't blame people for preferring a POSIX or Bash compatible shell because that's what you'd expect to find on any Linux or UNIX system. Or at the very least a Bourne Shell (sh). Plus most documentation online will be tailored for compliant shells. However it does become a self-fulling prophecy where compliant shells are more widely used because they're already more widely used. I'm fine with this though. People who want to make the shift and learn something new can still do so under the knowledge that they're breaking from the norms and all the potential complications that might bring; and people who just want something that's universal and works - irrespective of it's warts - can continue to do so.
I don't understand why your being standoffish over a technicality.
I’m just pointing out that this has literally zero whatsoever to do with the shell. You posted it as a comment in an article involving a choice of shells.
How am I being standoffish?
Coincidentally, this is what I'm working on with my shell.
The standard byte streams are just 3 file descriptors and on Linux are generally symlinks inside /proc but all that is handled by the pipe syscall (as you stated). However there is still a lot of code between the shell parsing your entered command line and pipe() being called and how the shell decides to implement fork() and pipe() is largely down to the shell designers. Going back to my earlier point about POSIX shells, there is a general expectation that these kinds of shells should just fork() and pipe(); which makes sense when you think about their heritage but it does allow developers to get creative if you're intending to break POSIX.
For example they could check the receiver processes for a signature (magic byte or something) to see if it's a supporting tool and if it is, the shell could then "man in the middle" the pipe; where it sets itself as the destination pipe for the first process and the source for the second process (eg `ls | grep foo` would be called as `ls | shell | grep`). That way the shell could then wrap STDOUT from `ls` up inside a more complex object and pass that to `grep`...and only do all this if `grep` already appears to support this new shell's object system.
Other ideas is that type information could be passed via a fourth file descriptor, UNIX socket or over a localhost TCP/IP listener. Or maybe you don't support smart processes and instead write your shell to do some of the heavy lifting instead via shell builtins (like how Bash has a few builtin functions) where you could write smarter data wrangling tools so it doesn't matter what crap `ls` or `grep` throw at you because you can pipeline that into a shell builtin.
This last approach of smarter builtins is the direction I took with my own hobby shell but I'm now looking for ways to pass that data type information along to other processes without breaking non-supporting processes.
I'm half asleep at the moment so probably haven't don't a good job explaining my thought process but there are a few of use playing around writing "alternative shells" (for want a better description).
It could be if it captured stdout of processes it launches.
Of course, the program would have to output a structured format that the shell recognized to provide the shell the option to do what is described upthread, so legacy programs wouldn't fit in well with it unless the shell was programmed with how to extract structured data from their unstructured output.
eg it could describe the data as a JSON array and the next command would grep through the elements rather than lines.
But I think it has a bit of a learning curve because not thinking in string outputs is quite different.
A lot of things are even defined as ordinary fish functions. In sh, aliases are a dark and evil feature that hooks into the parser and can be used to create rudimentary macros. They have some really surprising behavior. But in fish, `alias` is a shell function and you can get the complete source code on your screen by running `type alias`. It doesn't do any evil things because it can only do things you could do yourself.
Fish has sensible variables and arrays. All variables can be arrays. When unquoted, variables expand like "$@" in sh, so packing multiple arguments inside a variable is trivial and there's no need to worry about whitespace. Command output splits on newlines, which means that things like `for file in (find . -iname 'foo')` just work, assuming you don't have newlines in your filenames.
Writing one-liners in fish makes me much less anxious then doing so in sh.
Though I'll say up front, again as a casual user, I'm not sure exactly how fish accomplishes making me more productive than bash. I'm also don't know if I ought to switch to something like zsh. I often read folks saying great things about zsh but it seems more like something aimed at "power users" and that ain't me.
I've considered switching from bash to fish (something I never did with zsh). The main reason I didn't is Stockholm syndrome, or that I'm too used to bash by now.
I think you can get zsh to do most of what fish does out of the box. If bash is Ed, it feels zsh is emacs and fish is (neo)vim.
Zsh is huge and I always get a bit of a panic attack when someone has given me a ssh login with zsh as the default shell. And an irrational urge to maul a unicorn.
With fish, it feels more like a friend went and tidied up your apartment just to be nice.
I guess I'm so used to bash, that the limited support that comes from completions is enough - and I end up writing a bit of documentation and automation, and work on "foreign" (other people's) servers - and it helps me to work in a posix shell for that reason - with fewer surprises.
You might even find that fish does out of the box something bash (now) can too - just isn't enabled by default or in typical distribution's configs.
Ymmv - it's worth testing imnho. And more interesting than zsh, which just feels like someone was bored in it class in high school and added colors and tinkered with the prompt, and tried à million different ideas - but never really liked working in shell.
I would have thought fish=emacs and zsh=vim in this analogy, since fish isn't really compatible with bash but zsh is?
$ wc -l ./.profile ./.vim/vimrc
249 ./.profile
173 ./.vim/vimrc
422 total
...but I probably just forgot that I'm an outlier:)For a similar reason, command substitution only splits on newlines. Unfortunately, some commands like pkg-config assume that the shell splits on regular spaces so you will need to use workarounds like (pkg-config | string split "")
But with decades of bash experience, I struggle with making even the slightest scripting in fish's own language for whenever I want to make a smart little addition to my environment.
I know some folks say that vim-style editing is overkill for a shell where you're often just submitting one-liners, but it saves so much time for me to be able to just jump right into the middle of a previous command and change one word without holding down arrow keys to get there.
Granted, it's been awhile since I looked into Fish's vim mode, so maybe it's improved. Last time I checked, it sounded like it just wasn't a priority, since Fish's selling point is the intelligent autocomplete and such.
ex: `$ echo "hello"` > hello `$ ^hello^goodbye` > echo "goodbye" > goodbye
This could be a nice project; lets call it "shark".
They have considered a compatibility layer in the past:
https://github.com/fish-shell/fish-shell/wiki/POSIX-compatib...
The only trouble is, such snippets have a way of sneaking into documentation, ci pipelines and other places.
And then non-posix isn't quite as nice anymore. Even if csh or fish might be the nicer language.
I do think the oil shell project is on the right track, by trying to "fix" shell (and fish is a great source of inspiration for the interactive part).
Still, when plan9 didn't manage to take over, I guess I'm a bit sceptical about any new shell having much success...
The "expect it to work, didn't" is more on the user's side, going from e.g. bash to fish.
:set shell=/bin/bashAlso fish utils like `string join` etc. are super helpful when writing small scripts.
Shameless plug: https://github.com/cideM/fish-yvm yarn version manager written in fish
Thought they were being ironic with the 90s / Netscape / glorious VGA comments but maybe these really haven't been updated in an age. They've got screenshots not updated since 2006 (based on the release date in GitHub for release 1.21, given version 1.21 is show in one of the screenshots! You can also tell they're older from the chrome on the Mac terminal title bars)
It looks like the project didn't start calling itself a shell for the 90s until 2013. At least on the project's home page. Compare
* https://web.archive.org/web/20130420050628/http://fishshell....
* https://web.archive.org/web/20130521005841/http://fishshell....