ferrous_forge/formatting/
project_ops.rs1use super::types::FormatResult;
4use super::utils::ensure_rustfmt_installed;
5use crate::{Error, Result};
6use std::path::Path;
7use std::process::Command;
8use tokio::fs;
9
10pub async fn check_formatting(project_path: &Path) -> Result<FormatResult> {
12 ensure_rustfmt_installed().await?;
13
14 let output = Command::new("cargo")
15 .args(&["fmt", "--", "--check"])
16 .current_dir(project_path)
17 .output()
18 .map_err(|e| Error::process(format!("Failed to run rustfmt: {}", e)))?;
19
20 let formatted = output.status.success();
21 let stderr = String::from_utf8_lossy(&output.stderr);
22
23 Ok(FormatResult {
24 formatted,
25 unformatted_files: if formatted {
26 vec![]
27 } else {
28 vec![format!("Multiple files need formatting (see: {})", stderr)]
29 },
30 suggestions: vec![],
31 })
32}
33
34pub async fn auto_format(project_path: &Path) -> Result<()> {
36 ensure_rustfmt_installed().await?;
37
38 let status = Command::new("cargo")
39 .args(&["fmt", "--all"])
40 .current_dir(project_path)
41 .status()
42 .map_err(|e| Error::process(format!("Failed to run cargo fmt: {}", e)))?;
43
44 if !status.success() {
45 return Err(Error::process("Formatting failed".to_string()));
46 }
47
48 Ok(())
49}
50
51pub async fn get_format_diff(project_path: &Path) -> Result<String> {
53 ensure_rustfmt_installed().await?;
54
55 let output = Command::new("cargo")
56 .args(&["fmt", "--", "--check", "--print-diff"])
57 .current_dir(project_path)
58 .output()
59 .map_err(|e| Error::process(format!("Failed to get format diff: {}", e)))?;
60
61 Ok(String::from_utf8_lossy(&output.stdout).to_string())
62}
63
64pub async fn apply_rustfmt_config(project_path: &Path) -> Result<()> {
66 let config_content = r#"# Ferrous Forge rustfmt configuration
67max_width = 100
68tab_spaces = 4
69newline_style = "Unix"
70use_small_heuristics = "Default"
71edition = "2021"
72"#;
73
74 let config_path = project_path.join("rustfmt.toml");
75 fs::write(&config_path, config_content).await?;
76
77 Ok(())
78}