@@ -192,16 +192,41 @@ impl Display for Command {
192192}
193193
194194impl FromStr for Command {
195- type Err = ( ) ;
195+ type Err = String ;
196196 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
197- let mut values = s
197+ let values = s
198198 . replacen ( ':' , "" , 1 )
199199 . to_lowercase ( )
200200 . split_whitespace ( )
201201 . map ( String :: from)
202202 . collect :: < Vec < String > > ( ) ;
203+ if values. is_empty ( ) {
204+ return Err ( String :: from ( "command string is empty" ) ) ;
205+ }
206+ debug_assert ! ( !values. is_empty( ) , "command string is empty" ) ;
207+ debug_assert_eq ! (
208+ values[ 0 ] ,
209+ values[ 0 ] . to_lowercase( ) ,
210+ "command is not lowercase"
211+ ) ;
203212 let command = values. first ( ) . cloned ( ) . unwrap_or_default ( ) ;
204- let args = values. drain ( 1 ..) . collect :: < Vec < String > > ( ) ;
213+ debug_assert ! ( !command. is_empty( ) , "command is empty" ) ;
214+
215+ let args = values. iter ( ) . skip ( 1 ) . cloned ( ) . collect :: < Vec < String > > ( ) ;
216+ if command. is_empty ( ) {
217+ return Err ( String :: from ( "command is empty" ) ) ;
218+ }
219+
220+ let arg = args. first ( ) . cloned ( ) . unwrap_or_default ( ) ;
221+
222+ #[ rustfmt:: skip]
223+ let arg_or_fallback = |fallback : & str | -> Result < String , String > {
224+ if arg. is_empty ( ) && !fallback. is_empty ( ) {
225+ Ok ( fallback. to_string ( ) )
226+ } else if arg. is_empty ( ) && fallback. is_empty ( ) {
227+ Err ( String :: from ( "argument is missing" ) )
228+ } else { Ok ( arg. clone ( ) ) } } ;
229+
205230 match command. as_str ( ) {
206231 "confirm" => Ok ( Command :: Confirm ( Box :: new ( if args. is_empty ( ) {
207232 Command :: None
@@ -210,28 +235,27 @@ impl FromStr for Command {
210235 } ) ) ) ,
211236 "help" | "h" => Ok ( Command :: ShowHelp ) ,
212237 "style" => Ok ( Command :: ChangeStyle (
213- Style :: from_str (
214- & args. first ( ) . cloned ( ) . unwrap_or_default ( ) ,
215- true ,
216- )
217- . unwrap_or_default ( ) ,
238+ Style :: from_str ( & arg, true ) . unwrap_or_default ( ) ,
218239 ) ) ,
219240 "output" | "out" => {
220241 if !args. is_empty ( ) {
221242 Ok ( Command :: ShowOutput (
222- OutputType :: from (
223- args. first ( ) . cloned ( ) . unwrap_or_default ( ) ,
224- ) ,
243+ OutputType :: from_str ( & arg) . unwrap_or_default ( ) ,
225244 args[ 1 ..] . join ( " " ) ,
226245 ) )
227246 } else {
228- Err ( ( ) )
247+ Err ( String :: from ( "output type is missing" ) )
229248 }
230249 }
231250 "options" | "opt" => Ok ( Command :: ShowOptions ) ,
232- "list" | "ls" => Ok ( Command :: ListKeys ( KeyType :: from_str (
233- & args. first ( ) . cloned ( ) . unwrap_or_else ( || String :: from ( "pub" ) ) ,
234- ) ?) ) ,
251+ "list" | "ls" => Ok ( Command :: ListKeys (
252+ KeyType :: from_str (
253+ & arg_or_fallback ( "pub" ) ?, // 'is_empty()' when unwrap_or_default() was used above the match statemnt
254+ )
255+ . map_err ( |_| {
256+ String :: from ( "invalid key type :: [list] | [ls]" )
257+ } ) ?,
258+ ) ) ,
235259 "import" | "receive" => Ok ( Command :: ImportKeys (
236260 s. replacen ( ':' , "" , 1 )
237261 . split_whitespace ( )
@@ -253,11 +277,10 @@ impl FromStr for Command {
253277 patterns. truncate ( patterns. len ( ) - 1 )
254278 }
255279 Ok ( Command :: ExportKeys (
256- KeyType :: from_str (
257- & args
258- . first ( )
259- . cloned ( )
260- . unwrap_or_else ( || String :: from ( "pub" ) ) ,
280+ KeyType :: from_str ( & arg_or_fallback ( "pub" ) ?) . map_err (
281+ |_| {
282+ String :: from ( "invalid key type :: [export] | [exp]" )
283+ } ,
261284 ) ?,
262285 patterns,
263286 export_subkeys,
@@ -266,28 +289,27 @@ impl FromStr for Command {
266289 "delete" | "del" => {
267290 let key_id = args. get ( 1 ) . cloned ( ) . unwrap_or_default ( ) ;
268291 Ok ( Command :: DeleteKey (
269- KeyType :: from_str (
270- & args
271- . first ( )
272- . cloned ( )
273- . unwrap_or_else ( || String :: from ( "pub" ) ) ,
274- ) ?,
292+ KeyType :: from_str ( & arg_or_fallback ( "pub" ) ?) ?,
275293 if let Some ( key) = key_id. strip_prefix ( "0x" ) {
276294 format ! ( "0x{}" , key. to_string( ) . to_uppercase( ) )
277295 } else {
278296 key_id
279297 } ,
280298 ) )
281299 }
282- "send" => Ok ( Command :: SendKey ( args. first ( ) . cloned ( ) . ok_or ( ( ) ) ?) ) ,
283- "edit" => Ok ( Command :: EditKey ( args. first ( ) . cloned ( ) . ok_or ( ( ) ) ?) ) ,
284- "sign" => Ok ( Command :: SignKey ( args. first ( ) . cloned ( ) . ok_or ( ( ) ) ?) ) ,
300+ #[ rustfmt:: skip]
301+ "send" => Ok ( Command :: SendKey ( args. first ( ) . cloned ( ) . expect ( "Invalid" ) ) ) ,
302+ #[ rustfmt:: skip]
303+ "edit" => Ok ( Command :: EditKey ( args. first ( ) . cloned ( ) . expect ( "Invalid" ) ) ) ,
304+ #[ rustfmt:: skip]
305+ "sign" => Ok ( Command :: SignKey ( args. first ( ) . cloned ( ) . expect ( "Invalid" ) ) ) ,
306+ #[ rustfmt:: skip]
285307 "generate" | "gen" => Ok ( Command :: GenerateKey ) ,
286308 "copy" | "c" => {
287309 if let Some ( arg) = args. first ( ) . cloned ( ) {
288- Ok ( Command :: Copy (
289- Selection :: from_str ( & arg , true ) . map_err ( |_| ( ) ) ? ,
290- ) )
310+ Ok ( Command :: Copy ( Selection :: from_str ( & arg , true ) . map_err (
311+ |_| String :: from ( "invalid key type :: [copy] | [c]" ) ,
312+ ) ? ) )
291313 } else {
292314 Ok ( Command :: SwitchMode ( Mode :: Copy ) )
293315 }
@@ -320,9 +342,22 @@ impl FromStr for Command {
320342 "get" | "g" => {
321343 Ok ( Command :: Get ( args. first ( ) . cloned ( ) . unwrap_or_default ( ) ) )
322344 }
323- "mode" | "m" => Ok ( Command :: SwitchMode ( Mode :: from_str (
324- & args. first ( ) . cloned ( ) . ok_or ( ( ) ) ?,
325- ) ?) ) ,
345+ "mode" | "m" => {
346+ // Ok(Command::SwitchMode(Mode::from_str(&args.first().cloned())?))
347+ let args = arg_or_fallback ( "" ) . map_err ( |_| {
348+ String :: from ( "mode is missing :: [mode] | [m]" )
349+ } ) ?;
350+
351+ if let Ok ( mode) = match Mode :: from_str ( & args) {
352+ Ok ( mode) => Ok ( mode) ,
353+ Err ( _) => Err ( String :: from ( "invalid mode :: [mode] | [m]" ) ) ,
354+ } {
355+ Ok ( Command :: SwitchMode ( mode) )
356+ } else {
357+ Err ( String :: from ( "invalid mode :: [mode] | [m]" ) )
358+ }
359+ }
360+
326361 "normal" | "n" => Ok ( Command :: SwitchMode ( Mode :: Normal ) ) ,
327362 "visual" | "v" => Ok ( Command :: SwitchMode ( Mode :: Visual ) ) ,
328363 "paste" | "p" => Ok ( Command :: Paste ) ,
@@ -331,7 +366,7 @@ impl FromStr for Command {
331366 "next" => Ok ( Command :: NextTab ) ,
332367 "previous" | "prev" => Ok ( Command :: PreviousTab ) ,
333368 "refresh" | "r" => {
334- if args. first ( ) == Some ( & String :: from ( "keys" ) ) {
369+ if args. first ( ) . cloned ( ) == Some ( String :: from ( "keys" ) ) {
335370 Ok ( Command :: RefreshKeys )
336371 } else {
337372 Ok ( Command :: Refresh )
@@ -340,7 +375,7 @@ impl FromStr for Command {
340375 "quit" | "q" | "q!" => Ok ( Command :: Quit ) ,
341376 "logs" | "l" => Ok ( Command :: Logs ) ,
342377 "none" => Ok ( Command :: None ) ,
343- _ => Err ( ( ) ) ,
378+ _ => Err ( format ! ( "invalid command: {command}" ) ) ,
344379 }
345380 }
346381}
@@ -350,7 +385,7 @@ mod tests {
350385 use super :: * ;
351386 use pretty_assertions:: assert_eq;
352387 #[ test]
353- fn test_app_command ( ) -> Result < ( ) , ( ) > {
388+ fn test_app_command ( ) -> Result < ( ) , String > {
354389 assert_eq ! (
355390 Command :: Confirm ( Box :: new( Command :: None ) ) ,
356391 Command :: from_str( ":confirm none" ) ?
0 commit comments