Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions .bash_aliases
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# shellcheck shell=bash
# General System Utilities
alias c='clear'
alias gh='history | grep'
alias grephist='history | grep'
alias lt='ls --human-readable --size -1 -S --classify'
alias sha='shasum -a 256'
alias sshrestart='sudo /etc/init.d/ssh restart'
Expand Down Expand Up @@ -33,26 +33,31 @@ alias speed='speedtest-cli --server 2406 --simple'
alias dcdown='docker compose down'
alias dcup='docker compose up'
alias dexec='docker exec -it'
alias dockerclean='docker rm $(docker ps -a -q)'
alias dockerdu='docker system df'
alias dockerls='docker ps -a'
# shellcheck disable=SC2142 # $3 is awk's field variable, not a shell positional param
alias docker-rmi-untagged='docker rmi $(docker images | grep "^<none>" | awk "{print \$3}")'
alias dockerstopall='docker stop $(docker ps -a -q)'
alias dlogs='docker logs'

# Development and Git
startgit() { cd "$(git rev-parse --show-toplevel)" && git checkout master && git pull; }

# File Management
alias rmrf='rm -rf' # Use with caution
alias rmrf='rm -rf' # Use with caution
alias mkdir='mkdir -p'
alias mv='mv -i'
alias cp='cp -i'
alias chmod002='sudo chmod -R a=,a+rX,u+w,g+w'

# Searching
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'

# System Monitoring
alias top='htop' # Requires htop installed
alias top='htop' # Requires htop installed
alias df='df -h'
alias du='du -ch'

Expand All @@ -70,9 +75,9 @@ alias ....='cd ../../../'
alias .....='cd ../../../../'

# Enhanced ls
alias ll='ls -lAFh'
alias la='ls -A'
alias l='ls -CF'
alias ll='ls -lAFha --color=auto --group-directories-first'
alias la='ls -A --color=auto --group-directories-first'
alias l='ls -CF --color=auto --group-directories-first'

# Git Operations
alias gs='git status'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true


jobs:
shellcheck:
runs-on: ubuntu-latest
timeout-minutes: 5
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ repos:
hooks:
- id: shfmt
args: [--write, --indent, '2', --case-indent, --binary-next-line]
exclude: ^docker_aliases\.sh$ # zsh-specific ${(f)...} syntax is incompatible with shfmt

- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
Expand Down
5 changes: 5 additions & 0 deletions docker_aliases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ function grpdown {
services=$(_dc_group "$grp")
[[ -z "$services" ]] && { _dc_red "No services in group: $grp"; return 1; }
_dc_blue "Stopping $grp: $services"
# shellcheck disable=SC2086 # word splitting intentional — $services is space-separated list
_dc_compose stop $services "$@"
_dc_green "$grp stopped"
}
Expand All @@ -265,6 +266,7 @@ function grpup {
services=$(_dc_group "$grp")
[[ -z "$services" ]] && { _dc_red "No services in group: $grp"; return 1; }
_dc_blue "Starting $grp: $services"
# shellcheck disable=SC2086 # word splitting intentional — $services is space-separated list
_dc_compose up -d $services "$@"
_dc_green "$grp started"
}
Expand All @@ -275,6 +277,7 @@ function grplogs {
local services
services=$(_dc_group "$grp")
[[ -z "$services" ]] && { _dc_red "No services in group: $grp"; return 1; }
# shellcheck disable=SC2086 # word splitting intentional — $services is space-separated list
_dc_compose logs -f $services "$@"
}

Expand All @@ -284,6 +287,7 @@ function grpps {
local services
services=$(_dc_group "$grp")
[[ -z "$services" ]] && { _dc_red "No services in group: $grp"; return 1; }
# shellcheck disable=SC2086 # word splitting intentional — $services is space-separated list
_dc_compose ps $services "$@"
}

