steel_core/command/execution/
structure.rs1use steel_registry::{REGISTRY, RegistryExt as _, TaggedRegistryExt as _, structure::StructureRef};
4use steel_utils::Identifier;
5
6use super::argument::{identifier_matches, parse_identifier};
7use crate::command::brigadier::{CommandSyntaxError, StringReader, SuggestionsBuilder};
8
9#[derive(Clone, Debug, PartialEq, Eq)]
11pub(crate) enum StructureOrTagKey {
12 Structure(Identifier),
13 Tag(Identifier),
14}
15
16impl StructureOrTagKey {
17 pub(crate) fn resolve(&self) -> Option<Vec<StructureRef>> {
18 match self {
19 Self::Structure(key) => REGISTRY
20 .structures
21 .by_key(key)
22 .map(|structure| vec![structure]),
23 Self::Tag(key) => REGISTRY.structures.get_tag(key),
24 }
25 }
26
27 pub(crate) fn as_printable(&self) -> String {
28 match self {
29 Self::Structure(key) => key.to_string(),
30 Self::Tag(key) => format!("#{key}"),
31 }
32 }
33
34 pub(crate) fn found_name(&self, found_structure: &Identifier) -> String {
35 match self {
36 Self::Structure(key) => key.to_string(),
37 Self::Tag(key) => format!("#{key} ({found_structure})"),
38 }
39 }
40}
41
42pub(super) fn parse_structure_or_tag_key(
43 reader: &mut StringReader<'_>,
44) -> Result<StructureOrTagKey, CommandSyntaxError> {
45 if reader.peek() != Some('#') {
46 return parse_identifier(reader).map(StructureOrTagKey::Structure);
47 }
48
49 let start = reader.checkpoint();
50 reader.skip();
51 match parse_identifier(reader) {
52 Ok(key) => Ok(StructureOrTagKey::Tag(key)),
53 Err(error) => {
54 reader.restore(start);
55 Err(error)
56 }
57 }
58}
59
60pub(super) fn suggest_structures(builder: &mut SuggestionsBuilder<'_>) {
61 let remaining = builder.remaining_lowercase();
62 let suggestions = if let Some(tag_prefix) = remaining.strip_prefix('#') {
63 REGISTRY
64 .structures
65 .tag_keys()
66 .filter(|tag| identifier_matches(tag_prefix, tag))
67 .map(|tag| format!("#{tag}"))
68 .collect::<Vec<_>>()
69 } else {
70 REGISTRY
71 .structures
72 .iter()
73 .filter(|(_, structure)| identifier_matches(remaining, &structure.key))
74 .map(|(_, structure)| structure.key.to_string())
75 .chain(
76 REGISTRY
77 .structures
78 .tag_keys()
79 .filter(|tag| identifier_matches(remaining, tag))
80 .map(|tag| format!("#{tag}")),
81 )
82 .collect()
83 };
84 for suggestion in suggestions {
85 builder.suggest(suggestion);
86 }
87}