I found that while fish has better syntax than bash for most things, the hassles with incompatibility or unexpected behavior brought me much more trouble than BASH's syntax ever has
I found that while fish has better syntax than bash for most things, the hassles with incompatibility or unexpected behavior brought me much more trouble than BASH's syntax ever has
I haven’t tweaked my shell config in 7 or 8 months now.
This is a different mindset from the giant zsh configs, “plugin managers” and other junk that is wholly irrelevant to using the shell. You’d think that fish incorporating a lot of functionality that zsh has would manifest as bloating fish, but, IMO the reality is that zsh’s “bloat” is pushed into user configuration and the user is tasked with making it work.
As for a replacement for oh-my-zsh itself, I had good experiences with zgen[1] but the fastest I've found is zim-fw[2] which produces acceptable start times for me[3].
[0] https://github.com/romkatv/powerlevel10k/
[1] https://github.com/tarjoilija/zgen
For example, to me, it is _insane_ that in 2021 async prompts are not a completely solved problem. The shell should provide a mechanism to do so easily, rather than duct-taping thin veneers over syscalls via a scripting language.
I've found that sometimes the opposite can be true (in a good way!). At one workplace, I introduced Fish to some fellow developers who until then mostly saw using the command line as a strange, difficult, and unpleasant part of their jobs.
Once I got them started with Fish, they were happy enough with default interactive behaviors, convenient documentation, and simple scripting syntax that it encouraged them to do a little more scripting, and eventually to customize some of the aesthetic stuff by writing custom prompts!
It was pretty cool to see.
This is such an incredibly odd perspective to me. I use zsh and have not touched my shell config in years. Messing with configurations to get things working to your liking is a one time thing. I don't even use plugins.
On the other hand, if fish doesn't work to your liking out of the box, and for many people it does not, there's no "messing with it" that's possible. You are forced to give up and use something else. Your reason to choose fish is only a good reason if you already agree with every minute choice the developers made and refuse to let you adjust.
What do you want to do that isn't possible? I also haven't messed with it in months if not more (fish in my case, not zsh) but years ago I messed with the prompt a lot to get it to my liking. (From a previous zsh config.) It was perfectly possible.
Which part of fish makes this impossible? You can tweak the startup, the completions, the key bindings, the prompt, and so on.
I went through a "distro hopping" phase at some point with Linux and ended up settling on a system with very little custom config. It's close to the defaults so I can work very comfortably even in a random server.
Of course this is not ideal. If you have a tool or set of config that you like, then you should use it. I've just found that the human brain can overcome bad UX quite well with a little effort ;)
The fact that I can write a simple for loop without needing to look up how to do it by far beats the POSIX compatibility, if I need it I can still write a bash script, but when using the shell I don't need to recall where semicolons or `do`, brackets (and how many) go.
for i in $(seq 1 10)
do echo $i
done
Then you can just replace new lines with ; if writing a one liner. for i in $(seq 1 10); do echo $i; done
I guess it isn't as simple as python for i in range(10): print(i)
but it's pretty close aside from the variable binding. for i in {1..10} for i in {1..10}; echo $i
to me is as clear as the python version.
Very compact and useful for one liners.Did the same, but moved on.
Now it is: bash => zsh => fish => nu
I use bash as my default user shell, fish as the default shell of my terminal emulator, and I write scripts for both POSIX sh (dash and busybox ash) and bash. I end up using three different shells with different purposes.
Sure, I could use zsh both as an interactive and scripting shell but I don't have the time or willingness to configure it when fish offers a nice out of the box experience. Not to mention that zsh shouldn't be used as a scripting shell in the first place.
Why not? If I'm writing scripts for automating configuration on modern macOS, for example, where ZSH is installed by default, why not write ZSH scripts?
I know what you mean, though. Most shell languages don't feel like flexible, expressive programming languages in the way that they ought to and could.
As you may know, there are some new shells/languages that are trying to bridge the gap in a way that still leaves the shell well-suited to interactive use. The Oil shell wiki has a great list of them (and Oil is one such shell itself, of course): https://github.com/oilshell/oil/wiki/Alternative-Shells
Perl's actually pretty good here; I'm pretty new to it, but it's generally what I reach for when I feel like a bash script has gotten just a bit too complicated.
If all you're doing is `a | b | c | d` then use bash but if you're pulling stuff out of the middle in a loop, yeah, might want to use a real language.
I guess there are two reasons
- if the script doesn't need arrays, POSIX sh (dash) scripts will be much faster than bash/zsh scripts
- if you do need arrays, bash is vastly more ubiquitous than any other shell on the planet right now (except POSIX sh). It's installed on almost all Linux distributions by default. I'm not gonna use a ZSH script because I'd have to install ZSH, which seems unnecessary. A good example is tomb, which is a ZSH script for encryption on Linux.
If you're sure that your scripts will always run on macOS, use POSIX sh if you don't need arrays and ZSH if you do need them.
I script in bash (though I'm super interested in oil), and use fish as my interactive shell, it's pinned to screen 0 in my screen session.
I don't write shell scripts a lot, I prefer to write python scripts (that are more maintainable and simple to write). But I write complex commands in the shell a lot, for example I may need to convert a bunch of images from one format to another, just use a for loop with imagemagik directly from the command line, then maybe a regex with sed to rename them, and done. It's not rare that I write commands that are more than 5 lines long.
With all the quirks of POSIX shell scripting languages (well in reality I use zsh that is nicer) they let you hack things together fast, and that makes them powerful.
Why would I need do to that?
> But I write complex commands in the shell a lot ... It's not rare that I write commands that are more than 5 lines long.
Ah, well, yeah, in that case, you might wanna stick to ZSH. I don't write complex commands on the shell. If it's more than 1 line long, I will make it a script. Multiple lines of commands with, or without, backward slash separators look ugly and unwieldy to me. A text editor like vim would do a far better job handling those 5 lines instead of an interactive shell.
The more languages you know the more valuable you are. I prefer to only write golang but sometimes that leads to typescript, Makefiles and bash scripting as well.
such as?
# MacPorts Installer addition on 2016-07-01_at_00:46:04: adding an appropriate PATH variable for use with MacPorts.
export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
# Finished adapting your PATH environment variable for use with MacPorts.
And I had to put the fish equivalent of that into ~/.config/fish/config.fish myself.You should keep using bash as your default login and user shell, define your environment variables, like PATH, in your `.bashrc`/`.bash_profile` but use fish as the default shell of your terminal emulator. In that case, fish should pick up the PATH from bash.
Unlike what some people may think, it's not just about the tool itself but its ecosystem as well.
autoload -Uz vcs_info
zstyle ':vcs_info:*' enable git hg
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:git*' formats "%{$fg[cyan]%}(%{$fg[green]%}%s %{$fg[blue]%}%r%{$fg[cyan]%}:%{$fg[green]%}%b%{$fg[yellow]%}%m%u%c%{$fg[cyan]%})%{$reset_color%} "
setopt prompt_subst
export PROMPT="%{$fg_bold[red]%}%n%{$reset_color$fg[white]%}@%{$fg_bold[green]%}%m%{$reset_color$fg[white]%}:%{$fg[cyan]%}%1~ \${vcs_info_msg_0_}%{$fg_bold[white]%}%(#.#.\$) %{$reset_color%}" set -l git_branch (git branch 2>/dev/null | sed -n '/\* /s///p')
if test -n "$git_branch"
echo -n -s (set_color yellow) "<$git_branch>" (set_color normal) " "
endI’ve recent switched from vanilla bash to ZSH. I mainly use oh-my-zsh and Power10k. Once again the defaults without much customization.
I keep a personal fork with a few added plugins (most notably zsh-autosuggestions and ssh-agent). No need for a plugin manager.
oh-my-zsh is way too bloated. But it's a nice repo if you're looking for plugins and aliases.
Another random tip: python virtualenv generates a activate.fish script that you should use instead of the plain activate script.
It basically runs the script in bash, diffs the environment, and applies the environment changes to your outer fish shell. I use it for some internal tools, and previously used it for nvm though I moved from nvm to fnm now which has fish support.
The only thing I ever used bass for was this edge case where at work the way we login to AWS is using this Okta AWS integration that prints out a list of export commands.
Since fish isn’t compatible with bash export commands, I just run that command result through bass, which automatically converts them to the fish set -x commands.
If I remember right, I think the reason why the bash script my company made didn’t work is that the export commands that were run in bash weren’t propagated to the underlying fish environment. I was using fish to run a script with a separate shell, so it didn’t affect my environment variables.
Or maybe it was because running exec inside a bash script throws you back into fish which then can’t understand the export command.
I could have definitely done my own thing with sed/awk instead, but I suck at those tools and someone else already implemented the functionality in bass.
bass exec aws_okta_thing_that_prints_export_commands_to_stdout
(Off the top of my head, I think it was something like that, could be misremembering! And by this comment you might be able to tell that I’m far from an expert on how everything works.)Shebangs are actually handled by the operating system kernel! I only know this because certain kinds of shebangs work on Linux, but not on other OSes
Can you also share what are the most significant problems with posix incompatibility for you? Why is it a problem?
Internally we have a boot strap run book developers/operations to bring up either Windows/WSL or MacOS to a consistent shell env.
#!/usr/bin/env bash
which means the interactive environment is irrelevant. Users of nonstandard shells like fish need to learn a bit of on-the-fly translation if they expect to copy/paste into their terminals, but it isn't too onerous.MacOS has version 3.2.57(1) Ubuntu has version 5.0.17(1)
Apparently Apple cites license concerns as the reason for not upgrading it. Don't know how valid that is.
License on version 3.2.57 is GPLv2 License on version 5.0.17 is GPLv3+
It's simple enough to update if you use homebrew.
`brew install bash`
Add the brew version of bash to the /private/etc/shells and change the shell.
Really nice shell though, I hope it gets more traction.
I kind of forgot that even use it until I read your comment :)
I hated Apple, but my opinion changed when I learned how to configure ZSH.