From 1e0e5c864cb86e2daa856820132065aaa36f5798 Mon Sep 17 00:00:00 2001 From: godsfryingpan Date: Mon, 23 Mar 2026 16:34:30 -0600 Subject: [PATCH] Add Pallet Lint and Pallet Fmt (#28) closes #15 closes #16 Reviewed-on: http://192.168.1.227:3000/sfrembling/pallet/pulls/28 Co-authored-by: godsfryingpan Co-committed-by: godsfryingpan --- PKGBUILD | 2 +- src/app.rs | 90 ++++++++++++++++++++++++++++++++++++- src/templates/.clang-format | 23 ++++++++++ src/templates/.clang-tidy | 2 + src/templates/.gitignore | 2 + src/templates/main.c | 4 +- 6 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 src/templates/.clang-format create mode 100644 src/templates/.clang-tidy create mode 100644 src/templates/.gitignore diff --git a/PKGBUILD b/PKGBUILD index b89bc34..706f278 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -6,7 +6,7 @@ pkgdesc="A simple C project manager inspired by Cargo" arch=('x86_64') url="" license=('MIT') -depends=('gcc' 'pkgconf') +depends=('gcc' 'pkgconf' 'clang') makedepends=('rust' 'cargo') source=() diff --git a/src/app.rs b/src/app.rs index d1a3f2f..c6f7c4f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -10,7 +10,9 @@ use colored::Colorize; use glob::glob; const MAIN_C: &str = include_str!("templates/main.c"); -const GITIGNORE: &str = "target/\ncompile_commands.json\n"; +const GITIGNORE: &str = include_str!("templates/.gitignore"); +const CLANG_FORMAT: &str = include_str!("templates/.clang-format"); +const CLANG_TIDY: &str = include_str!("templates/.clang-tidy"); #[derive(clap::Parser)] #[clap(version, about)] @@ -74,6 +76,10 @@ enum Subcommand { /// The package to remove package: String, }, + /// Format C source code using clang-format + Fmt, + /// Lint C source code using clang-tidy + Lint, } #[derive(clap::Subcommand)] @@ -212,6 +218,18 @@ impl App { std::process::exit(1); } } + Subcommand::Fmt => { + if let Err(e) = fmt() { + eprintln!("Error formatting project: {e}"); + std::process::exit(1); + } + } + Subcommand::Lint => { + if let Err(e) = lint() { + eprintln!("Error linting project: {e}"); + std::process::exit(1); + } + } } } } @@ -542,6 +560,8 @@ fn create_project>(directory: P) -> std::io::Result<()> { std::fs::write("src/main.c", MAIN_C)?; std::fs::write(".gitignore", GITIGNORE)?; + std::fs::write(".clang-tidy", CLANG_TIDY)?; + std::fs::write(".clang-format", CLANG_FORMAT)?; let lossy = pathdir.to_string_lossy(); @@ -792,3 +812,71 @@ fn clean() -> std::io::Result<()> { Ok(()) } + +fn fmt() -> std::io::Result<()> { + let source_files: Vec = glob("src/*.c") + .map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))? + .chain( + glob("src/*.h") + .map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))?, + ) + .filter_map(|e| e.ok()) + .collect(); + + let status = Command::new("clang-format") + .arg("-i") + .args(&source_files) + .status() + .map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::NotFound, + "clang-format not found — try installing it (e.g. sudo pacman -S clang)", + ) + })?; + + if !status.success() { + return Err(std::io::Error::other("clang-format failed")); + } + + println!(" {} all source files", "Formatted".green().bold()); + + Ok(()) +} + +fn lint() -> std::io::Result<()> { + gen_compile_commands(&None)?; + + let source_files: Vec = glob("src/*.c") + .map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))? + .filter_map(|e| e.ok()) + .collect(); + + let mut any_warnings = false; + + for src in &source_files { + println!(" {} {}", "Linting".green().bold(), src.display()); + + let status = Command::new("clang-tidy") + .arg(src) + .arg("--use-color") + .status() + .map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::NotFound, + "clang-tidy not found — try installing it (e.g. sudo pacman -S clang)", + ) + })?; + + if !status.success() { + any_warnings = true; + } + } + + if any_warnings { + println!("\n {} lint warnings found", "Warning".yellow().bold()); + } else { + println!("\n {} no issues found", "Finished".green().bold()); + } + + Ok(()) +} diff --git a/src/templates/.clang-format b/src/templates/.clang-format new file mode 100644 index 0000000..a614e9b --- /dev/null +++ b/src/templates/.clang-format @@ -0,0 +1,23 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +ColumnLimit: 100 + +BreakBeforeBraces: Attach +BraceWrapping: + AfterFunction: false + AfterControlStatement: false + +SpaceAfterCStyleCast: false +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false + +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveDeclarations: Consecutive + +PointerAlignment: Right + +SortIncludes: CaseSensitive +IncludeBlocks: Regroup diff --git a/src/templates/.clang-tidy b/src/templates/.clang-tidy new file mode 100644 index 0000000..a7a8b2b --- /dev/null +++ b/src/templates/.clang-tidy @@ -0,0 +1,2 @@ +Checks: "clang-diagnostic-*,clang-analyzer-*" +WarningsAsErrors: "" diff --git a/src/templates/.gitignore b/src/templates/.gitignore new file mode 100644 index 0000000..18dd0cd --- /dev/null +++ b/src/templates/.gitignore @@ -0,0 +1,2 @@ +target/ +compile_commands.json \ No newline at end of file diff --git a/src/templates/main.c b/src/templates/main.c index 1089a12..3bccb6c 100644 --- a/src/templates/main.c +++ b/src/templates/main.c @@ -1,7 +1,7 @@ #include int main() { - printf("Hello, world!\n"); + printf("Hello, world!\n"); - return 0; + return 0; }