Merge pull request #9 from oovm/master

Replace StructOpt with Clap
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2022-02-13 13:05:48 -05:00
commit 97abba4e3b
17 files changed
+157 -128

No files matched your search

+1
View File
@@ -1,2 +1,3 @@
/target /target
Cargo.lock Cargo.lock
.idea/
+17 -14
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "dioxus-cli" name = "dioxus-cli"
version = "0.1.2" version = "0.1.3"
authors = ["Jonathan Kelley"] authors = ["Jonathan Kelley"]
edition = "2018" edition = "2018"
description = "CLI tool for developing, testing, and publishing Dioxus apps" description = "CLI tool for developing, testing, and publishing Dioxus apps"
@@ -9,31 +9,34 @@ license = "MIT/Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
thiserror = "1.0.23" # cli core
log = "0.4.13" clap = {version = "3.0.14", features = ["derive"]}
fern = { version = "0.6.0", features = ["colored"] } thiserror = "1.0.30"
wasm-bindgen-cli-support = "0.2.79" wasm-bindgen-cli-support = "0.2.79"
anyhow = "1.0.38" # features
serde = { version = "1.0.133", features = ["derive"] } log = "0.4.14"
serde_json = "1" fern = { version = "0.6.0", features = ["colored"] }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
toml = "0.5.8" toml = "0.5.8"
fs_extra = "1.2.0" fs_extra = "1.2.0"
cargo_toml = "0.10.0" cargo_toml = "0.11.4"
futures = "0.3.12" futures = "0.3.21"
notify = { version = "5.0.0-pre.13", features = ["serde"] } notify = { version = "5.0.0-pre.13", features = ["serde"] }
html_parser = "0.6.2" html_parser = "0.6.2"
binary-install = "0.0.2" binary-install = "0.0.2"
convert_case = "0.5.0" convert_case = "0.5.0"
structopt = "0.3.25"
cargo_metadata = "0.14.1" cargo_metadata = "0.14.1"
tokio = { version = "1.15.0", features = ["full"] } tokio = { version = "1.16.1", features = ["full"] }
atty = "0.2.14" atty = "0.2.14"
regex = "1.5.4" regex = "1.5.4"
chrono = "0.4.19" chrono = "0.4.19"
anyhow = "1.0.53"
hyper = "0.14.17"
axum = { version = "0.4.4", features = ["ws", "headers"] } axum = { version = "0.4.5", features = ["ws", "headers"] }
tower-http = { version = "0.2.0", features = ["fs", "trace"] } tower-http = { version = "0.2.2", features = ["fs", "trace"] }
headers = "0.3" headers = "0.3.7"
# hyper = { version = "0.14.11", features = ["full"] } # hyper = { version = "0.14.11", features = ["full"] }
[[bin]] [[bin]]
+6 -1
View File
@@ -15,8 +15,13 @@ dioxus-cli (inspired by wasm-pack and webpack) is a tool to help get dioxus proj
## Installation ## Installation
``` ```shell
# for stable
$ cargo install dioxus-cli $ cargo install dioxus-cli
# for latest
$ cargo install --git https://github.com/DioxusLabs/cli
# for developing
$ cargo install --path . --debug
``` ```
Now, `dioxus` is in your path. Now, `dioxus` is in your path.
+8
View File
@@ -0,0 +1,8 @@
version = "Two"
edition = "2018"
imports_granularity = "Crate"
#use_small_heuristics = "Max"
#control_brace_style = "ClosingNextLine"
normalize_comments = true
format_code_in_doc_comments = true
+5 -7
View File
@@ -11,13 +11,11 @@ use std::{
use wasm_bindgen_cli_support::Bindgen; use wasm_bindgen_cli_support::Bindgen;
pub fn build(config: &CrateConfig) -> Result<()> { pub fn build(config: &CrateConfig) -> Result<()> {
/* // [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
[1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?) // [2] Generate the appropriate build folders
[2] Generate the appropriate build folders // [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
[3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm // [4] Wasm-opt the .wasm file with whatever optimizations need to be done
[4] Wasm-opt the .wasm file with whatever optimizations need to be done // [5] Link up the html page to the wasm module
[5] Link up the html page to the wasm module
*/
let CrateConfig { let CrateConfig {
out_dir, out_dir,
+7 -10
View File
@@ -1,21 +1,18 @@
use std::{io::Write, path::PathBuf}; use super::*;
use crate::{cfg::ConfigOptsBuild, gen_page};
use structopt::StructOpt;
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, StructOpt)] #[derive(Clone, Debug, Parser)]
#[structopt(name = "build")] #[clap(name = "build")]
pub struct Build { pub struct Build {
#[structopt(flatten)] #[clap(flatten)]
pub build: ConfigOptsBuild, pub build: ConfigOptsBuild,
} }
impl Build { impl Build {
pub fn build(self) -> anyhow::Result<()> { pub fn build(self) -> Result<()> {
let mut crate_config = crate::CrateConfig::new()?; let mut crate_config = crate::CrateConfig::new()?;
// change the relase state. // change the release state.
crate_config.with_release(self.build.release); crate_config.with_release(self.build.release);
if self.build.example.is_some() { if self.build.example.is_some() {
@@ -30,7 +27,7 @@ impl Build {
crate::builder::build_desktop(&crate_config)?; crate::builder::build_desktop(&crate_config)?;
} }
_ => { _ => {
return Err(anyhow::anyhow!("Unsoppurt platform target.")); return custom_error!("Unsoppurt platform target.");
} }
} }
+11 -14
View File
@@ -1,46 +1,43 @@
use std::path::PathBuf; use super::*;
use structopt::StructOpt;
use serde::Deserialize;
/// Config options for the build system. /// Config options for the build system.
#[derive(Clone, Debug, Default, Deserialize, StructOpt)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
pub struct ConfigOptsBuild { pub struct ConfigOptsBuild {
/// The index HTML file to drive the bundling process [default: index.html] /// The index HTML file to drive the bundling process [default: index.html]
#[structopt(parse(from_os_str))] #[clap(parse(from_os_str))]
pub target: Option<PathBuf>, pub target: Option<PathBuf>,
/// Build in release mode [default: false] /// Build in release mode [default: false]
#[structopt(long)] #[clap(long)]
#[serde(default)] #[serde(default)]
pub release: bool, pub release: bool,
/// Build a example [default: ""] /// Build a example [default: ""]
#[structopt(long)] #[clap(long)]
pub example: Option<String>, pub example: Option<String>,
/// Build platform: support Web & Desktop [default: "web"] /// Build platform: support Web & Desktop [default: "web"]
#[structopt(long, default_value = "web")] #[clap(long, default_value = "web")]
pub platform: String, pub platform: String,
} }
#[derive(Clone, Debug, Default, Deserialize, StructOpt)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
pub struct ConfigOptsServe { pub struct ConfigOptsServe {
/// The index HTML file to drive the bundling process [default: index.html] /// The index HTML file to drive the bundling process [default: index.html]
#[structopt(parse(from_os_str))] #[clap(parse(from_os_str))]
pub target: Option<PathBuf>, pub target: Option<PathBuf>,
/// Build a example [default: ""] /// Build a example [default: ""]
#[structopt(long)] #[clap(long)]
pub example: Option<String>, pub example: Option<String>,
/// Build in release mode [default: false] /// Build in release mode [default: false]
#[structopt(long)] #[clap(long)]
#[serde(default)] #[serde(default)]
pub release: bool, pub release: bool,
/// Build platform: support Web & Desktop [default: "web"] /// Build platform: support Web & Desktop [default: "web"]
#[structopt(long, default_value = "web")] #[clap(long, default_value = "web")]
pub platform: String, pub platform: String,
} }
+4 -10
View File
@@ -1,18 +1,12 @@
use std::{ use super::*;
fs::remove_dir_all,
path::PathBuf,
process::{Command, Stdio},
};
use structopt::StructOpt;
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, StructOpt)] #[derive(Clone, Debug, Parser)]
#[structopt(name = "clean")] #[clap(name = "clean")]
pub struct Clean {} pub struct Clean {}
impl Clean { impl Clean {
pub fn clean(self) -> anyhow::Result<()> { pub fn clean(self) -> Result<()> {
let crate_config = crate::CrateConfig::new()?; let crate_config = crate::CrateConfig::new()?;
let output = Command::new("cargo") let output = Command::new("cargo")
+5 -8
View File
@@ -1,11 +1,8 @@
use std::{fs::File, io::Write}; use super::*;
use serde::Deserialize;
use structopt::StructOpt;
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, Deserialize, StructOpt)] #[derive(Clone, Debug, Deserialize, Subcommand)]
#[structopt(name = "config")] #[clap(name = "config")]
pub enum Config { pub enum Config {
/// Init `Dioxus.toml` for project/folder. /// Init `Dioxus.toml` for project/folder.
Init { Init {
@@ -13,14 +10,14 @@ pub enum Config {
name: String, name: String,
/// Cover old config /// Cover old config
#[structopt(long)] #[clap(long)]
#[serde(default)] #[serde(default)]
force: bool, force: bool,
}, },
} }
impl Config { impl Config {
pub fn config(self) -> anyhow::Result<()> { pub fn config(self) -> Result<()> {
let crate_root = crate::cargo::crate_root()?; let crate_root = crate::cargo::crate_root()?;
match self { match self {
Config::Init { name, force } => { Config::Init { name, force } => {
+9 -24
View File
@@ -1,26 +1,16 @@
use std::{ use super::*;
fs::File, use crate::custom_error;
io::{Read, Write},
path::PathBuf,
process::{Command, Stdio},
};
use regex::Regex;
use serde::Deserialize;
use structopt::StructOpt;
use crate::{error::Result, Error};
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, Default, Deserialize, StructOpt)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
#[structopt(name = "create")] #[clap(name = "create")]
pub struct Create { pub struct Create {
/// Init project name /// Init project name
#[structopt(default_value = ".")] #[clap(default_value = ".")]
name: String, name: String,
/// Template path /// Template path
#[structopt(default_value = "gh:dioxuslabs/dioxus-template", long)] #[clap(default_value = "gh:dioxuslabs/dioxus-template", long)]
template: String, template: String,
} }
@@ -34,10 +24,7 @@ impl Create {
let project_path = PathBuf::from(&self.name); let project_path = PathBuf::from(&self.name);
if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() { if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() {
return Err(Error::Other(anyhow::anyhow!( return custom_error!("🧨 Folder '{}' is initialized.", &self.name);
"🧨 Folder '{}' is initialized.",
&self.name
)));
} }
log::info!("🔧 Start to create a new project '{}'.", self.name); log::info!("🔧 Start to create a new project '{}'.", self.name);
@@ -58,9 +45,7 @@ impl Create {
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.output()?; .output()?;
if !install_output.status.success() { if !install_output.status.success() {
return Err(Error::Other(anyhow::anyhow!( return custom_error!("Try to install cargo-generate failed.");
"Try to install cargo-generate failed."
)));
} }
} }
@@ -74,7 +59,7 @@ impl Create {
.output()?; .output()?;
if !generate_output.status.success() { if !generate_output.status.success() {
return Err(Error::Other(anyhow::anyhow!("Generate project failed."))); return custom_error!("Generate project failed.");
} }
let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?; let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?;
+25 -11
View File
@@ -1,5 +1,3 @@
use structopt::StructOpt;
pub mod build; pub mod build;
pub mod cfg; pub mod cfg;
pub mod clean; pub mod clean;
@@ -8,26 +6,41 @@ pub mod create;
pub mod serve; pub mod serve;
pub mod translate; pub mod translate;
use crate::{
cfg::{ConfigOptsBuild, ConfigOptsServe},
custom_error,
error::Result,
gen_page, server, CrateConfig, Error,
};
use clap::{Parser, Subcommand};
use html_parser::{Dom, Element, Node};
use regex::Regex;
use serde::Deserialize;
use std::{
fmt::{Display, Formatter},
fs::{remove_dir_all, File},
io::{Read, Write},
path::PathBuf,
process::{exit, Command, Stdio},
};
/// Build, bundle, & ship your Dioxus app. /// Build, bundle, & ship your Dioxus app.
/// #[derive(Parser)]
/// #[clap(name = "dioxus")]
#[derive(StructOpt)]
#[structopt(name = "dioxus")]
pub struct Cli { pub struct Cli {
#[structopt(subcommand)] #[clap(subcommand)]
pub action: Commands, pub action: Commands,
/// Enable verbose logging. /// Enable verbose logging.
#[structopt(short)] #[clap(short)]
pub v: bool, pub v: bool,
//
// // note: dioxus is still roughly compatible with trunk // // note: dioxus is still roughly compatible with trunk
// /// Path to the Trunk config file [default: Trunk.toml] // /// Path to the Trunk config file [default: Trunk.toml]
// #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")] // #[clap(long, parse(from_os_str), env = "TRUNK_CONFIG")]
// pub config: Option<PathBuf>, // pub config: Option<PathBuf>,
} }
#[derive(StructOpt)] #[derive(Parser)]
pub enum Commands { pub enum Commands {
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
Build(build::Build), Build(build::Build),
@@ -40,5 +53,6 @@ pub enum Commands {
/// Clean output artifacts. /// Clean output artifacts.
Clean(clean::Clean), Clean(clean::Clean),
/// Dioxus config file controls. /// Dioxus config file controls.
#[clap(subcommand)]
Config(config::Config), Config(config::Config),
} }
+7 -9
View File
@@ -1,17 +1,15 @@
use crate::{cfg::ConfigOptsServe, gen_page, server, CrateConfig}; use super::*;
use std::{io::Write, path::PathBuf, process::{Command, Stdio}};
use structopt::StructOpt;
/// Run the WASM project on dev-server /// Run the WASM project on dev-server
#[derive(Clone, Debug, StructOpt)] #[derive(Clone, Debug, Parser)]
#[structopt(name = "serve")] #[clap(name = "serve")]
pub struct Serve { pub struct Serve {
#[structopt(flatten)] #[clap(flatten)]
pub serve: ConfigOptsServe, pub serve: ConfigOptsServe,
} }
impl Serve { impl Serve {
pub async fn serve(self) -> anyhow::Result<()> { pub async fn serve(self) -> Result<()> {
let mut crate_config = crate::CrateConfig::new()?; let mut crate_config = crate::CrateConfig::new()?;
// change the relase state. // change the relase state.
@@ -51,7 +49,7 @@ impl Serve {
return Ok(()); return Ok(());
} }
_ => { _ => {
return Err(anyhow::anyhow!("Unsoppurt platform target.")); return custom_error!("Unsoppurt platform target.");
} }
} }
@@ -64,7 +62,7 @@ impl Serve {
Ok(()) Ok(())
} }
pub fn regen_dev_page(crate_config: &CrateConfig) -> anyhow::Result<()> { pub fn regen_dev_page(crate_config: &CrateConfig) -> Result<()> {
let serve_html = gen_page(&crate_config.dioxus_config, true); let serve_html = gen_page(&crate_config.dioxus_config, true);
let mut file = std::fs::File::create( let mut file = std::fs::File::create(
+7 -16
View File
@@ -1,34 +1,25 @@
use anyhow::Result; use super::*;
use html_parser::Dom;
use html_parser::Element;
use html_parser::Node;
#[allow(unused_imports)]
use std::fmt::{Display, Formatter};
use std::io::Read;
use std::path::PathBuf;
use std::process::exit;
use structopt::StructOpt;
/// Build the Rust WASM app and all of its assets. /// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, StructOpt)] #[derive(Clone, Debug, Parser)]
#[structopt(name = "translate")] #[clap(name = "translate")]
pub struct Translate { pub struct Translate {
/// Activate debug mode /// Activate debug mode
// short and long flags (-d, --debug) will be deduced from the field's name // short and long flags (-d, --debug) will be deduced from the field's name
#[structopt(short, long)] #[clap(short, long)]
pub component: bool, pub component: bool,
/// Input file /// Input file
#[structopt(short, long)] #[clap(short, long)]
pub file: Option<String>, pub file: Option<String>,
/// Output file, stdout if not present /// Output file, stdout if not present
#[structopt(parse(from_os_str))] #[clap(parse(from_os_str))]
pub output: Option<PathBuf>, pub output: Option<PathBuf>,
} }
impl Translate { impl Translate {
pub fn translate(self) -> anyhow::Result<()> { pub fn translate(self) -> Result<()> {
let Translate { let Translate {
component, component,
output, output,
+37
View File
@@ -11,6 +11,15 @@ pub enum Error {
#[error("I/O Error: {0}")] #[error("I/O Error: {0}")]
IO(#[from] std::io::Error), IO(#[from] std::io::Error),
#[error("Format Error: {0}")]
FormatError(#[from] std::fmt::Error),
#[error("Format failed: {0}")]
ParseError(String),
#[error("Runtime Error: {0}")]
RuntimeError(String),
#[error("Failed to write error")] #[error("Failed to write error")]
FailedToWrite, FailedToWrite,
@@ -20,6 +29,9 @@ pub enum Error {
#[error("Failed to write error")] #[error("Failed to write error")]
CargoError(String), CargoError(String),
#[error("{0}")]
CustomError(String),
#[error(transparent)] #[error(transparent)]
Other(#[from] anyhow::Error), Other(#[from] anyhow::Error),
} }
@@ -35,3 +47,28 @@ impl From<String> for Error {
Error::Unique(s) Error::Unique(s)
} }
} }
impl From<html_parser::Error> for Error {
fn from(e: html_parser::Error) -> Self {
Self::ParseError(e.to_string())
}
}
impl From<hyper::Error> for Error {
fn from(e: hyper::Error) -> Self {
Self::RuntimeError(e.to_string())
}
}
#[macro_export]
macro_rules! custom_error {
($msg:literal $(,)?) => {
Err(Error::CustomError($msg.to_string()))
};
($err:expr $(,)?) => {
Err(Error::from($err))
};
($fmt:expr, $($arg:tt)*) => {
Err(Error::CustomError(format!($fmt, $($arg)*)))
};
}
+2 -2
View File
@@ -1,9 +1,9 @@
use clap::Parser;
use dioxus_cli::*; use dioxus_cli::*;
use structopt::StructOpt;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let args = Cli::from_args(); let args = Cli::parse();
set_up_logging(); set_up_logging();
match args.action { match args.action {
+2 -2
View File
@@ -10,14 +10,14 @@ use notify::{RecommendedWatcher, Watcher};
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
use crate::{builder, serve::Serve, CrateConfig}; use crate::{builder, serve::Serve, CrateConfig, Result};
use tokio::sync::broadcast; use tokio::sync::broadcast;
struct WsRelodState { struct WsRelodState {
update: broadcast::Sender<String>, update: broadcast::Sender<String>,
} }
pub async fn startup(config: CrateConfig) -> anyhow::Result<()> { pub async fn startup(config: CrateConfig) -> Result<()> {
log::info!("🚀 Starting development server..."); log::info!("🚀 Starting development server...");
let dist_path = config.out_dir.clone(); let dist_path = config.out_dir.clone();
+4
View File
@@ -0,0 +1,4 @@
#[test]
fn ready() {
println!("Compiled successfully!")
}