add getopt. allow double sessions
authorJoerg Jaspert <joerg@ganneff.de>
Mon, 15 Jul 2013 13:31:43 +0000 (15:31 +0200)
committerJoerg Jaspert <joerg@ganneff.de>
Mon, 15 Jul 2013 13:31:43 +0000 (15:31 +0200)
bin/tm

diff --git a/bin/tm b/bin/tm
index f881481..7ed0cea 100755 (executable)
--- a/bin/tm
+++ b/bin/tm
@@ -77,6 +77,21 @@ unset bindex
 ########################################################################
 # Nothing below here to configure
 
+# Should we open another session, even if we already have one with
+# this name? (Ie. second multisession to the same set of hosts)
+# This is either set by the getopts option -n or by having -n
+# as very first parameter after the tm command
+if [[ "${1}" = "-n" ]]; then
+    DOUBLENAME=true
+    # And now get rid of it. getopts won't see it, as it was first and
+    # we remove it - but it doesn't matter, we set it already.
+    # getopts is only used if it appears somewhere else in the
+    # commandline
+    shift
+else
+    DOUBLENAME=false
+fi
+
 # Store the commandline
 declare -r cmdline=${1:-""}
 
@@ -92,15 +107,30 @@ declare -r OLDIFS=${IFS}
 ########################################################################
 function usage() {
     echo "tmux helper by Joerg Jaspert <joerg@ganneff.de>"
-    echo "Call as: $0 CMD [host]..."
+    echo "There are two ways to call it. Traditional and \"getopts\" style."
+    echo "Traditional call as: $0 CMD [host]..."
+    echo "Getopts call as: $0 [-s host] [-m hostlist] [-l] [-n] [-h] [-c config] [-e]"
     echo ""
+    echo "Traditional:"
     echo "CMD is one of"
     echo " ls          List running sessions"
     echo " s           Open ssh session to host"
     echo " ms          Open multi ssh sessions to hosts, synchronizing input"
-    echo " \$anything   Either plain tmux session with name of \$anything or"
+    echo "             To open a second session to the same set of hosts put a"
+    echo "             -n in front of ms"
+    echo " \$anything  Either plain tmux session with name of \$anything or"
     echo "             session according to TMDIR file"
     echo ""
+    echo "Getopts style:"
+    echo "-l           List running sessions"
+    echo "-s host      Open ssh session to host"
+    echo "-ms hostlist Open multi ssh sessions to hosts, synchronizing input"
+    echo "             Due to the way getopts works, hostlist must be enclosed in \"\""
+    echo "-n           Open a second session to the same set of hosts"
+    echo "-c config    Setup session according to TMDIR file"
+    echo "-e SESSION   Use existion session named SESSION"
+    echo ""
+    echo ""
     echo "TMDIR file:"
     echo "Each file in \$TMDIR defines a tmux session."
     echo "Filename is the commandline option \$anything"
@@ -132,6 +162,55 @@ function usage() {
     exit 42
 }
 
+# Simple "cleanup" of a variable, removing space and dots as we don't
+# want them in our tmux session name
+function clean_session() {
+    local toclean=${*:-""}
+
+    # Neither space nor dot are friends in the SESSION name
+    toclean=${toclean// /_}
+    echo ${toclean//./_}
+}
+
+# Merge the commandline parameters (hosts) into a usable session name
+# for tmux
+function ssh_sessname() {
+    local sess="${*}"
+
+    if [[ ${TMSORT} = true ]]; then
+        local one=$1
+        # get rid of first argument (s|ms), we don't want to sort this
+        shift
+        sess=$(for i in $*; do echo $i; done | sort | tr '\n' ' ')
+        sess="${one} ${sess% *}"
+    else
+        # no sorting, wanted, so we just get rid of first argument (s|ms)
+        shift
+    fi
+    clean_session ${sess}
+}
+
+# Use a configuration file to setup the tmux parameters/session
+function own_config() {
+    # Set IFS to be NEWLINE only, not also space/tab, as our input files
+    # are \n seperated (one entry per line) and lines may well have spaces
+    IFS="
+"
+    # Fill an array with our config
+    TMDATA=( $(cat "${TMDIR}/$1") )
+    # Restore IFS
+    IFS=${OLDIFS}
+
+    SESSION=$(clean_session ${TMDATA[0]})
+
+    if [ "${TMDATA[1]}" != "NONE" ]; then
+        TMOPTS=${TMDATA[1]}
+    fi
+}
+
+########################################################################
+# MAIN work follows here
+
 # Check the first cmdline parameter, we might want to prepare something
 case ${cmdline} in
     ls)
@@ -144,22 +223,35 @@ case ${cmdline} in
         # So we have to prepare our session name to fit in what tmux (and shell)
         # allow us to have. And so that we can reopen an existing session, if called
         # with the same hosts again.
-        sess="${*}"
-
-        if [[ ${TMSORT} = true ]]; then
-            one=$1
-            # get rid of first argument (s|ms), we don't want to sort this
-            shift
-            sess=$(for i in $*; do echo $i; done | sort | tr '\n' ' ')
-            sess="${one} ${sess% *}"
-        else
-            # no sorting, wanted, so we just get rid of first argument (s|ms)
-            shift
-        fi
-
-        # Neither space nor dot are friends in the SESSION name
-        sess=${sess// /_}
-        SESSION=${sess//./_}
+        SESSION=$(ssh_sessname $@)
+        ;;
+    -*)
+        while getopts "lnhs:m:c:e:" OPTION; do
+            case $OPTION in
+                l) # ls
+                    tmux list-sessions
+                    exit 0
+                    ;;
+                s) # ssh
+                    SESSION=$(ssh_sessname s ${OPTARG})
+                    ;;
+                m) # ms (needs hostnames in "")
+                    SESSION=$(ssh_sessname ms ${OPTARG})
+                    ;;
+                c) # pre-defined config
+                    own_config ${OPTARG}
+                    ;;
+                e) # existing session name
+                    SESSION=$(clean_session ${OPTARG})
+                    ;;
+                n) # new session even if same name one already exists
+                    DOUBLENAME=true
+                    ;;
+                h)
+                    usage
+                    ;;
+            esac
+        done
         ;;
     *)
         # Nothing special (or something in our tmux.d)
