mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-11 00:07:55 +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]
|
[dependencies]
|
||||||
lazy_static = { workspace = true }
|
lazy_static = { workspace = true }
|
||||||
command_system_macros = { path = "../command_system_macros" }
|
|
||||||
|
|
||||||
uniffi = { version = "0.25" }
|
uniffi = { version = "0.25" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ mod string;
|
||||||
mod token;
|
mod token;
|
||||||
use token::*;
|
use token::*;
|
||||||
|
|
||||||
use command_system_macros::commands;
|
|
||||||
|
|
||||||
// todo!: move all this stuff into a different file
|
// todo!: move all this stuff into a different file
|
||||||
// lib.rs should just have exported symbols and command definitions
|
// lib.rs should just have exported symbols and command definitions
|
||||||
|
|
||||||
|
|
@ -69,23 +67,105 @@ impl TreeBranch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Command {
|
struct Command {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
help: String,
|
help: String,
|
||||||
cb: String,
|
cb: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: aliases
|
fn command(tokens: &[&Token], help: &str, cb: &str) -> Command {
|
||||||
// todo: categories
|
Command {
|
||||||
commands! {
|
tokens: tokens.iter().map(|&x| x.clone()).collect(),
|
||||||
command(help, help, "Shows the help command");
|
help: help.to_string(),
|
||||||
|
cb: cb.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command(member new, member_new, "Creates a new system member");
|
mod commands {
|
||||||
command(member @MemberRef, member_show, "Shows information about a member");
|
use super::Token;
|
||||||
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");
|
use super::command;
|
||||||
command(member @MemberRef privacy, member_privacy_show, "Displays a member's current privacy settings");
|
use super::Token::*;
|
||||||
command(member @MemberRef privacy @MemberPrivacyTarget @PrivacyLevel, member_privacy_update, "Changes a member's privacy settings");
|
|
||||||
|
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 {
|
pub enum CommandResult {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
// Dictionary of (left, right) quote pairs
|
// Dictionary of (left, right) quote pairs
|
||||||
// Each char in the string is an individual quote, multi-char strings imply "one of the following chars"
|
// 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> = {
|
pub static ref QUOTE_PAIRS: HashMap<String, String> = {
|
||||||
let mut pairs = HashMap::new();
|
let mut pairs = HashMap::new();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue