diff --git a/Cargo.lock b/Cargo.lock index d54e563..9fe511d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -11,6 +20,56 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -106,6 +165,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "core-foundation" version = "0.9.4" @@ -157,8 +222,11 @@ name = "dcr" version = "0.9.1" dependencies = [ "ctrlc", + "env_logger", "fatfs", "glob", + "log", + "owo-colors", "self-replace", "serde", "serde_json", @@ -168,6 +236,37 @@ dependencies = [ "ureq", ] +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + [[package]] name = "digest" version = "0.10.7" @@ -198,7 +297,30 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "env_filter" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", ] [[package]] @@ -475,12 +597,54 @@ dependencies = [ "serde_core", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "js-sys" version = "0.3.103" @@ -518,9 +682,9 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "log" -version = "0.4.30" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "memchr" @@ -570,12 +734,24 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "owo-colors" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -588,6 +764,21 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -604,7 +795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -631,6 +822,35 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "rustix" version = "1.1.4" @@ -757,7 +977,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -828,6 +1048,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -836,7 +1067,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -852,6 +1083,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + [[package]] name = "tinystr" version = "0.8.3" @@ -976,6 +1227,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "version_check" version = "0.9.5" @@ -1032,7 +1289,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -1100,7 +1357,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1111,7 +1368,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1271,7 +1528,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -1287,7 +1544,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -1354,7 +1611,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -1375,7 +1632,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -1415,7 +1672,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ebf2e9d..a529b9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,11 @@ serde_json = "1" ctrlc = "3" fatfs = { version = "0.3", optional = true } +# Logging +log = "0.4.34" +env_logger = "0.11.11" +owo-colors = "4" + [profile.release] opt-level = "z" lto = "thin" diff --git a/src/cli/add.rs b/src/cli/add.rs index 44cfb40..7c791f8 100644 --- a/src/cli/add.rs +++ b/src/cli/add.rs @@ -15,10 +15,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build_config::Config; use crate::core::deps::register; use crate::utils::fs::find_project_root; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use toml::Value; use toml::map::Map; @@ -91,7 +92,7 @@ pub fn add(args: &[String]) -> i32 { let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; @@ -99,11 +100,11 @@ pub fn add(args: &[String]) -> i32 { let root = match find_project_root(&start_dir) { Ok(Some(dir)) => dir, Ok(None) => { - error("dcr.toml file not found"); + error!("dcr.toml file not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; @@ -111,7 +112,7 @@ pub fn add(args: &[String]) -> i32 { let mut config = match Config::open(&root.join("dcr.toml").to_string_lossy()) { Ok(cfg) => cfg, Err(err) => { - error(&err.to_string()); + error!("{err}"); return 1; } }; @@ -154,13 +155,13 @@ pub fn add(args: &[String]) -> i32 { } else if let Some(version) = add_args.version_from_registry { Value::String(version) } else { - error("Dependency source (path, git, or pkg-config) must be provided"); + error!("Dependency source (path, git, or pkg-config) must be provided"); return 1; }; let key = format!("dependencies.{}", add_args.name); if let Err(err) = config.edit(&key, dep_value) { - error(&format!("Failed to update dcr.toml: {}", err)); + error!("Failed to update dcr.toml: {err}"); return 1; } @@ -179,13 +180,13 @@ pub fn add(args: &[String]) -> i32 { /// `path:`, `github:`, `gitlab:`, or `git:` prefixes, or a full git URL. fn parse_add_args(args: &[String]) -> Result { if args.is_empty() { - error("Usage: dcr add [--branch | --tag | --rev ]"); - error("Sources:"); - error(" github:user/repo -> github.com/user/repo"); - error(" gitlab:user/repo -> gitlab.com/user/repo"); - error(" git:host.com/user/repo -> host.com/user/repo"); - error(" path:./path/to/lib -> local path"); - error(" pkg-config:fmt -> system pkg-config package"); + error!("Usage: dcr add [--branch | --tag | --rev ]"); + error!("Sources:"); + error!(" github:user/repo -> github.com/user/repo"); + error!(" gitlab:user/repo -> gitlab.com/user/repo"); + error!(" git:host.com/user/repo -> host.com/user/repo"); + error!(" path:./path/to/lib -> local path"); + error!(" pkg-config:fmt -> system pkg-config package"); return Err(1); } @@ -198,7 +199,7 @@ fn parse_add_args(args: &[String]) -> Result { let mut iter = args.iter(); if let Some(n) = iter.next() { if n.starts_with("--") { - error("First argument must be the dependency name"); + error!("First argument must be the dependency name"); return Err(1); } name = n.clone(); @@ -206,7 +207,7 @@ fn parse_add_args(args: &[String]) -> Result { if let Some(s) = iter.next() { if s.starts_with("--") { - error("Second argument must be the dependency source"); + error!("Second argument must be the dependency source"); return Err(1); } source_spec = s.clone(); @@ -225,7 +226,7 @@ fn parse_add_args(args: &[String]) -> Result { ) }) .map_err(|(msg, code)| { - error(&msg); + error!("{msg}"); code })?; return Ok(AddArgs { @@ -240,7 +241,7 @@ fn parse_add_args(args: &[String]) -> Result { }); } Err(e) => { - error(&format!("Cannot add `{}` without source: {}", name, e)); + error!("Cannot add `{}` without source: {}", name, e); return Err(1); } } @@ -251,26 +252,26 @@ fn parse_add_args(args: &[String]) -> Result { "--branch" => { branch = iter.next().cloned(); if branch.is_none() { - error("--branch requires a value"); + error!("--branch requires a value"); return Err(1); } } "--tag" => { tag = iter.next().cloned(); if tag.is_none() { - error("--tag requires a value"); + error!("--tag requires a value"); return Err(1); } } "--rev" => { rev = iter.next().cloned(); if rev.is_none() { - error("--rev requires a value"); + error!("--rev requires a value"); return Err(1); } } _ => { - error(&format!("Unknown argument: {}", arg)); + error!("Unknown argument: {arg}"); return Err(1); } } @@ -292,7 +293,7 @@ fn parse_add_args(args: &[String]) -> Result { .map(str::to_string) .collect::>(); if packages.is_empty() { - error("pkg-config source must name at least one package"); + error!("pkg-config source must name at least one package"); return Err(1); } pkg_config = Some(packages); @@ -326,7 +327,7 @@ fn parse_add_args(args: &[String]) -> Result { { path = Some(source_spec); } else { - error( + error!( "Source must be a path, pkg-config:, a prefixed source (path:, git:, github:, gitlab:), or a full URL", ); return Err(1); diff --git a/src/cli/build.rs b/src/cli/build.rs index 2975bfe..6116127 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::cli::clean::clean; use crate::cli::flags::parse_build_run_flags; use crate::cli::r#gen::{ProjectInfo, write_dcr_metadata}; @@ -27,7 +29,6 @@ use crate::utils::build::{ normalize_kind, resolve_artifact_target_dir, resolve_compiler, }; use crate::utils::fs::{canonicalize_path, find_project_root}; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, BOLD_YELLOW, colored, printc}; use std::io::IsTerminal; use std::path::Path; @@ -173,18 +174,18 @@ pub fn build(args: &[String]) -> i32 { let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; let root = match find_project_root(&start_dir) { Ok(Some(dir)) => canonicalize_path(&dir), Ok(None) => { - error("dcr.toml file not found"); + error!("dcr.toml file not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; @@ -242,7 +243,7 @@ pub fn build(args: &[String]) -> i32 { } Err(err) => { common::finish_progress_line(); - error(&err.message); + error!("{}", err.message); 1 } } diff --git a/src/cli/clean.rs b/src/cli/clean.rs index 2c02b95..0c0e8e7 100644 --- a/src/cli/clean.rs +++ b/src/cli/clean.rs @@ -15,11 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build_config::Config; use crate::core::workspace::parse_workspace; use crate::utils::build::{default_profile_flags, default_target_triple, parse_version_info}; use crate::utils::fs::{check_dir, find_project_root, with_dir}; -use crate::utils::log::{error, warn}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use glob::glob; use std::fs; @@ -56,25 +57,25 @@ pub fn clean(args: &[String]) -> i32 { let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; let root = match find_project_root(&start_dir) { Ok(Some(dir)) => dir, Ok(None) => { - error("dcr.toml file not found"); + error!("dcr.toml file not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; let flags = match parse_clean_flags(args) { Ok(v) => v, Err(msg) => { - error(&msg); + error!("{msg}"); return 1; } }; @@ -83,7 +84,7 @@ pub fn clean(args: &[String]) -> i32 { match with_dir(&root, || clean_from_root(&root, &flags)) { Ok(()) => 0, Err(msg) => { - error(&msg); + error!("{msg}"); 1 } } @@ -229,7 +230,7 @@ fn clean_project_at( target_items.contains(&profile.to_string()) }; if !dir_exists { - warn(&format!("Directory target/{} not found", target_dir)); + warn!("Directory target/{target_dir} not found"); } else { println!(" Profile: {}", colored(profile, BOLD_GREEN)); if let Some(t) = target { @@ -253,7 +254,7 @@ fn clean_project_at( colored("\n ✔", BOLD_GREEN) ); } else { - warn("Directory target not found"); + warn!("Directory target not found"); } clean_custom_paths(&config, "debug")?; clean_custom_paths(&config, "release")?; diff --git a/src/cli/flag_update.rs b/src/cli/flag_update.rs index 8e0fa0d..4819d0a 100644 --- a/src/cli/flag_update.rs +++ b/src/cli/flag_update.rs @@ -15,7 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::utils::log::{error, warn}; +use crate::prelude::*; + use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc}; use serde::Deserialize; use std::fs; @@ -64,21 +65,21 @@ pub fn flag_update(args: &[String]) -> i32 { } if !args.is_empty() { - warn("Command does not support additional arguments"); + warn!("Command does not support additional arguments"); return 1; } let current_exe = match std::env::current_exe() { Ok(path) => path, Err(_) => { - error("Failed to resolve current binary path"); + error!("Failed to resolve current binary path"); return 1; } }; // Refuse self-update when the binary is owned by pacman/AUR. if let Some(package_name) = pacman_owned_package(¤t_exe) { - warn("This dcr binary is managed by pacman/AUR"); + warn!("This dcr binary is managed by pacman/AUR"); println!( "Update via package manager: yay/paru -Syu {package_name} or sudo pacman -Syu {package_name}" ); @@ -91,7 +92,7 @@ pub fn flag_update(args: &[String]) -> i32 { let release = match fetch_latest_release() { Ok(release) => release, Err(err) => { - error(&format!("Failed to check for updates: {err}")); + error!("Failed to check for updates: {err}"); return 1; } }; @@ -109,14 +110,14 @@ pub fn flag_update(args: &[String]) -> i32 { .iter() .find(|asset| candidate_names.iter().any(|name| name == &asset.name)) else { - error(&format!("Binary for target {target} not found")); + error!("Binary for target {target} not found"); return 1; }; let bytes = match download_asset(&asset.browser_download_url) { Ok(bytes) => bytes, Err(err) => { - error(&format!("Failed to download update: {err}")); + error!("Failed to download update: {err}"); return 1; } }; @@ -124,7 +125,7 @@ pub fn flag_update(args: &[String]) -> i32 { let temp_path = temp_binary_path(¤t_exe); if fs::write(&temp_path, &bytes).is_err() { - error("Failed to write temporary binary"); + error!("Failed to write temporary binary"); return 1; } set_executable_permissions(&temp_path); @@ -132,7 +133,7 @@ pub fn flag_update(args: &[String]) -> i32 { // Replace the running executable in place, then clean up the temp file. if self_replace::self_replace(&temp_path).is_err() { let _ = fs::remove_file(&temp_path); - error("Failed to replace current binary"); + error!("Failed to replace current binary"); return 1; } diff --git a/src/cli/flags.rs b/src/cli/flags.rs index 257eddf..c063fcd 100644 --- a/src/cli/flags.rs +++ b/src/cli/flags.rs @@ -15,8 +15,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::config::{PROFILE, flags}; -use crate::utils::log::warn; /// Flags shared by the `build` and `run` CLI commands. pub struct BuildRunFlags { @@ -82,7 +83,7 @@ pub fn parse_build_run_flags(args: &[String]) -> Result { while let Some(arg) = iter.next() { // DCR build/run options are long flags only (`--name`). if !arg.starts_with("--") { - warn("Unknown argument"); + warn!("Unknown argument"); return Err(1); } let candidate = arg.trim_start_matches("--"); @@ -106,7 +107,7 @@ pub fn parse_build_run_flags(args: &[String]) -> Result { if let Some(w) = iter.next() { workspace = Some(w.clone()); } else { - warn("--workspace requires a value"); + warn!("--workspace requires a value"); return Err(1); } continue; @@ -115,7 +116,7 @@ pub fn parse_build_run_flags(args: &[String]) -> Result { if let Some(t) = iter.next() { target = Some(t.clone()); } else { - warn("--target requires a value"); + warn!("--target requires a value"); return Err(1); } continue; @@ -123,13 +124,13 @@ pub fn parse_build_run_flags(args: &[String]) -> Result { // Profile names come from config::flags; only one profile may be set. if flags(candidate).is_some() { if profile != PROFILE { - warn("Duplicate profile flag"); + warn!("Duplicate profile flag"); return Err(1); } profile = candidate.to_string(); continue; } - warn("Unknown build flag"); + warn!("Unknown build flag"); return Err(1); } diff --git a/src/cli/fmt.rs b/src/cli/fmt.rs index 0f91e7c..f1eae26 100644 --- a/src/cli/fmt.rs +++ b/src/cli/fmt.rs @@ -15,7 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::utils::log::error; +use crate::prelude::*; + use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use glob::glob; use std::process::Command; @@ -88,11 +89,11 @@ pub fn fmt(args: &[String]) -> i32 { 0 } Ok(s) => { - error(&format!("clang-format failed with status: {}", s)); + error!("clang-format failed with status: {s}"); 1 } Err(e) => { - error(&format!("Failed to execute clang-format: {}", e)); + error!("Failed to execute clang-format: {e}"); 1 } } diff --git a/src/cli/gen.rs b/src/cli/gen.rs index 6e73b3a..3ac5f2f 100644 --- a/src/cli/gen.rs +++ b/src/cli/gen.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build::builder::BuildContext; use crate::core::build::builder::artifact::{absolute_artifact_path, resolve_artifact_path}; use crate::core::build::builder::collect_sources; @@ -29,7 +31,6 @@ use crate::utils::build::{ use crate::utils::fs::{ absolute_join, atomic_write, canonicalize_path, ensure_dcr_dir, find_project_root, }; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc}; use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -290,7 +291,7 @@ pub fn r#gen(args: &[String]) -> i32 { "vscode" => gen_vscode(rest), "clion" => gen_clion(rest), _ => { - error(&format!("Unknown gen subcommand: {subcommand}")); + error!("Unknown gen subcommand: {subcommand}"); 1 } } @@ -853,7 +854,7 @@ fn gen_project_info(args: &[String]) -> i32 { let all = match collect_all(&root, &profile) { Ok(v) => v, Err(e) => { - error(&e); + error!("{e}"); return 1; } }; @@ -975,7 +976,7 @@ fn gen_compile_commands(args: &[String]) -> i32 { let all = match collect_all(&root, &profile) { Ok(v) => v, Err(e) => { - error(&e); + error!("{e}"); return 1; } }; @@ -988,7 +989,7 @@ fn gen_compile_commands(args: &[String]) -> i32 { /// Used by `compile-commands`, `vscode`, and `clion`. fn gen_compile_commands_inner(root: &Path, profile: &str, all: &[ProjectInfo], quiet: bool) -> i32 { if let Err(e) = ensure_dcr_dir(root) { - error(&format!("Failed to create .dcr/: {e}")); + error!("Failed to create .dcr/: {e}"); return 1; } @@ -1009,7 +1010,7 @@ fn gen_compile_commands_inner(root: &Path, profile: &str, all: &[ProjectInfo], q 0 } Err(e) => { - error(&format!("Failed to write compile_commands.json: {e}")); + error!("Failed to write compile_commands.json: {e}"); 1 } } @@ -1163,7 +1164,7 @@ fn gen_vscode(args: &[String]) -> i32 { let all = match collect_all(&root, &profile) { Ok(v) => v, Err(e) => { - error(&e); + error!("{e}"); return 1; } }; @@ -1176,13 +1177,13 @@ fn gen_vscode(args: &[String]) -> i32 { let vscode_dir = root.join(".vscode"); if let Err(e) = std::fs::create_dir_all(&vscode_dir) { - error(&format!("Failed to create .vscode/: {e}")); + error!("Failed to create .vscode/: {e}"); return 1; } // tasks.json if let Err(e) = std::fs::write(vscode_dir.join("tasks.json"), gen_tasks_json()) { - error(&format!("Failed to write tasks.json: {e}")); + error!("Failed to write tasks.json: {e}"); return 1; } println!("Generated {}", vscode_dir.join("tasks.json").display()); @@ -1190,7 +1191,7 @@ fn gen_vscode(args: &[String]) -> i32 { // launch.json — one entry per binary target let launch = gen_launch_json(&all, &root); if let Err(e) = std::fs::write(vscode_dir.join("launch.json"), launch) { - error(&format!("Failed to write launch.json: {e}")); + error!("Failed to write launch.json: {e}"); return 1; } println!("Generated {}", vscode_dir.join("launch.json").display()); @@ -1198,14 +1199,14 @@ fn gen_vscode(args: &[String]) -> i32 { // settings.json (clangd compile-commands-dir) let settings = gen_settings_json(&root); if let Err(e) = std::fs::write(vscode_dir.join("settings.json"), settings) { - error(&format!("Failed to write settings.json: {e}")); + error!("Failed to write settings.json: {e}"); return 1; } println!("Generated {}", vscode_dir.join("settings.json").display()); // extensions.json — disable cpptools, recommend clangd if let Err(e) = std::fs::write(vscode_dir.join("extensions.json"), gen_extensions_json()) { - error(&format!("Failed to write extensions.json: {e}")); + error!("Failed to write extensions.json: {e}"); return 1; } println!("Generated {}", vscode_dir.join("extensions.json").display()); @@ -1453,7 +1454,7 @@ fn gen_clion(args: &[String]) -> i32 { let all = match collect_all(&root, &profile) { Ok(v) => v, Err(e) => { - error(&e); + error!("{e}"); return 1; } }; @@ -1466,19 +1467,19 @@ fn gen_clion(args: &[String]) -> i32 { let idea_dir = root.join(".idea"); if let Err(e) = std::fs::create_dir_all(&idea_dir) { - error(&format!("Failed to create .idea/: {e}")); + error!("Failed to create .idea/: {e}"); return 1; } let run_configs_dir = idea_dir.join("runConfigurations"); if let Err(e) = std::fs::create_dir_all(&run_configs_dir) { - error(&format!("Failed to create .idea/runConfigurations/: {e}")); + error!("Failed to create .idea/runConfigurations/: {e}"); return 1; } // externalTools.xml let ext_tools = gen_clion_external_tools(); if let Err(e) = std::fs::write(idea_dir.join("externalTools.xml"), ext_tools) { - error(&format!("Failed to write externalTools.xml: {e}")); + error!("Failed to write externalTools.xml: {e}"); return 1; } println!("Generated {}", idea_dir.join("externalTools.xml").display()); @@ -1486,7 +1487,7 @@ fn gen_clion(args: &[String]) -> i32 { // customTargets.xml let targets = gen_clion_custom_targets(); if let Err(e) = std::fs::write(idea_dir.join("customTargets.xml"), targets) { - error(&format!("Failed to write customTargets.xml: {e}")); + error!("Failed to write customTargets.xml: {e}"); return 1; } println!("Generated {}", idea_dir.join("customTargets.xml").display()); @@ -1494,7 +1495,7 @@ fn gen_clion(args: &[String]) -> i32 { // misc.xml — point CLion at compile_commands.json let misc = gen_clion_misc_xml(&root); if let Err(e) = std::fs::write(idea_dir.join("misc.xml"), misc) { - error(&format!("Failed to write misc.xml: {e}")); + error!("Failed to write misc.xml: {e}"); return 1; } println!("Generated {}", idea_dir.join("misc.xml").display()); @@ -1502,7 +1503,7 @@ fn gen_clion(args: &[String]) -> i32 { // .idea/.gitignore let gitignore = "# CLion generated files\nworkspace.xml\n*.iml\n"; if let Err(e) = std::fs::write(idea_dir.join(".gitignore"), gitignore) { - error(&format!("Failed to write .idea/.gitignore: {e}")); + error!("Failed to write .idea/.gitignore: {e}"); return 1; } println!("Generated {}", idea_dir.join(".gitignore").display()); @@ -1516,7 +1517,7 @@ fn gen_clion(args: &[String]) -> i32 { let fname = format!("{}.xml", sanitize_filename(&info.name)); let path = run_configs_dir.join(&fname); if let Err(e) = std::fs::write(&path, xml) { - error(&format!("Failed to write runConfigurations/{fname}: {e}")); + error!("Failed to write runConfigurations/{fname}: {e}"); return 1; } println!("Generated {}", path.display()); @@ -1720,18 +1721,18 @@ fn parse_gen_args(args: &[String]) -> Result<(PathBuf, String, bool), i32> { } let start = std::env::current_dir().map_err(|_| { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); 1i32 })?; let root = match find_project_root(&start) { Ok(Some(r)) => canonicalize_path(&r), Ok(None) => { - error("dcr.toml not found"); + error!("dcr.toml not found"); return Err(1); } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return Err(1); } }; diff --git a/src/cli/init.rs b/src/cli/init.rs index 4d80411..1a7cb72 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -15,11 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::config::FILE_MAIN_C; use crate::core::build_config::{Config, validate_package_name}; use crate::core::vcs::VcsKind; use crate::utils::fs::check_dir; -use crate::utils::log::{error, warn}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use std::fs; use std::io::Write; @@ -48,7 +49,7 @@ pub fn init(args: &[String]) -> i32 { if let Some(val) = iter.next() { vcs_str = Some(val.clone()); } else { - error("--vcs requires a value"); + error!("--vcs requires a value"); return 1; } } else if let Some(stripped) = arg.strip_prefix("--vcs=") { @@ -59,7 +60,7 @@ pub fn init(args: &[String]) -> i32 { } if !clean_args.is_empty() { - warn("Command does not support additional arguments"); + warn!("Command does not support additional arguments"); return 1; } @@ -71,16 +72,15 @@ pub fn init(args: &[String]) -> i32 { .unwrap_or_else(|| "project".to_string()); if !items.is_empty() { - error("Directory not empty"); + error!("Directory not empty"); return 1; } if let Err(e) = validate_package_name(&project_name) { - error(&format!( - "Invalid project name `{}`: {}", + error!( + "Invalid project name `{}`: {e}", colored(&project_name, BOLD_CYAN), - e - )); + ); return 1; } @@ -91,7 +91,7 @@ pub fn init(args: &[String]) -> i32 { // Create and initialize default manifest (dcr.toml). if Config::create("./dcr.toml", Some(&project_name)).is_err() { - error("Failed to create dcr.toml"); + error!("Failed to create dcr.toml"); return 1; } println!( @@ -102,18 +102,18 @@ pub fn init(args: &[String]) -> i32 { // Create src directory and write template main.c file. if fs::create_dir("src").is_err() { - error("Failed to create src/"); + error!("Failed to create src/"); return 1; } let mut main_c = match fs::File::create("./src/main.c") { Ok(file) => file, Err(_) => { - error("Failed to create src/main.c"); + error!("Failed to create src/main.c"); return 1; } }; if main_c.write_all(FILE_MAIN_C.as_bytes()).is_err() { - error("Failed to write src/main.c"); + error!("Failed to write src/main.c"); return 1; } println!( @@ -128,7 +128,7 @@ pub fn init(args: &[String]) -> i32 { match VcsKind::parse(vcs_val) { Ok(kind) => vcs_kind = kind, Err(e) => { - error(&e); + error!("{e}"); return 1; } } @@ -142,7 +142,7 @@ pub fn init(args: &[String]) -> i32 { if crate::utils::git::is_git_available() { let project_path = std::path::Path::new("."); if let Err(e) = crate::core::vcs::init_vcs(vcs_kind, project_path) { - warn(&format!("Failed to initialize git repository: {}", e)); + warn!("Failed to initialize git repository: {e}"); } else { println!( " {} Initialized git repository", @@ -150,14 +150,14 @@ pub fn init(args: &[String]) -> i32 { ); } } else { - warn( + warn!( "Git is not installed or not found in PATH. Skipping Git repository initialization.", ); } } if let Err(e) = crate::utils::fs::ensure_gitignore_has_dcr(std::path::Path::new(".")) { - warn(&format!("Failed to update .gitignore: {e}")); + warn!("Failed to update .gitignore: {e}"); } println!( diff --git a/src/cli/lint.rs b/src/cli/lint.rs index b47b2ec..37f2c97 100644 --- a/src/cli/lint.rs +++ b/src/cli/lint.rs @@ -15,11 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build::common; use crate::core::build_config::Config; use crate::utils::build::{get_bool_with_profile, get_list_with_profile}; use crate::utils::fs::find_project_root; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, BOLD_YELLOW, colored, printc}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -46,7 +47,7 @@ pub fn lint(args: &[String]) -> i32 { let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; @@ -54,11 +55,11 @@ pub fn lint(args: &[String]) -> i32 { let root = match find_project_root(&start_dir) { Ok(Some(r)) => r, Ok(None) => { - error("dcr.toml not found"); + error!("dcr.toml not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; @@ -66,7 +67,7 @@ pub fn lint(args: &[String]) -> i32 { let config = match Config::open(&root.join("dcr.toml").to_string_lossy()) { Ok(c) => c, Err(e) => { - error(&format!("Failed to load dcr.toml: {e}")); + error!("Failed to load dcr.toml: {e}"); return 1; } }; @@ -98,7 +99,7 @@ pub fn lint(args: &[String]) -> i32 { match common::collect_sources(&roots, &cxx_extensions, &exclude_dirs, &include_paths) { Ok(f) => f, Err(e) => { - error(&format!("Failed to collect source files: {e}")); + error!("Failed to collect source files: {e}"); return 1; } }; @@ -142,7 +143,7 @@ pub fn lint(args: &[String]) -> i32 { let output = match cmd.output() { Ok(o) => o, Err(e) => { - error(&format!("Failed to execute clang-tidy: {}", e)); + error!("Failed to execute clang-tidy: {e}"); return 1; } }; diff --git a/src/cli/new.rs b/src/cli/new.rs index f0671d4..e7ec5bb 100644 --- a/src/cli/new.rs +++ b/src/cli/new.rs @@ -15,11 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::config::FILE_MAIN_C; use crate::core::build_config::{Config, validate_package_name}; use crate::core::vcs::VcsKind; use crate::utils::fs::check_dir; -use crate::utils::log::{error, warn}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use std::fs; use std::io::Write; @@ -50,7 +51,7 @@ pub fn new(args: &[String]) -> i32 { if let Some(val) = iter.next() { vcs_str = Some(val.clone()); } else { - error("--vcs requires a value"); + error!("--vcs requires a value"); return 1; } } else if let Some(stripped) = arg.strip_prefix("--vcs=") { @@ -61,11 +62,11 @@ pub fn new(args: &[String]) -> i32 { } if clean_args.is_empty() { - error("Project name not specified"); + error!("Project name not specified"); return 1; } if clean_args.len() > 1 { - warn("Command does not support additional arguments"); + warn!("Command does not support additional arguments"); return 1; } @@ -76,19 +77,18 @@ pub fn new(args: &[String]) -> i32 { ); if let Err(e) = validate_package_name(project_name) { - error(&format!( - "Invalid project name `{}`: {}", + error!( + "Invalid project name `{}`: {e}", colored(project_name, BOLD_CYAN), - e - )); + ); return 1; } if items.contains(project_name) { - error(&format!( + error!( "Directory `{}` already exists\n", colored(project_name, BOLD_CYAN) - )); + ); printc("Hint:", BOLD_CYAN); println!( " Use `{}` to initialize an existing project\n or specify a different project name", @@ -98,7 +98,7 @@ pub fn new(args: &[String]) -> i32 { } if fs::create_dir(project_name).is_err() { - error("Failed to create directory"); + error!("Failed to create directory"); return 1; } println!( @@ -110,7 +110,7 @@ pub fn new(args: &[String]) -> i32 { // Initialize and write project configuration manifest (dcr.toml). let toml_path = format!("./{project_name}/dcr.toml"); if Config::create(&toml_path, Some(project_name)).is_err() { - error("Failed to create dcr.toml"); + error!("Failed to create dcr.toml"); return 1; } println!( @@ -121,19 +121,19 @@ pub fn new(args: &[String]) -> i32 { // Generate src directory and populate initial main.c file. if fs::create_dir_all(format!("./{project_name}/src")).is_err() { - error("Failed to create src/"); + error!("Failed to create src/"); return 1; } let main_c_path = format!("./{project_name}/src/main.c"); let mut main_c = match fs::File::create(&main_c_path) { Ok(file) => file, Err(_) => { - error("Failed to create src/main.c"); + error!("Failed to create src/main.c"); return 1; } }; if main_c.write_all(FILE_MAIN_C.as_bytes()).is_err() { - error("Failed to write src/main.c"); + error!("Failed to write src/main.c"); return 1; } println!( @@ -148,7 +148,8 @@ pub fn new(args: &[String]) -> i32 { match VcsKind::parse(vcs_val) { Ok(kind) => vcs_kind = kind, Err(e) => { - error(&e); + error!("{e}"); + return 1; } } @@ -162,7 +163,7 @@ pub fn new(args: &[String]) -> i32 { if crate::utils::git::is_git_available() { let project_path = std::path::Path::new(project_name); if let Err(e) = crate::core::vcs::init_vcs(vcs_kind, project_path) { - warn(&format!("Failed to initialize git repository: {}", e)); + warn!("Failed to initialize git repository: {e}"); } else { println!( " {} Initialized git repository", @@ -170,7 +171,7 @@ pub fn new(args: &[String]) -> i32 { ); } } else { - warn( + warn!( "Git is not installed or not found in PATH. Skipping Git repository initialization.", ); } @@ -178,7 +179,7 @@ pub fn new(args: &[String]) -> i32 { let project_path = std::path::Path::new(project_name); if let Err(e) = crate::utils::fs::ensure_gitignore_has_dcr(project_path) { - warn(&format!("Failed to update .gitignore: {e}")); + warn!("Failed to update .gitignore: {e}"); } println!( diff --git a/src/cli/run.rs b/src/cli/run.rs index fd11bf6..9bc2b85 100644 --- a/src/cli/run.rs +++ b/src/cli/run.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::cli::build::build; use crate::cli::flags::parse_build_run_flags; use crate::core::build_config::Config; @@ -22,7 +24,6 @@ use crate::core::runner::run_binary; use crate::utils::build::{normalize_target_os, parse_version_info, substitute_vars}; use crate::utils::fs::find_project_root; use crate::utils::fs::with_dir; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use std::path::Path; use std::process::Command; @@ -91,18 +92,18 @@ pub fn run(args: &[String]) -> i32 { let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; let root = match find_project_root(&start_dir) { Ok(Some(dir)) => dir, Ok(None) => { - error("dcr.toml file not found"); + error!("dcr.toml file not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; @@ -111,7 +112,8 @@ pub fn run(args: &[String]) -> i32 { }) { Ok(cfg) => cfg, Err(err) => { - error(&err); + error!("{err}"); + return 1; } }; @@ -143,11 +145,12 @@ pub fn run(args: &[String]) -> i32 { ) { Ok(Some(ws)) => ws, Ok(None) => { - error("Workspace root has no members defined"); + error!("Workspace root has no members defined"); return 1; } Err(e) => { - error(&e); + error!("{e}"); + return 1; } }; @@ -159,9 +162,9 @@ pub fn run(args: &[String]) -> i32 { Some(m) => m, None => { if let Some(name) = &flags.workspace { - error(&format!("Workspace member '{name}' not found")); + error!("Workspace member '{name}' not found"); } else { - error("No workspace member to run (set `main = true` on one member)"); + error!("No workspace member to run (set `main = true` on one member)"); } return 1; } @@ -172,7 +175,8 @@ pub fn run(args: &[String]) -> i32 { }) { Ok(code) => code, Err(e) => { - error(&e); + error!("{e}"); + 1 } }; @@ -181,7 +185,7 @@ pub fn run(args: &[String]) -> i32 { match run_project(&root, &flags, None) { Ok(code) => code, Err(e) => { - error(&e); + error!("{e}"); 1 } } diff --git a/src/cli/test.rs b/src/cli/test.rs index 0d614c9..1efd968 100644 --- a/src/cli/test.rs +++ b/src/cli/test.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::cli::build; use crate::config::{FILE_DCR_TEST_H, FILE_TEST_C, flags}; use crate::core::build_config::Config; @@ -23,7 +25,6 @@ use crate::utils::build::{ get_string_with_profile, resolve_compiler, resolve_pkg_config_flags, }; use crate::utils::fs::{find_project_root, with_dir}; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, BOLD_RED, RESET, colored, printc}; use std::fs; use std::path::{Path, PathBuf}; @@ -60,25 +61,25 @@ pub fn test(args: &[String]) -> i32 { profile = arg.trim_start_matches("--"); continue; } - error("Unknown argument"); + error!("Unknown argument"); return 1; } let start_dir = match std::env::current_dir() { Ok(dir) => dir, Err(_) => { - error("Failed to determine current directory"); + error!("Failed to determine current directory"); return 1; } }; let root = match find_project_root(&start_dir) { Ok(Some(dir)) => dir, Ok(None) => { - error("dcr.toml file not found"); + error!("dcr.toml file not found"); return 1; } Err(_) => { - error("Failed to find project root"); + error!("Failed to find project root"); return 1; } }; @@ -87,7 +88,8 @@ pub fn test(args: &[String]) -> i32 { match with_dir(&root, ensure_test_header) { Ok(()) => {} Err(msg) => { - error(&msg); + error!("{msg}"); + return 1; } } @@ -96,7 +98,7 @@ pub fn test(args: &[String]) -> i32 { match with_dir(&root, || run_testsuite(profile)) { Ok(code) => code, Err(msg) => { - error(&msg); + error!("{msg}"); 1 } } diff --git a/src/cli/tree.rs b/src/cli/tree.rs index 5717c9b..ce9649a 100644 --- a/src/cli/tree.rs +++ b/src/cli/tree.rs @@ -15,8 +15,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build_config::Config; -use crate::utils::log::error; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc}; use std::collections::HashSet; use std::path::{Path, PathBuf}; @@ -40,7 +41,7 @@ pub fn tree(args: &[String]) -> i32 { let config = match Config::open("dcr.toml") { Ok(c) => c, Err(_) => { - error("dcr.toml not found in current directory"); + error!("dcr.toml not found in current directory"); return 1; } }; diff --git a/src/core/build_config.rs b/src/core/build_config.rs index e8ccd6b..d2070a9 100644 --- a/src/core/build_config.rs +++ b/src/core/build_config.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use serde::Deserialize; use std::collections::BTreeMap; use std::fs; @@ -334,35 +336,35 @@ impl Config { .map(str::trim) .filter(|s| !s.is_empty()); let Some(required) = required else { - crate::utils::log::warn(&format!( + warn!( "package.dcr-version is missing in {}. Add e.g. dcr-version = \"{tool}\" \ - so collaborators know which dcr this project targets \ - (written automatically by `dcr new` / `dcr init`).", - self.path.display() - )); + so collaborators know which dcr this project targets \ + (written automatically by `dcr new` / `dcr init`).", + self.path.display(), + ); return; }; match crate::utils::build::compare_semver(tool, required) { Some(std::cmp::Ordering::Less) => { - crate::utils::log::warn(&format!( + warn!( "this project requires dcr {required} (package.dcr-version), \ but you are running dcr {tool}. Some features may be missing or misbehave. \ Upgrade dcr (e.g. `dcr --update`) or lower package.dcr-version if intentional." - )); + ); } Some(std::cmp::Ordering::Greater) => { - crate::utils::log::warn(&format!( + warn!( "this project pins dcr {required} (package.dcr-version), \ - but you are running newer dcr {tool}. Config/defaults may be outdated. \ - Review the changelog and bump package.dcr-version when the project is verified." - )); + but you are running newer dcr {tool}. Config/defaults may be outdated. \ + Review the changelog and bump package.dcr-version when the project is verified.", + ); } Some(std::cmp::Ordering::Equal) => {} None => { - crate::utils::log::warn(&format!( - "package.dcr-version = \"{required}\" is not a valid semver (expected X.Y.Z); ignoring" - )); + warn!( + "package.dcr-version = \"{required}\" is not a valid semver (expected X.Y.Z); ignoring", + ); } } } diff --git a/src/main.rs b/src/main.rs index 0254792..d3dc23e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,19 +14,23 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::utils::log::error; mod cli; mod config; mod core; mod platform; +mod prelude; mod utils; +use prelude::*; + /// Main entry point for DCR, a Cargo-like C/C++ project manager. /// /// Collects command-line arguments via `std::env::args()` and dispatches to the /// appropriate subcommand handler. With fewer than two arguments, shows help and /// exits with code 0; otherwise exits with the handler's exit code. fn main() { + utils::log::init(); + let args: Vec = std::env::args().collect(); if args.len() < 2 { @@ -61,7 +65,7 @@ fn main() { "--help" => cli::help::help(), "--update" => cli::flag_update::flag_update(rest), _ => { - error("Unknown command or argument"); + error!("Unknown command or argument"); 1 } }; diff --git a/src/prelude.rs b/src/prelude.rs new file mode 100644 index 0000000..a1f87fc --- /dev/null +++ b/src/prelude.rs @@ -0,0 +1 @@ +pub use log::{error, warn}; diff --git a/src/utils/build.rs b/src/utils/build.rs index 8b716ec..d50e7f9 100644 --- a/src/utils/build.rs +++ b/src/utils/build.rs @@ -15,8 +15,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::prelude::*; + use crate::core::build_config::Config; -use crate::utils::log::warn; use std::path::{Path, PathBuf}; /// Version information parsed from a version string. @@ -251,10 +252,9 @@ pub fn normalize_target_os(target: &str) -> &str { "windows" => "x86_64-pc-windows-msvc", _ if target.contains('-') => target, _ => { - warn(&format!( - "Unknown target '{}', using as-is. Supported short names: linux, macos, windows", - target - )); + warn!( + "Unknown target '{target}', using as-is. Supported short names: linux, macos, windows" + ); target } } diff --git a/src/utils/log.rs b/src/utils/log.rs index 5726cb8..a029d37 100644 --- a/src/utils/log.rs +++ b/src/utils/log.rs @@ -15,17 +15,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::utils::text::{BOLD_RED, BOLD_YELLOW, colored}; +use env_logger::{Builder, WriteStyle}; +use log::{Level, LevelFilter}; +use owo_colors::OwoColorize; +use std::io::Write; -/// Logs an error message to the standard error stream. -/// -/// The message is prefixed with a red "error" label for visibility. -#[allow(dead_code)] -pub fn error(msg: &str) { - eprintln!("{}: {msg}", colored("error", BOLD_RED)); -} +// A function for initializing the logging lib with basic settings. +pub fn init() { + Builder::new() + .filter_level(LevelFilter::Warn) + .write_style(WriteStyle::Auto) + .format(|buf, record| { + let colored_lv = match record.level() { + Level::Error => record.level().red().to_string(), + Level::Warn => record.level().yellow().to_string(), + Level::Info => record.level().default_color().to_string(), + _ => record.level().purple().italic().to_string(), + }; -#[allow(dead_code)] -pub fn warn(msg: &str) { - eprintln!("{}: {msg}", colored("warn", BOLD_YELLOW)); + writeln!( + buf, + "{}: {}", + colored_lv.to_lowercase().bold(), + record.args(), + ) + }) + .init(); }