refactor(commands): clearer token match typing, make tree.possible_commads return iterator instead of traversing the whole tree immediately

This commit is contained in:
dusk 2025-01-12 04:23:46 +09:00
parent 877592588c
commit d5c271be20
No known key found for this signature in database
4 changed files with 125 additions and 102 deletions

View file

@ -24,7 +24,7 @@ impl TreeBranch {
current_branch = current_branch.branches.entry(token).or_insert(TreeBranch {
current_command: None,
branches: OrderMap::new(),
})
});
}
// when we're out of tokens, add an Empty branch with the callback and no sub-branches
current_branch.branches.insert(
@ -44,20 +44,25 @@ impl TreeBranch {
self.branches.keys()
}
pub fn possible_commands(&self, max_depth: usize) -> Vec<Command> {
if max_depth == 0 {
return Vec::new();
pub 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)
}
let mut commands = Vec::new();
for token in self.possible_tokens() {
if let Some(tree) = self.get_branch(token) {
if let Some(command) = tree.command() {
commands.push(command);
// we dont need to look further if we found a command
continue;
}
commands.append(&mut tree.possible_commands(max_depth - 1));
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
}