Forráskód Böngészése

feat: init use `cargo-generate `

mrxiaozhuox 3 éve
szülő
commit
bdcc06648b
8 módosított fájl, 74 hozzáadás és 103 törlés
  1. 2 1
      Cargo.toml
  2. 1 1
      Dioxus.toml
  3. 4 0
      src/cli/build/mod.rs
  4. 8 0
      src/cli/cfg.rs
  5. 54 43
      src/cli/init/mod.rs
  6. 5 0
      src/cli/serve/mod.rs
  7. 0 42
      src/template/config.toml
  8. 0 16
      src/template/default.rs

+ 2 - 1
Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "dioxus-cli"
-version = "0.1.1"
+version = "0.1.2"
 authors = ["Jonathan Kelley"]
 edition = "2018"
 description = "CLI tool for developing, testing, and publishing Dioxus apps"
@@ -28,6 +28,7 @@ structopt = "0.3.25"
 cargo_metadata = "0.14.1"
 tokio = { version = "1.15.0", features = ["full"] }
 atty = "0.2.14"
+regex = "1.5.4"
 
 axum = { version = "0.4.4", features = ["ws", "headers"] }
 tower-http = { version = "0.2.0", features = ["fs", "trace"] }

+ 1 - 1
Dioxus.toml

@@ -13,7 +13,7 @@ platforms = ["web"]
 out_dir = "dist"
 
 # resource (static) file folder
-static_dir = "static"
+public_dir = "public"
 
 [web.watcher]
 

+ 4 - 0
src/cli/build/mod.rs

