Merge branch 'master' into jk/autofmt-project
This commit is contained in:
commit
e1705a2920
15 files changed
+191
-358
No files matched your search
Generated
+15
@@ -715,6 +715,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rsx-rosetta",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
@@ -2268,6 +2269,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"
|
||||
|
||||
@@ -82,6 +82,7 @@ dioxus-core = { git = "https://github.com/DioxusLabs/dioxus", features = [
|
||||
] }
|
||||
dioxus-autofmt = { git = "https://github.com/dioxuslabs/dioxus" }
|
||||
gitignore = "1.0.7"
|
||||
rsx-rosetta = { git = "https://github.com/dioxuslabs/dioxus" }
|
||||
|
||||
[[bin]]
|
||||
path = "src/main.rs"
|
||||
|
||||
+3
-3
@@ -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
@@ -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,
|
||||
|
||||
+86
-262
@@ -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;
|
||||
// Get the right input for the translation
|
||||
let contents = determine_input(self.file, self.raw)?;
|
||||
|
||||
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.");
|
||||
}
|
||||
// Ensure we're loading valid HTML
|
||||
let dom = html_parser::Dom::parse(&contents)?;
|
||||
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin().read_to_string(&mut buffer).unwrap();
|
||||
// Convert the HTML to RSX
|
||||
let out = convert_html_to_formatted_rsx(&dom, self.component);
|
||||
|
||||
buffer.trim().to_string()
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
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)?;
|
||||
pub fn convert_html_to_formatted_rsx(dom: &Dom, component: bool) -> String {
|
||||
let callbody = rsx_rosetta::rsx_from_html(&dom);
|
||||
|
||||
// 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)?;
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
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![];
|
||||
|
||||
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##" ))
|
||||
}}"##
|
||||
)?;
|
||||
|
||||
if svg_idx == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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(())
|
||||
match component {
|
||||
true => write_callbody_with_icon_section(callbody),
|
||||
false => dioxus_autofmt::write_block_out(callbody).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
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_callbody_with_icon_section(mut callbody: CallBody) -> String {
|
||||
let mut svgs = vec![];
|
||||
|
||||
rsx_rosetta::collect_svgs(&mut callbody.roots, &mut svgs);
|
||||
|
||||
let mut out = write_component_body(dioxus_autofmt::write_block_out(callbody).unwrap());
|
||||
|
||||
if !svgs.is_empty() {
|
||||
write_svg_section(&mut out, svgs);
|
||||
}
|
||||
|
||||
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(());
|
||||
}
|
||||
|
||||
// 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 {
|
||||
render_child(f, child, il + 1, svg_buffer, skip_svg, svg_idx)?;
|
||||
}
|
||||
|
||||
// close the tag
|
||||
write_tabs(f, il)?;
|
||||
writeln!(f, "}}")?;
|
||||
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 write_tabs(f: &mut impl std::fmt::Write, num: u32) -> std::fmt::Result {
|
||||
for _ in 0..num {
|
||||
write!(f, " ")?
|
||||
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 }");
|
||||
}
|
||||
Ok(())
|
||||
|
||||
out.push_str("\n}");
|
||||
}
|
||||
|
||||
fn indent_and_write(raw: &str, idx: usize, out: &mut String) {
|
||||
for line in raw.lines() {
|
||||
for _ in 0..idx {
|
||||
out.push_str(" ");
|
||||
}
|
||||
out.push_str(line);
|
||||
out.push('\n');
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if let Some(raw) = raw {
|
||||
return Ok(raw);
|
||||
}
|
||||
|
||||
if let Some(file) = file {
|
||||
return Ok(std::fs::read_to_string(&file)?);
|
||||
}
|
||||
|
||||
// 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.");
|
||||
}
|
||||
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin().read_to_string(&mut buffer).unwrap();
|
||||
|
||||
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);
|
||||
}
|
||||
+25
-13
@@ -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,23 +17,34 @@ 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);
|
||||
};
|
||||
|
||||
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)?;
|
||||
|
||||
toml::from_str::<DioxusConfig>(&meta_str)
|
||||
.map_err(|_| crate::Error::Unique("Dioxus.toml parse failed".into()))
|
||||
toml::from_str::<DioxusConfig>(&std::fs::read_to_string(dioxus_conf_file)?)
|
||||
.map_err(|_| crate::Error::Unique("Dioxus.toml parse failed".into()))
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
fn acquire_dioxus_toml(dir: PathBuf) -> Option<PathBuf> {
|
||||
// prefer uppercase
|
||||
if dir.join("Dioxus.toml").is_file() {
|
||||
return Some(dir.join("Dioxus.toml"));
|
||||
}
|
||||
|
||||
// lowercase is fine too
|
||||
if dir.join("dioxus.toml").is_file() {
|
||||
return Some(dir.join("Dioxus.toml"));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
impl Default for DioxusConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -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)
|
||||
|
||||
+42
-58
@@ -1,81 +1,65 @@
|
||||
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());
|
||||
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()
|
||||
});
|
||||
|
||||
let plugin_state = PluginManager::init(dioxus_config.plugin);
|
||||
|
||||
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().await {
|
||||
log::error!("format error: {}", e);
|
||||
}
|
||||
}
|
||||
Autoformat(opts) => opts
|
||||
.autoformat()
|
||||
.await
|
||||
.map_err(|e| anyhow!("🚫 Error autoformatting RSX: {}", e)),
|
||||
|
||||
Commands::Version(opt) => {
|
||||
Version(opt) => {
|
||||
let version = opt.version();
|
||||
println!("{}", version);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -10,4 +10,4 @@ impl UserData for PluginDirs {
|
||||
Ok(path.to_str().unwrap().to_string())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 flate2::read::GzDecoder;
|
||||
use tar::Archive;
|
||||
use crate::tools::extract_zip;
|
||||
use flate2::read::GzDecoder;
|
||||
use mlua::UserData;
|
||||
use tar::Archive;
|
||||
|
||||
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)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,4 +25,4 @@ impl UserData for PluginLogger {
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,4 @@ impl UserData for PluginOS {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user