@@ -21,6 +21,10 @@ pub struct Command {
21
21
#[ arg( long) ]
22
22
project_type : Option < ProjectType > ,
23
23
24
+ /// Package manager
25
+ #[ arg( long) ]
26
+ package_manager : Option < String > ,
27
+
24
28
/// Target language
25
29
#[ arg( long) ]
26
30
language : Option < String > ,
@@ -68,6 +72,7 @@ struct ProjectConfig {
68
72
project_type : ProjectType ,
69
73
language : String ,
70
74
private : bool ,
75
+ package_manager : Option < String > ,
71
76
}
72
77
73
78
// Template constants using include_str!
@@ -114,18 +119,26 @@ static CHECKMARK: Emoji<'_, '_> = Emoji("✓ ", "");
114
119
115
120
pub fn handler ( args : & Command ) -> Result < ( ) > {
116
121
let ( project_path, project_name) = if args. no_interactive {
117
- let project_path = args
118
- . path
119
- . clone ( )
120
- . unwrap_or_else ( || PathBuf :: from ( "my-codemod" ) ) ;
122
+ let project_path = match args. path . clone ( ) {
123
+ Some ( path) => path ,
124
+ None => return Err ( anyhow ! ( "Path argument is required" ) ) ,
125
+ } ;
121
126
122
- let project_name = args. name . clone ( ) . unwrap_or_else ( || {
123
- project_path
124
- . file_name ( )
125
- . and_then ( |n| n. to_str ( ) )
126
- . unwrap_or ( "my-codemod" )
127
- . to_string ( )
128
- } ) ;
127
+ let project_name = match args. name . clone ( ) {
128
+ Some ( name) => name,
129
+ None => {
130
+ let file_name = project_path
131
+ . file_name ( )
132
+ . and_then ( |n| n. to_str ( ) )
133
+ . ok_or_else ( || {
134
+ anyhow ! (
135
+ "Could not determine project name from path {}" ,
136
+ project_path. display( )
137
+ )
138
+ } ) ?;
139
+ file_name. to_string ( )
140
+ }
141
+ } ;
129
142
130
143
( project_path, project_name)
131
144
} else {
@@ -158,23 +171,40 @@ pub fn handler(args: &Command) -> Result<()> {
158
171
}
159
172
160
173
let config = if args. no_interactive {
174
+ let project_type = args
175
+ . project_type
176
+ . clone ( )
177
+ . ok_or_else ( || anyhow ! ( "Project type is required --project-type" ) ) ?;
178
+ let package_manager = match ( & project_type, args. package_manager . clone ( ) ) {
179
+ ( ProjectType :: AstGrepJs , Some ( pm) ) => Some ( pm) ,
180
+ ( ProjectType :: AstGrepJs , None ) => {
181
+ return Err ( anyhow ! (
182
+ "--package-manager is required when --project-type is ast-grep-js"
183
+ ) ) ;
184
+ }
185
+ _ => None ,
186
+ } ;
161
187
ProjectConfig {
162
188
name : project_name,
163
189
description : args
164
190
. description
165
191
. clone ( )
166
- . unwrap_or_else ( || "A new codemod" . to_string ( ) ) ,
192
+ . ok_or_else ( || anyhow ! ( "Description is required --description" ) ) ? ,
167
193
author : args
168
194
. author
169
195
. clone ( )
170
- . unwrap_or_else ( || "Author <author@example.com>" . to_string ( ) ) ,
171
- license : args. license . clone ( ) . unwrap_or_else ( || "MIT" . to_string ( ) ) ,
172
- project_type : args. project_type . clone ( ) . unwrap_or ( ProjectType :: Shell ) ,
196
+ . ok_or_else ( || anyhow ! ( "Author is required --author" ) ) ?,
197
+ license : args
198
+ . license
199
+ . clone ( )
200
+ . ok_or_else ( || anyhow ! ( "License is required --license" ) ) ?,
201
+ project_type : project_type. clone ( ) ,
173
202
language : args
174
203
. language
175
204
. clone ( )
176
- . unwrap_or_else ( || "javascript" . to_string ( ) ) ,
205
+ . ok_or_else ( || anyhow ! ( "Language is required --language" ) ) ? ,
177
206
private : args. private ,
207
+ package_manager,
178
208
}
179
209
} else {
180
210
interactive_setup ( & project_name, args) ?
@@ -183,7 +213,7 @@ pub fn handler(args: &Command) -> Result<()> {
183
213
create_project ( & project_path, & config) ?;
184
214
185
215
// Run post init commands
186
- run_post_init_commands ( & project_path, & config) ?;
216
+ run_post_init_commands ( & project_path, & config, args . no_interactive ) ?;
187
217
188
218
print_next_steps ( & project_path, & config) ?;
189
219
@@ -259,6 +289,7 @@ fn interactive_setup(project_name: &str, args: &Command) -> Result<ProjectConfig
259
289
project_type,
260
290
language,
261
291
private,
292
+ package_manager : args. package_manager . clone ( ) ,
262
293
} )
263
294
}
264
295
@@ -471,14 +502,23 @@ fn create_readme(project_path: &Path, config: &ProjectConfig) -> Result<()> {
471
502
Ok ( ( ) )
472
503
}
473
504
474
- fn run_post_init_commands ( project_path : & Path , config : & ProjectConfig ) -> Result < ( ) > {
505
+ fn run_post_init_commands (
506
+ project_path : & Path ,
507
+ config : & ProjectConfig ,
508
+ no_interactive : bool ,
509
+ ) -> Result < ( ) > {
475
510
match config. project_type {
476
511
ProjectType :: AstGrepJs => {
477
- let package_manager = Select :: new (
478
- "Which package manager would you like to use?" ,
479
- vec ! [ "npm" , "yarn" , "pnpm" ] ,
480
- )
481
- . prompt ( ) ?;
512
+ let package_manager = if no_interactive {
513
+ config. package_manager . clone ( ) . unwrap_or ( "npm" . to_string ( ) )
514
+ } else {
515
+ Select :: new (
516
+ "Which package manager would you like to use?" ,
517
+ vec ! [ "npm" , "yarn" , "pnpm" ] ,
518
+ )
519
+ . prompt ( ) ?
520
+ . to_string ( )
521
+ } ;
482
522
483
523
let output = ProcessCommand :: new ( package_manager)
484
524
. arg ( "install" )
0 commit comments