66// ------------------------------------------------------------------------------------------------
77
88use anyhow:: anyhow;
9+ use chrono:: Datelike ;
910use clap:: Args ;
1011use clap:: ValueHint ;
1112use dialoguer:: Input ;
@@ -21,9 +22,14 @@ use std::io::Write;
2122use std:: path:: Path ;
2223use std:: path:: PathBuf ;
2324
24- const TSSG_VERSION : & str = env ! ( "CARGO_PKG_VERSION" ) ;
25+ use self :: license:: lookup_license;
26+ use self :: license:: DEFAULT_LICENSES ;
27+ use self :: license:: NO_LICENSE ;
28+ use self :: license:: OTHER_LICENSE ;
29+
30+ mod license;
2531
26- const DEFAULT_LICENSES : & [ & str ] = & [ "APACHE-2.0" , "BSD-2-Clause" , "BSD-3-Clause" , "ISC" , "MIT" ] ;
32+ const TSSG_VERSION : & str = env ! ( "CARGO_PKG_VERSION" ) ;
2733
2834lazy_static ! {
2935 static ref VALID_CRATE_NAME : Regex = Regex :: new( r"^[a-zA-Z_-][a-zA-Z0-9_-]*$" ) . unwrap( ) ;
@@ -210,41 +216,29 @@ impl ProjectSettings {
210216 license identifiers.
211217 "#
212218 } ;
213- let other_index = DEFAULT_LICENSES . len ( ) ;
214- let none_index = other_index + 1 ;
215- let selected = DEFAULT_LICENSES
216- . iter ( )
217- . position ( |l| l == & self . license )
218- . unwrap_or_else ( || {
219- if self . license . is_empty ( ) {
220- none_index
221- } else {
222- other_index
223- }
224- } ) ;
225- let ( other, other_default) = if selected == other_index {
219+ let selected = lookup_license ( & self . license ) ;
220+ let ( other, other_default) = if selected == OTHER_LICENSE {
226221 ( format ! ( "Other ({})" , self . license) , self . license . as_ref ( ) )
227222 } else {
228223 ( "Other" . to_string ( ) , "" )
229224 } ;
230- let mut selector = Select :: new ( ) ;
231- let selected = selector
225+ let selected = Select :: new ( )
232226 . with_prompt ( "License" )
233- . items ( DEFAULT_LICENSES )
227+ . items ( & DEFAULT_LICENSES . iter ( ) . map ( |l| l . 0 ) . collect :: < Vec < _ > > ( ) )
234228 . item ( & other)
235229 . item ( "None" )
236230 . default ( selected)
237231 . interact ( ) ?;
238- self . license = if selected == none_index {
232+ self . license = if selected == NO_LICENSE {
239233 "" . to_string ( )
240- } else if selected == other_index {
234+ } else if selected == OTHER_LICENSE {
241235 Input :: new ( )
242236 . with_prompt ( "Other license" )
243237 . with_initial_text ( other_default)
244238 . allow_empty ( true )
245239 . interact_text ( ) ?
246240 } else {
247- DEFAULT_LICENSES [ selected] . to_string ( )
241+ DEFAULT_LICENSES [ selected] . 0 . to_string ( )
248242 } ;
249243
250244 printdoc ! { r#"
@@ -288,13 +282,22 @@ impl ProjectSettings {
288282 self . grammar_crate_name . replace ( "-" , "_" )
289283 }
290284
285+ fn license_author ( & self ) -> String {
286+ if self . author . is_empty ( ) {
287+ format ! ( "the {} authors" , self . crate_name)
288+ } else {
289+ self . author . clone ( )
290+ }
291+ }
292+
291293 fn generate_files_into ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
292294 fs:: create_dir_all ( project_path) ?;
293295 fs:: create_dir_all ( project_path. join ( "rust" ) ) ?;
294296 fs:: create_dir_all ( project_path. join ( "src" ) ) ?;
295297 fs:: create_dir_all ( project_path. join ( "test" ) ) ?;
296298 self . generate_readme ( project_path) ?;
297299 self . generate_changelog ( project_path) ?;
300+ self . generate_license ( project_path) ?;
298301 self . generate_cargo_toml ( project_path) ?;
299302 self . generate_rust_bin ( project_path) ?;
300303 self . generate_rust_lib ( project_path) ?;
@@ -437,6 +440,31 @@ impl ProjectSettings {
437440 Ok ( ( ) )
438441 }
439442
443+ fn generate_license ( & self , project_path : & Path ) -> std:: io:: Result < ( ) > {
444+ match lookup_license ( & self . license ) {
445+ NO_LICENSE | OTHER_LICENSE => { }
446+ selected => {
447+ let mut file = File :: create ( project_path. join ( "LICENSE" ) ) ?;
448+ let year = chrono:: Utc :: now ( ) . year ( ) ;
449+ let author = self . license_author ( ) ;
450+ ( DEFAULT_LICENSES [ selected] . 2 ) ( & mut file, year, & author) ?;
451+ }
452+ } ;
453+ Ok ( ( ) )
454+ }
455+
456+ fn write_license_header ( & self , file : & mut File , prefix : & str ) -> std:: io:: Result < ( ) > {
457+ match lookup_license ( & self . license ) {
458+ NO_LICENSE | OTHER_LICENSE => { }
459+ selected => {
460+ let year = chrono:: Utc :: now ( ) . year ( ) ;
461+ let author = self . license_author ( ) ;
462+ ( DEFAULT_LICENSES [ selected] . 1 ) ( file, year, & author, prefix) ?;
463+ }
464+ } ;
465+ Ok ( ( ) )
466+ }
467+
440468 fn generate_cargo_toml ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
441469 let mut file = File :: create ( project_path. join ( "Cargo.toml" ) ) ?;
442470 writedoc ! { file, r#"
@@ -496,6 +524,7 @@ impl ProjectSettings {
496524
497525 fn generate_rust_bin ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
498526 let mut file = File :: create ( project_path. join ( "rust/bin.rs" ) ) ?;
527+ self . write_license_header ( & mut file, "// " ) ?;
499528 writedoc ! { file, r#"
500529 use clap::Parser;
501530 use tree_sitter_stack_graphs::cli::provided_languages::Subcommands;
@@ -522,6 +551,7 @@ impl ProjectSettings {
522551
523552 fn generate_rust_lib ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
524553 let mut file = File :: create ( project_path. join ( "rust/lib.rs" ) ) ?;
554+ self . write_license_header ( & mut file, "// " ) ?;
525555 writedoc ! { file, r#"
526556 use tree_sitter_stack_graphs::loader::FileAnalyzers;
527557 use tree_sitter_stack_graphs::loader::LanguageConfiguration;
@@ -563,6 +593,7 @@ impl ProjectSettings {
563593
564594 fn generate_rust_test ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
565595 let mut file = File :: create ( project_path. join ( "rust/test.rs" ) ) ?;
596+ self . write_license_header ( & mut file, "// " ) ?;
566597 writedoc ! { file, r#"
567598 use std::path::PathBuf;
568599 use tree_sitter_stack_graphs::ci::Tester;
@@ -586,6 +617,7 @@ impl ProjectSettings {
586617
587618 fn generate_stack_graphs_tsg ( & self , project_path : & Path ) -> anyhow:: Result < ( ) > {
588619 let mut file = File :: create ( project_path. join ( "src/stack-graphs.tsg" ) ) ?;
620+ self . write_license_header ( & mut file, ";; " ) ?;
589621 writedoc ! { file, r#"
590622 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
591623 ;; Stack graphs definition for {}
0 commit comments