Skip to content

Commit

Permalink
Add format subcommand
Browse files Browse the repository at this point in the history
Using `clang-format`.

Needs support for specifying settings, but that should come in its own PR.
  • Loading branch information
DvvCz committed Mar 29, 2024
1 parent 0317499 commit 14c9150
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cpkg"
description = "A dead simple C package manager."
version = "0.5.3"
version = "0.6.0"
edition = "2021"

authors = ["David Cruz <codebycruz@gmail.com>"]
Expand All @@ -17,4 +17,5 @@ indoc = "2.0.5"
nanoserde = "0.1.37"
rustyline = "14.0.0"
self_update = "0.39.0"
walkdir = "2.5.0"
which = "6.0.1"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ cpkg run
- [x] `test`
- [x] `doc` w/ Doxygen
- [x] `repl`
- [ ] `format`
- [x] `format`

## Installation

Expand Down
35 changes: 35 additions & 0 deletions src/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pub trait Format {
fn format(&self, src: &std::path::Path) -> anyhow::Result<()>;
}

pub struct ClangFormat;

impl Format for ClangFormat {
fn format(&self, src: &std::path::Path) -> anyhow::Result<()> {
let paths = walkdir::WalkDir::new(src)
.into_iter()
.flat_map(std::convert::identity) // Filter out walkdir failures
.filter(|e| e.path().extension().filter(|ext| *ext == "c" || *ext == "h").is_some()) // Only formatting .c and .h files
.map(|e| e.path().to_owned()); // Retrieving paths of files

let cmd = std::process::Command::new("clang-format")
.args(paths)
.arg("-i") // Format in place (edit files)
.output()?;

if cmd.status.success() {
Ok(())
} else {
Err(anyhow::anyhow!("Failed to format files. {}", String::from_utf8_lossy(&cmd.stderr)))
}
}
}

/// Tries to find an available C formatter
/// Currently only supports clang-format.
pub fn try_locate() -> anyhow::Result<Box<dyn Format>> {
match which::which("clang-format") {
Ok(path) => Ok(Box::new(ClangFormat)),
Err(_) => Err(anyhow::anyhow!("Couldn't find clang-format."))
}
}
22 changes: 21 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::compiler::CompilerFlags;

mod compiler;
mod docgen;
mod format;

/// Dead simple C package manager
#[derive(Parser)]
Expand Down Expand Up @@ -38,12 +39,15 @@ enum Commands {
#[command(about = "Removes compiled programs from the project.\x1b[33m")]
Clean,

#[command(about = "Generates documentation for the project using doxygen, if available.\n\x1b[36m")]
#[command(about = "Generates documentation for the project using doxygen, if available.\x1b[33m")]
Doc {
#[arg(short, long)]
open: bool
},

#[command(about = "Formats the project's code using clang-format, if available.\n\x1b[36m")]
Format,

#[command(about = "Creates a REPL with gcc or clang, if available.\x1b[36m")]
Repl,

Expand Down Expand Up @@ -264,6 +268,22 @@ fn main() -> anyhow::Result<()> {
}
},

Commands::Format => {
let config = std::path::Path::new("cpkg.toml");
if !config.exists() {
anyhow::bail!("No cpkg.toml detected, this doesn't seem to be a valid project.");
}

let backend = format::try_locate()?;

let now = std::time::Instant::now();

let proj = std::path::Path::new("src");
backend.format(proj)?;

println!("Formatted code in {}s", now.elapsed().as_secs_f32());
},

Commands::Repl => {
use std::io::{Write, BufRead};

Expand Down

0 comments on commit 14c9150

Please sign in to comment.