1/// Semantics for a piece of error information
2#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
3#[non_exhaustive]
4#[cfg(feature = "error-context")]
5pub 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
42impl 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
67impl 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")]
77pub 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
94impl 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) => v.fmt(f),
99 Self::String(v) => v.fmt(f),
100 Self::Strings(v) => v.join(", ").fmt(f),
101 Self::StyledStr(v) => v.fmt(f),
102 Self::StyledStrs(v) => {
103 for (i, v) in v.iter().enumerate() {
104 if i != 0 {
105 ", ".fmt(f)?;
106 }
107 v.fmt(f)?;
108 }
109 Ok(())
110 }
111 Self::Number(v) => v.fmt(f),
112 }
113 }
114}
115