Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for some text to show up in a pane

Tags:

events

tmux

In a shell script, I would love to be able to send keys to a tmux session after waiting for commands to change something in a pane.

Here is one of my use cases:

tmux send-keys -t ...  'vi .' c-m # This opens NERDTree
sleep 3                           # Sometimes sleep 2 is not enough
tmux send-keys -t ...  c-w l      # Go to tab right

The commands can trigger the send key command by means of their output, but if there is a better way I would be listening.

First idea I had, and is actually ok for my simple first use case, was a clumsy

  function wait_for_text_event
  {
       while :; do
          tmux capture-pane -t ... -p | grep "string triggering completion" && return 0
       done
       # never executed unless a timeout mechanism is implemented
       return 1
  }

Now I can do

tmux send-keys -t ... 'vi .' c-m
wait_for_text_event 'README.md'   # meaning NERDTree has opened the split window
tmux send-keys -t ...  c-w l      # Go to tab right

However Implementing timeouts gets already tricky in shell and the busy wait is ugly anyway.

Is there some command (or way to implement it) which would just block until some text shows up in a pane e.g.

tmux wait-for-text -t ... "Hello World" && tmux send-keys ...

possibly with a timeout.

Or maybe I am approaching this the wrong way?

like image 787
lab419 Avatar asked Sep 03 '25 03:09

lab419


2 Answers

You can use the builtin timeout executable in linux and run a subshell. Try something like this:

# $1: string to grep for
# $2: timeout in s
wait_for_text_event()
{
  timeout $2 bash <<EOT
  while :; do
    sleep 1
    echo "test" | grep $1 2>&1 > /dev/null && break
  done
EOT
  echo $?
}

echo $(wait_for_text_event "text" 5)   # this times out, returncode !=0
echo $(wait_for_text_event "test" 5)   # this passes, returncode == 0
like image 131
GeeF Avatar answered Sep 07 '25 17:09

GeeF


tmux capture-pane -pJ -S-10000 -t XX will print the contents of pane XX starting from up to 10000 lines up the scrollback. So you should be able to do something like

until tmux capture-pane ... | grep $TEXT >/dev/null; do :; done

You might want to add a sleep not to waste CPU, and then include some amount of the scrollback in case the text appeared and scrolled away during the sleep.

like image 35
nafg Avatar answered Sep 07 '25 19:09

nafg