mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-09 15:27:54 +00:00
refactor(command_parser): simplify how tokens are defined in commands
This commit is contained in:
parent
f804e7629f
commit
071db3d6d6
9 changed files with 114 additions and 76 deletions
|
|
@ -3,10 +3,11 @@ use command_parser::parameter;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn cmds() -> impl Iterator<Item = Command> {
|
pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
let ap = tokens!(["config", "cfg"], ["autoproxy", "ap"]);
|
let cfg = ("config", ["cfg"]);
|
||||||
|
let ap = tokens!(cfg, ("autoproxy", ["ap"]));
|
||||||
|
|
||||||
let ap_account = concat_tokens!(ap, [["account", "ac"]]);
|
let ap_account = tokens!(ap, ("account", ["ac"]));
|
||||||
let ap_timeout = concat_tokens!(ap, [["timeout", "tm"]]);
|
let ap_timeout = tokens!(ap, ("timeout", ["tm"]));
|
||||||
|
|
||||||
[
|
[
|
||||||
command!(ap_account => "cfg_ap_account_show")
|
command!(ap_account => "cfg_ap_account_show")
|
||||||
|
|
@ -14,9 +15,9 @@ pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
command!(ap_account, Toggle => "cfg_ap_account_update")
|
command!(ap_account, Toggle => "cfg_ap_account_update")
|
||||||
.help("Toggles autoproxy for the account"),
|
.help("Toggles autoproxy for the account"),
|
||||||
command!(ap_timeout => "cfg_ap_timeout_show").help("Shows the autoproxy timeout"),
|
command!(ap_timeout => "cfg_ap_timeout_show").help("Shows the autoproxy timeout"),
|
||||||
command!(ap_timeout, parameter::RESET => "cfg_ap_timeout_reset")
|
command!(ap_timeout, ("reset", ["clear", "default"]) => "cfg_ap_timeout_reset")
|
||||||
.help("Resets the autoproxy timeout"),
|
.help("Resets the autoproxy timeout"),
|
||||||
command!(ap_timeout, parameter::DISABLE => "cfg_ap_timeout_off")
|
command!(ap_timeout, parameter::Toggle::Off => "cfg_ap_timeout_off")
|
||||||
.help("Disables the autoproxy timeout"),
|
.help("Disables the autoproxy timeout"),
|
||||||
command!(ap_timeout, ("timeout", OpaqueString) => "cfg_ap_timeout_update")
|
command!(ap_timeout, ("timeout", OpaqueString) => "cfg_ap_timeout_update")
|
||||||
.help("Sets the autoproxy timeout"),
|
.help("Sets the autoproxy timeout"),
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use super::*;
|
||||||
|
|
||||||
pub fn cmds() -> impl Iterator<Item = Command> {
|
pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
[
|
[
|
||||||
command!(["thunder"] => "fun_thunder"),
|
command!("thunder" => "fun_thunder"),
|
||||||
command!(["meow"] => "fun_meow"),
|
command!("meow" => "fun_meow"),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn cmds() -> impl Iterator<Item = Command> {
|
pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
let help = ["help", "h"];
|
let help = ("help", ["h"]);
|
||||||
[
|
[
|
||||||
command!([help] => "help")
|
command!(help => "help")
|
||||||
.flag(("foo", OpaqueString)) // todo: just for testing
|
.flag(("foo", OpaqueString)) // todo: just for testing
|
||||||
.help("Shows the help command"),
|
.help("Shows the help command"),
|
||||||
command!([help, "commands"] => "help_commands").help("help commands"),
|
command!(help, "commands" => "help_commands").help("help commands"),
|
||||||
command!([help, "proxy"] => "help_proxy").help("help proxy"),
|
command!(help, "proxy" => "help_proxy").help("help proxy"),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ pub mod server_config;
|
||||||
pub mod switch;
|
pub mod switch;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
|
|
||||||
use command_parser::{
|
use command_parser::{command, command::Command, parameter::ParameterKind::*, tokens};
|
||||||
command, command::Command, concat_tokens, parameter::ParameterKind::*, tokens,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn all() -> impl Iterator<Item = Command> {
|
pub fn all() -> impl Iterator<Item = Command> {
|
||||||
(help::cmds())
|
(help::cmds())
|
||||||
|
|
@ -29,3 +27,5 @@ pub fn all() -> impl Iterator<Item = Command> {
|
||||||
.chain(config::cmds())
|
.chain(config::cmds())
|
||||||
.chain(fun::cmds())
|
.chain(fun::cmds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const RESET: (&str, [&str; 2]) = ("reset", ["clear", "default"]);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn cmds() -> impl Iterator<Item = Command> {
|
pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
let member = ["member", "m"];
|
let member = ("member", ["m"]);
|
||||||
let description = ["description", "desc"];
|
let description = ("description", ["desc"]);
|
||||||
let privacy = ["privacy", "priv"];
|
let privacy = ("privacy", ["priv"]);
|
||||||
let new = ["new", "n"];
|
let new = ("new", ["n"]);
|
||||||
|
|
||||||
let member_target = tokens!(member, MemberRef);
|
let member_target = tokens!(member, MemberRef);
|
||||||
let member_desc = concat_tokens!(member_target, [description]);
|
let member_desc = tokens!(member_target, description);
|
||||||
let member_privacy = concat_tokens!(member_target, [privacy]);
|
let member_privacy = tokens!(member_target, privacy);
|
||||||
|
|
||||||
[
|
[
|
||||||
command!([member, new, ("name", OpaqueString)] => "member_new")
|
command!(member, new, ("name", OpaqueString) => "member_new")
|
||||||
.help("Creates a new system member"),
|
.help("Creates a new system member"),
|
||||||
command!(member_target => "member_show")
|
command!(member_target => "member_show")
|
||||||
.flag("pt")
|
.flag("pt")
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn cmds() -> impl Iterator<Item = Command> {
|
pub fn cmds() -> impl Iterator<Item = Command> {
|
||||||
let system = ["system", "s"];
|
let system = ("system", ["s"]);
|
||||||
let new = ["new", "n"];
|
let new = ("new", ["n"]);
|
||||||
|
|
||||||
let system_new = tokens!(system, new);
|
let system_new = tokens!(system, new);
|
||||||
|
|
||||||
[
|
[
|
||||||
command!([system] => "system_show").help("Shows information about your system"),
|
command!(system => "system_show").help("Shows information about your system"),
|
||||||
command!(system_new => "system_new").help("Creates a new system"),
|
command!(system_new => "system_new").help("Creates a new system"),
|
||||||
command!(system_new, ("name", OpaqueString) => "system_new_name")
|
command!(system_new, ("name", OpaqueString) => "system_new_name")
|
||||||
.help("Creates a new system (using the provided name)"),
|
.help("Creates a new system (using the provided name)"),
|
||||||
|
|
|
||||||
|
|
@ -90,27 +90,7 @@ impl Display for Command {
|
||||||
// (and something like &dyn Trait would require everything to be referenced which doesnt look nice anyway)
|
// (and something like &dyn Trait would require everything to be referenced which doesnt look nice anyway)
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! command {
|
macro_rules! command {
|
||||||
([$($v:expr),+] => $cb:expr$(,)*) => {
|
($($v:expr),+ => $cb:expr$(,)*) => {
|
||||||
$crate::command::Command::new($crate::tokens!($($v),+), $cb)
|
$crate::command::Command::new($crate::tokens!($($v),+), $cb)
|
||||||
};
|
};
|
||||||
($tokens:expr => $cb:expr$(,)*) => {
|
|
||||||
$crate::command::Command::new($tokens.clone(), $cb)
|
|
||||||
};
|
|
||||||
($tokens:expr, $($v:expr),+ => $cb:expr$(,)*) => {
|
|
||||||
$crate::command::Command::new($crate::concat_tokens!($tokens.clone(), [$($v),+]), $cb)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! tokens {
|
|
||||||
($($v:expr),+$(,)*) => {
|
|
||||||
[$($crate::token::Token::from($v)),+]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! concat_tokens {
|
|
||||||
($tokens:expr, [$($v:expr),+]$(,)*) => {
|
|
||||||
$tokens.clone().into_iter().chain($crate::tokens!($($v),+).into_iter()).collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ use std::{fmt::Debug, str::FromStr};
|
||||||
|
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
|
use crate::token::Token;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ParameterValue {
|
pub enum ParameterValue {
|
||||||
OpaqueString(String),
|
OpaqueString(String),
|
||||||
|
|
@ -180,10 +182,7 @@ impl FromStr for PrivacyLevelKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ENABLE: [&str; 5] = ["on", "yes", "true", "enable", "enabled"];
|
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
|
||||||
pub const DISABLE: [&str; 5] = ["off", "no", "false", "disable", "disabled"];
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
|
||||||
pub enum Toggle {
|
pub enum Toggle {
|
||||||
On,
|
On,
|
||||||
Off,
|
Off,
|
||||||
|
|
@ -193,10 +192,20 @@ impl FromStr for Toggle {
|
||||||
type Err = SmolStr;
|
type Err = SmolStr;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
let matches_self =
|
||||||
ref s if ENABLE.contains(s) => Ok(Self::On),
|
|toggle: &Self| matches!(Token::from(*toggle).try_match(Some(s)), Some(Ok(None)));
|
||||||
ref s if DISABLE.contains(s) => Ok(Self::Off),
|
[Self::On, Self::Off]
|
||||||
_ => Err("invalid toggle, must be on/off".into()),
|
.into_iter()
|
||||||
|
.find(matches_self)
|
||||||
|
.ok_or_else(|| SmolStr::new("invalid toggle, must be on/off"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Toggle> for Token {
|
||||||
|
fn from(toggle: Toggle) -> Self {
|
||||||
|
match toggle {
|
||||||
|
Toggle::On => Self::from(("on", ["yes", "true", "enable", "enabled"])),
|
||||||
|
Toggle::Off => Self::from(("off", ["no", "false", "disable", "disabled"])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -209,5 +218,3 @@ impl Into<bool> for Toggle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const RESET: [&str; 3] = ["reset", "clear", "default"];
|
|
||||||
|
|
|
||||||
|
|
@ -104,46 +104,96 @@ impl Token {
|
||||||
impl Display for Token {
|
impl Display for Token {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Token::Empty => write!(f, ""),
|
Self::Empty => write!(f, ""),
|
||||||
Token::Value { name, .. } => write!(f, "{name}"),
|
Self::Value { name, .. } => write!(f, "{name}"),
|
||||||
Token::Parameter(param) => param.kind().format(f, param.name()),
|
Self::Parameter(param) => param.kind().format(f, param.name()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const L: usize> From<(&str, [&str; L])> for Token {
|
||||||
|
fn from((name, aliases): (&str, [&str; L])) -> Self {
|
||||||
|
Self::Value {
|
||||||
|
name: name.into(),
|
||||||
|
aliases: aliases.into_iter().map(SmolStr::new).collect::<Vec<_>>(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Token {
|
impl From<&str> for Token {
|
||||||
fn from(name: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
Token::Value {
|
Self::from((value, []))
|
||||||
name: SmolStr::new(name),
|
|
||||||
aliases: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const L: usize> From<[&str; L]> for Token {
|
|
||||||
fn from(value: [&str; L]) -> Self {
|
|
||||||
assert!(value.len() > 0, "can't create a Token::Value from nothing");
|
|
||||||
Token::Value {
|
|
||||||
name: value[0].into(),
|
|
||||||
aliases: value.into_iter().skip(1).map(SmolStr::new).collect::<Vec<_>>(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Parameter> for Token {
|
impl From<Parameter> for Token {
|
||||||
fn from(value: Parameter) -> Self {
|
fn from(value: Parameter) -> Self {
|
||||||
Token::Parameter(value)
|
Self::Parameter(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParameterKind> for Token {
|
impl From<ParameterKind> for Token {
|
||||||
fn from(value: ParameterKind) -> Self {
|
fn from(value: ParameterKind) -> Self {
|
||||||
Token::from(Parameter::from(value))
|
Self::from(Parameter::from(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(&str, ParameterKind)> for Token {
|
impl From<(&str, ParameterKind)> for Token {
|
||||||
fn from(value: (&str, ParameterKind)) -> Self {
|
fn from(value: (&str, ParameterKind)) -> Self {
|
||||||
Token::from(Parameter::from(value))
|
Self::from(Parameter::from(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TokensIterator {
|
||||||
|
inner: Vec<Token>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for TokensIterator {
|
||||||
|
type Item = Token;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
(self.inner.len() > 0).then(|| self.inner.remove(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<Token>> From<T> for TokensIterator {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: vec![value.into()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const L: usize> From<[Token; L]> for TokensIterator {
|
||||||
|
fn from(value: [Token; L]) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: value.into_iter().collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const L: usize> From<[Self; L]> for TokensIterator {
|
||||||
|
fn from(value: [Self; L]) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: value
|
||||||
|
.into_iter()
|
||||||
|
.map(|t| t.collect::<Vec<_>>())
|
||||||
|
.flatten()
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Token>> for TokensIterator {
|
||||||
|
fn from(value: Vec<Token>) -> Self {
|
||||||
|
Self { inner: value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! tokens {
|
||||||
|
($($v:expr),+$(,)*) => {
|
||||||
|
$crate::token::TokensIterator::from([$($crate::token::TokensIterator::from($v.clone())),+])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue