Skip to content

Instantly share code, notes, and snippets.

@Willshaw
Created May 31, 2026 17:12
Show Gist options
  • Select an option

  • Save Willshaw/6aa91dd19d2654deb8f1690b057cb75a to your computer and use it in GitHub Desktop.

Select an option

Save Willshaw/6aa91dd19d2654deb8f1690b057cb75a to your computer and use it in GitHub Desktop.
Script to easily cd into Github repos, if you keep them all tidy under a single folder like I do
# add this to your .zshrc
switch-repo() {
local github_dir="$HOME/Github"
local query="$1"
local -a repos matches
local repo name selected
if [[ ! -d "$github_dir" ]]; then
print -u2 "switch-repo: $github_dir does not exist"
return 1
fi
repos=("$github_dir"/*(/N))
if (( ${#repos} == 0 )); then
print -u2 "switch-repo: no repositories found in $github_dir"
return 1
fi
_switch_repo_choose() {
local -a options
options=("$@")
local selected_index=1
local number_buffer=""
local key sequence
local i marker display_name
if [[ ! -r /dev/tty ]]; then
print -u2 "switch-repo: interactive selection requires a terminal"
return 1
fi
while true; do
print -n "\033[H\033[J"
print "Select a repository:"
print "Use up/down + Enter, or type a number + Enter."
print
for i in {1..${#options}}; do
display_name="${options[$i]:t}"
if (( i == selected_index )); then
marker=">"
else
marker=" "
fi
printf "%s %2d) %s\n" "$marker" "$i" "$display_name"
done
if [[ -n "$number_buffer" ]]; then
print
print -n "Choice: $number_buffer"
fi
IFS= read -rs -k 1 key < /dev/tty
case "$key" in
$'\e')
IFS= read -rs -k 2 sequence < /dev/tty
case "$sequence" in
'[A')
(( selected_index-- ))
if (( selected_index < 1 )); then
selected_index=${#options}
fi
number_buffer=""
;;
'[B')
(( selected_index++ ))
if (( selected_index > ${#options} )); then
selected_index=1
fi
number_buffer=""
;;
esac
;;
$'\n'|$'\r')
if [[ -n "$number_buffer" ]]; then
if (( number_buffer >= 1 && number_buffer <= ${#options} )); then
print -n "\033[H\033[J"
REPLY="${options[$number_buffer]}"
return 0
fi
number_buffer=""
else
print -n "\033[H\033[J"
REPLY="${options[$selected_index]}"
return 0
fi
;;
[0-9])
number_buffer+="$key"
;;
$'\177'|$'\b')
number_buffer="${number_buffer[1,-2]}"
;;
q|Q)
print -n "\033[H\033[J"
return 1
;;
esac
done
}
if [[ -z "$query" ]]; then
_switch_repo_choose "${repos[@]}" || return 1
cd -- "$REPLY"
return
fi
for repo in "${repos[@]}"; do
name="${repo:t}"
if [[ "${name:l}" == *"${query:l}"* ]]; then
matches+=("$repo")
fi
done
case ${#matches} in
0)
print -u2 "switch-repo: no repositories match '$query'"
return 1
;;
1)
cd -- "$matches[1]"
;;
*)
_switch_repo_choose "${matches[@]}" || return 1
cd -- "$REPLY"
;;
esac
}
alias sr=switch-repo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment