diff --git a/Cargo.lock b/Cargo.lock index 67e4730..a7227be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,22 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + [[package]] name = "bitflags" version = "1.2.1" @@ -18,6 +35,17 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "chrono" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" +dependencies = [ + "num-integer", + "num-traits", + "time", +] + [[package]] name = "filetime" version = "0.2.10" @@ -214,6 +242,12 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "lazy_format" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f389fd31a70d3b0f1d9d80e8f7a9366127fe5fb819f4d4dd21122a167352da8f" + [[package]] name = "lazy_static" version = "1.4.0" @@ -245,9 +279,13 @@ dependencies = [ name = "lolicron" version = "0.1.0" dependencies = [ + "chrono", "futures", + "lazy_format", "lazy_static", "notify", + "once_cell", + "recolored", "sexp", "tokio", ] @@ -330,6 +368,25 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num-integer" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.0" @@ -408,6 +465,17 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "recolored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1584c92dd8a87686229f766bb3a62d263a90c47c81e45a49f1a6d684a1b7968d" +dependencies = [ + "atty", + "lazy_static", + "winapi 0.3.9", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -446,6 +514,16 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "tokio" version = "0.2.22" diff --git a/Cargo.toml b/Cargo.toml index 09344e6..0968b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,8 @@ tokio = {version = "0.2", features=["time", "macros", "io-driver", "sync", "rt-c notify = "4.0" futures= "0.3" sexp = "1.1" -lazy_static="*" \ No newline at end of file +once_cell = "1.4" +lazy_static = "1.4" +lazy_format = "1.8" +recolored = "1.9.3" +chrono = "0.4" \ No newline at end of file diff --git a/src/context.rs b/src/context.rs index 2c4a179..ef24152 100644 --- a/src/context.rs +++ b/src/context.rs @@ -11,11 +11,7 @@ use tokio::{ task, }; -/// Command to interrupt an `Imouto` worker -#[derive(Debug)] -pub enum Command { - -} +use job::Command; /// The child worker for a `Context` interval or target. #[derive(Debug)] diff --git a/src/job.rs b/src/job.rs new file mode 100644 index 0000000..da1fa69 --- /dev/null +++ b/src/job.rs @@ -0,0 +1,19 @@ +use super::*; + +/// Command to interrupt an `Imouto` worker +#[derive(Debug, PartialEq,Eq,Hash)] +pub enum Command { + /// Ungraceful shutdown + Abort, + /// Graceful shutdown + Shutdown, + + /// Update interval + Reset(interval::Time), + + /// Full reload + Reload, + + /// Debug informations + Dump, +} diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..bad53ae --- /dev/null +++ b/src/log.rs @@ -0,0 +1,226 @@ +//! Global logging state + +use std::{ + fmt::{ + self, + Display, + }, + io::{ + self, + Write, + }, +}; +use once_cell::sync::OnceCell; + +/// Logging level +#[derive(PartialEq,Copy,Eq,Debug,Clone,Hash,Ord,PartialOrd)] +pub enum Level +{ + Silent, + Error, + Warn, + Info, + Debug, +} + +impl Default for Level +{ + #[inline] + fn default() -> Level + { + #[cfg(debug_assertions)] + return Level::Debug; + #[cfg(not(debug_assertions))] + return Level::Warn; + } +} + +impl std::fmt::Display for Level +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + use recolored::Colorize; + write!(f, "{}", match &self { + Self::Silent => "Fatal".bright_red().bold(), + Self::Error => "Error".red(), + Self::Warn => "Warning".yellow(), + Self::Info => "Info".normal(), + Self::Debug => "Debug".dimmed(), + }) + } +} + + +/// A logger that prints to stdout and stderr idk. +/// # TODO +/// Make this a trait and have variants that print to files and such +#[derive(Debug)] +pub struct Logger +{ + level: Level, + title: String, + use_local_time: bool, +} + +static INSTANCE: OnceCell = OnceCell::new(); + +impl Logger +{ + pub fn new(level: Level) -> Self + { + Self { + level, + title: String::new(), + use_local_time: false, + } + } + + #[inline] + pub fn global() -> &'static Logger + { + INSTANCE.get().expect("[logger] uninitialised") + } + + + fn initialise(level: Level) -> &'static Logger + { + INSTANCE.set(Logger::new(level)).expect("[logger] already initialised"); + Logger::global() + } + + pub fn println(&self, mut to: impl Write, level: Level, what: impl Display) -> io::Result<()> + { + //lol + enum Date { + Local(chrono::DateTime), + Utc(chrono::DateTime), + } + impl std::fmt::Display for Date + { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + match self { + Self::Local(l) => write!(f, "{}", l), + Self::Utc(l) => write!(f, "{}", l), + } + } + } + impl From> for Date + { + #[inline] + fn from(from: chrono::DateTime) -> Self + { + Self::Local(from) + } + } + + impl From> for Date + { + #[inline] + fn from(from: chrono::DateTime) -> Self + { + Self::Utc(from) + } + } + + + if self.level >= level { + let now: Date = if self.use_local_time { + chrono::offset::Local::now().into() + } else { + chrono::offset::Utc::now().into() + }; + + if self.title.len() > 0 { + write!(to, "{} [{}] <{}>: ", now, level, self.title)?; + } else { + write!(to, "{} [{}]: ", now, level)?; + } + writeln!(to, "{}", what)?; + } + Ok(()) + } +} + +#[macro_export] macro_rules! debug { + ($obj:expr) => { + { + let stdout = std::io::stdout(); + let stdout = stdout.lock(); + $crate::log::Logger::global().println(stdout, $crate::log::Level::Debug, $obj).expect("i/o error") + } + }; + ($fmt:literal, $($args:expr),*) => { + debug!(lazy_format::lazy_format!($fmt, $($args,)*)) + }; +} + +#[macro_export] macro_rules! info { + ($obj:expr) => { + { + let stdout = std::io::stdout(); + let stdout = stdout.lock(); + $crate::log::Logger::global().println(stdout, $crate::log::Level::Info, $obj).expect("i/o error") + } + }; + ($fmt:literal, $($args:expr),*) => { + info!(lazy_format::lazy_format!($fmt, $($args,)*)) + }; +} + + +#[macro_export] macro_rules! warn { + ($obj:expr) => { + { + let stderr = std::io::stderr(); + let stderr = stderr.lock(); + $crate::log::Logger::global().println(stderr, $crate::log::Level::Warn, $obj).expect("i/o error") + } + }; + ($fmt:literal, $($args:expr),*) => { + warn!(lazy_format::lazy_format!($fmt, $($args,)*)) + }; +} + +#[macro_export] macro_rules! error { + ($obj:expr) => { + { + let stderr = std::io::stderr(); + let stderr = stderr.lock(); + $crate::log::Logger::global().println(stderr, $crate::log::Level::Error, $obj).expect("i/o error") + } + }; + ($fmt:literal, $($args:expr),*) => { + error!(lazy_format::lazy_format!($fmt, $($args,)*)) + }; +} + +#[macro_export] macro_rules! fatal { + ($obj:expr) => { + { + let stdout = std::io::stdout(); + let stdout = stdout.lock(); + $crate::log::Logger::global().println(stdout, $crate::log::Level::Silent, $obj).expect("i/o error"); + + std::process::exit(-1) + } + }; + ($fmt:literal, $($args:expr),*) => { + error!(lazy_format::lazy_format!($fmt, $($args,)*)) + }; +} + +/// Initialise the global logger instance. If logging macros are called before this, they will panic. +#[inline] +pub fn init(level: Level) +{ + Logger::initialise(level); +} + +/// The global logger's level +#[inline] +pub fn level() -> &'static Level +{ + &Logger::global().level +} diff --git a/src/main.rs b/src/main.rs index f801a94..8a37933 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,11 +14,13 @@ use tokio::{ task, }; +mod log; + mod interval; mod config; -mod context; -mod live; +//mod context; +//mod live; async fn do_thing_every() -> Result<(mpsc::Sender<()>, task::JoinHandle<()>), Box> { @@ -55,12 +57,16 @@ async fn do_thing_every() -> Result<(mpsc::Sender<()>, task::JoinHandle<()>), Bo #[tokio::main] async fn main() -> Result<(), Box> { + log::init(Default::default()); + + debug!("Initialised"); + let (mut tx, h) = do_thing_every().await?; loop { time::delay_for(Duration::from_secs(6)).await; tx.send(()).await?; } - h.await; + h.await?; Ok(()) }