diff --git a/bin/tmuxifier b/bin/tmuxifier index 5539aa5..d3923d3 100755 --- a/bin/tmuxifier +++ b/bin/tmuxifier @@ -3,11 +3,12 @@ set -e [ -n "$TMUXIFIER_DEBUG" ] && set -x resolve_link() { - $(type -p greadlink readlink | head -1) $1 + $(type -p greadlink readlink | head -1) "$1" } abs_dirname() { - local cwd="$(pwd)" + local cwd + cwd="$(pwd)" local path="$1" while [ -n "$path" ]; do @@ -20,48 +21,63 @@ abs_dirname() { cd "$cwd" } -if [ -z "${TMUXIFIER}" ]; then - # Set TMUXIFIER relative to the "tmuxifier" executable. - export TMUXIFIER="$(dirname "$(abs_dirname "$0")")" -else - # Strip any trailing slash (/) characters from TMUXIFIER variable. - export TMUXIFIER="${TMUXIFIER%/}" -fi +main() { + if [ -z "${TMUXIFIER}" ]; then + # Set TMUXIFIER relative to the "tmuxifier" executable. + export TMUXIFIER="$(dirname "$(abs_dirname "$0")")" + else + # Strip any trailing slash (/) characters from TMUXIFIER variable. + export TMUXIFIER="${TMUXIFIER%/}" + fi -# Load tmuxifier environment variables. -source "$TMUXIFIER/lib/env.sh" + # Bootstrap tmuxifier. + source "$TMUXIFIER/lib/load.sh" -# Add tmuxifier's internal commands to PATH. -export PATH="$TMUXIFIER/libexec:$PATH" + # Check Tmux version. + export TMUXIFIER_MIN_TMUX_VERSION="1.6" + if [ "$(tmuxifier-tmux-version "$TMUXIFIER_MIN_TMUX_VERSION")" == "<" ]; then + echo -e "ERROR: Tmuxifier requires Tmux v${TMUXIFIER_MIN_TMUX_VERSION}" \ + "or newer. You have v$(tmuxifier-tmux-version)." >&2 + exit 1 + fi -# Check Tmux version. -export TMUXIFIER_MIN_TMUX_VERSION="1.6" -if [ "$(tmuxifier-tmux-version "$TMUXIFIER_MIN_TMUX_VERSION")" == "<" ]; then - echo -e "ERROR: Tmuxifier requires Tmux v${TMUXIFIER_MIN_TMUX_VERSION}" \ - "or newer. You have v$(tmuxifier-tmux-version)." >&2 - exit 1 -fi + # Get command and shift arguments. + local command="$1" + shift 1 -# Parse given command -command="$1" -case "$command" in - "" | "-h" | "--help") - echo -e "tmuxifier $(tmuxifier-version)\n$(tmuxifier-help)" >&2 - ;; + # Resolve to full command name if an alias is given. + command="$(tmuxifier-alias "$command" || echo "$command")" - "-v" | "--version") - tmuxifier-version - ;; + case "$command" in + "" | "-h" | "--help") + echo -e "tmuxifier $(tmuxifier-version)\n$(tmuxifier-help)" >&2 + ;; - *) - ! command_path="$(tmuxifier-resolve-command-path "$command")" + "-v" | "--version") + tmuxifier-version + ;; - if [ -z "$command_path" ]; then - echo "tmuxifier: no such command '$command'" >&2 - exit 1 - fi + *) + local command_path + local func_name - shift 1 - exec "$command_path" "$@" - ;; -esac + func_name="tmuxifier-$command" + + # Check if command is available as a function. + if declare -f "$func_name" > /dev/null; then + "$func_name" "$@" + else + # Fall back to libexec executable. + command_path="$(tmuxifier-resolve-command-path "$command")" || true + if [ -z "$command_path" ]; then + echo "tmuxifier: no such command '$command'" >&2 + exit 1 + fi + + exec "$command_path" "$@" + fi + ;; + esac +} + +main "$@" diff --git a/lib/commands/alias.sh b/lib/commands/alias.sh new file mode 100644 index 0000000..e16a346 --- /dev/null +++ b/lib/commands/alias.sh @@ -0,0 +1,56 @@ +# Resolve a tmuxifier command alias to its full command name. +# +# Usage: +# tmuxifier-alias +# +# Arguments: +# $1 - Alias to resolve +# +# Output: +# The full command name if alias is recognized, empty otherwise. +# +# Returns: +# 0 - Alias was recognized +# 1 - Alias was not recognized +tmuxifier-alias() { + # Provide tmuxifier help + if calling-help "$@"; then + echo "usage: tmuxifier alias + +Resolve a command alias to it's full name." + return + fi + + case "$1" in + "session" | "ses" | "s") + echo "load-session" + ;; + "window" | "win" | "w") + echo "load-window" + ;; + "new-ses" | "nses" | "ns") + echo "new-session" + ;; + "new-win" | "nwin" | "nw") + echo "new-window" + ;; + "edit-ses" | "eses" | "es") + echo "edit-session" + ;; + "edit-win" | "ewin" | "ew") + echo "edit-window" + ;; + "l") + echo "list" + ;; + "list-ses" | "lses" | "ls") + echo "list-sessions" + ;; + "list-win" | "lwin" | "lw") + echo "list-windows" + ;; + *) + return 1 + ;; + esac +} diff --git a/lib/commands/resolve-command-path.sh b/lib/commands/resolve-command-path.sh new file mode 100644 index 0000000..3712985 --- /dev/null +++ b/lib/commands/resolve-command-path.sh @@ -0,0 +1,43 @@ +# Resolve the absolute path to a tmuxifier command or alias. +# +# Usage: +# tmuxifier-resolve-command-path +# +# Arguments: +# $1 - Command name or alias to resolve +# +# Output: +# The absolute path to the command executable, or empty if not found. +# +# Returns: +# 0 - Command was found +# 1 - Command was not found +tmuxifier-resolve-command-path() { + # Provide tmuxifier help + if calling-help "$@"; then + echo "usage: tmuxifier resolve-command-path + +Outputs the absolute path to the given command or command alias." + return + fi + + local command_path="" + + if [ -n "$1" ]; then + # Look for executable file, not functions. + command_path="$(type -P "tmuxifier-$1" 2> /dev/null)" || true + if [ -z "$command_path" ]; then + local resolved + resolved="$(tmuxifier-alias "$1")" + if [ -n "$resolved" ]; then + command_path="$(type -P "tmuxifier-$resolved" 2> /dev/null)" || true + fi + fi + fi + + if [ -n "$command_path" ]; then + echo "$command_path" + else + return 1 + fi +} diff --git a/lib/commands/tmux-version.sh b/lib/commands/tmux-version.sh new file mode 100644 index 0000000..ada850a --- /dev/null +++ b/lib/commands/tmux-version.sh @@ -0,0 +1,63 @@ +# Enable extended globbing for version string cleanup. +shopt -s extglob + +# Output current Tmux version, or compare against a target version. +# +# Usage: +# tmuxifier-tmux-version # Outputs current Tmux version +# tmuxifier-tmux-version "1.9" # Outputs "=", "<", or ">" +# +# Arguments: +# $1 - Optional target version to compare against +# +# Output: +# Without arguments: The current Tmux version string +# With target version: One of "=", "<", or ">" indicating if the current +# Tmux version is equal to, less than, or greater than +# the target version. +# +# Returns: +# 0 - Always succeeds +tmuxifier-tmux-version() { + # Provide tmuxifier help + if calling-help "$@"; then + echo "usage: tmuxifier tmux-version [] + +Outputs current Tmux version. If given optional target-version it outputs one +of three possible characters indicating if the current Tmux version number is +equal to, less than, or greater than the . + +The three possible outputs are \"=\", \"<\", and \">\"." + return + fi + + local version + version="$(tmux -V)" + version="${version/tmux /}" + + # Fix for tmux next-* versions + version="${version/next-/}" + + if [ -z "$1" ]; then + echo "$version" + return + fi + + if [ "$version" == "master" ]; then + # When version string is "master", tmux was compiled from source, and we + # assume it's later than whatever the is. + echo '>' + else + # Fix for "1.9a" version comparison, as vercomp() can only deal with + # purely numeric version numbers. + version="${version//+([a-zA-Z])/}" + + local result + vercomp "$version" "$1" && result=$? || result=$? + case $result in + 0) echo '=' ;; + 1) echo '>' ;; + 2) echo '<' ;; + esac + fi +} diff --git a/lib/load.sh b/lib/load.sh new file mode 100644 index 0000000..7a1b3af --- /dev/null +++ b/lib/load.sh @@ -0,0 +1,17 @@ +# Setup layout path. +if [ -z "${TMUXIFIER_LAYOUT_PATH}" ]; then + export TMUXIFIER_LAYOUT_PATH="${TMUXIFIER}/layouts" +else + export TMUXIFIER_LAYOUT_PATH="${TMUXIFIER_LAYOUT_PATH%/}" +fi + +# Add tmuxifier's internal commands to PATH. +export PATH="$TMUXIFIER/libexec:$PATH" + +# Load utility functions. +source "$TMUXIFIER/lib/util.sh" + +# Load command functions from lib/commands/ directory directly. +source "$TMUXIFIER/lib/commands/alias.sh" +source "$TMUXIFIER/lib/commands/resolve-command-path.sh" +source "$TMUXIFIER/lib/commands/tmux-version.sh" diff --git a/libexec/tmuxifier-alias b/libexec/tmuxifier-alias index 60c63a2..329b416 100755 --- a/libexec/tmuxifier-alias +++ b/libexec/tmuxifier-alias @@ -1,47 +1,6 @@ #! /usr/bin/env bash -set -e [ -n "$TMUXIFIER_DEBUG" ] && set -x -# Load internal utility functions. -source "$TMUXIFIER/lib/util.sh" +source "$TMUXIFIER/lib/load.sh" -# Provide tmuxifier help -if calling-help "$@"; then - echo "usage: tmuxifier alias - -Resolve a command alias to it's full name." - exit -fi - -case "$1" in - "session" | "ses" | "s") - echo "load-session" - ;; - "window" | "win" | "w") - echo "load-window" - ;; - "new-ses" | "nses" | "ns") - echo "new-session" - ;; - "new-win" | "nwin" | "nw") - echo "new-window" - ;; - "edit-ses" | "eses" | "es") - echo "edit-session" - ;; - "edit-win" | "ewin" | "ew") - echo "edit-window" - ;; - "l") - echo "list" - ;; - "list-ses" | "lses" | "ls") - echo "list-sessions" - ;; - "list-win" | "lwin" | "lw") - echo "list-windows" - ;; - *) - exit 1 - ;; -esac +tmuxifier-alias "$@" diff --git a/libexec/tmuxifier-resolve-command-path b/libexec/tmuxifier-resolve-command-path index 6eeec67..39be6db 100755 --- a/libexec/tmuxifier-resolve-command-path +++ b/libexec/tmuxifier-resolve-command-path @@ -1,30 +1,6 @@ #! /usr/bin/env bash -set -e [ -n "$TMUXIFIER_DEBUG" ] && set -x -# Load internal utility functions. -source "$TMUXIFIER/lib/util.sh" +source "$TMUXIFIER/lib/load.sh" -# Provide tmuxifier help -if calling-help "$@"; then - echo "usage: tmuxifier resolve-command-path - -Outputs the absolute path to the given command or command alias." - exit -fi - -if [ -n "$1" ]; then - ! command_path="$(command -v "tmuxifier-$1")" - if [ -z "$command_path" ]; then - resolved="$(tmuxifier-alias "$1")" - if [ -n "$resolved" ]; then - ! command_path="$(command -v "tmuxifier-$resolved")" - fi - fi -fi - -if [ -n "$command_path" ]; then - echo "$command_path" -else - exit 1 -fi +tmuxifier-resolve-command-path "$@" diff --git a/libexec/tmuxifier-tmux-version b/libexec/tmuxifier-tmux-version index 8dedff5..89ace4e 100755 --- a/libexec/tmuxifier-tmux-version +++ b/libexec/tmuxifier-tmux-version @@ -1,70 +1,6 @@ #! /usr/bin/env bash -shopt -s extglob [ -n "$TMUXIFIER_DEBUG" ] && set -x -# Load internal utility functions. -source "$TMUXIFIER/lib/util.sh" +source "$TMUXIFIER/lib/load.sh" -# Provide tmuxifier help -if calling-help "$@"; then - echo "usage: tmuxifier tmux-version [] - -Outputs current Tmux version. If given optional target-version it outputs one -of three possible characters indicating if the current Tmux version number is -equal to, less than, or greater than the . - -The three possible outputs are \"=\", \"<\", and \">\"." - exit -fi - -# The vercomp() function is shamelessly ripped/borrowed from the following -# StackOverflow answer: http://stackoverflow.com/a/4025065/42146 -vercomp() { - if [[ $1 == $2 ]]; then return 0; fi - - local IFS=. - local i ver1=($1) ver2=($2) - - # fill empty fields in ver1 with zeros - for ((i = ${#ver1[@]}; i < ${#ver2[@]}; i++)); do ver1[i]=0; done - - for ((i = 0; i < ${#ver1[@]}; i++)); do - # fill empty fields in ver2 with zeros - if [[ -z ${ver2[i]} ]]; then ver2[i]=0; fi - - if ((10#${ver1[i]} > 10#${ver2[i]})); then - return 1 - elif ((10#${ver1[i]} < 10#${ver2[i]})); then - return 2 - fi - done - return 0 -} - -version=$(tmux -V) -version=${version/tmux /} - -# Fix for tmux next-* versions -version=${version/next-/} - -if [ -z "$1" ]; then - echo "$version" - exit -fi - -if [ "$version" == "master" ]; then - # When version string is "master", tmux was compiled from source, and we - # assume it's later than whatever the is. - echo '>' -else - # Fix for "1.9a" version comparison, as vercomp() can only deal with - # purely numeric version numbers. - version=${version//+([a-zA-Z])/} - - vercomp "$version" "$1" - case $? in - 0) echo '=' ;; - 1) echo '>' ;; - 2) echo '<' ;; - esac -fi +tmuxifier-tmux-version "$@"