Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve #21 get_remote_info via ssh itself #24

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ Replaces the `#H` format and adds a `#U` format option.

### Usage

- `#H` will be the hostname of your current path. If there is an ssh session opened, the ssh hostname will show instead of the local one.
- `#H` (`#{hostname}`) will be the hostname of your current path. If there is an ssh session opened, the ssh hostname will show instead of the local one.
- `#{hostname_short}` will be the short hostname of your current path (up to the first dot). If there is an ssh session opened, the ssh hostname will show instead of the local one.
- `#U` will show the `whoami` result or the user that logged in an ssh session.
- `#U` (`#{username}`) will show the `whoami` result or the user that logged in an ssh session.
- `#{pane_ssh_port}` if an open ssh session will show the connection port, otherwise it will be empty.
- `#{pane_ssh_connected}` will be set to 1 if the currently selected pane has an active ssh connection. (Useful for `#{?#{pane_ssh_connected},ssh,no-ssh}` which will evaluate to `ssh` if there is an active ssh in the currently selected pane and `no-ssh` otherwise.)
- `#{pane_ssh_connect}` if an open ssh session will show the connection info in `"username@hostname:port"` format, otherwise it will be empty.

Here's the example in `.tmux.conf`:

Expand Down
31 changes: 20 additions & 11 deletions current_pane_hostname.tmux
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@

CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

interpolation=('\#H' '\#{hostname_short}' '\#U' '\#\{pane_ssh_port\}' '\#\{pane_ssh_connected\}')
script=("#($CURRENT_DIR/scripts/hostname.sh)" "#($CURRENT_DIR/scripts/hostname_short.sh)" "#($CURRENT_DIR/scripts/whoami.sh)" "#($CURRENT_DIR/scripts/port.sh)" "#($CURRENT_DIR/scripts/pane_ssh_connected.sh)")
# Create map placeholders to handle scripts
# to provide one handler for multiple placeholders.
# Use '//' as separator, due to unix limitation in filenames
placeholders_to_scripts=(
"\#U//#($CURRENT_DIR/scripts/user.sh)"
"\#\{username\}//#($CURRENT_DIR/scripts/user.sh)"
"\#H//#($CURRENT_DIR/scripts/host.sh)"
"\#\{hostname\}//#($CURRENT_DIR/scripts/host.sh)"
"\#\{hostname_short\}//#($CURRENT_DIR/scripts/host_short.sh)"
"\#\{pane_ssh_port\}//#($CURRENT_DIR/scripts/port.sh)"
"\#\{pane_ssh_connected\}//#($CURRENT_DIR/scripts/pane_ssh_connected.sh)"
"\#\{pane_ssh_connect\}//#($CURRENT_DIR/scripts/pane_ssh_connect.sh)")


source $CURRENT_DIR/scripts/shared.sh

