start working on a cli app #7

Merged
schrottkatze merged 12 commits from :app into main 2024-01-20 19:09:52 +00:00
3 changed files with 357 additions and 46 deletions
Showing only changes of commit 4788278d86 - Show all commits

240
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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.
multisamplednight marked this conversation as resolved Outdated

Might want to streamline those two, in order to avoid accidentally checking only one of them in future.

The figment crate might be worth looking at in that case.

Might want to streamline those two, in order to avoid accidentally checking only one of them in future. The `figment` crate might be worth looking at in that case.

i'd prefer to try at least to some degree reduce dependencies, but i'll work on something like that then

i'd prefer to try at least to some degree reduce dependencies, but i'll work on something like that then

You don't need to use figment. Custom merge logic works fine, too.

You don't _need_ to use `figment`. Custom merge logic works fine, too.
#[arg(short, long)]
pub config_file: Option<PathBuf>,
#[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<Configs<'_>> {
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<PathBuf>) -> 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();
}
}