Fish

The file present in ~/.config/fish/config.fish is the configuration file for the fish shellopen in new window. It contains custom functions, environment variables and abbreviations.

Just in case, we might sometimes need to declare the fish function fish_title as true, so let’s do so.

function fish_title
    true
end

Fish from within Emacs

I sometimes call fish from within Emacs, with M-x ansi-term. In this case, the variable TERM needs to have the value eterm-color.

if test -n "$EMACS"
    set -x TERM eterm-color
end

Global variables

An important thing to do is to load all variables from my ~/.profile file (which you can find hereopen in new window). The foreign-envopen in new window plugin comes in handy:

fenv source ~/.profile

Direnvopen in new window is a really neat tool that allows you to load the content of a dotenv file as environment variables. Its installation is quite simple for fish.

direnv hook fish | source

Since I don’t really have a better place on this website to put it, here is my direnv configuration located at $HOME/.config/direnv/direnv.toml.

[global]
load_dotenv = true

Development

Finally, some development packages require the PKG_CONFIG_PATH to be set, so let’s do so.

set -gx PKG_CONFIG_PATH /usr/local/lib/pkgconfig/ $PKG_CONFIG_PATH

Tramp remote access

When accessing from a remote machine our computer from Emacs, tramp needs a precise shell appearance: a simple $ followed by a space after which to put the commands it needs to execute, and nothing else. Due to this, let’s deactivate and redefine some functions defining the appearance of fish.

if test "$TERM" = "dumb"
    function fish_prompt
        echo "\$ "
    end
    function fish_right_prompt; end
    function fish_greeting; end
    function fish_title; end
end

Regular fish shell appearance

Now, there is only one function I modify when it comes to the appearance of fish when I’m the one using it: the fish_greeting function. I just want it empty.

function fish_greeting; end

For my fish prompt, I use starshipopen in new window, a shell-agnostic prompt. Let’s load it:

starship init fish | source

Setting up external tools

Starship configuration

As mentioned above, starship is a shell-agnostic prompt, written in Rust and which can be configured separately from the shell. I decided to configure it here though, since fish is the only shell I use which is compatible with starship.

First I’ll modify the default format variable, removing the modules I don’t need.

format = """
$username\
$hostname\
$shlvl\
$singularity\
$kubernetes\
$directory\
$vcsh\
$git_branch\
$git_commit\
$git_state\
$git_metrics\
$git_status\
$hg_branch\
$docker_context\
$package\
$cmake\
$dart\
$deno\
$lua\
$nodejs\
$python\
$rlang\
$rust\
$scala\
$zig\
$memory_usage\
$env_var\
$custom\
$cmd_duration\
$line_break\
$jobs\
$battery\
$time\
$status\
$shell\
$character"""

I want starship to be able to detect Lisp files, be it CommonLisp or EmacsLisp. Unfortunately, it seems nerd-font doesn’t have any symbol for either language, so I’m just using a lambda character.

[custom.lisp]
extensions = ["lisp", "el"]
symbol = "λ "
style = "bold green"

Finally, let’s disable all modules I don’t need.

[cobol]
disable = true
[dotnet]
disable = true
[elixir]
disable = true
[elm]
disable = true
[erlang]
disable = true
[golang]
disable = true
[helm]
disable = true
[java]
disable = true
[julia]
disable = true
[kotlin]
disable = true
[nim]
disable = true
[ocaml]
disable = true
[perl]
disable = true
[php]
disable = true
[pulumi]
disable = true
[purescript]
disable = true
[red]
disable = true
[ruby]
disable = true
[swift]
disable = true
[terraform]
disable = true
[vlang]
disable = true
[vagrant]
disable = true
[nix_shell]
disable = true
[conda]
disable = true
[aws]
disable = true
[gcloud]
disable = true
[openstack]
disable = true
[crystal]
disable = true

Loading zoxide

zoxide is a smarter cd command. I actually have it replace cd entirely through the --cmd flag you see below…

zoxide init --cmd cd fish | source

Abbreviations

Abbreviations are a great way to keep correctly track of which commands are run in the shell without polluting the history of the shell with obscure commands. When typing an abbreviation, fish will replace it with replace it with its expanded equivalent. Below are some of the abbreviations I use. Be aware some of them that invoke GUI programs can be invoked through devour which will make the terminal disappear while the program runs, and once the GUI program exists the terminal window will come back.

System monitoring

Here I have some abbreviations which are quite useful when performing some system monitoring. With df, we can get an overview of our filesystem usage, while with diskspace we get some more precise information. meminfo is a call to free with sane defaults, and similar to meminfo, we also have gpumeminfo to get a quick look at the memory-related logs of our X session. I also declared cpuinfo an alias of lscpu in order to keep consistent with meminfo. pscpu gives us information on what the CPU is running right now, and pscpu10 limits that to the top 10 threads. Similarly, psmem gives us information on the memory usage of the current threads, and psmem10 only the ten most important threads in terms of memory usage.

abbreviationcommand
dfdf -H
diskspacesudo df -h | grep -E “sd|lv|Size”
dudu -ch
meminfofree -m -l -t
gpumeminfogrep -i –color memory /var/log/Xorg.0.log
cpuinfolscpu
pscpups auxf | sort -nr -k 3
pscpu10ps auxf | sort -nr -k 3 | head -10
psmemps auxf | sort -nr -k 4
psmem10ps auxf | sort -nr -k 4 | head -10
abbr df 'df -H'
abbr diskspace 'sudo df -h | grep -E "sd|lv|Size"'
abbr du 'du -ch'
abbr meminfo 'free -m -l -t'
abbr gpumeminfo 'grep -i --color memory /var/log/Xorg.0.log'
abbr cpuinfo 'lscpu'
abbr pscpu 'ps auxf | sort -nr -k 3'
abbr pscpu10 'ps auxf | sort -nr -k 3 | head -10'
abbr psmem 'ps auxf | sort -nr -k 4'
abbr psmem10 'ps auxf | sort -nr -k 4 | head -10'

System management (packages and services)

I added some of these abbreviations due to how often I have to write the whole thing.

Package management

The first command is remove which removes a package from my system, as well as its dependencies no longer needed. p. pacman’s or paru’s. This is why I simply type purge. And if I want to simply search among the pacman repos, I can type search. Otherwise, if I want to include AUR results, I’ll use paru.

abbreviationcommand
removesudo pacman -Rsc
purgeparu -Sc
abbr remove 'sudo pacman -Rsc'
abbr purge 'paru -Sc'

Service management

I don’t have the muscle memory of systemctl. So instead, I simply type c when I want to do something user service related. And if I want to manipulate system services, I can instead type a simple capital S.

abbreviationcommand
ssystemctl
susersystemctl –user
abbr s 'systemctl'
abbr suser 'systemctl --user'

Development

A good amount of these commands are development related, especially when it comes to compilation or Docker.

CMake

I have the following abbreviations to quickly run CMake and create a configuration for debug or release profiles.

abbreviationcommand
cdebugcmake -DCMAKE_BUILD_TYPE=Debug
creleasecmake -DCMAKE_BUILD_TYPE=Release

Here is the corresponding fish configuration:

abbr cdebug 'cmake -DCMAKE_BUILD_TYPE=Debug'
abbr crelease 'cmake -DCMAKE_BUILD_TYPE=Release'

Docker

And of course, when it comes to Docker Compose, I don’t have time to write the full command, so I use these instead.

abbreviationcommand
dcdocker-compose
dcbdocker-compose build
dcddocker-compose down
dcldocker-compose logs
dclfdocker-compose logs -f
dcpdocker-compose pull
dcrdocker-compose run –rm
dcudocker-compose up
dcubdocker-compose up –build
dcuddocker-compose up -d
dcudbdocker-compose up -d –build

Here is the corresponding fish configuration:

abbr dc 'docker-compose'
abbr dcb 'docker-compose build'
abbr dcd 'docker-compose down'
abbr dcl 'docker-compose logs'
abbr dclf 'docker-compose logs -f'
abbr dcp 'docker-compose pull'
abbr dcr 'docker-compose run --rm'
abbr dcu 'docker-compose up'
abbr dcub 'docker-compose up --build'
abbr dcud 'docker-compose up -d'
abbr dcudb 'docker-compose up -d --build'

Text editors

I greatly prefer to use Emacsclient as my main text editor; Emacs has basically all I need. So, it’s only normal I have an abbreviation to launch a new instance of it. If launched in the terminal, I’ll usually want Emacs to be displayed in CLI mode and not in GUI mode, otherwise I would invoke it with my WM’s shortcut. In case we want to launch Emacs in GUI mode anyway, egui is available too.

abbreviationcommand
eemacsclient -c -n
eguidevour emacsclient -c

Here is the corresponding fish configuration:

abbr e 'emacsclient -c -n'
abbr egui 'devour emacsclient -c'

Compilation

By default, I set clang, clang++, gcc and g++ to the latest standard and with the -Wall flag activated.

abbreviationcommand
clangclang -Wall
clang++clang++ -Wall
g++g++ -Wall -std=c++20
gccgcc -Wall -std=c18

Here is the corresponding fish configuration:

abbr clang 'clang -Wall'
abbr clang++ 'clang++ -Wall'
abbr g++ 'g++ -Wall -std=c++20'
abbr gcc 'gcc -Wall -std=c18'

Git

And let’s face it: we all at one point just wanted to commit our code without thinking about the message, to just get over with it. Don’t worry, I got you covered.

abbreviationcommand
randcommitgit commit -m (curl -s whatthecommit.com/index.txtopen in new window)

Here is the corresponding fish configuration:

abbr randcommit 'git commit -m (curl -s whatthecommit.com/index.txt)'

LaTeX

Yes, although I use org-mode, I still have some use for LaTeX, especially when it comes to PDF exports of my org files. Hence, why I use the LaTeX package manager. It is recommended to use tllocalmgr instead of tlmgr, but I can never remember the command, and the latter is faster to type, so time for an abbreviation. Same goes for texhash which must be run as sudo.

abbreviationcommand
tlmgrtllocalmgr
texhashsudo texhash

Here is the corresponding fish configuration:

abbr tlmgr 'tllocalmgr'
abbr texhash 'sudo texhash'

Some security measures

Some commands can be quite dangerous when not used properly, which is why I added default flags and options in order to get warnings before things get ugly. The -i and -I add prompts in case we might not want to do what we asked the shell to do. Notice lns which creates symlinks, rmd which removes directories, rmf which forces deletion, and rmdf which forces the delition of a directory. Notice also the --preserve-root which will prevent me from accidentally removing the root folder. I added the same option to chgrp, chmod, and chown.

abbreviationcommand
cpcp -i
rsyncrsync -Pa –progress
lnln -i
lnsln -si
mvmv -i
rmrm -Iv
rmdrm –preserve-root -Irv
rmdfrm –preserve-root -Irfv
rmfrm –preserve-root -Ifv
chgrpchgrp –preserve-root -v
chmodchmod –preserve-root -v
chownchown –preserve-root -v

Here is the corresponding fish configuration:

abbr cp 'cp -i'
abbr rsync 'rsync -Pa --progress'
abbr ln 'ln -i'
abbr lns 'ln -si'
abbr mv 'mv -i'
abbr rm 'rm -Iv'
abbr rmd 'rm --preserve-root -Irv'
abbr rmdf 'rm --preserve-root -Irfv'
abbr rmf 'rm --preserve-root -Ifv'
abbr chgrp 'chgrp --preserve-root -v'
abbr chmod 'chmod --preserve-root -v'
abbr chown 'chown --preserve-root -v'

Typos

Let’s admit it, we all make typos from time to time in the shell, and some are recurrent enough we make abbreviations or aliases of the correct command. Well, I have some of my abbreviations which were make exactly because of this. Sometimes for some reason, my brain makes me write clean instead of clear. So, let’s just replace the former by the latter. I’m also very bad at typing exit. And sometimes I suck at typing htop.

abbreviationcommand
cleanclear
exiexit
extiexit
hotphtop

Here is the corresponding fish configuration:

abbr clean 'clear'
abbr exi 'exit'
abbr exti 'exit'
abbr hotp 'htop'

Misc

