@@ -23,9 +23,10 @@ use std::path::PathBuf;
2323const TSSG_VERSION : & str = env ! ( "CARGO_PKG_VERSION" ) ;
2424
2525lazy_static ! {
26- static ref VALID_NAME : Regex = Regex :: new( r"^[a-zA-Z0-9_.-]+$" ) . unwrap( ) ;
27- static ref VALID_CRATE_NAME : Regex = Regex :: new( r"^[a-zA-Z0-9_.-]+$" ) . unwrap( ) ;
26+ static ref VALID_CRATE_NAME : Regex = Regex :: new( r"^[a-zA-Z_-][a-zA-Z0-9_-]*$" ) . unwrap( ) ;
2827 static ref VALID_CRATE_VERSION : Regex = Regex :: new( r"^[0-9]+\.[0-9]+\.[0-9]+$" ) . unwrap( ) ;
28+ static ref VALID_DEPENDENCY_VERSION : Regex =
29+ Regex :: new( r"^[~^]?[0-9]+(\.[0-9]+(\.[0-9]+)?)?$" ) . unwrap( ) ;
2930}
3031
3132/// Initialize project
@@ -46,6 +47,7 @@ impl InitArgs {
4647 let mut config = ProjectSettings :: default ( ) ;
4748 loop {
4849 config. read_from_console ( ) ?;
50+ println ! ( ) ;
4951 println ! ( "=== Review project settings ===" ) ;
5052 println ! (
5153 "Project directory : {}" ,
@@ -97,12 +99,12 @@ struct ProjectSettings {
9799 language_name : String ,
98100 language_id : String ,
99101 language_file_extension : String ,
100- package_name : String ,
101- package_version : String ,
102+ crate_name : String ,
103+ crate_version : String ,
102104 author : String ,
103105 license : String ,
104- grammar_package_name : String ,
105- grammar_package_version : String ,
106+ grammar_crate_name : String ,
107+ grammar_crate_version : String ,
106108}
107109
108110impl ProjectSettings {
@@ -117,13 +119,12 @@ impl ProjectSettings {
117119 . with_prompt ( "Language name" )
118120 . with_initial_text ( & self . language_name )
119121 . interact_text ( ) ?;
120- println ! ( ) ;
121122
122123 printdoc ! { r#"
123124
124125 Give an identifier for {}. This identifier will be used for the suggested project
125- name and suggested dependencies. May only contain letters, numbers, dashes, dots,
126- and underscores.
126+ name and suggested dependencies. May only contain letters, numbers, dashes, and
127+ underscores.
127128 "# ,
128129 self . language_name,
129130 } ;
@@ -135,56 +136,58 @@ impl ProjectSettings {
135136 } else {
136137 & self . language_id
137138 } )
138- . validate_with ( regex_validator ( & VALID_NAME ) )
139+ . validate_with ( regex_validator ( & VALID_CRATE_NAME ) )
139140 . interact_text ( ) ?;
140- println ! ( ) ;
141141
142142 printdoc ! { r#"
143143
144144 Give the file extension for {}. This file extension will be used for stub files in
145- the project. May only contain letters, numbers, dashes, dots, and underscores.
145+ the project. May only contain letters, numbers, dashes, and underscores.
146146 "# ,
147147 self . language_name,
148148 } ;
149+ let default_language_file_extension = if self . language_file_extension . is_empty ( ) {
150+ & self . language_id
151+ } else {
152+ & self . language_file_extension
153+ } ;
149154 self . language_file_extension = Input :: new ( )
150155 . with_prompt ( "Language file extension" )
151- . with_initial_text ( & self . language_file_extension )
152- . validate_with ( regex_validator ( & VALID_NAME ) )
156+ . with_initial_text ( default_language_file_extension )
157+ . validate_with ( regex_validator ( & VALID_CRATE_NAME ) )
153158 . interact_text ( ) ?;
154- println ! ( ) ;
155159
156160 printdoc ! { r#"
157161
158- Give the package name for this project. Must be a valid Rust crate name.
162+ Give the crate name for this project. May only contain letters, numbers, dashes,
163+ and underscores.
159164 "#
160165 } ;
161- let default_package_name = "tree-sitter-stack-graphs-" . to_string ( ) + & self . language_id ;
162- self . package_name = Input :: new ( )
166+ let default_crate_name = "tree-sitter-stack-graphs-" . to_string ( ) + & self . language_id ;
167+ self . crate_name = Input :: new ( )
163168 . with_prompt ( "Package name" )
164- . with_initial_text ( if self . package_name . is_empty ( ) {
165- & default_package_name
169+ . with_initial_text ( if self . crate_name . is_empty ( ) {
170+ & default_crate_name
166171 } else {
167- & self . package_name
172+ & self . crate_name
168173 } )
169174 . validate_with ( regex_validator ( & VALID_CRATE_NAME ) )
170175 . interact_text ( ) ?;
171- println ! ( ) ;
172176
173177 printdoc ! { r#"
174178
175- Give the package version for this project.
179+ Give the crate version for this project. Must be in MAJOR.MINOR.PATCH format .
176180 "#
177181 } ;
178- self . package_version = Input :: new ( )
182+ self . crate_version = Input :: new ( )
179183 . with_prompt ( "Package version" )
180- . with_initial_text ( if self . package_version . is_empty ( ) {
184+ . with_initial_text ( if self . crate_version . is_empty ( ) {
181185 "0.1.0"
182186 } else {
183- & self . package_version
187+ & self . crate_version
184188 } )
185189 . validate_with ( regex_validator ( & VALID_CRATE_VERSION ) )
186190 . interact_text ( ) ?;
187- println ! ( ) ;
188191
189192 printdoc ! { r#"
190193
@@ -196,7 +199,6 @@ impl ProjectSettings {
196199 . with_initial_text ( & self . author )
197200 . allow_empty ( true )
198201 . interact_text ( ) ?;
199- println ! ( ) ;
200202
201203 printdoc ! { r#"
202204
@@ -208,42 +210,48 @@ impl ProjectSettings {
208210 . with_initial_text ( & self . license )
209211 . allow_empty ( true )
210212 . interact_text ( ) ?;
211- println ! ( ) ;
212213
213214 printdoc ! { r#"
214215
215216 Give the crate name for the Tree-sitter grammar that is to be used for
216- parsing.
217+ parsing. May only contain letters, numbers, dashes, and underscores.
217218 "#
218219 } ;
219- let default_grammar_package_name = "tree-sitter-" . to_string ( ) + & self . language_id ;
220- self . grammar_package_name = Input :: new ( )
221- . with_prompt ( "Grammar package name" )
222- . with_initial_text ( if self . grammar_package_name . is_empty ( ) {
223- & default_grammar_package_name
220+ let default_grammar_crate_name = "tree-sitter-" . to_string ( ) + & self . language_id ;
221+ self . grammar_crate_name = Input :: new ( )
222+ . with_prompt ( "Grammar crate name" )
223+ . with_initial_text ( if self . grammar_crate_name . is_empty ( ) {
224+ & default_grammar_crate_name
224225 } else {
225- & self . grammar_package_name
226+ & self . grammar_crate_name
226227 } )
227228 . interact_text ( ) ?;
228- println ! ( ) ;
229229
230230 printdoc ! { r##"
231231
232- Give the crate version the {} dependency. The format must be MAJOR.MINOR.PATCH.
233- Prefix with ~ to allow any patch version, for example: ~0.4.1
234- Prefix with ^ to allow any minor version, for example: ^1.2.7
232+ Give the crate version the {} dependency. This must be a valid Cargo
233+ dependency version. For example, 1.2, ^0.4.1, or ~3.2.4.
234+ See https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html.
235235 "## ,
236- self . grammar_package_name ,
236+ self . grammar_crate_name ,
237237 } ;
238- self . grammar_package_version = Input :: new ( )
239- . with_prompt ( "Grammar package version" )
240- . with_initial_text ( & self . grammar_package_version )
238+ self . grammar_crate_version = Input :: new ( )
239+ . with_prompt ( "Grammar crate version" )
240+ . with_initial_text ( & self . grammar_crate_version )
241+ . validate_with ( regex_validator ( & VALID_DEPENDENCY_VERSION ) )
241242 . interact_text ( ) ?;
242- println ! ( ) ;
243243
244244 Ok ( ( ) )
245245 }
246246
247+ fn package_name ( & self ) -> String {
248+ self . crate_name . replace ( "-" , "_" )
249+ }
250+
251+ fn grammar_package_name ( & self ) -> String {
252+ self . grammar_crate_name . replace ( "-" , "_" )
253+ }
254+
247255 fn generate_files_into ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
248256 fs:: create_dir_all ( project_path) ?;
249257 fs:: create_dir_all ( project_path. join ( "rust" ) ) ?;
@@ -359,13 +367,13 @@ impl ProjectSettings {
359367 Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation.
360368 "#### ,
361369 self . language_name,
362- self . language_name, self . grammar_package_name ,
363- self . grammar_package_name , self . grammar_package_name ,
364- self . package_name , self . package_version ,
365- self . package_name ,
366- self . package_name ,
367- self . package_name ,
368- self . package_name ,
370+ self . language_name, self . grammar_crate_name ,
371+ self . grammar_crate_name , self . grammar_crate_name ,
372+ self . crate_name , self . crate_version ,
373+ self . crate_name ,
374+ self . crate_name ,
375+ self . crate_name ,
376+ self . crate_name ,
369377 self . language_file_extension,
370378 } ?;
371379 Ok ( ( ) )
@@ -381,7 +389,7 @@ impl ProjectSettings {
381389 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
382390 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
383391 "#### ,
384- self . package_name ,
392+ self . crate_name ,
385393 } ?;
386394 Ok ( ( ) )
387395 }
@@ -396,9 +404,9 @@ impl ProjectSettings {
396404 readme = "README.md"
397405 keywords = ["tree-sitter", "stack-graphs", "{}"]
398406 "# ,
399- self . package_name ,
400- self . package_version ,
401- self . language_name, self . grammar_package_name ,
407+ self . crate_name ,
408+ self . crate_version ,
409+ self . language_name, self . grammar_crate_name ,
402410 self . language_id
403411 } ?;
404412 if !self . author . is_empty ( ) {
@@ -436,9 +444,9 @@ impl ProjectSettings {
436444 tree-sitter-stack-graphs = "{}"
437445 {} = "{}"
438446 "# ,
439- self . package_name ,
447+ self . crate_name ,
440448 TSSG_VERSION ,
441- self . grammar_package_name , self . grammar_package_version ,
449+ self . grammar_crate_name , self . grammar_crate_version ,
442450 } ?;
443451 Ok ( ( ) )
444452 }
@@ -453,7 +461,7 @@ impl ProjectSettings {
453461 fn main() -> anyhow::Result<()> {{
454462 let cli = Cli::parse();
455463 cli.subcommand.run(vec![
456- tree_sitter_stack_graphs_typescript ::language_configuration(&NoCancellation),
464+ {} ::language_configuration(&NoCancellation),
457465 ])
458466 }}
459467
@@ -463,7 +471,8 @@ impl ProjectSettings {
463471 #[clap(subcommand)]
464472 subcommand: Subcommands,
465473 }}
466- "#
474+ "# ,
475+ self . package_name( ) ,
467476 } ?;
468477 Ok ( ( ) )
469478 }
@@ -481,7 +490,7 @@ impl ProjectSettings {
481490 /// The stack graphs builtins configuration for this language
482491 pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg");
483492 /// The stack graphs builtins source for this language
484- pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.ts ");
493+ pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.{} ");
485494
486495 /// The name of the file path global variable
487496 pub const FILE_PATH_VAR: &str = "FILE_PATH";
@@ -501,15 +510,16 @@ impl ProjectSettings {
501510 .unwrap()
502511 }}
503512 "# ,
504- self . grammar_package_name. replace( "-" , "_" ) ,
513+ self . language_file_extension,
514+ self . grammar_package_name( ) ,
505515 self . language_file_extension,
506516 self . language_file_extension,
507517 } ?;
508518 Ok ( ( ) )
509519 }
510520
511521 fn generate_rust_test ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
512- let mut file = File :: create ( project_path. join ( "rust/lib .rs" ) ) ?;
522+ let mut file = File :: create ( project_path. join ( "rust/test .rs" ) ) ?;
513523 writedoc ! { file, r#"
514524 use std::path::PathBuf;
515525 use tree_sitter_stack_graphs::ci::Tester;
@@ -526,7 +536,7 @@ impl ProjectSettings {
526536 .run()
527537 }}
528538 "# ,
529- self . package_name,
539+ self . package_name( ) ,
530540 } ?;
531541 Ok ( ( ) )
532542 }
@@ -625,12 +635,12 @@ impl std::fmt::Display for ProjectSettings {
625635 self . language_name,
626636 self . language_id,
627637 self . language_file_extension,
628- self . package_name ,
629- self . package_version ,
638+ self . crate_name ,
639+ self . crate_version ,
630640 self . author,
631641 self . license,
632- self . grammar_package_name ,
633- self . grammar_package_version ,
642+ self . grammar_crate_name ,
643+ self . grammar_crate_version ,
634644 }
635645 }
636646}
0 commit comments