mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 04:56:49 +00:00
remove command_system_macros
This commit is contained in:
parent
737d6d3216
commit
b6eec3784d
5 changed files with 93 additions and 176 deletions
|
|
@ -1,12 +0,0 @@
|
|||
[package]
|
||||
name = "command_system_macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
syn = "2.0"
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
use proc_macro2::{Delimiter, TokenStream, TokenTree, Literal, Span};
|
||||
use syn::parse::{Parse, ParseStream, Result as ParseResult};
|
||||
use syn::{parse_macro_input, Token, Ident};
|
||||
use quote::{quote, quote_spanned};
|
||||
|
||||
enum CommandToken {
|
||||
/// "typed argument" being a member of the `Token` enum in the
|
||||
/// command parser crate.
|
||||
///
|
||||
/// prefixed with `@` in the command macro.
|
||||
TypedArgument(Ident, Span),
|
||||
|
||||
/// interpreted as a literal string in the command input.
|
||||
///
|
||||
/// no prefix in the command macro.
|
||||
Literal(Literal, Span),
|
||||
}
|
||||
|
||||
impl Parse for CommandToken {
|
||||
fn parse(input: ParseStream) -> ParseResult<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![@]) {
|
||||
// typed argument
|
||||
input.parse::<Token![@]>()?;
|
||||
let ident = input.parse::<Ident>()?;
|
||||
Ok(Self::TypedArgument(ident.clone(), ident.span()))
|
||||
} else if lookahead.peek(Ident) {
|
||||
// literal string
|
||||
let ident = input.parse::<Ident>()?;
|
||||
let lit = Literal::string(&format!("{ident}"));
|
||||
Ok(Self::Literal(lit, ident.span()))
|
||||
} else {
|
||||
Err(input.error("expected a command token"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<TokenStream> for CommandToken {
|
||||
fn into(self) -> TokenStream {
|
||||
match self {
|
||||
Self::TypedArgument(ident, span) => quote_spanned! {span=>
|
||||
Token::#ident
|
||||
},
|
||||
|
||||
Self::Literal(lit, span) => quote_spanned! {span=>
|
||||
Token::Value(vec![ #lit.to_string(), ])
|
||||
},
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
struct Command {
|
||||
tokens: Vec<CommandToken>,
|
||||
help: Literal,
|
||||
cb: Literal,
|
||||
}
|
||||
|
||||
impl Parse for Command {
|
||||
fn parse(input: ParseStream) -> ParseResult<Self> {
|
||||
let mut tokens = Vec::<CommandToken>::new();
|
||||
loop {
|
||||
if input.peek(Token![,]) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokens.push(input.parse::<CommandToken>()?);
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let cb_ident = input.parse::<Ident>()?;
|
||||
let cb = Literal::string(&format!("{cb_ident}"));
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let help = input.parse::<Literal>()?;
|
||||
|
||||
Ok(Self {
|
||||
tokens,
|
||||
cb,
|
||||
help,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<TokenStream> for Command {
|
||||
fn into(self) -> TokenStream {
|
||||
let Self { tokens, help, cb } = self;
|
||||
let tokens = tokens.into_iter().map(Into::into).collect::<Vec<TokenStream>>();
|
||||
|
||||
quote! {
|
||||
Command { tokens: vec![#(#tokens),*], help: #help.to_string(), cb: #cb.to_string() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn commands(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let stream: TokenStream = stream.into();
|
||||
let mut commands: Vec<TokenStream> = Vec::new();
|
||||
|
||||
let mut top_level_tokens = stream.into_iter();
|
||||
'a: loop {
|
||||
// "command"
|
||||
match top_level_tokens.next() {
|
||||
Some(TokenTree::Ident(ident)) if format!("{ident}") == "command" => {}
|
||||
None => break 'a,
|
||||
_ => panic!("contents of commands! macro is invalid"),
|
||||
}
|
||||
//
|
||||
match top_level_tokens.next() {
|
||||
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => {
|
||||
let group_stream: proc_macro::TokenStream = group.stream().into();
|
||||
commands.push(parse_macro_input!(group_stream as Command).into());
|
||||
}
|
||||
_ => panic!("contents of commands! macro is invalid"),
|
||||
}
|
||||
// ;
|
||||
match top_level_tokens.next() {
|
||||
Some(TokenTree::Punct(punct)) if format!("{punct}") == ";" => {}
|
||||
_ => panic!("contents of commands! macro is invalid"),
|
||||
}
|
||||
}
|
||||
|
||||
let command_registrations = commands
|
||||
.iter()
|
||||
.map(|v| -> TokenStream { quote! { tree.register_command(#v); }.into() })
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let res = quote! {
|
||||
lazy_static::lazy_static! {
|
||||
static ref COMMAND_TREE: TreeBranch = {
|
||||
let mut tree = TreeBranch {
|
||||
current_command_key: None,
|
||||
possible_tokens: vec![],
|
||||
branches: HashMap::new(),
|
||||
};
|
||||
|
||||
#command_registrations
|
||||
|
||||
tree.sort_tokens();
|
||||
|
||||
// println!("{{tree:#?}}");
|
||||
|
||||
tree
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// panic!("{res}");
|
||||
|
||||
res.into()
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ crate-type = ["cdylib"]
|
|||
|
||||
[dependencies]
|
||||
lazy_static = { workspace = true }
|
||||
command_system_macros = { path = "../command_system_macros" }
|
||||
|
||||
uniffi = { version = "0.25" }
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ mod string;
|
|||
mod token;
|
||||
use token::*;
|
||||
|
||||
use command_system_macros::commands;
|
||||
|
||||
// todo!: move all this stuff into a different file
|
||||
// lib.rs should just have exported symbols and command definitions
|
||||
|
||||
|
|
@ -69,23 +67,105 @@ impl TreeBranch {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Command {
|
||||
tokens: Vec<Token>,
|
||||
help: String,
|
||||
cb: String,
|
||||
}
|
||||
|
||||
// todo: aliases
|
||||
// todo: categories
|
||||
commands! {
|
||||
command(help, help, "Shows the help command");
|
||||
fn command(tokens: &[&Token], help: &str, cb: &str) -> Command {
|
||||
Command {
|
||||
tokens: tokens.iter().map(|&x| x.clone()).collect(),
|
||||
help: help.to_string(),
|
||||
cb: cb.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
command(member new, member_new, "Creates a new system member");
|
||||
command(member @MemberRef, member_show, "Shows information about a member");
|
||||
command(member @MemberRef description, member_desc_show, "Shows a member's description");
|
||||
command(member @MemberRef description @FullString, member_desc_update, "Changes a member's description");
|
||||
command(member @MemberRef privacy, member_privacy_show, "Displays a member's current privacy settings");
|
||||
command(member @MemberRef privacy @MemberPrivacyTarget @PrivacyLevel, member_privacy_update, "Changes a member's privacy settings");
|
||||
mod commands {
|
||||
use super::Token;
|
||||
|
||||
use super::command;
|
||||
use super::Token::*;
|
||||
|
||||
fn cmd(value: &str) -> Token {
|
||||
Token::Value(vec![value.to_string()])
|
||||
}
|
||||
|
||||
pub fn cmd_with_alias(value: &[&str]) -> Token {
|
||||
Token::Value(value.iter().map(|x| x.to_string()).collect())
|
||||
}
|
||||
|
||||
// todo: this needs to have less ampersands -alyssa
|
||||
pub fn happy() -> Vec<super::Command> {
|
||||
let system = &cmd_with_alias(&["system", "s"]);
|
||||
let member = &cmd_with_alias(&["member", "m"]);
|
||||
let description = &cmd_with_alias(&["description", "desc"]);
|
||||
let privacy = &cmd_with_alias(&["privacy", "priv"]);
|
||||
vec![
|
||||
command(&[&cmd("help")], "help", "Shows the help command"),
|
||||
command(
|
||||
&[system],
|
||||
"system_show",
|
||||
"Shows information about your system",
|
||||
),
|
||||
command(&[system, &cmd("new")], "system_new", "Creates a new system"),
|
||||
command(
|
||||
&[member, &cmd_with_alias(&["new", "n"])],
|
||||
"member_new",
|
||||
"Creates a new system member",
|
||||
),
|
||||
command(
|
||||
&[member, &MemberRef],
|
||||
"member_show",
|
||||
"Shows information about a member",
|
||||
),
|
||||
command(
|
||||
&[member, &MemberRef, description],
|
||||
"member_desc_show",
|
||||
"Shows a member's description",
|
||||
),
|
||||
command(
|
||||
&[member, &MemberRef, description, &FullString],
|
||||
"member_desc_update",
|
||||
"Changes a member's description",
|
||||
),
|
||||
command(
|
||||
&[member, &MemberRef, privacy],
|
||||
"member_privacy_show",
|
||||
"Displays a member's current privacy settings",
|
||||
),
|
||||
command(
|
||||
&[
|
||||
member,
|
||||
&MemberRef,
|
||||
privacy,
|
||||
&MemberPrivacyTarget,
|
||||
&PrivacyLevel,
|
||||
],
|
||||
"member_privacy_update",
|
||||
"Changes a member's privacy settings",
|
||||
),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref COMMAND_TREE: TreeBranch = {
|
||||
let mut tree = TreeBranch {
|
||||
current_command_key: None,
|
||||
possible_tokens: vec![],
|
||||
branches: HashMap::new(),
|
||||
};
|
||||
|
||||
commands::happy().iter().for_each(|x| tree.register_command(x.clone()));
|
||||
|
||||
tree.sort_tokens();
|
||||
|
||||
// println!("{{tree:#?}}");
|
||||
|
||||
tree
|
||||
};
|
||||
}
|
||||
|
||||
pub enum CommandResult {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||
lazy_static::lazy_static! {
|
||||
// Dictionary of (left, right) quote pairs
|
||||
// Each char in the string is an individual quote, multi-char strings imply "one of the following chars"
|
||||
// Certain languages can have quote patterns that have a different character for open and close
|
||||
pub static ref QUOTE_PAIRS: HashMap<String, String> = {
|
||||
let mut pairs = HashMap::new();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue