Core LibraryalphaExamples

Choose documentation 3

latest

Current version

latest
English

Prerelease This site documents an alpha of libtmux. Its structure, URLs and APIs are subject to change.

Edit this page on GitHub

Attach and send keys

Get a session handle, send a command to a pane, and capture output. These examples use libtmux from your program; to attach your terminal interactively, see Attaching to tmux.

The examples include setup, error handling, and cleanup. Source and verification identifies their files and checks.

//! Build a throwaway session, use it, and leave nothing behind.
//!
//! ```console
//! $ cargo run --example scratch
//! ```
use std::time::Duration;
use libtmux::test::unique_name;
use libtmux::{NewWindowOptions, PaneWait, Server, SplitDirection, SplitOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// An example must not build sessions on whatever server the reader
// happens to be using, so this one gets a socket of its own. More than one
// libtmux runs on a developer's machine, so it goes in a directory this
// one owns rather than straight into the temporary directory.
let root = std::path::Path::new("/tmp/libtmux-rs-dev");
std::fs::create_dir_all(root)?;
let socket = root.join(format!("{}.sock", unique_name("libtmux-scratch")));
let server = Server::builder().socket_path(&socket).build()?;
// The scope kills the session whether the body succeeds or fails, so a
// failure partway through does not leave a session behind.
println!("server on {}", socket.display());
let output = server
.with_session(unique_name("scratch").as_str(), async |session| {
println!(" session {} created", session.id());
let window = session
.new_window(NewWindowOptions::new("work").command("sh"))
.await?;
println!(" window {} running sh", window.id());
window
.split(SplitOptions::new(SplitDirection::Below).command("sh"))
.await?;
println!(" split it: {} panes", window.panes().await?.len());
// A window always has an active pane, but saying so with a panic
// would be a worse example than handling it.
let Some(pane) = window.active_pane().await? else {
return Ok(0);
};
println!(" typing into {}", pane.id());
pane.send_line("printf 'hello from tmux\\n'").await?;
// tmux runs the shell asynchronously, so wait for the output
// rather than sleeping and hoping. The outcome is checked because
// a wait that reached its deadline still returns successfully.
match pane.wait_for_text("hello", Duration::from_secs(5)).await? {
PaneWait::Arrived => println!(" the pane printed it"),
other => println!(" gave up: {other:?}"),
}
// region: capture
let lines = pane.capture().await?;
for line in lines.iter().filter(|line| !line.as_bytes().is_empty()) {
println!(" | {}", line.to_string_lossy());
}
// endregion
Ok::<_, Box<dyn std::error::Error>>(lines.len())
})
.await?;
println!("captured {output} lines, then the scope killed the session");
// The lenient form is the one that answers this question. The scope killed
// the only session, so tmux exited with it, and the loud form reports that
// as the failure it is rather than as the empty listing this is asking for.
assert!(
server.sessions().await.unwrap_or_default().is_empty(),
"the scope cleaned up",
);
println!(
"sessions left behind: {}",
server.sessions().await.unwrap_or_default().len()
);
server.shutdown().await?;
// tmux does not unlink its socket when the server exits, so whatever named
// one owns removing it. Leaving it behind is invisible until /tmp fills up.
std::fs::remove_file(&socket)?;
Ok(())
}

Finding an existing session instead

For a script that runs repeatedly, look up a session before creating it. Attaching to tmux shows that pattern, and Filtering and querying, in practice covers absent and ambiguous matches.

Where this comes from

Source: crates/libtmux/examples/scratch.rs

In this page: read whole from the file

Checked by: run to completion against a throwaway tmux by scripts/run-examples.sh (just examples), which CI runs and which also asserts the example leaves no session behind

Source inclusion

A file="..." fence reads the named source during the site build. Hand-quoted excerpts are copies; their source files and regions are listed above.

Esc

Type to search.

Reference preview Open reference