123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- use futures::{stream::FuturesUnordered, StreamExt};
- use std::{fs, process::exit};
- use super::*;
- // For reference, the rustfmt main.rs file
- // https://github.com/rust-lang/rustfmt/blob/master/src/bin/main.rs
- /// Build the Rust WASM app and all of its assets.
- #[derive(Clone, Debug, Parser)]
- pub struct Autoformat {
- /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits
- /// with 1 and prints a diff if formatting is required.
- #[clap(short, long)]
- pub check: bool,
- /// Input rsx (selection)
- #[clap(short, long)]
- pub raw: Option<String>,
- /// Input file
- #[clap(short, long)]
- pub file: Option<String>,
- }
- impl Autoformat {
- // Todo: autoformat the entire crate
- pub async fn autoformat(self) -> Result<()> {
- // Default to formatting the project
- if self.raw.is_none() && self.file.is_none() {
- if let Err(e) = autoformat_project(self.check).await {
- eprintln!("error formatting project: {}", e);
- exit(1);
- }
- }
- if let Some(raw) = self.raw {
- if let Some(inner) = dioxus_autofmt::fmt_block(&raw, 0) {
- println!("{}", inner);
- } else {
- // exit process with error
- eprintln!("error formatting codeblock");
- exit(1);
- }
- }
- // Format single file
- if let Some(file) = self.file {
- let file_content = fs::read_to_string(&file);
- match file_content {
- Ok(s) => {
- let edits = dioxus_autofmt::fmt_file(&s);
- let out = dioxus_autofmt::apply_formats(&s, edits);
- match fs::write(&file, out) {
- Ok(_) => {
- println!("formatted {}", file);
- }
- Err(e) => {
- eprintln!("failed to write formatted content to file: {}", e);
- }
- }
- }
- Err(e) => {
- eprintln!("failed to open file: {}", e);
- exit(1);
- }
- }
- }
- Ok(())
- }
- }
- /// Read every .rs file accessible when considering the .gitignore and try to format it
- ///
- /// Runs using Tokio for multithreading, so it should be really really fast
- ///
- /// Doesn't do mod-descending, so it will still try to format unreachable files. TODO.
- async fn autoformat_project(check: bool) -> Result<()> {
- let crate_config = crate::CrateConfig::new()?;
- let mut files_to_format = vec![];
- collect_rs_files(&crate_config.crate_dir, &mut files_to_format);
- let counts = files_to_format
- .into_iter()
- .filter(|file| {
- if file.components().any(|f| f.as_os_str() == "target") {
- return false;
- }
- true
- })
- .map(|path| async {
- let _path = path.clone();
- let res = tokio::spawn(async move {
- let contents = tokio::fs::read_to_string(&path).await?;
- let edits = dioxus_autofmt::fmt_file(&contents);
- let len = edits.len();
- if !edits.is_empty() {
- let out = dioxus_autofmt::apply_formats(&contents, edits);
- tokio::fs::write(&path, out).await?;
- }
- Ok(len) as Result<usize, tokio::io::Error>
- })
- .await;
- if res.is_err() {
- eprintln!("error formatting file: {}", _path.display());
- }
- res
- })
- .collect::<FuturesUnordered<_>>()
- .collect::<Vec<_>>()
- .await;
- let files_formatted: usize = counts
- .into_iter()
- .map(|f| match f {
- Ok(Ok(res)) => res,
- _ => 0,
- })
- .sum();
- if files_formatted > 0 && check {
- eprintln!("{} files needed formatting", files_formatted);
- exit(1);
- }
- Ok(())
- }
- fn collect_rs_files(folder: &PathBuf, files: &mut Vec<PathBuf>) {
- let Ok(folder) = folder.read_dir() else { return };
- // load the gitignore
- for entry in folder {
- let Ok(entry) = entry else { continue; };
- let path = entry.path();
- if path.is_dir() {
- collect_rs_files(&path, files);
- }
- if let Some(ext) = path.extension() {
- if ext == "rs" {
- files.push(path);
- }
- }
- }
- }
- #[test]
- fn spawn_properly() {
- let out = Command::new("dioxus")
- .args([
- "fmt",
- "-f",
- r#"
- //
- rsx! {
- div {}
- }
- //
- //
- //
- "#,
- ])
- .output()
- .expect("failed to execute process");
- dbg!(out);
- }
|