ferrous_forge/formatting/
project_ops.rs

1//! Project-level formatting operations
2
3use 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
10/// Check formatting for entire project
11pub 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
34/// Auto-format entire project
35pub 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
51/// Get formatting diff for the project
52pub 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
64/// Apply rustfmt configuration to project
65pub 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}