mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-06 13:57:54 +00:00
refactor: separate commands into command_parser, command_definitions crates
This commit is contained in:
parent
4f390e2a14
commit
0c012e98b5
33 changed files with 464 additions and 378 deletions
75
crates/command_parser/src/tree.rs
Normal file
75
crates/command_parser/src/tree.rs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
use ordermap::OrderMap;
|
||||
|
||||
use crate::{command::Command, token::Token};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TreeBranch {
|
||||
current_command: Option<Command>,
|
||||
branches: OrderMap<Token, TreeBranch>,
|
||||
}
|
||||
|
||||
impl Default for TreeBranch {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
current_command: None,
|
||||
branches: OrderMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeBranch {
|
||||
pub fn register_command(&mut self, command: Command) {
|
||||
let mut current_branch = self;
|
||||
// iterate over tokens in command
|
||||
for token in command.tokens.clone() {
|
||||
// recursively get or create a sub-branch for each token
|
||||
current_branch = current_branch
|
||||
.branches
|
||||
.entry(token)
|
||||
.or_insert_with(TreeBranch::default);
|
||||
}
|
||||
// when we're out of tokens, add an Empty branch with the callback and no sub-branches
|
||||
current_branch.branches.insert(
|
||||
Token::Empty,
|
||||
TreeBranch {
|
||||
branches: OrderMap::new(),
|
||||
current_command: Some(command),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn command(&self) -> Option<Command> {
|
||||
self.current_command.clone()
|
||||
}
|
||||
|
||||
pub(super) fn possible_tokens(&self) -> impl Iterator<Item = &Token> {
|
||||
self.branches.keys()
|
||||
}
|
||||
|
||||
pub(super) fn possible_commands(&self, max_depth: usize) -> impl Iterator<Item = &Command> {
|
||||
// dusk: i am too lazy to write an iterator for this without using recursion so we box everything
|
||||
fn box_iter<'a>(
|
||||
iter: impl Iterator<Item = &'a Command> + 'a,
|
||||
) -> Box<dyn Iterator<Item = &'a Command> + 'a> {
|
||||
Box::new(iter)
|
||||
}
|
||||
|
||||
if max_depth == 0 {
|
||||
return box_iter(std::iter::empty());
|
||||
}
|
||||
let mut commands = box_iter(std::iter::empty());
|
||||
for branch in self.branches.values() {
|
||||
if let Some(command) = branch.current_command.as_ref() {
|
||||
commands = box_iter(commands.chain(std::iter::once(command)));
|
||||
// we dont need to look further if we found a command (only Empty tokens have commands)
|
||||
continue;
|
||||
}
|
||||
commands = box_iter(commands.chain(branch.possible_commands(max_depth - 1)));
|
||||
}
|
||||
commands
|
||||
}
|
||||
|
||||
pub(super) fn get_branch(&self, token: &Token) -> Option<&TreeBranch> {
|
||||
self.branches.get(token)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue