diff --git a/.harper-dictionary.txt b/.harper-dictionary.txt index 2fa5906..077da36 100644 --- a/.harper-dictionary.txt +++ b/.harper-dictionary.txt @@ -1,5 +1,8 @@ Implementers Multi-Device +OS PKM clippy +dir +env eyre diff --git a/Cargo.lock b/Cargo.lock index 38d1335..aa3e50f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -512,7 +512,6 @@ dependencies = [ "directories", "futures", "human-panic", - "lazy_static", "ratatui", "serde", "signal-hook 0.4.3", @@ -520,6 +519,8 @@ dependencies = [ "tokio", "tokio-util", "tracing", + "tracing-error", + "tracing-subscriber", ] [[package]] @@ -933,6 +934,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.8.0" @@ -1013,6 +1023,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "num-conv" version = "0.2.0" @@ -1960,15 +1979,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 74dbe2a..b874990 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,5 +56,6 @@ tokio = { version = "1.50.0", features = ["full"] } tokio-util = "0.7.18" signal-hook = "0.4.3" strum = { version = "0.28.0", features = ["derive"] } -lazy_static = "1.5.0" directories = "6.0.0" +tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } +tracing-error = "0.2.1" diff --git a/src/config.rs b/src/config.rs index e7af62d..64bc11b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,19 +1,20 @@ use directories::ProjectDirs; -use lazy_static::lazy_static; use serde::Deserialize; use std::{env, path::PathBuf, sync::LazyLock}; -// #[expect(dead_code)] -static PROJECT_NAME: LazyLock = LazyLock::new(|| env!("CARGO_CRATE_NAME").to_uppercase()); +/// Project Name: Filaments +pub static PROJECT_NAME: LazyLock = + LazyLock::new(|| env!("CARGO_CRATE_NAME").to_uppercase()); -#[expect(dead_code)] -static DATA_FOLDER: LazyLock> = LazyLock::new(|| { +/// The OS-agnostic data directory for the project. +pub static DATA_DIRECTORY: LazyLock> = LazyLock::new(|| { env::var(format!("{}_DATA", PROJECT_NAME.clone())) .ok() .map(PathBuf::from) }); -#[expect(dead_code)] -static CONFIG_FOLDER: LazyLock> = LazyLock::new(|| { + +/// The OS-agnostic config directory for the project. +pub static CONFIG_DIRECTORY: LazyLock> = LazyLock::new(|| { env::var(format!("{}_CONFIG", PROJECT_NAME.clone())) .ok() .map(PathBuf::from) @@ -47,26 +48,23 @@ impl Config { /// Returns the path to the OS-agnostic data directory. pub fn get_data_dir() -> PathBuf { - let directory = if let Some(s) = DATA_FOLDER.clone() { - s - } else if let Some(proj_dirs) = project_directory() { - proj_dirs.data_local_dir().to_path_buf() - } else { - PathBuf::from(".").join(".data") - }; - directory + DATA_DIRECTORY.clone().unwrap_or_else(|| { + project_directory().map_or_else( + || PathBuf::from(".").join(".data"), + |proj_dirs| proj_dirs.data_local_dir().to_path_buf(), + ) + }) } /// Returns the path to the OS-agnostic config directory. +#[expect(dead_code)] pub fn get_config_dir() -> PathBuf { - let directory = if let Some(s) = CONFIG_FOLDER.clone() { - s - } else if let Some(proj_dirs) = project_directory() { - proj_dirs.config_local_dir().to_path_buf() - } else { - PathBuf::from(".").join(".config") - }; - directory + CONFIG_DIRECTORY.clone().unwrap_or_else(|| { + project_directory().map_or_else( + || PathBuf::from(".").join(".config"), + |proj_dirs| proj_dirs.config_local_dir().to_path_buf(), + ) + }) } fn project_directory() -> Option { diff --git a/src/logging.rs b/src/logging.rs new file mode 100644 index 0000000..f709dd0 --- /dev/null +++ b/src/logging.rs @@ -0,0 +1,52 @@ +use std::{ + fs::{File, create_dir_all}, + sync::LazyLock, +}; + +use color_eyre::eyre::Result; +use tracing::Level; +use tracing_error::ErrorLayer; +use tracing_subscriber::{EnvFilter, Layer, fmt, layer::SubscriberExt, util::SubscriberInitExt}; + +use crate::config; + +/// The user-set log level if it exists. +pub static LOG_LEVEL_ENV: LazyLock = + LazyLock::new(|| format!("{}_LOG_LEVEL", config::PROJECT_NAME.clone())); + +/// The logfile name set by our package name. +pub static LOG_FILE: LazyLock = LazyLock::new(|| format!("{}.log", env!("CARGO_PKG_NAME"))); + +/// Initializes the logger, which writes logs to a `log_file` in the data dir. +/// +/// NOTE: log level is configurable via the `RUST_LOG` env var or the +/// `FILAMENTS_LOG_LEVEL` env var +pub fn init() -> Result<()> { + let directory = config::get_data_dir(); + + create_dir_all(&directory)?; + + let log_path = directory.join(LOG_FILE.clone()); + let log_file = File::create(log_path)?; + + let env_filter = EnvFilter::builder().with_default_directive(Level::INFO.into()); + + // If `RUST_LOG` is set, use that as default,, or use value of `LOG_ENV` variable. + let env_filter = env_filter + .try_from_env() + .or_else(|_| env_filter.with_env_var(LOG_LEVEL_ENV.clone()).from_env())?; + + let file_subscriber = fmt::layer() + .with_file(true) + .with_line_number(true) + .with_writer(log_file) + .with_target(false) + .with_ansi(false) + .with_filter(env_filter); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .try_init()?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index c19fa4e..fa44d78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,13 @@ mod components; mod config; mod errors; +mod logging; mod signal; mod tui; fn main() -> color_eyre::Result<()> { errors::init()?; + logging::init()?; Ok(()) }