1 | /// Semantics for a piece of error information |
2 | #[derive (Copy, Clone, Debug, PartialEq, Eq, Hash)] |
3 | #[non_exhaustive ] |
4 | #[cfg (feature = "error-context" )] |
5 | pub enum ContextKind { |
6 | /// The cause of the error |
7 | InvalidSubcommand, |
8 | /// The cause of the error |
9 | InvalidArg, |
10 | /// Existing arguments |
11 | PriorArg, |
12 | /// Accepted subcommands |
13 | ValidSubcommand, |
14 | /// Accepted values |
15 | ValidValue, |
16 | /// Rejected values |
17 | InvalidValue, |
18 | /// Number of values present |
19 | ActualNumValues, |
20 | /// Number of allowed values |
21 | ExpectedNumValues, |
22 | /// Minimum number of allowed values |
23 | MinValues, |
24 | /// Potential fix for the user |
25 | SuggestedCommand, |
26 | /// Potential fix for the user |
27 | SuggestedSubcommand, |
28 | /// Potential fix for the user |
29 | SuggestedArg, |
30 | /// Potential fix for the user |
31 | SuggestedValue, |
32 | /// Trailing argument |
33 | TrailingArg, |
34 | /// Potential fix for the user |
35 | Suggested, |
36 | /// A usage string |
37 | Usage, |
38 | /// An opaque message to the user |
39 | Custom, |
40 | } |
41 | |
42 | impl ContextKind { |
43 | /// End-user description of the error case, where relevant |
44 | pub fn as_str(self) -> Option<&'static str> { |
45 | match self { |
46 | Self::InvalidSubcommand => Some("Invalid Subcommand" ), |
47 | Self::InvalidArg => Some("Invalid Argument" ), |
48 | Self::PriorArg => Some("Prior Argument" ), |
49 | Self::ValidSubcommand => Some("Valid Subcommand" ), |
50 | Self::ValidValue => Some("Valid Value" ), |
51 | Self::InvalidValue => Some("Invalid Value" ), |
52 | Self::ActualNumValues => Some("Actual Number of Values" ), |
53 | Self::ExpectedNumValues => Some("Expected Number of Values" ), |
54 | Self::MinValues => Some("Minimum Number of Values" ), |
55 | Self::SuggestedCommand => Some("Suggested Command" ), |
56 | Self::SuggestedSubcommand => Some("Suggested Subcommand" ), |
57 | Self::SuggestedArg => Some("Suggested Argument" ), |
58 | Self::SuggestedValue => Some("Suggested Value" ), |
59 | Self::TrailingArg => Some("Trailing Argument" ), |
60 | Self::Suggested => Some("Suggested" ), |
61 | Self::Usage => None, |
62 | Self::Custom => None, |
63 | } |
64 | } |
65 | } |
66 | |
67 | impl std::fmt::Display for ContextKind { |
68 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
69 | self.as_str().unwrap_or_default().fmt(f) |
70 | } |
71 | } |
72 | |
73 | /// A piece of error information |
74 | #[derive (Clone, Debug, PartialEq, Eq)] |
75 | #[non_exhaustive ] |
76 | #[cfg (feature = "error-context" )] |
77 | pub enum ContextValue { |
78 | /// [`ContextKind`] is self-sufficient, no additional information needed |
79 | None, |
80 | /// A single value |
81 | Bool(bool), |
82 | /// A single value |
83 | String(String), |
84 | /// Many values |
85 | Strings(Vec<String>), |
86 | /// A single value |
87 | StyledStr(crate::builder::StyledStr), |
88 | /// many value |
89 | StyledStrs(Vec<crate::builder::StyledStr>), |
90 | /// A single value |
91 | Number(isize), |
92 | } |
93 | |
94 | impl std::fmt::Display for ContextValue { |
95 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
96 | match self { |
97 | Self::None => "" .fmt(f), |
98 | Self::Bool(v: &bool) => v.fmt(f), |
99 | Self::String(v: &String) => v.fmt(f), |
100 | Self::Strings(v: &Vec) => v.join(sep:", " ).fmt(f), |
101 | Self::StyledStr(v: &StyledStr) => v.fmt(f), |
102 | Self::StyledStrs(v: &Vec) => { |
103 | for (i: usize, v: &StyledStr) in v.iter().enumerate() { |
104 | if i != 0 { |
105 | ", " .fmt(f)?; |
106 | } |
107 | v.fmt(f)?; |
108 | } |
109 | Ok(()) |
110 | } |
111 | Self::Number(v: &isize) => v.fmt(f), |
112 | } |
113 | } |
114 | } |
115 | |