commit
3c355f54f2
11 changed files with 491 additions and 54 deletions
243
Cargo.lock
generated
243
Cargo.lock
generated
|
@ -38,6 +38,12 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "bpaf"
|
||||
version = "0.9.12"
|
||||
|
@ -75,7 +81,7 @@ dependencies = [
|
|||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -84,12 +90,53 @@ version = "0.8.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
|
@ -109,9 +156,14 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bpaf",
|
||||
"chrono",
|
||||
"deranged",
|
||||
"directories",
|
||||
"indexmap",
|
||||
"regex",
|
||||
"rgb",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"shell-words",
|
||||
"strum",
|
||||
"tracing",
|
||||
|
@ -150,6 +202,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
|||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -158,6 +211,12 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
|
@ -179,6 +238,16 @@ version = "0.2.155"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
|
@ -216,6 +285,12 @@ version = "1.19.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
@ -252,6 +327,17 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.5"
|
||||
|
@ -293,6 +379,53 @@ version = "1.0.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
|
@ -356,6 +489,26 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
|
@ -459,6 +612,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
|
@ -541,7 +700,31 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[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-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]]
|
||||
|
@ -550,28 +733,46 @@ version = "0.52.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_aarch64_gnullvm 0.52.5",
|
||||
"windows_aarch64_msvc 0.52.5",
|
||||
"windows_i686_gnu 0.52.5",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_i686_msvc 0.52.5",
|
||||
"windows_x86_64_gnu 0.52.5",
|
||||
"windows_x86_64_gnullvm 0.52.5",
|
||||
"windows_x86_64_msvc 0.52.5",
|
||||
]
|
||||
|
||||
[[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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[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.5"
|
||||
|
@ -584,24 +785,48 @@ version = "0.52.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[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.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[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.5"
|
||||
|
|
|
@ -16,10 +16,15 @@ ansi_colours = { version = "1.2.2", default-features = false }
|
|||
anyhow = { version = "1.0.86", default-features = false }
|
||||
bpaf = { version = "0.9.12", default-features = false }
|
||||
chrono = { version = "0.4.38", default-features = false }
|
||||
deranged = { version = "0.3.11", default-features = false }
|
||||
derive_more = { version = "1.0.0-beta.6", default-features = false }
|
||||
directories = { version = "5.0.1", default-features = false }
|
||||
indexmap = { version = "2.2.6", default-features = false }
|
||||
regex = { version = "1.10.5", default-features = false }
|
||||
rgb = { version = "0.8.37", default-features = false }
|
||||
serde = { version = "1.0.203", default-features = false }
|
||||
serde_json = { version = "1.0.118", default-features = false }
|
||||
serde_path_to_error = { version = "0.1.16", default-features = false }
|
||||
shell-words = { version = "1.1.0", default-features = false }
|
||||
strum = { version = "0.26.3", default-features = false }
|
||||
tracing = { version = "0.1.40", default-features = false }
|
||||
|
|
|
@ -14,10 +14,15 @@ default-run = "hyfetch"
|
|||
anyhow = { workspace = true, features = ["std"] }
|
||||
bpaf = { workspace = true, features = [] }
|
||||
chrono = { workspace = true, features = ["clock", "std"] }
|
||||
deranged = { workspace = true, features = ["serde", "std"] }
|
||||
# derive_more = { workspace = true, features = ["std"] }
|
||||
indexmap = { workspace = true, features = ["std"] }
|
||||
directories = { workspace = true, features = [] }
|
||||
indexmap = { workspace = true, features = ["serde", "std"] }
|
||||
regex = { workspace = true, features = ["perf", "std", "unicode"] }
|
||||
rgb = { workspace = true, features = [] }
|
||||
serde = { workspace = true, features = ["derive", "std"] }
|
||||
serde_json = { workspace = true, features = ["std"] }
|
||||
serde_path_to_error = { workspace = true, features = [] }
|
||||
shell-words = { workspace = true, features = ["std"] }
|
||||
strum = { workspace = true, features = ["derive", "std"] }
|
||||
tracing = { workspace = true, features = ["attributes", "std"] }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
use std::io::{self, IsTerminal};
|
||||
use std::fmt;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, ErrorKind, IsTerminal, Read};
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use chrono::Datelike;
|
||||
use directories::ProjectDirs;
|
||||
use hyfetch::cli_options::options;
|
||||
use hyfetch::models::Config;
|
||||
use hyfetch::neofetch_util::get_distro_ascii;
|
||||
use tracing::debug;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let options = options().fallback_to_usage().run();
|
||||
let options = options().run();
|
||||
|
||||
init_tracing_subsriber(options.debug).context("Failed to init tracing subscriber")?;
|
||||
|
||||
|
@ -25,25 +30,26 @@ fn main() -> Result<()> {
|
|||
|
||||
// TODO
|
||||
|
||||
// TODO
|
||||
// let config = if options.config {
|
||||
// create_config()
|
||||
// } else {
|
||||
// check_config(options.config_file)
|
||||
// };
|
||||
let config = if options.config {
|
||||
create_config(options.config_file).context("Failed to create config")?
|
||||
} else if let Some(config) =
|
||||
read_config(&options.config_file).context("Failed to read config")?
|
||||
{
|
||||
config
|
||||
} else {
|
||||
create_config(options.config_file).context("Failed to create config")?
|
||||
};
|
||||
|
||||
let now = chrono::Local::now();
|
||||
let show_pride_month = options.june
|
||||
|| now.month() == 6
|
||||
// TODO
|
||||
// && !config.pride_month_shown.contains(now.year())
|
||||
// && !june_path.is_file()
|
||||
&& io::stdout().is_terminal();
|
||||
let cache_path = ProjectDirs::from("", "", "hyfetch")
|
||||
.context("Failed to get base dirs")?
|
||||
.cache_dir()
|
||||
.to_owned();
|
||||
let june_path = cache_path.join(format!("animation-displayed-{}", now.year()));
|
||||
let show_pride_month =
|
||||
options.june || now.month() == 6 && !june_path.is_file() && io::stdout().is_terminal();
|
||||
|
||||
if show_pride_month
|
||||
// TODO
|
||||
// && !config.pride_month_disable
|
||||
{
|
||||
if show_pride_month && !config.pride_month_disable {
|
||||
// TODO
|
||||
// pride_month.start_animation();
|
||||
println!();
|
||||
|
@ -51,7 +57,11 @@ fn main() -> Result<()> {
|
|||
println!("(You can always view the animation again with `hyfetch --june`)");
|
||||
println!();
|
||||
|
||||
// TODO
|
||||
if !june_path.is_file() {
|
||||
fs::create_dir_all(cache_path).context("Failed to create cache dir")?;
|
||||
File::create(&june_path)
|
||||
.with_context(|| format!("Failed to create file {june_path:?}"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
@ -59,6 +69,51 @@ fn main() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads config from file.
|
||||
///
|
||||
/// Returns `None` if the config file does not exist.
|
||||
#[tracing::instrument(level = "debug")]
|
||||
fn read_config<P>(path: P) -> Result<Option<Config>>
|
||||
where
|
||||
P: AsRef<Path> + fmt::Debug,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
|
||||
let mut file = match File::open(path) {
|
||||
Ok(file) => file,
|
||||
Err(err) if err.kind() == ErrorKind::NotFound => {
|
||||
return Ok(None);
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(err).with_context(|| format!("Failed to open {path:?}"));
|
||||
},
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
file.read_to_string(&mut buf)
|
||||
.with_context(|| format!("Failed to read {path:?}"))?;
|
||||
|
||||
let deserializer = &mut serde_json::Deserializer::from_str(&buf);
|
||||
let config: Config = serde_path_to_error::deserialize(deserializer)
|
||||
.with_context(|| format!("Failed to parse {path:?}"))?;
|
||||
|
||||
debug!(?config, "read config");
|
||||
|
||||
Ok(Some(config))
|
||||
}
|
||||
|
||||
/// Creates config interactively.
|
||||
///
|
||||
/// The config is automatically stored to file.
|
||||
#[tracing::instrument(level = "debug")]
|
||||
fn create_config<P>(path: P) -> Result<Config>
|
||||
where
|
||||
P: AsRef<Path> + fmt::Debug,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn init_tracing_subsriber(debug: bool) -> Result<()> {
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
|
|
|
@ -5,6 +5,7 @@ use anyhow::Context;
|
|||
#[cfg(feature = "autocomplete")]
|
||||
use bpaf::ShellComp;
|
||||
use bpaf::{construct, long, OptionParser, Parser};
|
||||
use directories::BaseDirs;
|
||||
use strum::VariantNames;
|
||||
|
||||
use crate::presets::Preset;
|
||||
|
@ -13,11 +14,11 @@ use crate::types::{AnsiMode, Backend};
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Options {
|
||||
pub config: bool,
|
||||
pub config_file: Option<PathBuf>,
|
||||
pub config_file: PathBuf,
|
||||
pub preset: Option<Preset>,
|
||||
pub mode: Option<AnsiMode>,
|
||||
pub backend: Option<Backend>,
|
||||
pub backend_args: Vec<String>,
|
||||
pub args: Vec<String>,
|
||||
pub colors_scale: Option<f32>,
|
||||
pub colors_set_lightness: Option<f32>,
|
||||
pub colors_use_overlay: bool,
|
||||
|
@ -37,7 +38,16 @@ pub fn options() -> OptionParser<Options> {
|
|||
.argument("CONFIG_FILE");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let config_file = config_file.complete_shell(ShellComp::Nothing);
|
||||
let config_file = config_file.optional();
|
||||
let config_file = config_file
|
||||
.fallback_with(|| {
|
||||
Ok::<_, anyhow::Error>(
|
||||
BaseDirs::new()
|
||||
.context("Failed to get base dirs")?
|
||||
.config_dir()
|
||||
.join("hyfetch.json"),
|
||||
)
|
||||
})
|
||||
.debug_fallback();
|
||||
let preset = long("preset")
|
||||
.short('p')
|
||||
.help(&*format!(
|
||||
|
@ -49,7 +59,11 @@ PRESET={{{}}}",
|
|||
#[cfg(feature = "autocomplete")]
|
||||
let preset = preset.complete(complete_preset);
|
||||
let preset = preset
|
||||
.parse(|s| Preset::from_str(&s).with_context(|| format!("Failed to parse preset `{s}`")))
|
||||
.parse(|s| {
|
||||
Preset::from_str(&s).with_context(|| {
|
||||
format!("PRESET should be one of {{{}}}", Preset::VARIANTS.join(","))
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let mode = long("mode")
|
||||
.short('m')
|
||||
|
@ -62,7 +76,11 @@ MODE={{{}}}",
|
|||
#[cfg(feature = "autocomplete")]
|
||||
let mode = mode.complete(complete_mode);
|
||||
let mode = mode
|
||||
.parse(|s| AnsiMode::from_str(&s).with_context(|| format!("Failed to parse mode `{s}`")))
|
||||
.parse(|s| {
|
||||
AnsiMode::from_str(&s).with_context(|| {
|
||||
format!("MODE should be one of {{{}}}", AnsiMode::VARIANTS.join(","))
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let backend = long("backend")
|
||||
.short('b')
|
||||
|
@ -75,12 +93,19 @@ BACKEND={{{}}}",
|
|||
#[cfg(feature = "autocomplete")]
|
||||
let backend = backend.complete(complete_backend);
|
||||
let backend = backend
|
||||
.parse(|s| Backend::from_str(&s).with_context(|| format!("Failed to parse backend `{s}`")))
|
||||
.parse(|s| {
|
||||
Backend::from_str(&s).with_context(|| {
|
||||
format!(
|
||||
"BACKEND should be one of {{{}}}",
|
||||
Backend::VARIANTS.join(",")
|
||||
)
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let backend_args = long("args")
|
||||
let args = long("args")
|
||||
.help("Additional arguments pass-through to backend")
|
||||
.argument::<String>("ARGS")
|
||||
.parse(|s| shell_words::split(&s).context("Failed to split args for shell"))
|
||||
.parse(|s| shell_words::split(&s).context("ARGS should be valid command-line arguments"))
|
||||
.fallback(vec![]);
|
||||
let colors_scale = long("c-scale")
|
||||
.help("Lighten colors by a multiplier")
|
||||
|
@ -125,7 +150,7 @@ BACKEND={{{}}}",
|
|||
preset,
|
||||
mode,
|
||||
backend,
|
||||
backend_args,
|
||||
args,
|
||||
colors_scale,
|
||||
colors_set_lightness,
|
||||
colors_use_overlay,
|
||||
|
|
|
@ -1,5 +1,22 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use deranged::RangedU8;
|
||||
use rgb::RGB8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// An indexed color where the color palette is the set of colors used in
|
||||
/// neofetch ascii art.
|
||||
///
|
||||
/// The range of valid values as supported in neofetch is `1`-`6`.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
|
||||
pub struct NeofetchAsciiIndexedColor(RangedU8<1, 6>);
|
||||
|
||||
/// An indexed color where the color palette is the set of unique colors in a
|
||||
/// preset.
|
||||
///
|
||||
/// The range of valid values depends on the number of unique colors in a
|
||||
/// certain preset.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
|
||||
pub struct PresetIndexedColor(usize);
|
||||
|
||||
pub trait FromHex {
|
||||
/// Creates color from hex code.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod cli_options;
|
||||
pub mod color_util;
|
||||
pub mod distros;
|
||||
pub mod models;
|
||||
pub mod neofetch_util;
|
||||
pub mod presets;
|
||||
pub mod types;
|
||||
|
|
71
crates/hyfetch/src/models.rs
Normal file
71
crates/hyfetch/src/models.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::neofetch_util::ColorAlignment;
|
||||
use crate::presets::Preset;
|
||||
use crate::types::{AnsiMode, Backend, LightDark};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub preset: Preset,
|
||||
pub mode: AnsiMode,
|
||||
pub light_dark: LightDark,
|
||||
pub lightness: Option<f32>,
|
||||
pub color_align: ColorAlignment,
|
||||
pub backend: Backend,
|
||||
#[serde(with = "self::args_serde_with")]
|
||||
pub args: Vec<String>,
|
||||
pub distro: Option<String>,
|
||||
pub pride_month_disable: bool,
|
||||
}
|
||||
|
||||
mod args_serde_with {
|
||||
use std::fmt;
|
||||
|
||||
use serde::de::{self, value, Deserialize, Deserializer, SeqAccess, Visitor};
|
||||
use serde::ser::Serializer;
|
||||
|
||||
pub(super) fn serialize<S>(value: &Vec<String>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&shell_words::join(value))
|
||||
}
|
||||
|
||||
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct StringOrVec;
|
||||
|
||||
impl<'de> Visitor<'de> for StringOrVec {
|
||||
type Value = Vec<String>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("string or list of strings")
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
shell_words::split(s).map_err(de::Error::custom)
|
||||
}
|
||||
|
||||
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(StringOrVec)
|
||||
}
|
||||
}
|
|
@ -4,14 +4,35 @@ use std::ffi::OsStr;
|
|||
use std::os::unix::process::ExitStatusExt as _;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::sync::OnceLock;
|
||||
use std::{env, fmt};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use indexmap::IndexMap;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::color_util::{NeofetchAsciiIndexedColor, PresetIndexedColor};
|
||||
use crate::distros::Distro;
|
||||
|
||||
static NEOFETCH_COLOR_RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "lowercase", tag = "mode")]
|
||||
pub enum ColorAlignment {
|
||||
Horizontal {
|
||||
fore_back: Option<(NeofetchAsciiIndexedColor, NeofetchAsciiIndexedColor)>,
|
||||
},
|
||||
Vertical {
|
||||
fore_back: Option<(NeofetchAsciiIndexedColor, NeofetchAsciiIndexedColor)>,
|
||||
},
|
||||
Custom {
|
||||
#[serde(rename = "custom_colors")]
|
||||
colors: IndexMap<NeofetchAsciiIndexedColor, PresetIndexedColor>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Gets the absolute path of the neofetch command.
|
||||
pub fn get_command_path() -> Result<PathBuf> {
|
||||
if let Ok(workspace_dir) = env::var("CARGO_WORKSPACE_DIR") {
|
||||
|
@ -72,13 +93,16 @@ where
|
|||
}
|
||||
|
||||
/// Gets distro ascii width and height, ignoring color code.
|
||||
pub fn ascii_size<S>(asc: S, neofetch_color_re: &Regex) -> (u8, u8)
|
||||
pub fn ascii_size<S>(asc: S) -> (u8, u8)
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let asc = asc.as_ref();
|
||||
|
||||
let Some(width) = neofetch_color_re
|
||||
let Some(width) = NEOFETCH_COLOR_RE
|
||||
.get_or_init(|| {
|
||||
Regex::new(r"\$\{c[0-9]\}").expect("neofetch color regex should not be invalid")
|
||||
})
|
||||
.replace_all(asc, "")
|
||||
.split('\n')
|
||||
.map(|line| line.len())
|
||||
|
@ -98,14 +122,11 @@ where
|
|||
{
|
||||
let asc = asc.as_ref();
|
||||
|
||||
let neofetch_color_re =
|
||||
Regex::new(r"\$\{c[0-9]\}").expect("neofetch color regex should not be invalid");
|
||||
let (w, _) = ascii_size(asc);
|
||||
|
||||
let (w, _) = ascii_size(asc, &neofetch_color_re);
|
||||
|
||||
let mut buf = "".to_owned();
|
||||
let mut buf = String::new();
|
||||
for line in asc.split('\n') {
|
||||
let (line_w, _) = ascii_size(line, &neofetch_color_re);
|
||||
let (line_w, _) = ascii_size(line);
|
||||
let pad = " ".repeat((w - line_w) as usize);
|
||||
buf.push_str(&format!("{line}{pad}\n"))
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ use std::iter;
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use indexmap::IndexSet;
|
||||
use rgb::RGB8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{EnumString, VariantNames};
|
||||
|
||||
use crate::color_util::FromHex;
|
||||
|
||||
#[derive(Clone, Hash, Debug, EnumString, VariantNames)]
|
||||
#[derive(Clone, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum Preset {
|
||||
Abrosexual,
|
||||
|
@ -44,13 +46,16 @@ pub enum Preset {
|
|||
Genderfaun,
|
||||
Genderfluid,
|
||||
Genderflux,
|
||||
#[serde(rename = "gendernonconforming1")]
|
||||
#[strum(serialize = "gendernonconforming1")]
|
||||
GenderNonconforming1,
|
||||
#[serde(rename = "gendernonconforming2")]
|
||||
#[strum(serialize = "gendernonconforming2")]
|
||||
GenderNonconforming2,
|
||||
Gendervoid,
|
||||
Girlflux,
|
||||
Greygender,
|
||||
#[serde(alias = "biromantic2")]
|
||||
Greysexual,
|
||||
Gynesexual,
|
||||
Intergender,
|
||||
|
@ -79,7 +84,7 @@ pub enum Preset {
|
|||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct ColorProfile {
|
||||
colors: Vec<RGB8>,
|
||||
pub colors: Vec<RGB8>,
|
||||
}
|
||||
|
||||
impl Preset {
|
||||
|
@ -409,10 +414,6 @@ impl ColorProfile {
|
|||
Ok(Self::new(weighted_colors))
|
||||
}
|
||||
|
||||
pub fn colors(&self) -> &[RGB8] {
|
||||
&self.colors
|
||||
}
|
||||
|
||||
/// Creates another color profile with only the unique colors.
|
||||
pub fn unique_colors(&self) -> Self {
|
||||
let unique_colors = self.colors.iter().collect::<IndexSet<_>>();
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::{EnumString, VariantNames};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, EnumString, VariantNames)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum AnsiMode {
|
||||
#[serde(rename = "8bit")]
|
||||
#[strum(serialize = "8bit")]
|
||||
Ansi256,
|
||||
Rgb,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, EnumString, VariantNames)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum LightDark {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum Backend {
|
||||
Qwqfetch,
|
||||
|
|
Loading…
Reference in a new issue