Finally, some miscellaneous abbreviations that don’t really fit into any of the above categories.

Media

Here you will find various commands related to media in general. The first one is a command to play some chillhop from the Lofi Girl YouTube channelopen in new window’s livestream.

abbr chill 'mpv --force-window=no --no-video "https://www.youtube.com/watch?v=jfKfPfyJRdk" &'

When it comes to MPV, I do not want to force it to open a graphical window if for example I want to listen to an audio file. I also do not want any border on that window. So, I declared this abbreviation.

abbr mpv 'mpv --no-border --force-window=no'

When I want to download a song from YouTube, I’ll just use the command flac videoIdentifier to get it through youtube-dl.

abbr flac 'youtube-dl -x --audio-format flac --audio-quality 0 -o "~/Music/%(uploader)s/%(title)s.%(ext)s"'

Some sane default options for nsxivopen in new window. This includes playing GIFs and not displaying the filename below. Nsxiv will also open in full-screen and will fit the displayed image to the frame. It will also output to stdout the selected files in case I want to pipe them to another program.

abbr nsxiv 'nsxiv -abfos f'

The following abbreviation is here to launch software with my Nvidia GPU.

abbr nv 'env __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia'

Finally, let’s declare the following abbreviation that will launch an MPV instance displaying my webcam:

abbr webcam 'devour mpv --demuxer-lavf-format=video4linux2 --demuxer-lavf-o-set=input_format=mjpeg av://v4l2:/dev/video0 --profile=low-latency --untimed'

Sudo

First, I make it so that sudo comes with the -A switch in order to call my custom graphical script for getting my password (see askpass). I also made it so please is an equivalent to sudo -A as a joke.

abbr please 'sudo -A'

History

I find it more intuitive and faster to just write hist instead of history, so let’s declare that.

abbr hist history

Compression

It seems it’s just like many other people, but I cannot for the life of me remember the syntax of tar. So, I made the following abbreviations, and one day hopefully, after seeing the abbreviations’ expansion over and over I’ll remember the command like I did for the abbreviation of remove (see Package management).

abbreviationcommand
compresstar -czf
untartar -xvzf
abbr compress 'tar -czf'
abbr untar 'tar -xvzf'

exa

abbreviationcommand
ezaeza -halg@ –group-directories-first –git
lsleza -halg@ –group-directories-first –git
abbr eza 'eza -halg@ --group-directories-first --git'
abbr lsl 'eza -halg@ --group-directories-first --git'

Network Management

First, we have just nmcli with sane default options, that is a pretty output with colours.

abbr nmcli 'nmcli -p -c auto'

NordVPN

Next, we have some NordVPN-related shortcuts. The first one is a simple abbreviation to nordvpn. The second one is a shortcut to connect to a server, and to disconnect from the current server. I also have a couple of shortcuts to quickly connect to some preselected countries, mainly France, Germany, Japan and the US.

abbreviationcommand
nnordvpn
ncnordvpn c
ndnordvpn d
ncfnordvpn c France
ncgnordvpn c Germany
ncjnordvpn c Japan
ncunordvpn c United_States
abbr n 'nordvpn'
abbr nc 'nordvpn c'
abbr nd 'nordvpn d'
abbr ncf 'nordvpn c France'
abbr ncg 'nordvpn c Germany'
abbr ncj 'nordvpn c Japan'
abbr ncu 'nordvpn c United_States'

Wget

By default, continue a download that was interrupted.

abbr wget 'wget --hsts-file="$XDG_DATA_HOME/wget-hsts" -c'

Last thing before we’re done

For some reason, Fish began searching for packages when I enter a command name wrong. For instance, if I type vim, I get something like this:

$ vim
fish: Unknown command: vim
usr/bin/vim is owned by extra/gvim 8.2.2653-1
usr/bin/vim is owned by extra/vim 8.2.2653-1

But I don’t want that, it slows down my shell. So, in order to fix that, we need the following lines:

function fish_command_not_found
    __fish_default_command_not_found_handler $argv
end

Ta-dah! No more package suggestions from fish!

I also have some private abbreviations I don’t want people to know about that I store in a separate configuration file.

source $HOME/.config/fish/private.fish