Intro:
First of all, why using ZSH instead of bash? Well, I would say that the extensibility as one of most precious assets in the UNIX/Linux community gains a lot when we dive into zshell world.
Most of the things we are going to see here also work in bash, but I cannot guarantee 100% compatibility
Refereces:
- https://www.youtube.com/watch?v=bTLYiNvRIVI
- https://github.com/ChristianChiarulli
- https://jdhao.github.io/2019/06/13/zsh_bind_keys/
Aliases
They are shorter versions of your favorite commands, for example: Open the last neovim edited file:
# Now you can type in your shell "lvim"
alias lvim='vim -c "normal '\''0"'
If you have xclip
installed then the aliases are set
(( $+commands[xclip] )) && {
alias pbpaste='xclip -i -selection clipboard -o'
alias pbcopy='xclip -selection clipboard'
}
Another useful alias to check your zsh startup time.
alias timezsh='for i in $(seq 1 10); do time zsh -i -c exit; done'
Keybindings
# pressing Ctrl+Alt+l will run our previous "alias -> lvim"
bindkey -s '^[^L' 'lvim^M'
Press Ctrl+g
to show your git status
bindkey -s '^g' 'git status --short^M'
To figure out keybindings You can manually find which key code is sent when you press a key. You can use showkey -a
to print the key codes.
Widgets
Widgets are some functions that add extra features to the shell, for example, I have one widget to open wherever I have in the clipboard into a neovim session and a shortcut/keybinding associated with that:
# Edit content of clipboard on vim
function _edit_clipboard(){
nvim -c '0pu+'
# I don't know why "xclip -i -selection clipboard -o" does not work
}
zle -N edit-clipboard _edit_clipboard
bindkey '^x^v' edit-clipboard
Autoloaded functions
I have a folder ~/.dotfiles/zsh/autoloaded
with a lot of functions that are autoloaded in the code below:
MY_ZSH_FPATH=${ZDOTDIR}/autoloaded
fpath=( $MY_ZSH_FPATH $fpath )
if [[ -d "$MY_ZSH_FPATH" ]]; then
for func in $MY_ZSH_FPATH/*; do
autoload -Uz ${func:t}
done
fi
unset MY_ZSH_FPATH
Integrate FZF
What about pressing Ctrl+o
in your shell and getting a FZF search conveyed to the nvim, and more, if you give up nothing will happen.
In my case I have restricted the range of the FZF search to my ~/.dotfiles
because there I have a wiki with almost everything I have written down for the last couple of years.
# source:https://stackoverflow.com/a/65375231/2571881
# ~/.dotfiles/zsh/autoload/vif
function vif() {
local fname
local current_dir=$PWD
cd ~/.dotfiles
fname=$(fzf) || return
vim "$fname"
cd $current_dir
}
# https://jdhao.github.io/2019/06/13/zsh_bind_keys/
bindkey -s '^o' 'vif^M'
# send a list of "oldfiles" to FZF
function old(){
[[ -f /tmp/oldfiles.txt ]] && \rm /tmp/oldfiles.txt
vim -c 'redir >> /tmp/oldfiles.txt | silent oldfiles | redir end | q'
local fname
FILES=()
# for i in $(awk '/home/ && !/man:/ {print $2}' /tmp/oldfiles.txt); do
for i in $(awk '!/man:/ {print $2}' /tmp/oldfiles.txt); do
[[ -f $i ]] && FILES+=($i)
done
fname=$(printf "%s\n" "${FILES[@]}" | awk '!a[$0]++' | fzf) || return
vim "$fname"
}
Performance improviments
There is an important type of file in zsh called zcompdump:
zcompdump files are produced to speed up the running of compinit, Which initializes the shell completion in zsh. zcompdump is used by zsh completion system to speed up completion. The lines below are meant to make your zcompdump faster.
First you have to define where will be your ZSH_COMPDUMP
file located:
# ~/.zshenv
export ZSH_COMPDUMP="${ZDOTFILES}/.zcompdump"
autoload -Uz zrecompile
autoload -Uz compinit
dump=$ZSH_COMPDUMP
# http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html
if [[ -s $dump(#qN.mh+24) && (! -s "$dump.zwc" || "$dump" -nt "$dump.zwc") ]]; then
compinit -i d $ZSH_COMPDUMP
zrecompile $ZSH_COMPDUMP
fi
compinit -C
Lazy loading
If you search about zsh performance improvements you will see some mentions about lazy loading nvm, npm and nodejs.
The actual nvm, node and so on are inside a function with their names, on those functions we call them, which means, only at first run they will be loaded.
# virtual machine management
nvm() {
unfunction $0
export NVM_DIR=~/.nvm
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
nvm "$@"
}
node() {
unfunction $0
export NVM_DIR=~/.nvm
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
node "$@"
}
npm() {
unfunction $0
export NVM_DIR=~/.nvm
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
npm "$@"
}
To make sure you have set everything ok just run:
which node
node --version
which node
You will see that when you run which node
it will show your lazy-loading function definition, after runnin node --version
the node is at this point already loaded, so, when you run which node
you will see the real node path.
Some aliases that worth mention:
# Note: most of these aliases only work on zsh because I am using `$(( $comand[] ))`
# the below alias uses pbpaste alias mentioned earlier
# and defines an anonymous function
# yt-dlp is a youtube-dl fork with improviments
alias ya='(){yt-dlp -x --audio-format mp3 -o "%(title)s.%(ext)s" $(pbpaste);}'
(( $#commands[(I)(trash|gio)] == 2 )) && alias trash='gio trash'
# https://askubuntu.com/a/63203/3798
# https://www.cnx-software.com/2016/12/16/compress-decompress-files-faster-with-lbzip2-multi-threaded-version-of-bzip2/
(( $+commands[lbzip2] )) && alias tar='tar --use-compress-program=lbzip2'
##alias upgrade='sudo pacman -Syyu'
alias upgrade='doas xbps-install -Suv'
alias xi='doas xbps-install -Sy'
alias xq='doas xbps-query -Rs'
alias xr='doas xbps-remove -R'
# Just in case you mess your vim settings use this
alias vinone="nvim -u NONE -U NONE -N -i NONE -c 'set mouse=a| syntax on | set nu'"
alias mkcd='(){mkdir -p "$1"; cd "$1"}'
# using trans (translator)
(( $+commands[trans] )) && {
alias pt='(){trans -b en:pt "$1";}'
alias en='(){trans -b pt:en "$1";}'
}
(( $+commands[perl-rename] )) && {
alias prename='perl-rename'
alias rename='perl-rename'
}
# to fix utf-8 filenames, see more here: https://stackoverflow.com/a/26941707/2571881
alias wget='wget --restrict-file-names=nocontrol'
Function to add plugins on zsh
function zsh_add_plugin() {
PLUGIN_NAME=${1##*/}
[[ -d $ZDOTDIR/plugins ]] || mkdir "$ZDOTDIR/plugins"
if [ -d "$ZDOTDIR/plugins/$PLUGIN_NAME" ]; then
zsh_add_file "plugins/$PLUGIN_NAME/$PLUGIN_NAME.plugin.zsh" || \
zsh_add_file "plugins/$PLUGIN_NAME/$PLUGIN_NAME.zsh"
else
git clone "https://github.com/$1.git" "$ZDOTDIR/plugins/$PLUGIN_NAME"
fi
}
Now you can put on your zshrc:
zsh_add_plugin "zsh-users/zsh-autosuggestions"
Making this post better
If you have any suggestions give us some comment below and we will love to talk about it!
Top comments (1)
Nice, post. If you want to boost your Zsh join us :)
z-shell.pages.dev/