use std::ffi::OsString;
use crate::formats::TmuxText;
use crate::internal::core::Core;
use crate::{Command, Error};
#[derive(Clone, Copy, Debug)]
pub(crate) enum Scope<'target> {
Server,
GlobalSession,
GlobalWindow,
Session(&'target str),
Window(&'target str),
Pane(&'target str),
}
impl Scope<'_> {
fn apply(self, command: Command) -> Command {
match self {
Self::Server => command.arg("-s"),
Self::GlobalSession => command.arg("-g"),
Self::GlobalWindow => command.arg("-w").arg("-g"),
Self::Session(target) => command.arg("-t").arg(OsString::from(target)),
Self::Window(target) => command.arg("-w").arg("-t").arg(OsString::from(target)),
Self::Pane(target) => command.arg("-p").arg("-t").arg(OsString::from(target)),
}
}
}
pub(crate) async fn get(
core: &Core,
scope: Scope<'_>,
name: &str,
) -> Result<Option<TmuxText>, Error> {
let command = scope
.apply(Command::new("show-options"))
.arg("-v")
.arg(OsString::from(name));
let result = core.execute(command).await?;
if !result.success() {
if name.starts_with('@') {
return Ok(None);
}
return Err(Error::CommandFailed {
command: "show-options",
exit_code: result.exit_code(),
stderr: result.stderr_lossy().into_owned(),
});
}
let stdout = result.stdout();
let value = stdout.strip_suffix(b"\n").unwrap_or(stdout);
if value.is_empty() {
return Ok(None);
}
Ok(Some(TmuxText::from(value.to_vec())))
}
pub(crate) async fn names(core: &Core, scope: Scope<'_>) -> Result<Vec<String>, Error> {
let result = core
.execute(scope.apply(Command::new("show-options")))
.await?;
if !result.success() {
return Err(Error::CommandFailed {
command: "show-options",
exit_code: result.exit_code(),
stderr: result.stderr_lossy().into_owned(),
});
}
Ok(result
.stdout_lossy()
.lines()
.filter_map(|line| line.split_whitespace().next())
.map(ToOwned::to_owned)
.collect())
}
pub(crate) async fn set(
core: &Core,
scope: Scope<'_>,
name: &str,
value: impl Into<OsString>,
append: bool,
) -> Result<(), Error> {
let mut command = scope.apply(Command::new("set-option"));
if append {
command = command.arg("-a");
}
run(
core,
command
.arg(OsString::from(name))
.sensitive_arg(value.into()),
)
.await
}
pub(crate) async fn unset(core: &Core, scope: Scope<'_>, name: &str) -> Result<(), Error> {
run(
core,
scope
.apply(Command::new("set-option"))
.arg("-u")
.arg(OsString::from(name)),
)
.await
}
pub(crate) async fn set_hook(
core: &Core,
scope: Scope<'_>,
name: &str,
command_text: impl Into<OsString>,
) -> Result<(), Error> {
run(
core,
scope
.apply(Command::new("set-hook"))
.arg(OsString::from(name))
.sensitive_arg(command_text.into()),
)
.await
}
pub(crate) async fn unset_hook(core: &Core, scope: Scope<'_>, name: &str) -> Result<(), Error> {
run(
core,
scope
.apply(Command::new("set-hook"))
.arg("-u")
.arg(OsString::from(name)),
)
.await
}
async fn run(core: &Core, command: Command) -> Result<(), Error> {
let result = core.execute(command).await?;
if result.success() {
return Ok(());
}
Err(Error::CommandFailed {
command: "set-option",
exit_code: result.exit_code(),
stderr: result.stderr_lossy().into_owned(),
})
}