#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct ClientTitleState {
pub(super) title: Option<String>,
pub(super) path: Option<String>,
}
impl ClientTitleState {
#[cfg_attr(not(test), allow(dead_code))]
pub(crate) fn title(&self) -> Option<&str> {
self.title.as_deref()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct RenderedClientTitle {
state: ClientTitleState,
bytes: Vec<u8>,
}
impl RenderedClientTitle {
pub(crate) const fn state(&self) -> &ClientTitleState {
&self.state
}
pub(crate) const fn wrote(&self) -> bool {
!self.bytes.is_empty()
}
pub(crate) fn bytes(&self) -> &[u8] {
&self.bytes
}
pub(crate) fn committed(&self) -> Option<&ClientTitleState> {
self.wrote().then_some(&self.state)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum ClientPathUpdate<'a> {
#[default]
Unread,
Reported(&'a str),
Cleared,
}
impl<'a> ClientPathUpdate<'a> {
pub(crate) fn from_pane(path: &'a str) -> Self {
if path.is_empty() {
Self::Cleared
} else {
Self::Reported(path)
}
}
const fn payload(self) -> Option<&'a str> {
match self {
Self::Unread => None,
Self::Reported(path) => Some(path),
Self::Cleared => Some(""),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct ClientTitleUpdate<'a> {
pub(crate) resolved: Option<&'a str>,
pub(crate) path: ClientPathUpdate<'a>,
pub(crate) previous: Option<&'a ClientTitleState>,
}
impl<'a> ClientTitleUpdate<'a> {
pub(super) fn pending_title(&self) -> Option<&'a str> {
let resolved = self.resolved?;
(self.previous.and_then(|previous| previous.title.as_deref()) != Some(resolved))
.then_some(resolved)
}
pub(super) fn pending_path(&self) -> Option<&'a str> {
self.resolved?;
let path = self.path.payload()?;
(self.previous.and_then(|previous| previous.path.as_deref()) != Some(path)).then_some(path)
}
#[cfg(test)]
pub(super) fn rendered_by(
&self,
terminal: &super::OuterTerminal,
) -> Option<RenderedClientTitle> {
terminal.rendered_client_title(*self)
}
pub(super) fn rendered(&self, bytes: Vec<u8>) -> Option<RenderedClientTitle> {
let resolved = self.resolved?;
Some(RenderedClientTitle {
bytes,
state: ClientTitleState {
title: Some(resolved.to_owned()),
path: self.path.payload().map(str::to_owned).or_else(|| {
self.previous
.and_then(|previous| previous.path.as_ref())
.cloned()
}),
},
})
}
}