diff --git a/session/_session b/session/_session index c5df710..a0bb176 100644 --- a/session/_session +++ b/session/_session @@ -34,7 +34,7 @@ __session_hosts() { } _arguments \ - '(- *)'{-h,--help}'[Show usage information]' \ - '(- *)'{-p,--project}'[Create or attach to a session for a project in ~/Projects]:project:__session_projects' \ - ':session:__session_sessions' \ - ':host:__session_hosts' + '(- : *)'{-h,--help}'[Show usage information]' \ + '(-H --host)'{-H,--host}'[Create or attach to the session on a remote host via ssh]:host:__session_hosts' \ + '(-p --project :)'{-p,--project}'[Create or attach to a session for a project in ~/Projects]:project:__session_projects' \ + '(-p --project)1:session:__session_sessions' diff --git a/session/session.plugin.zsh b/session/session.plugin.zsh index 2d8feb1..5b9b644 100644 --- a/session/session.plugin.zsh +++ b/session/session.plugin.zsh @@ -1,28 +1,97 @@ session() { - if [[ "$1" == "" ]]; then - echo "usage: session [-h] [] - session -p " - elif [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then - echo "usage: session [-h] [] - session -p + local usage="usage: session [-h] [-H ] + session [-H ] -p " + local name="" project="" host="" -Create or attach to a tmux session by name either locally on on a remote host + while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + echo "$usage + +Create or attach to a tmux session by name either locally or on a remote host via ssh. With -p create or attach to a session for , a path in ~/Projects with the prefix removed, which must be a git repository. The session is named after the project and holds a home window plus a window at the project, named after its default branch. + +With -H create or attach to the session on via ssh, where is +either a hostname or a shortname defined in ~/.config/session. Combined with -p +the project is resolved on , not locally. Not allowed inside a tmux +session. " - elif [[ "$1" == "-p" ]] || [[ "$1" == "--project" ]]; then - local project=${2%/} - if [[ "$project" == "" ]]; then - echo "$fg[red]error:$reset_color missing argument" + return 0 + ;; + -p|--project) + if [[ "$2" == "" ]]; then + echo "$fg[red]error:$reset_color missing argument" + return 1 + fi + project=${2%/} + shift 2 + ;; + -H|--host) + if [[ "$2" == "" ]]; then + echo "$fg[red]error:$reset_color missing argument" + return 1 + fi + host=$2 + shift 2 + ;; + -*) + echo "$fg[red]error:$reset_color unknown option: $1" + return 1 + ;; + *) + if [[ "$name" != "" ]]; then + echo "$fg[red]error:$reset_color invalid argument: $1" + return 1 + fi + name=$1 + shift + ;; + esac + done + + if [[ "$project" != "" ]] && [[ "$name" != "" ]]; then + echo "$fg[red]error:$reset_color not allowed with -p" + return 1 + fi + if [[ "$project" == "" ]] && [[ "$name" == "" ]]; then + echo "$usage" + return 0 + fi + + if [[ "$host" != "" ]]; then + if [[ "$TMUX" != "" ]]; then + echo "$fg[red]error:$reset_color not allowed inside tmux session" return 1 fi - if [[ "$3" != "" ]]; then - echo "$fg[red]error:$reset_color invalid argument: $3" - return 1 + declare -A hosts + if [ -f ~/.config/session ]; then + source ~/.config/session + fi + host=${hosts[$host]:-$host} + fi + + if [[ "$project" != "" ]]; then + # tmux rewrites `.` and `:` in session names, so mirror that to keep the + # name we create and the name we target in sync. + name=${project//[.:]/_} + if [[ "$host" != "" ]]; then + # The project lives in the remote ~/Projects, so resolve it there rather + # than locally. The remote session-created hook reads TMUX_PROJECT back + # out of the remote tmux server to build the layout. + ssh "$host" -t " + repo=\$HOME/Projects/${(q)project} + [ -d \"\$repo\" ] || + { echo 'error: no such project: ${(q)project}' >&2; exit 1; } + git -C \"\$repo\" rev-parse --git-dir >/dev/null 2>&1 || + { echo \"error: not a git repository: \$repo\" >&2; exit 1; } + exec tmux new-session -As ${(q)name} -c \"\$HOME\" -e TMUX_PROJECT=${(q)project} + " + return fi local repo=$HOME/Projects/$project if [ ! -d "$repo" ]; then @@ -33,9 +102,6 @@ its default branch. echo "$fg[red]error:$reset_color not a git repository: $repo" return 1 fi - # tmux rewrites `.` and `:` in session names, so mirror that to keep the - # name we create and the name we target in sync. - local name=${project//[.:]/_} if [[ "$TMUX" == "" ]]; then tmux new-session -As "$name" -c $HOME -e "TMUX_PROJECT=$project" else @@ -43,33 +109,13 @@ its default branch. tmux new-session -Ads "$name" -c $HOME -e "TMUX_PROJECT=$project" tmux switch-client -t "=$name" fi + elif [[ "$host" != "" ]]; then + ssh "$host" -t tmux new-session -As "$name" + elif [[ "$TMUX" == "" ]]; then + tmux new-session -As "$name" else - local name=$1 - local host=$2 - if [[ "$3" != "" ]]; then - echo "$fg[red]error:$reset_color invalid argument: $3" - return 1 - fi - declare -A hosts - if [ -f ~/.config/session ]; then - source ~/.config/session - fi - local url=$hosts[$host] - host=${url:-$host} - if [[ "$TMUX" == "" ]]; then - local cmd="tmux new-session -As $name" - if [[ "$host" != "" ]]; then - cmd="ssh $host -t $cmd" - fi - eval $cmd - else - if [[ "$host" != "" ]]; then - echo "$fg[red]error:$reset_color not allowed inside tmux session" - return 1 - fi - tmux list-sessions | grep "$name:" &> /dev/null || \ - tmux new-session -Ads $name -c $HOME - tmux switch-client -t $name - fi + tmux has-session -t "=$name" &> /dev/null || \ + tmux new-session -Ads "$name" -c $HOME + tmux switch-client -t "=$name" fi }