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> {
16 ensure_rustfmt_installed().await?;
17
18 let output = Command::new("cargo")
19 .args(&["fmt", "--", "--check"])
20 .current_dir(project_path)
21 .output()
22 .map_err(|e| Error::process(format!("Failed to run rustfmt: {}", e)))?;
23
24 let formatted = output.status.success();
25 let stderr = String::from_utf8_lossy(&output.stderr);
26
27 Ok(FormatResult {
28 formatted,
29 unformatted_files: if formatted {
30 vec![]
31 } else {
32 vec![format!("Multiple files need formatting (see: {})", stderr)]
33 },
34 suggestions: vec![],
35 })
36}
37
38pub async fn auto_format(project_path: &Path) -> Result<()> {
44 ensure_rustfmt_installed().await?;
45
46 let status = Command::new("cargo")
47 .args(&["fmt", "--all"])
48 .current_dir(project_path)
49 .status()
50 .map_err(|e| Error::process(format!("Failed to run cargo fmt: {}", e)))?;
51
52 if !status.success() {
53 return Err(Error::process("Formatting failed".to_string()));
54 }
55
56 Ok(())
57}
58
59pub async fn get_format_diff(project_path: &Path) -> Result<String> {
65 ensure_rustfmt_installed().await?;
66
67 let output = Command::new("cargo")
68 .args(&["fmt", "--", "--check", "--print-diff"])
69 .current_dir(project_path)
70 .output()
71 .map_err(|e| Error::process(format!("Failed to get format diff: {}", e)))?;
72
73 Ok(String::from_utf8_lossy(&output.stdout).to_string())
74}
75
76pub async fn apply_rustfmt_config(project_path: &Path) -> Result<()> {
82 let config_content = r#"# Ferrous Forge rustfmt configuration
83max_width = 100
84tab_spaces = 4
85newline_style = "Unix"
86use_small_heuristics = "Default"
87edition = "2021"
88"#;
89
90 let config_path = project_path.join("rustfmt.toml");
91 fs::write(&config_path, config_content).await?;
92
93 Ok(())
94}