fish (and helix) are two program that I can install right way anywhere and get on with my work. Not much configuration needed. bash is still my goto for scripting but feels archaic as an actual shell. zsh requires incantations to emulate fish features. IIRC I have never even used any plugins/manager with fish.
IIRC I have never even used any plugins/manager with fish
They aren’t needed. Git submodules plus a few lines of script can get you 90% of the features if you want that workflow.
Along the same lines, I wouldn’t call the fish oh-my-zsh equivalent harmful, but it does reflect a cargo cult of values: where more options and knobs to tweak is inherently superior, instead of asking what is truly needed.
They aren’t needed. Git submodules plus a few lines of script can get you 90% of the features if you want that workflow.
But given how simple it is, something like fisher is pretty unobtrusive and works with most of the plugins out there. My config.fish is mostly comments documenting which fisher plugins I use for what.
This is a good call-out, and I do essentially the same thing for my fish setup. The same pattern also works fine for (n)vim, and you don’t even need the script equivalent there
fish works very nicely without any config at all but I remember it being worthwhile to configure the prompt for a bit just because fish made doing that very easy and pleasant.
I just change it to a 2 line informative prompt or another theme using fish_config. I only have a fish.config (w/ starship) on my main PC and laptop which is also <100 lines.
I’ve been on it for a while and I love it. I don’t write shell scripts any more and if I did I can just drop into bash. But fish is now just a zero config piece of my setup and I love it.
I do write shell scripts (especially as part of my overall system config) and Fish is so good for those. The built-in tooling for manipulating strings (particularly shell-style escaping), the fact that arrays are actually sensible and usable and you’re not constantly fighting with what quote style to preserve the right kind or expand correctly, they all make it possible to write good interactive-use tooling and helpers beyond just an alias or two.
I’ve got a few functions that I use written in fish and I can absolutely see how it’s a much less abusive programming environment than POSIX shells, yes.
Hint for the uninitiated: Just type for and then enter. It ends with end.
I’ve many times written loops, scopes (begin … end) and functions that pushed 50 lines, right in the terminal. And then funcsaved them. Yeah! Who needs to limit themselves to one-liners?
I’ll answer for bash: No, it doesn’t, it uses readline, and it reads one line at a time. You can’t move vertically in what you are editing, and when you run the same command again, it’s all collapsed into one long line. The difference is something like the difference between python and ipython.
Zsh apparently doesn’t collapse it to one line, but the arrow keys don’t move vertically, so I don’t know if I’m treating it right.
Another happy fish user here :). I switched from bash like a year ago. I just gave a try one day, expecting to miss many things from my curated .bashrc and quickly go back to the default Linux shell, and oh boy was i wrong!
For starters, the default interactive experience is miles ahead of bash. I’m a fan of having proper tab-completion on commands; i love having git or apt doing smart completions. And i dislike programs not providing tab-completion, which is why i seldom used short aliases in bash. On fish, it’s like everything has nicer tab-completions, and the interactivity is just, idk, snappier.
But also, i missed almost nothing from my old and trusty .bashrc. Most of my config was for patching up bash basically. Things like better history handling, better $PS1, defaults, colors, etc. And the few things i missed where some functions or aliases that i’m used to.
Speaking of which, some people mentioned that they use fish interactively, but never for scripting. I think having some little fish scripts, like functions or abbreviations, can be very useful. For example, i have a couple of functions for copy/pasting on the terminal:
function c -d "Copy to clipboard"
xclip -selection clipboard
end
function v -d "Paste from clipboard"
xclip -o -selection clipboard
end
They are so useful for doing things like ungodly-pipeline | c and then pasting on another program, or doing some command-line text processing with what’s on the clipboard without having to put it on a file first: v | grep 'foo|bar'.
Abbreviations are also super helpful. They are kinda like aliases, but not quite. They expand to their definitions when used, which i quite like, since it leaves the full commands on the history, making it easier to understand/remember what you did, also easier to share, easier to tweak, etc.
I hope the new Rust re-written version gets released soon :)
I love fish too, but I’m surprised to see this here without any comparison to the several arguably even better shells that are written by lobsters. Strange.
They are better along a different metric: there’s a shell as a programming language, and there’s a shell as a user-interface. Most alt-shells (notably, nushell) attack the programming language angle.
Fish is one of the relatively fewer projects that attacks the UX angle, and this is where fish is significantly superior to the competition (mostly because no one competes with it on this metric).
After attack on the programming language (we use NGS at work and it is productive), I’m finally getting to the UI. It took time because I insisted that (most of the) UI would be implemented in NGS itself.
NGS does attack the UX angle in a particular way: full screen interactivity. It was shown in 1976 (release of vi) that cursor movement capacity of the terminal can be used in this way.
Just arguably better, but factually inferior 😂. Just kidding!
But fish is a beast of a project and many people love it. I am one of them. It is a project that didn’t get hype-driven boosts like zshell. Every single person that I heard raving about zshell have never hear about fish.
What I am trying to say is that it is a product that really builds on delivering high quality real world gains mostly. Hence the love it gets.
But I was really impressed about elvish. I think it is a very well thought out next step in the right direction.
I have been using fish shell for almost 5 years now. The things I like the most are number one. I don’t have to use equal signs and it kind of just understands when I do variable assignment. Number two: automatic completions for anything with a man page. Number three: beautiful prompts. Number four: automatic package completion with most package managers. This means I don’t have to remember the whole name of the package and can do like a tab and it will give me all the things that start with a. I also like the community. It’s a very nice community. Strangely enough, it’s actually starting to be written in rust these days! I also like the completions which are much nicer than bash’s. And finally, the syntax is much richer if you’re writing scripts. I especially like the if then syntax and Superior string handling. The only downside is if you like want to overwrite things where you do greater than and then the file name. It doesn’t work very well. Also worth mentioning Fisher which what you put fish plugins installed. Overall, it’s a great operating system and I like it a lot.
I just switched to fish after using zsh for a few years. Needing to install plugins to reach what fish has built in was the big motivator for me. Omz is also really slow and I never used any of the plugins.
Overall super happy with fish and was excited by how easy it was to switch to it. The default prompt is also really nice and has almost everything I need. I just wish it would tell me when I have unstaged/staged changes in a git repo by default.
Ah! I didn’t see your comment before I posted my query about successful use as a login shell. Thanks for the feny recommendation, that looks quite useful.
This is interesting. Maybe I should give it another go.
Ctrl + cursor keys is a CUA standard keystroke for word-by-word navigation, and I’ve been using CUA pretty much exclusively everywhere for a third of a century now. Anything and everything from before it, including all arcane Unix weirdness, can DIAF. I don’t care, I am not interested, and I never will be. CUA or die. A shell that supports more CUA is a good thing.
I don’t code, I don’t script, I don’t customise, and I don’t want to. But I navigate, all the time, and it annoys me that it’s still crappy and broken on Linux – and much MUCH worse on the BSDs, all of them.
I’ve written about this and had angry upset BSD users complaining at me, because – as far as I can see – they don’t know or care about any nasty modern keystrokes from the 1990s, presumably because they use 1970s ones.
I remember the 1970s. That’s why I don’t use any 1970s UIs.
I am interested in long-running broad idioms/customs/conventions of keyboard shortcuts, their “philosophy” of usage (for want of a better term), and the histories that shape their emergence & durability in different systems and tribes. Ex. the presence/absence of “vim keys” hjkl and “emacs keys” C-a C-e C-f C-b, etc, across wide-ranging applications. If you or someone else was able to enrich the above comment with a bit more context, it would potentially be more illuminating and considerable.
I wrote most of the Wikipedia page, and all of the second article.
It saddens and dismays me that CUA is forgotten now. It was a very widespread cross-platform initiative and it dictates the UI not only of later-era DOS, OS/2, and all versions of Windows, but also of GNOME 1/2, MATE, Xfce, LXDE, LXQt, much of KDE (although that project is terrible at it) and dozens of other OSes and UIs from BeOS to QNX.
If all of these UIs are “CUA compliant”, then it means very little than “anything shaped vaguely like Windows”. IBM’s CUA was more than “paste is C-v”, but trying to rationalize IBM terminal user interfaces and their early GUIs. Outside of that context though, does it have much purpose?
If all of these UIs are “CUA compliant”, then it means very little than “anything shaped vaguely like Windows”.
No, not really. In fact I’d say you have it backwards. The real causation here is that CUA took the broad ideas from classic MacOS: a standardised menu bar, with standard entries in standard places with standard keystrokes, with standard notation for submenus and dialog boxes, with standard buttons in standard places, etc. etc.
And it defined these in ways that worked on a dumb terminal, a smart terminal, in DOS, in a choice of GUIs, etc.
Windows used that to inform its design.
Then a host of other OSes and desktops and apps accidentally implemented CUA because they copied Windows.
But I feel it’s important to trace the evolution. It didn’t start with Windows.
It roughly went:
Alto (chaotic)
Lisa (more organized)
Mac (ruthlessly rationalised partly just to fit)
Windows 1/2 (kinda a mess again)
IBM CUA
Windows 3
Everything else.
Very approximately.
Step 5.5 is OS/2 but sadly it influenced little else.
Ctrl+C, Ctrl+V, etc. are taken from the Macintosh HIG and adapted to a pre-104-key PC keyboard where you can’t use Command+C, Command+V, etc.
According to the copy of the CUA “Object-Oriented Interface Design: IBM Common User Access™ Guidelines” (the one published by Que with the IBM logo and “The Official Guide” on it) on my shelf, the CUA versions are Shift+Del for Cut, Ctrl+Ins for Copy, and Shift+Ins for Paste, as used in MS-DOS Edit.
Yes, I knew all those tricks. When I’m using Windows, Linux on desktop, or Android, I use them often. I just thought of them as Windows’s native text editing keyboard shortcuts, which Linux distributions must have copied in order to attract users by providing an easier onboarding experience.
I mostly run macOS, so I’m more often using macOS’s equivalent keyboard shortcuts:
Option-Left and Option-Right to move word by word
Command-C, Command-V, etc.
Holding Shift and movement to select
Press Command-Left or Command-Right to go to the beginning or end of the line
Press Command-Up or Command-Down to go to the beginning or end of the text input
Even after using Windows shortcuts for years, I find them slightly less comfortable than macOS’s shortcuts. The biggest reason is that the Ctrl, Home, and End keys are harder to reach than the Command and Option (Alt) keys. I also slightly prefer the behavior of macOS’s Option-Right, which moves the cursor to after the current word (before the space), to Windows’s Ctrl+Right, which moves the cursor to before the next word (after the space). I think macOS’s Option-Right and Option-Left also skip over punctuation in more cases, requiring fewer presses to navigate far. But I recognize that each behavior has text editing situations it’s suited for.
I sometimes have to use Microsoft Office programs for macOS such as Word and Outlook. I hate their text editing keyboard shortcuts, which are unnecessarily different from either OS’s. They use Option-Right to move words (as in macOS), but it moves the cursor to the before the next word (as in Windows). They use Command-Home to move to the beginning of the document (matching neither OS).
Microsoft Office programs also have annoying behavior when you select text by dragging with the mouse. They snap the start of your selection so that entire word you started dragging inside is selected. To un-snap, you have to move the mouse back over the word you started dragging from. That might help novice users select by words, but power users already know that they can do that with double-click-and-drag, so that feature just gets in the way. I’m glad that unlike in Office, dragging to select text works the same on macOS’s and Windows’s native text controls.
My perspective is heretical but it’s informed by being active in computing for more than 40 years and a very wide range of OS experience.
It’s this.
There are a few companies who designed and specified UI conventions for their OSes. Not many. Apple did it well, few others did. IBM did the best job there’s been, informed by Apple’s HIG.
And aside from that, there are a few influential individual apps, mostly with terrible UI that just grew before there were standards. Vi, Emacs, some DEC stuff, and so on.
Two of these are documented, systematic, complete, and worthy of attention. Apple classic Mac HIG, and IBM CUA.
“And the rest is noise,” as a wise man once wrote.
I would argue not heretical at all and totally reasonable perspective. My only nitpick: I’m not sure I’d call Emacs and VI terrible UI, but I would agree they are unique :)
I’ve first used computers in the 90s, so I also have CUA hardwired and soldered to my spine. This is why, although I do use vim daily for quick edits and file inspection, I never even considered using it, emacs, or any other terminal based editor as my main editor. CUA editing just beats it.
But we have a problem, terminal emulators colide with CUA. There is really no solution for this. For example, Ctrl+C is used by both for very important things, you have to break one of them in order to support the other.
Both are too well established to change now.
I’m still bitter about gnome’s switch from Alt-x to Ctrl-x for commands, which caused us to have exactly the same terminal app confusion as Windows. There was no reason to make ^C conflict with command-C except to massage the tender scalps of migrating Windows users.
There’s stuff in macOS that I can tell was influenced by Windows and CUA, because it does things with keystrokes that classic MacOS did not. Not much but I think the influence is there.
(Until you turn on Voiceover. Then you teleport to the Wild West in 1860, and good luck.)
But we have a problem, terminal emulators colide with CUA.
CUA was the industry standard. What this means in real life is very simple (in theory): the standard supercedes and replaces pre-standard UI.
In practice, it’s different, of course.
There is really no solution for this. For example, Ctrl+C is used by both for very important things, you have to break one of them in order to support the other. Both are too well established to change now.
No they aren’t. In the Linux world, Ctrl+C does what it always did and Shift+Ctrl+C does Copy. It’s not ideal and I’d have replaced the ’70s keystroke with the ’90s one, but whatever. It works.
BTW, if you’d like a CUA editor for the console, have you tried Tilde?
That is not “in the Linux world”, that’s a specific example of collision of CUA with a terminal [emulator].
On virtually every desktop environment Ctrl+C is the shortcut for copying to the clipboard..It’s not Ctrl+shift+c as you claim. That is just what MOST (but not all) terminal emulators use as alternative because they don’t want to break the old interrupt functionality.
I absolutely love fish! One of the first things I do in a fresh Linux install is to install fish and append exec fish to the default .bashrc. One thing that puzzled me (unless I’m missing something) was the removal of configuring aliases via the web configuration… idk in what version that changed but I was disappointed by it.
I still use fish daily and now do alias -s gc=“git commit” instead but I kinda liked the visual of seeing all my aliases in one place… I know there are a tons more ways to see my aliases but probably I was spoiled by the web configuration :-)
while we here, I’ll just ask a question that’s bugging me for a while that I’ve not been able to dig into. i don’t have a bashrc in my home directory but when i run “bash” from my fish shell, i am landed into a new bash shell (echo $?) works. but if I do echo $SHELL it’s still set to fish instead of bash.
I think you have at least three misconceptions here.
The question is about what happens to $SHELL when fish calls execve("bash"). The possibilities are:
fish sets it – no, because fish doesn’t care that bash is a shell
bash sets is – no, because (1)
some third party sets it – no because (3)
Nothing sets it, so it doesn’t change.
(1) what is $SHELL for?
$SHELL is analogous to $HOME: it informs programs what the user’s default is. It isn’t like $PWD which changes as the user does stuff. Traditionally $SHELL and $HOME are set by login from the user’s password entry. $SHELL is not set by shell interpreters like cd sets $PWD.
(2) how does a terminal emulator relate to $SHELL?
A terminal emulator might:
read $SHELL to determine which program to start inside a terminal
set $SHELL in the manner of login to the program which it is configured to start in new terminals
ignore $SHELL completely
A terminal emulator doesn’t have anything to do with the environment of programs running in the terminal except for the initial environment of the first program, because:
(3) how do environment variables work?
The environment is copied between processes like the command line arguments, it isn’t shared. There isn’t any cross-process mutable state here.
While a program is running it doesn’t have to use libc‘s functions and data structures to work with the environment. This is most obvious when a program calls execve(): it typically constructs a new environment from scratch that is passed to execve() and thence copied to the new executable. (argv and envp are typically placed above the program’s initial stack frame.)
This means there isn’t any good way for some third party (e.g. a terminal emulator) to have any control over the environment of other processes. It would have to do something extremely horrible such as running them under ptrace and setting a breakpoint on execve so that it can mess with the arguments. Not something that normally happens if ever.
I should give fish another try. Reading this made me realise I rely on ^S, ^X, as well as frequent use of ^Z, jobs and fg: habits I learned in a very different time, With better equivalents now
I really like fish. Unfortunately, I had to switch back to zsh on macOS: the git prompt is “too” (we’re talking milliseconds, but still noticeable) slow and is run every time the prompt is shown, with a much more significant slowdown on big repos. I tried fixing a bit the fish_prompt.fish function:
function _is_git_dirty
not /usr/bin/git diff-index --cached --quiet HEAD -- &>/dev/null
or not /usr/bin/git diff --no-ext-diff --quiet --exit-code &>/dev/null
end
function _is_git_repo
git rev-parse --git-dir HEAD 2>&1 > /dev/null
return $status
end
but nothing changed and I don’t have that much time that I can profile the prompt of my shell and optimize it the way I want it, especially when there’s a viable alternative.
Thanks for the lucid plug! (I’m the author.) It takes pains to avoid any IPC mechanism that might hit disk when communicating back the git status to the prompt, at the expense of features.
What I’d like to see in fish 4 is a declarative prompt mechanism that makes it easy to write async prompts, because the shell is in the best place to coordinate/redraw the prompt when needed.
This probably slows prompt speed by O(μsec) within the large repos, but, if you are using vcs_info in a recent Zsh (it really sounds like you might be from your comment) then it probably helps prompt speeds outside any repo where cost is reduced from a fork-exec spawn to only 1 [[ -d ]] per directory-level of depth from “/” by O(msec):
tstatus=0 # Track bad exit statuses
TRAPZERR() { tstatus=$[tstatus + status]; } # Record prog & func failures
autoload -Uz vcs_info
zstyle ':vcs_info:git:*' formats '(%b)'
zstyle ':vcs_info:hg*:*' formats '(hg)'
precmd() { # set PSVAR to exit status for FIRST prompt after failed command(s)
local tst=$tstatus this="." last="" # vcs_info trashes tstatus
unset vcs_info_msg_0_ # Need only unset used vars
while [[ ! "$last" -ef "$this" ]]; do # Skip vcs_info unless have .VC/
[[ -d $this/.git/ ]] && { vcs_info; break }
last=$this; this=../$last #..(since vcs_info *spawns*).
done
if [[ $tst -ne 0 ]]; then PSVAR="${vcs_info_msg_0_}[${tst}]"
else PSVAR="${vcs_info_msg_0_}"; fi # %v in $PS1234
tstatus=0
}
preexec() { tstatus=0; PSVAR="" }
It’s obviously workload dependent whether this is an optimization or not. Also, if you want %v in your $PS1 or whatever to reflect multiple VC systems then you can add a [[ -d $this/.hg/ ]] or whatnot. There may be some magic wherein vcs_info itself could be smart in this way, but I was just looking for this the other day and couldn’t find it or some VCS_RESTRICT_TO="git hg" setting to say limit the extra stat()s to just VCs I care about having %v representation.
I kept in this snippet a bonus bit to replace/supplement setopt print_exit_value with a little state machine to accumulate the total exit status prompt-to-prompt. (Mostly, 10+ prints in something like for i in {1..10}; (exit 1) annoyed me. It’s also possible Zsh has some new setopt to control loop print exits.)
Thanks! I know there are many prompt packages. git-prompt.zsh seems like a nice self-contained, very hackable one. Dunno how well attended exit status is in this subculture. { Of course, shortly after I posted I realized I should have updated that code to something like TRAPZERR(){for s in $pipestatus; tstatus=$[tstatus+s] } so that for i in {1..10}; (exit 10)|(exit 20), for example, shows [300]. 🤦♂️}
It’s definitely hackable. I wanted a lot of small differences that I didn’t want to bother the creator with, but I found it really easy to work with in a fork. (That said, you definitely want to know a bit about awk.)
In case it helps, when I was optimizing my git integration for my zsh prompt back when I was on a 2011 CPU and a rotating boot drive, I found the following was fastest for “show current branch in the prompt”:
As an optimization for time to prompt in a new terminal, if $PWD is $HOME, assume it’s not a git repo.
git symbolic-ref was the lightest way I found to get the current branch name and do an early return if not in a repo.
Making the git portion of the prompt a function makes early return easy.
I’m the kind of autism-spectrum guy who doesn’t really get any benefit from an asynchronous prompt because having the prompt change after it’s become usable would be comparably irritating to just having it delayed, so I wrote my prompt completely without anything like oh-my-zsh and micro-optimized the crap out of it. For example, I dug up this trick for skipping fortune if things were taking too long:
# (Use a prompt expansion modifier `(%s)` on a defaulting variable substitution
# `:-` that contains a default but no variable so it can access `strftime`
# without invoking a subshell to call `print -P`.)
local start_time="${(%):-"%D{%s}"}"
# [...]
# I prefer to have a fortune from any new shell, not just login ones
# ...but I don't want it further bogging down an already slow start.
local end_time="${(%):-"%D{%s}"}"
if [[ $(( end_time - start_time )) < 2 ]]; then
# Might as well micro-optimize this. $+commands is up to 10x faster
# (https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh/)
if (( $+commands[fortune] )); then
fortune
fi
else
echo "Skipping fortune (slow startup)"
fi
I have been using Fish for a few years now. I’m pretty lazy so I never read any docs or tutorials and even still it’s a really good experience. I pretty much know ctrl-f and that’s it
I love fish shell! I’ve used it for over a decade and have nothing but praise.
One thing I’ve never done successfully is use it as a login shell, though. It’s a small thing to type fish at the beginning of a terminal session and it has never bothered me (such that I haven’t bothered to try it again in that same decade) but I am curious whether anyone has had any luck doing so.
My previous experiences involved many missing environment settings, especially custom ones defined globally (for bash) on Linux boxes at $work. Basically nothing that was supposed to function, would function.
As mentioned though I haven’t tried it in ages. Seems like there are quite a few comprehensive options at this point.
I’ve done this to myself before and usually it’s pretty easy to unheck via a root login or a rescue prompt. That said, my previous job had toooons of custom bash scripts and aliases as well, which I gleefully have now jettisoned from my life, so I sympathize.
I never touch the shell defaults for the root user if I can help it, so in that we are alike.
I saw you got a tip elsewhere here, but I thought I’d add my experiences.
On NixOS, it just works. On nix-darwin on macOS, I have the following in its init script:
for p in (string split " " $NIX_PROFILES)
fish_add_path -p -m $p/bin
end
Looking at my pre-Nix configs, when I ran macOS without nix-darwin, there wasn’t anything special I seemed to need to get it working OK. Similarly for my Linux hosts, but I do have a general feeling there was weirdness at times (such that I wasn’t surprised to hear you had trouble!).
I’ve used it as a login shell for over a decade – sed -ri s|/bin/bash|/usr/bin/fish|g /etc/passwd. The only program I’ve seen completely fall on its face due to this is ssh-copy-id, but that was fixed a long time ago.
I don’t ever see myself changing login shells for users other than myself, but I guess your point is that you can safely use it for both your (single person) user and root accounts?
I recall it being relatively common advice to avoid using it as a login shell way back when. There was no way I could use it the way you describe in the environments I was working in which required relatively complex environment setup (not to mention on the prod hosts where your incantation would have affected other people).
I’m glad I asked though, as now I know a few solutions which would work even under those conditions.
I tried fish a couple of times but always felt that when it comes to auto completions, ctrl+r & fzf worked far better in bash. Having tab completion on virtually every command line was neat though.
Fish don’t do ^R at all, no; it was a bit of a hurdle for me adopting it at first, but I soon came to find its autocomplete and recall was more efficient than using ^R in bash overall.
I use fish percol plugin which is a single line of code and bind Ctrl+r. I find it better than fzf because it’s simpler and not fuzzy finder. I think it does what you want.
i tried it for a few months and sadly had to switch back to bash because i tried to use fish keybindings in all command lines (like repls and containers), without noticing it before i mess up the text
I honestly have never heard of the fish shell.
Been using bash just as a default and I don’t write many shell scripts so I wonder is it worth switching for.
Your interactive shell does not have to be your login shell, nor does it have to be what shell scripts were written in. The shebang line is a wonderful load-carrying abstraction, after all.
Perhaps read the article — it talks about exactly why, and none of them are about writing scripts (the author mentions never having learned its scripting language).
fish (and helix) are two program that I can install right way anywhere and get on with my work. Not much configuration needed. bash is still my goto for scripting but feels archaic as an actual shell. zsh requires incantations to emulate fish features. IIRC I have never even used any plugins/manager with fish.
They aren’t needed. Git submodules plus a few lines of script can get you 90% of the features if you want that workflow.
Along the same lines, I wouldn’t call the fish oh-my-zsh equivalent harmful, but it does reflect a cargo cult of values: where more options and knobs to tweak is inherently superior, instead of asking what is truly needed.
But given how simple it is, something like fisher is pretty unobtrusive and works with most of the plugins out there. My config.fish is mostly comments documenting which fisher plugins I use for what.
This is a good call-out, and I do essentially the same thing for my fish setup. The same pattern also works fine for (n)vim, and you don’t even need the script equivalent there
fish works very nicely without any config at all but I remember it being worthwhile to configure the prompt for a bit just because fish made doing that very easy and pleasant.
I just change it to a 2 line informative prompt or another theme using fish_config. I only have a fish.config (w/ starship) on my main PC and laptop which is also <100 lines.
Helix the adobe thing or helix the perforce thing ? Or some other thing?
Presumably the editor https://helix-editor.com/
Helix the… Helix thing
I’ve been on it for a while and I love it. I don’t write shell scripts any more and if I did I can just drop into bash. But fish is now just a zero config piece of my setup and I love it.
I do write shell scripts (especially as part of my overall system config) and Fish is so good for those. The built-in tooling for manipulating strings (particularly shell-style escaping), the fact that arrays are actually sensible and usable and you’re not constantly fighting with what quote style to preserve the right kind or expand correctly, they all make it possible to write good interactive-use tooling and helpers beyond just an alias or two.
I’ve got a few functions that I use written in fish and I can absolutely see how it’s a much less abusive programming environment than POSIX shells, yes.
Writing for loops in fish are 97.3% less of a pain in the ass than in bash. :-P
Not least because it has multiline editing!
Hint for the uninitiated: Just type
forand then enter. It ends withend.I’ve many times written loops, scopes (
begin … end) and functions that pushed 50 lines, right in the terminal. And thenfuncsaved them. Yeah! Who needs to limit themselves to one-liners?Oh heck, I always forget about
funcsave. Thanks for the reminder!bash and zsh support multi-line editing too, is there something special or different about fish’s multi-line editor?
I’ll answer for bash: No, it doesn’t, it uses readline, and it reads one line at a time. You can’t move vertically in what you are editing, and when you run the same command again, it’s all collapsed into one long line. The difference is something like the difference between python and ipython.
Zsh apparently doesn’t collapse it to one line, but the arrow keys don’t move vertically, so I don’t know if I’m treating it right.
Another happy fish user here :). I switched from bash like a year ago. I just gave a try one day, expecting to miss many things from my curated .bashrc and quickly go back to the default Linux shell, and oh boy was i wrong!
For starters, the default interactive experience is miles ahead of bash. I’m a fan of having proper tab-completion on commands; i love having git or apt doing smart completions. And i dislike programs not providing tab-completion, which is why i seldom used short aliases in bash. On fish, it’s like everything has nicer tab-completions, and the interactivity is just, idk, snappier.
But also, i missed almost nothing from my old and trusty .bashrc. Most of my config was for patching up bash basically. Things like better history handling, better $PS1, defaults, colors, etc. And the few things i missed where some functions or aliases that i’m used to.
Speaking of which, some people mentioned that they use fish interactively, but never for scripting. I think having some little fish scripts, like functions or abbreviations, can be very useful. For example, i have a couple of functions for copy/pasting on the terminal:
They are so useful for doing things like
ungodly-pipeline | cand then pasting on another program, or doing some command-line text processing with what’s on the clipboard without having to put it on a file first:v | grep 'foo|bar'.Abbreviations are also super helpful. They are kinda like aliases, but not quite. They expand to their definitions when used, which i quite like, since it leaves the full commands on the history, making it easier to understand/remember what you did, also easier to share, easier to tweak, etc.
I hope the new Rust re-written version gets released soon :)
I love fish too, but I’m surprised to see this here without any comparison to the several arguably even better shells that are written by lobsters. Strange.
See https://github.com/oils-for-unix/oils/wiki/Alternative-Shells for a long list. Of those, at least oils, elvish and NGS are written by lobsters, and I think others (nushell?).
FWIW, I find fish close to perfect for interactive use but not for scripting, and it would be nice to unify the two.
They are better along a different metric: there’s a shell as a programming language, and there’s a shell as a user-interface. Most alt-shells (notably, nushell) attack the programming language angle.
Fish is one of the relatively fewer projects that attacks the UX angle, and this is where fish is significantly superior to the competition (mostly because no one competes with it on this metric).
Yeah, this dichotomy was important in the past too https://lobste.rs/s/iuzuge/why_does_freebsd_default_csh_tcsh#c_j7csuv
After attack on the programming language (we use NGS at work and it is productive), I’m finally getting to the UI. It took time because I insisted that (most of the) UI would be implemented in NGS itself.
NGS does attack the UX angle in a particular way: full screen interactivity. It was shown in 1976 (release of vi) that cursor movement capacity of the terminal can be used in this way.
More at:
https://github.com/ngs-lang/ngs/wiki/UI-Design
https://youtu.be/J4_DGkKGWIo
Yeah I really appreciate its motto being a snarky callout to the UX angle. “A command line shell for the 90’s” indeed.
Hey, some fish core devs are also lobsters! Well, at least this one!
Awesome and thank you!
Thanks for you work.
Whats happening in fish shell as we speak? Ia the move to that complete? What game changing new features can we expect?
Fish has been good enough for me that none of the newshells have stuck.
Just arguably better, but factually inferior 😂. Just kidding!
But fish is a beast of a project and many people love it. I am one of them. It is a project that didn’t get hype-driven boosts like zshell. Every single person that I heard raving about zshell have never hear about fish. What I am trying to say is that it is a product that really builds on delivering high quality real world gains mostly. Hence the love it gets.
But I was really impressed about elvish. I think it is a very well thought out next step in the right direction.
I have been using fish shell for almost 5 years now. The things I like the most are number one. I don’t have to use equal signs and it kind of just understands when I do variable assignment. Number two: automatic completions for anything with a man page. Number three: beautiful prompts. Number four: automatic package completion with most package managers. This means I don’t have to remember the whole name of the package and can do like a tab and it will give me all the things that start with a. I also like the community. It’s a very nice community. Strangely enough, it’s actually starting to be written in rust these days! I also like the completions which are much nicer than bash’s. And finally, the syntax is much richer if you’re writing scripts. I especially like the if then syntax and Superior string handling. The only downside is if you like want to overwrite things where you do greater than and then the file name. It doesn’t work very well. Also worth mentioning Fisher which what you put fish plugins installed. Overall, it’s a great operating system and I like it a lot.
+1 from me. If you like a semi (or more) customized shell and you haven’t tried fish, you should! Thanks Julia for the great write up.
I just switched to fish after using zsh for a few years. Needing to install plugins to reach what fish has built in was the big motivator for me. Omz is also really slow and I never used any of the plugins.
Overall super happy with fish and was excited by how easy it was to switch to it. The default prompt is also really nice and has almost everything I need. I just wish it would tell me when I have unstaged/staged changes in a git repo by default.
love fish, i actually chsh’d and it still works fine - i just use fenv to source
/etc/profileand/etc/profile.d/*shthe only reason i still have bash is to copy-paste bash commands from the internet - just drop into bash for one command, paste, exit
Ah! I didn’t see your comment before I posted my query about successful use as a login shell. Thanks for the feny recommendation, that looks quite useful.
no problem, you can also use
if status is-loginto guard it so it only gets sourced when it is used as a login shell:https://git.sr.ht/~p00f/dotfiles/tree/5354bb5c652a2559766346099c3d7835ce2c3a74/item/fish/.config/fish/config.fish#L3
This is interesting. Maybe I should give it another go.
Ctrl + cursor keys is a CUA standard keystroke for word-by-word navigation, and I’ve been using CUA pretty much exclusively everywhere for a third of a century now. Anything and everything from before it, including all arcane Unix weirdness, can DIAF. I don’t care, I am not interested, and I never will be. CUA or die. A shell that supports more CUA is a good thing.
I don’t code, I don’t script, I don’t customise, and I don’t want to. But I navigate, all the time, and it annoys me that it’s still crappy and broken on Linux – and much MUCH worse on the BSDs, all of them.
I’ve written about this and had angry upset BSD users complaining at me, because – as far as I can see – they don’t know or care about any nasty modern keystrokes from the 1990s, presumably because they use 1970s ones.
I remember the 1970s. That’s why I don’t use any 1970s UIs.
I am interested in long-running broad idioms/customs/conventions of keyboard shortcuts, their “philosophy” of usage (for want of a better term), and the histories that shape their emergence & durability in different systems and tribes. Ex. the presence/absence of “vim keys” hjkl and “emacs keys” C-a C-e C-f C-b, etc, across wide-ranging applications. If you or someone else was able to enrich the above comment with a bit more context, it would potentially be more illuminating and considerable.
I’m guessing “CUA” refers to IBM Common User Access. I had never heard of it before. Another article about it: The rise and fall of the standard user interface.
I wrote most of the Wikipedia page, and all of the second article.
It saddens and dismays me that CUA is forgotten now. It was a very widespread cross-platform initiative and it dictates the UI not only of later-era DOS, OS/2, and all versions of Windows, but also of GNOME 1/2, MATE, Xfce, LXDE, LXQt, much of KDE (although that project is terrible at it) and dozens of other OSes and UIs from BeOS to QNX.
If all of these UIs are “CUA compliant”, then it means very little than “anything shaped vaguely like Windows”. IBM’s CUA was more than “paste is C-v”, but trying to rationalize IBM terminal user interfaces and their early GUIs. Outside of that context though, does it have much purpose?
No, not really. In fact I’d say you have it backwards. The real causation here is that CUA took the broad ideas from classic MacOS: a standardised menu bar, with standard entries in standard places with standard keystrokes, with standard notation for submenus and dialog boxes, with standard buttons in standard places, etc. etc.
And it defined these in ways that worked on a dumb terminal, a smart terminal, in DOS, in a choice of GUIs, etc.
Windows used that to inform its design.
Then a host of other OSes and desktops and apps accidentally implemented CUA because they copied Windows.
But I feel it’s important to trace the evolution. It didn’t start with Windows.
It roughly went:
Very approximately.
Step 5.5 is OS/2 but sadly it influenced little else.
If you reply to this very message, your browser will support:
This is CUA. Just out of curiosity, did you now these ‘tricks’ themselves even if not their origin?
Ctrl+C, Ctrl+V, etc. are taken from the Macintosh HIG and adapted to a pre-104-key PC keyboard where you can’t use Command+C, Command+V, etc.
According to the copy of the CUA “Object-Oriented Interface Design: IBM Common User Access™ Guidelines” (the one published by Que with the IBM logo and “The Official Guide” on it) on my shelf, the CUA versions are Shift+Del for Cut, Ctrl+Ins for Copy, and Shift+Ins for Paste, as used in MS-DOS Edit.
Yes, I knew all those tricks. When I’m using Windows, Linux on desktop, or Android, I use them often. I just thought of them as Windows’s native text editing keyboard shortcuts, which Linux distributions must have copied in order to attract users by providing an easier onboarding experience.
I mostly run macOS, so I’m more often using macOS’s equivalent keyboard shortcuts:
Even after using Windows shortcuts for years, I find them slightly less comfortable than macOS’s shortcuts. The biggest reason is that the Ctrl, Home, and End keys are harder to reach than the Command and Option (Alt) keys. I also slightly prefer the behavior of macOS’s Option-Right, which moves the cursor to after the current word (before the space), to Windows’s Ctrl+Right, which moves the cursor to before the next word (after the space). I think macOS’s Option-Right and Option-Left also skip over punctuation in more cases, requiring fewer presses to navigate far. But I recognize that each behavior has text editing situations it’s suited for.
I sometimes have to use Microsoft Office programs for macOS such as Word and Outlook. I hate their text editing keyboard shortcuts, which are unnecessarily different from either OS’s. They use Option-Right to move words (as in macOS), but it moves the cursor to the before the next word (as in Windows). They use Command-Home to move to the beginning of the document (matching neither OS).
Microsoft Office programs also have annoying behavior when you select text by dragging with the mouse. They snap the start of your selection so that entire word you started dragging inside is selected. To un-snap, you have to move the mouse back over the word you started dragging from. That might help novice users select by words, but power users already know that they can do that with double-click-and-drag, so that feature just gets in the way. I’m glad that unlike in Office, dragging to select text works the same on macOS’s and Windows’s native text controls.
My perspective is heretical but it’s informed by being active in computing for more than 40 years and a very wide range of OS experience.
It’s this.
There are a few companies who designed and specified UI conventions for their OSes. Not many. Apple did it well, few others did. IBM did the best job there’s been, informed by Apple’s HIG.
And aside from that, there are a few influential individual apps, mostly with terrible UI that just grew before there were standards. Vi, Emacs, some DEC stuff, and so on.
Two of these are documented, systematic, complete, and worthy of attention. Apple classic Mac HIG, and IBM CUA.
“And the rest is noise,” as a wise man once wrote.
I would argue not heretical at all and totally reasonable perspective. My only nitpick: I’m not sure I’d call Emacs and VI terrible UI, but I would agree they are unique :)
I’ve first used computers in the 90s, so I also have CUA hardwired and soldered to my spine. This is why, although I do use vim daily for quick edits and file inspection, I never even considered using it, emacs, or any other terminal based editor as my main editor. CUA editing just beats it.
But we have a problem, terminal emulators colide with CUA. There is really no solution for this. For example, Ctrl+C is used by both for very important things, you have to break one of them in order to support the other. Both are too well established to change now.
I mean, Command+C for Copy, Control+C for interrupt?
Well that is on OSX, which annoyingly doesn’t adopt CUA.
I’m still bitter about gnome’s switch from Alt-x to Ctrl-x for commands, which caused us to have exactly the same terminal app confusion as Windows. There was no reason to make ^C conflict with command-C except to massage the tender scalps of migrating Windows users.
There’s stuff in macOS that I can tell was influenced by Windows and CUA, because it does things with keystrokes that classic MacOS did not. Not much but I think the influence is there.
(Until you turn on Voiceover. Then you teleport to the Wild West in 1860, and good luck.)
CUA was the industry standard. What this means in real life is very simple (in theory): the standard supercedes and replaces pre-standard UI.
In practice, it’s different, of course.
No they aren’t. In the Linux world, Ctrl+C does what it always did and Shift+Ctrl+C does Copy. It’s not ideal and I’d have replaced the ’70s keystroke with the ’90s one, but whatever. It works.
BTW, if you’d like a CUA editor for the console, have you tried Tilde?
https://os.ghalkes.nl/tilde/
That is not “in the Linux world”, that’s a specific example of collision of CUA with a terminal [emulator]. On virtually every desktop environment Ctrl+C is the shortcut for copying to the clipboard..It’s not Ctrl+shift+c as you claim. That is just what MOST (but not all) terminal emulators use as alternative because they don’t want to break the old interrupt functionality.
I absolutely love fish! One of the first things I do in a fresh Linux install is to install fish and append
exec fishto the default.bashrc. One thing that puzzled me (unless I’m missing something) was the removal of configuring aliases via the web configuration… idk in what version that changed but I was disappointed by it.I still use fish daily and now do
alias -s gc=“git commit”instead but I kinda liked the visual of seeing all my aliases in one place… I know there are a tons more ways to see my aliases but probably I was spoiled by the web configuration :-)Why not just
chshyour default shell to fish instead of going through the bashrc?I find that a few tools I use still depend on bash and write their configuration to bashrc (i.e. set PATH and export env variables).
Given that those pass to fish I don’t feel like translating those to fish config and managing them myself :-)
Elvish shares a lot of those - I count 1, 3, 6, 7, 9, 11, 12, but there’s more to learn from fish :)
while we here, I’ll just ask a question that’s bugging me for a while that I’ve not been able to dig into. i don’t have a bashrc in my home directory but when i run “bash” from my fish shell, i am landed into a new bash shell (echo $?) works. but if I do echo $SHELL it’s still set to fish instead of bash.
any guesses why so?
$SHELLis set byloginto the shell field of your password entry. It isn’t set by shell interpreters.eg https://man.freebsd.org/cgi/man.cgi?query=login
The description in POSIX is vague because POSIX doesn’t cover
loginhttps://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03I bet $5 you have your terminal program set to ignore $SHELL
I think you have at least three misconceptions here.
The question is about what happens to $SHELL when fish calls
execve("bash"). The possibilities are:Nothing sets it, so it doesn’t change.
(1) what is $SHELL for?
$SHELL is analogous to $HOME: it informs programs what the user’s default is. It isn’t like $PWD which changes as the user does stuff. Traditionally $SHELL and $HOME are set by
loginfrom the user’s password entry. $SHELL is not set by shell interpreters likecdsets $PWD.(2) how does a terminal emulator relate to $SHELL?
A terminal emulator might:
loginto the program which it is configured to start in new terminalsA terminal emulator doesn’t have anything to do with the environment of programs running in the terminal except for the initial environment of the first program, because:
(3) how do environment variables work?
The environment is copied between processes like the command line arguments, it isn’t shared. There isn’t any cross-process mutable state here.
While a program is running it doesn’t have to use
libc‘s functions and data structures to work with the environment. This is most obvious when a program callsexecve(): it typically constructs a new environment from scratch that is passed toexecve()and thence copied to the new executable. (argv and envp are typically placed above the program’s initial stack frame.)This means there isn’t any good way for some third party (e.g. a terminal emulator) to have any control over the environment of other processes. It would have to do something extremely horrible such as running them under ptrace and setting a breakpoint on execve so that it can mess with the arguments. Not something that normally happens if ever.
Sorry! I misread the question and made you type a lot.
[Comment removed by author]
I should give fish another try. Reading this made me realise I rely on ^S, ^X, as well as frequent use of ^Z, jobs and fg: habits I learned in a very different time, With better equivalents now
I use ^Z, jobs and
fgall day. What are these better equivalents you mention?Oh I mean stuff like screen, tmux, terminal-inside-neovim, even simple things like “multiple terminals”. But old habits die hard.
“Better” is too strong of a word that I wouldn’t use, but I imagine using multiple windows/tabs/split panes is what OP had in mind.
I really like
fish. Unfortunately, I had to switch back tozshon macOS: the git prompt is “too” (we’re talking milliseconds, but still noticeable) slow and is run every time the prompt is shown, with a much more significant slowdown on big repos. I tried fixing a bit thefish_prompt.fishfunction:but nothing changed and I don’t have that much time that I can profile the prompt of my shell and optimize it the way I want it, especially when there’s a viable alternative.
Check out lucid.fish, Tide or Hydro prompt repos. All of them do async git status.
Thanks for the lucid plug! (I’m the author.) It takes pains to avoid any IPC mechanism that might hit disk when communicating back the git status to the prompt, at the expense of features.
What I’d like to see in fish 4 is a declarative prompt mechanism that makes it easy to write async prompts, because the shell is in the best place to coordinate/redraw the prompt when needed.
The Starship prompt also works well.
It’s fast in general but it’s still synchronous. So it will delay the rendering of the prompt in huge repositories.
This probably slows prompt speed by O(μsec) within the large repos, but, if you are using
vcs_infoin a recent Zsh (it really sounds like you might be from your comment) then it probably helps prompt speeds outside any repo where cost is reduced from a fork-exec spawn to only 1 [[ -d ]] per directory-level of depth from “/” by O(msec):It’s obviously workload dependent whether this is an optimization or not. Also, if you want
%vin your$PS1or whatever to reflect multiple VC systems then you can add a[[ -d $this/.hg/ ]]or whatnot. There may be some magic whereinvcs_infoitself could be smart in this way, but I was just looking for this the other day and couldn’t find it or someVCS_RESTRICT_TO="git hg"setting to say limit the extra stat()s to just VCs I care about having %v representation.I kept in this snippet a bonus bit to replace/supplement
setopt print_exit_valuewith a little state machine to accumulate the total exit status prompt-to-prompt. (Mostly, 10+ prints in something likefor i in {1..10}; (exit 1)annoyed me. It’s also possible Zsh has some newsetoptto control loop print exits.)An alternative to
vcs_infothat can perform far better in large repos is git-prompt.zsh. It’s async, and (in my experience) very snappy.Thanks! I know there are many prompt packages.
git-prompt.zshseems like a nice self-contained, very hackable one. Dunno how well attended exit status is in this subculture. { Of course, shortly after I posted I realized I should have updated that code to something likeTRAPZERR(){for s in $pipestatus; tstatus=$[tstatus+s] }so thatfor i in {1..10}; (exit 10)|(exit 20), for example, shows[300]. 🤦♂️}It’s definitely hackable. I wanted a lot of small differences that I didn’t want to bother the creator with, but I found it really easy to work with in a fork. (That said, you definitely want to know a bit about
awk.)In case it helps, when I was optimizing my git integration for my zsh prompt back when I was on a 2011 CPU and a rotating boot drive, I found the following was fastest for “show current branch in the prompt”:
$PWDis$HOME, assume it’s not a git repo.git symbolic-refwas the lightest way I found to get the current branch name and do an early return if not in a repo.I’m the kind of autism-spectrum guy who doesn’t really get any benefit from an asynchronous prompt because having the prompt change after it’s become usable would be comparably irritating to just having it delayed, so I wrote my prompt completely without anything like oh-my-zsh and micro-optimized the crap out of it. For example, I dug up this trick for skipping
fortuneif things were taking too long:My fish is a bit more customized than hers maybe, but I like that zero configuration plugins do most of the heavy lifting.
I’d be curious to see if she comes up with a bunch of stuff of how
fishcould build on its strengths and become much better still.I have been using Fish for a few years now. I’m pretty lazy so I never read any docs or tutorials and even still it’s a really good experience. I pretty much know ctrl-f and that’s it
I love fish shell! I’ve used it for over a decade and have nothing but praise.
One thing I’ve never done successfully is use it as a login shell, though. It’s a small thing to type fish at the beginning of a terminal session and it has never bothered me (such that I haven’t bothered to try it again in that same decade) but I am curious whether anyone has had any luck doing so.
I use as a login shell on several devices (Linux & MacOS) and have had no problems, is there something in particular you’re worried about?
My previous experiences involved many missing environment settings, especially custom ones defined globally (for bash) on Linux boxes at $work. Basically nothing that was supposed to function, would function.
As mentioned though I haven’t tried it in ages. Seems like there are quite a few comprehensive options at this point.
Cool to hear you’ve had good experiences with it!
I’ve done this to myself before and usually it’s pretty easy to unheck via a root login or a rescue prompt. That said, my previous job had toooons of custom bash scripts and aliases as well, which I gleefully have now jettisoned from my life, so I sympathize.
I never touch the shell defaults for the root user if I can help it, so in that we are alike.
I saw you got a tip elsewhere here, but I thought I’d add my experiences.
On NixOS, it just works. On nix-darwin on macOS, I have the following in its init script:
Looking at my pre-Nix configs, when I ran macOS without nix-darwin, there wasn’t anything special I seemed to need to get it working OK. Similarly for my Linux hosts, but I do have a general feeling there was weirdness at times (such that I wasn’t surprised to hear you had trouble!).
Even if you don’t have it as the login shell, you can make it the default for all your sessions:
exec fishat the end of your .bashrcThanks for this! It goes to show how little I have been bothered with typing fish that I didn’t even think of this :)
I’ve used it as a login shell for over a decade – sed -ri s|/bin/bash|/usr/bin/fish|g /etc/passwd. The only program I’ve seen completely fall on its face due to this is ssh-copy-id, but that was fixed a long time ago.
I don’t ever see myself changing login shells for users other than myself, but I guess your point is that you can safely use it for both your (single person) user and root accounts?
I recall it being relatively common advice to avoid using it as a login shell way back when. There was no way I could use it the way you describe in the environments I was working in which required relatively complex environment setup (not to mention on the prod hosts where your incantation would have affected other people).
I’m glad I asked though, as now I know a few solutions which would work even under those conditions.
It’s written in Rust. Did it get rewritten or something?
It did.
edit: some more info on progress of the last portion.
First thing I did was check the language it was written in, yes.
Guess it works!
There is a ongoing rewrite from C++ → Rust for v4.0 release.
It did indeed
Are you talking about anything different than just chsh -s /path/to/fish ?
As far as I know almost everyone does it. I never considering not doing it and do it an all machines, including servers.
I tried fish a couple of times but always felt that when it comes to auto completions, ctrl+r & fzf worked far better in bash. Having tab completion on virtually every command line was neat though.
Does that still not work with fish’s history module?
Fish don’t do ^R at all, no; it was a bit of a hurdle for me adopting it at first, but I soon came to find its autocomplete and recall was more efficient than using ^R in bash overall.
I use fish percol plugin which is a single line of code and bind Ctrl+r. I find it better than fzf because it’s simpler and not fuzzy finder. I think it does what you want.
i tried it for a few months and sadly had to switch back to bash because i tried to use fish keybindings in all command lines (like repls and containers), without noticing it before i mess up the text
I agree completely. I have been using it for a while, and I really love it!
I honestly have never heard of the fish shell. Been using bash just as a default and I don’t write many shell scripts so I wonder is it worth switching for.
Your interactive shell does not have to be your login shell, nor does it have to be what shell scripts were written in. The shebang line is a wonderful load-carrying abstraction, after all.
Perhaps read the article — it talks about exactly why, and none of them are about writing scripts (the author mentions never having learned its scripting language).