azalea_brigadier/context/
command_context.rs

1use std::{
2    any::Any,
3    collections::HashMap,
4    fmt::{self, Debug},
5    rc::Rc,
6    sync::Arc,
7};
8
9use parking_lot::RwLock;
10
11use super::{ParsedArgument, parsed_command_node::ParsedCommandNode, string_range::StringRange};
12use crate::{
13    modifier::RedirectModifier,
14    tree::{Command, CommandNode},
15};
16
17/// A built `CommandContextBuilder`.
18pub struct CommandContext<S> {
19    pub source: Arc<S>,
20    pub(super) input: String,
21    pub(super) arguments: HashMap<String, ParsedArgument>,
22    pub(super) command: Command<S>,
23    pub(super) root_node: Arc<RwLock<CommandNode<S>>>,
24    pub(super) nodes: Vec<ParsedCommandNode<S>>,
25    pub(super) range: StringRange,
26    pub(super) child: Option<Rc<CommandContext<S>>>,
27    pub(super) modifier: Option<Arc<RedirectModifier<S>>>,
28    pub(super) forks: bool,
29}
30
31impl<S> Clone for CommandContext<S> {
32    fn clone(&self) -> Self {
33        Self {
34            source: self.source.clone(),
35            input: self.input.clone(),
36            arguments: self.arguments.clone(),
37            command: self.command.clone(),
38            root_node: self.root_node.clone(),
39            nodes: self.nodes.clone(),
40            range: self.range,
41            child: self.child.clone(),
42            modifier: self.modifier.clone(),
43            forks: self.forks,
44        }
45    }
46}
47
48impl<S> Debug for CommandContext<S> {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        f.debug_struct("CommandContext")
51            // .field("source", &self.source)
52            .field("input", &self.input)
53            // .field("arguments", &self.arguments)
54            // .field("command", &self.command)
55            // .field("root_node", &self.root_node)
56            // .field("nodes", &self.nodes)
57            .field("range", &self.range)
58            .field("child", &self.child)
59            // .field("modifier", &self.modifier)
60            .field("forks", &self.forks)
61            .finish()
62    }
63}
64
65impl<S> CommandContext<S> {
66    pub fn copy_for(&self, source: Arc<S>) -> Self {
67        if Arc::ptr_eq(&source, &self.source) {
68            // fast path
69            return self.clone();
70        }
71
72        CommandContext {
73            source,
74            input: self.input.clone(),
75            arguments: self.arguments.clone(),
76            command: self.command.clone(),
77            root_node: self.root_node.clone(),
78            nodes: self.nodes.clone(),
79            range: self.range,
80            child: self.child.clone(),
81            modifier: self.modifier.clone(),
82            forks: self.forks,
83        }
84    }
85
86    pub fn child(&self) -> Option<&CommandContext<S>> {
87        self.child.as_ref().map(|c| c.as_ref())
88    }
89
90    pub fn last_child(&self) -> &CommandContext<S> {
91        let mut result = self;
92        while let Some(child) = result.child() {
93            result = child;
94        }
95        result
96    }
97
98    pub fn command(&self) -> &Command<S> {
99        &self.command
100    }
101
102    pub fn argument(&self, name: &str) -> Option<&dyn Any> {
103        let argument = self.arguments.get(name);
104        argument.map(|a| a.result.as_ref())
105    }
106
107    pub fn redirect_modifier(&self) -> Option<&RedirectModifier<S>> {
108        self.modifier.as_ref().map(|m| m.as_ref())
109    }
110
111    pub fn range(&self) -> &StringRange {
112        &self.range
113    }
114
115    pub fn input(&self) -> &str {
116        &self.input
117    }
118
119    pub fn root_node(&self) -> &Arc<RwLock<CommandNode<S>>> {
120        &self.root_node
121    }
122
123    pub fn nodes(&self) -> &[ParsedCommandNode<S>] {
124        &self.nodes
125    }
126
127    pub fn has_nodes(&self) -> bool {
128        !self.nodes.is_empty()
129    }
130
131    pub fn is_forked(&self) -> bool {
132        self.forks
133    }
134}