The Terminal Experience
I have a list of things i want in my terminal to make it useful and it all is
centered around navigation.
What I Want
- sessions that last even when i close my terminal
- multiple running sessions, and these sessions are based on directory
- "tabs" within a session
- navigate to any session by directory name "instantly"
- navigate to any session by directory with fuzzy find
- run scripts or whatever programs i want when navigating to a directory
I Choose Tmux
I personally use tmux + ghostty, though i hear wezterm, another terminal emulator, you can emulate pretty much every way I use tmux. I have not used wezterm so i cannot speak much about it. Zellij has similar experience but more modern
Quick Notes
- About 3 years ago I did the first version of Dev productivity and some things about my setup has changed, and parts have remained the same. After 3 years, this is still my most useful script I have ever created. But i have added some significant improvements to the script
Installing TMUX
Platform | Install Command |
---|---|
Arch Linux | pacman -S tmux |
Debian or Ubuntu | apt install tmux |
Fedora | dnf install tmux |
RHEL or CentOS | yum install tmux |
macOS (using Homebrew) | brew install tmux |
macOS (using MacPorts) | port install tmux |
openSUSE | zypper install tmux |
Base Config
Here is the basic config that will make life easier. This will ensure that you have a similar experience to me
set -g default-terminal "tmux-256color"
set -s escape-time 0
set -g base-index 1
# optional -- i like C-a not C-b (pure preference)
unbind C-b
set-option -g prefix C-a
bind-key C-a send-prefix
# vi key movement for copy/pasta mode
set-window-option -g mode-keys vi
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
# <WHERE YOUR TMUX CONF GOES> = XDG_CONFIG_HOME/tmux/tmux.conf
# <WHERE YOUR TMUX CONF GOES> = ~/.tmux.conf
bind r source-file <WHERE YOUR TMUX CONF GOES> \; display-message "tmux.conf reloaded"
Install it via our dev-env!
We can even use our fancy new dev-env script to install it!
Lets navigate tmux
Lets go through some basic commands about tmux so you can see how they work with just usage. I will show you the ones I use and some that I don't use
ource /home/theprimeagen/.tmux-sessionizer what is prefix key
just using -* commands
- creating window
- detaching
- attaching
- showing all running sessions
- killing pane / window / session
- creating and navigating splits
- tmux is controlled by a config
A bit of customization
I like to navigate my tmux panes like i navigate my vim windows
lets try this out:
# Add to your tmux.conf file
bind -r h select-pane -L
bind -r j select-pane -D
bind -r k select-pane -U
bind -r l select-pane -R
Based on my previous 5 points, only two have been met.
- sessions that last even when i close my terminal
- "tabs" within a session
It turns out that tmux
is also scriptable! And its quite fantastic
The Session API
A target
is a tuple of <session_name>[:<widx>|<wname>[.<pane_idx>]]
tmux new-session -s <sname> -n <initial wname> -d[etach]
tmux list-sessions
tmux attach-session -t <target>
tmux has-session -t <target> # don't forget -t vs -t=
tmux switch-client -t <target>
The Window API
tmux new-window -n <name> [-t session:window_index]
tmux list-windows [-t session]
tmux select-window -t session:[window_idx | window_name].[pane_idx]
Other fun apis
tmux send-keys -t <target> "text" [ctrl keys,...]
Lets start with our first script
From my original points, we still have 4 points left to address to create the "perfect" navigation system for the terminal
What I Want
sessions that last even when i close my terminal- multiple running sessions, and these sessions are based on directory
"tabs" within a session- navigate to any session by directory name "instantly"
- navigate to any session by directory with fuzzy find
- run scripts or whatever programs i want when navigating to a directory
Lets Address Point 6 First
This is one of the easier points to address (a bit weird)
6. run scripts or whatever programs i want when navigating to a directory
- opens and creates the configuration you want for a project ** gimp **
Opener script
#!/usr/bin/env bash
if [[ -x ./.ready-tmux ]]; then
./.ready-tmux
elif [[ -x ~/.ready-tmux ]]; then
~/.ready-tmux
fi
clear
Thats pretty cool?
That was pretty awesome that we can create all the windows / splits we want with a simple script (don't worry, it'll get a lot better)
Progress
We have checked off another component of what I consider a great terminal experience
But we still have a few left
- multiple running sessions, and these sessions are based on directory
- navigate to any session by directory name "instantly"
- navigate to any session by directory with fuzzy find
Detour time
FZF is an incredible tool for fuzzy finding. Its not just for finding directories. You can fuzzy find on anything you pass in and is often used within text editors.
I will add fzf to my scripts
dev-env/runs/libs
# ... other libs i install ...
git clone git@github.com:junegunn/fzf.git $HOME/personal/fzf
$HOME/personal/fzf/install
dev-env/env/.zsh_profile
## All that sweet sweet fzf
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
Execute
Make sure i only run my libs script
run --dry libs
Run my lib script
run libs
Copy all of my files over
dev-env
Test run
try pressing C-r
(Control + r) and it should bring up a beautiful fuzzy find
comparatively to your standard C-r
from the terminal
Playing with FZF
input
➜ dev-prod-2 git:(main) ✗ echo "1\n2\n3" | fzf
output
3
2
▌ 1
3/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>
Lets solve the last problems
- multiple running sessions, and these sessions are based on directory
- navigate to any session by directory name "instantly"
- navigate to any session by directory with fuzzy find
Some notes
We don't want to search every directory on the file system, we want to have some sort of subset.
We want to navigate based on the results of FZF
CODE TIME!!
Lets start this MF script (MF = Mother FZF):
- get a selected directory from fzf.
- create a clean tmux session name
Expected Code
#!/usr/bin/env bash
selected=$(find ~/personal -mindepth 1 -maxdepth 1 -type d | fzf)
if [[ -z "$selected" ]]; then
exit 0
fi
selected_name=$(basename $selected | tr ".,: " "____")
echo "selected!! $selected -- selected_name $selected_name"
Lets make the script gooooood
- if there is, navigate to that session
- if there is not, create that session and navigate to it
Expected Code
#!/usr/bin/env bash
selected=$(find ~/personal -maxdepth 1 -mindepth 1 -type d | fzf)
if [[ -z "$selected" ]]; then
exit 0
fi
selected_name=$(basename $selected | tr ".,: " "____")
switch_to() {
if [[ -z "$TMUX" ]]; then
tmux attach-session -t $selected_name
else
tmux switch-client -t $selected_name
fi
}
if tmux has-session -t="$selected_name"; then
switch_to
else
tmux new-session -ds $selected_name -c $selected
switch_to
fi
Remember our previous scriptedy-tmux
It would be nice if we could combine our two scripts...
Next Expected Script
#!/usr/bin/env bash
selected=$(find ~/personal -maxdepth 1 -mindepth 1 -type d | fzf)
if [[ -z "$selected" ]]; then
exit 0
fi
selected_name=$(basename $selected | tr ".,: " "____")
switch_to() {
if [[ -z "$TMUX" ]]; then
tmux attach-session -t $selected_name
else
tmux switch-client -t $selected_name
fi
tmux send-keys -t $selected_name "ready-tmux"
tmux send-keys -t $selected_name "welcome to fem"
}
if tmux has-session -t="$selected_name"; then
switch_to
else
tmux new-session -ds $selected_name -c $selected
switch_to
fi
How do i execute this?
- we copy it to a $PATH location
- we can create a tmux shortcut to execute it