pub struct Client { /* private fields */ }Expand description
One client attached to the tmux server.
Clients have no $-style id. tmux identifies them by the terminal they
occupy, so Client::name is the identity and is always present.
§Examples
let guard = libtmux::test::TestServer::new().await?;
guard.server().new_session("work").await?;
// A session created without attaching has no client, which is the usual
// shape under test and under automation.
assert!(guard.server().clients().await?.is_empty());
guard.shutdown().await?;Implementations§
Source§impl Client
impl Client
Sourcepub fn created(&self) -> SystemTime
pub fn created(&self) -> SystemTime
Return when the client connected.
tmux keeps whole seconds. ClientFields::client_created filters and
reads the same field as the i64 of Unix seconds tmux reports, because
the query grammar compares integers.
Sourcepub fn is_readonly(&self) -> bool
pub fn is_readonly(&self) -> bool
Report whether the client is attached read-only.
Sourcepub fn is_control_mode(&self) -> bool
pub fn is_control_mode(&self) -> bool
Report whether the client is a control-mode client.
Control-mode clients speak tmux’s machine protocol rather than drawing a terminal, so they are usually other programs rather than people.
Sourcepub fn is_own(&self) -> bool
Available on crate feature control-mode only.
pub fn is_own(&self) -> bool
control-mode only.Report whether this process opened this client itself.
tmux counts a control connection as an attached client, and this crate
opens them: crate::Pane::stream_output,
crate::control::ControlMode::attach and the waits built on them all
show up in a client listing beside a human’s terminal. A caller asking
“is anybody watching this session” means anybody else, so this is the
question to ask before counting.
false for every client once this process ends, since the answer is
about connections this Server is still holding open.
§Examples
let others = server
.clients()
.await?
.into_iter()
.filter(|client| !client.is_own())
.count();Sourcepub async fn refresh(&mut self) -> Result<&mut Self, Error>
pub async fn refresh(&mut self) -> Result<&mut Self, Error>
Replace this handle’s snapshot with the client’s current state.
§Errors
Returns Error::ObjectGone when the client has detached. If tmux
omits a stopped client from the listing, a probe can distinguish it as
Error::ClientSuspended. Releases that keep it listed can refresh
successfully instead. Keep the handle when the client is suspended.
Returns a listing error when tmux could not be read.
Sourcepub async fn refreshed(&self) -> Result<Self, Error>
pub async fn refreshed(&self) -> Result<Self, Error>
Return a new handle holding the client’s current state.
§Errors
Returns the same errors as Self::refresh, including
Error::ClientSuspended when an omitted client is found stopped.
A stopped client that remains listed can refresh successfully instead.
Sourcepub async fn attached_session(&self) -> Result<Option<Session>, Error>
pub async fn attached_session(&self) -> Result<Option<Session>, Error>
The session this client is attached to.
None when the client is attached to nothing, which is an ordinary
state rather than a failure.
Resolved through #{session_id} rather than #{client_session}. The
latter is what tmux calls the attachment, but it is a name, and a
name is not a handle: tmux will create a session called a:b and then
refuse to address it, because : separates a session from a window in
a target. The ID is unambiguous by construction.
Costs one tmux command. tmux fills a client’s session into the same format tree it fills the client’s own fields into, so the whole session snapshot comes back with the id rather than needing a listing after it.
$ cargo test --package libtmux --all-features --test command_budget \
asking_a_client§Errors
Returns an error when tmux cannot be reached, or answers with an ID this crate cannot parse.
§Examples
let guard = libtmux::test::TestServer::new().await?;
let server = guard.server();
let session = server.new_session("work").await?;
// A control-mode connection is a client, so the server has one to find.
let control = libtmux::control::ControlMode::attach(server, session.id()).await?;
let client = server.clients().await?.into_iter().next().expect("one client");
let attached = client.attached_session().await?.expect("it is attached");
assert_eq!(attached.id(), session.id());
control.shutdown().await?;
guard.shutdown().await?;Sourcepub async fn attached_window(&self) -> Result<Option<Window>, Error>
pub async fn attached_window(&self) -> Result<Option<Window>, Error>
The current window of the session this client is attached to.
Not this client’s own view. tmux keeps the current window on the
session – curw is a member of struct session, not of
struct client – so every client attached to one session reports the
same window, and one client changing it changes it for all of them.
None when the client is attached to nothing.
Costs one tmux command, as Self::attached_session describes.
§Errors
Returns an error when tmux cannot be reached, or answers with an ID this crate cannot parse.
Sourcepub async fn attached_pane(&self) -> Result<Option<Pane>, Error>
pub async fn attached_pane(&self) -> Result<Option<Pane>, Error>
The active pane of the current window of this client’s session.
Shares the caveat on Self::attached_window, and adds one: this is
the window’s active pane, not a per-client focus, because tmux does
not keep one. Two clients on the same session always report the same
pane.
None when the client is attached to nothing.
Costs one tmux command, as Self::attached_session describes.
§Errors
Returns an error when tmux cannot be reached, or answers with an ID this crate cannot parse.
Sourcepub async fn detach(self) -> Result<(), Error>
pub async fn detach(self) -> Result<(), Error>
Detach this client from its server.
This consumes the handle: the client is gone once it detaches.
§Errors
Returns an error when tmux refuses the command.
Sourcepub async fn suspend(&self) -> Result<(), Error>
pub async fn suspend(&self) -> Result<(), Error>
Suspend this client, as if its user pressed the suspend key.
The handle survives, and deliberately: unlike Self::detach, this
stops the client rather than ending it. Some tmux releases omit a
suspended client from Server::clients; others keep it listed.
The client resumes when its process continues with SIGCONT.
§Errors
Returns an error when tmux refuses the command. A later
Self::refresh can return Error::ClientSuspended or succeed,
depending on whether that tmux release omits the stopped client.
Sourcepub async fn lock(&self) -> Result<(), Error>
pub async fn lock(&self) -> Result<(), Error>
Lock this client’s terminal.
Runs the lock-command option, which is lock -np unless the server
was told otherwise. crate::Session::lock locks every client
attached to one session and crate::Server::lock_all locks every
client on the server; this locks exactly one.
tmux marks a locked client with the flag it uses for a suspended one,
so a locked client can leave crate::Server::clients the same way and
returns to normal when its lock-command exits. A server with
lock-after-time set reaches that state with nobody asking.
§Errors
Returns an error when tmux refuses the command. A later
Self::refresh can return Error::ClientSuspended or succeed,
depending on whether that tmux release omits the locked client.
Source§impl Client
impl Client
Sourcepub fn get<F: ReadField<Self>>(&self, field: F) -> Availability<F::Value<'_>>
Available on crate feature query only.
pub fn get<F: ReadField<Self>>(&self, field: F) -> Availability<F::Value<'_>>
query only.Read one field of this client’s snapshot, named by the handle that filters it.
Every field in ClientFields reads this way, including those with no
getter of their own. Nothing is sent to tmux, so the value is as old as
the snapshot. The result says why a field holds no value: see
Availability.
§Examples
use libtmux::Client;
use libtmux::query::Filterable as _;
let fields = Client::filter_fields();
for client in server.clients().await? {
// The key table a client is in: `prefix` right after the prefix key.
if let Some(table) = client.get(fields.client_key_table).available() {
println!("{client}: {}", table.to_string_lossy());
}
}Trait Implementations§
Source§impl Debug for Client
Renders nothing but the type.
impl Debug for Client
Renders nothing but the type.
A client name is a terminal path, which identifies the user’s machine, so it stays out of diagnostics like every other snapshot value.
impl Eq for Client
impl FilterSchema for Client
query only.Source§impl Filterable for Client
Available on crate feature query only.Filtering a client uses the same handles as the snapshot beneath it.
impl Filterable for Client
query only.Filtering a client uses the same handles as the snapshot beneath it.
Matching and validation delegate to that snapshot, so an expression can
only name fields the catalog knows. The companion is re-parameterized to
Client so the type a listing returns is the type an expression
filters.