@@ -113,68 +113,42 @@ pub enum Argument<'a> {
113113 Stdio ,
114114}
115115
116- impl < ' a > Argument < ' a > {
117- /// Converts this argument into a [`ParsingError::UnexpectedArg `] error.
116+ impl Argument < ' _ > {
117+ /// Converts this argument into a [`ParsingError::Unexpected `] error.
118118 ///
119119 /// This is a convenience method for creating contextual error messages when an argument
120120 /// is encountered but not expected by the application. The resulting error message
121121 /// includes appropriate formatting based on the argument type.
122122 ///
123- /// # Parameters
124- ///
125- /// * `value` - Optional value associated with the argument (primarily used with options)
126- ///
127123 /// # Examples
128124 ///
129125 /// ```rust
130126 /// use sap::Argument;
131127 ///
132- /// // Long option with value
128+ /// // Long option
133129 /// let arg = Argument::Long("unknown");
134- /// let error = arg.into_error(Some("value") );
135- /// assert_eq!(error.to_string(), "unexpected argument: --unknown=value ");
130+ /// let error = arg.unexpected( );
131+ /// assert_eq!(error.to_string(), "unexpected argument: --unknown");
136132 ///
137- /// // Short option without value
133+ /// // Short option
138134 /// let arg = Argument::Short('x');
139- /// let error = arg.into_error(None::<&str> );
135+ /// let error = arg.unexpected( );
140136 /// assert_eq!(error.to_string(), "unexpected argument: -x");
141137 ///
138+ /// // Positional value
139+ /// let arg = Argument::Value("file".into());
140+ /// let error = arg.unexpected();
141+ /// assert_eq!(error.to_string(), "unexpected argument: file");
142+ ///
142143 /// // Stdio argument
143144 /// let arg = Argument::Stdio;
144- /// let error = arg.into_error(None::<&str> );
145+ /// let error = arg.unexpected( );
145146 /// assert_eq!(error.to_string(), "unexpected argument: -");
146147 /// ```
147- pub fn into_error < A > ( self , value : A ) -> ParsingError
148- where
149- A : Into < Option < & ' a str > > ,
150- {
151- use Argument :: { Long , Short , Stdio , Value } ;
152-
153- match self {
154- Long ( arg) => ParsingError :: UnexpectedArg {
155- offender : arg. to_string ( ) ,
156- value : value. into ( ) . map ( String :: from) ,
157- format : "=" ,
158- prefix : "--" ,
159- } ,
160- Short ( arg) => ParsingError :: UnexpectedArg {
161- offender : arg. to_string ( ) ,
162- value : value. into ( ) . map ( String :: from) ,
163- format : " " ,
164- prefix : "-" ,
165- } ,
166- Value ( arg) => ParsingError :: UnexpectedArg {
167- offender : arg. to_string ( ) ,
168- value : None ,
169- format : "" ,
170- prefix : "" ,
171- } ,
172- Stdio => ParsingError :: UnexpectedArg {
173- offender : "-" . to_string ( ) ,
174- value : None ,
175- format : "" ,
176- prefix : "" ,
177- } ,
148+ #[ must_use]
149+ pub fn unexpected ( & self ) -> ParsingError {
150+ ParsingError :: Unexpected {
151+ argument : self . to_string ( ) ,
178152 }
179153 }
180154}
@@ -380,9 +354,8 @@ where
380354 if char == '=' {
381355 self . state = State :: Poisoned ;
382356
383- return Err ( ParsingError :: InvalidOption {
357+ return Err ( ParsingError :: InvalidSyntax {
384358 reason : "Short options do not support values" ,
385- offender : None ,
386359 } ) ;
387360 }
388361
@@ -623,8 +596,14 @@ where
623596///
624597/// All parsing operations return a `Result` with this error type. Each variant
625598/// provides specific context about what went wrong during parsing.
626- #[ derive( Debug ) ]
599+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
627600pub enum ParsingError {
601+ /// The argument iterator was empty (contained no program name).
602+ ///
603+ /// This should not occur during normal program execution but may happen
604+ /// when creating parsers from empty custom iterators.
605+ Empty ,
606+
628607 /// Invalid option syntax or format was encountered.
629608 ///
630609 /// This typically occurs when:
@@ -634,11 +613,7 @@ pub enum ParsingError {
634613 /// # Fields
635614 ///
636615 /// * `reason` - Human-readable description of what was invalid
637- /// * `offender` - The specific argument that caused the error (if available)
638- InvalidOption {
639- reason : & ' static str ,
640- offender : Option < String > ,
641- } ,
616+ InvalidSyntax { reason : & ' static str } ,
642617
643618 /// An option value was not consumed after being parsed.
644619 ///
@@ -651,63 +626,33 @@ pub enum ParsingError {
651626 /// * `value` - The unconsumed value that was attached to the option
652627 UnconsumedValue { value : String } ,
653628
654- /// The argument iterator was empty (contained no program name).
655- ///
656- /// This should not occur during normal program execution but may happen
657- /// when creating parsers from empty custom iterators.
658- Empty ,
659-
660629 /// An unexpected or unrecognized argument was encountered.
661630 ///
662- /// This error is typically created by calling [`Argument::into_error `] when
631+ /// This error is typically created by calling [`Argument::unexpected `] when
663632 /// the application encounters an argument it doesn't know how to handle.
664633 ///
665634 /// # Fields
666635 ///
667- /// * `offender` - The argument name that was unexpected
668- /// * `value` - Associated value (if any)
669- /// * `format` - How the value is formatted in error messages (e.g., "=" or " ")
670- /// * `prefix` - The argument prefix (e.g., "--" for long options, "-" for short)
671- UnexpectedArg {
672- offender : String ,
673- value : Option < String > ,
674- format : & ' static str ,
675- prefix : & ' static str ,
676- } ,
636+ /// * `argument` - The formatted argument string (e.g., "--unknown", "-x value", "file.txt")
637+ ///
638+ /// # Examples
639+ ///
640+ /// ```rust
641+ /// use sap::{Argument, ParsingError};
642+ ///
643+ /// let error = Argument::Long("unknown").unexpected();
644+ /// assert_eq!(error.to_string(), "unexpected argument: --unknown");
645+ /// ```
646+ Unexpected { argument : String } ,
677647}
678648
679649impl Display for ParsingError {
680650 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
681651 match self {
682- Self :: InvalidOption { reason, offender } => {
683- write ! ( f, "reason: {reason}" ) ?;
684- if let Some ( sentence) = offender {
685- write ! ( f, " at: {sentence}" ) ?;
686- }
687-
688- Ok ( ( ) )
689- }
690-
691- Self :: UnconsumedValue { value } => {
692- write ! ( f, "leftover value: {value}" , )
693- }
694-
695- Self :: UnexpectedArg {
696- offender,
697- value,
698- format,
699- prefix,
700- } => match value {
701- Some ( val) => {
702- write ! ( f, "unexpected argument: {prefix}{offender}{format}{val}" )
703- }
704-
705- None => {
706- write ! ( f, "unexpected argument: {prefix}{offender}" )
707- }
708- } ,
709-
710- Self :: Empty => write ! ( f, "env variables were empty" ) ,
652+ Self :: Empty => write ! ( f, "argument list is empty" ) ,
653+ Self :: InvalidSyntax { reason } => write ! ( f, "invalid syntax: {reason}" ) ,
654+ Self :: UnconsumedValue { value } => write ! ( f, "unconsumed value: {value}" ) ,
655+ Self :: Unexpected { argument } => write ! ( f, "unexpected argument: {argument}" ) ,
711656 }
712657 }
713658}
@@ -950,30 +895,39 @@ mod tests {
950895 }
951896
952897 #[ test]
953- fn argument_into_error ( ) {
954- assert_eq ! (
955- Long ( "test" ) . into_error( "value" ) . to_string( ) ,
956- "unexpected argument: --test=value"
957- ) ;
898+ fn argument_unexpected ( ) {
899+ use crate :: ParsingError ;
900+
901+ // Test unexpected() without values
958902 assert_eq ! (
959- Long ( "test" ) . into_error( None :: <& str >) . to_string( ) ,
960- "unexpected argument: --test"
903+ Long ( "test" ) . unexpected( ) ,
904+ ParsingError :: Unexpected {
905+ argument: "--test" . to_string( )
906+ }
961907 ) ;
962908 assert_eq ! (
963- Short ( 'x' ) . into_error( "val" ) . to_string( ) ,
964- "unexpected argument: -x val"
909+ Short ( 'x' ) . unexpected( ) ,
910+ ParsingError :: Unexpected {
911+ argument: "-x" . to_string( )
912+ }
965913 ) ;
966914 assert_eq ! (
967- Short ( 'x' ) . into_error( None :: <& str >) . to_string( ) ,
968- "unexpected argument: -x"
915+ Value ( "file" . into( ) ) . unexpected( ) ,
916+ ParsingError :: Unexpected {
917+ argument: "file" . to_string( )
918+ }
969919 ) ;
970920 assert_eq ! (
971- Value ( "file" . into( ) ) . into_error( None :: <& str >) . to_string( ) ,
972- "unexpected argument: file"
921+ Stdio . unexpected( ) ,
922+ ParsingError :: Unexpected {
923+ argument: "-" . to_string( )
924+ }
973925 ) ;
926+
927+ // Verify Display implementation still works correctly
974928 assert_eq ! (
975- Stdio . into_error ( None :: < & str > ) . to_string( ) ,
976- "unexpected argument: -"
929+ Long ( "test" ) . unexpected ( ) . to_string( ) ,
930+ "unexpected argument: --test "
977931 ) ;
978932 }
979933
0 commit comments