azalea_brigadier/errors/
command_syntax_error.rs

1use std::{
2    cmp,
3    fmt::{self, Debug, Write},
4};
5
6use super::builtin_errors::BuiltInError;
7
8#[derive(Clone, PartialEq)]
9pub struct CommandSyntaxError {
10    kind: BuiltInError,
11    message: String,
12    input: Option<String>,
13    cursor: Option<usize>,
14}
15
16const CONTEXT_AMOUNT: usize = 10;
17
18impl CommandSyntaxError {
19    pub fn new(kind: BuiltInError, message: String, input: &str, cursor: usize) -> Self {
20        Self {
21            kind,
22            message,
23            input: Some(input.to_string()),
24            cursor: Some(cursor),
25        }
26    }
27
28    pub fn create(kind: BuiltInError, message: String) -> Self {
29        Self {
30            kind,
31            message,
32            input: None,
33            cursor: None,
34        }
35    }
36
37    pub fn message(&self) -> String {
38        let mut message = self.message.clone();
39        let context = self.context();
40        if let Some(context) = context {
41            write!(
42                message,
43                " at position {}: {context}",
44                self.cursor.unwrap_or(usize::MAX)
45            )
46            .unwrap();
47        }
48        message
49    }
50
51    pub fn raw_message(&self) -> &String {
52        &self.message
53    }
54
55    pub fn context(&self) -> Option<String> {
56        if let Some(input) = &self.input
57            && let Some(cursor) = self.cursor
58        {
59            let mut builder = String::new();
60            let cursor = cmp::min(input.len(), cursor);
61
62            if cursor > CONTEXT_AMOUNT {
63                builder.push_str("...");
64            }
65
66            builder.push_str(
67                &input[(cmp::max(0, cursor as isize - CONTEXT_AMOUNT as isize) as usize)..cursor],
68            );
69            builder.push_str("<--[HERE]");
70
71            return Some(builder);
72        }
73        None
74    }
75
76    pub fn kind(&self) -> &BuiltInError {
77        &self.kind
78    }
79
80    pub fn input(&self) -> &Option<String> {
81        &self.input
82    }
83
84    pub fn cursor(&self) -> Option<usize> {
85        self.cursor
86    }
87}
88
89impl Debug for CommandSyntaxError {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        write!(f, "{}", self.message())
92    }
93}