diff --git a/Cargo.lock b/Cargo.lock index 7e1aaf8..091f8a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -53,7 +53,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -62,9 +62,12 @@ version = "0.1.0" dependencies = [ "ariadne", "clap", + "dirs", + "owo-colors", "ron", "serde", "serde_json", + "time", ] [[package]] @@ -226,6 +229,36 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "either" version = "1.9.0" @@ -285,6 +318,17 @@ dependencies = [ "spin", ] +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gif" version = "0.12.0" @@ -350,6 +394,23 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + [[package]] name = "lock_api" version = "0.4.11" @@ -400,6 +461,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "owo-colors" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" + [[package]] name = "pl-cli" version = "0.1.0" @@ -422,6 +504,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.70" @@ -469,6 +557,26 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "ron" version = "0.8.1" @@ -570,6 +678,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tiff" version = "0.9.0" @@ -581,6 +709,26 @@ dependencies = [ "weezl", ] +[[package]] +name = "time" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +dependencies = [ + "deranged", + "libc", + "num_threads", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -599,19 +747,49 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "weezl" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -620,51 +798,93 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.0" diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index 4f05ebc..0325fc1 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -6,8 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { workspace = true, features = [ "derive" ] } +clap = { workspace = true, features = [ "derive", "env" ] } serde = { workspace = true, features = [ "derive" ] } ron = { workspace = true } serde_json = { workspace = true } ariadne = "0.4" +time = { version = "0.3", features = [ "local-offset" ] } +dirs = "5" +owo-colors = "4" diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index b5de824..6fec037 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,48 +1,124 @@ -use crate::{config::Configs, error_reporting::report_serde_json_err}; +use clap::Parser; +use cli::Args; +use welcome_msg::print_startup_msg; + +use crate::config::Configs; mod cli { - use clap::{Parser, Subcommand}; + use std::path::PathBuf; + + use clap::Parser; #[derive(Parser)] - struct Args { - #[command(subcommand)] - command: Command, + pub(crate) struct Args { + /// Read this config file. + #[arg(short, long)] + pub config_file: Option, + #[arg(long, env = "NO_STARTUP_MESSAGE", default_value = "false")] + pub no_startup_message: bool, } - - #[derive(Clone, Subcommand)] - enum Command {} } mod config { + use std::{ + fs, + path::{Path, PathBuf}, + process, + }; + use serde::{Deserialize, Serialize}; + use crate::error_reporting::{report_serde_json_err, report_serde_ron_err}; + #[derive(Debug, Serialize, Deserialize)] - pub struct Configs<'a> { - example_value: i32, - example_string: &'a str, + pub struct Configs { + #[serde(default = "default_example_value")] + pub example_value: i32, + #[serde(default = "default_no_startup_msg")] + pub no_startup_message: bool, } - impl Configs<'_> { - pub fn read_json(config_text: &str) -> serde_json::Result> { - serde_json::from_str(config_text) + /// what the fuck serde why do i need this + fn default_example_value() -> i32 { + 43 + } + fn default_no_startup_msg() -> bool { + false + } + + impl Configs { + pub fn read(custom_path: Option) -> Self { + use owo_colors::OwoColorize; + let p = match custom_path { + Some(p) => p, + None => { + let config_path = dirs::config_dir().expect("config dir should exist"); + + let ron_path = config_path.with_file_name("config.ron"); + let json_path = config_path.with_file_name("config.json"); + + if Path::new(&ron_path).exists() { + ron_path + } else if Path::new(&json_path).exists() { + json_path + } else { + eprintln!("{}: couldn't find config file", "Fatal error".red()); + process::exit(1) + } + } + }; + + match p.extension().map(|v| v.to_str().unwrap()) { + Some("ron") => Self::read_json(&fs::read_to_string(p).unwrap()), + Some("json") => Self::read_ron(&fs::read_to_string(p).unwrap()), + None | Some(_) => { + eprintln!( + "{}: couldn't determine config file type", + "Fatal error".red() + ); + process::exit(1) + } + } + } + pub fn read_json(config_text: &str) -> Configs { + match serde_json::from_str(config_text) { + Ok(c) => c, + Err(e) => report_serde_json_err(config_text, e), + } + } + + pub fn read_ron(config_text: &str) -> Configs { + match ron::from_str(config_text) { + Ok(c) => c, + Err(e) => report_serde_ron_err(config_text, e), + } } } } mod error_reporting { - use std::{ops::Range, process}; + use std::process; - use ariadne::{Report, Source}; + use ron::error::Position; pub fn report_serde_json_err(src: &str, err: serde_json::Error) -> ! { - use ariadne::{Color, ColorGenerator, Fmt, Label, Report, ReportKind, Source}; - let offset = try_reconstruct_loc(src, err.line(), err.column()); + report_serde_err(src, err.line(), err.column(), err.to_string()) + } + + pub fn report_serde_ron_err(src: &str, err: ron::error::SpannedError) -> ! { + let Position { line, col } = err.position; + report_serde_err(src, line, col, err.to_string()) + } + + pub fn report_serde_err(src: &str, line: usize, col: usize, msg: String) -> ! { + use ariadne::{Label, Report, Source}; + let offset = try_reconstruct_loc(src, line, col); Report::build(ariadne::ReportKind::Error, "test", offset) .with_label( Label::new(("test", offset..offset)).with_message("Something went wrong here!"), ) - .with_message(err.to_string()) + .with_message(msg) .with_note( "We'd like to give better errors, but serde errors are horrible to work with...", ) @@ -54,25 +130,37 @@ mod error_reporting { fn try_reconstruct_loc(src: &str, line_nr: usize, col_nr: usize) -> usize { let (line_nr, col_nr) = (line_nr - 1, col_nr - 1); - src.lines().enumerate().fold(0, |acc, (i, line)| { - if i < line_nr { - acc + line.len() - } else if i == line_nr { - acc + col_nr - } else { - acc - } - }) + src.lines() + .enumerate() + .fold(0, |acc, (i, line)| match i.cmp(&line_nr) { + std::cmp::Ordering::Less => acc + line.len() + 1, + std::cmp::Ordering::Equal => acc + col_nr, + std::cmp::Ordering::Greater => acc, + }) + } +} + +mod welcome_msg { + use time::{Month, OffsetDateTime}; + + pub fn print_startup_msg() { + // now or fallback to utc + let now = OffsetDateTime::now_local().unwrap_or_else(|_| OffsetDateTime::now_utc()); + + if now.month() == Month::June { + println!("Hello, thanks for using iOwO and happy pride month!"); + println!("Why pride month is important in {}", now.year()); + } else { + println!("Hello, thanks for using iOwO! :3"); + } } } fn main() { - const TEST_JSON_CONFIG: &str = "{ \"example_value\": 42, \"example_string\": \"meow\" }"; - const TEST_JSON_CONFIG_BROKEN: &str = "{ - \"example_value\": \"42\", - \"example_string\": \"meow\" -}"; + let args = Args::parse(); + let cfg = Configs::read(args.config_file); - dbg!(Configs::read_json(TEST_JSON_CONFIG_BROKEN) - .map_err(|e| report_serde_json_err(TEST_JSON_CONFIG_BROKEN, e))); + if !(args.no_startup_message || cfg.no_startup_message) { + print_startup_msg(); + } }