Răsfoiți Sursa

chore: use rosetta

Jonathan Kelley 2 ani în urmă
părinte
comite
479ee2a0f1

+ 28 - 24
Cargo.lock

@@ -438,16 +438,15 @@ dependencies = [
 
 [[package]]
 name = "console"
-version = "0.15.2"
+version = "0.15.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"
+checksum = "5556015fe3aad8b968e5d4124980fbe2f6aaee7aeec6b749de1faaa2ca5d0a4c"
 dependencies = [
  "encode_unicode",
  "lazy_static",
  "libc",
- "terminal_size",
  "unicode-width",
- "winapi",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -663,7 +662,7 @@ dependencies = [
 [[package]]
 name = "dioxus-autofmt"
 version = "0.0.0"
-source = "git+https://github.com/dioxuslabs/dioxus#641488e825d861a14670ba7a15a535e76d3cee7a"
+source = "git+https://github.com/dioxuslabs/dioxus#04ca284704b3aa7e18cf7b4f2e573e25df3d47eb"
 dependencies = [
  "dioxus-rsx",
  "prettyplease",
@@ -709,6 +708,7 @@ dependencies = [
  "proc-macro2",
  "regex",
  "reqwest",
+ "rsx-rosetta",
  "serde",
  "serde_json",
  "syn",
@@ -726,7 +726,7 @@ dependencies = [
 [[package]]
 name = "dioxus-core"
 version = "0.2.1"
-source = "git+https://github.com/dioxuslabs/dioxus#641488e825d861a14670ba7a15a535e76d3cee7a"
+source = "git+https://github.com/dioxuslabs/dioxus#04ca284704b3aa7e18cf7b4f2e573e25df3d47eb"
 dependencies = [
  "bumpalo",
  "futures-channel",
@@ -743,7 +743,7 @@ dependencies = [
 [[package]]
 name = "dioxus-html"
 version = "0.2.1"
-source = "git+https://github.com/dioxuslabs/dioxus#641488e825d861a14670ba7a15a535e76d3cee7a"
+source = "git+https://github.com/dioxuslabs/dioxus#04ca284704b3aa7e18cf7b4f2e573e25df3d47eb"
 dependencies = [
  "async-trait",
  "dioxus-core",
@@ -759,7 +759,7 @@ dependencies = [
 [[package]]
 name = "dioxus-rsx"
 version = "0.0.1"
-source = "git+https://github.com/dioxuslabs/dioxus#641488e825d861a14670ba7a15a535e76d3cee7a"
+source = "git+https://github.com/dioxuslabs/dioxus#04ca284704b3aa7e18cf7b4f2e573e25df3d47eb"
 dependencies = [
  "dioxus-core",
  "internment",
@@ -2018,9 +2018,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.18"
+version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81bdd679d533107e090c2704a35982fc06302e30898e63ffa26a81155c012e92"
+checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b"
 
 [[package]]
 name = "ppv-lite86"
@@ -2247,6 +2247,20 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "rsx-rosetta"
+version = "0.0.0"
+source = "git+https://github.com/dioxuslabs/dioxus#04ca284704b3aa7e18cf7b4f2e573e25df3d47eb"
+dependencies = [
+ "convert_case",
+ "dioxus-autofmt",
+ "dioxus-rsx",
+ "html_parser",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "rust-argon2"
 version = "0.8.3"
@@ -2379,9 +2393,9 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.151"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
 dependencies = [
  "serde_derive",
 ]
@@ -2398,9 +2412,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.151"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2607,16 +2621,6 @@ dependencies = [
  "winapi-util",
 ]
 
-[[package]]
-name = "terminal_size"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
-dependencies = [
- "libc",
- "winapi",
-]
-
 [[package]]
 name = "textwrap"
 version = "0.16.0"

+ 1 - 0
Cargo.toml

@@ -81,6 +81,7 @@ dioxus-core = { git = "https://github.com/DioxusLabs/dioxus", features = [
     "serialize",
 ] }
 dioxus-autofmt = { git = "https://github.com/dioxuslabs/dioxus" }
+rsx-rosetta = { git = "https://github.com/dioxuslabs/dioxus" }
 
 [[bin]]
 path = "src/main.rs"

+ 3 - 3
src/builder.rs

@@ -385,9 +385,9 @@ fn prettier_build(mut cmd: Command) -> anyhow::Result<Vec<Diagnostic>> {
                 let message = msg.message;
                 match message.level {
                     cargo_metadata::diagnostic::DiagnosticLevel::Error => {
-                        return Err(anyhow::anyhow!(message
-                            .rendered
-                            .unwrap_or("Unknown".into())));
+                        return Err(anyhow::anyhow!(
+                            message.rendered.unwrap_or("Unknown".into())
+                        ));
                     }
                     cargo_metadata::diagnostic::DiagnosticLevel::Warning => {
                         warning_messages.push(message.clone());

+ 1 - 2
src/cli/mod.rs

@@ -16,11 +16,10 @@ use crate::{
     gen_page, server, CrateConfig, Error,
 };
 use clap::{Parser, Subcommand};
-use html_parser::{Dom, Element, Node};
+use html_parser::Dom;
 use regex::Regex;
 use serde::Deserialize;
 use std::{
-    fmt::{Display, Formatter},
     fs::{remove_dir_all, File},
     io::{Read, Write},
     path::PathBuf,

+ 70 - 246
src/cli/translate/mod.rs

@@ -1,5 +1,9 @@
 use std::process::exit;
 
+use dioxus_rsx::{BodyNode, CallBody, Component};
+use proc_macro2::{Ident, Span};
+use syn::punctuated::Punctuated;
+
 use super::*;
 
 /// Build the Rust WASM app and all of its assets.
@@ -26,291 +30,111 @@ pub struct Translate {
 
 impl Translate {
     pub fn translate(self) -> Result<()> {
-        let Translate {
-            component,
-            output,
-            file,
-            raw,
-        } = self;
-
-        let contents = match (file, raw) {
-            (Some(input), None) => std::fs::read_to_string(&input).unwrap_or_else(|e| {
-                log::error!("Cloud not read input file: {}.", e);
-                exit(0);
-            }),
-            (None, Some(raw)) => raw,
-            (Some(_), Some(_)) => {
-                log::error!("Only one of --file or --raw can be specified.");
-                exit(0);
-            }
-            (None, None) => {
-                if atty::is(atty::Stream::Stdin) {
-                    return custom_error!("No input file, source, or stdin to translate from.");
-                }
-
-                let mut buffer = String::new();
-                std::io::stdin().read_to_string(&mut buffer).unwrap();
+        // Get the right input for the translation
+        let contents = determine_input(self.file, self.raw)?;
 
-                buffer.trim().to_string()
-            }
-        };
+        // Ensure we're loading valid HTML
+        let dom = html_parser::Dom::parse(&contents)?;
 
-        let out_buf = match component {
-            true => format!("{}", convert_html_to_component(&contents).unwrap()),
-            false => {
-                let mut buf = String::new();
-                let dom = Dom::parse(&contents).unwrap();
-                for child in &dom.children {
-                    simple_render_child(&mut buf, child, 0)?;
-                }
-                buf
-            }
-        };
+        // Convert the HTML to RSX
+        let out = convert_html_to_formatted_rsx(&dom, self.component);
 
-        if let Some(output) = output {
-            std::fs::write(&output, out_buf)?;
-        } else {
-            print!("{}", out_buf);
+        // Write the output
+        match self.output {
+            Some(output) => std::fs::write(&output, out)?,
+            None => print!("{}", out),
         }
 
         Ok(())
     }
 }
 
-/// render without handling svgs or anything
-pub fn simple_render_child(
-    f: &mut impl std::fmt::Write,
-    child: &Node,
-    il: u32,
-) -> std::fmt::Result {
-    write_tabs(f, il)?;
-    match child {
-        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
-        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
-        Node::Element(el) => {
-            // open the tag
-            write!(f, "{} {{ ", &el.name)?;
-
-            // todo: dioxus will eventually support classnames
-            // for now, just write them with a space between each
-            let class_iter = &mut el.classes.iter();
-            if let Some(first_class) = class_iter.next() {
-                write!(f, "class: \"{}", first_class)?;
-                for next_class in class_iter {
-                    write!(f, " {}", next_class)?;
-                }
-                write!(f, "\",")?;
-            }
-            writeln!(f)?;
-
-            // write the attributes
-            if let Some(id) = &el.id {
-                write_tabs(f, il + 1)?;
-                writeln!(f, "id: \"{}\",", id)?;
-            }
-
-            for (name, value) in &el.attributes {
-                write_tabs(f, il + 1)?;
-
-                use convert_case::{Case, Casing};
-                if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
-                    let new_name = name.to_case(Case::Snake);
-                    match value {
-                        Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
-                        None => writeln!(f, "{}: \"\",", new_name)?,
-                    }
-                } else {
-                    if matches!(name.as_str(), "for" | "async" | "type" | "as") {
-                        write!(f, "r#")?
-                    }
-
-                    match value {
-                        Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
-                        None => writeln!(f, "{}: \"\",", name)?,
-                    }
-                }
-            }
-
-            // now the children
-            for child in &el.children {
-                simple_render_child(f, child, il + 1)?;
-            }
+pub fn convert_html_to_formatted_rsx(dom: &Dom, component: bool) -> String {
+    let callbody = rsx_rosetta::rsx_from_html(&dom);
 
-            // close the tag
-            write_tabs(f, il)?;
-            writeln!(f, "}}")?;
-        }
-    };
-    Ok(())
-}
-
-pub fn convert_html_to_component(html: &str) -> Result<ComponentRenderer> {
-    Ok(ComponentRenderer {
-        dom: Dom::parse(html)?,
-        icon_index: 0,
-    })
-}
-
-#[allow(dead_code)]
-pub struct ComponentRenderer {
-    dom: Dom,
-    icon_index: usize,
+    match component {
+        true => write_callbody_with_icon_section(callbody),
+        false => dioxus_autofmt::write_block_out(callbody).unwrap(),
+    }
 }
 
-impl Display for ComponentRenderer {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        writeln!(
-            f,
-            r##"
-fn component(cx: Scope) -> Element {{
-    cx.render(rsx!("##
-        )?;
-        let mut svg_nodes = vec![];
+fn write_callbody_with_icon_section(mut callbody: CallBody) -> String {
+    let mut svgs = vec![];
 
-        let mut svg_idx = 0;
-        for child in &self.dom.children {
-            render_child(f, child, 2, &mut svg_nodes, true, &mut svg_idx)?;
-        }
-        write!(
-            f,
-            r##"    ))
-}}"##
-        )?;
+    rsx_rosetta::collect_svgs(&mut callbody.roots, &mut svgs);
 
-        if svg_idx == 0 {
-            return Ok(());
-        }
+    let mut out = write_component_body(dioxus_autofmt::write_block_out(callbody).unwrap());
 
-        writeln!(f, "\n\nmod icons {{")?;
-        writeln!(f, "\tuse super::*;")?;
-
-        let mut id = 0;
-        while let Some(svg) = svg_nodes.pop() {
-            writeln!(
-                f,
-                r##"    pub(super) fn icon_{}(cx: Scope) -> Element {{
-        cx.render(rsx!("##,
-                id
-            )?;
-            write_tabs(f, 3)?;
-
-            render_element(f, svg, 3, &mut svg_nodes, false, &mut 0)?;
-
-            writeln!(f, "\t\t))\n\t}}")?;
-            id += 1;
-        }
-
-        writeln!(f, "}}")?;
-
-        Ok(())
+    if !svgs.is_empty() {
+        write_svg_section(&mut out, svgs);
     }
+
+    out
 }
 
-fn render_child<'a>(
-    f: &mut Formatter<'_>,
-    child: &'a Node,
-    il: u32,
-    svg_buffer: &mut Vec<&'a Element>,
-    skip_svg: bool,
-    svg_idx: &mut usize,
-) -> std::fmt::Result {
-    write_tabs(f, il)?;
-    match child {
-        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
-        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
-        Node::Element(el) => render_element(f, el, il, svg_buffer, skip_svg, svg_idx)?,
-    };
-    Ok(())
+fn write_component_body(raw: String) -> String {
+    let mut out = String::from("fn component(cx: Scope) -> Element {\n    cx.render(rsx! {");
+    indent_and_write(&raw, 1, &mut out);
+    out.push_str("    })\n}");
+    out
 }
 
-fn render_element<'a>(
-    f: &mut Formatter<'_>,
-    el: &'a Element,
-    il: u32,
-    svg_buffer: &mut Vec<&'a Element>,
-    skip_svg: bool,
-    svg_idx: &mut usize,
-) -> std::fmt::Result {
-    if el.name == "svg" && skip_svg {
-        svg_buffer.push(el);
-        // todo: attach the right icon ID
-        writeln!(f, "icons::icon_{} {{}}", svg_idx)?;
-        *svg_idx += 1;
-        return Ok(());
+fn write_svg_section(out: &mut String, svgs: Vec<BodyNode>) {
+    out.push_str("\n\nmod icons {");
+    out.push_str("\n    use super::*;");
+    for (idx, icon) in svgs.into_iter().enumerate() {
+        let raw = dioxus_autofmt::write_block_out(CallBody { roots: vec![icon] }).unwrap();
+        out.push_str("\n\n    pub fn icon_");
+        out.push_str(&idx.to_string());
+        out.push_str("(cx: Scope) -> Element {\n        cx.render(rsx! {");
+        indent_and_write(&raw, 2, out);
+        out.push_str("        })\n    }");
     }
 
-    // open the tag
-    write!(f, "{} {{ ", &el.name)?;
+    out.push_str("\n}");
+}
 
-    // todo: dioxus will eventually support classnames
-    // for now, just write them with a space between each
-    let class_iter = &mut el.classes.iter();
-    if let Some(first_class) = class_iter.next() {
-        write!(f, "class: \"{}", first_class)?;
-        for next_class in class_iter {
-            write!(f, " {}", next_class)?;
+fn indent_and_write(raw: &str, idx: usize, out: &mut String) {
+    for line in raw.lines() {
+        for _ in 0..idx {
+            out.push_str("    ");
         }
-        write!(f, "\",")?;
+        out.push_str(line);
+        out.push('\n');
     }
-    writeln!(f)?;
+}
 
-    // write the attributes
-    if let Some(id) = &el.id {
-        write_tabs(f, il + 1)?;
-        writeln!(f, "id: \"{}\",", id)?;
+fn determine_input(file: Option<String>, raw: Option<String>) -> Result<String> {
+    // Make sure not both are specified
+    if file.is_some() && raw.is_some() {
+        log::error!("Only one of --file or --raw should be specified.");
+        exit(0);
     }
 
-    for (name, value) in &el.attributes {
-        write_tabs(f, il + 1)?;
-
-        use convert_case::{Case, Casing};
-        if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
-            let new_name = name.to_case(Case::Snake);
-            match value {
-                Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
-                None => writeln!(f, "{}: \"\",", new_name)?,
-            }
-        } else {
-            if matches!(name.as_str(), "for" | "async" | "type" | "as") {
-                write!(f, "r#")?
-            }
+    if let Some(raw) = raw {
+        return Ok(raw);
+    }
 
-            match value {
-                Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
-                None => writeln!(f, "{}: \"\",", name)?,
-            }
-        }
+    if let Some(file) = file {
+        return Ok(std::fs::read_to_string(&file)?);
     }
 
-    // now the children
-    for child in &el.children {
-        render_child(f, child, il + 1, svg_buffer, skip_svg, svg_idx)?;
+    // If neither exist, we try to read from stdin
+    if atty::is(atty::Stream::Stdin) {
+        return custom_error!("No input file, source, or stdin to translate from.");
     }
 
-    // close the tag
-    write_tabs(f, il)?;
-    writeln!(f, "}}")?;
-    Ok(())
-}
+    let mut buffer = String::new();
+    std::io::stdin().read_to_string(&mut buffer).unwrap();
 
-fn write_tabs(f: &mut impl std::fmt::Write, num: u32) -> std::fmt::Result {
-    for _ in 0..num {
-        write!(f, "    ")?
-    }
-    Ok(())
+    Ok(buffer.trim().to_string())
 }
 
 #[test]
 fn generates_svgs() {
-    use std::io::Write;
-
     let st = include_str!("../../../tests/svg.html");
 
-    let out = format!("{:}", convert_html_to_component(st).unwrap());
-    dbg!(&out);
+    let out = convert_html_to_formatted_rsx(&html_parser::Dom::parse(st).unwrap(), true);
 
-    std::fs::File::create("svg_rsx.rs")
-        .unwrap()
-        .write_all(out.as_bytes())
-        .unwrap();
+    println!("{}", out);
 }

+ 24 - 12
src/config.rs

@@ -1,10 +1,11 @@
 use crate::error::Result;
 use serde::{Deserialize, Serialize};
-use std::{collections::HashMap, fs::File, io::Read, path::PathBuf};
+use std::{collections::HashMap, path::PathBuf};
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct DioxusConfig {
     pub application: ApplicationConfig,
+
     pub web: WebConfig,
 
     #[serde(default = "default_plugin")]
@@ -16,21 +17,32 @@ fn default_plugin() -> toml::Value {
 }
 
 impl DioxusConfig {
-    pub fn load() -> crate::error::Result<DioxusConfig> {
+    pub fn load() -> crate::error::Result<Option<DioxusConfig>> {
         let crate_dir = crate::cargo::crate_root()?;
 
-        if !crate_dir.join("Dioxus.toml").is_file() {
-            log::warn!("Config file: `Dioxus.toml` not found; using default config.");
-            return Ok(DioxusConfig::default());
-        }
+        // we support either `Dioxus.toml` or `Cargo.toml`
+        let Some(dioxus_conf_file) = acquire_dioxus_toml(crate_dir) else {
+            return Ok(None);
+        };
+
+        toml::from_str::<DioxusConfig>(&std::fs::read_to_string(dioxus_conf_file)?)
+            .map_err(|_| crate::Error::Unique("Dioxus.toml parse failed".into()))
+            .map(Some)
+    }
+}
 
-        let mut dioxus_conf_file = File::open(crate_dir.join("Dioxus.toml"))?;
-        let mut meta_str = String::new();
-        dioxus_conf_file.read_to_string(&mut meta_str)?;
+fn acquire_dioxus_toml(dir: PathBuf) -> Option<PathBuf> {
+    // prefer uppercase
+    if dir.join("Dioxus.toml").is_file() {
+        return Some(dir.join("Dioxus.toml"));
+    }
 
-        toml::from_str::<DioxusConfig>(&meta_str)
-        .map_err(|_| crate::Error::Unique("Dioxus.toml parse failed".into()))
+    // lowercase is fine too
+    if dir.join("dioxus.toml").is_file() {
+        return Some(dir.join("Dioxus.toml"));
     }
+
+    None
 }
 
 impl Default for DioxusConfig {
@@ -141,7 +153,7 @@ pub enum ExecutableType {
 
 impl CrateConfig {
     pub fn new() -> Result<Self> {
-        let dioxus_config = DioxusConfig::load()?;
+        let dioxus_config = DioxusConfig::load()?.unwrap_or_default();
 
         let crate_dir = if let Some(package) = &dioxus_config.application.sub_package {
             crate::cargo::crate_root()?.join(package)

+ 41 - 58
src/main.rs

@@ -1,81 +1,64 @@
+use anyhow::anyhow;
 use clap::Parser;
 use dioxus_cli::{plugin::PluginManager, *};
-use std::process::exit;
+use Commands::*;
 
 #[tokio::main]
-async fn main() -> Result<()> {
+async fn main() -> anyhow::Result<()> {
     let args = Cli::parse();
-    set_up_logging();
 
-    let dioxus_config = DioxusConfig::load().unwrap_or(DioxusConfig::default());
+    set_up_logging();
 
-    let plugin_state = PluginManager::init(dioxus_config.plugin);
+    let dioxus_config = DioxusConfig::load()
+        .map_err(|e| anyhow!("Failed to load `dioxus.toml` because: {e}"))?
+        .unwrap_or_else(|| {
+            log::warn!("Your `dioxus.toml` could not be found. Using the default config. To set up this crate with dioxus, use `dioxus init`.");
+            DioxusConfig::default()
+        });
 
-    if let Err(e) = plugin_state {
-        log::error!("🚫 Plugin system initialization failed: {e}");
-        exit(1);
-    }
+    PluginManager::init(dioxus_config.plugin)
+        .map_err(|e| anyhow!("🚫 Plugin system initialization failed: {e}"))?;
 
     match args.action {
-        Commands::Translate(opts) => {
-            if let Err(e) = opts.translate() {
-                log::error!("🚫 Translate failed: {}", e);
-                exit(1);
-            }
-        }
+        Translate(opts) => opts
+            .translate()
+            .map_err(|e| anyhow!("🚫 Translation of HTML into RSX failed: {}", e)),
 
-        Commands::Build(opts) => {
-            if let Err(e) = opts.build() {
-                log::error!("🚫 Build project failed: {}", e);
-                exit(1);
-            }
-        }
+        Build(opts) => opts
+            .build()
+            .map_err(|e| anyhow!("🚫 Building project failed: {}", e)),
 
-        Commands::Clean(opts) => {
-            if let Err(e) = opts.clean() {
-                log::error!("🚫 Clean project failed: {}", e);
-                exit(1);
-            }
-        }
+        Clean(opts) => opts
+            .clean()
+            .map_err(|e| anyhow!("🚫 Cleaning project failed: {}", e)),
 
-        Commands::Serve(opts) => {
-            if let Err(e) = opts.serve().await {
-                log::error!("🚫 Serve startup failed: {}", e);
-                exit(1);
-            }
-        }
+        Serve(opts) => opts
+            .serve()
+            .await
+            .map_err(|e| anyhow!("🚫 Serving project failed: {}", e)),
 
-        Commands::Create(opts) => {
-            if let Err(e) = opts.create() {
-                log::error!("🚫 Create project failed: {}", e);
-                exit(1);
-            }
-        }
+        Create(opts) => opts
+            .create()
+            .map_err(|e| anyhow!("🚫 Creating new project failed: {}", e)),
 
-        Commands::Config(opts) => {
-            if let Err(e) = opts.config() {
-                log::error!("config error: {}", e);
-                exit(1);
-            }
-        }
+        Config(opts) => opts
+            .config()
+            .map_err(|e| anyhow!("🚫 Configuring new project failed: {}", e)),
 
-        Commands::Plugin(opts) => {
-            if let Err(e) = opts.plugin().await {
-                log::error!("tool error: {}", e);
-            }
-        }
+        Plugin(opts) => opts
+            .plugin()
+            .await
+            .map_err(|e| anyhow!("🚫 Error with plugin: {}", e)),
 
-        Commands::Autoformat(opts) => {
-            if let Err(e) = opts.autoformat() {
-                log::error!("format error: {}", e);
-            }
-        }
+        Autoformat(opts) => opts
+            .autoformat()
+            .map_err(|e| anyhow!("🚫 Error autoformatting RSX: {}", e)),
 
-        Commands::Version(opt) => {
+        Version(opt) => {
             let version = opt.version();
             println!("{}", version);
+
+            Ok(())
         }
     }
-
-    Ok(())
 }

+ 0 - 1
src/plugin/interface/command.rs

@@ -37,7 +37,6 @@ impl UserData for PluginCommander {
         methods.add_function(
             "exec",
             |_, args: (Vec<String>, StdioFromString, StdioFromString)| {
-                
                 let cmd = args.0;
                 let stdout = args.1;
                 let stderr = args.2;

+ 1 - 1
src/plugin/interface/dirs.rs

@@ -10,4 +10,4 @@ impl UserData for PluginDirs {
             Ok(path.to_str().unwrap().to_string())
         });
     }
-}
+}

+ 7 - 9
src/plugin/interface/fs.rs

@@ -1,13 +1,13 @@
 use std::{
-    fs::{create_dir, create_dir_all, remove_dir_all},
-    path::PathBuf, io::{Read, Write},
+    fs::{create_dir, create_dir_all, remove_dir_all, File},
+    io::{Read, Write},
+    path::PathBuf,
 };
-use std::fs::File;
 
-use mlua::UserData;
+use crate::tools::extract_zip;
 use flate2::read::GzDecoder;
+use mlua::UserData;
 use tar::Archive;
-use crate::tools::extract_zip;
 
 pub struct PluginFileSystem;
 impl UserData for PluginFileSystem {
@@ -49,9 +49,9 @@ impl UserData for PluginFileSystem {
             }
 
             if file.unwrap().write_all(content.as_bytes()).is_err() {
-                return Ok(false)
+                return Ok(false);
             }
-            
+
             Ok(true)
         });
         methods.add_function("unzip_file", |_, args: (String, String)| {
@@ -64,7 +64,6 @@ impl UserData for PluginFileSystem {
             Ok(true)
         });
         methods.add_function("untar_gz_file", |_, args: (String, String)| {
-
             let file = PathBuf::from(args.0);
             let target = PathBuf::from(args.1);
 
@@ -80,7 +79,6 @@ impl UserData for PluginFileSystem {
                 return Ok(false);
             }
 
-
             Ok(true)
         });
     }

+ 1 - 1
src/plugin/interface/log.rs

@@ -25,4 +25,4 @@ impl UserData for PluginLogger {
             Ok(())
         });
     }
-}
+}

+ 1 - 1
src/plugin/interface/os.rs

@@ -15,4 +15,4 @@ impl UserData for PluginOS {
             }
         });
     }
-}
+}

+ 1 - 1
src/plugin/interface/path.rs

@@ -12,7 +12,7 @@ impl UserData for PluginPath {
                 path = path.join(i);
             }
             Ok(path.to_str().unwrap().to_string())
-        });    
+        });
 
         // parent function
         methods.add_function("parent", |_, path: String| {

+ 4 - 3
src/plugin/mod.rs

@@ -13,10 +13,9 @@ use crate::{
 };
 
 use self::{
-    interface::PluginInfo,
     interface::{
         command::PluginCommander, dirs::PluginDirs, fs::PluginFileSystem, log::PluginLogger,
-        network::PluginNetwork, os::PluginOS, path::PluginPath,
+        network::PluginNetwork, os::PluginOS, path::PluginPath, PluginInfo,
     },
     types::PluginConfig,
 };
@@ -143,7 +142,9 @@ impl PluginManager {
                                             }
                                         }
                                         Ok(false) => {
-                                            log::warn!("Plugin init function result is `false`, init failed.");
+                                            log::warn!(
+                                                "Plugin init function result is `false`, init failed."
+                                            );
                                         }
                                         Err(e) => {
                                             log::warn!("Plugin init failed: {e}");

+ 2 - 2
src/tools.rs

@@ -252,8 +252,8 @@ impl Tool {
 
             if self.target_platform() == "linux" {
                 // This code does not update permissions idk why
-                /*let mut perms = final_file.metadata()?.permissions();
-                perms.set_mode(0o744);*/
+                // let mut perms = final_file.metadata()?.permissions();
+                // perms.set_mode(0o744);
 
                 // Adding to the binary execution rights with "chmod"
                 let mut command = Command::new("chmod");