o/uutalk - Useful Utilities
Today I want to talk about a few utilities to supercharge your shell workflows!
zsh
- a modern shell replacement for Bash with better tab-completion, complex globbing and pluginsripgrep
- a fastergrep
with friendlier defaultsfd
- a fasterfind
with friendlier defaultsexa
- a prettierls
with friendlier defaultsbat
- a prettiercat
with syntax highlighting, line numbers, git highlights and paginghub
- enables GitHub.com features like creating pull requests from the command linefzf
- easily fuzzily filter any list (files, directories, git branches, etc.)
Install all of these tools in a single command (zsh
& fzf
benefit from additional configuration that we'll discuss):
brew install zsh ripgrep fd exa bat hub fzf
See the Cut for time section for a few more helpful utilities that I couldn't squeeze into this talk!
🐚 Shell - zsh
If you work at Opendoor view the up-to-date living guide here
A superset of Bash with modern bells and whistles. These include better tab-completion, more complex globbing support, a plugin system, and more!
zsh
will be the default shell in macOS Catalina so might as well start getting used to it 😃
Set up:
brew install zsh
sudo sh -c "echo $(command -v zsh) >> /etc/shells"
chsh -s "$(command -v zsh)"
Don't have time to discuss everything that's different but I do want to highlight tab completion. We need to add two lines to our .zshrc
to turn this on (the onboarding tutorial has an option to do this). Add the following lines to ~/.zshrc
:
autoload -Uz compinit
compinit
Now source it to use our changes - source ~/.zshrc
. Okay, let's walk through two (by no means comprehensive) examples of zsh
tab completion vs bash
tab completion:
ls -<TAB>
# bash does nothing
# zsh displays flags
git add <TAB>
# bash displays files in the directory
# zsh displays unstaged files
# additional note: repeatedly hitting Tab cycles through
# options in zsh, in bash it just redisplays all options
Plugins add functionality to zsh
. There are many different plugin managers, I use zplugin which is the fastest plugin manager I've found and supports loading plugins asynchronously.
Run the installation script:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zplugin/master/doc/install.sh)"
The install script should add the below lines to your ~/.zshrc
. If it doesn't, add them manually.
source "$HOME/.zplugin/bin/zplugin.zsh"
autoload -Uz _zplugin
(( ${+_comps} )) && _comps[zplugin]=_zplugin
To install the three plugins I'll discuss add the following snippet to ~/.zshrc
:
# ref - search zsh-autosuggestions
# http://zdharma.org/zplugin/wiki/GALLERY/#plugins
zplugin ice wait lucid atload'_zsh_autosuggest_start'
zplugin light zsh-users/zsh-autosuggestions
# note: any plugins that define widgets the syntax highlighting might need to
# color (such as `zsh-autosuggestions`) must be loaded prior
# ref - search fast-syntax-highlighting
# http://zdharma.org/zplugin/wiki/GALLERY/#plugins
zplugin ice wait lucid atinit"ZPLGM[COMPINIT_OPTS]=-C; zpcompinit; zpcdreplay"
zplugin light zdharma/fast-syntax-highlighting
# prompt
# ref - https://github.com/romkatv/powerlevel10k#zplugin
zplugin ice depth=1
zplugin light romkatv/powerlevel10k
- Context aware prompt - display context of current directory (e.g. git status, executable versions, virtual environments, etc.)
Install by adding the following line to
~/.zshrc
-zplugin light romkatv/powerlevel10k
- Syntax highlighting - highlight your commands as you type them
Install by adding the following lines to
~/.zshrc
:zplugin ice wait lucid atinit"ZPLGM[COMPINIT_OPTS]=-C; zpcompinit; zpcdreplay" zplugin light zdharma/fast-syntax-highlighting
- History autocompletions - suggest previous commands from history as you type
Install by adding the following lines to
~/.zshrc
:zplugin ice wait lucid atload'_zsh_autosuggest_start' zplugin light zsh-users/zsh-autosuggestions
This plugin benefits from configuring a few shortcuts:
# Ctrl-e accepts until end of line (same as right arrow) bindkey '^e' autosuggest-accept # Ctrl-Space accepts until end of line and immediately execute bindkey '^ ' autosuggest-execute # Ctrl-w accepts next word bindkey '^w' forward-word # count only alphanumeric characters as part of a word WORDCHARS=
🔎 ripgrep
A faster and generally more user friendly replacement for grep
. It searches recursively by default, respects .gitignore
(and .ignore
) files, and skips hidden and binary files.
Here's a writeup of more details on the tool by it's creator including detailed benchmarks.
Here is a heads up comparison on an arbitrary query:
# takes ~30 seconds w/o `--exlude-dir` (this exclude also wouldn't cover all
# files ignored by ripgrep, e.g. go build files, python virtualenvironments, etc.)
grep -r TradeInStep . --exclude-dir=node_modules --color -n
rg TradeInStep
Here are some usage examples:
# recursively search current directory for pattern
rg pattern
# include .gitignored and hidden files
rg -uu pattern
# search for whole word matches in files matching the given glob
rg -w @types/lodash -g 'package.json'
🔎 fd
A simpler, faster find
(fd
is to find
what ripgrep
is to grep
). Skips hidden directories, respects .gitignore
files, colorized terminal output, smart case (case-insensitive by default, case sensitive if pattern includes a capital).
Here is a heads up comparison on an arbitrary query:
find . -iname '*TradeInStep*' -not -path '*/node_modules/*'
# or
fd TradeInStep
A few other usage examples:
# search for files matching pattern (no more `find . -iname '*PATTERN*'`)
fd pattern
# include hidden and ignored files
fd --hidden --no-ignore pattern
💎 exa
A prettier ls
that comes with friendlier defaults and adds extra contextual information (like git info with --git
).
Add the following line to ~/.zshrc
to alias ls
to exa
: alias ls=exa
Note: if you do alias
ls
toexa
you can always use regularls
with/bin/ls
🦇 bat
A prettier cat
with syntax highlighting, line numbers, git highlights and paging.
🐙🐈 hub
Augments git
when using GitHub (the tool itself is developed by GitHub). hub
supports PR creation, easier repo cloning, viewing CI status & more!
hub
is a strict superset of git
and GitHub suggests aliasing git
to hub
for easier usage (anecdotally I've had git
aliased to hub
for over a year now without any issues).
By far the most useful feature of hub
for me is pull request creation:
# `-p` pushes branch if not pushed, `-o` opens PR in browser, `-c` copies PR link to clipboard
# first `-m` specifies PR title, second `-m` specific PR body, `-l` adds the given label (can
# specify multiple separated by commas - `-l label-one,label-two`), `-r` adds the given reviewer
# (again can specify multiple separated by commas - `-r username-one,username-two`)
hub pull-request -poc -m 'title here' -m 'body here' -l merge-when-green -r bmalehorn
Here a few other usage examples:
# clone a repository without the full url (omit the username for your own repos)
hub clone username/repo_name
# create a repository on GitHub (optional organization and repo name)
hub create organization/repo_name
# compare the current branch to master (or given base branch)
hub compare <optional-base-branch>
# view status of GitHub CI checks
hub ci-status -v
# open repo in browser
hub browse
🌸🚀 fzf
A fantastic fuzzy finder for fun coding and my personal favorite of these utilities!
fzf
enables interactive fuzzy filtering of a list of strings (file paths, lines of code, git commits, etc.) with previews!
To set up fzf
let's run it's setup script:
$(brew --prefix)/opt/fzf/install
We now have completions and key bindings. First, let's talk completions:
# fuzzily cd to a directory
cd **<Tab>
# kill processes
kill -9 <Tab>
# fuzzily open file in your editor
vim **<Tab>
Next, key bindings. The setup script adds three bindings. These can be triggered at any time, not just the start of a shell command!
Ctrl-r
- shell historyCtrl-t
- all files under the current directoryAlt-c
- cd to selected directory under the current one
Finally, I have my own configuration that adds a few other handy shortcuts along with configuring previews. This can be added by copying and pasting the config from the fzf.zsh
file in this gist to the end of your ~/.zshrc
or by running the command below which curls the file down and appends it.
# install preview dependencies (can use the older versions
# (e.g. `grep` instead of `rg`, `find` instead of `fd`) of
# each of these if you prefer by editing `~/.zshrc`)
brew install bat exa fd
# append fzf.zsh from this gist to ~/.zshrc
curl https://gist.githubusercontent.com/nathanshelly/4b7020d09d413cab823914b06162145a/raw/de3a42bb78be18336ffc0c81878028c94894f72d/fzf.zsh >> ~/.zshrc
Here are the new shortcuts this config adds:
Ctrl-p
- open selected file(s) in$EDITOR
Alt-h
- list commitsAlt-f
- list unstaged filesAlt-r
- list branches (local & remote)
- Why you should be using fzf
- Key bindings for
git
withfzf
- fzf for the win
- Turn your fzf into a live REPL
fasd
- quickly access files and folders based on frequency and recency of accesstldr
- a cliff-notes man pagetmux
- a terminal multiplexer to replace endless terminal tabstrash
- replacement forrm
that moves files to the trash so you can recover them
Install all of these tools in a single command - brew install fasd tldr tmux trash
💨 fasd
Quickly access files and folders from anywhere on your machine based on frequency and recency of access ("frecency").
v def conf => vim /some/awkward/path/to/type/default.conf
j abc => cd /hell/of/a/awkward/path/to/get/to/abcdef
m movie => mplayer /whatever/whatever/whatever/awesome_movie.mp4
o eng paper => xdg-open /you/dont/remember/where/english_paper.pdf
vim `f rc lo` => vim /etc/rc.local
vim `f rc conf` => vim /etc/rc.conf
See the repo for more details including setup instructions! Note: the README doesn't mention using Homebrew but it's there - brew install fasd
📖 tldr
A cliff notes man
page. Provides quick high-level documentation of a tool with some examples.
Run on tar
:
🗑 trash
A replacement for rm
. Files deleted with trash
are moved to the system Trash folder so you can easily recover them if you accidentally delete something. Bonus, it works on files and directories (no need to ever type -r
again).
🤹 tmux
Ripped shamelessly from the tmux
README:
tmux is a terminal multiplexer.
It enables a number of terminals to be created, accessed, and controlled from a single screen. tmux may be detached from a screen and continue running in the background, then later reattached.
See any of these guides for a great primer on why you might want to use it and how to get started!