@@ -8,7 +8,7 @@ use inquire::validator::ValueRequiredValidator;
8
8
9
9
use std:: fmt:: Display ;
10
10
use std:: fs:: { self , File } ;
11
- use std:: path:: PathBuf ;
11
+ use std:: path:: { Path , PathBuf } ;
12
12
13
13
#[ derive( Parser ) ]
14
14
pub struct NewArg {
@@ -29,25 +29,33 @@ pub struct NewArg {
29
29
/// Please see the command description for the what arguments are required.
30
30
#[ arg( short, long, global = true ) ]
31
31
yes : bool ,
32
- /// Create new project/items in the folder specified by this argument.
33
- #[ arg( short, long, global = true , default_value = "." ) ]
34
- base_dir : PathBuf ,
32
+
33
+ /// Path to ast-grep root config, default is sgconfig.yml.
34
+ #[ clap( short, long, value_name = "CONFIG_FILE" ) ]
35
+ config : Option < PathBuf > ,
36
+ }
37
+
38
+ fn create_dir ( project_dir : & Path , dir : & str ) -> Result < PathBuf > {
39
+ let path = project_dir. join ( dir) ;
40
+ fs:: create_dir_all ( & path) ?;
41
+ // create a .gitkeep file to keep the folder in git
42
+ // https://github.com/ast-grep/ast-grep/issues/1273
43
+ let gitkeep = path. join ( ".gitkeep" ) ;
44
+ File :: create ( gitkeep) ?;
45
+ Ok ( path)
35
46
}
36
47
37
48
impl NewArg {
38
- fn ask_dir_and_create ( & self , prompt : & str , default : & str ) -> Result < PathBuf > {
49
+ fn find_project_config ( & self ) -> Result < Option < ProjectConfig > > {
50
+ ProjectConfig :: by_config_path ( self . config . clone ( ) )
51
+ }
52
+ fn ask_dir ( & self , prompt : & str , default : & str ) -> Result < String > {
39
53
let dir = if self . yes {
40
54
default. to_owned ( )
41
55
} else {
42
56
inquire:: Text :: new ( prompt) . with_default ( default) . prompt ( ) ?
43
57
} ;
44
- let path = self . base_dir . join ( dir) ;
45
- fs:: create_dir_all ( & path) ?;
46
- // create a .gitkeep file to keep the folder in git
47
- // https://github.com/ast-grep/ast-grep/issues/1273
48
- let gitkeep = path. join ( ".gitkeep" ) ;
49
- File :: create ( gitkeep) ?;
50
- Ok ( path)
58
+ Ok ( dir)
51
59
}
52
60
53
61
fn confirm ( & self , prompt : & str ) -> Result < bool > {
@@ -144,8 +152,8 @@ impl Display for Entity {
144
152
}
145
153
146
154
pub fn run_create_new ( mut arg : NewArg ) -> Result < ( ) > {
147
- let config_path = ProjectConfig :: by_project_dir ( & arg. base_dir ) ?;
148
- register_custom_language ( config_path ) ?;
155
+ let project_config = arg. find_project_config ( ) ?;
156
+ register_custom_language ( project_config ) ?;
149
157
if let Some ( entity) = arg. entity . take ( ) {
150
158
run_create_entity ( entity, arg)
151
159
} else {
@@ -155,12 +163,12 @@ pub fn run_create_new(mut arg: NewArg) -> Result<()> {
155
163
156
164
fn run_create_entity ( entity : Entity , arg : NewArg ) -> Result < ( ) > {
157
165
// check if we are under a project dir
158
- if let Some ( found) = ProjectConfig :: by_project_dir ( & arg. base_dir ) ? {
166
+ if let Some ( found) = arg. find_project_config ( ) ? {
159
167
return do_create_entity ( entity, found, arg) ;
160
168
}
161
169
// check if we creating a project
162
170
if entity == Entity :: Project {
163
- create_new_project ( arg)
171
+ create_new_project ( arg, std :: env :: current_dir ( ) ? . as_path ( ) )
164
172
} else {
165
173
// if not, return error
166
174
Err ( anyhow:: anyhow!( EC :: ProjectNotExist ) )
@@ -179,29 +187,33 @@ fn do_create_entity(entity: Entity, found: ProjectConfig, arg: NewArg) -> Result
179
187
180
188
fn ask_entity_type ( arg : NewArg ) -> Result < ( ) > {
181
189
// 1. check if we are under a sgconfig.yml
182
- if let Some ( found) = ProjectConfig :: by_project_dir ( & arg. base_dir ) ? {
190
+ if let Some ( found) = arg. find_project_config ( ) ? {
183
191
// 2. ask users what to create if yes
184
192
let entity = arg. ask_entity_type ( ) ?;
185
193
do_create_entity ( entity, found, arg)
186
194
} else {
187
195
// 3. ask users to provide project info if no sgconfig found
188
196
print ! ( "No sgconfig.yml found. " ) ;
189
- create_new_project ( arg)
197
+ let current_dir = std:: env:: current_dir ( ) ?;
198
+ create_new_project ( arg, & current_dir)
190
199
}
191
200
}
192
201
193
- fn create_new_project ( arg : NewArg ) -> Result < ( ) > {
202
+ fn create_new_project ( arg : NewArg , project_dir : & Path ) -> Result < ( ) > {
194
203
println ! ( "Creating a new ast-grep project..." ) ;
195
- let rule_dirs = arg. ask_dir_and_create ( "Where do you want to have your rules?" , "rules" ) ?;
204
+ let ask_dir_and_create = |prompt : & str , default : & str | -> Result < PathBuf > {
205
+ let dir = arg. ask_dir ( prompt, default) ?;
206
+ create_dir ( project_dir, & dir)
207
+ } ;
208
+ let rule_dirs = ask_dir_and_create ( "Where do you want to have your rules?" , "rules" ) ?;
196
209
let test_dirs = if arg. confirm ( "Do you want to create rule tests?" ) ? {
197
- let test_dirs =
198
- arg. ask_dir_and_create ( "Where do you want to have your tests?" , "rule-tests" ) ?;
210
+ let test_dirs = ask_dir_and_create ( "Where do you want to have your tests?" , "rule-tests" ) ?;
199
211
Some ( TestConfig :: from ( test_dirs) )
200
212
} else {
201
213
None
202
214
} ;
203
215
let utils = if arg. confirm ( "Do you want to create folder for utility rules?" ) ? {
204
- let util_dirs = arg . ask_dir_and_create ( "Where do you want to have your utilities?" , "utils" ) ?;
216
+ let util_dirs = ask_dir_and_create ( "Where do you want to have your utilities?" , "utils" ) ?;
205
217
Some ( util_dirs)
206
218
} else {
207
219
None
@@ -214,7 +226,7 @@ fn create_new_project(arg: NewArg) -> Result<()> {
214
226
language_globs : None , // advanced feature, skip now
215
227
language_injections : vec ! [ ] , // advanced feature
216
228
} ;
217
- let config_path = arg . base_dir . join ( "sgconfig.yml" ) ;
229
+ let config_path = project_dir . join ( "sgconfig.yml" ) ;
218
230
let f = File :: create ( config_path) ?;
219
231
serde_yaml:: to_writer ( f, & root_config) ?;
220
232
println ! ( "Your new ast-grep project has been created!" ) ;
@@ -358,9 +370,9 @@ mod test {
358
370
name : None ,
359
371
lang : None ,
360
372
yes : true ,
361
- base_dir : tempdir . to_path_buf ( ) ,
373
+ config : None ,
362
374
} ;
363
- run_create_new ( arg) ?;
375
+ create_new_project ( arg, tempdir ) ?;
364
376
assert ! ( tempdir. join( "sgconfig.yml" ) . exists( ) ) ;
365
377
Ok ( ( ) )
366
378
}
@@ -371,9 +383,9 @@ mod test {
371
383
name : Some ( "test-rule" . into ( ) ) ,
372
384
lang : Some ( SupportLang :: Rust . into ( ) ) ,
373
385
yes : true ,
374
- base_dir : temp. to_path_buf ( ) ,
386
+ config : Some ( temp. join ( "sgconfig.yml" ) ) ,
375
387
} ;
376
- run_create_new ( arg) . unwrap ( ) ;
388
+ run_create_new ( arg) ? ;
377
389
assert ! ( temp. join( "rules/test-rule.yml" ) . exists( ) ) ;
378
390
Ok ( ( ) )
379
391
}
@@ -384,9 +396,9 @@ mod test {
384
396
name : Some ( "test-utils" . into ( ) ) ,
385
397
lang : Some ( SupportLang :: Rust . into ( ) ) ,
386
398
yes : true ,
387
- base_dir : temp. to_path_buf ( ) ,
399
+ config : Some ( temp. join ( "sgconfig.yml" ) ) ,
388
400
} ;
389
- run_create_new ( arg) . unwrap ( ) ;
401
+ run_create_new ( arg) ? ;
390
402
assert ! ( temp. join( "utils/test-utils.yml" ) . exists( ) ) ;
391
403
Ok ( ( ) )
392
404
}
0 commit comments