This commit is contained in:
2024-10-18 22:19:09 +02:00
parent a850f644de
commit ece099b6a4
11 changed files with 1056 additions and 229 deletions

View File

@@ -1,99 +1,133 @@
#!/bin/bash
#!/usr/bin/env bash
function ctrl_c() {
stty "$saved_stty"
exit 1
}
set -o pipefail
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
# only accepts ESC backslash for ST.
function print_osc() {
if [[ $TERM == screen* ]] ; then printf "\033Ptmux;\033\033]"
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
printf "\033Ptmux;\033\033]"
else
printf "\033]" >& 2
printf "\033]"
fi
}
# More of the tmux workaround described above.
function print_st() {
if [[ $TERM == screen* ]] ; then
printf "\a\033\\" >& 2
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
printf "\a\033\\"
else
printf "\a" >& 2
printf "\a"
fi
}
function get_b64_version() {
if [[ -z "${BASE64_VERSION+x}" ]]; then
BASE64_VERSION=$(base64 --version 2>&1)
export BASE64_VERSION
fi
}
function b64_encode() {
get_b64_version
if [[ $BASE64_VERSION =~ GNU ]]; then
# Disable line wrap
base64 -w0
else
base64
fi
}
function b64_decode() {
get_b64_version
if [[ $BASE64_VERSION =~ fourmilab ]]; then
BASE64_ARG=-d
elif [[ $BASE64_VERSION =~ GNU ]]; then
BASE64_ARG=-di
else
BASE64_ARG=-D
fi
base64 $BASE64_ARG
}
function error() {
errcho "ERROR: $*"
}
function errcho() {
echo "$@" >&2
}
function show_help() {
echo "Usage:" 1>& 2
echo " $(basename $0) name" 1>& 2
errcho
errcho "Usage: it2getvar variable_name"
errcho
errcho "Output value of the iTerm2 variable"
errcho
errcho "See the Variables Reference for information about built-in iTerm2 variables:"
errcho " -> https://iterm2.com/documentation-variables.html"
errcho
}
# Read some bytes from stdin. Pass the number of bytes to read as the first argument.
function read_bytes() {
numbytes=$1
dd bs=1 count=$numbytes 2>/dev/null
}
# read_until c
# Returns bytes read from stdin up to but not including the fist one equal to c
function read_until() {
result=""
while :
do
b=$(read_bytes 1)
if [[ $b == $1 ]]
then
echo "$result"
return
function check_dependency() {
if ! (builtin command -V "$1" >/dev/null 2>&1); then
error "missing dependency: can't find $1"
exit 1
fi
result="$result$b"
done
}
## Main
if [[ $# != 1 ]]
then
show_help
exit 1
# get_variable variable_name
#
# This function uses POSIX standard synonym for the controlling terminal
# associated with the current process group - /dev/tty. It is useful for programs
# that wish to be sure of writing or reading data from the terminal
# no matter how STDIN/STDOUT/STDERR has been redirected.
function get_variable() {
trap 'cleanup' EXIT
stty -echo < /dev/tty
exec 9<> /dev/tty
print_osc >&9
printf "1337;ReportVariable=%s" "$(echo -n "$1" | b64_encode)" >&9
print_st >&9
read -r -t 5 -d $'\a' iterm_response <&9
exec 9>&-
stty echo < /dev/tty
[[ "$iterm_response" =~ ReportVariable= ]] || {
error "Failed to read response from iTerm2"
exit 2
}
echo "$(b64_decode <<< ${iterm_response#*=})"
}
function cleanup() {
stty echo < /dev/tty
}
# Show help if no arguments
if [ $# -eq 0 ]; then
show_help
exit
fi
if ! test -t 1
then
echo "Standard error not a terminal"
exit 1
fi
check_dependency stty
check_dependency base64
# Save the tty's state.
saved_stty=$(stty -g)
# Trap ^C to fix the tty.
trap ctrl_c INT
# Enter raw mode and turn off echo so the terminal and I can chat quietly.
stty -echo -icanon raw
print_osc
printf "1337;ReportVariable=%s" "$(printf "%s" "$1" | base64)" >& 2
print_st
VERSION=$(base64 --version 2>&1)
if [[ "$VERSION" =~ fourmilab ]]; then
BASE64ARG=-d
elif [[ "$VERSION" =~ GNU ]]; then
BASE64ARG=-di
else
BASE64ARG=-D
fi
ignore=$(read_bytes 1)
name=$(read_until )
re='^]1337;ReportVariable=(.*)'
if [[ $name =~ $re ]]
then
printf "%s" $(base64 $BASE64ARG <<< ${BASH_REMATCH[1]})
exit 0
else
exit 1
fi
# Process command line arguments
case "$1" in
-h|--h|--help)
show_help
exit
;;
-*)
error "Unknown option: $1"
show_help
exit 1
;;
*)
[[ -z "$1" ]] && error "Variable name can't be empty" && exit 1
get_variable "$1"
;;
esac
exit 0