use std::fmt;
use flagset::FlagSet;
use crate::element::{ActionKind, AtomicTag};
pub struct SupportResponse<I>
where
I: IntoIterator + Clone,
I::Item: AsRef<str>,
{
iter: I,
supported: FlagSet<ActionKind>,
}
impl<I> SupportResponse<I>
where
I: IntoIterator + Clone,
I::Item: AsRef<str>,
{
pub fn new(iter: I, supported: FlagSet<ActionKind>) -> Self {
Self { iter, supported }
}
fn write_supported(&self, f: &mut fmt::Formatter, query: &str) -> fmt::Result {
let (name, arg) = match query.split_once('.') {
Some((name, arg)) => (name, Some(arg)),
None => (query, None),
};
match AtomicTag::well_known(name) {
Some(tag) if self.supported.contains(tag.action) => match arg {
None => Self::write_can(f, name),
Some("*") => Self::write_can_args(f, name, tag),
Some(arg) if tag.supports(arg) => Self::write_can_arg(f, name, arg),
Some(arg) => Self::write_cant_arg(f, name, arg),
},
_ => Self::write_cant(f, name),
}
}
fn write_all_supported(&self, f: &mut fmt::Formatter) -> fmt::Result {
for tag in AtomicTag::supported() {
if self.supported.contains(tag.action) {
Self::write_can(f, tag.name)?;
Self::write_can_args(f, tag.name, tag)?;
}
}
if !self.supported.contains(ActionKind::Font) && self.supported.contains(ActionKind::Color)
{
write!(f, " +font +font.color +font.back")?;
}
Ok(())
}
fn write_cant(f: &mut fmt::Formatter, tag: &str) -> fmt::Result {
write!(f, " -{tag}")
}
fn write_can(f: &mut fmt::Formatter, tag: &str) -> fmt::Result {
write!(f, " +{tag}")
}
fn write_can_arg(f: &mut fmt::Formatter, tag: &str, arg: &str) -> fmt::Result {
write!(f, " +{tag}.{arg}")
}
fn write_cant_arg(f: &mut fmt::Formatter, tag: &str, arg: &str) -> fmt::Result {
write!(f, " -{tag}.{arg}")
}
fn write_can_args(f: &mut fmt::Formatter, name: &str, tag: &AtomicTag) -> fmt::Result {
for arg in tag.args {
write!(f, " +{name}.{arg}")?;
}
Ok(())
}
}
impl<I> fmt::Display for SupportResponse<I>
where
I: IntoIterator + Clone,
I::Item: AsRef<str>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\x1B[1z<SUPPORTS")?;
let mut has_args = false;
for arg in self.iter.clone() {
has_args = true;
self.write_supported(f, arg.as_ref())?;
}
if !has_args {
self.write_all_supported(f)?;
}
write!(f, ">\r\n")
}
}