Hey all, one of the fish devs here. It's awesome to see all of the comments and happy users.
We are in the process of scoping a major release (fish 3.0) that can include major syntactic changes. If there's an aspect of fish you would like to see changed, now is a great time! Of course we'll read the comments here, and our issues page [1] is where discussion happens.
We're also welcoming new contributors. It's easy to get started writing completions or with the issues labelled "easy-pick". The core code base is reasonably modern C++ too.
I implore you to NOT use JSON or ProtocolBuffers, neither are appropriate formats for configuring my shell, or storing long sets of textual data. Protocol Buffers is hardly the kind of format I want to parse and read my history in, and JSON is a less than ideal configuration format for many reasons.
https://github.com/vstakhov/libucl UCL (Universal Configuration Language) is a much more appropriate format for configuring programs than JSON, and is has been accepted as standard for use configuring all tools included in the FreeBSD operating system.
I also suggest you consider using a different language to store shell history, since shell history and shell configuration are two very different jobs with different goals and trade offs. I personally would suggest a simple safe format like TOML https://github.com/toml-lang/toml for storing the history.
But If you do want a single format for both configuration and history, I would implore you to pick TOML not JSON or Protocol Buffers.
Supporting this, I don't think protobuf is a good format for storing history files. Backward compatibility is tricky with it - I don't think the history format is going to change all that much, but I think there were changes in history of fish shell like adding time field. If the choice would be on a binary format, I would much, much, much more prefer SQLite for that. Also, B-trees are perfectly fine choice for searching history, as they make prefix searches trivial.
TOML is definitely an interesting choice if a text format is deemed necessary however. Array of tables syntax should be a fine syntax choice for storing history.
I was about to say SQLite, it seems perfect - binary, fast, easy to update cheaply in place, immune to escaping et al problems (if you use prepared statements, not glue SQL with + of course), reliable, available in most languages (even for C and C++ the integration is trivial - it's a single pair of files drop in) and on the CLI, stable, the history data is very row/item oriented and not totally heterogeneous or free form, etc.
I totally drank the SQLite koolaid a long time ago.
History file may be read & updated simultaneously my multiple processes. Is that sufficiently safe from corruption with SQLite?
(honest question, no FUD implied. same risks apply to alternatives too.)
In addition protobuf is designed for communications, not incremental updates in a local store. As such making things robust to store things on a development machine is non-trivial. SQLite is so much better for that. After Firefox switched to use it for its own history, most problems with history corruption disappeared.
Out of the mainstream formats, JSON is among the easiest to parse - thanks to the CLI tool jq. Does UCL have something equivalent?
Protobuf (or any other binary format) has the benefit of being faster to load, but I agree - it should not be be used to store things like history. It should be easy to parse history without having to write code. And with Protobuf, you need the schema.
If a binary format is going to be used, it should be optional - or perhaps there should be tools to convert the history file to/from a plaintext format.
There is uclcmd [https://github.com/allanjude/uclcmd] which could do with some more work but was created with the intent of being a UCL equivalent of JQ.
Thanks for writing that up, I linked to it from the issue. FWIW I agree with you that shell history should be a simple format, and even ad-hoc parseable via Unix tools. zsh uses simple : and ; delimiters. JSON is more complex, and binary formats like protobuf are way out.
Long-time fish user here, I'll second this comment and implore that you choose TOML for the configuration format. TOML format is easy for users to understand, and well-written parsers for it exist in every programming language.
For configuration I would very much prefer to have something that can be properly grepped/patched/generated with shell scripts if necessary. What openssh uses for its config mostly fulfill this, but ini file also are not that bad. Anything hierarchical like JSON/TOML/UCL etc. becomes very unattractive the moment one has to patch them from automated setup scripts.
Both are single binaries, so easy to run them where you need it. I don't know comparable stuff for the other mentioned formats, whenever I need to deal with yaml in scripts i run
I would be totally fine with any format that can be converted to JSON on the fly. Of course I would love to have something like these tools more integrated within a shell, but the representing text format on the disk is not that important for me.
pgcli was a huge help to some former colleagues who had some trouble working with relational databases and SQL for the first time. I'm a big fan myself as well. Thank you for building a great piece of software.
Copy and pasted from another reply: "I still wish fish support && and ||, if only for the times when I copy and paste some one-liner off of stack overflow and have to rewrite it."
That and support for
SOME_ENV_VAR=foo ./bar
(not having to prepend "env ") are what's stopping me from recommending fish to others.
I really like that you have to use `env` in fish, since it's cross-shell - it works in bash/zsh/dash/whatever. The `A=b foo` syntax is an unnecessary appendix in the syntax that complicates matters while only saving 4 characters.
It's not just to save typing - having an `A=b foo` form built-in instead of relying on an external program means `foo` can be an alias or shell function.
I agree and think the best fix would be if the syntax would be forbidden in bash/zsh. Problem is: Millions of code snippets on the Internet not using env.
That syntax is from very early days of sh itself (predecessor of bash), IIRC. So removing it would break many scripts, as sibling comment by jhasse said.
While I like fish, I stopped using it because of a small convenience feature ZSH has.
With ZSH, I can run a command with a space at the start so it's excluded from history, even though its not saved to disk, the last command is still stored in memory so I can press Up to access it again.
This is handy when a mistake is made in the command means I need to run it again with some small change.
Heh I have the opposite preference, I use space to ensure when pressing up it will not bring up that command, to not mistakingly run it when muscle memory will expect another command there (for mv and rm commands mostly)
This feature seems to exist also in bash. I discovered it accidentally while wondering why my history did not include my last commands (copy/pasted with a leading space).
I tried fish and it seemed ok, I didn’t continue with it cause I needed to rewrite all my aliases and functions (work related not at home). From memory one was && vs “and” which we use a lot to chain commands. Something like implementing &&/|| would go a long way, compat command sub, closing if statements . I know it seems like a small thing to modify your aliases/functions but I would basically need to modify mine and be a maintainer for the shared ones.
TLDR adddition transitionally compat with bash or zsh
If there is anything I would personally like to see it’s the bass plugin rolled into the shell itself to make transitions for bash and some esoteric edge cases easier to handle https://github.com/edc/bass
I would love to see zsh navigation tools[0] be integrated in fish. There is a long standing issue in fish which is the support for CTRL-R history, while many are pondering on the UI of it. I would like to see znt's UI be adopted (not saying it's perfect, but quite a good starting point for user conversion).
Avid fish user since last 3 years. On feature I miss from bash is the `sudo !` to re-run previous command as sudo. Last time I checked fish didn't offer an equivalent. Either that or something similar will be useful
In fish Alt+Up does something similar, but repeated presses iterates over all words of all commands rather than last words of bash commands. A big improvement is you can type some chars first and then Alt+Up only gets words matching this substring — like Up but word granularity! (Closest bash key is Ctrl+Alt+I)
If you don't mind the differences, and want Alt+. muscle memory to work in fish too, do:
bind \e. history-token-search-backward
(plus Alt+Up doesn't work for me in linux console, Alt+. does)
Hey, thank you for contributing to one of my favorite pieces of software :) The Fish shell is my primary choice, because it's so intuitive and easy to use. I never encountered a situation where the Fish shell behaved contrary to my expectations. I do wish there was a native Windows version, because that's where I spend 50% of my digital time, but only because it's so great.
Fish's FAQ already explains why it doesn't use `!!` – it says that editing commands from history by pressing the up arrow is more memorable and flexible. I don't find it a problem to type “up Ctrl-A sudo” instead of “sudo !!”.
It would be great if Fish supported &&. I know it has its own syntax for this but it's not particularly fun going through a command you copy pasted from elsewhere and swapping out all the &&s (I usually just end up firing up bash).
Thanks for it! I am also using Fish happily for interactive terminal work. Not so much for scripting as I am lazy to learn the new syntax.
What I don't like is that after hitting Tab twice when doing path completion, the list of possibilities comes out, allowing arrow keys to be used for selection. The problem is that it requires pressing Enter to confirm the suggestion and I fear of executing the command with incomplete path prematurely (it's just one more Enter hit away).
We're open to a lot of things (except "make it fully POSIX-compatible"). We're still trying to not massively break everything, though.
The sort of things we've discussed include:
- Not expanding `{}` so you don't need to quote it with e.g. `find -exec {}` (currently this is read as a zero-element brace expansion, i.e. it expands to no argument)
- Removing the `?` single-character glob because it's apparently entirely unused and is another special character to remember (in fact we've also talked about removing `^` as a shorthand for redirecting stderr and `%something` process expansion)
- Allowing `$(command)` command substitutions, which could be used inside quotes as well (long term, these would replace our current `(command)` style)
- Possibly removing the special handling we have for $PATH, $CDPATH and $MANPATH (these are treated by fish as lists, which is nice in some ways and causes pain in others)
I'm very glad to see that getting rid of the magic path variable semantics is a possibility for 3.0 :)
Other than that, my biggest pain point with fish now is that it doesn't interact well with pkg-config (issue #982) and the workarounds for that are a bit awkward. eval is scary and may require double-quoting the non-pkg-config parameters, and string splitting can wrongly split inside quoted text.
Vi mode has been implemented since 2.2.0 (July 2015), although it's an ongoing work in progress - if there's something missing then we'd consider adding it (although nobody's going to reimplement Vim in fish - sometimes Alt-E is your best option).
the main feature i use fish for is the syntax expansion, and history usage of it.
The biggest gripe i have with it is the specific syntax. If fish would act more like a bash shell in case of syntax. ( i know i would need a totally different shell). But it could replace the fish for me in an instant. everywhere.
Anyways.
Thanks for the fish.
I used fish twice for about a year each time, but I keep switching back to zsh, because:
* The main things I like about fish are predictive history completion and syntax highlighting, both of which work about the same with a pair of zsh plugins;
* The syntax occupies what is, for me, an awkward middle ground: it's a bit better than POSIX syntax if POSIX shells didn't exist, but not enough better that I care to juggle the two syntaxes;
* I don't like that fish tries to be "helpful" in certain cases such as lying to you about the delimeter actually used by $PATH.
I have a couple of specific gripes about the syntax, which aren't really inherent issues so much as unimplemented features.
I think if I was going to deviate from a POSIX shell, the alternative would have to be more better than fish to be worth it.
I started with bash, moved on to zsh and finally settled on fish. Besides fish being super user-friendly out of the box, I couldn’t find a zsh plugin that emulated its history search abilities.
There are two history search features in fish that I really like: One is searching for a half typed command as above, but the other one that I haven’t found elsewhere is completing words from other commands. For example, I can type ‘touch something’ and later on do ‘cat some’ and then press option+up and fish will complete it to ‘something’.
After using ZSH I have that first feature and love it. I try to keep as much of my history as possible and it's amazing how much time you can save that way. Does that second feature not clutter up that history though?
> * The syntax occupies what is, for me, an awkward middle ground: it's a bit better than POSIX syntax if POSIX shells didn't exist, but not enough better that I care to juggle the two syntaxes;
This. It's an awesome shell, but I couldn't set is as a default because my already done shellscripts and aliases would stop working. And I also can't set it on server, because then a deployment tool logs in, and expects bash.
And if it isn't default, I might not bother, I'd forget to run it manually most of the time.
(The worst offender is replacing && with 'and' - why not at least enable both and preserve compatibility?)
Is it possible to configure zsh to have sane variable expansion like fish does? One of my favourite parts of fish is that I don't need to quote every variable I use out of a paranoid fear that they might contain spaces.
There's nothing major. I maintain a set of POSIX and fish scripts as part of my job and, given that I have to know both relatively well, I find I end up preferring the on-average-slightly-more-terse POSIX syntax.
One thing that can be particularly annoying is that it seems to be impossible in fish to evaluate a command in a subshell and embed its output into a string without assigning it to a variable first.
ARGV handling is a little weird too. I understand the impulse to get rid of $1, $2, $3, $*, $@, $#, etc., but it ends up just requiring different gymnastics, like writing `set -e argv[1]` instead of `shift.
> Out of curiosity, what use case do you have that makes a POSIX shell a big deal?
Running on a POSIX system, there are decades' worth of shell snippets out there which don't work with fish, but do with sh, ksh, bash & zsh.
Fish is just gratuitously incompatible. Having fish-users on a team is a pain, because they'll write everything in fish and either not bother producing sh equivalents, or produce insufficiently-tested sh equivalents. It's just a lot of pain and bother, and what's the benefit? Zsh does everything fish does and more, so why not just use it?
Edit: I just wish that the original fish developers had chosen to implement all their cool features and be sh-compatible, or at the very least had exercised some wisdom in where they chose to break compatibility. Instead, it very much feels like a 22-year-old's project: full of ideas, some good & some bad, and needlessly without respect for the past. I've no problem with rejecting the past when the past is broken (and sh is broken in places); my problem is with the equivalent of saying, 'hey, English spelling is terrible, soh Aiv dəseidid tū dəvelup mai ohn.'
Back in the day I used to use csh and tcsh, both of which had famously landmine-laden scripting gotchas. So, I wrote my scripts in sh or bash. Now that I use zsh mostly, same thing, I don't actually write my scripts in zsh--especially for production, I write them in sh or bash. zsh for me is an interactive CLI-only tool. Honestly, I think the problem here sounds more about not standardizing on a common denominator for shared scripts.
Where stuff like fish is a pain for me is with apps that for whatever reason need shell integration (virtualenv, for example). Non-POSIX shells end up being an afterthought there, so you end up with no or buggy support, and end up having to find some other custom variant (virtualfish, etc.) to get good behavior. Sticking with a more mainstream shell tends to be safer there, and zsh barely makes it over that line.
Shameless plug: Elvish is another non-POSIX shell aiming at interactive friendliness and saner scripting: https://elvish.io/
Some highlights:
* It comes with helpful interactive features, like syntax highlighting and on-the-fly error checking; enhanced history searching with ^R; directory history and a Ranger-inspired "navigation mode" (see homepage for demos).
* It supports some advanced (in shell standards) programming concepts, like lambdas, namespaces, nestable maps. It also has some pretty powerful API for interactive features. These two aspects work hand in hand and offers quite some customization possibilities. In fact, one user implemented interactive history expansion (!! !$ !1) himself: http://zzamboni.org/post/bang-bang---shell-shortcuts-in-elvi... his configuration file is also worth readng: http://zzamboni.org/post/my-elvish-configuration-with-commen....
* A lightweight builtin package manager is in the work.
* It is written in Go and comes as a statically linked binary.
* A native Windows port is under way, in case you care :)
Not GP, but since 90% of of my sporadic scripting is "searching on SO how to do something somewhat complicated that I'll never do again so it's not worth the time to learn how to master it", bash is (oddly enough) a lot easier to use here since looking up how to do it in Fish is a lot more hassle.
Similarly, if you want your code to be portable, bash is a safer bet.
I put that badly. Fish certainly does support scripting, but as a relatively niche piece of software you get bad portability (everything has bash) and poor maintainability (because everyone else scripts in bash). Fish is a great shell and maybe this will change, but at the present time I'd be doing my clients a disservice if I wrote them tools in a language few others could work with.
Correction: Most bash scripts are brittle. You can write rock-solid bash scripts if you know what you're doing. For example, Arch Linux is an entire distribution built mostly on bash scripts.
Of course, if your scripts only run on your own machine (which is a huge if), then fish is probably better.
Sure you probably can write non-brittle bash script, but it has always seemed above my own ability.
Beyond bash ubiquity, I've never found to have any other value against other slightly higher language whether it is perl, tcl, python, etc ...
I wouldn't use it because I wouldn't want to add a somewhat strange and unnecessary dependency to my projects. It's also why I resist switching from bash even though I've used other shells and enjoyed them. There are only so many skills I can keep in good practice. If I use bash then it will be one of them.
I find fish to be a more pleasant scripting languge personally, but bash scripts are the lingua franca everywhere I've worked. It's easier just to learn bash.
Whenever I'm reading about some alternative shell and thinking about switching, I'm afraid of losing my proficiency in bash. For better or worse, it's the de facto standard in scripting, so I see it as an important skill. How does this work for those of you who risked and switched? Don't you feel some kind of schizophrenia, or accidental cross-polination typos/mistakes? How does it work when you login to some remote machine, do you have the alt. shell installed everywhere?
I started by switching on one of my machines, then installing it on my main user machines, and then I ended up as a fish committer. I still use bash and zsh every few days and I don't think I've lost any of my skills in that, though they've grown slower. As long as my prompts are recognisably different it's rare for me to make a mistake.
I have the same problem. I mainly use zsh because it's not drastically different from bash but still offers some useful things that bash lacks. But, honestly, we should just bite the bullet and move on to something better. Yes, we will still need to write scripts in bash from time to time and maybe we'll need to look up a few points that we've forgotten but we won't forget the fundamentals and that's all you really need. Well, that and a web search.
If nothing else, I have thousands of lines of my own shell scripts that I don't care to move to a different shell syntax that's not obviously better :)
I'm designing a new shell language which bash can be auto-converted to. This is a lot of work and the plans might change, but the beginnings of it are here:
I switched to zsh 3-4 years ago. I use it only on my local macs ( work & home ).
I will never install it on any remote system, because it doesn't feel right to force a shell to other remote users.
Also how much time do you need something that fancy on a remote prompt? The nice features of bash like [Ctrl-r] works everywhere and the shortcuts ( Ctrl-a, etc. ) are usually the same.
The power that zsh gives me is all about my local dev machine. Things like utilities command completion or `scp remote-server:~/ [tab]` to find a file on a remote machine, or the countless other extras are mostly useful on my local.
I have my dofiles script on github that I run on remote machines I frequently connect to and it installs zsh with my .zshrc, .bashrc in case I switch to bash and all the other dotfiles I got accustomed to. It has been definitely worth the extra trouble. Of course I still use bash for scripting and zsh is not really in the way.
I love fish shell, I love the autocomplete, but I've been forced to switch back to bash lately, because fish syntax is just different enough from bash-isms to break too much scripts / tools / commands.
I know I could just invoke bash, but prefixing commands with "bash -c '" is tiring and papercuts are why I switched to fish in the first place. I wish bash had a sane auto-complete prediction like fish.
There's some initial pain in retrofitting your Bash startup to work under fish, but after that it's worth it. For example I had to search for how to use ssh-agent with fish, and now it works great: https://github.com/st3fan/dotfiles/blob/master/fish/ssh.fish
You need to learn a few idioms like: replace $[1+1] with (math "1+1"); replace
> for f in $(ls); do echo $f; done
with
> for f in (ls); echo $f; end
I should start a Rosetta Stone of Bashisms to Fishisms - I'd be interested if anyone has got Android Open Source build environment / lunch working.
Your scripts should begin with #!/bin/bash or similar so you can execute them from anywhere. Are there bash built-in commands or functions that you need while in fish?
If nothing else, I have thousands of lines of my own shell scripts that I don't care to move to a different shell syntax that's not obviously better :)
There are lots of posts on the blog about it, but here is an example:
However one thing is that it's not yet a good interactive shell. It's mainly treating bash as a programming language. However I think that is a good foundation for an interactive shell. Some details here:
You can get it much of the way there by tweaking `~/.inputrc`
"\e[A": history-search-backward # Up key
"\e[B": history-search-forward # Down key.
Allows you to get press up while you have `ssh 10.2` in the terminal to cycle through ips matching, etc. It won't display like in fish before pressing it, but I find that's a reasonable tradeoff.
bash uses readline to handle user input and in readline the completion function is a parameter. Could a more clever completion function be substituted to get the same behaviour with bash?
Fish is really great for using it in your terminal. Autocompletion, fuzzy matching, and so on, are amazing.
Unfortunately, although it is fully scriptable, writing scripts in Fish feels a little clunky at times. For example, I wanted to test if $dest exists, and if not, whether $src is newer than $dest. Since there are no && or ||, parentheses are used for command substitution, and the Fish version of "test" has no -nt to check if a file is newer, I have to do this:
if begin; not command test -f $dest; end; or begin; command test $src -nt $dest; end
# do something
end
It's true fish is generally more verbose, as it has less magical syntax. fish is also missing some niceties like `set -e` and `set -x` which we would like to add, but the main focus is interactive use.
Happily the begin/ends in ifs are no longer necessary:
if not command test -f $dest
or command test $src -nt $dest
# stuff
end
In this particular case, you can simplify it further with test's operators:
if command [ ! -f $dest -o $src -nt $dest ]
#stuff
end
which is comparable in length to bash, though other cases will certainly be longer.
I'm a very happy fish user but this is one of my pain points as well. If you want to define a function, the syntax is light-years ahead of bash, including named arguments (and closures!), but it took a fair bit of googling and eyebrow-wrinkling before I could figure out the way just to set a default argument for that function.
What I ended up with was (for a shortcut for generating a password on the command line):
function pw --argument length
test -z $length; and set length 16
python3.6 -c "import secrets; print(secrets.token_urlsafe($length))"
end
I think you should actually use "; and" in place of &&. That said I still wish fish support && and ||, if only for the times when I copy and paste some one-liner off of stack overflow and have to rewrite it.
I use fish as my primary shell. I've ran into a few issues where it broke existing fish scripts, and, uh, let's just say some of the developers (not 'ridiculous_fish) were less than stellar in their response. (I get it. It's open source. You don't owe anyone anything: but you also don't have to be a jerk about it, and I also don't owe you using your software.)
My original reason for using fish was onboarding junior engineers. I had a pretty fancy zsh/emacs setup, and they'd ask me how to make their shell do that (reminder: on macOS you get bash3.2 by default!). So I switched to fish/spacemacs, so the answer isn't "uh sure you can rsync 50MB of accrued elisp".
Still easy to reproduce. Maybe consider some of those plugins. You don't have to give up being POSIXy. Whether or not that's good or bad, I leave up to you :)
(Commented out bits are things I'm playing with: mostly to improve shell startup time.)
It's a Python-based shell that attempts to be somewhat bash-compatible (for ease of use over, e.g., IPython). Instead of making a new scripting language (fish), go all in.
Pros: scripting is amazing.
( while True: ls ~ )
Cons: can be a bit slow (because Python interpreter).
It is also worth noting that the ecosystem around fish is quite developed, making it easy to get easy integration and completions for most well-known tools.
oh-my-fish [1] plugins is a good place to see (part of) what is available
I'm happy w/ zsh but have played a bit w/ xonsh (a POSIX-compliant shell w/ deep python integration), because my cousin is a core contributor. Curious if others here have tried xonsh and what your experiences have been.
I use xonsh on my Windows machine at work (too lazy to learn Power Shell). Very happy with it, and a quick way to get a bash type shell on Windows. Not the most stable beast (e.g. yesterday I typed "pwd" and it crashed and returned me to the Windows prompt).
I also use it on my home computer (on top of zsh) and am pretty happy with it.
It is a bit slower in terms of response time, but that's OK. Most of the problems I had with it have been resolved after filing bug reports. The only annoyance is that when I quit Midnight Commander, I'm back in the directory I started with. But that's a MC problem, and not xonsh. Every shell out there has a special wrapper script to handle MC. I just need to understand the one zsh uses and port it over to xonsh.
The two best parts about xonsh:
1. You can use the command line like you would a Python interpreter. Need to do a quick calculation? Just type it in and press Enter.
2. No more obnoxious bash/zsh scripting. Write all your shell scripts in Python!
I've been quiet happy with https://github.com/junegunn/fzf/wiki/Examples-(fish) as a ctrl-r replacement for fish. I would love this included natively in fish though so I won't have to manage remote shell configurations.
The great thing about fish for me is that comes so nicely set up on first install that, a few path additions aside, I don’t have to mess with it. Any time spent on shell configuration is time wasted from my perspective.
This in turn means I’m willing to install it with no hesitation in all my local and remote logins, so I have a uniform simple setup everywhere.
I've used fish as my shell for over five years. Thanks to the developers!
One issue is the behavior of globs. I often want to do "scp host:directory/* ." but you can't do that in fish, so I drop to bash. That's pretty much all I drop to bash for.
Note that the reason bash works here is actually a bit ugly.
Like fish, it'll interpret an unquoted asterisk (sorry HN formatting) as the glob character. So it tries to match pathnames to `host:directory/`.
Only the default bash behavior (if "nullglob" and "failglob" aren't set) is to pass the literal glob expression if no match could be found.
So once you `mkdir host:directory; touch host:directory/file` (which you can do - this is unix, so almost all pathnames are allowed), this will be broken.
This means you _should quote the token_ in bash, which is exactly what you should do in fish.
Note: This is also why you might see code like the following in bash:
I think what convinced me was the last point: if you really can't do what you're trying to do in Fish, firing up sh/csh/ksh/bash/python/xonsh costs virtually no effort.
> if you really can't do what you're trying to do in Fish, firing up sh/csh/ksh/bash/python/xonsh costs virtually no effort.
But of course having to recall how to do something in a POSIX-compatible shell can cost if you've been using a POSIX-incompatible shell for years. Memory and experience do fade over time.
I’ve been enjoying fish for the handy tab complete of command line options, the interactive history, and it’s pretty.
I’m certainly guilty of finding one-liners online which frequently fail in fish, which puts me in the position of either actually learning what the terse statement actually does and re-implementing it in the fish “c-like” syntax, or I just drop into bash then get on with my business.
Really happy with it, but I know I get sideways stares from graybeards and gurus who consider it the small-batch, fixed-gear, “Crocs” of shells.
I've been using fish for a few years now, and it has made bash feel not just outdated, but completely obsolete. I am at loss for why it hasn't taken the entire world by storm.
I use fish since the first time I tried it some years ago because it upgrades your user experience.
I don't understand what the fuss with not being compatible with bash is. Bash scripts run with #!/bin/bash in bash. If you need to write/copy&paste some bash code just jump to a bash shell. In the meantime, fish will save you lots of time on your daily regular shell usage.
Love fish, especially because of the easy configuration and out of the box features. No need for complicated frameworks or curated dotfiles. There are two syntax changes I’d love to see:
1. Support for last command by !!, as in `sudo !!`.
2. Ability to search history from a partial command like `git checkout`, where up arrow would step backward from the present.
That's true. Sorry for my poorly-worded English. For a small example:
$ ls -la foo
$ ls -la bar
$ ls -la /
When I type `ls -l` and hit the up arrow, my first result is `ls -la bar` not `ls -la /`. This is a small problem but sometimes annoying, especially after using other shells that work differently.
In this case, what most likely happens is that the first result is offered as the suggestion - i.e. the greyed-out part in the commandline. To accept that, press right-arrow (with the default bindings, of course).
If you like fish but miss the plugin ecosystem of zsh you might be interested in the fish-shell plugin manager, fisherman. I've really been enjoying fish with z and fzf.
Thanks for the awesome fish shell – my beloved default.
For improvements here are two things I wish where possible in fish:
* The ability via a flag to say that a fish-function should not interpret passed function-arguments. This would enable us to pass e.g. URLs to a function without quote them, which is somewhat anointing right now. So this change would be a nice usability improvement.
* I would like to be able to write dynamic completions, containing of a key-value pair. The key should be displayed and if the user selects a completion-item, the corresponding value should be passed to a fish-function from which arbitrary actions could be triggered. Maybe supporting JSON input here would be nice too.
>* The ability via a flag to say that a fish-function should not interpret passed function-arguments.
Note that functions already don't expand the passed arguments. Fish expands them _before_ executing the function, so what you are asking for is a major layering violation.
E.g. you can do this:
function a
b $argv
end
function b
string escape -- $argv
end
a 'something * with ? loads {} of $pecial char"acters'
and the output will come out right. You only need to quote it once.
>This would enable us to pass e.g. URLs to a function without quote them
I'm assuming what you are asking for isn't _passing_ URLs to functions, but rather _pasting_ URLs into the commandline.
In which case fish has a feature I like to call "magic paste". When you paste with an open single quote (`somecommand '`), it'll escape single quotes (and backslashes). So you type the closing single quote and your argument will be passed to the command you are calling as the exact text you pasted.
>The key should be displayed and if the user selects a completion-item, the corresponding value should be passed to a fish-function from which arbitrary actions could be triggered.
We have "descriptions" for completions, which will be displayed _alongside_ the argument (i.e. the "value"). To generate them dynamically, simply separate them with a tab character (`\t`) from the argument, and separate these pairs with newlines.
We use this to great effect in numerous places. E.g. the git completions will offer commit hashes with the summary line as description, so when I type `git revert <TAB>` I get something like
0a129475 (Replace opts.stdout with opts.to_stdout)
I'm not sure I like the idea of hiding the real argument from the user.
>Maybe supporting JSON input here would be nice too.
The best completions are those that actually call the stuff they are completing (because that makes them really reactive), and not many commandline tools actually generate JSON. Anything in particular you're thinking about here?
(And now I'm hoping that HN doesn't hopelessly mangle this comment)
I wrote a little utility [1] to quicker navigate on the file system. Right now I have two commands:
m [folder] // goto highest ranked folder
mm [folder] // list results for folder-keyword
I would like to be able to write 'm foobar' and then press tab to get a vertical completion-list. When the user selects a completion-list-item I would like to pass the result-path to the cd command.
Some time ago I tried to write such a completion, but failed – that's why I still use a separate mm-function to list search results.
I think JSON might be a good choice here because it would simplify the interaction with the completion program for advanced completions. Passing all those flags – mixed with some other shell function calls – to the 'complete' program is a bit cumbersome. My dream would be to have something like 'complete -c maybe --json [maybe-flag-to-generate-json-output]' and handle everything inside the application.
{
"fish_completion_version": 1,
"header": "optional, completion header",
"orientation": "vertical",
"on_single_result": "optional, choose-item or display-item",
"arguments": [
{
"item",
"description",
"optional return value, if empty return item"
}],
"item_handler": "optional, name of fish function to call on-item-chosen"
}
I know JSON is not something you want to assemble in a script, but all programming languages have support for it and it's easy to use.
Like I said, that's a rather large layering violation, since the function has nothing to do with the expansions happening on its arguments. They are expanded before they ever reach the function. It's essentially allowing functions to modify the syntax around them.
How exactly would this treat e.g.
yt $URL/somefile
Would the variable still be expanded? Would an asterisk glob be? If I _did_ want it to expand something even though the function is declared "pure", how would that work?
Now I couldn't be sure how my arguments would be interpreted, or I'd have to go checking for everything I invoke.
I use youtube-dl myself quite often, and what I do is just type
youtube-dl '
then press ctrl-v (which is a keybinding that uses xsel or pbpaste to get the clipboard contents and insert them into the commandline) or ctrl-shift-v (which is my terminal's paste binding). Then I press `'` again and can download the video.
Additionally, it's looking like 3.0 will remove the `?` glob, which is the thing that is most annoying with URLs (though "&" is also a thing).
> I would like to be able to write 'm foobar' and then press tab to get a vertical completion-list. When the user selects a completion-list-item I would like to pass the result-path to the cd command.
I would assume the reason you failed is that the argument you want doesn't match the argument the user typed. Because fish's completions undergo filtering (with some fuzzy-matching, so e.g. `f_c_i` matches `fish_config_interactive`). Otherwise every completion script would have to implement that by itself, and consistently to not confuse people.
For completions, that's the right thing to do.
What you want, I'd argue, isn's a completion. What you want is a selection menu. Which could be implemented with fish's completion pager (we have an open issue about making it accessible to the outside), but isn't the same thing.
JSON here is a red herring, since you don't just want to add items (with descriptions), but also control the behavior of the pager ("orientation" and "on_single_result"). That you could do just with arguments to this `select` command (`list_of_items | select --orientation=vertical --on-single=choose`).
> Would the variable still be expanded? Would an asterisk glob be?
No. Pure should mean don't do anything from here on, just pass the arguments to the function.
> If I _did_ want it to expand something even though the function is declared "pure", how would that work?
If expanding should be possible in a pure context, then maybe by using a known syntax like:
yt ($URL)/somefile
Eshell expands Lisp code when using (lisp-code-here) which is kind of elegant. So when in a pure context, you would have to switch to expansion-mode by using curly braces.
I like fish enough that I went and added fish support to ROS when I was doing ROS development. I still leave bash as my system shell because scripts. But all my terminals are set to start with fish instead.
I've been using fish on my laptop for some time now, it is an interesting project and I use it personally for purely aesthetic reasons. However I have a lot of muscle memory with bash-isms which also work in ZSH.
History expansion `!$` for example, is missing.
SDTIN redirects as I expect `<<<` etc; are also missing. And to get ^R to work again I had to install fzf.
Now, I am fairly certain I'm doing it wrong, but I never found a good place to read how to do it the fish way... If anyone has good replacements for the things I've mentioned I'd be quite keen to hear them.
I definitely prefer zsh. I just feel like Fish tries too hard and it's just awkward to switch between fish and bash when frequently switching between different machines.
It's been a while since I've tried it so perhaps someone can comment whether things have changed or if there was something I missed. When I last tried fish, I liked it but I couldn't get past the lack of ctrl-r (backward history search), which I rely on extensively. I found having to reach over to the up/down arrows too clumsy in comparison. An oh-my-zsh plugin also provides fuzzy searching (history-search-multi-word).
I have fish installed because for some odd reason, the "SSH link" feature of Midnight Commander didn't work across two servers that we use. After installing it I could use the "Shell Link" feature and it was lovely to be able to exchange files between servers using a 'graphical' terminal. Specially useful with some of our devs which aren't too command line happy.
This is amazing. IMHO Ubuntu, Elementary, OSX and other OSes that are trying to be practical, easy and pleasurable to use out of the box should offer this by default, together with tldr.sh.
Loved it a few years ago, stopped using it when I started using conda and it didn’t support switching into those environments. I’ll try again hopefully that’s fixed.
I tried oh-my-zsh and it was too slow for me for some reason. Returning from a command took a second. Maybe I had some buggy plugin enabled, I don't know.
Fish is almost zero configuration and has many useful functions built-in and they are quite fast. Unfortunatelly it doesn't use bash-style syntax like zsh does.
No, not to my knowledge! It does autoindent things for you when you’re editing multiline functions inline, but whitespace is fortunately not significant.
I've been using fish for 3 ~ 4 years and I love it. It's come a long was in its development and it's interesting to watch as so many of the bugs have been resolved. Today's fish is incredibly stable and solid. The history, highlighting and completion are well beyond what I've seen in other shells (at least not without adding additional plugins).
I still write scripts in bash for compatibility (when I have to; I try to use Python whenever it's an option), but for my interactive shell, fish is really amazing and I'd hate to go back to anything else.
Of course I think my own project, Oil, could be a "21st century shell", or I wouldn't be working on it :) It's designed in a principled way, and it's also the only one that's compatible with bash.
The web based configuration is completely optional. Editing dotfiles works just as well. I have been using fish for quite a while but never use the web interface (I didn't even remember it existed)
That is the one thing I really didn't like about Fish; that and how the help screens use to launch in a web browser. But once you get past the initial configuration, you never use that stuff again. Despite that fault, I still love Fish shell.
We are in the process of scoping a major release (fish 3.0) that can include major syntactic changes. If there's an aspect of fish you would like to see changed, now is a great time! Of course we'll read the comments here, and our issues page [1] is where discussion happens.
We're also welcoming new contributors. It's easy to get started writing completions or with the issues labelled "easy-pick". The core code base is reasonably modern C++ too.
http://github.com/fish-shell/fish-shell/issues/