Core LibraryalphaAPI Reference

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.

method libtmux-rs latest

QueryIteratorExt.exactly_one

Return the only item, or an error for zero or multiple items.

Source and package
Qualified name
query.QueryIteratorExt.exactly_one
Module
query
Declared in
QueryIteratorExt
Package
libtmux
Source
crates/libtmux/src/query.rs
#[allow(clippy::module_name_repetitions)] pub trait QueryIteratorExt: Iterator + Sized fn exactly_one(mut self) -> Result< Self::Item, ExactlyOneError >

Description#

At most two items are pulled from the iterator.

Errors

Returns ExactlyOneError::NoItems for an empty iterator and ExactlyOneError::MultipleItems when a second item is present.

Examples#

use libtmux::query::QueryIteratorExt;
let values = [7];
assert_eq!(values.iter().exactly_one(), Ok(&values[0]));

Handle missing and ambiguous matches. Compare exactly_one and one_or_none for no match, one match and multiple matches. Use a Unix environment with Git, rustup, and tmux 3.3a or newer. The toolchain file below pins Rust 1.97.1. In an empty directory, fetch the documented source:

Terminal window
$ git clone https://github.com/libtmux/libtmux-rs.git libtmux-source &&
git -C libtmux-source checkout --detach 84de9258a07d10bdd5f6da01b016a9ae06fe1210

Save this complete consumer setup as Cargo.toml: View source

[package]
name = "libtmux-api-example"
version = "0.0.0"
edition = "2024"
publish = false
[workspace]
exclude = ["libtmux-source"]
[dependencies]
libtmux = { path = "libtmux-source/crates/libtmux" }
tempfile = "3.20"
tokio = { version = "1.40", features = ["macros", "rt", "time"] }

Save this complete consumer setup as rust-toolchain.toml: View source

[toolchain]
channel = "1.97.1"
components = ["clippy", "rust-src", "rustfmt"]
profile = "minimal"

Save this complete program as src/main.rs. 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

//! Distinguish no match, one match and multiple matches.
use std::error::Error;
use std::time::Duration;
use libtmux::query::{ExactlyOneError, Filterable as _, MultipleItemsError, QueryIteratorExt as _};
use libtmux::{NewSessionOptions, Server, Session};
type ExampleError = Box<dyn Error>;
fn check(condition: bool, message: &str) -> Result<(), ExampleError> {
if condition {
Ok(())
} else {
Err(message.into())
}
}
async fn demonstrate(server: &Server) -> Result<(), ExampleError> {
server
.new_session(NewSessionOptions::new("work").command("cat"))
.await?;
server
.new_session(NewSessionOptions::new("review").command("cat"))
.await?;
let sessions = server.sessions().await?;
let fields = Session::filter_fields();
let work = fields.session_name.eq("work");
let missing = fields.session_name.eq("missing");
check(
sessions
.iter()
.matching(&work)
.exactly_one()?
.name()
.as_bytes()
== b"work",
"wrong single match",
)?;
check(
sessions.iter().matching(&missing).one_or_none()?.is_none(),
"missing match was present",
)?;
check(
matches!(
sessions.iter().matching(&missing).exactly_one(),
Err(ExactlyOneError::NoItems)
),
"missing match did not report NoItems",
)?;
check(
matches!(
sessions.iter().exactly_one(),
Err(ExactlyOneError::MultipleItems)
),
"ambiguous match was accepted",
)?;
check(
matches!(sessions.iter().one_or_none(), Err(MultipleItemsError)),
"optional lookup accepted multiple matches",
)?;
println!("cardinality: none, one, multiple");
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-cardinality-")
.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())
}
}

Copy the complete files from the pinned checkout and run the consumer. This also creates src for the displayed program. Success exits with status 0; setup, operation, deadline or cleanup failures exit unsuccessfully and print diagnostics to stderr:

Terminal window
$ mkdir -p src &&
cp libtmux-source/crates/libtmux/examples/api/consumer.toml Cargo.toml &&
cp libtmux-source/rust-toolchain.toml rust-toolchain.toml &&
cp libtmux-source/crates/libtmux/examples/api_cardinality.rs src/main.rs &&
cargo run --quiet

Expected output:

cardinality: none, one, multiple
Parameters

Discussed in Filtering and queries

Esc

Type to search.

Reference preview Open reference