Parse CLI options, including presets

This commit is contained in:
Teoh Han Hui 2024-06-26 08:33:06 +08:00
parent 7534371b05
commit bf2c3c51d4
No known key found for this signature in database
GPG key ID: D43E2BABAF97DCAE
12 changed files with 1043 additions and 2 deletions

71
.editorconfig Normal file
View file

@ -0,0 +1,71 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 4
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.csv]
trim_trailing_whitespace = false
[*.js]
indent_style = space
indent_size = 4
[*.json]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
[*.py]
indent_style = space
indent_size = 4
[*.rs]
indent_style = space
indent_size = 4
[*.sh]
indent_style = space
indent_size = 4
[*.toml]
indent_style = space
indent_size = 4
[*.{yaml,yml}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[.github/{actions,workflows}/**/*.yml]
indent_style = space
indent_size = 2
[Cargo.toml]
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab
indent_size = 4
[neofetch]
indent_style = space
indent_size = 4
[package.json]
indent_style = space
indent_size = 2

19
.gitattributes vendored
View file

@ -1,2 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
* text=auto eol=lf
*.csv text eol=lf
*.js text eol=lf
*.json text eol=lf
*.md text eol=lf
*.py text eol=lf
*.rs text eol=lf
*.sh text eol=lf
*.toml text eol=lf
*.txt text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
Cargo.lock text eol=lf merge=binary
Makefile text eol=lf
MANIFEST.in text eol=lf
neofetch text eol=lf

299
Cargo.lock generated Normal file
View file

@ -0,0 +1,299 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "bpaf"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3280efcf6d66bc77c2cf9b67dc8acee47a217d9be67dd590b3230dffe663724d"
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "env_filter"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
dependencies = [
"log",
]
[[package]]
name = "env_logger"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyfetch"
version = "1.4.11"
dependencies = [
"anyhow",
"bpaf",
"env_logger",
"indexmap",
"log",
"rgb",
"strum",
]
[[package]]
name = "indexmap"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rgb"
version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8"
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
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_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[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.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[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.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[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.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

23
Cargo.toml Normal file
View file

@ -0,0 +1,23 @@
[workspace]
resolver = "2"
members = ["crates/*"]
[workspace.package]
version = "1.4.11"
authors = ["Azalea Gui <azalea@hydev.org>"]
edition = "2021"
rust-version = "1.75.0"
description = "Neofetch with LGBTQ+ pride flags!"
repository = "https://github.com/hykilpikonna/hyfetch"
license = "MIT"
[workspace.dependencies]
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 }
derive_more = { version = "1.0.0-beta.6", default-features = false }
env_logger = { version = "0.11.3", default-features = false }
indexmap = { version = "2.2.6", default-features = false }
log = { version = "0.4.21", default-features = false }
rgb = { version = "0.8.37", default-features = false }
strum = { version = "0.26.3", default-features = false }

24
crates/hyfetch/Cargo.toml Normal file
View file

@ -0,0 +1,24 @@
[package]
name = "hyfetch"
version = { workspace = true }
authors = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
description = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
[dependencies]
# ansi_colours = { workspace = true, features = ["rgb"] }
anyhow = { workspace = true, features = ["std"] }
bpaf = { workspace = true, features = [] }
# derive_more = { workspace = true, features = ["std"] }
env_logger = { workspace = true, features = ["auto-color", "humantime", "unstable-kv"] }
indexmap = { workspace = true, features = ["std"] }
log = { workspace = true, features = ["kv"] }
rgb = { workspace = true, features = [] }
strum = { workspace = true, features = ["derive", "std"] }
[features]
default = ["autocomplete"]
autocomplete = ["bpaf/autocomplete"]

View file

@ -0,0 +1,14 @@
use anyhow::Result;
use hyfetch::cli_options::options;
use log::debug;
fn main() -> Result<()> {
env_logger::init();
let options = options().fallback_to_usage().run();
debug!(options:?; "CLI options");
// TODO
Ok(())
}

View file

@ -0,0 +1,111 @@
use std::path::PathBuf;
use std::str::FromStr;
#[cfg(feature = "autocomplete")]
use bpaf::ShellComp;
use bpaf::{construct, long, OptionParser, Parser};
use strum::VariantNames;
use crate::presets::Preset;
use crate::types::AnsiMode;
#[derive(Clone, Debug)]
pub struct Options {
pub config: bool,
pub config_file: Option<PathBuf>,
pub preset: Option<Preset>,
pub mode: Option<AnsiMode>,
// pub backend: Option<Backend>,
// pub backend_args: Option<String>,
// pub colors_scale: Option<f32>,
// pub colors_set_lightness: Option<f32>,
// pub colors_use_overlay: bool,
// pub june: bool,
// pub debug: bool,
// pub test_distro: Option<String>,
// pub ascii_file: Option<PathBuf>,
// pub test_print: bool,
// pub ask_exit: bool,
}
pub fn options() -> OptionParser<Options> {
let config = long("config").short('c').help("Configure hyfetch").switch();
let config_file = long("config-file")
.short('C')
.help("Use another config file")
.argument("CONFIG_FILE");
#[cfg(feature = "autocomplete")]
let config_file = config_file.complete_shell(ShellComp::Nothing);
let config_file = config_file.optional();
let preset = long("preset")
.short('p')
.help(&*format!(
"Use preset
PRESET={{{}}}",
Preset::VARIANTS.join(",")
))
.argument::<String>("PRESET");
#[cfg(feature = "autocomplete")]
let preset = preset.complete(complete_preset);
let preset = preset.parse(|s| Preset::from_str(&s)).optional();
let mode = long("mode")
.short('m')
.help(&*format!(
"Color mode
MODE={{{}}}",
AnsiMode::VARIANTS.join(",")
))
.argument::<String>("MODE");
#[cfg(feature = "autocomplete")]
let mode = mode.complete(complete_mode);
let mode = mode.parse(|s| AnsiMode::from_str(&s)).optional();
// TODO
construct!(Options {
config,
config_file,
preset,
mode,
// TODO
})
.to_options()
.version(env!("CARGO_PKG_VERSION"))
}
#[cfg(feature = "autocomplete")]
fn complete_preset(input: &String) -> Vec<(String, Option<String>)> {
Preset::VARIANTS
.iter()
.filter_map(|&name| {
if name.starts_with(input) {
Some((name.to_owned(), None))
} else {
None
}
})
.collect::<Vec<_>>()
}
#[cfg(feature = "autocomplete")]
fn complete_mode(input: &String) -> Vec<(String, Option<String>)> {
AnsiMode::VARIANTS
.iter()
.filter_map(|&name| {
if name.starts_with(input) {
Some((name.to_owned(), None))
} else {
None
}
})
.collect::<Vec<_>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_options() {
options().check_invariants(false)
}
}

View file

@ -0,0 +1,32 @@
use anyhow::{anyhow, Context, Result};
use rgb::RGB8;
pub trait FromHex {
/// Creates color from hex code.
fn from_hex<S>(hex: S) -> Result<RGB8>
where
S: AsRef<str>;
}
impl FromHex for RGB8 {
fn from_hex<S>(hex: S) -> Result<RGB8>
where
S: AsRef<str>,
{
let hex = hex.as_ref();
let hex = hex.strip_prefix('#').unwrap_or(hex);
if hex.len() != 6 {
Err(anyhow!("invalid length for hex color"))?;
}
let r =
u8::from_str_radix(&hex[0..2], 16).context("Failed to parse hex color component")?;
let g =
u8::from_str_radix(&hex[2..4], 16).context("Failed to parse hex color component")?;
let b =
u8::from_str_radix(&hex[4..6], 16).context("Failed to parse hex color component")?;
Ok(RGB8::new(r, g, b))
}
}

View file

@ -0,0 +1,4 @@
pub mod cli_options;
pub mod color_util;
pub mod presets;
pub mod types;

View file

@ -0,0 +1,421 @@
use std::iter;
use anyhow::{anyhow, Context, Result};
use indexmap::IndexSet;
use rgb::RGB8;
use strum::{EnumString, VariantNames};
use crate::color_util::FromHex;
#[derive(Clone, Hash, Debug, EnumString, VariantNames)]
#[strum(serialize_all = "kebab-case")]
pub enum Preset {
Abrosexual,
Agender,
Akiosexual,
Androsexual,
Aroace1,
Aroace2,
Aroace3,
Aromantic,
Asexual,
Autoromantic,
Autosexual,
/// Colors from Gilbert Baker's original 1978 flag design
Baker,
/// Meme flag
Beiyang,
Bigender,
Biromantic1,
Bisexual,
Boyflux2,
/// Meme flag
Burger,
Demiboy,
Demifae,
Demifaun,
Demigender,
Demigirl,
Femboy,
Finsexual,
Fraysexual,
GayMen,
Genderfae,
Genderfaun,
Genderfluid,
Genderflux,
#[strum(serialize = "gendernonconforming1")]
GenderNonconforming1,
#[strum(serialize = "gendernonconforming2")]
GenderNonconforming2,
Gendervoid,
Girlflux,
Greygender,
Greysexual,
Gynesexual,
Intergender,
Lesbian,
Neutrois,
Nonbinary,
NonhumanUnity,
Omniromantic,
Omnisexual,
Pangender,
Pansexual,
Plural,
Polysexual,
Queer,
Rainbow,
Tomboy,
Transfeminine,
Transgender,
Transmasculine,
Unlabeled1,
Unlabeled2,
Voidboy,
Voidgirl,
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct ColorProfile {
colors: Vec<RGB8>,
}
impl Preset {
pub fn color_profile(&self) -> ColorProfile {
(match self {
// used colorpicker to source from https://fyeahaltpride.tumblr.com/post/151704251345/could-you-guys-possibly-make-an-abrosexual-pride
Self::Abrosexual => ColorProfile::from_hex_colors(vec![
"#46D294", "#A3E9CA", "#FFFFFF", "#F78BB3", "#EE1766",
]),
Self::Agender => ColorProfile::from_hex_colors(vec![
"#000000", "#BABABA", "#FFFFFF", "#BAF484", "#FFFFFF", "#BABABA", "#000000",
]),
// sourced from https://www.flagcolorcodes.com/akiosexual
Self::Akiosexual => ColorProfile::from_hex_colors(vec![
"#F9485E", "#FEA06A", "#FEF44C", "#FFFFFF", "#000000",
]),
// sourced from https://lgbtqia.fandom.com/wiki/Androsexual
Self::Androsexual => {
ColorProfile::from_hex_colors(vec!["#01CCFF", "#603524", "#B799DE"])
},
// sourced from https://flag.library.lgbt/flags/aroace/
Self::Aroace1 => ColorProfile::from_hex_colors(vec![
"#E28C00", "#ECCD00", "#FFFFFF", "#62AEDC", "#203856",
]),
// sourced from https://flag.library.lgbt/flags/aroace/
Self::Aroace2 => ColorProfile::from_hex_colors(vec![
"#000000", "#810081", "#A4A4A4", "#FFFFFF", "#A8D47A", "#3BA740",
]),
// sourced from https://flag.library.lgbt/flags/aroace/
Self::Aroace3 => ColorProfile::from_hex_colors(vec![
"#3BA740", "#A8D47A", "#FFFFFF", "#ABABAB", "#000000", "#A4A4A4", "#FFFFFF",
"#810081",
]),
Self::Aromantic => ColorProfile::from_hex_colors(vec![
"#3BA740", "#A8D47A", "#FFFFFF", "#ABABAB", "#000000",
]),
Self::Asexual => {
ColorProfile::from_hex_colors(vec!["#000000", "#A4A4A4", "#FFFFFF", "#810081"])
},
// sourced from https://www.flagcolorcodes.com/autoromantic
Self::Autoromantic => ColorProfile::from_hex_colors(
// symbol interpreted
vec!["#99D9EA", "#99D9EA", "#3DA542", "#7F7F7F", "#7F7F7F"],
),
// sourced from https://www.flagcolorcodes.com/autosexual
Self::Autosexual => ColorProfile::from_hex_colors(vec!["#99D9EA", "#7F7F7F"]),
// used https://gilbertbaker.com/rainbow-flag-color-meanings/ as source and colorpicked
Self::Baker => ColorProfile::from_hex_colors(vec![
"#F23D9E", "#F80A24", "#F78022", "#F9E81F", "#1E972E", "#1B86BC", "#243897",
"#6F0A82",
]),
Self::Beiyang => ColorProfile::from_hex_colors(vec![
"#DF1B12", "#FFC600", "#01639D", "#FFFFFF", "#000000",
]),
// sourced from https://www.flagcolorcodes.com/bigender
Self::Bigender => ColorProfile::from_hex_colors(vec![
"#C479A2", "#EDA5CD", "#D6C7E8", "#FFFFFF", "#D6C7E8", "#9AC7E8", "#6D82D1",
]),
// sourced from https://www.flagcolorcodes.com/biromantic-alternate-2
Self::Biromantic1 => ColorProfile::from_hex_colors(vec![
"#8869A5", "#D8A7D8", "#FFFFFF", "#FDB18D", "#151638",
]),
Self::Bisexual => ColorProfile::from_hex_colors(vec!["#D60270", "#9B4F96", "#0038A8"]),
// sourced from https://www.flagcolorcodes.com/boyflux-alternate-2
Self::Boyflux2 => ColorProfile::from_hex_colors(vec![
"#E48AE4", "#9A81B4", "#55BFAB", "#FFFFFF", "#A8A8A8", "#81D5EF", "#69ABE5",
"#5276D4",
])
.and_then(|c| c.with_weights(vec![1, 1, 1, 1, 1, 5, 5, 5])),
Self::Burger => ColorProfile::from_hex_colors(vec![
"#F3A26A", "#498701", "#FD1C13", "#7D3829", "#F3A26A",
]),
// sourced from https://www.flagcolorcodes.com/demiboy
Self::Demiboy => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C4C4C4", "#9DD7EA", "#FFFFFF", "#9DD7EA", "#C4C4C4", "#7F7F7F",
]),
// used colorpicker to source form https://www.deviantart.com/pride-flags/art/Demifae-870194777
Self::Demifae => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#7F7F7F", "#C5C5C5", "#C5C5C5", "#97C3A4", "#C4DEAE", "#FFFFFF",
"#FCA2C5", "#AB7EDF", "#C5C5C5", "#C5C5C5", "#7F7F7F", "#7F7F7F",
]),
// sourced from https://www.flagcolorcodes.com/demifaun
Self::Demifaun => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#7F7F7F", "#C6C6C6", "#C6C6C6", "#FCC688", "#FFF19C", "#FFFFFF",
"#8DE0D5", "#9682EC", "#C6C6C6", "#C6C6C6", "#7F7F7F", "#7F7F7F",
]),
// yellow sourced from https://lgbtqia.fandom.com/f/p/4400000000000041031
// other colors sourced from demiboy and demigirl flags
Self::Demigender => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C4C4C4", "#FBFF75", "#FFFFFF", "#FBFF75", "#C4C4C4", "#7F7F7F",
]),
// sourced from https://www.flagcolorcodes.com/demigirl
Self::Demigirl => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C4C4C4", "#FDADC8", "#FFFFFF", "#FDADC8", "#C4C4C4", "#7F7F7F",
]),
Self::Femboy => ColorProfile::from_hex_colors(vec![
"#d260a5", "#e4afcd", "#fefefe", "#57cef8", "#fefefe", "#e4afcd", "#d260a5",
]),
// sourced from https://lgbtqia.wiki/wiki/Finsexual
Self::Finsexual => ColorProfile::from_hex_colors(vec![
"#B18EDF", "#D7B1E2", "#F7CDE9", "#F39FCE", "#EA7BB3",
]),
// sampled from https://es.m.wikipedia.org/wiki/Archivo:Fraysexual_flag.jpg
Self::Fraysexual => {
ColorProfile::from_hex_colors(vec!["#226CB5", "#94E7DD", "#FFFFFF", "#636363"])
},
// sourced from https://www.flagcolorcodes.com/gay-men
Self::GayMen => ColorProfile::from_hex_colors(vec![
"#078D70", "#98E8C1", "#FFFFFF", "#7BADE2", "#3D1A78",
]),
// sourced from https://www.flagcolorcodes.com/genderfae
Self::Genderfae => ColorProfile::from_hex_colors(vec![
"#97C3A5", "#C3DEAE", "#F9FACD", "#FFFFFF", "#FCA2C4", "#DB8AE4", "#A97EDD",
]),
// sourced from https://www.flagcolorcodes.com/genderfaun
Self::Genderfaun => ColorProfile::from_hex_colors(vec![
"#FCD689", "#FFF09B", "#FAF9CD", "#FFFFFF", "#8EDED9", "#8CACDE", "#9782EC",
]),
Self::Genderfluid => ColorProfile::from_hex_colors(vec![
"#FE76A2", "#FFFFFF", "#BF12D7", "#000000", "#303CBE",
]),
// sourced from https://www.deviantart.com/pride-flags/art/Genderflux-1-543925589
Self::Genderflux => ColorProfile::from_hex_colors(vec![
"f47694", "f2a2b9", "cecece", "7ce0f7", "3ecdf9", "fff48d",
]),
Self::GenderNonconforming1 => ColorProfile::from_hex_colors(vec![
"#50284d", "#96467b", "#5c96f7", "#ffe6f7", "#5c96f7", "#96467b", "#50284d",
])
.and_then(|c| c.with_weights(vec![4, 1, 1, 1, 1, 1, 4])),
Self::GenderNonconforming2 => ColorProfile::from_hex_colors(vec![
"#50284d", "#96467b", "#5c96f7", "#ffe6f7", "#5c96f7", "#96467b", "#50284d",
]),
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Gendervoid => ColorProfile::from_hex_colors(vec![
"#081149", "#4B484B", "#000000", "#4B484B", "#081149",
]),
// sourced from https://commons.wikimedia.org/wiki/File:Girlflux_Pride_Flag.jpg
Self::Girlflux => ColorProfile::from_hex_colors(vec![
"f9e6d7", "f2526c", "bf0311", "e9c587", "bf0311", "f2526c", "f9e6d7",
]),
// sourced from https://www.flagcolorcodes.com/greygender
Self::Greygender => ColorProfile::from_hex_colors(vec![
"#B3B3B3", "#B3B3B3", "#FFFFFF", "#062383", "#062383", "#FFFFFF", "#535353",
"#535353",
]),
// sourced from https://www.flagcolorcodes.com/greysexual
Self::Greysexual => ColorProfile::from_hex_colors(vec![
"#740194", "#AEB1AA", "#FFFFFF", "#AEB1AA", "#740194",
]),
// sourced from https://lgbtqia.fandom.com/wiki/Gynesexual
Self::Gynesexual => {
ColorProfile::from_hex_colors(vec!["#F4A9B7", "#903F2B", "#5B953B"])
},
// sourced from https://www.flagcolorcodes.com/intergender
Self::Intergender => ColorProfile::from_hex_colors(
// todo: use weighted spacing
vec!["#900DC2", "#900DC2", "#FFE54F", "#900DC2", "#900DC2"],
),
Self::Lesbian => ColorProfile::from_hex_colors(vec![
"#D62800", "#FF9B56", "#FFFFFF", "#D462A6", "#A40062",
]),
// sourced from https://www.flagcolorcodes.com/neutrois
Self::Neutrois => ColorProfile::from_hex_colors(vec!["#FFFFFF", "#1F9F00", "#000000"]),
Self::Nonbinary => {
ColorProfile::from_hex_colors(vec!["#FCF431", "#FCFCFC", "#9D59D2", "#282828"])
},
// used https://twitter.com/foxbrained/status/1667621855518236674/photo/1 as source and colorpicked
Self::NonhumanUnity => {
ColorProfile::from_hex_colors(vec!["#177B49", "#FFFFFF", "#593C90"])
},
Self::Omniromantic => ColorProfile::from_hex_colors(vec![
"#FEC8E4", "#FDA1DB", "#89739A", "#ABA7FE", "#BFCEFF",
]),
// sourced from https://www.flagcolorcodes.com/omnisexual
Self::Omnisexual => ColorProfile::from_hex_colors(vec![
"#FE9ACE", "#FF53BF", "#200044", "#6760FE", "#8EA6FF",
]),
Self::Pangender => ColorProfile::from_hex_colors(vec![
"#FFF798", "#FEDDCD", "#FFEBFB", "#FFFFFF", "#FFEBFB", "#FEDDCD", "#FFF798",
]),
Self::Pansexual => ColorProfile::from_hex_colors(vec!["#FF1C8D", "#FFD700", "#1AB3FF"]),
// used https://pluralpedia.org/w/Plurality#/media/File:Plural-Flag-1.jpg as source and colorpicked
Self::Plural => ColorProfile::from_hex_colors(vec![
"#2D0625", "#543475", "#7675C3", "#89C7B0", "#F3EDBD",
]),
Self::Polysexual => {
ColorProfile::from_hex_colors(vec!["#F714BA", "#01D66A", "#1594F6"])
},
Self::Queer => ColorProfile::from_hex_colors(vec!["#B57FDD", "#FFFFFF", "#49821E"]),
Self::Rainbow => ColorProfile::from_hex_colors(vec![
"#E50000", "#FF8D00", "#FFEE00", "#028121", "#004CFF", "#770088",
]),
Self::Tomboy => ColorProfile::from_hex_colors(vec![
"#2f3fb9", "#613a03", "#fefefe", "#f1a9b7", "#fefefe", "#613a03", "#2f3fb9",
]),
// used colorpicker to source from https://www.deviantart.com/pride-flags/art/Trans-Woman-Transfeminine-1-543925985
// linked from https://gender.fandom.com/wiki/Transfeminine
Self::Transfeminine => ColorProfile::from_hex_colors(vec![
"#73DEFF", "#FFE2EE", "#FFB5D6", "#FF8DC0", "#FFB5D6", "#FFE2EE", "#73DEFF",
]),
Self::Transgender => ColorProfile::from_hex_colors(vec![
"#55CDFD", "#F6AAB7", "#FFFFFF", "#F6AAB7", "#55CDFD",
]),
// sourced from https://www.flagcolorcodes.com/transmasculine
Self::Transmasculine => ColorProfile::from_hex_colors(vec![
"#FF8ABD", "#CDF5FE", "#9AEBFF", "#74DFFF", "#9AEBFF", "#CDF5FE", "#FF8ABD",
]),
// sourced from https://web.archive.org/web/20221002181913/https://unlabeledinfo.carrd.co/#flags
Self::Unlabeled1 => {
ColorProfile::from_hex_colors(vec!["#EAF8E4", "#FDFDFB", "#E1EFF7", "#F4E2C4"])
},
// sourced from https://web.archive.org/web/20221002181913/https://unlabeledinfo.carrd.co/#flags
Self::Unlabeled2 => ColorProfile::from_hex_colors(vec![
"#250548", "#FFFFFF", "#F7DCDA", "#EC9BEE", "#9541FA", "#7D2557",
]),
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Voidboy => ColorProfile::from_hex_colors(vec![
"#0B130C", "#547655", "#66B969", "#547655", "#0B130C",
]),
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Voidgirl => ColorProfile::from_hex_colors(vec![
"#180827", "#7A5A8B", "#E09BED", "#7A5A8B", "#180827",
]),
})
.expect("presets should not be invalid")
}
}
impl ColorProfile {
pub fn new(colors: Vec<RGB8>) -> Self {
Self { colors }
}
pub fn from_hex_colors<S>(hex_colors: Vec<S>) -> Result<Self>
where
S: AsRef<str>,
{
let colors = hex_colors
.into_iter()
.map(RGB8::from_hex)
.collect::<Result<_>>()
.context("Failed to parse hex colors")?;
Ok(Self::new(colors))
}
/// Maps colors based on weights.
///
/// # Arguments
///
/// * `weights` - Weights of each color (`weights[i]` = how many times
/// `colors[i]` appears)
pub fn with_weights(&self, weights: Vec<u8>) -> Result<Self> {
if weights.len() != self.colors.len() {
Err(anyhow!(
"`weights` should have the same number of elements as `colors`"
))?;
}
let mut weighted_colors = vec![];
for (i, w) in weights.into_iter().enumerate() {
weighted_colors.extend(iter::repeat(self.colors[i]).take(w as usize));
}
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<_>>();
let unique_colors = {
let mut v = Vec::with_capacity(unique_colors.len());
v.extend(unique_colors);
v
};
Self::new(unique_colors)
}
}

View file

@ -0,0 +1,9 @@
use strum::{EnumString, VariantNames};
#[derive(Clone, Eq, PartialEq, Hash, Debug, EnumString, VariantNames)]
#[strum(serialize_all = "lowercase")]
pub enum AnsiMode {
#[strum(serialize = "8bit")]
Ansi256,
Rgb,
}

18
rustfmt.toml Normal file
View file

@ -0,0 +1,18 @@
edition = "2021"
# empty_item_single_line = true
# error_on_line_overflow = true
# format_code_in_doc_comments = true
# format_strings = true
# group_imports = "StdExternalCrate"
# imports_granularity = "Module"
# imports_layout = "Mixed"
match_block_trailing_comma = true
newline_style = "Unix"
# normalize_comments = true
# normalize_doc_attributes = true
# overflow_delimited_expr = true
# reorder_impl_items = true
use_field_init_shorthand = true
use_try_shorthand = true
# wrap_comments = true