feat: zsh widgets, tmux session handling

This commit is contained in:
2026-02-13 12:00:02 +00:00
parent 61bf7b366b
commit 6461654bff
2 changed files with 72 additions and 12 deletions

View File

@@ -29,18 +29,20 @@ by invoking the `setup-new` script directly via `curl`:
## Keyboard shortcuts ## Keyboard shortcuts
Custom zsh widgets bound in `.zshrc`:
| Key | Mnemonic | Action | | Key | Mnemonic | Action |
|-----|----------|--------| |-----|----------|--------|
| `^A` | **A**ll commits | Git log browser with diff preview |
| `^B` | **B**ranch | Git branch checkout with log preview | | `^B` | **B**ranch | Git branch checkout with log preview |
| `^E` | **E**dit | Find and edit file in `$EDITOR` | | `^E` | **E**dit | Find and edit file in `$EDITOR` |
| `^F` | **F**ind | Find in files (rg + fzf), open at line | | `^F` | **F**ind | Find in files (rg + fzf), open at line |
| `^G` | **G**o remote | SSH/codespace connect *(local only)* | | `^G` | **G**o remote | SSH/codespace connect *(local only)* |
| `^J` | **J**ump | Zoxide directory jump | | `^J` | **J**ump | Zoxide directory jump |
| `^N` | **N**avigate | Tmux session create/switch | | `^K` | **K**ommands | Command help lookup (tldr/man) |
| `^N` | **N**avigate | Tmux session create/attach |
| `^O` | **O**pen | Open repo/PR/issues/actions in browser | | `^O` | **O**pen | Open repo/PR/issues/actions in browser |
| `^P` | **P**roject | Switch to workspace project | | `^P` | **P**roject | Switch to workspace project |
| `^R` | **R**everse | Fuzzy search command history *(fzf built-in)* |
| `^S` | **S**ession | Browse & resume Copilot CLI sessions | | `^S` | **S**ession | Browse & resume Copilot CLI sessions |
| `^X` | e**X**ecute | Process manager (fzf + kill) |
| `^Y` | **Y**ank stash | Browse git stashes with diff preview | | `^Y` | **Y**ank stash | Browse git stashes with diff preview |

View File

@@ -91,18 +91,62 @@ _dots_load_keybindings() {
zle -N _dots_find_in_files_widget zle -N _dots_find_in_files_widget
bindkey '^F' _dots_find_in_files_widget bindkey '^F' _dots_find_in_files_widget
# Ctrl+N: tmux session # Ctrl+A: git log browser
_dots_tmux_widget() { _dots_git_log_widget() {
if [[ -z "$TMUX" ]]; then local commit
tmux new-session </dev/tty commit="$(git log --oneline --color --decorate -50 2>/dev/null \
| fzf --ansi --no-sort \
--preview 'git show --color=always {1}' \
--preview-window='right:60%')" || { zle reset-prompt; return; }
BUFFER="git show ${commit%% *}"
zle reset-prompt
zle accept-line
}
zle -N _dots_git_log_widget
bindkey '^A' _dots_git_log_widget
# Ctrl+K: command help lookup
_dots_help_widget() {
local cmd
cmd="$(print -l ${(ko)commands} | fzf --preview 'tldr {1} 2>/dev/null || man -P cat {1} 2>/dev/null | head -80')" \
|| { zle reset-prompt; return; }
if command -v tldr &>/dev/null; then
BUFFER="tldr ${(q)cmd}"
else else
local session BUFFER="man ${(q)cmd}"
session="$(tmux list-sessions -F '#{session_name}' 2>/dev/null \
| fzf --preview 'tmux list-windows -t {} -F " #{window_index}: #{window_name} #{pane_current_command}"')" \
|| { zle reset-prompt; return; }
tmux switch-client -t "$session"
fi fi
zle reset-prompt zle reset-prompt
zle accept-line
}
zle -N _dots_help_widget
bindkey '^K' _dots_help_widget
# Ctrl+N: tmux session
_dots_tmux_widget() {
[[ -n "${CODESPACES:-}" ]] && { zle reset-prompt; return; }
local sessions
sessions="$(tmux list-sessions -F '#{session_name}' 2>/dev/null)"
if [[ -z "$sessions" ]]; then
BUFFER="tmux new-session"
elif [[ -n "$TMUX" ]]; then
local session
session="$({ echo '+ new session'; echo "$sessions"; } \
| fzf --preview 'case {} in "+ new session") echo "Create a new tmux session";; *) tmux list-windows -t {} -F " #{window_index}: #{window_name} #{pane_current_command}";; esac')" \
|| { zle reset-prompt; return; }
if [[ "$session" == "+ new session" ]]; then
BUFFER="tmux new-session -d && tmux switch-client -n"
else
BUFFER="tmux switch-client -t ${(q)session}"
fi
else
local session
session="$(echo "$sessions" \
| fzf --preview 'tmux list-windows -t {} -F " #{window_index}: #{window_name} #{pane_current_command}"')" \
|| { zle reset-prompt; return; }
BUFFER="tmux attach -t ${(q)session}"
fi
zle reset-prompt
zle accept-line
} }
zle -N _dots_tmux_widget zle -N _dots_tmux_widget
bindkey '^N' _dots_tmux_widget bindkey '^N' _dots_tmux_widget
@@ -219,6 +263,20 @@ for line in sys.stdin:
zle -N _dots_copilot_session_widget zle -N _dots_copilot_session_widget
bindkey '^S' _dots_copilot_session_widget bindkey '^S' _dots_copilot_session_widget
# Ctrl+X: process manager
_dots_process_widget() {
local proc
proc="$(ps -eo pid,user,%cpu,%mem,command 2>/dev/null \
| fzf --header-lines=1 --preview 'ps -p {1} -o pid,ppid,stat,start,time,command 2>/dev/null' \
--preview-window='down:4:wrap')" || { zle reset-prompt; return; }
local pid="${${proc## #}%% *}"
BUFFER="kill $pid"
zle reset-prompt
zle accept-line
}
zle -N _dots_process_widget
bindkey '^X' _dots_process_widget
# Ctrl+Y: git stash browser # Ctrl+Y: git stash browser
_dots_stash_widget() { _dots_stash_widget() {
local stash local stash