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