Lightweight, clean, simple. This is what I’m looking for in a zsh configuration
Starting the shell
First, let’s review the shell login and interaction
Interaction
The shell may or may not interact. Normal startup requires interaction if you type a command and wait for it to return, but no interaction is required if you run the script directly
echo $-
determines if there is an interaction, each letter represents an attribute. i
is for interactive (interactive)
The interactive shell will have PROMPT, so there will be a PS1
variable, and you can use the PS1
variable to determine if it is interactive or not.
Login
login shell, bash by shopt
, zsh by setopt
. (zsh’s echo $-
can also determine if you are logged in). Remember that setopt
is the command that sets all of zsh’s features with setopt
, unsetopt noxxxor
unsetopt`.
Open terminal and ssh are both logged-in shells by default. directly executing bash
/ zsh
is a non-login shell, specify the ---login
argument. The su
command is also non-login by default, specify the su -
or su -l
argument. -
and -l
are exactly the same
The combination of interactive and login permutations can be divided into four cases.
- non-interactive non-login
- non-interactive login
- Interactive non-login
- Interactive login
They also load different configuration files. To simplify the process, just ignore the other files and use only bashrc
or zshrc
. Delete all the others (.bash_profile
, .bash_login
, .zprofile
, .zlogin
all of them), which will definitely read the .bashrc
or .zshrc
file
motd
Anyone familiar with Linux will be familiar with the full name of motd, Message Of The Day
Put the contents in /etc/motd
and display the contents every time you log in
The motd itself is plain text, and traditionally motd is only plain text. Of course, we can do something similar to motd by displaying something when the shell starts executing commands
For example, use cowsay
to display a welcome message (put this command in the shell’s configuration file)
Themes and configuration framework
If you don’t use any theme, you will have to deal with the $PS1
variables yourself, and there are four variables in PS
. Consider the complexity of setting them up yourself. The preferred option is of course to use the big boys’ configuration
zsh is basically the same as it was decades ago due to its history, but nowadays zsh has a lot of very powerful features. It’s just that the default is not to turn on
oh-my-zsh
The most famous configuration framework for zsh. Configuring zsh can even be said for oh-my-zsh and non-oh-my-zsh
automatically sets the color section, just enable it to override the ugly as hell default color scheme. The default configuration is perfect
A lot of useful functions and themes are integrated (personally I recommend the ys
theme), more extreme users will even use the ramdom theme and choose one randomly each time you turn it on to ensure freshness
oh-my-zsh has a lot of stuff to manage. oh-my-zsh’s various plugins are basically full of aliases. it is recommended not to use any of them
prezto
An alternative to oh-my-zsh, or an alternative to it. It’s a bit lighter than oh-my-zsh.
zimfw
Use ruby’s erb
stencil engine to compile the final configuration file.
Configure the enabled plugins in zimrc
, then compile to produce the ~/.zshrc
file. You’ll have to recompile every time you make a change, but that’s not a big deal.
By default, the git plugin will be enabled, so be careful to disable it (I recommend disabling it), it’s all git aliases.
grml-zsh-config
The default zsh configuration for Grml OS, which is a Debian-based Linux distribution. It is mainly designed for live CDs
I like grml’s configuration, it’s simple and lightweight. This is the new age default. grml does not include the ability to manage plugins. It is a pure zshrc
file
grml has several themes built in.
The grml zsh configuration is very flexible, and the default grml theme supports vsc (git show current branch) which allows you to customize the various items displayed. For example, to make prompt display two lines like this.
powerlevel series
Themes for the zsh version of the powerline series
powerlevel9k is an extremely complex theme that will definitely catch your eye, or should be called the most powerful zsh theme on the planet. The most distinctive thing about this theme is probably the integration with various programming environments, even recognizing some web frameworks, VM environments of programming languages
Later on, someone developed powerlevel10k, which is just like powerlevel9k, but with good performance.
pure
This is a very nice theme. It calls itself prompt, but it should be classified as a theme. Because for the shell, the topic is prompt
Separate prompt
It’s too complicated to implement a complex prompt in the shell, so let’s just put a layer on the outside. Then came a new idea. Put an interactive shell on top of the old shell. I’ve taken it upon myself to call it “detached prompt”. The detached prompt is powerful, though. But do we really need such a powerful prompt?
Liquid Prompt
Liquid Prompt was probably the first to do this, making prompt a separate component. Configuration management is independent of other functions, and supports bash and zsh
spaceship-prompt
This is a prompt optimized for zsh, but still a pure shell implementation, so you could say that spaceship directly raises the complexity of prompt by one level. Towards a separate prompt for front and back ends
starship
Just a prompt, using a rust implementation that is exceptionally fast and efficient. This acts as an interactive front-end, with a shell as the back-end. It supports most shells, and has moved towards a completely separate prompt.
oh-my-posh
It was originally written specifically for powershell, but was later rewritten in golang to make it a separate prompt for the front and back ends, and you can specify a different back end
Plugin Manager
I personally don’t use this plugin manager, it just makes it easier to toss back and forth, but it’s not right to toss shell configuration every day
antigen
This is the official zsh plugin management tool, and it’s absolutely clean. It’s a pure package manager. Oh no, it has special adaptations for oh-my-zsh and prezto
antibody
A package manager written in golang. As you can see from the name, it’s a counterpart to antigen
zplug
A vim-plug-like plugin manager
zgen
A lightweight plugin manager with only 500 lines of code
zinit
is a plugin manager implemented in C, with very high performance and probably the fastest. zplugin and zinit are one project, zplugin is the previous name.
Like zimfw, you can compile plugins to run faster. Unlike zimfw, no configuration is provided, this is just the plugin manager and compiler.
zsh plugins
fish has a lot of useful features, code highlighting, auto-suggestions. fish has a lot of interactive features that are already implemented in zsh
zsh-users family
zsh-users is an official zsh repository with several great plugins that are integrated into basically all zsh configuration frameworks:
- zsh-syntax-highlighting (code highlighting)
- zsh-autosuggestions (auto-suggestions)
- zsh-history-substring-search (prefix search)
And for example: zsh-users/zsh-apple-touchbar My MBP doesn’t have a touchbar so I won’t comment on it
zinit series
- fast-syntax-highlighting (high performance code highlighting)
- history-search-multi-word (enhanced version of
Crtl-R
)
Plugins written by the author of zinit, can be used here to replace the zsh-users series
thefuck
to correct spelling errors. There seems to be a lot of people who use a plugin, I don’t use this and don’t recommend it.
I’d like to know what the mentality of people who use this plugin is fuck, fuck, fuuuu…
autojump
According to the use of habits to automatically jump to the directory, he will maintain a database to record which directories are usually used
Custom Functions
MacOS needs to set the default shortcuts, Crtl + left/right arrow
is occupied by Mission Control function
Change the Crtl + left/right arrow
shortcut in System Preferences > Keyboard > Shortcuts
, otherwise the ability to jump a word will be lost. I changed it to Crtl + Command + left/right arrow
. I remember that this is the default key for switching virtual desktops in Deepin Linux
Turn off flow control
The shell and terminal (iTerm2 ignores this feature) need to support both to see the effect, most terminals are supported. shell is enabled by default
This is an old feature, historically (and still is in some terminals), Ctrl-S
pauses output while Ctrl-Q
continues. From today’s point of view, this feature is basically useless. It also takes up two shortcut keys
The default setting in many frameworks is not to disable flowcontrol
. Only oh-my-zsh is set to be disabled in the configuration framework
Let’s turn it off: setopt noflowcontrol
push-line
I don’t know how to describe this function, but oh-my-zsh has a Ctrl-Q
shortcut that saves the current input, then executes a new command, and releases the saved content afterwards. This feature is very useful.
Many setups and frameworks will set Ctrl-Q
to push-line
.
|
|
But push-line
can’t handle the here doc case.
You can set it to push-line-or-edit
and it will handle here docs.
|
|
push-line
and push-line-or-edit
are useful, and are built-in features of zsh. They are not enabled by default, and there are many other features in zsh that are not enabled by default. Before writing a new feature, it’s best to check man zshzle
to see if it’s available.
Quick sudo
Perhaps you will often sudo !!
to use sudo
to execute the previous command.
sudo
is used a lot, so let’s customize a shortcut.
|
|
This way you can quickly add sudo
directly with Ctrl-S
, and automatically remove sudo
if it is preceded by sudo
.
grml comes with a similar configuration, but it only supports adding sudo
, so there is a difference between the way I changed it and grml.
Now the grml zsh configuration is the same as mine grml/zshrc#119
Command Complementary Load Optimization
The kubectl
command is typical, this patch file is very large, with tens of thousands of lines
The official documentation puts this in .zshrc
, which is a very poor way of writing performance
|
|
Generating a file and putting it in $FPATH
would be a better option.
|
|
Put this in the zsh configuration file.
Or use the Lazyload method, where you define a placeholder function first and then load it on input. But $FPATH
is already a lazyload. I’ve always thought it was a mistake to use Lazyload for completion (I’ve seen people use it this way, feel free to argue me down).
fzf and shell
fzf provides a shortcut to the shell, you need to enable this feature yourself.
Three binding shortcuts are provided
Ctrl-R
Enhanced history searchCrtl-T
fuzzy path selectionAlt-C
fuzzy path jumping
Complement function provides **
and then press <TAB>
syntax, use fzf to select complement
Crtl-T
is actually a zsh default shortcut, the fuzzy path selection function provided by fzf is too infrequently used, so here it is set back to the default shortcut.
|
|
For Apple computers, the Alt-C
shortcut has to be handled
Recent directories
Remember Elvish’s Crtl-L
list selection to jump to the most recent directory?
Use fzf to implement one, and since the Crtl-L
shortcut is already occupied, use ALT-X
|
|
Navigation mode (Navigation mode)
Elvish Crtl-N
shortcut to start the navigation mode. Similar to ranger or nnn’s tui to select a directory inside
This feature can be adapted with ranger or nnn. Both projects provide examples, but I prefer ranger, nnn is faster. There is also a very lean implementation of a pure shell vifon/deer
-
ranger
1 2 3 4 5 6 7 8 9 10 11 12
# Fork from: https://github.com/ranger/ranger/blob/master/examples/shell_automatic_cd.sh ranger_cd() { local temp_file="$(mktemp -t "ranger_cd.${USERNAME}")" ranger --choosedir="$temp_file" -- "${@:-$PWD}" if chosen_dir="$(cat -- "$temp_file")" && [ -n "$chosen_dir" ] && [ "$chosen_dir" != "$PWD" ]; then cd -- "$chosen_dir" fi rm -f -- "$temp_file" } # This binds Ctrl-N to ranger_cd: bindkey -s '^N' 'ranger_cd\n'
-
nnn
Some packages include this script as well, such as Archlinux, so you can just
source
.MacOS homebrew does not provide a
quitcd
script, so you need to set it up yourself.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
# Frok from: https://github.com/jarun/nnn/blob/master/misc/quitcd/quitcd.bash_zsh nnn_cd () { # Block nesting of nnn in subshells if [ -n $NNNLVL ] && [ "${NNNLVL:-0}" -ge 1 ]; then echo "nnn is already running" return fi # The default behaviour is to cd on quit (nnn checks if NNN_TMPFILE is set) # To cd on quit only on ^G, remove the "export" as in: # NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd" # NOTE: NNN_TMPFILE is fixed, should not be modified export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd" # Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn # stty start undef # stty stop undef # stty lwrap undef # stty lnext undef nnn "$@" if [ -f "$NNN_TMPFILE" ]; then . "$NNN_TMPFILE" rm -f "$NNN_TMPFILE" > /dev/null fi } bindkey -s '^N' 'nnn_cd\n'
-
lf
If you think
ranger
is slow written in python and you don’t likennn
. Then you can trylf
written by golang.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Frok from: https://github.com/gokcehan/lf/blob/master/etc/lfcd.sh lfcd () { tmp="$(mktemp)" lf -last-dir-path="$tmp" "$@" if [ -f "$tmp" ]; then dir="$(cat "$tmp")" rm -f "$tmp" if [ -d "$dir" ]; then if [ "$dir" != "$(pwd)" ]; then cd "$dir" fi fi fi } bindkey -s '^N' 'lfcd\n'
-
hunter
This is a command line file manager written in Rust. There is no way to link with the shell yet, maybe in the future this feature will be available.
Variables
We’ve certainly all seen this written before
There are more paths, let’s unify them
|
|
VISUAL
and EDITOR
, will give priority to VISUAL
and will use EDITOR
only when it is not available.
Performance
This is several orders of magnitude faster than oh-my-zsh, which is slower than hell.
|
|
What configuration do I use
The pictures in this article don’t say much, I’ve selected some visually appealing plugins for the pictures, in fact, my personal configuration is very lean. The most practical configurations don’t look anything high-end in the pictures. The practical configuration that really works looks pretty much the same as the default
Good prompt.
- current path
- git branch (should be optional, as a software developer, this is necessary)
- The result of the last command execution
$?
- If it’s a server, it’s better to show the hostname and user
- personal preference, preference for two lines
- Try not to have special fonts and special characters (ascii characters)
I use the default configuration of zimfw on my main machine MPB, plus a little bit of self-defined functions, and the default configuration of grml on all other machines.
If you are interested in my configuration you can come here: a-wing/dotfiles#zsh