From fcfc553d6b9d4a40ebfe2871b335affa5809eba9 Mon Sep 17 00:00:00 2001 From: Tar-Tarus Date: Mon, 30 Sep 2024 12:00:43 +0200 Subject: [PATCH] CLI: Add javascript as option for template flag to `new` (#3395) --- CHANGELOG.md | 4 + Cargo.lock | 3 + Cargo.toml | 2 +- compiler-cli/Cargo.toml | 1 + compiler-cli/src/main.rs | 6 +- compiler-cli/src/new.rs | 14 +++- ...new__tests__new_with_default_template.snap | 23 ++++++ ..._new_with_default_template@.gitignore.snap | 8 ++ ...__new_with_default_template@README.md.snap | 28 +++++++ ..._new_with_default_template@gleam.toml.snap | 23 ++++++ ...__tests__new_with_javascript_template.snap | 24 ++++++ ...w_with_javascript_template@.gitignore.snap | 8 ++ ...ew_with_javascript_template@README.md.snap | 28 +++++++ ...w_with_javascript_template@gleam.toml.snap | 24 ++++++ compiler-cli/src/new/tests.rs | 76 ++++++++++++++++--- 15 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@.gitignore.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@README.md.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@gleam.toml.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@.gitignore.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@README.md.snap create mode 100644 compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@gleam.toml.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index e1973667e30..de36b777efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Build tool +- The `--template` flag for `gleam new` takes the values `erlang` and + `javascript` to specify what target to use, with `erlang` being the default. + ([Mohammed Khouni](https://github.com/Tar-Tarus)) + ### Compiler - The compiler now prints correctly qualified or aliased type names when diff --git a/Cargo.lock b/Cargo.lock index 2a93273b045..375a3b89f94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,6 +819,7 @@ dependencies = [ "http", "ignore", "im", + "insta", "itertools", "lsp-server", "lsp-types", @@ -1188,9 +1189,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" dependencies = [ "console", + "globset", "lazy_static", "linked-hash-map", "similar", + "walkdir", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1d6a3a01dad..d26ee6b2e80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ thiserror = "1" # Test assertion errors with diffs pretty_assertions = "1" # Snapshot testing to make test maintenance easier -insta = "1" +insta = {version = "1", features = ["glob"]} # A transitive dependency needed to compile into wasm32-unknown-unknown # See https://docs.rs/getrandom/latest/getrandom/index.html#webassembly-support getrandom = { version = "0", features = ["js"] } diff --git a/compiler-cli/Cargo.toml b/compiler-cli/Cargo.toml index e937e446f20..e2036c87461 100644 --- a/compiler-cli/Cargo.toml +++ b/compiler-cli/Cargo.toml @@ -65,6 +65,7 @@ walkdir.workspace = true # Creation of temporary directories tempfile = "3" pretty_assertions.workspace = true +insta.workspace = true [build-dependencies] # For statically linking the VCRuntime on Windows when diff --git a/compiler-cli/src/main.rs b/compiler-cli/src/main.rs index 1e62173f80f..62153c90724 100644 --- a/compiler-cli/src/main.rs +++ b/compiler-cli/src/main.rs @@ -253,6 +253,10 @@ enum Command { Export(ExportTarget), } +fn template_doc() -> &'static str { + "The template to use" +} + fn target_doc() -> String { format!("The platform to target ({})", Target::VARIANTS.join("|")) } @@ -288,7 +292,7 @@ pub struct NewOptions { #[arg(long)] pub name: Option, - #[arg(long, ignore_case = true, default_value = "lib")] + #[arg(long, ignore_case = true, default_value = "erlang", help = template_doc())] pub template: new::Template, /// Skip git initialization and creation of .gitignore, .git/* and .github/* files diff --git a/compiler-cli/src/new.rs b/compiler-cli/src/new.rs index 45b041b87db..1d0a3c2c7df 100644 --- a/compiler-cli/src/new.rs +++ b/compiler-cli/src/new.rs @@ -24,9 +24,13 @@ const ELIXIR_VERSION: &str = "1.15.4"; #[derive( Debug, Serialize, Deserialize, Display, EnumString, VariantNames, ValueEnum, Clone, Copy, )] -#[strum(serialize_all = "kebab_case")] +#[strum(serialize_all = "lowercase")] +#[clap(rename_all = "lower")] pub enum Template { + #[clap(skip)] Lib, + Erlang, + JavaScript, } #[derive(Debug)] @@ -74,6 +78,10 @@ impl FileToCreate { let skip_git = creator.options.skip_git; let skip_github = creator.options.skip_github; let gleam_version = creator.gleam_version; + let target = match creator.options.template { + Template::JavaScript => "target = \"javascript\"\n", + Template::Lib | Template::Erlang => "", + }; match self { Self::Readme => Some(format!( @@ -142,7 +150,7 @@ pub fn hello_world_test() { Self::GleamToml => Some(format!( r#"name = "{project_name}" version = "1.0.0" - +{target} # Fill out these fields if you intend to generate HTML documentation or publish # your project to the Hex package manager. # @@ -241,7 +249,7 @@ impl Creator { } match self.options.template { - Template::Lib => { + Template::Lib | Template::Erlang | Template::JavaScript => { for file in FileToCreate::iter() { let path = file.location(self); if let Some(contents) = file.contents(self) { diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template.snap new file mode 100644 index 00000000000..5e43b21ce72 --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template.snap @@ -0,0 +1,23 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(path.join(\"gleam.toml\")).unwrap()" +--- +name = "my_project" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.34.0 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@.gitignore.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@.gitignore.snap new file mode 100644 index 00000000000..e74e870747d --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@.gitignore.snap @@ -0,0 +1,8 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +*.beam +*.ez +/build +erl_crash.dump diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@README.md.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@README.md.snap new file mode 100644 index 00000000000..580acfa15cd --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@README.md.snap @@ -0,0 +1,28 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +# my_project + +[![Package Version](https://img.shields.io/hexpm/v/my_project)](https://hex.pm/packages/my_project) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/my_project/) + +```sh +gleam add my_project@1 +``` +```gleam +import my_project + +pub fn main() { + // TODO: An example of the project in use +} +``` + +Further documentation can be found at . + +## Development + +```sh +gleam run # Run the project +gleam test # Run the tests +``` diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@gleam.toml.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@gleam.toml.snap new file mode 100644 index 00000000000..9e43a7b996d --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_default_template@gleam.toml.snap @@ -0,0 +1,23 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +name = "my_project" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.34.0 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template.snap new file mode 100644 index 00000000000..af6ba63fb7e --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template.snap @@ -0,0 +1,24 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(path.join(\"gleam.toml\")).unwrap()" +--- +name = "my_project" +version = "1.0.0" +target = "javascript" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.34.0 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@.gitignore.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@.gitignore.snap new file mode 100644 index 00000000000..e74e870747d --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@.gitignore.snap @@ -0,0 +1,8 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +*.beam +*.ez +/build +erl_crash.dump diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@README.md.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@README.md.snap new file mode 100644 index 00000000000..580acfa15cd --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@README.md.snap @@ -0,0 +1,28 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +# my_project + +[![Package Version](https://img.shields.io/hexpm/v/my_project)](https://hex.pm/packages/my_project) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/my_project/) + +```sh +gleam add my_project@1 +``` +```gleam +import my_project + +pub fn main() { + // TODO: An example of the project in use +} +``` + +Further documentation can be found at . + +## Development + +```sh +gleam run # Run the project +gleam test # Run the tests +``` diff --git a/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@gleam.toml.snap b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@gleam.toml.snap new file mode 100644 index 00000000000..ab0f37de9ef --- /dev/null +++ b/compiler-cli/src/new/snapshots/gleam__new__tests__new_with_javascript_template@gleam.toml.snap @@ -0,0 +1,24 @@ +--- +source: compiler-cli/src/new/tests.rs +expression: "crate::fs::read(Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect(\"Non Utf8 Path\")).unwrap()" +--- +name = "my_project" +version = "1.0.0" +target = "javascript" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.34.0 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/compiler-cli/src/new/tests.rs b/compiler-cli/src/new/tests.rs index fbf97498f8a..1df4929257e 100644 --- a/compiler-cli/src/new/tests.rs +++ b/compiler-cli/src/new/tests.rs @@ -11,7 +11,7 @@ fn new() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: false, skip_github: false, @@ -33,6 +33,62 @@ fn new() { assert!(toml.contains("name = \"my_project\"")); } +#[test] +fn new_with_default_template() { + let tmp = tempfile::tempdir().unwrap(); + let path = Utf8PathBuf::from_path_buf(tmp.into_path()).expect("Non Utf8 Path"); + + let creator = super::Creator::new( + super::NewOptions { + project_root: path.join("my_project").to_string(), + template: super::Template::Erlang, + name: None, + skip_git: false, + skip_github: true, + }, + "1.0.0-gleam", + ) + .unwrap(); + creator.run().unwrap(); + + insta::glob!(path, "my_project/*.*", |file_path| { + if !file_path.is_dir() { + insta::assert_snapshot!(crate::fs::read( + Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), + ) + .unwrap()); + } + }); +} + +#[test] +fn new_with_javascript_template() { + let tmp = tempfile::tempdir().unwrap(); + let path = Utf8PathBuf::from_path_buf(tmp.into_path()).expect("Non Utf8 Path"); + + let creator = super::Creator::new( + super::NewOptions { + project_root: path.join("my_project").to_string(), + template: super::Template::JavaScript, + name: None, + skip_git: false, + skip_github: true, + }, + "1.0.0-gleam", + ) + .unwrap(); + creator.run().unwrap(); + + insta::glob!(path, "my_project/*.*", |file_path| { + if !file_path.is_dir() { + insta::assert_snapshot!(crate::fs::read( + Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), + ) + .unwrap()); + } + }); +} + #[test] fn new_with_skip_git() { let tmp = tempfile::tempdir().unwrap(); @@ -41,7 +97,7 @@ fn new_with_skip_git() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: false, @@ -62,7 +118,7 @@ fn new_with_skip_github() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: false, skip_github: true, @@ -86,7 +142,7 @@ fn new_with_skip_git_and_github() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: true, @@ -110,7 +166,7 @@ fn invalid_path() { assert!(super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: false, skip_github: false, @@ -128,7 +184,7 @@ fn invalid_name() { assert!(super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: Some("-".into()), skip_git: false, skip_github: false, @@ -148,7 +204,7 @@ fn existing_directory_no_files() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: true, @@ -175,7 +231,7 @@ fn existing_directory_with_one_existing_file() { assert!(super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: true, @@ -198,7 +254,7 @@ fn existing_directory_with_non_generated_file() { let creator = super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: true, @@ -228,7 +284,7 @@ fn conflict_with_existing_files() { super::Creator::new( super::NewOptions { project_root: path.to_string(), - template: super::Template::Lib, + template: super::Template::Erlang, name: None, skip_git: true, skip_github: true,