@@ -18,6 +18,10 @@ impl Build {
         // change the relase state.
         crate_config.with_release(self.build.release);
 
+        if self.build.example.is_some() {
+            crate_config.as_example(self.build.example.unwrap());
+        }
+
         crate::builder::build(&crate_config)?;
 
         let temp = gen_page(&crate_config.dioxus_config, false);

+ 8 - 0
src/cli/cfg.rs

@@ -16,6 +16,10 @@ pub struct ConfigOptsBuild {
     #[serde(default)]
     pub release: bool,
 
+    /// Build a example [default: ""]
+    #[structopt(long)]
+    pub example: Option<String>,
+
     /// Optional pattern for the app loader script [default: None]
     ///
     /// Patterns should include the sequences `{base}`, `{wasm}`, and `{js}` in order to
@@ -62,6 +66,10 @@ pub struct ConfigOptsServe {
     #[structopt(parse(from_os_str))]
     pub target: Option<PathBuf>,
 
+    /// Build a example [default: ""]
+    #[structopt(long)]
+    pub example: Option<String>,
+
     /// Build in release mode [default: false]
     #[structopt(long)]
     #[serde(default)]

+ 54 - 43
src/cli/init/mod.rs

@@ -1,16 +1,18 @@
 use std::{
-    fs::{File, OpenOptions},
-    io::Write,
+    fs::File,
+    io::{Read, Write},
     path::PathBuf,
     process::{Command, Stdio},
 };
 
+use regex::Regex;
+use serde::Deserialize;
 use structopt::StructOpt;
 
-use crate::error::{Error, Result};
+use crate::{error::Result, Error};
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, StructOpt)]
+#[derive(Clone, Debug, Default, Deserialize, StructOpt)]
 #[structopt(name = "init")]
 pub struct Init {
     /// Init project name
@@ -18,69 +20,73 @@ pub struct Init {
     name: String,
 
     /// Template path
-    #[structopt(default_value = "default", long)]
+    #[structopt(default_value = "gh:dioxuslabs/dioxus-template", long)]
     template: String,
+
+    /// Create a `lib` project, include a `hello-world` example.
+    #[structopt(long)]
+    #[serde(default)]
+    pub lib: bool,
 }
 
 impl Init {
     pub fn init(self) -> Result<()> {
-        if self.name.contains(".") {
+        if Self::name_vaild_check(self.name.clone()) {
             log::error!("❗Unsupported project name.");
             return Ok(());
         }
 
-        log::info!("🔧 Start to init a new project '{}'.", self.name);
-
         let project_path = PathBuf::from(&self.name);
 
-        if project_path.join("Cargo.toml").is_file() {
-            log::warn!("Folder '{}' is initialized.", self.name);
-            return Ok(());
+        if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() {
+            return Err(Error::Other(anyhow::anyhow!(
+                "🧨 Folder '{}' is initialized.",
+                &self.name
+            )));
         }
 
+        log::info!("🔧 Start to init a new project '{}'.", self.name);
+
         let output = Command::new("cargo")
-            .arg("init")
-            .arg(&format!("./{}", self.name))
-            .arg("--bin")
+            .arg("generate")
+            .arg("--help")
             .stdout(Stdio::piped())
             .stderr(Stdio::piped())
             .output()?;
 
         if !output.status.success() {
-            return Err(Error::CargoError("Cargo init failed".into()));
+            log::warn!("Tool is not installed: cargo-generate, try to install it.");
+            let install_output = Command::new("cargo")
+                .arg("install")
+                .arg("cargo-generate")
+                .stdout(Stdio::inherit())
+                .stderr(Stdio::inherit())
+                .output()?;
+            if !install_output.status.success() {
+                return Err(Error::Other(anyhow::anyhow!(
+                    "Try to install cargo-generate failed."
+                )));
+            }
         }
 
-        // get the template code
-        let template_str = match self.template {
-            _ => include_str!("../../template/default.rs"),
-        };
+        let generate_output = Command::new("cargo")
+            .arg("generate")
+            .arg(&self.template)
+            .arg("--name")
+            .arg(&self.name)
+            .stdout(Stdio::piped())
+            .stderr(Stdio::inherit())
+            .output()?;
 
-        let main_rs_file = project_path.join("src").join("main.rs");
-        if !main_rs_file.is_file() {
-            return Err(Error::FailedToWrite);
+        if !generate_output.status.success() {
+            return Err(Error::Other(anyhow::anyhow!("Generate project failed.")));
         }
 
-        let mut file = File::create(main_rs_file)?;
-        file.write_all(&template_str.as_bytes())?;
-
-        let mut file = File::create(project_path.join("Dioxus.toml"))?;
-        let dioxus_conf = String::from(include_str!("../../template/config.toml"))
-            .replace("{project-name}", &self.name);
-        file.write_all(dioxus_conf.as_bytes())?;
-
-        // log::info!("🎯 Project initialization completed.");
-
-        if !Command::new("cargo")
-            .args(["add", "dioxus", "--features web"])
-            .output()?
-            .status
-            .success()
-        {
-            let mut file = OpenOptions::new()
-                .append(true)
-                .open(project_path.join("Cargo.toml"))?;
-            file.write_all("dioxus = { version = \"0.1.7\", features = [\"web\"] }".as_bytes())?;
-        }
+        let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?;
+        let mut meta_file = String::new();
+        dioxus_file.read_to_string(&mut meta_file)?;
+        meta_file = meta_file.replace("{{project-name}}", &self.name);
+        File::create(project_path.join("Dioxus.toml"))?.write_all(meta_file.as_bytes())?;
 
         println!("");
         log::info!("💡 Project initialized:");
@@ -89,4 +95,9 @@ impl Init {
 
         Ok(())
     }
+
+    fn name_vaild_check(name: String) -> bool {
+        let r = Regex::new(r"^[a-zA-Z][a-zA-Z0-9\-_]$").unwrap();
+        r.is_match(&name)
+    }
 }

+ 5 - 0
src/cli/serve/mod.rs

@@ -13,9 +13,14 @@ pub struct Serve {
 impl Serve {
     pub async fn serve(self) -> anyhow::Result<()> {
         let mut crate_config = crate::CrateConfig::new()?;
+
         // change the relase state.
         crate_config.with_release(self.serve.release);
 
+        if self.serve.example.is_some() {
+            crate_config.as_example(self.serve.example.unwrap());
+        }
+
         crate::builder::build(&crate_config).expect("build failed");
 
         // generate dev-index page

+ 0 - 42
src/template/config.toml

@@ -1,42 +0,0 @@
-[application]
-
-# App (Project) Name
-name = "{project-name}"
-
-# Dioxus App Support Platform
-# desktop, web, mobile, ssr
-platforms = ["web"]
-
-[web.app]
-
-# HTML title tag content
-title = "dioxus | ⛺"
-
-# Web `build` & `serve` dist path
-out_dir = "dist"
-
-# resource (public) file folder
-public_dir = "public"
-
-[web.watcher]
-
-# when watcher trigger, regenerate the `index.html`
-reload_html = true
-
-# which files or dirs will be watcher monitoring
-watch_path = ["src"]
-
-# include `assets` in web platform
-[web.resource]
-
-# CSS style file
-style = []
-
-# Javascript code file
-script = []
-
-[web.resource.dev]
-
-# Javascript code file
-# serve: [dev-server] only
-script = []

+ 0 - 16
src/template/default.rs

@@ -1,16 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus::web::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! (
-        div {
-            style: "text-align: center;",
-            h1 { "🌗 Dioxus 🚀" }
-            h3 { "Frontend that scales." }
-            p { "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust." }
-        }
-    ))
-}