use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SigilCommand {
pub verb: Verb,
pub target: Option<SigilRef>,
pub args: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Verb {
Ls,
Cat,
Find,
Grep,
Man,
Save,
Set,
Rm,
Lbl,
}
impl Verb {
pub fn requires_target(self) -> bool {
!matches!(self, Self::Man | Self::Save)
}
}
impl fmt::Display for Verb {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::Ls => "ls",
Self::Cat => "cat",
Self::Find => "find",
Self::Grep => "grep",
Self::Man => "man",
Self::Save => "save",
Self::Set => "set",
Self::Rm => "rm",
Self::Lbl => "lbl",
};
f.write_str(s)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SigilRef {
Scope(ScopeRef),
Positional(std::num::NonZeroU8),
Id(String),
Named(NamedRef),
}
impl SigilRef {
pub fn is_collection(&self) -> bool {
matches!(
self,
Self::Scope(ScopeRef { modifier: Modifier::All, .. }) | Self::Named(NamedRef::All)
)
}
pub fn is_instance(&self) -> bool {
!self.is_collection()
}
}
impl fmt::Display for SigilRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Scope(s) => write!(f, "{s}"),
Self::Positional(d) => {
for _ in 0..d.get() {
f.write_str("^")?;
}
Ok(())
}
Self::Id(id) => f.write_str(id),
Self::Named(n) => write!(f, "{n}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScopeRef {
pub scope: Scope,
pub modifier: Modifier,
}
impl fmt::Display for ScopeRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let prefix = match self.scope {
Scope::User => '@',
Scope::Channel => '#',
};
match &self.modifier {
Modifier::Current => write!(f, "{prefix}~"),
Modifier::All => write!(f, "{prefix}*"),
Modifier::Name(n) => write!(f, "{prefix}{n}"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Scope {
User,
Channel,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Modifier {
Current,
All,
Name(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NamedRef {
Label(String),
All,
}
impl fmt::Display for NamedRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Label(l) => write!(f, ":{l}"),
Self::All => f.write_str(":*"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseError {
NotSigil,
MissingVerb,
UnknownVerb(String),
MissingTarget { verb: Verb },
InvalidTarget { got: String },
DeprecatedSigil(String),
MissingSearchTerm { verb: Verb },
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotSigil => write!(f, "Not a sigil command (must start with @@/)"),
Self::MissingVerb => write!(f, "Missing verb after @@/"),
Self::UnknownVerb(v) => write!(f, "Unknown verb '{v}'"),
Self::MissingTarget { verb } => {
write!(f, "'{verb}' requires a target")
}
Self::InvalidTarget { got } => {
write!(f, "Invalid target '{got}'")
}
Self::DeprecatedSigil(msg) => write!(f, "{msg}"),
Self::MissingSearchTerm { verb } => {
write!(f, "'{verb}' requires a search term. Did you mean 'ls'?")
}
}
}
}