@@ -175,25 +267,8 @@ case ${cmdline} in
             else
                 usage
             fi
-        fi
-        if [ -r "${TMDIR}/$1" ]; then
-            # Set IFS to be NEWLINE only, not also space/tab, as our input files
-            # are \n seperated (one entry per line) and lines may well have spaces
-            IFS="
-"
-            # Fill an array with our config
-            TMDATA=( $(cat "${TMDIR}/$1") )
-            # Restore IFS
-            IFS=${OLDIFS}
-
-            SESSION=${TMDATA[0]}
-            # Neither space nor dot are friends in the SESSION name
-            SESSION=${SESSION// /_}
-            SESSION=${SESSION//./_}
-
-            if [ "${TMDATA[1]}" != "NONE" ]; then
-                TMOPTS=${TMDATA[1]}
-            fi
+        elif [ -r "${TMDIR}/$1" ]; then
+            own_config $1
         else
             # Not a config file, so just session name.
             TMDATA=""
@@ -201,6 +276,17 @@ case ${cmdline} in
         fi
         ;;
 esac
+
+# And now check if we would end up with a doubled session name.
+# If so add something "random" to the new name, like our pid.
+if [[ ${DOUBLENAME} == true ]] && tmux has-session -t ${SESSION} 2>/dev/null; then
+    # Session exist but we are asked to open another one,
+    # so adjust our session name
+    if [[ ${SESSION} =~ ([ms]+)_(.*) ]]; then
+        SESSION="${BASH_REMATCH[1]}_$$_${BASH_REMATCH[2]}"
+    fi
+fi
+
 if [[ ${TMSESSHOST} = true ]]; then
     declare -r SESSION="$(hostname -s)_${SESSION}"
 else