Compare commits
10 Commits
99722302a2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cfcd14e0a | |||
| 130525a868 | |||
| a6734c45ab | |||
| b14662a666 | |||
| 149d308f9b | |||
| 1e0e5c864c | |||
| c619621cf3 | |||
| 0334cd2fce | |||
| c5ecb78fd4 | |||
| 3c4bfca546 |
300
Cargo.lock
generated
300
Cargo.lock
generated
@@ -38,7 +38,7 @@ version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -49,7 +49,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -63,6 +63,18 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -72,6 +84,15 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.11.1"
|
||||
@@ -84,6 +105,12 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.0"
|
||||
@@ -115,6 +142,16 @@ dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_nushell"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbb9e9715d29a754b468591be588f6b926f5b0a1eb6a8b62acabeb66ff84d897"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.0"
|
||||
@@ -145,7 +182,7 @@ version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -167,6 +204,17 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162"
|
||||
dependencies = [
|
||||
"dispatch2",
|
||||
"nix",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@@ -177,12 +225,33 @@ dependencies = [
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -227,6 +296,26 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
@@ -239,18 +328,110 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"notify-types",
|
||||
"walkdir",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-types"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
@@ -259,12 +440,15 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "pallet"
|
||||
version = "1.0.6"
|
||||
version = "1.1.1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"clap_complete_nushell",
|
||||
"colored",
|
||||
"ctrlc",
|
||||
"glob",
|
||||
"notify",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha256",
|
||||
@@ -295,6 +479,15 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
@@ -461,12 +654,46 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -476,6 +703,71 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.0"
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
[package]
|
||||
name = "pallet"
|
||||
version = "1.0.6"
|
||||
version = "1.1.1"
|
||||
edition = "2024"
|
||||
description = "A project manager and build system for C inspired by Rust's Cargo"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.6.0", features = ["derive"] }
|
||||
clap_complete = "4.6.0"
|
||||
clap_complete_nushell = "4.6.0"
|
||||
colored = "3.1.1"
|
||||
ctrlc = "3.5.2"
|
||||
glob = "0.3.3"
|
||||
notify = "8.2.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
sha256 = "1.6.0"
|
||||
|
||||
4
PKGBUILD
4
PKGBUILD
@@ -1,12 +1,12 @@
|
||||
# Maintainer: Shea Frembling <sfrembling@gmail.com>
|
||||
pkgname=pallet
|
||||
pkgver=1.0.6
|
||||
pkgver=1.1.1
|
||||
pkgrel=1
|
||||
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=()
|
||||
|
||||
|
||||
@@ -72,3 +72,11 @@ args = [
|
||||
"-O3",
|
||||
]
|
||||
```
|
||||
|
||||
## Creating Changelogs
|
||||
|
||||
Use the following command to create a changelog:
|
||||
|
||||
```sh
|
||||
git log --oneline (git describe --tags --abbrev=0)..HEAD | sed 's/^/- /' | xclip -selection clipboard
|
||||
```
|
||||
|
||||
338
src/app.rs
338
src/app.rs
@@ -2,6 +2,7 @@ use std::{
|
||||
env::set_current_dir,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
sync::{Arc, atomic::Ordering},
|
||||
};
|
||||
|
||||
use clap::CommandFactory;
|
||||
@@ -9,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)]
|
||||
@@ -55,11 +58,28 @@ enum Subcommand {
|
||||
},
|
||||
/// List available build modes
|
||||
List,
|
||||
/// Add a new package to the project (throguh pkg-config)
|
||||
/// Add a new package to the project (through pkg-config)
|
||||
Add {
|
||||
/// The package to be added
|
||||
package: String,
|
||||
},
|
||||
/// Watches for source code changes and triggers a recompilation && re-run on change
|
||||
Watch {
|
||||
/// The build mode to use
|
||||
mode: Option<String>,
|
||||
/// Arguments to pass to the project binary
|
||||
#[arg(long, short)]
|
||||
args: Option<Vec<String>>,
|
||||
},
|
||||
/// Removes a package from the project (through pkg-config)
|
||||
Remove {
|
||||
/// 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)]
|
||||
@@ -75,6 +95,8 @@ enum UtilSubcommand {
|
||||
/// The build mode to generate for
|
||||
mode: Option<String>,
|
||||
},
|
||||
/// Generate the config keys for Pallet.toml
|
||||
GenConfigKeys,
|
||||
}
|
||||
|
||||
#[derive(Clone, clap::ValueEnum)]
|
||||
@@ -83,6 +105,7 @@ enum ShellCompletions {
|
||||
Fish,
|
||||
PowerShell,
|
||||
Zsh,
|
||||
Nushell,
|
||||
}
|
||||
|
||||
impl App {
|
||||
@@ -95,9 +118,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
Subcommand::Init => {
|
||||
let root = std::env::current_dir().expect("the current working directory");
|
||||
let path = root.file_name().expect("some file name");
|
||||
if let Err(e) = create_project(path.to_string_lossy().to_string()) {
|
||||
if let Err(e) = create_project(".") {
|
||||
eprintln!("Error initializing project: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
@@ -160,6 +181,12 @@ impl App {
|
||||
name,
|
||||
&mut std::io::stdout(),
|
||||
),
|
||||
ShellCompletions::Nushell => clap_complete::generate(
|
||||
clap_complete_nushell::Nushell,
|
||||
&mut command,
|
||||
name,
|
||||
&mut std::io::stdout(),
|
||||
),
|
||||
}
|
||||
}
|
||||
UtilSubcommand::GenCompileCommands { mode } => {
|
||||
@@ -168,6 +195,15 @@ impl App {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
UtilSubcommand::GenConfigKeys => {
|
||||
println!(
|
||||
"{} a property with a '?' indicates that the property is optional",
|
||||
"Hint".yellow().bold()
|
||||
);
|
||||
for (id, desc, dt) in crate::config::Config::get_config_syntax() {
|
||||
println!(" - {} ({}): {desc}", id.green().bold(), dt.blue().bold());
|
||||
}
|
||||
}
|
||||
},
|
||||
Subcommand::List => {
|
||||
if let Err(e) = list() {
|
||||
@@ -181,8 +217,212 @@ impl App {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Subcommand::Watch { mode, args } => {
|
||||
if let Err(e) = watch(&mode, args) {
|
||||
eprintln!("Error running watch: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Subcommand::Remove { package } => {
|
||||
if let Err(e) = remove(&package) {
|
||||
eprintln!("Error removing package {package} from project: {e}");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(package: &str) -> std::io::Result<()> {
|
||||
let mut conf = get_config().ok_or(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"no Pallet.toml found in local directory",
|
||||
))?;
|
||||
|
||||
let deps = conf.dependencies.get_or_insert_with(Vec::new);
|
||||
|
||||
if let Some(index) = deps.iter().position(|dep| dep == package) {
|
||||
deps.remove(index);
|
||||
} else {
|
||||
println!(
|
||||
" {} package {package} not found in Pallet.toml, no change made",
|
||||
"Warning".yellow().bold()
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
std::fs::write(
|
||||
"Pallet.toml",
|
||||
toml::to_string_pretty(&conf).expect("valid TOML"),
|
||||
)?;
|
||||
|
||||
println!(
|
||||
" {} removed package {package}",
|
||||
"Successfully".green().bold()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn watch(mode: &Option<String>, args: Option<Vec<String>>) -> std::io::Result<()> {
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
let mut stdout = std::io::stdout();
|
||||
|
||||
// enter alternate screen
|
||||
write!(stdout, "\x1b[?1049h")?;
|
||||
stdout.flush()?;
|
||||
|
||||
// set up ctrl+c handler BEFORE doing anything else
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
let running_clone = running.clone();
|
||||
ctrlc::set_handler(move || {
|
||||
running_clone.store(false, Ordering::SeqCst);
|
||||
})
|
||||
.map_err(|e| std::io::Error::other(format!("{e}")))?;
|
||||
|
||||
let result = watch_inner(mode, args, running);
|
||||
|
||||
// exit alternate screen — guaranteed to run now
|
||||
write!(stdout, "\x1b[?1049l")?;
|
||||
stdout.flush()?;
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn watch_inner(
|
||||
mode: &Option<String>,
|
||||
args: Option<Vec<String>>,
|
||||
running: Arc<std::sync::atomic::AtomicBool>,
|
||||
) -> std::io::Result<()> {
|
||||
use notify::{Event, RecursiveMode, Watcher, recommended_watcher};
|
||||
use std::io::Write;
|
||||
use std::sync::mpsc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
let clear = || {
|
||||
let mut stdout = std::io::stdout();
|
||||
write!(stdout, "\x1b[2J\x1b[H").ok();
|
||||
stdout.flush().ok();
|
||||
};
|
||||
|
||||
let print_header = |label: &str| {
|
||||
println!(
|
||||
" {} project (ctrl+c to stop) — {label}",
|
||||
"Watching".green().bold()
|
||||
);
|
||||
println!("{}", "─".repeat(50).dimmed());
|
||||
};
|
||||
|
||||
// track the running child process
|
||||
let mut child: Option<std::process::Child> = None;
|
||||
|
||||
let kill_child = |child: &mut Option<std::process::Child>| {
|
||||
if let Some(c) = child {
|
||||
c.kill().ok();
|
||||
c.wait().ok();
|
||||
}
|
||||
*child = None;
|
||||
};
|
||||
|
||||
let run_child = |mode: &Option<String>,
|
||||
args: &Option<Vec<String>>|
|
||||
-> std::io::Result<std::process::Child> {
|
||||
let conf = get_config().ok_or(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"no Pallet.toml found",
|
||||
))?;
|
||||
let build_config = conf.get_or_default(mode).ok_or(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"build layout not found",
|
||||
))?;
|
||||
let mut command = Command::new(format!("target/{}/{}", build_config.name, conf.name));
|
||||
if let Some(a) = args {
|
||||
for arg in a {
|
||||
command.arg(arg);
|
||||
}
|
||||
}
|
||||
command
|
||||
.spawn()
|
||||
.map_err(|e| std::io::Error::other(format!("{e}")))
|
||||
};
|
||||
|
||||
// initial build + run
|
||||
clear();
|
||||
print_header("starting");
|
||||
if build(mode, false).is_ok() {
|
||||
child = run_child(mode, &args).ok();
|
||||
}
|
||||
|
||||
let (tx, rx) = mpsc::channel::<notify::Result<Event>>();
|
||||
let mut watcher = recommended_watcher(tx).map_err(|e| std::io::Error::other(format!("{e}")))?;
|
||||
watcher
|
||||
.watch(Path::new("src"), RecursiveMode::Recursive)
|
||||
.map_err(|e| std::io::Error::other(format!("{e}")))?;
|
||||
|
||||
let mut last_build = Instant::now()
|
||||
.checked_sub(Duration::from_secs(1))
|
||||
.unwrap_or(Instant::now());
|
||||
|
||||
while running.load(Ordering::SeqCst) {
|
||||
match rx.recv_timeout(Duration::from_millis(100)) {
|
||||
Ok(Ok(event)) => {
|
||||
let is_relevant = matches!(
|
||||
event.kind,
|
||||
notify::EventKind::Create(_)
|
||||
| notify::EventKind::Modify(_)
|
||||
| notify::EventKind::Remove(_)
|
||||
);
|
||||
let affects_source = event.paths.iter().any(|p| {
|
||||
matches!(
|
||||
p.extension().and_then(|e| e.to_str()),
|
||||
Some("c") | Some("h")
|
||||
)
|
||||
});
|
||||
let debounced = last_build.elapsed() > Duration::from_millis(500);
|
||||
|
||||
if is_relevant && affects_source && debounced {
|
||||
last_build = Instant::now();
|
||||
|
||||
// kill whatever is currently running
|
||||
kill_child(&mut child);
|
||||
|
||||
clear();
|
||||
print_header("rebuilding");
|
||||
|
||||
match build(mode, false) {
|
||||
Ok(_) => {
|
||||
child = run_child(mode, &args).ok();
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!(" {} {e}", "Error".red().bold());
|
||||
// child stays None until next successful build
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Err(e)) => eprintln!(" {} watch error: {e}", "Error".red().bold()),
|
||||
Err(mpsc::RecvTimeoutError::Timeout) => continue, // check running flag and loop
|
||||
Err(mpsc::RecvTimeoutError::Disconnected) => break,
|
||||
}
|
||||
}
|
||||
|
||||
kill_child(&mut child);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_package(package: &str) -> std::io::Result<()> {
|
||||
@@ -253,7 +493,7 @@ fn gen_compile_commands(mode: &Option<String>) -> std::io::Result<()> {
|
||||
let cwd = std::env::current_dir()?;
|
||||
let obj_dir = format!("target/{}/obj", build_config.name);
|
||||
|
||||
let source_files: Vec<PathBuf> = glob("src/*.c")
|
||||
let source_files: Vec<PathBuf> = glob("src/**/*.c")
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))?
|
||||
.filter_map(|e| e.ok())
|
||||
.collect();
|
||||
@@ -331,8 +571,22 @@ fn create_project<P: AsRef<Path>>(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 config = crate::config::Config::new(&pathdir.to_string_lossy());
|
||||
let lossy = pathdir.to_string_lossy();
|
||||
|
||||
let app_name = if lossy == "." {
|
||||
let root = std::env::current_dir()?;
|
||||
root.file_name()
|
||||
.expect("a valid file name")
|
||||
.to_string_lossy()
|
||||
.to_string()
|
||||
} else {
|
||||
lossy.to_string()
|
||||
};
|
||||
|
||||
let config = crate::config::Config::new(&app_name);
|
||||
|
||||
let serial = toml::to_string_pretty(&config).expect("a valid TOML structure");
|
||||
|
||||
@@ -422,7 +676,7 @@ fn build(mode: &Option<String>, force_recompile: bool) -> std::io::Result<()> {
|
||||
.collect();
|
||||
}
|
||||
|
||||
let source_files: Vec<PathBuf> = glob("src/*.c")
|
||||
let source_files: Vec<PathBuf> = glob("src/**/*.c")
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))?
|
||||
.filter_map(|e| e.ok())
|
||||
.collect();
|
||||
@@ -569,3 +823,71 @@ fn clean() -> std::io::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fmt() -> std::io::Result<()> {
|
||||
let source_files: Vec<PathBuf> = 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<PathBuf> = 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(())
|
||||
}
|
||||
|
||||
@@ -35,6 +35,46 @@ impl Config {
|
||||
self.build.iter().find(|bc| bc.name == self.default_build)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_config_syntax() -> Vec<(String, String, String)> {
|
||||
vec![
|
||||
(
|
||||
"compiler?",
|
||||
"the compiler used by Pallet (defeault=gcc)",
|
||||
"string",
|
||||
),
|
||||
("name", "the name of your application", "string"),
|
||||
(
|
||||
"default_build",
|
||||
"the name of the build to use by default when running or building",
|
||||
"string",
|
||||
),
|
||||
(
|
||||
"description?",
|
||||
"a brief description of your application",
|
||||
"string",
|
||||
),
|
||||
("version?", "the version of your application", "string"),
|
||||
(
|
||||
"authors?",
|
||||
"the author or authors of your application",
|
||||
"string[]",
|
||||
),
|
||||
(
|
||||
"build",
|
||||
"a build config that can be used when compiling",
|
||||
"{name: string, args: string[]}[]",
|
||||
),
|
||||
(
|
||||
"dependencies",
|
||||
"libraries (such as zlib) used by your application that require pkg-config to be compiled correclty",
|
||||
"string[]"
|
||||
)
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(a, b, c)| (a.to_owned(), b.to_owned(), c.to_owned()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
|
||||
23
src/templates/.clang-format
Normal file
23
src/templates/.clang-format
Normal file
@@ -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
|
||||
2
src/templates/.clang-tidy
Normal file
2
src/templates/.clang-tidy
Normal file
@@ -0,0 +1,2 @@
|
||||
Checks: "clang-diagnostic-*,clang-analyzer-*"
|
||||
WarningsAsErrors: ""
|
||||
2
src/templates/.gitignore
vendored
Normal file
2
src/templates/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target/
|
||||
compile_commands.json
|
||||
Reference in New Issue
Block a user