Core Library0.xAPI Reference

Choose documentation 3

latest

Current version

latest
English

Early release libtmux is released, and its APIs may still change between releases. This site's structure and URLs may change too.

method libtmux-rs latest

Pane.wait_for_text

Wait until this pane's output contains needle.

Source and package
Qualified name
libtmux::pane::Pane::wait_for_text
Module
pane
Declared in
Pane
Package
libtmux
Source
crates/libtmux/src/pane/observe.rs
pub async fn wait_for_text( &self, needle: impl AsRef<[u8]>, within: Duration, ) -> Result<PaneWait, Error>

Description#

Pane::wait_until() takes a predicate over the lines instead.

Polls rather than streams, so it needs no feature: a caller who dispatches a command needs to know when it finished, and Pane::send_keys() without that is half an operation. A control-mode subscription would answer sooner and is not available in a default build.

A look costs one capture-pane and looks are 120ms apart, which keeps a wait under ten dispatches a second and answers within an interval of the text appearing. The first look comes before the first sleep, so text already there when the wait begins is answered at once, and a within shorter than one interval buys exactly one look.

Each look reads the scrollback rather than the visible screen, and joins lines tmux wrapped. Both matter for correctness rather than completeness: text that scrolled off before the look would otherwise be missed and reported as absent, and a line wider than the pane arrives split, so a needle spanning the wrap point would never match.

A pane whose process ends answers PaneWait::Dead rather than running to the deadline, because waiting longer cannot change it. So does a pane that tmux removes mid-wait and a server that exits mid-wait. The answer carries no text: the wait keeps none, so output seen before the pane or server ended is not recoverable from it.

A Pane::capture() called immediately after this returns can occasionally miss the very output that satisfied the wait: tmux's own redraw of the screen a fast, multi-byte-heavy write produced can still be in flight when the next capture-pane reads it, independent of this crate. Raw tmux shows the same gap running the equivalent send-keys/capture-pane sequence directly. A caller sensitive to this should retry the capture rather than trust it on the first look.

Errors

Returns an error when tmux cannot be reached or refuses a capture for a reason other than the pane or server ending, which is PaneWait::Dead. Running out of time is PaneWait::TimedOut, not an error.

Cancel safety

Nothing happened. A look only reads, so output a dropped wait missed stays in the scrollback, up to history-limit, for the next wait.

Examples#

use libtmux::PaneWait;
use std::time::Duration;
pane.send_line("printf 'ready\\n'").await?;
let seen = pane.wait_for_text("ready", Duration::from_secs(10)).await?;
assert_eq!(seen, PaneWait::Arrived);

Capture complete output lines. Submit a shell command atomically and wait for whole output lines within a deadline. Use Rust 1.85 or newer with Cargo, and tmux 3.3a or newer, on a Unix system. In an empty directory, create a project and add the published crates:

Terminal window
$ cargo init --name libtmux-api-example &&
cargo add libtmux@0.1.2 tempfile@3.20 &&
cargo add tokio@1.40 --features macros,rt,time

Replace src/main.rs with this complete program. It owns a private tmux socket, applies a ten-second task deadline, and reports both task and cleanup errors. Server::kill() stops its daemon; Server::shutdown() closes its client executor. Successful cleanup removes the temporary directory even when the task fails. View source

//! Capture complete output lines after submitting a shell command.
use std::error::Error;
use std::time::Duration;
use libtmux::{NewSessionOptions, PaneWait, Server};
type ExampleError = Box<dyn Error>;
async fn demonstrate(server: &Server) -> Result<(), ExampleError> {
let session = server
.new_session(
NewSessionOptions::new("capture").command("env ENV=/dev/null PS1='api-ready> ' sh"),
)
.await?;
let panes = session.panes().await?;
let pane = panes.first().ok_or("session has no pane")?;
if pane
.wait_for_text("api-ready>", Duration::from_secs(5))
.await?
!= PaneWait::Arrived
{
return Err("shell prompt did not become ready".into());
}
pane.send_line("printf '\\nfirst line\\nsecond line\\n'")
.await?;
loop {
let lines = pane.capture().await?;
if lines.iter().any(|line| line.as_bytes() == b"first line")
&& lines.iter().any(|line| line.as_bytes() == b"second line")
{
break;
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
println!("capture: first line, second line");
Ok(())
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), ExampleError> {
let root = std::path::Path::new("/tmp/libtmux-rs-dev");
std::fs::create_dir_all(root)?;
let directory = tempfile::Builder::new()
.prefix("api-capture-")
.tempdir_in(root)?;
std::fs::write(
directory.path().join("owner"),
std::process::id().to_string(),
)?;
let server = Server::builder()
.socket_path(directory.path().join("tmux.sock"))
.config_file("/dev/null")
.default_timeout(Duration::from_secs(5))
.build()?;
let outcome = tokio::time::timeout(Duration::from_secs(10), demonstrate(&server)).await;
// Stop the owned daemon before closing the client executor.
let killed = server.kill().await;
let closed = server.shutdown().await;
let cleanup_failed = killed.is_err() || closed.is_err();
let mut failures = Vec::new();
match outcome {
Ok(Ok(())) => {}
Ok(Err(error)) => failures.push(format!("example failed: {error}")),
Err(error) => failures.push(format!("example deadline: {error}")),
}
if let Err(error) = killed {
failures.push(format!("daemon cleanup: {error}"));
}
if let Err(error) = closed {
failures.push(format!("executor cleanup: {error}"));
}
if cleanup_failed {
let retained = directory.keep();
failures.push(format!("inspect retained directory {}", retained.display()));
} else if let Err(error) = directory.close() {
failures.push(format!("directory cleanup: {error}"));
}
if failures.is_empty() {
Ok(())
} else {
Err(failures.join("; ").into())
}
}

Run the consumer. Success exits with status 0; setup, operation, deadline or cleanup failures exit unsuccessfully and print diagnostics to stderr:

Terminal window
$ cargo run --quiet

Expected output:

capture: first line, second line
Parameters

tmux command#

The tmux commands behind wait_for_text.

tmux C API#

The C declarations in tmux that implement these commands.

Esc

Type to search.

Reference previewOpen reference