- homebrew compatibility on Ubuntu
- Python environments
- Vars, expansions, extensions, suffixes
- For loops
- Test exit status
- Temporary variable setting uses
- VS code
- Aliases, custom commands
- Writing functions
Not the aquatic creatures, but rather the
which is not as shit as the other ones.
I’m gradually transitioning to
fish, after accidentally losing a lot of precious data due to a quirk in
bash syntax. Long boring story.
It’s time for new, exciting, different stupid errors.
fish has a strong fanbase and an opinionated design.
If you dislike those design opinions, at least you might appreciate it has a
healthy degree of sarcasm in said opinions, which sarcasm is sorely absent from
the drearily earnest nerdview of your typical gnu.org
You might also hold that having any kind of principled opinion is better than the
design-by-accumulation-of-tradition-cruft which structures command-line
- Ubuntu users can get an updated fish PPA.
- or, macOS/Linux: install using homebrew
Modifying the PATH
This is the most confusing thing in fish for me. It is worth reading tutorials, e.g.
To add a path, use the utility command fish_add_path
To remove a path
set PATH (string match -v /usr/local/bin $PATH)
Adding a path? Say it’s
set -gx PATH /usr/local/bin $PATH
set -U fish_user_paths /usr/local/bin $fish_user_paths
Removing a path?
set -gx PATH (string match -v /usr/local/bin $PATH)
🏗 explain the difference between
will depend upon me understanding how the content of
$PATH magically replenishes
itself and the difference between “universal” and ”global” variables.
Modifying any settings with GUI
Put commands in
Extremely traditional config
one of the things I like about fish is how there are sane defaults and I don’t need to have any config. Which works for me, because I have no interest in learning fish syntax. I just want a helpful shell, I don’t want to have to know yet another language, and I deeply resent fish every time it doesn’t process the line of posix sh I paste into it from a wiki...
After jumping between several different shells and rewriting my
.profile a number of different times for a number of different shells, I came up with a way to decouple my environment config from the shell I use. My environment always works, I don’t have to learn fish or any other syntax.
I set `/bin/dash` as my login shell. the first line of my `~/.profile` is `ENV=$HOME/.shinit; export ENV.` In any interactive shell, dash executes `~/.shinit`, which contains one line:` exec /usr/bin/fish`.
Every config item I need from my shell goes into
~/.profile, written in easy, conventional posix sh- and I still get to use fish as my interactive shell, without having to go through the trouble of adopting its config to my system.
Optiligence notes that this minor alteration should work.
eval (ssh-agent -c)
Alternatively, see danhper/fish-ssh-agent or ivakyb/fish_ssh_agent.
wget https://gitlab.com/kyb/fish_ssh_agent/raw/master/functions/fish_ssh_agent.fish -P ~/.config/fish/functions/
Append next line to
You really need to verify that
https://gitlab.com/kyb/fish_ssh_agent/raw/master/functions/fish_ssh_agent.fish is not anything malicious; this is high security code.
To be more secure, we can get a known-good (IMO) version thusly:
wget https://github.com/ivakyb/fish_ssh_agent/raw/e09c21501c20730634ab80d6bc9329335eabe065/functions/fish_ssh_agent.fish -P ~/.config/fish/functions/
You can hack fish. Popular plugin management systems exist also. AFAICT a passable default is oh my fish
curl -L https://get.oh-my.fish | fish
fisher seems to be around too?
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
It also handles
omf plugins, apparently.
omf manual is brusque.
See a helpful blogpost.
I am currently running omf, but since it intrusively changed my prompt I am grumpy at it.
However, I got a better prompt, spacefish.
omf install spacefish
It does need the wacky powerline fonts.
sudo apt-get install fonts-powerline
There are various useful plugins that are not purely cosmetic; For example fzf adds fuzzy history search. z does recency/frequency-based directory navigation.
homebrew compatibility on Ubuntu
Since I use
fish shell as my default but ubuntu automatically executes the
bash startup script
.profile on login,
I ran into the following errors when it tried to run the
fish init in a
bash process when I used homebrew:
bash: set: -g: invalid option set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] bash: set: -g: invalid option ...
This is maybe related to an intermittently reported bug in homebrew.
The fix that worked for me was to change the automatically-added line in
.profile to be
eval $(SHELL=bash /bin/brew shellenv)
and to add
eval (env SHELL=fish /bin/brew shellenv)
If I used
virtualenv on python I would need
Or switch to native python3
which is more or less the same thing but works better and doesn’t support python 2.
But if you need to support python 2 at this stage it’s because you are
in some weird enterprise environment with horrid legacy software, so hopefully you can farm this problem out to the tech support team?
Either that or you are barred from using
fish by policy and this is not a problem.
Using anaconda python
You need to do some extra setup to use conda with fish.
~/miniconda3/bin/conda init fish
Or, for older versions,
~/miniconda3/ with the output of
conda info --root
if you used a non-standard install location)
Vars, expansions, extensions, suffixes
Wildcards are minimal, just
**, and brace expansion,
For more sophisticated string processing, one defines custom functions (which I never actually do) or use classic subcommands which I do all the time.
for file in (ls *.html) mv $file (basename $file .html).txt end
or expansion via
string, which is harder to
for file in (ls *.html) mv $file (string replace -r "\.html\$" .txt $file) end
while true echo "Loop forever" end
Test exit status
if test $status -eq 0 echo yeah end
To simply execute the second command if the first succeeded the command you want is and, which is hard to google for:
../bin/something.sh foo; and cp foo ~/Dropbox/
Temporary variable setting uses
env FOO=BAR baz.sh
Aliases, custom commands
How to use nvm, rbenv, pyenv, goenv... with the fish shell
Deleting history interactively:
while true if test (count (jobs)) -lt 5 dostuff & else wait # to wait for _any_ job end end
NB that only allocates 5 jobs at a time. Nifty.
No comments yet. Why not leave one?