tmux_wait_for_many: initial version

Script that waits for line matching given regexp to appear in tmux pane(s).
This is useful, for example, for checking whether command running in pane
ended.
parent 67ea4dda
2019-05-13:
- tmux_wait_for_many: initial version
2019-03-11: 2019-03-11:
- vsleep: Fix length calculation for time fields - vsleep: Fix length calculation for time fields
- vsleep: Improve handling of terminal resizing while running - vsleep: Improve handling of terminal resizing while running
......
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'
# End of Unofficial Bash Strict Mode
# defaults
mode=s
list=0
full=0
verbose=0
wait_time=1
skip=''
# defaults
# Helper functions
verbose() {
(( verbose == 0 )) && return
printf -- "$@"
}
die() {
printf -- "$@" >&2
printf '\n' >&2
exit 1
}
show_help_and_die() {
error_message="${1:-}"
help_message="Syntax:
$0 [-a] [-f] [-l] [-v] [-s SKIP_MATCHER] [-w WAIT_TIME] PANE_MATCHER LINE_MATCHER
Description:
Waits for line matching given regexp to appear in tmux pane(s).
This is useful, for example, for checking whether command running in pane
ended.
Options:
-a : Enables matching across all sessions, not only current.
-f : Match line in any place on screen, not only last non-empty.
-l : List all matching panes and exit, don't wait on anything.
-s : Skip lines that match this regular expression (egrep style).
-w : Wait given time between checks of terminal, defaults to 1 (second).
-v : Print verbose information while working.
Arguments:
PANE_MATCHER : Regular expression (compatible with egrep), that will be
used to select panes that should be processed. Without
-a, panes are listed only from current session, and have
format:
WINDOW_NAME.PANE_INDEX
With -a, panes are listed from all sessions, and have
format:
SESSION_NAME:WINDOW_NAME.PANE_INDEX
LINE_MATCHER : Regular expression (compatible with egrep), that will be
used to check if last non-empty line in pane(s) contain
what was expected.
In case -f was provided, the whole screen (visible part)
will be checked."
if [[ -n "${error_message}" ]]
then
printf "Error:\n %s\n\n" "${error_message}" >&2
echo "${help_message}" >&2
exit 1
fi
echo "${help_message}"
exit 0
}
# Helper functions
# MAIN PROGRAM
## Make sure we're under tmux
[[ -n "${TMUX_PANE:-}" ]] || die "You have to run $0 under Tmux!"
current_tmux_session="$( tmux display-message -p -t "${TMUX_PANE}" "#S" )"
## Make sure we're under tmux
## Parse and validate command line arguments
while getopts 'aflvs:w:h?' opt "$@"
do
case "${opt}" in
a)
mode="a"
;;
v)
verbose=1
;;
l)
list=1
;;
f)
full=1
;;
s)
skip="${OPTARG}"
;;
w)
wait_time="${OPTARG}"
;;
h|?)
show_help_and_die
;;
esac
done
shift $((OPTIND - 1))
matcher="${1:-}"
[[ -n "${matcher}" ]] || show_help_and_die "You didn't provide PANE_MATCHER?!"
shift
(( list < 1 )) && (( $# != 1 )) && show_help_and_die "You didn't provide LINE_MATCHER (or did provide many)?!"
line_matcher="$1"
## Parse and validate command line arguments
verbose 'Current tmux session: %s\n' "${current_tmux_session}"
## Get list of panes
if [[ "${mode}" == "s" ]]
then
full_pane_list="$( tmux list-panes -s -F $'#D\t#W.#P' )"
else
full_pane_list="$( tmux list-panes -a -F $'#D\t#S:#W.#P' )"
fi
## Get list of panes
## Find matching panes
target_pane_ids=()
target_pane_names=()
while read -r pane_id pane_name
do
[[ "${pane_name}" =~ $matcher ]] || continue
target_pane_ids+=( "${pane_id}" )
target_pane_names+=( "${pane_name}" )
done <<< "${full_pane_list}"
## Find matching panes
(( 0 == "${#target_pane_ids[@]}" )) && die "There are no matching panes."
if (( "${list}" == 1 ))
then
echo "List of matching panes:"
echo "======================="
i=0
while (( i < ${#target_pane_ids[@]} ))
do
printf -- "- %s\n" "${target_pane_names[$i]}"
(( ++i ))
done
exit 1
fi
verbose "Waiting for line matching: >>%s<<\n" "${line_matcher}"
(( "${full}" == 0 )) || verbose "anywhere on screen(s) on:\n"
(( "${full}" == 0 )) && verbose "in the last line of:\n"
i=0
while (( i < ${#target_pane_ids[@]} ))
do
(( i > 0 )) && verbose ', '
verbose '%s:' "${target_pane_names[$i]}"
while true
do
verbose .
captured="$(
tmux capture-pane -p -t "${target_pane_ids[$i]}" | \
grep -E '[^[:space:]]'
)"
[[ -n "${skip}" ]] && captured="$( grep -vE "${skip}" <<< "${captured}" )"
(( "${full}" == 0 )) && captured="$( tail -n 1 <<< "${captured}" )"
grep -q "${line_matcher}" <<< "${captured}" && break
sleep "${wait_time}"
done
verbose '\x08+'
(( ++i ))
done
verbose '\n'
exit 0
# vim: set ft=sh:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment