1
+ use crate :: output:: report_unhandled_error;
2
+ use crate :: { report_error, report_info, Args } ;
3
+ use clap:: CommandFactory ;
4
+ use std:: process;
1
5
use thiserror:: Error ;
2
6
3
7
#[ derive( Error , Debug ) ]
4
8
pub enum CliError {
5
- #[ error( "invalid arguments, please supply a path argument or use --repl" ) ]
6
- MissingPath ,
7
9
#[ error( "unable read file at path {0}" ) ]
8
10
ReadFileError ( String ) ,
9
11
#[ error( "{0}" ) ]
@@ -12,4 +14,68 @@ pub enum CliError {
12
14
WriteFileError ( String ) ,
13
15
#[ error( "unable to read input" ) ]
14
16
ReadInputError ,
17
+ #[ error( "unable to read stdin" ) ]
18
+ ReadStdinError ,
19
+ #[ error( "repl argument supplied with piped input or output" ) ]
20
+ ReplWithPipe ,
21
+ #[ error( "No input file supplied and no input piped.\n Try adding a path argument: 'melody ./file.mdy'" ) ]
22
+ StdinWithoutPipe ,
23
+ }
24
+
25
+ #[ derive( Debug ) ]
26
+ pub enum ErrorKind {
27
+ Info ,
28
+ Error ,
29
+ }
30
+
31
+ impl CliError {
32
+ pub fn kind ( & self ) -> ErrorKind {
33
+ match self {
34
+ CliError :: StdinWithoutPipe => ErrorKind :: Info ,
35
+ _ => ErrorKind :: Error ,
36
+ }
37
+ }
38
+
39
+ fn report ( & self ) {
40
+ match self . kind ( ) {
41
+ ErrorKind :: Info => {
42
+ report_info ( & self . to_string ( ) ) ;
43
+ println ! ( ) ;
44
+ // silently ignoring an error when printing help
45
+ // as we're already handling an error and have printed info
46
+ let _print_result = Args :: command ( ) . print_help ( ) ;
47
+ }
48
+ ErrorKind :: Error => {
49
+ report_error ( & self . to_string ( ) ) ;
50
+ }
51
+ } ;
52
+ }
53
+
54
+ fn to_exit_code ( & self ) -> exitcode:: ExitCode {
55
+ match self {
56
+ CliError :: WriteFileError ( _)
57
+ | CliError :: ReadFileError ( _)
58
+ | CliError :: ReadInputError
59
+ | CliError :: ReadStdinError => exitcode:: IOERR ,
60
+ CliError :: ParseError ( _) => exitcode:: DATAERR ,
61
+ CliError :: ReplWithPipe => exitcode:: USAGE ,
62
+ CliError :: StdinWithoutPipe => exitcode:: NOINPUT ,
63
+ }
64
+ }
65
+ }
66
+
67
+ pub fn handle_error ( error : & anyhow:: Error ) -> ! {
68
+ let cli_error = error. downcast_ref :: < CliError > ( ) ;
69
+
70
+ let cli_error = match cli_error {
71
+ Some ( cli_error) => cli_error,
72
+ None => {
73
+ report_unhandled_error ( & error. to_string ( ) ) ;
74
+ process:: exit ( exitcode:: SOFTWARE ) ;
75
+ }
76
+ } ;
77
+
78
+ cli_error. report ( ) ;
79
+
80
+ process:: exit ( cli_error. to_exit_code ( ) )
15
81
}
0 commit comments