Expand All @@ -294,6 +298,7 @@ function grprestart {
services=$(_dc_group "$grp")
[[ -z "$services" ]] && { _dc_red "No services in group: $grp"; return 1; }
_dc_blue "Restarting $grp: $services"
# shellcheck disable=SC2086 # word splitting intentional — $services is space-separated list
_dc_compose restart $services "$@"
_dc_green "$grp restarted"
}
Expand Down
187 changes: 96 additions & 91 deletions tmux_session_picker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,105 +40,110 @@ _TMUX_SESS_PAIRS=(
_TMUX_NOTABLE_PROCS=(claude vim nvim docker node python pwsh htop)

# === Implementation ===
if command -v tmux >/dev/null 2>&1 &&
[[ $- == *i* ]] && [[ -n "$SSH_TTY" ]] && [[ -z "$TMUX" ]] && [[ -z "$NOTMUX" ]]; then
if command -v tmux >/dev/null 2>&1 \
&& [[ $- == *i* ]] && [[ -n "$SSH_TTY" ]] && [[ -z "$TMUX" ]] && [[ -z "$NOTMUX" ]]; then

# Create sessions for valid paths
for _pair in "${_TMUX_SESS_PAIRS[@]}"; do
_sess_name="${_pair%%=*}"
_sess_path="${_pair#*=}"
if [[ -d "$_sess_path" ]] && ! tmux has-session -t "$_sess_name" 2>/dev/null; then
tmux new-session -d -s "$_sess_name" -c "$_sess_path"
fi
done
# Create sessions for valid paths
for _pair in "${_TMUX_SESS_PAIRS[@]}"; do
_sess_name="${_pair%%=*}"
_sess_path="${_pair#*=}"
if [[ -d "$_sess_path" ]] && ! tmux has-session -t "$_sess_name" 2>/dev/null; then
tmux new-session -d -s "$_sess_name" -c "$_sess_path"
fi
done

# Detect notable processes in a tmux session via pstree
_tmux_procs() {
local sid=$1
local pids procs=""
pids=$(tmux list-panes -t "$sid" -F '#{pane_pid}' 2>/dev/null)
for _pid in $pids; do
local tree
tree=$(pstree -A "$_pid" 2>/dev/null) || continue
for _proc in "${_TMUX_NOTABLE_PROCS[@]}"; do
[[ "$tree" == *"$_proc"* ]] && procs="${procs:+$procs, }$_proc"
done
done
printf '%s' "${procs:--}"
}
# Detect notable processes in a tmux session via pstree
_tmux_procs() {
local sid=$1
local pids procs=""
pids=$(tmux list-panes -t "$sid" -F '#{pane_pid}' 2>/dev/null)
for _pid in $pids; do
local tree
tree=$(pstree -A "$_pid" 2>/dev/null) || continue
for _proc in "${_TMUX_NOTABLE_PROCS[@]}"; do
[[ "$tree" == *"$_proc"* ]] && procs="${procs:+$procs, }$_proc"
done
done
printf '%s' "${procs:--}"
}

# Relative time since last activity in a session
_tmux_age() {
local sid=$1
local now age_s
now=$(date +%s)
local last
last=$(tmux display-message -t "$sid" -p '#{session_activity}' 2>/dev/null) || { printf '?'; return; }
age_s=$(( now - last ))
if (( age_s < 60 )); then printf 'just now'
elif (( age_s < 3600 )); then printf '%dm ago' "$(( age_s / 60 ))"
elif (( age_s < 86400 )); then printf '%dh ago' "$(( age_s / 3600 ))"
else printf '%dd ago' "$(( age_s / 86400 ))"; fi
# Relative time since last activity in a session
_tmux_age() {
local sid=$1
local now age_s
now=$(date +%s)
local last
last=$(tmux display-message -t "$sid" -p '#{session_activity}' 2>/dev/null) || {
printf '?'
return
}
age_s=$((now - last))
if ((age_s < 60)); then
printf 'just now'
elif ((age_s < 3600)); then
printf '%dm ago' "$((age_s / 60))"
elif ((age_s < 86400)); then
printf '%dh ago' "$((age_s / 3600))"
else printf '%dd ago' "$((age_s / 86400))"; fi
}

# Session picker with loop (re-displays after creating new sessions)
while true; do
_tmux_names=()
_tmux_count=0
# Session picker with loop (re-displays after creating new sessions)
while true; do
_tmux_names=()
_tmux_count=0

printf '\n'
printf '# %-16s %s %-20s %s\n' 'SESSION' 'WIN' 'PROCESSES' 'LAST ACCESS'
printf -- '--- %-16s %s %-20s %s\n' '----------------' '---' '--------------------' '-------------------'
printf '\n'
printf '# %-16s %s %-20s %s\n' 'SESSION' 'WIN' 'PROCESSES' 'LAST ACCESS'
printf -- '--- %-16s %s %-20s %s\n' '----------------' '---' '--------------------' '-------------------'

while IFS='|' read -r _sname _swins _satt; do
(( _tmux_count++ ))
_tmux_names[$_tmux_count]="$_sname"
_label="${_sname}${_satt:+ *}"
_procs=$(_tmux_procs "$_sname")
_age=$(_tmux_age "$_sname")
printf '%-4s %-16s %3s %-20s %s\n' "${_tmux_count})" "$_label" "$_swins" "$_procs" "$_age"
done < <(tmux list-sessions -F '#{session_name}|#{session_windows}|#{?session_attached,*,}' 2>/dev/null)
while IFS='|' read -r _sname _swins _satt; do
((_tmux_count++))
_tmux_names[_tmux_count]="$_sname"
_label="${_sname}${_satt:+ *}"
_procs=$(_tmux_procs "$_sname")
_age=$(_tmux_age "$_sname")
printf '%-4s %-16s %3s %-20s %s\n' "${_tmux_count})" "$_label" "$_swins" "$_procs" "$_age"
done < <(tmux list-sessions -F '#{session_name}|#{session_windows}|#{?session_attached,*,}' 2>/dev/null)

printf '\n[1-%d] attach [n] new [s] skip\n' "$_tmux_count"
printf '> '
read -r _choice
printf '\n[1-%d] attach [n] new [s] skip\n' "$_tmux_count"
printf '> '
read -r _choice

case "$_choice" in
s|skip)
break
;;
n|new)
printf 'Session name: '
read -r _new_name
printf 'Start directory: '
read -r _new_path
_new_path="${_new_path:-$HOME}"
if [[ -n "$_new_name" ]] && [[ -d "$_new_path" ]]; then
tmux new-session -d -s "$_new_name" -c "$_new_path"
else
printf 'Invalid name or path.\n' >&2
continue
fi
;;
[0-9]*)
if (( _choice >= 1 && _choice <= _tmux_count )); then
exec tmux attach -t "${_tmux_names[_choice]}"
else
printf 'Invalid selection.\n' >&2
fi
;;
"")
;;
*)
# Try as session name directly
if tmux has-session -t "$_choice" 2>/dev/null; then
exec tmux attach -t "$_choice"
else
printf 'Unknown session: %s\n' "$_choice" >&2
fi
;;
esac
done
case "$_choice" in
s | skip)
break
;;
n | new)
printf 'Session name: '
read -r _new_name
printf 'Start directory: '
read -r _new_path
_new_path="${_new_path:-$HOME}"
if [[ -n "$_new_name" ]] && [[ -d "$_new_path" ]]; then
tmux new-session -d -s "$_new_name" -c "$_new_path"
else
printf 'Invalid name or path.\n' >&2
continue
fi
;;
[0-9]*)
if ((_choice >= 1 && _choice <= _tmux_count)); then
exec tmux attach -t "${_tmux_names[_choice]}"
else
printf 'Invalid selection.\n' >&2
fi
;;
"") ;;
*)
# Try as session name directly
if tmux has-session -t "$_choice" 2>/dev/null; then
exec tmux attach -t "$_choice"
else
printf 'Unknown session: %s\n' "$_choice" >&2
fi
;;
esac
done

unset _pair _sess_name _sess_path _tmux_names _tmux_count _sname _swins _satt _choice _new_name _new_path _label _procs _age _pid _proc
unset _pair _sess_name _sess_path _tmux_names _tmux_count _sname _swins _satt _choice _new_name _new_path _label _procs _age _pid _proc
fi
Loading