1
+ use clap:: Clap ;
2
+ use fmterr:: fmt_err;
1
3
use perseus_cli:: errors:: * ;
2
4
use perseus_cli:: {
3
- build, check_env, delete_artifacts, delete_bad_dir, eject, export, has_ejected, help, prepare,
4
- report_err, serve, PERSEUS_VERSION ,
5
+ build, check_env, delete_artifacts, delete_bad_dir, eject, export, has_ejected,
6
+ parse:: { Opts , Subcommand } ,
7
+ prepare, serve,
5
8
} ;
6
9
use std:: env;
7
10
use std:: io:: Write ;
@@ -26,7 +29,10 @@ fn real_main() -> i32 {
26
29
let dir = match dir {
27
30
Ok ( dir) => dir,
28
31
Err ( err) => {
29
- report_err ! ( PrepError :: CurrentDirUnavailable { source: err } ) ;
32
+ eprintln ! (
33
+ "{}" ,
34
+ fmt_err( & PrepError :: CurrentDirUnavailable { source: err } )
35
+ ) ;
30
36
return 1 ;
31
37
}
32
38
} ;
@@ -37,11 +43,11 @@ fn real_main() -> i32 {
37
43
// If something failed, we print the error to `stderr` and return a failure exit code
38
44
Err ( err) => {
39
45
let should_cause_deletion = err_should_cause_deletion ( & err) ;
40
- report_err ! ( err) ;
46
+ eprintln ! ( "{}" , fmt_err ( & err) ) ;
41
47
// Check if the error needs us to delete a partially-formed '.perseus/' directory
42
48
if should_cause_deletion {
43
49
if let Err ( err) = delete_bad_dir ( dir) {
44
- report_err ! ( err) ;
50
+ eprintln ! ( "{}" , fmt_err ( & err) ) ;
45
51
}
46
52
}
47
53
1
@@ -56,105 +62,76 @@ fn real_main() -> i32 {
56
62
fn core ( dir : PathBuf ) -> Result < i32 , Error > {
57
63
// Get `stdout` so we can write warnings appropriately
58
64
let stdout = & mut std:: io:: stdout ( ) ;
59
- // Get the arguments to this program, removing the first one (something like `perseus`)
60
- let mut prog_args: Vec < String > = env:: args ( ) . collect ( ) ;
61
- // This will panic if the first argument is not found (which is probably someone trying to fuzz us)
62
- let _executable_name = prog_args. remove ( 0 ) ;
63
- // Check the user's environment to make sure they have prerequisites
64
- check_env ( ) ?;
65
+
65
66
// Warn the user if they're using the CLI single-threaded mode
66
67
if env:: var ( "PERSEUS_CLI_SEQUENTIAL" ) . is_ok ( ) {
67
68
writeln ! ( stdout, "Note: the Perseus CLI is running in single-threaded mode, which is less performant on most modern systems. You can switch to multi-threaded mode by unsetting the 'PERSEUS_CLI_SEQUENTIAL' environment variable. If you've deliberately enabled single-threaded mode, you can safely ignore this.\n " ) . expect ( "Failed to write to stdout." ) ;
68
69
}
69
- // Check for special arguments
70
- if matches ! ( prog_args. get( 0 ) , Some ( _) ) {
71
- if prog_args[ 0 ] == "-v" || prog_args[ 0 ] == "--version" {
72
- writeln ! ( stdout, "You are currently running the Perseus CLI v{}! You can see the latest release at https://github.com/arctic-hen7/perseus/releases." , PERSEUS_VERSION ) . expect ( "Failed to write to stdout." ) ;
73
- Ok ( 0 )
74
- } else if prog_args[ 0 ] == "-h" || prog_args[ 0 ] == "--help" {
75
- help ( stdout) ;
76
- Ok ( 0 )
77
- } else {
78
- // Now we can check commands
79
- if prog_args[ 0 ] == "build" {
80
- // Set up the '.perseus/' directory if needed
81
- prepare ( dir. clone ( ) ) ?;
82
- // Delete old build artifacts
70
+
71
+ // Parse the CLI options with `clap`
72
+ let opts: Opts = Opts :: parse ( ) ;
73
+ // Check the user's environment to make sure they have prerequisites
74
+ // We do this after any help pages or version numbers have been parsed for snappiness
75
+ check_env ( ) ?;
76
+ // If we're not cleaning up artifacts, create them if needed
77
+ if !matches ! ( opts. subcmd, Subcommand :: Clean ( _) ) {
78
+ prepare ( dir. clone ( ) ) ?;
79
+ }
80
+ let exit_code = match opts. subcmd {
81
+ Subcommand :: Build ( build_opts) => {
82
+ // Delete old build artifacts
83
+ delete_artifacts ( dir. clone ( ) , "static" ) ?;
84
+ build ( dir, build_opts) ?
85
+ }
86
+ Subcommand :: Export ( export_opts) => {
87
+ // Delete old build/exportation artifacts
88
+ delete_artifacts ( dir. clone ( ) , "static" ) ?;
89
+ delete_artifacts ( dir. clone ( ) , "exported" ) ?;
90
+ export ( dir, export_opts) ?
91
+ }
92
+ Subcommand :: Serve ( serve_opts) => {
93
+ // Delete old build artifacts if `--no-build` wasn't specified
94
+ if !serve_opts. no_build {
83
95
delete_artifacts ( dir. clone ( ) , "static" ) ?;
84
- let exit_code = build ( dir, & prog_args) ?;
85
- Ok ( exit_code)
86
- } else if prog_args[ 0 ] == "export" {
87
- // Set up the '.perseus/' directory if needed
88
- prepare ( dir. clone ( ) ) ?;
89
- // Delete old build/exportation artifacts
96
+ }
97
+ serve ( dir, serve_opts) ?
98
+ }
99
+ Subcommand :: Test ( test_opts) => {
100
+ // This will be used by the subcrates
101
+ env:: set_var ( "PERSEUS_TESTING" , "true" ) ;
102
+ // Set up the '.perseus/' directory if needed
103
+ prepare ( dir. clone ( ) ) ?;
104
+ // Delete old build artifacts if `--no-build` wasn't specified
105
+ if !test_opts. no_build {
90
106
delete_artifacts ( dir. clone ( ) , "static" ) ?;
107
+ }
108
+ serve ( dir, test_opts) ?
109
+ }
110
+ Subcommand :: Clean ( clean_opts) => {
111
+ if clean_opts. dist {
112
+ // The user only wants to remove distribution artifacts
113
+ // We don't delete `render_conf.json` because it's literally impossible for that to be the source of a problem right now
114
+ delete_artifacts ( dir. clone ( ) , "static" ) ?;
115
+ delete_artifacts ( dir. clone ( ) , "pkg" ) ?;
91
116
delete_artifacts ( dir. clone ( ) , "exported" ) ?;
92
- let exit_code = export ( dir, & prog_args) ?;
93
- Ok ( exit_code)
94
- } else if prog_args[ 0 ] == "serve" {
95
- // Set up the '.perseus/' directory if needed
96
- prepare ( dir. clone ( ) ) ?;
97
- // Delete old build artifacts if `--no-build` wasn't specified
98
- if !prog_args. contains ( & "--no-build" . to_string ( ) ) {
99
- delete_artifacts ( dir. clone ( ) , "static" ) ?;
100
- }
101
- let exit_code = serve ( dir, & prog_args) ?;
102
- Ok ( exit_code)
103
- } else if prog_args[ 0 ] == "test" {
104
- // The `test` command serves in the exact same way, but it also sets `PERSEUS_TESTING`
105
- // This will be used by the subcrates
106
- env:: set_var ( "PERSEUS_TESTING" , "true" ) ;
107
- // Set up the '.perseus/' directory if needed
108
- prepare ( dir. clone ( ) ) ?;
109
- // Delete old build artifacts if `--no-build` wasn't specified
110
- if !prog_args. contains ( & "--no-build" . to_string ( ) ) {
111
- delete_artifacts ( dir. clone ( ) , "static" ) ?;
112
- }
113
- let exit_code = serve ( dir, & prog_args) ?;
114
- Ok ( exit_code)
115
- } else if prog_args[ 0 ] == "prep" {
116
- // This command is deliberately undocumented, it's only used for testing
117
- // Set up the '.perseus/' directory if needed
118
- prepare ( dir) ?;
119
- Ok ( 0 )
120
- } else if prog_args[ 0 ] == "eject" {
121
- // Set up the '.perseus/' directory if needed
122
- prepare ( dir. clone ( ) ) ?;
123
- eject ( dir) ?;
124
- Ok ( 0 )
125
- } else if prog_args[ 0 ] == "clean" {
126
- if prog_args. get ( 1 ) == Some ( & "--dist" . to_string ( ) ) {
127
- // The user only wants to remove distribution artifacts
128
- // We don't delete `render_conf.json` because it's literally impossible for that to be the source of a problem right now
129
- delete_artifacts ( dir. clone ( ) , "static" ) ?;
130
- delete_artifacts ( dir, "pkg" ) ?;
131
- } else {
132
- // This command deletes the `.perseus/` directory completely, which musn't happen if the user has ejected
133
- if has_ejected ( dir. clone ( ) ) && prog_args. get ( 1 ) != Some ( & "--force" . to_string ( ) )
134
- {
135
- return Err ( EjectionError :: CleanAfterEject . into ( ) ) ;
136
- }
137
- // Just delete the '.perseus/' directory directly, as we'd do in a corruption
138
- delete_bad_dir ( dir) ?;
139
- }
140
-
141
- Ok ( 0 )
142
117
} else {
143
- writeln ! (
144
- stdout,
145
- "Unknown command '{}'. You can see the help page with -h/--help." ,
146
- prog_args[ 0 ]
147
- )
148
- . expect ( "Failed to write to stdout." ) ;
149
- Ok ( 1 )
118
+ // This command deletes the `.perseus/` directory completely, which musn't happen if the user has ejected
119
+ if has_ejected ( dir. clone ( ) ) && !clean_opts. force {
120
+ return Err ( EjectionError :: CleanAfterEject . into ( ) ) ;
121
+ }
122
+ // Just delete the '.perseus/' directory directly, as we'd do in a corruption
123
+ delete_bad_dir ( dir) ?;
150
124
}
125
+ 0
151
126
}
152
- } else {
153
- writeln ! (
154
- stdout,
155
- "Please provide a command to run, or use -h/--help to see the help page."
156
- )
157
- . expect ( "Failed to write to stdout." ) ;
158
- Ok ( 1 )
159
- }
127
+ Subcommand :: Eject => {
128
+ eject ( dir) ?;
129
+ 0
130
+ }
131
+ Subcommand :: Prep => {
132
+ // The `.perseus/` directory has already been set up in the preliminaries, so we don't need to do anything here
133
+ 0
134
+ }
135
+ } ;
136
+ Ok ( exit_code)
160
137
}
0 commit comments