do_interpolation() {
local interpolated=$1
local j=0

for i in "${interpolation[@]}"; do
local s=${script[$j]}
local interpolated=${interpolated//$i/$s}
((j+=1))
done
echo "$interpolated"
local interpolated=$1
for assignment in ${placeholders_to_scripts[@]}; do
# ${assignment%\/\/*} - remove from // til EOL
# ${assignment#*\/\/} - remove from BOL til //
# ${interpolated//A/B} - replace all occurrences of A in interpolated with B
local interpolated=${interpolated//${assignment%\/\/*}/${assignment#*\/\/}}
done
echo "$interpolated"
}

update_tmux_option() {
Expand Down
2 changes: 1 addition & 1 deletion scripts/whoami.sh → scripts/host.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh

main() {
get_info "whoami"
get_info host
}

main
2 changes: 1 addition & 1 deletion scripts/hostname.sh → scripts/host_short.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh

main() {
get_info "hostname"
get_info host_short
}

main
2 changes: 1 addition & 1 deletion scripts/hostname_short.sh → scripts/pane_ssh_connect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh

main() {
get_info "hostname -s"
get_info
}

main
6 changes: 1 addition & 5 deletions scripts/pane_ssh_connected.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh

main() {
if ssh_connected; then
echo 1
else
echo 0
fi
ssh_connected && echo 1 || echo 0
}

main
4 changes: 1 addition & 3 deletions scripts/port.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh

main() {
if ssh_connected; then
get_info "port"
fi
get_info port
}

main
153 changes: 76 additions & 77 deletions scripts/shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ get_tmux_option() {
local option=$1
local default_value=$2
local option_value=$(tmux show-option -gqv "$option")
if [ -z "$option_value" ]; then
echo "$default_value"
else
echo "$option_value"
fi
[[ -z "$option_value" ]] && echo "$default_value" || echo "$option_value"
}

set_tmux_option() {
Expand All @@ -17,87 +13,90 @@ set_tmux_option() {
tmux set-option -gq "$option" "$value"
}

parse_ssh_port() {
# If there is a port get it
local port=$(echo $1|grep -Eo '\-p\s*([0-9]+)'|sed 's/-p\s*//')
get_remote_info() {
# First get the current pane command pid to get the full command with arguments
local cmd=$(_current_pane_command | grep -E 'ssh' | sed -E 's/^[0-9]*[[:blank:]]*ssh //')
# Fetch configuration with given cmd
ssh -G $cmd 2>/dev/null | grep -E -e '^host\s' -e '^port\s' -e '^user\s' | sort | cut -f 2 -d ' ' | xargs
}

if [ -z $port ]; then
local port=22
fi
get_container_info() {
local cmd=$(_current_pane_command | grep -E 'docker|podman' | sed -E 's/^[0-9]*[[:blank:]]* //')

echo $port
local runner=${cmd%% *}
if [[ $cmd =~ ' --name' ]]; then
local container=$(echo ${cmd##* --name} | cut -f 1 -d ' ')
container=${container##*=}
else
# @TODO get dynamic named container
# local all_running_containers=$($runner ps -q | xargs $runner inspect)
return
fi

local info=$($runner inspect --format '{{ .Config.Hostname }}/{{ .Config.Domainname }}/{{ .Config.User }}' $container)
local host=$(echo $info | cut -f 1 -d '/')
local domain=$(echo $info | cut -f 2 -d '/')
local user=$(echo $info | cut -f 3 -d '/')
# @TODO `port` is not applicable with container for now
echo "${host}${domain:+.$domain} 0 ${user}"
}

get_ssh_user() {
local ssh_user=$(whoami)

for ssh_config in `awk '
$1 == "Host" {
gsub("\\\\.", "\\\\.", $2);
gsub("\\\\*", ".*", $2);
host = $2;
next;
}
$1 == "User" {
$1 = "";
sub( /^[[:space:]]*/, "" );
printf "%s|%s\n", host, $0;
}' .ssh/config`; do
local host_regex=${ssh_config%|*}
local host_user=${ssh_config#*|}
if [[ "$1" =~ $host_regex ]]; then
ssh_user=$host_user
break
fi
done

echo $ssh_user
get_info() {
local host port user
# If command is ssh, fetch connection info
if ssh_connected; then
read -r host port user <<<$(get_remote_info)
fi
if containered; then
read -r host port user <<<$(get_container_info)
fi
# Return requested info
case "$1" in
"user") # user from ssh info or `whoami`
[[ -z "$user" ]] && _get_username || echo "$user"
;;
"host") # host from ssh info or `hostname`
[[ -z "$host" ]] && _get_hostname || echo "$host"
;;
"host_short") # host from ssh info or `hostname -s`
[[ -z "$host" ]] && _get_hostname_short || echo "$host"
;;
"port") # port from ssh info or empty
echo "$port"
;;
*) # user from ssh info + "@host" if host is not empty + ":port" if port is not empty
echo "${user}${host:+@$host}${port:+:$port}"
;;
esac
}

get_remote_info() {
local command=$1

# First get the current pane command pid to get the full command with arguments
local cmd=$({ pgrep -flaP `tmux display-message -p "#{pane_pid}"` ; ps -o command -p `tmux display-message -p "#{pane_pid}"` ; } | xargs -I{} echo {} | grep ssh | sed -E 's/^[0-9]*[[:blank:]]*ssh //')

local port=$(parse_ssh_port "$cmd")

local cmd=$(echo $cmd|sed 's/\-p\s*'"$port"'//g')
local user=$(echo $cmd | awk '{print $NF}'|cut -f1 -d@)
local host=$(echo $cmd | awk '{print $NF}'|cut -f2 -d@)

if [ $user == $host ]; then
local user=$(get_ssh_user $host)
fi

case "$1" in
"whoami")
echo $user
;;
"hostname")
echo $host
;;
"port")
echo $port
;;
*)
echo "$user@$host:$port"
;;
esac
ssh_connected() {
local cmd=$(_current_pane_command)

[[ $cmd =~ " ssh " ]] || [[ $cmd =~ " sshpass " ]]
}

get_info() {
# If command is ssh do some magic
if ssh_connected; then
echo $(get_remote_info $1)
else
echo $($1)
fi
containered() {
local cmd=$(_current_pane_command)

[[ $cmd =~ " docker " ]] || [[ $cmd =~ " podman " ]]
}

ssh_connected() {
# Get current pane command
local cmd=$(tmux display-message -p "#{pane_current_command}")
_current_pane_command() {
local pane_pid=$(tmux display-message -p "#{pane_pid}")

# @TODO research, maybe `pgrep -flaP $pane_pid` is enough
{ pgrep -flaP $pane_pid; ps -o command -p $pane_pid; } | xargs -I{} echo {}
}

_get_username() {
command -v whoami && whoami
}

_get_hostname() {
command -v hostname && hostname || echo "${HOSTNAME}"
}

[ $cmd = "ssh" ] || [ $cmd = "sshpass" ]
_get_hostname_short() {
command -v hostname && hostname --short || echo "${HOSTNAME%%.*}"
}
11 changes: 11 additions & 0 deletions scripts/user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

source $CURRENT_DIR/shared.sh

main() {
get_info user
}

main