Pimp my terminal
As a Linux user, I enjoy working with the terminal, and I find it an especially powerful tool. Therefore, I've spent quite a long time customizing it, and here is my definitive guide for terminal customizations.
First I thought I would only create a short post with some of the tweaks I like. But I had so many things I wanted to show that this started to become a considerably long post. So I've decided to publish it now, with as many tips as I can write, and I'll be updating it with new tips & tricks.
If you want to download my configuration files, check my `~/.dotfiles` repository. Notice that there I save my own configuration files, and some of them might not work out of the box for you, but following this guide, you'll be able to customize everything on your taste.
If you find anything from this post that could be improved, or know about other settings that may be cool enough to also include them, don't hesitate to contact me via email (daniel@drasite.com) or opening an issue on my GitHub dotfiles repository.
Index
1. Patched Fonts
I want to start talking about patched fonts as many of the customizations that I'll be explaining later may depend on them. Patched fonts consist of regular fonts to which some additional symbols have been added. That way, you can show special icons (such as your OS icon), or add new shapes to your prompt.
The most successful project is nerd-fonts, which includes many of the most used
fonts, and also a DIY patcher, in case you want a different one. My favorite
font from this project is
HACK bold
Nerd Fonts
Nerd Fonts is a project that patches developer targeted fonts with a high number of glyphs (icons). Specifically to add a high number of extra glyphs from popular 'iconic fonts' such as Font Awesome, Devicons, Octicons, and others.
2. Colorizing the terminal
2.1. Color Scheme
On the way to the definitive terminal, there is nothing that improves its looks more than customizing its color-scheme, so this will be our start point. Searching on the Internet, you'll be able to find plenty of themes, but the easiest way to apply them is using Gogh. This tool doesn't require any installation and allows you to pick your favorite colors from a long list of different prebuilt schemes.
This is the list of compatible terminals:
Gnome Terminal
, Pantheon Terminal
, Tilix
and XFCE4 Terminal
. It also works on iTerm for macOS
bash -c "$(curl -sLo- https://git.io/vQgMr)"
Flat Remix
The color-scheme that I'll be utilizing in all the screenshots is based on the color palette used for Flat Remix icon theme, which I personally love 😍.
If you also like it, you can manually copy it from the following box, or run the command below for an automatized installation (notice that the script is based on Gohg and, therefore, will only work if you are using a compatible terminal).
#8C42AB#EC0101#47D4B9#FF8A18#277FFF#D71655#05A1F7#FFFFFF
Install Flat Remix color-scheme:
bash -c "$(curl -sLo- https://git.io/JvvDs)"
2.2. Some aliases
Some of the commands you already have installed, in fact, do support color highlighting, for example: ls, grep, and diff. In case you want these commands always to have the color option enabled, you can write aliases in your terminal configuration file (.bashrc / .zshrc) to force them.
alias ls='ls --color=auto' alias grep='grep --color=auto' alias fgrep='fgrep --color=auto' alias egrep='egrep --color=auto' alias diff='diff --color=auto'
You can replace as well some common commands with newer, more colorful utilities. Just keep in mind, when using aliases for this purpose, that you may be overriding a useful tool with another one that you may not have installed. This can be especially important if you are using the same dotfiles for multiple machines, where you may not have the same packages. To avoid this, you can program the alias so that it'll be only configured in case the needed command is available. Here's the template:
# This is a template; Replace "new-command" and "alias-name" command -v new-command > /dev/null && alias alias-name='new-command ...'
2.3. Man pages
Man pages support coloring too, which makes them so much visually pleasing. For it, man
uses a bunch of variables where you can configure the color escape sequences you want to use.
export LESS_TERMCAP_mb=$'\e[1;32m' export LESS_TERMCAP_md=$'\e[1;32m' export LESS_TERMCAP_me=$'\e[0m' export LESS_TERMCAP_se=$'\e[0m' export LESS_TERMCAP_so=$'\e[01;33m' export LESS_TERMCAP_ue=$'\e[0m' export LESS_TERMCAP_us=$'\e[1;4;31m'
2.4. LS & TREE from the future
LSD
The next gen ls command.
This project is heavily inspired by the super colorls project but with some little differences. For example it is written in rust and not in ruby which makes it much faster.
Alias ls=lsd
command -v lsd > /dev/null && alias ls='lsd --group-dirs first'
Alias tree=lsd
command -v lsd > /dev/null && alias tree='lsd --tree'
2.5. TOP from the future
HTOP
htop
is an interactive system-monitor process-viewer and
process-manager. It is designed as an alternative to the Unix program top.
It shows a frequently updated list of the processes running on a computer,
normally ordered by the amount of CPU usage. Unlike top, htop provides a full
list of processes running, instead of the top resource-consuming processes.
htop uses color and gives visual information about processor, swap and memory
status. htop can also display the processes as a tree.
Alias top=htop
command -v htop > /dev/null && alias top='htop'
YTOP
Another TUI based system monitor, this time in Rust!
Alias top=ytop
command -v ytop > /dev/null && alias top='ytop --per-cpu'
YTop over light background
command -v ytop > /dev/null && alias top='ytop --per-cpu -c default-dark'
BashTop
Resource monitor that shows usage and stats for processor, memory, disks, network and processes.
Bashtop includes flat-remix and flat-remix-light themes
Alias top=bashtop
command -v bashtop > /dev/null && alias top='bashtop'
2.6. CAT & LESS from the future
BAT
A cat clone with syntax highlighting and Git integration.
Configure BAT to use the color-scheme from the terminal
alias bat='bat --theme=ansi-dark'
BAT over light background
alias bat='bat --theme=ansi-light'
Alias cat=bat
command -v bat > /dev/null && alias cat='bat --pager=never'
Alias less=bat
command -v bat > /dev/null && alias cat='bat'
2.7. LOLcat
LOLcat... 🤣️ Get rainbows and unicorns everywhere! This tool commonly appears used together with neofetch, adding a stunning rainbow effect to its output.3. Bash customizations
Bash (Bourne-again shell) is the most popular shell program and comes preinstalled on many Unix-based operating systems. It may not be the most customizable shell available, but it does support prompt customizations using color codes and escape sequences.
In case you are using this shell and want to save some of the settings provided
in this post, you can write them to your local .bashrc
file so
that they are executed before the interactive shell is launched.
3.1.Custom prompt
Bash uses a variable named PS1 to store the prompt code. This value is readen every time it needs to be written again, in order to maintain its output updated. Therefore, you can override the default prompt by setting a new string to PS1.
For bash, I usually like to have a clean prompt with some coloring, only showing the current relative directory. Here is my personal configuration:
PS1=" \[\033[1;36m\]\w >\[\033[1;34m\]>\[\033[0m\] "
But, if you prefer, you can create some more complex prompts as well:
PS1="\n \[\033[0;34m\]┌─────(\[\033[1;35m\]\u\[\033[0;34m\])─────(\[\033[1;32m\]\w\[\033[0;34m\]) \n └> \[\033[1;36m\]\$ \[\033[0m\]"
Powerline like bash prompt
In case you installed a patched font as described before, now you'll be able to use any kind of symbols for building your prompt. These fonts include many powerline symbols that allow you to fully customize your terminal without having to install any external plugin.
You can search for custom glyphs here: https://www.nerdfonts.com/cheat-sheet
OS_ICON= # Replace this with your OS icon PS1="\n \[\033[0;34m\]╭─────\[\033[0;31m\]\[\033[0;37m\]\[\033[41m\] $OS_ICON \u \[\033[0m\]\[\033[0;31m\]\[\033[0;34m\]─────\[\033[0;32m\]\[\033[0;30m\]\[\033[42m\] \w \[\033[0m\]\[\033[0;32m\] \n \[\033[0;34m\]╰ \[\033[1;36m\]\$ \[\033[0m\]"
You can even make it look like you are using Zsh with Powerlevel10k installed, just by tweaking the PS1 variable!
OS_ICON= # Replace this with your OS icon PS1="\n \[\033[0;34m\]╭─\[\033[0;31m\]\[\033[0;37m\]\[\033[41m\] $OS_ICON \u \[\033[0m\]\[\033[0;31m\]\[\033[44m\]\[\033[0;34m\]\[\033[44m\]\[\033[0;30m\]\[\033[44m\] \w \[\033[0m\]\[\033[0;34m\] \n \[\033[0;34m\]╰ \[\033[1;36m\]\$ \[\033[0m\]"
In case you want to create your own personalized prompt below you'll find all the color codes and some of the most used escape sequences to build it.
Color codes
"\[\033[0m\]" # no colors (reset) "\[\033[0;30m\]" # black "\[\033[0;31m\]" # red "\[\033[0;32m\]" # green "\[\033[0;33m\]" # yellow "\[\033[0;34m\]" # blue "\[\033[0;35m\]" # magenta "\[\033[0;36m\]" # cyan "\[\033[37m\]" # white # emphasized (bolded) colors "\[\033[1;30m\]" # black "\[\033[1;31m\]" # red "\[\033[1;32m\]" # green "\[\033[1;33m\]" # yellow "\[\033[1;34m\]" # blue "\[\033[1;35m\]" # magenta "\[\033[1;36m\]" # cyan "\[\033[1;37m\]" # white # background colors "\[\033[40m\]" # black "\[\033[41m\]" # red "\[\033[42m\]" # green "\[\033[43m\]" # yellow "\[\033[44m\]" # blue "\[\033[45m\]" # magenta "\[\033[46m\]" # cyan "\[\033[47m\]" # white
Common prompt escape sequences
View the complete list\d the date in "Weekday Month Date" format (e.g., "Tue May 26") \h the hostname \j the number of jobs currently managed by the shell \n a newline \t the current time \u the username \w the current working directory \W the basename of the current working directory \$ if the effective UID is 0, a #, otherwise a $
3.2.Completion Plugin
Bash completion is a functionality through which bash helps users type their commands faster and easier. It accomplishes that by presenting possible options when users press the tab key while typing a command.
Once you have it installed, you can enable it by adding the following lines to
your ~/.bashrc
file:
if [ -f /usr/share/bash-completion/bash_completion ]; then source /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then source /etc/bash_completion fi
3.3.Enable Globstar **
shopt -s globstar
Globstar option enables the **
pattern, which works pretty similar
to the single * but in a recursive way, so it can look in all directories and
subdirectories for matches.
When the globstar shell option is enabled, and*
is used in a pathname expansion context, two adjacent *s**
used as a single pattern will match all files and zero or more directories and subdirectories. If followed by a/
, two adjacent *s will match only directories and subdirectories.
4. Zsh customizations
Zsh is a much more configurable shell with tons of plugins and themes that will make your terminal look awesome and even improve your workflow. For this shell customization possibilities are almost limitless, so now I'll simply explain the settings and themes I use.
One key difference of Zsh is that it doesn't come with preconfigured settings as other shells like bash or fish, so I would suggest copying some of my settings as a starting point, particularly if you are installing it for the first time.
If you are using this shell and want to save some of the settings provided
in this post, you can write them to your local .zshrc
file so
that they are executed before the interactive shell is launched.
4.1. Configure Keybindings
One of the first things I quickly noticed using Zsh is that many of the keys
and shortcuts that I was used to, coming from bash, wouldn't work at all or
resulted in unexpected behaviors. Even END
and HOME
keys didn't work. So here you have all the keybinding configuration I use:
bindkey '^[[2~' overwrite-mode bindkey '^[[3~' delete-char bindkey '^[[H' beginning-of-line bindkey '^[[1~' beginning-of-line bindkey '^[[F' end-of-line bindkey '^[[4~' end-of-line bindkey '^[[1;5C' forward-word bindkey '^[[1;5D' backward-word bindkey '^[[3;5~' kill-word bindkey '^[[5~' beginning-of-buffer-or-history bindkey '^[[6~' end-of-buffer-or-history
4.2. Misc settings
This is only a list of my personal settings, just in case they help you:
unsetopt NO_BEEP unsetopt NO_MATCH setopt AUTO_CD setopt BEEP setopt NOMATCH setopt NOTIFY setopt INC_APPEND_HISTORY setopt SHARE_HISTORY setopt HIST_EXPIRE_DUPS_FIRST setopt HIST_IGNORE_DUPS setopt HIST_IGNORE_ALL_DUPS setopt HIST_FIND_NO_DUPS setopt HIST_SAVE_NO_DUPS setopt HIST_REDUCE_BLANKS setopt HIST_VERIFY setopt HIST_BEEP setopt INTERACTIVE_COMMENTS setopt MAGIC_EQUAL_SUBST setopt NULL_GLOB autoload compinit && compinit
4.3. Powerlevel10K
POWERLEVEL9K:
There are a number of Powerline ZSH themes available, now. The developers of this theme focus on four primary goals:
- Give users a great out-of-the-box configuration with no additional configuration required.
- Make customization easy for users who do want to tweak their prompt.
- Provide useful segments that you can enable to make your prompt even more effective and helpful. We have prompt segments for everything from unit test coverage to your AWS instance.
- Optimize the code for execution speed as much as possible. A snappy terminal is a happy terminal.
POWERLEVEL10K is a fast reimplementation of POWERLEVEL9K with even some extra features. It even maintains the same variable names, so you won't need to change your configuration if you are coming from POWERLEVEL9k.
One thing that I love from POWERLEVEL10K is that, if you have yet no configuration, when you launch it the first time, it will show you a guide asking your preferences. During this process, it shows multiple examples, making it so much easier to customize.
You can always launch the configuration wizard by running p10k configure
s=' ' # fix too wide icons POWERLEVEL9K_MODE=nerdfont-complete POWERLEVEL9K_SHORTEN_STRATEGY=truncate_beginning POWERLEVEL9K_PROMPT_ADD_NEWLINE=true POWERLEVEL9K_PROMPT_ON_NEWLINE=true # <- Set this to false for simgle line prompt POWERLEVEL9K_RPROMPT_ON_NEWLINE=true POWERLEVEL9K_SHORTEN_DIR_LENGTH=2 POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='${P9K_CONTENT} $(whoami | grep -v "^root\$")' POWERLEVEL9K_OS_ICON_BACKGROUND=red POWERLEVEL9K_OS_ICON_FOREGROUND=white POWERLEVEL9K_ROOT_INDICATOR_BACKGROUND=black POWERLEVEL9K_ROOT_INDICATOR_FOREGROUND=red POWERLEVEL9K_SSH_BACKGROUND=white POWERLEVEL9K_SSH_FOREGROUND=blue POWERLEVEL9K_FOLDER_ICON= POWERLEVEL9K_DIR_BACKGROUND=blue POWERLEVEL9K_DIR_FOREGROUND=black POWERLEVEL9K_DIR_WRITABLE_BACKGROUND=black POWERLEVEL9K_DIR_WRITABLE_FOREGROUND=red POWERLEVEL9K_VCS_CLEAN_FOREGROUND=black POWERLEVEL9K_VCS_CLEAN_BACKGROUND=green POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=black POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=yellow POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=white POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=black POWERLEVEL9K_VCS_UNTRACKED_ICON=● POWERLEVEL9K_VCS_UNSTAGED_ICON=± POWERLEVEL9K_VCS_INCOMING_CHANGES_ICON=↓ POWERLEVEL9K_VCS_OUTGOING_CHANGES_ICON=↑ POWERLEVEL9K_VCS_COMMIT_ICON=$s POWERLEVEL9K_STATUS_VERBOSE=false POWERLEVEL9K_STATUS_VERBOSE=false POWERLEVEL9K_STATUS_OK_IN_NON_VERBOSE=true POWERLEVEL9K_EXECUTION_TIME_ICON=$s POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=0 POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND=black POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=blue POWERLEVEL9K_COMMAND_BACKGROUND_JOBS_BACKGROUND=black POWERLEVEL9K_COMMAND_BACKGROUND_JOBS_FOREGROUND=cyan POWERLEVEL9K_TIME_ICON= POWERLEVEL9K_TIME_FORMAT='%D{%I:%M}' POWERLEVEL9K_TIME_BACKGROUND=black POWERLEVEL9K_TIME_FOREGROUND=white POWERLEVEL9K_RAM_ICON= POWERLEVEL9K_RAM_FOREGROUND=black POWERLEVEL9K_RAM_BACKGROUND=yellow POWERLEVEL9K_VI_MODE_FOREGROUND=black POWERLEVEL9K_VI_COMMAND_MODE_STRING=NORMAL POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=green POWERLEVEL9K_VI_VISUAL_MODE_STRING=VISUAL POWERLEVEL9K_VI_MODE_VISUAL_BACKGROUND=blue POWERLEVEL9K_VI_OVERWRITE_MODE_STRING=OVERTYPE POWERLEVEL9K_VI_MODE_OVERWRITE_BACKGROUND=red POWERLEVEL9K_VI_INSERT_MODE_STRING= POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL='\uE0B2' POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL='\uE0B0' POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX='%F{blue}╭─' POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX='%F{blue}╰%f ' POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon root_indicator ssh dir dir_writable vcs) POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(vi_mode status command_execution_time background_jobs time ram) ZLE_RPROMPT_INDENT=0 # ---- load POWERLEVEL10K --- source /usr/share/zsh-theme-powerlevel10k/powerlevel10k.zsh-theme
4.4. Useful plugins
For Zsh many people usually installs some kind of configuration framework such
as "Oh My Zsh", which can be really useful (I guess...), but I prefer to do it
manually. It isn't something complicated, you just need to install the plugin
you want and then source
it in your local ~/.zshrc
config file. Speaking about the installation, you can do it manually, just
downloading the plugin and copying it to the directory you want, or using a package
manager, which commonly installs the plugin inside
/usr/share/zsh/plugins/
.
Autosuggestions
Fish-like fast/unobtrusive autosuggestions for Zsh.
It suggests commands as you type based on history and completions.
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
Syntax highlighting
This package provides syntax highlighting for the shell Zsh. It enables highlighting of commands whilst they are typed at a Zsh prompt into an interactive terminal. This helps in reviewing commands before running them, particularly in catching syntax errors.
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#ccc' source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
5. Other customizations
To finalize this post, I'll be dropping here some scripts and settings that help me optimize my workflow.
Useful functions
Find shortcut
find <str>
Similar to locate
, this function allows you to search files
recursively, but it only shows matches placed within the current directory. The
script overrides the original find command adding this useful shortcut, which
can be used by writing find
followed by the string you want to
use. Vanilla find
command needs more than one parameter to be able to
return useful results, so this modification won't alter its functionality,
therefore, you will still be able to use it normally as well.
find() { if [ $# = 1 ] then command find . -iname "*$@*" else command find "$@" fi }
LazyGit
lazygit "<Message>"
In case you use git
, this function will save you some extra
commands. Running it will preview and add to git's cache all the changes from
the current directory. Following this, they will be committed using the
provided message and pushed to the current branch.
lazygit() { git status . git add . git commit -m "$@" git push origin HEAD }
Advanced lazygit
Similar to the previous function, this git shortcut executes git add, commit, and push and additionally supports commit amends. It handles the rebase process for you so that you don't have to clean the branch after applying a fixup.lazygit() { USAGE=" lazygit [OPTION]... GIT but lazy Options: --fixup <commit> runs 'git commit --fixup <commit> [...]' --amend runs 'git commit --amend --no-edit [...]' -f, --force runs 'git push --force-with-lease [...]' -h, --help show this help text " COMMIT='' MESSAGE='' AMEND=0 FORCE=0 while [ $# -gt 0 ] do key="$1" case $key in --fixup) COMMIT="$2" shift # past argument shift # past value ;; --amend) AMEND=1 shift # past argument ;; -f|--force) FORCE=1 shift # past argument ;; -h|--help) echo "$USAGE" return 0 ;; *) MESSAGE="$1" shift # past argument ;; esac done git status . git add . if [ $AMEND -eq 1 ] then git commit --amend --no-edit elif [ "$COMMIT" != '' ] then git commit --fixup "$COMMIT" GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "$COMMIT^" else git commit -m "$MESSAGE" fi git push origin HEAD $([ "$FORCE" -eq 1 ] && echo '--force-with-lease') }
Git graphical log
glog() { setterm -linewrap off git --no-pager log --all --color=always --graph --abbrev-commit --decorate \ --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' | \ sed -E \ -e 's/\|(\x1b\[[0-9;]*m)+\\(\x1b\[[0-9;]*m)+ /├\1─╮\2/' \ -e 's/(\x1b\[[0-9;]+m)\|\x1b\[m\1\/\x1b\[m /\1├─╯\x1b\[m/' \ -e 's/\|(\x1b\[[0-9;]*m)+\\(\x1b\[[0-9;]*m)+/├\1╮\2/' \ -e 's/(\x1b\[[0-9;]+m)\|\x1b\[m\1\/\x1b\[m/\1├╯\x1b\[m/' \ -e 's/╮(\x1b\[[0-9;]*m)+\\/╮\1╰╮/' \ -e 's/╯(\x1b\[[0-9;]*m)+\//╯\1╭╯/' \ -e 's/(\||\\)\x1b\[m (\x1b\[[0-9;]*m)/╰╮\2/' \ -e 's/(\x1b\[[0-9;]*m)\\/\1╮/g' \ -e 's/(\x1b\[[0-9;]*m)\//\1╯/g' \ -e 's/^\*|(\x1b\[m )\*/\1⎬/g' \ -e 's/(\x1b\[[0-9;]*m)\|/\1│/g' \ | command less -r +'/[^/]HEAD' setterm -linewrap on }
Git settings
Git configuration file is placed in~/.gitconfig
[color] # colorize output diff = auto status = auto branch = auto interactive = auto ui = true pager = true [credential] # cache credentials helper = cache --timeout=3600