Compare commits

...

78 Commits

Author SHA1 Message Date
azalea 9cf9985973 [U] Release 2.1.0-rc1 2026-04-07 16:14:21 -04:00
azalea 18bb479415 [U] Update fastfetch 2026-04-07 20:06:41 +00:00
azalea b667cc8ad6 [U] Changelog 2026-04-07 17:11:36 +00:00
azalea e838166b16 [F] Fix background color detection timeout (#453) 2026-04-07 17:04:55 +00:00
azalea 43e1dc1067 [F] poor cat 2026-04-07 16:32:08 +00:00
azalea cc5d7570fb [+] CLI for selecting multiple flags at random (#487) 2026-04-07 16:13:17 +00:00
azalea b05d9c44b4 [+] Option to select random flags (#487) 2026-04-07 15:50:30 +00:00
azalea 2995c78e66 [U] Update deps 2026-04-07 15:39:18 +00:00
azalea 1d89f237db [F] Fix build 2026-04-07 15:39:12 +00:00
azalea 75cde60494 [U] Changelog 2026-04-07 15:39:04 +00:00
azalea fa71dfb84e [+] Haruhi Suzumiya flag (#486) 2026-04-07 15:26:24 +00:00
azalea c147a2ffc6 [-] export distros 2026-04-07 07:42:18 +00:00
azalea 9cc0f9a111 [O] Dedup 2026-04-07 07:15:27 +00:00
azalea 0aa7731c17 [O] No need to export distros 2026-04-07 07:08:23 +00:00
azalea 255dd3e630 [U] Changelog 2026-04-07 06:57:02 +00:00
azalea 7100f7a682 [F] Fix first line missing 2026-04-07 06:23:16 +00:00
azalea 68cb804ccf [+] Read from distro data in python 2026-04-07 06:05:18 +00:00
azalea e9b65287a3 [+] Read from distro data in rust 2026-04-07 06:00:01 +00:00
azalea 5ff0a8d49a [O] Distro as data 2026-04-07 05:58:09 +00:00
azalea 635fbfff01 [F] Fix bash in MINGW64 2026-04-07 02:29:26 +00:00
azalea 13e56f621b [F] Fix macchina #491 2026-04-07 01:55:11 +00:00
Joanna Hartley 9500e8c0aa Add support for QNX/Blackberry 10 (#480)
* Add support for QNX 8.x/Blackberry 10

* Maybe the real uptime was the friends we made along the way

* Detect name of the terminal application

* Re-run the list distros script

* Fix for incorrect memory utilization, and various copilot suggestions. Removed code providing unreliable detection of the terminal application

* Apply suggestion from @Copilot

Ignore header lines for qpkg package manager

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Remove erroneous dependencies

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-07 09:10:05 +08:00
thea e5ba2b3be9 [+] Add custom_presets config option (#481)
* [+] Add custom_presets config option

* [F] Resolve Copilot issues
2026-04-07 09:09:52 +08:00
thea e78e60da3d [+] Live filter preset selection (#482)
* [+] Live filter preset selection

* [F] Resolve Copilot issues
2026-04-07 09:09:42 +08:00
joyous.fart 809b9c34f4 added peter griffin pride flag (#489)
added peter griffin pride flag (inspired by a yahiamice video i think (i dont remember which one sadly))
2026-03-24 09:03:22 +08:00
Enid Brown 352a1ba086 Fix terminal font output in kitty (#484)
[fix] fix terminal font output in kitty
2026-03-08 22:06:08 +08:00
azalea b81d5fed1b [F] Continue even when current path is not found (Fixes #426) 2026-02-11 21:47:27 -05:00
azalea f32e2df4fa [F] Fallback for OS unsupported by rust (Fix #474) 2026-02-11 21:26:36 -05:00
azalea abcc1d265b [F] Prioritize CLI-specified ASCII art by reading it early to prevent file descriptor issues and ensure it overrides configuration. (#475) 2026-02-11 20:57:49 -05:00
notfrants 25824da0e0 Added codex linux and re-run the list distros script (#477)
* Add codex linux

* Fix zirconium (#468)

* Remove non-existing distros (re-run the list_distros.py script)

* Add codex linux to the help message
2026-02-12 09:39:26 +08:00
Theo Haines 5e0f1ee909 [+] Add rubber flag (#479) 2026-02-12 09:28:14 +08:00
Andrin Haldner 62b0fd959f Fix shell detection by using os.execv instead of subprocess.run (#469)
Replace subprocess.run with os.execv to directly exec the Rust binary
2026-01-24 00:17:55 -05:00
bri 9a66c10afd [+] Add zirconium distro (#468)
add zirconium to neofetch
2026-01-24 00:16:32 -05:00
azalea 62fdc22c00 [U] Release 2.0.5 2025-11-21 07:21:23 -05:00
azalea 1fdcfa66b8 Update neofetch 2025-11-21 20:20:39 +08:00
azalea d08a0745a5 [F] Fix shell check 2025-11-21 20:18:44 +08:00
azalea 4ee5344209 Update deploy.md 2025-11-21 20:10:23 +08:00
azalea 26030b0628 [+] Changelogs 2025-11-21 20:04:03 +08:00
azalea 9b376f97c0 [F] Fix #460: Hyfetch panics upon entering invalid alignment option after roll 2025-11-21 19:38:19 +08:00
azalea 2dc18050ca [F] Fix warning 2025-11-21 19:32:14 +08:00
azalea e816235637 [F] Fix #462 Python version prints Traceback on KeyboardInterrupt 2025-11-21 19:27:52 +08:00
azalea 8046e9bab3 [F] Fix #465 2025-11-21 19:21:23 +08:00
ruby_rose e03cda1475 Added femme flag (#456)
* Added femme

* Properly added femme to the list in build.rs

* Revert "Properly added femme to the list in build.rs"

This reverts commit be7f0748ac042bb824a074a664d9978e835a3a58.

---------

Co-authored-by: Azalea <22280294+hykilpikonna@users.noreply.github.com>
2025-11-21 19:14:56 +08:00
Tini 20e5fb3f89 issue #440 void_old added (#457) 2025-11-21 19:10:36 +08:00
LithTheFox e253a75924 Added back the flags that were lost in the python and rust presets merge (#466)
* Added flags that were lost in the Python and Rust presets merge

* [F] Should be above meme flags

---------

Co-authored-by: Azalea <22280294+hykilpikonna@users.noreply.github.com>
2025-11-21 19:09:54 +08:00
azalea 2252fc36e7 Merge branch 'master' of github.com:hykilpikonna/hyfetch 2025-10-22 13:15:42 +08:00
azalea 4e23243384 [O] Colorize secureblue (#434) 2025-10-22 13:15:17 +08:00
azalea f6dc68d7dc [+] Secureblue (closes #434) 2025-10-22 13:02:53 +08:00
azalea f947373a23 [U] Release 2.0.4 2025-10-22 00:46:55 -04:00
azalea 5b745cde01 [U] Changelog 2025-10-22 00:29:49 -04:00
azalea 1afbd66355 [O] Specify python 3.7 to be min version 2025-10-22 12:29:29 +08:00
azalea 2fe21deea8 [F] Fix windows binary mixed with unix 2025-10-22 12:08:39 +08:00
azalea 37a19901bb [U] Update build tool to work with new builder 2025-10-22 11:56:40 +08:00
azalea 063679b72d [O] Moderize python build tool from setup-tools to hatchling 2025-10-22 11:55:07 +08:00
azalea 264cf11690 Merge branch 'master' of github.com:hykilpikonna/hyfetch 2025-10-22 11:34:09 +08:00
azalea 6280d370bc [U] Clarify notes 2025-10-22 11:30:49 +08:00
azalea 6cfc337d83 [O] Fix unused warning on non-windows 2025-10-22 11:28:52 +08:00
azalea 533de96e80 [U] Update notes 2025-10-22 11:24:49 +08:00
azalea dee984f931 [U] Release 2.0.3 2025-10-21 23:20:52 -04:00
azalea 959d42ee9c [F] Typo 2025-10-21 23:20:00 -04:00
azalea eb349aa1aa [U] Changelog 2025-10-21 23:17:56 -04:00
azalea d5751e06af [O] Shorten 2025-10-22 10:53:51 +08:00
azalea 981602b690 [O] Anyhow 2025-10-22 10:42:58 +08:00
azalea a8d752aa9f [F] Preserve preset order in codegen 2025-10-22 10:33:11 +08:00
azalea c57e8a4a49 [+] Rust codegen for presets
#451
2025-10-22 10:27:18 +08:00
azalea 67ae918ae8 [O] Fix weights
#451
2025-10-22 09:53:46 +08:00
azalea e788f93c2b [F] from __future__ import annotations 2025-10-22 08:27:50 +08:00
azalea 75a2e9d8d3 [O] Python load presets from json
#451
2025-10-22 08:24:32 +08:00
azalea 23888c0e3e Merge branch 'SHORTEN' 2025-10-21 19:52:01 +08:00
azalea e5ad9e564d Merge branch 'master' of github.com:hykilpikonna/hyfetch 2025-10-21 19:51:35 +08:00
azalea 328381b336 [+] presets.json 2025-10-21 19:50:59 +08:00
ObsoleteDev 28a181d97b [+] Transbian pride flag (#449)
* [+] Transbian flag py

* [C} Update wording on py Transbian flag

* [+] Add Transbian flag to rust

---------

Co-authored-by: Azalea <22280294+hykilpikonna@users.noreply.github.com>
2025-10-21 19:28:46 +08:00
ObsoleteDev bb514f8fd9 [+] Autism pride flag (py & rust) (#450)
Co-authored-by: Azalea <22280294+hykilpikonna@users.noreply.github.com>
2025-10-21 19:27:26 +08:00
ObsoleteDev b585ee1e26 [+] Add Transneutral & Cenelian flags (#452) 2025-10-21 19:26:14 +08:00
ObsoleteDev de2141347e Fix: Hyfetch panics on some distros that are not defined (#455) 2025-10-21 19:25:48 +08:00
Un1q32 ba88581ed4 Support iOS 1.x (#444)
* support iOS 1.x

* add comment

* reword and fix typo
2025-10-13 15:24:39 +08:00
apaz 932042b62c Swap inside fstring to double quote (#442) 2025-10-10 12:48:03 +08:00
thea f5c5e31691 [F] Fix 3-length hex codes in Python when using custom preset (#443)
[F] Fix 3-length hex codes in Python
2025-10-10 12:46:41 +08:00
664 changed files with 6376 additions and 8027 deletions
Generated
+193 -315
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/*"] members = ["crates/*"]
[workspace.package] [workspace.package]
version = "2.0.2" version = "2.1.0-rc1"
authors = ["Azalea Gui <azalea@hydev.org>"] authors = ["Azalea Gui <azalea@hydev.org>"]
edition = "2021" edition = "2021"
rust-version = "1.75.0" rust-version = "1.75.0"
-9
View File
@@ -1,9 +0,0 @@
include hyfetch/scripts/*
recursive-exclude tools *
recursive-exclude .github *
recursive-exclude .vscode *
exclude .gitignore
exclude .gitattributes
exclude package.json
exclude CONTRIBUTING.md
+90
View File
@@ -129,6 +129,96 @@ cargo install --git https://github.com/hykilpikonna/hyfetch
<!-- CHANGELOG STARTS HERE ---> <!-- CHANGELOG STARTS HERE --->
### 2.1.0-rc1
### 2.1.0
(changelog is generated by Gemini from commit history)
**✨ Features & Enhancements**
* Random Preset: Now can select multiple presets and let it randomly choose one on each run ([#487](https://github.com/hykilpikonna/hyfetch/issues/487)).
* Distro as Data: Migrated distribution ASCII art and metadata to a unified JSON-header format, enabling shared usage across Python and Rust implementations.
* Distro Parity: Added missing ASCII art and distros from [fastfetch](https://github.com/fastfetch-cli/fastfetch).
* New OS Support: Added support for QNX/Blackberry 10 ([#480](https://github.com/hykilpikonna/hyfetch/issues/480)).
* Custom Presets: Added `custom_presets` configuration option to allow user-defined color presets ([#481](https://github.com/hykilpikonna/hyfetch/issues/481)).
* Interactive Filtering: Added live filter for preset selection in the configuration menu ([#482](https://github.com/hykilpikonna/hyfetch/issues/482)).
* New Distros: Added support for Codex Linux ([#477](https://github.com/hykilpikonna/hyfetch/issues/477)) and Zirconium ([#468](https://github.com/hykilpikonna/hyfetch/issues/468)).
* New Flags: Added Peter Griffin pride flag ([#489](https://github.com/hykilpikonna/hyfetch/issues/489)), Rubber flag ([#479](https://github.com/hykilpikonna/hyfetch/issues/479)), and Haruhi Suzumiya flag ([#486](https://github.com/hykilpikonna/hyfetch/issues/486)).
**🐛 Bug Fixes**
* Windows/MSYS2: Fixed bash path detection and execution in MINGW64 environment ([#488](https://github.com/hykilpikonna/hyfetch/issues/488)).
* Backend Fixes: Fixed issues with the `macchina` backend crashing or reporting incorrect distribution ([#491](https://github.com/hykilpikonna/hyfetch/issues/491)).
* Terminal Fixes: Fixed terminal font output issues in Kitty terminal ([#484](https://github.com/hykilpikonna/hyfetch/issues/484)).
* Reliability:
* Improved path detection to continue even when current path is not found ([#426](https://github.com/hykilpikonna/hyfetch/issues/426)).
* Added fallback for operating systems unsupported by the Rust implementation ([#474](https://github.com/hykilpikonna/hyfetch/issues/474)).
* Fixed prioritization of CLI-specified ASCII art to ensure it correctly overrides configuration ([#475](https://github.com/hykilpikonna/hyfetch/issues/475)).
* Shell Detection: Switched to `os.execv` for more reliable shell detection and transition ([#469](https://github.com/hykilpikonna/hyfetch/issues/469)).
* Background Detection Timeout: Prevent crash due to timeout in background color detection ([#453](https://github.com/hykilpikonna/hyfetch/issues/453)).
### 2.0.5
**✨ Features & Enhancements**
* Added support for Secureblue ([#434](https://github.com/hykilpikonna/hyfetch/pull/434)).
* Added `void_old` logo variant ([#457](https://github.com/hykilpikonna/hyfetch/pull/457)).
* Added Femme flag ([#456](https://github.com/hykilpikonna/hyfetch/pull/456)).
**🐛 Bug Fixes**
* Fixed a panic when entering an invalid alignment option after rolling ([#460](https://github.com/hykilpikonna/hyfetch/issues/460)).
* Fixed Traceback printing on KeyboardInterrupt ([#462](https://github.com/hykilpikonna/hyfetch/issues/462)).
* Restored flags lost during Python/Rust presets merge ([#466](https://github.com/hykilpikonna/hyfetch/pull/466)).
* Fixed a panic with file metadata access ([#465](https://github.com/hykilpikonna/hyfetch/issues/465)).
### 2.0.4
**🔧 Building Pipeline Refactoring**
* Modernize Python building toolchain from `setup.py` to `pyproject.toml`
* Fixed a bug where Windows binaries are mistakenly built into Unix packages.
* Fixed a bug where `presets.json` was not being included in the built package.
### 2.0.3
(changelog is generated by Gemini from commit history)
This update brings a significant internal refactor to how color presets are managed, along with a new batch of pride flags and several important bug fixes.
**✨ Features & Enhancements**
* **Custom ASCII Art**: You can now specify a file path for custom ASCII art ([#429](https://github.com/hykilpikonna/hyfetch/pull/429)).
* **Hex Color Presets**: Added the ability to pass a custom comma-separated hex color string list (e.g., `#RRGGBB,#RRGGBB`) directly as a preset ([#435](https://github.com/hykilpikonna/hyfetch/pull/435)).
**🏳️‍🌈 New Flags**
* Added Transbian flag ([#449](https://github.com/hykilpikonna/hyfetch/pull/449))
* Added Autism Pride flag ([#450](https://github.com/hykilpikonna/hyfetch/pull/450))
* Added Transneutral & Cenelian flags ([#452](https://github.com/hykilpikonna/hyfetch/pull/452))
* Added Fluidflux flags ([#437](https://github.com/hykilpikonna/hyfetch/pull/437))
* Added Libragender flags ([#433](https://github.com/hykilpikonna/hyfetch/pull/433))
**🐛 Bug Fixes**
* **Crash Fix**: Fixed a panic that could occur if hyfetch was run on a distro with no defined ASCII art ([#455](https://github.com/hykilpikonna/hyfetch/pull/455)).
* **OS Support**: Added support for iOS 1.x ([#444](https://github.com/hykilpikonna/hyfetch/pull/444)) and old Apple TV models ([#438](https://github.com/hykilpikonna/hyfetch/pull/438)).
* **Python**:
* Fixed a bug where 3-length hex codes (e.g., `#FFF`) does not work properly ([#443](https://github.com/hykilpikonna/hyfetch/pull/443)).
* Fixed a string formatting issue for python 3.11 and earlier versions ([#442](https://github.com/hykilpikonna/hyfetch/pull/442)).
* Fixed a bug where extra top padding would appear above output ascii art ([#428](https://github.com/hykilpikonna/hyfetch/pull/428)).
* **Rust**:
* Fixed the logic for the pride month easter egg so it only marks itself as "displayed" during June ([#430](https://github.com/hykilpikonna/hyfetch/pull/430)).
* Fixed a build issue on Windows ([#439](https://github.com/hykilpikonna/hyfetch/pull/439)).
**🔧 Maintenance & Refactoring**
* **Preset Refactor**: Color presets are now stored in a central `presets.json` file. ([#451](https://github.com/hykilpikonna/hyfetch/issues/451)).
* **Dependency Updates**: Upgraded various Rust crates and other dependencies to their latest versions.
* **Code Cleanup**: General code shortening and readability improvements.
### 2.0.2 ### 2.0.2
This is a small patch release that adds more flags and fixes some bugs from the recent Rust rewrite. This is a small patch release that adds more flags and fixes some bugs from the recent Rust rewrite.
+6 -2
View File
@@ -15,7 +15,7 @@ ansi_colours = { workspace = true, features = [] }
anstream = { workspace = true, features = [], optional = true } anstream = { workspace = true, features = [], optional = true }
anyhow = { workspace = true, features = ["std"] } anyhow = { workspace = true, features = ["std"] }
bpaf = { workspace = true, features = [] } bpaf = { workspace = true, features = [] }
crossterm = { workspace = true, features = [] } crossterm = { workspace = true, features = ["events"] }
deranged = { workspace = true, features = ["serde", "std"] } deranged = { workspace = true, features = ["serde", "std"] }
directories = { workspace = true, features = [] } directories = { workspace = true, features = [] }
enterpolation = { workspace = true, features = ["bspline", "std"] } enterpolation = { workspace = true, features = ["bspline", "std"] }
@@ -41,10 +41,14 @@ unicode-segmentation = { workspace = true, features = [] }
which = { workspace = true, features = [] } which = { workspace = true, features = [] }
[build-dependencies] [build-dependencies]
indexmap = { workspace = true, features = ["std"] } indexmap = { workspace = true, features = ["std", "serde"] }
regex = { workspace = true, features = ["perf", "std", "unicode"] } regex = { workspace = true, features = ["perf", "std", "unicode"] }
unicode-normalization = { workspace = true, features = ["std"] } unicode-normalization = { workspace = true, features = ["std"] }
fs_extra = "1.3.0" fs_extra = "1.3.0"
serde = { workspace = true, features = ["derive", "std"] }
serde_json = { workspace = true, features = ["std"] }
anyhow = { workspace = true, features = ["std"] }
heck = "0.5.0"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
enable-ansi-support = { workspace = true, features = [] } enable-ansi-support = { workspace = true, features = [] }
+203 -112
View File
@@ -1,19 +1,33 @@
use std::env; use std::env;
use std::fmt::Write as _; use std::fmt::Write as _;
use std::fs; use std::fs;
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use fs_extra::dir::{CopyOptions}; use fs_extra::dir::CopyOptions;
use heck::ToUpperCamelCase;
use indexmap::IndexMap; use indexmap::IndexMap;
use regex::Regex; use serde::Deserialize;
use unicode_normalization::UnicodeNormalization as _; use unicode_normalization::UnicodeNormalization as _;
#[derive(Debug)] #[derive(Debug)]
struct AsciiDistro { struct AsciiDistro {
pattern: String, pattern: String,
color: String,
foreground: Vec<u8>,
background: Option<u8>,
art: String, art: String,
} }
#[derive(Deserialize, Debug)]
struct DistroHeader {
#[serde(rename = "match")]
pattern: String,
color: serde_json::Value,
foreground: Option<Vec<u8>>,
background: Option<u8>,
}
impl AsciiDistro { impl AsciiDistro {
fn friendly_name(&self) -> String { fn friendly_name(&self) -> String {
self.pattern self.pattern
@@ -29,36 +43,40 @@ fn anything_that_exist(paths: &[&Path]) -> Option<PathBuf> {
paths.iter().copied().find(|p| p.exists()).map(Path::to_path_buf) paths.iter().copied().find(|p| p.exists()).map(Path::to_path_buf)
} }
fn main() { fn main() -> Result<()> {
// Path hack to make file paths work in both workspace and manifest directory // Path hack to make file paths work in both workspace and manifest directory
let dir = PathBuf::from(env::var_os("CARGO_WORKSPACE_DIR").unwrap_or_else(|| env::var_os("CARGO_MANIFEST_DIR").unwrap())); let dir = PathBuf::from(env::var_os("CARGO_WORKSPACE_DIR").unwrap_or_else(|| env::var_os("CARGO_MANIFEST_DIR").unwrap()));
let o = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let o = PathBuf::from(env::var_os("OUT_DIR").unwrap());
for file in &["neofetch", "hyfetch/data"] { let data_dir = anything_that_exist(&[
let src = anything_that_exist(&[ &dir.join("hyfetch/data"),
&dir.join(file), &dir.join("../../hyfetch/data"),
&dir.join("../../").join(file), ]).context("couldn't find hyfetch/data")?;
]).expect("couldn't find neofetch");
let dst = o.join(file); let dst_root = o.join("hyfetch");
println!("cargo:rerun-if-changed={}", src.display()); fs::create_dir_all(&dst_root)?;
// Copy hyfetch/data
let opt = CopyOptions { overwrite: true, copy_inside: true, ..CopyOptions::default() };
fs_extra::dir::copy(&data_dir, &dst_root, &opt)?;
// Copy either file or directory // Copy neofetch
if src.is_dir() { let neofetch_src = anything_that_exist(&[
let opt = CopyOptions { overwrite: true, copy_inside: true, ..CopyOptions::default() }; &dir.join("neofetch"),
println!("copying {} to {}", src.display(), dst.display()); &dir.join("../../neofetch"),
fs_extra::dir::copy(&src, &dst, &opt).expect("Failed to copy directory to OUT_DIR"); ]).context("couldn't find neofetch")?;
} fs::copy(&neofetch_src, o.join("neofetch"))?;
else { fs::copy(&src, &dst).expect("Failed to copy file to OUT_DIR"); }
}
export_distros(&o.join("neofetch"), &o); preset_codegen(&o.join("hyfetch/data/presets.json"), &o.join("presets.rs"))?;
let distros_dir = data_dir.join("distros");
export_distros(&distros_dir, &o)?;
Ok(())
} }
fn export_distros<P>(neofetch_path: P, out_path: &Path) fn export_distros(distro_dir: &Path, out_path: &Path) -> Result<()>
where
P: AsRef<Path>,
{ {
let distros = parse_ascii_distros(neofetch_path); let distros = parse_ascii_distros(distro_dir)?;
let mut variants = IndexMap::with_capacity(distros.len()); let mut variants = IndexMap::with_capacity(distros.len());
for distro in &distros { for distro in &distros {
@@ -81,18 +99,13 @@ where
let mut buf = r###" let mut buf = r###"
#[derive(Clone, Eq, PartialEq, Hash, Debug)] #[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum Distro { pub enum Distro {
"### "###.to_string();
.to_owned();
for (variant, AsciiDistro { pattern, .. }) in &variants { for (variant, AsciiDistro { pattern, .. }) in &variants {
write!( write!(buf, r###"
buf,
r###"
// {pattern}) // {pattern})
{variant}, {variant},
"###, "###)?;
)
.unwrap();
} }
buf.push_str( buf.push_str(
@@ -154,15 +167,11 @@ impl Distro {
let condition = conds.join(" || "); let condition = conds.join(" || ");
write!( write!(buf, r###"
buf,
r###"
if {condition} {{ if {condition} {{
return Some(Self::{variant}); return Some(Self::{variant});
}} }}
"### "###)?;
)
.unwrap();
} }
buf.push_str( buf.push_str(
@@ -170,6 +179,66 @@ impl Distro {
None None
} }
pub fn color(&self) -> &str {
match self {
"###,
);
for (variant, AsciiDistro { color, .. }) in &variants {
write!(buf, r###"
Self::{variant} => {color:?},
"###, color = color)?;
}
buf.push_str(
r###"
}
}
pub fn foreground(&self) -> &[u8] {
match self {
"###,
);
for (variant, AsciiDistro { foreground, .. }) in &variants {
if foreground.is_empty() {
write!(buf, r###"
Self::{variant} => &[],
"###)?;
} else {
write!(buf, r###"
Self::{variant} => &{:?},
"###, foreground)?;
}
}
buf.push_str(
r###"
}
}
pub fn background(&self) -> Option<u8> {
match self {
"###,
);
for (variant, AsciiDistro { background, .. }) in &variants {
if let Some(b) = background {
write!(buf, r###"
Self::{variant} => Some({b}),
"###)?;
} else {
write!(buf, r###"
Self::{variant} => None,
"###)?;
}
}
buf.push_str(
r###"
}
}
pub fn ascii_art(&self) -> &str { pub fn ascii_art(&self) -> &str {
let art = match self { let art = match self {
"###, "###,
@@ -177,15 +246,11 @@ impl Distro {
let quotes = "#".repeat(80); let quotes = "#".repeat(80);
for (variant, AsciiDistro { art, .. }) in &variants { for (variant, AsciiDistro { art, .. }) in &variants {
write!( write!(buf, r###"
buf,
r###"
Self::{variant} => r{quotes}" Self::{variant} => r{quotes}"
{art} {art}
"{quotes}, "{quotes},
"###, "###)?;
)
.unwrap();
} }
buf.push_str( buf.push_str(
@@ -197,78 +262,104 @@ impl Distro {
"###, "###,
); );
fs::write(out_path.join("distros.rs"), buf).expect("couldn't write distros.rs"); fs::write(out_path.join("distros.rs"), buf)?;
Ok(())
} }
/// Parses ascii distros from neofetch script. fn parse_ascii_distros(distro_dir: &Path) -> Result<Vec<AsciiDistro>>
fn parse_ascii_distros<P>(neofetch_path: P) -> Vec<AsciiDistro>
where
P: AsRef<Path>,
{ {
let neofetch_path = neofetch_path.as_ref(); let mut distros = Vec::new();
let mut paths: Vec<_> = fs::read_dir(distro_dir)?
.filter_map(|e| e.ok())
.map(|e| e.path())
.collect();
paths.sort();
let nf = { for path in paths {
let nf = fs::read_to_string(neofetch_path).expect("couldn't read neofetch script"); if path.extension().and_then(|s| s.to_str()) == Some("ascii") {
let content = fs::read_to_string(&path)?;
// Get the content of "get_distro_ascii" function let (header_line, art) = content.split_once('\n').context("invalid distro file")?;
let (_, nf) = nf let header: DistroHeader = serde_json::from_str(header_line)?;
.split_once("get_distro_ascii() {\n") let color = match header.color {
.expect("couldn't find get_distro_ascii function"); serde_json::Value::String(s) => s,
let (nf, _) = nf serde_json::Value::Number(n) => n.to_string(),
.split_once("\n}\n") _ => "7".to_owned(),
.expect("couldn't find end of get_distro_ascii function"); };
distros.push(AsciiDistro {
let mut nf = nf.replace('\t', &" ".repeat(4)); pattern: header.pattern,
color,
// Remove trailing spaces foreground: header.foreground.unwrap_or_default(),
while nf.contains(" \n") { background: header.background,
nf = nf.replace(" \n", "\n"); art: art.to_owned(),
});
} }
nf
};
let case_re = Regex::new(r"case .*? in\n").expect("couldn't compile case regex");
let eof_re = Regex::new(r"EOF[ \n]*?;;").expect("couldn't compile eof regex");
// Split by blocks
let mut blocks = Vec::new();
for b in case_re.split(&nf) {
blocks.extend(eof_re.split(b).map(|sub| sub.trim()));
} }
Ok(distros)
// Parse blocks }
fn parse_block(block: &str) -> Option<AsciiDistro> {
let (block, art) = block.split_once("'EOF'\n")?; // Preset parsing
#[derive(Deserialize, Debug)]
// Join \ #[serde(untagged)]
// enum PresetEntry {
// > A <backslash> that is not quoted shall preserve the literal value of the Simple(Vec<String>),
// > following character, with the exception of a <newline>. If a <newline> Complex { colors: Vec<String>, weights: Option<Vec<u32>> },
// > follows the <backslash>, the shell shall interpret this as line }
// > continuation. The <backslash> and <newline> shall be removed before
// > splitting the input into tokens. Since the escaped <newline> is removed type PresetMap = IndexMap<String, PresetEntry>;
// > entirely from the input and is not replaced by any white space, it cannot
// > serve as a token separator. fn preset_codegen(json_path: &Path, out_path: &Path) -> Result<()> {
// See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_01 // 1. Read and parse the JSON file
let block = block.replace("\\\n", ""); let json_str = fs::read_to_string(json_path)?;
let map: PresetMap = serde_json::from_str(&json_str)?;
// Get case pattern let mut f = BufWriter::new(fs::File::create(&out_path)?);
let pattern = block
.split('\n') // 2. Build the code string
.next() let mut code_decl = String::new();
.and_then(|pattern| pattern.trim().strip_suffix(')'))?; let mut code_match = String::new();
for (key, data) in map.iter() {
// Unescape backslashes here because backslashes are escaped in neofetch let colors = match data {
// for printf PresetEntry::Simple(c) => c,
let art = art.replace(r"\\", r"\"); PresetEntry::Complex { colors, .. } => colors,
};
Some(AsciiDistro { let colors = colors.iter().map(|s| format!("\"{}\"", s)).collect::<Vec<_>>().join(", ");
pattern: pattern.to_owned(), let uck = key.to_upper_camel_case();
art,
}) code_decl += &format!(r#"
} #[serde(rename = "{key}")]
blocks #[strum(serialize = "{key}")]
.iter() {uck},
.filter_map(|block| parse_block(block)) "#);
.collect()
let w = if let PresetEntry::Complex { weights: Some(w), .. } = data {
format!(".and_then(|c| c.with_weights(vec![{}]))", w.iter().map(|n| n.to_string()).collect::<Vec<_>>().join(", "))
} else { "".to_string() };
code_match += &format!(r#"
Preset::{uck} => ColorProfile::from_hex_colors(vec![{colors}]){w},
"#);
}
// 3. Write the static map to the generated file
writeln!(f, r#"
pub use crate::color_profile::ColorProfile;
use serde::{{Deserialize, Serialize}};
use strum::{{AsRefStr, EnumCount, EnumString, VariantArray, VariantNames}};
#[derive(Copy, Clone, Hash, Debug, AsRefStr, Deserialize, EnumCount, EnumString, Serialize, VariantArray, VariantNames)]
pub enum Preset {{
{code_decl}
}}
impl Preset {{
pub fn color_profile(&self) -> ColorProfile {{
(match self {{
{code_match}
}})
.expect("preset color profiles should be valid")
}}
}}"#)?;
f.flush()?;
Ok(())
} }
+1 -7
View File
@@ -372,12 +372,7 @@ impl NormalizedAsciiArt {
// Line starts with neofetch color code // Line starts with neofetch color code
last = Some(&line[m.span()]); last = Some(&line[m.span()]);
}, },
Some(_) => { _ => {
new.push_str(last.context(
"failed to find neofetch color code from a previous line",
)?);
},
None => {
new.push_str(last.unwrap_or(NEOFETCH_COLOR_PATTERNS[0])); new.push_str(last.unwrap_or(NEOFETCH_COLOR_PATTERNS[0]));
}, },
} }
@@ -385,7 +380,6 @@ impl NormalizedAsciiArt {
// Get the last placeholder for the next line // Get the last placeholder for the next line
if let Some(m) = matches.last() { if let Some(m) = matches.last() {
last.context("non-space character seen before first color code")?;
last = Some(&line[m.span()]); last = Some(&line[m.span()]);
} }
+370 -139
View File
@@ -1,8 +1,9 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp; use std::cmp;
use std::collections::HashMap;
use std::fmt::Write as _; use std::fmt::Write as _;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{self, IsTerminal as _, Read as _}; use std::io::{self, IsTerminal as _, Read as _, Write};
use std::iter; use std::iter;
use std::iter::zip; use std::iter::zip;
use std::num::NonZeroU8; use std::num::NonZeroU8;
@@ -10,6 +11,8 @@ use std::path::{Path, PathBuf};
use aho_corasick::AhoCorasick; use aho_corasick::AhoCorasick;
use anyhow::{Context as _, Result}; use anyhow::{Context as _, Result};
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use deranged::RangedU8; use deranged::RangedU8;
use enterpolation::bspline::BSpline; use enterpolation::bspline::BSpline;
use enterpolation::{Curve as _, Generator as _}; use enterpolation::{Curve as _, Generator as _};
@@ -21,11 +24,12 @@ use hyfetch::color_util::{
NeofetchAsciiIndexedColor, PresetIndexedColor, Theme as _, ToAnsiString as _, NeofetchAsciiIndexedColor, PresetIndexedColor, Theme as _, ToAnsiString as _,
}; };
use hyfetch::distros::Distro; use hyfetch::distros::Distro;
use hyfetch::models::Config; use hyfetch::models::{build_hex_color_profile, Config, PresetValue};
#[cfg(feature = "macchina")] #[cfg(feature = "macchina")]
use hyfetch::neofetch_util::macchina_path; use hyfetch::neofetch_util::macchina_path;
use hyfetch::neofetch_util::{self, add_pkg_path, fastfetch_path, get_distro_ascii, get_distro_name, literal_input, ColorAlignment, NEOFETCH_COLORS_AC, NEOFETCH_COLOR_PATTERNS, TEST_ASCII}; use hyfetch::neofetch_util::{self, add_pkg_path, fastfetch_path, get_distro_ascii, get_distro_name, literal_input, ColorAlignment, NEOFETCH_COLORS_AC, NEOFETCH_COLOR_PATTERNS, TEST_ASCII};
use hyfetch::presets::{AssignLightness, ColorProfile, Preset}; use hyfetch::color_profile::{AssignLightness, ColorProfile};
use hyfetch::presets::{Preset};
use hyfetch::{pride_month, printc}; use hyfetch::{pride_month, printc};
use hyfetch::types::{AnsiMode, Backend, TerminalTheme}; use hyfetch::types::{AnsiMode, Backend, TerminalTheme};
use hyfetch::utils::{get_cache_path, input}; use hyfetch::utils::{get_cache_path, input};
@@ -43,7 +47,7 @@ use tracing::debug;
fn main() -> Result<()> { fn main() -> Result<()> {
add_pkg_path().expect("failed to add pkg path"); add_pkg_path().expect("failed to add pkg path");
#[cfg(windows)] #[cfg(windows)]
if let Err(err) = enable_ansi_support::enable_ansi_support() { if let Err(err) = enable_ansi_support::enable_ansi_support() {
debug!(%err, "could not enable ANSI escape code support"); debug!(%err, "could not enable ANSI escape code support");
@@ -51,6 +55,16 @@ fn main() -> Result<()> {
let options = options().run(); let options = options().run();
// Read ascii file first to avoid any issues with file descriptors being closed by other operations, and to allow CLI arguments to override config. (https://github.com/hykilpikonna/hyfetch/issues/475)
let cli_ascii = if let Some(path) = &options.ascii_file {
Some(RawAsciiArt {
asc: fs::read_to_string(path).with_context(|| format!("failed to read ascii from {path:?}"))?,
fg: Vec::new(),
})
} else {
None
};
let debug_mode = options.debug; let debug_mode = options.debug;
init_tracing_subsriber(debug_mode).context("failed to init tracing subscriber")?; init_tracing_subsriber(debug_mode).context("failed to init tracing subscriber")?;
@@ -122,43 +136,61 @@ fn main() -> Result<()> {
let backend = options.backend.unwrap_or(config.backend); let backend = options.backend.unwrap_or(config.backend);
let args = options.args.as_ref().or(config.args.as_ref()); let args = options.args.as_ref().or(config.args.as_ref());
fn parse_preset_string(preset_string: &str) -> Result<ColorProfile> { fn parse_preset_string(preset_string: &str, config: &Config) -> Result<ColorProfile> {
if preset_string.contains('#') { if preset_string.contains('#') {
let colors: Vec<&str> = preset_string.split(',').map(|s| s.trim()).collect(); let colors: Vec<String> = preset_string
for color in &colors { .split(',')
if !color.starts_with('#') || .map(|s| s.trim().to_owned())
(color.len() != 4 && color.len() != 7) || .collect();
!color[1..].chars().all(|c| c.is_ascii_hexdigit()) { let color_profile = build_hex_color_profile(&colors)
return Err(anyhow::anyhow!("invalid hex color: {}", color)); .context("failed to create color profile from hex")?;
} return Ok(color_profile);
} }
ColorProfile::from_hex_colors(colors)
.context("failed to create color profile from hex") let mut preset_profiles: HashMap<String, ColorProfile> = <Preset as VariantArray>::VARIANTS
} else if preset_string == "random" { .iter()
.map(|preset| (preset.as_ref().to_owned(), preset.color_profile()))
.collect();
preset_profiles.extend(config.custom_preset_profiles()?);
if preset_string.contains(',') {
let presets: Vec<&str> = preset_string.split(',').map(|s| s.trim()).collect();
let mut rng = fastrand::Rng::new(); let mut rng = fastrand::Rng::new();
let preset = *rng let selected_index = rng.usize(0..presets.len());
.choice(<Preset as VariantArray>::VARIANTS) return parse_preset_string(presets[selected_index], config);
.expect("preset iterator should not be empty"); }
Ok(preset.color_profile())
if preset_string == "random" {
let presets: Vec<ColorProfile> = preset_profiles.values().cloned().collect();
if presets.is_empty() {
return Err(anyhow::anyhow!("preset iterator should not be empty"));
}
let mut rng = fastrand::Rng::new();
let selected_index = rng.usize(0..presets.len());
return Ok(presets[selected_index].clone());
}
if let Some(color_profile) = preset_profiles.get(preset_string) {
Ok(color_profile.clone())
} else { } else {
use std::str::FromStr; let presets = preset_profiles
let preset = Preset::from_str(preset_string) .keys()
.with_context(|| { .map(String::as_str)
format!( .chain(iter::once("random"))
"PRESET should be comma-separated hex colors or one of {{{presets}}}", .sorted()
presets = <Preset as VariantNames>::VARIANTS .join(",");
.iter() Err(anyhow::anyhow!(
.chain(iter::once(&"random")) "PRESET should be comma-separated hex colors or one of {{{presets}}}"
.join(",") ))
)
})?;
Ok(preset.color_profile())
} }
} }
// Get preset // Get preset
let preset_string = options.preset.as_deref().unwrap_or(&config.preset); let preset_string = options
let color_profile = parse_preset_string(preset_string)?; .preset
.clone()
.unwrap_or_else(|| config.preset.get_random_if_multiple());
let color_profile = parse_preset_string(&preset_string, &config)?;
debug!(?color_profile, "color profile"); debug!(?color_profile, "color profile");
// Lighten // Lighten
@@ -176,19 +208,15 @@ fn main() -> Result<()> {
}; };
debug!(?color_profile, "lightened color profile"); debug!(?color_profile, "lightened color profile");
let asc = if let Some(path_str) = config.custom_ascii_path { let asc = if let Some(asc) = cli_ascii {
asc
} else if let Some(path_str) = config.custom_ascii_path {
let path = PathBuf::from(path_str); let path = PathBuf::from(path_str);
RawAsciiArt { RawAsciiArt {
asc: fs::read_to_string(&path) asc: fs::read_to_string(&path)
.with_context(|| format!("failed to read ascii from {path:?}"))?, .with_context(|| format!("failed to read ascii from {path:?}"))?,
fg: Vec::new(), fg: Vec::new(),
} }
} else if let Some(path) = options.ascii_file {
RawAsciiArt {
asc: fs::read_to_string(&path)
.with_context(|| format!("failed to read ascii from {path:?}"))?,
fg: Vec::new(),
}
} else { } else {
get_distro_ascii(distro, backend).context("failed to get distro ascii")? get_distro_ascii(distro, backend).context("failed to get distro ascii")?
}; };
@@ -240,15 +268,15 @@ fn det_bg() -> Result<Option<Srgb<u8>>, terminal_colorsaurus::Error> {
return Ok(None); return Ok(None);
} }
background_color(QueryOptions::default()) match background_color(QueryOptions::default()) {
.map(|terminal_colorsaurus::Color { r, g, b , .. }| Some(Srgb::new(r, g, b).into_format())) Ok(terminal_colorsaurus::Color { r, g, b, .. }) => {
.or_else(|err| { Ok(Some(Srgb::new(r, g, b).into_format()))
if matches!(err, terminal_colorsaurus::Error::UnsupportedTerminal(_)) { }
Ok(None) Err(err) => {
} else { debug!(?err, "failed to detect background color");
Err(err) Ok(None)
} }
}) }
} }
/// Creates config interactively. /// Creates config interactively.
@@ -446,6 +474,40 @@ fn create_config(
////////////////////////////// //////////////////////////////
// 3. Choose preset // 3. Choose preset
struct RawModeGuard {
enabled: bool,
}
impl RawModeGuard {
fn new() -> Result<Self> {
Ok(Self { enabled: false })
}
fn enable(&mut self) -> Result<()> {
if !self.enabled {
enable_raw_mode().context("failed to enable terminal raw mode")?;
self.enabled = true;
}
Ok(())
}
fn disable(&mut self) -> Result<()> {
if self.enabled {
disable_raw_mode().context("failed to disable terminal raw mode")?;
self.enabled = false;
}
Ok(())
}
}
impl Drop for RawModeGuard {
fn drop(&mut self) {
if self.enabled {
let _ = disable_raw_mode();
}
}
}
// Create flag lines // Create flag lines
let mut flags = Vec::with_capacity(Preset::COUNT); let mut flags = Vec::with_capacity(Preset::COUNT);
let spacing = { let spacing = {
@@ -472,7 +534,11 @@ fn create_config(
name = preset.as_ref(), name = preset.as_ref(),
spacing = usize::from(spacing) spacing = usize::from(spacing)
); );
flags.push([name, flag.clone(), flag.clone(), flag]); flags.push((
preset.clone(),
[name, flag.clone(), flag.clone(), flag],
preset.as_ref().to_ascii_lowercase(),
));
} }
// Calculate flags per row // Calculate flags per row
@@ -482,34 +548,28 @@ fn create_config(
let rows_per_page = (term_h.saturating_sub(13) / 5).clamp(1, u8::MAX.into()) as u8; let rows_per_page = (term_h.saturating_sub(13) / 5).clamp(1, u8::MAX.into()) as u8;
(flags_per_row, rows_per_page) (flags_per_row, rows_per_page)
}; };
let num_pages = (Preset::COUNT.div_ceil(flags_per_row as usize * rows_per_page as usize)).clamp(0, u8::MAX.into()) as u8; let flags_per_page = usize::from(flags_per_row) * usize::from(rows_per_page);
// Create pages fn filter_flag_indices(query: &str, flags: &[(Preset, [String; 4], String)]) -> Vec<usize> {
let mut pages = Vec::with_capacity(usize::from(num_pages)); if query.is_empty() {
for flags in flags.chunks(usize::from( return (0..flags.len()).collect();
u16::from(flags_per_row)
.checked_mul(u16::from(rows_per_page))
.unwrap(),
)) {
let mut page = Vec::with_capacity(usize::from(rows_per_page));
for flags in flags.chunks(usize::from(flags_per_row)) {
page.push(flags);
} }
pages.push(page);
let mut matched = flags
.iter()
.enumerate()
.filter_map(|(idx, (_, _, preset_name))| {
let position = preset_name.find(query)?;
Some((idx, preset_name.starts_with(query), position))
})
.collect::<Vec<_>>();
// Prefix matches are shown first, then other substring matches ordered by earliest index.
matched.sort_by_key(|&(idx, is_prefix, position)| (!is_prefix, position, idx));
matched.into_iter().map(|(idx, _, _)| idx).collect()
} }
let print_flag_page = |page, page_num: u8| -> Result<()> { fn print_flag_row(row: &[&[String; 4]], color_mode: AnsiMode) -> Result<()> {
clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?;
print_title_prompt(option_counter, "Let's choose a flag!");
println!("Available flag presets:\nPage: {page_num} of {num_pages}\n", page_num = page_num + 1);
for &row in page {
print_flag_row(row, color_mode).context("failed to print flag row")?;
}
println!();
Ok(())
};
fn print_flag_row(row: &[[String; 4]], color_mode: AnsiMode) -> Result<()> {
for i in 0..4 { for i in 0..4 {
let mut line = Vec::new(); let mut line = Vec::new();
for flag in row { for flag in row {
@@ -532,50 +592,214 @@ fn create_config(
) )
.expect("coloring text with default preset should not fail"); .expect("coloring text with default preset should not fail");
let preset: Preset; let print_flag_page = |filtered_indices: &[usize],
let color_profile; page_num: usize,
filter: &str,
hint: Option<&str>|
-> Result<()> {
let num_pages = filtered_indices.len().div_ceil(flags_per_page).max(1);
clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?;
print_title_prompt(option_counter, "Let's choose a flag!");
println!(
"Available flag presets:\nPage: {page} of {num_pages}\n",
page = page_num + 1
);
let mut page: u8 = 0; let start = page_num * flags_per_page;
loop { let end = (start + flags_per_page).min(filtered_indices.len());
print_flag_page(&pages[usize::from(page)], page).context("failed to print flag page")?; let mut visible_rows: usize = 0;
if start >= end {
println!("No presets matched this filter.");
} else {
for row in filtered_indices[start..end].chunks(usize::from(flags_per_row)) {
let row = row
.iter()
.map(|&idx| &flags[idx].1)
.collect::<Vec<&[String; 4]>>();
print_flag_row(&row, color_mode).context("failed to print flag row")?;
visible_rows += 1;
}
println!();
}
// Keep the prompt anchored by reserving a full page worth of flag rows.
for _ in visible_rows..usize::from(rows_per_page) {
for _ in 0..5 {
println!();
}
}
let mut opts: Vec<&str> = <Preset as VariantNames>::VARIANTS.into(); println!(
opts.extend(["next", "n", "prev", "p"]); "Use the up/down arrow keys to go to the previous/next page. Type to filter and press Enter to select."
);
println!("Enter '[n]ext' to go to the next page and '[p]rev' to go to the previous page."); printc(
let selection = literal_input( format!(
format!("Which {preset_default_colored} do you want to use? "), "Which {preset_default_colored} do you want to use? (default: {}, comma-separated for multiple at random)",
&opts[..], Preset::Rainbow.as_ref()
Preset::Rainbow.as_ref(), ),
false,
color_mode, color_mode,
) )
.context("failed to ask for choice input") .context("failed to print preset prompt")?;
.context("failed to select preset")?; print!("> {filter}");
if selection == "next" || selection == "n" { io::stdout().flush().context("failed to flush preset prompt")?;
page = (page + 1) % num_pages;
} else if selection == "prev" || selection == "p" { if let Some(hint) = hint {
page = (page + num_pages - 1) % num_pages; println!("\n{hint}");
} else {
preset = selection.parse().expect("selected preset should be valid");
debug!(?preset, "selected preset");
color_profile = preset.color_profile();
update_title(
&mut title,
&mut option_counter,
"Selected flag",
&color_profile
.with_lightness_adaptive(default_lightness, theme)
.color_text(
preset.as_ref(),
color_mode,
ForegroundBackground::Foreground,
false,
)
.expect("coloring text with selected preset should not fail"),
);
break;
} }
Ok(())
};
let selected_preset_names: Vec<String>;
let color_profile;
let mut page: usize = 0;
let mut filter = String::new();
let mut hint: Option<&str> = None;
let mut raw_mode = RawModeGuard::new().context("failed to initialize raw input mode")?;
loop {
raw_mode
.disable()
.context("failed to disable raw mode for rendering")?;
let filter_lower = filter.to_ascii_lowercase();
let parts: Vec<&str> = filter_lower.split(',').collect();
let current_query = parts.last().cloned().unwrap_or("");
let filtered_indices = filter_flag_indices(current_query, &flags);
let num_pages = filtered_indices.len().div_ceil(flags_per_page).max(1);
page = page.min(num_pages - 1);
print_flag_page(&filtered_indices, page, &filter, hint)
.context("failed to print flag page")?;
hint = None;
raw_mode
.enable()
.context("failed to enable raw mode for key input")?;
let event = event::read().context("failed to read keyboard event")?;
let Event::Key(key) = event else {
continue;
};
if !matches!(key.kind, KeyEventKind::Press | KeyEventKind::Repeat) {
continue;
}
match key.code {
KeyCode::Enter => {
let filter_lower = filter.to_ascii_lowercase();
let parts: Vec<&str> = filter_lower.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()).collect();
let mut resolved_presets = Vec::new();
if parts.is_empty() {
// Default to Rainbow if nothing is entered
resolved_presets.push(Preset::Rainbow.as_ref().to_owned());
} else {
for part in parts.iter() {
let selection = flags
.iter()
.find(|(_, _, name)| name == part)
.map(|(preset, _, _)| preset.as_ref().to_owned())
.or_else(|| {
// Fuzzy match each part
let filtered = filter_flag_indices(part, &flags);
filtered.first().map(|&idx| flags[idx].0.as_ref().to_owned())
});
if let Some(p) = selection {
resolved_presets.push(p);
} else {
hint = Some("One or more presets could not be found.");
}
}
}
if hint.is_none() {
selected_preset_names = resolved_presets;
break;
}
},
KeyCode::Up => {
page = (page + num_pages - 1) % num_pages;
},
KeyCode::Down => {
page = (page + 1) % num_pages;
},
KeyCode::Backspace => {
filter.pop();
page = 0;
},
KeyCode::Esc => {
filter.clear();
page = 0;
},
KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => {
raw_mode
.disable()
.context("failed to disable raw mode before interrupting")?;
println!();
return Err(anyhow::anyhow!("interrupted by user"));
},
KeyCode::Char(c)
if !key.modifiers.contains(KeyModifiers::CONTROL)
&& !key.modifiers.contains(KeyModifiers::ALT) =>
{
filter.push(c);
page = 0;
},
_ => {},
}
}
raw_mode
.disable()
.context("failed to disable raw mode after preset selection")?;
let selected_presets = if selected_preset_names.len() > 1 {
PresetValue::Multiple(selected_preset_names.clone())
} else {
PresetValue::Single(selected_preset_names.first().cloned().unwrap_or_else(|| Preset::Rainbow.as_ref().to_owned()))
};
color_profile = {
let first_name = selected_preset_names.first().cloned().unwrap_or_else(|| Preset::Rainbow.as_ref().to_owned());
if first_name.contains('#') {
let colors: Vec<String> = first_name.split(',').map(|s| s.trim().to_owned()).collect();
build_hex_color_profile(&colors).expect("hex colors should be valid")
} else {
flags.iter().find(|(_, _, name)| name == &first_name).map(|(p, _, _)| p.color_profile()).unwrap_or_else(|| Preset::Rainbow.color_profile())
}
};
{
let colored_names = selected_preset_names.iter().map(|name| {
let profile = if name.contains('#') {
let colors: Vec<String> = name.split(',').map(|s| s.trim().to_owned()).collect();
build_hex_color_profile(&colors).expect("hex colors should be valid")
} else {
flags.iter().find(|(_, _, n)| n == name).map(|(p, _, _)| p.color_profile()).unwrap_or_else(|| Preset::Rainbow.color_profile())
};
profile.with_lightness_adaptive(default_lightness, theme)
.color_text(name, color_mode, ForegroundBackground::Foreground, false)
.expect("coloring text should not fail")
}).join(", ");
let label = if selected_preset_names.len() > 1 {
"Selected flags (random)"
} else {
"Selected flag"
};
update_title(
&mut title,
&mut option_counter,
label,
&colored_names,
);
printc(
format!(
"Which {preset_default_colored} do you want to use? {}\n",
colored_names
),
color_mode,
)
.context("failed to print preset selection summary")?;
} }
////////////////////////////// //////////////////////////////
@@ -722,8 +946,11 @@ fn create_config(
// get distro string and convert it into the enum, neofetch friendly format, so we can check for small logos with the {distro}_small neofetch naming scheme. // get distro string and convert it into the enum, neofetch friendly format, so we can check for small logos with the {distro}_small neofetch naming scheme.
let tmp_dst = get_distro_name(backend).or_else(|_| get_distro_name(Backend::Neofetch)).context("failed to get distro name")?; let tmp_dst = get_distro_name(backend).or_else(|_| get_distro_name(Backend::Neofetch)).context("failed to get distro name")?;
let detected_dst = Some(distro.map_or_else( let detected_dst = Some(distro.map_or_else(
|| format!("{:?}", Distro::detect(tmp_dst).unwrap()), || {
|d| d.to_string(), Distro::detect(&tmp_dst)
.map_or("".to_string(), |d| format!("{:?}", d).to_lowercase())
},
|d| d.to_string().to_lowercase(),
)); ));
// in case someone specified {distro}_small already in the --distro arg // in case someone specified {distro}_small already in the --distro arg
@@ -732,26 +959,26 @@ fn create_config(
} else { } else {
detected_dst.unwrap() detected_dst.unwrap()
}; };
let running_dst_sml = if Distro::detect(&detected_dst_small_fmt).is_some() { let running_dst_sml = if Distro::detect(&detected_dst_small_fmt).is_some() {
detected_dst_small_fmt detected_dst_small_fmt
} else { } else {
"".to_string() "".to_string()
}; };
// load ascii // load ascii
let small_asc = get_distro_ascii(Some(&running_dst_sml), backend).context("failed to get distro ascii")?; let small_asc = get_distro_ascii(Some(&running_dst_sml), backend).context("failed to get distro ascii")?;
let small_asc = small_asc.to_normalized().context("failed to normalize ascii")?; let small_asc = small_asc.to_normalized().context("failed to normalize ascii")?;
let mut asc = asc; let mut asc = asc;
let mut logo_chosen: Option<String> = distro.cloned(); let mut logo_chosen: Option<String> = distro.cloned();
if small_asc.lines != asc.lines && running_dst_sml != "" { if small_asc.lines != asc.lines && running_dst_sml != "" {
let ds_arrangements = [ let ds_arrangements = [
("Default", asc.clone()), ("Default", asc.clone()),
("Small", small_asc.clone()) ("Small", small_asc.clone())
]; ];
let arrangements: IndexMap<Cow<str>, NormalizedAsciiArt> = let arrangements: IndexMap<Cow<str>, NormalizedAsciiArt> =
ds_arrangements.map(|(k, a)| (k.into(), a)).into(); ds_arrangements.map(|(k, a)| (k.into(), a)).into();
@@ -788,15 +1015,15 @@ fn create_config(
// prints small logo w/ big logo // prints small logo w/ big logo
for row in &asciis.into_iter().chunks(usize::from(ascii_per_row)) { for row in &asciis.into_iter().chunks(usize::from(ascii_per_row)) {
let row: Vec<Vec<String>> = row.collect(); let row: Vec<Vec<String>> = row.collect();
for i in 0..usize::from(asc.h).checked_add(1).unwrap() { for i in 0..usize::from(asc.h).checked_add(1).unwrap() {
let mut line = Vec::new(); let mut line = Vec::new();
for lines in &row { for lines in &row {
line.push(&*lines[i]); line.push(&*lines[i]);
} }
printc(line.join(" "), color_mode).context("failed to print ascii line")?; printc(line.join(" "), color_mode).context("failed to print ascii line")?;
} }
println!(); println!();
@@ -807,7 +1034,7 @@ fn create_config(
let choice = literal_input("Your choice?", &opts[..], "default", true, color_mode) let choice = literal_input("Your choice?", &opts[..], "default", true, color_mode)
.context("failed to ask for choice input") .context("failed to ask for choice input")
.context("failed to select logo type").context("failed to ask for choice input")?; .context("failed to select logo type").context("failed to ask for choice input")?;
if choice.to_lowercase() == "small" { if choice.to_lowercase() == "small" {
logo_chosen = Some(running_dst_sml); logo_chosen = Some(running_dst_sml);
asc = small_asc; asc = small_asc;
@@ -934,16 +1161,19 @@ fn create_config(
} }
// Save choice // Save choice
color_align = arrangements color_align = if choice == "horizontal" { ColorAlignment::Horizontal }
.into_iter() else if choice == "vertical" { ColorAlignment::Vertical }
.find_map(|(k, ca)| { else {
if k.to_lowercase() == choice { arrangements.into_iter()
Some(ca) .find_map(|(k, ca)| {
} else { if k.to_lowercase() == choice {
None Some(ca)
} } else {
}) None
.expect("selected color alignment should be valid"); }
})
.expect("selected color alignment is not valid") // TODO: it sould ask the user to retry instead of panicking
};
debug!(?color_align, "selected color alignment"); debug!(?color_align, "selected color alignment");
break; break;
} }
@@ -1050,7 +1280,7 @@ fn create_config(
// Create config // Create config
clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?; clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?;
let config = Config { let config = Config {
preset: preset.as_ref().to_string(), preset: selected_presets,
mode: color_mode, mode: color_mode,
light_dark: Some(theme), light_dark: Some(theme),
auto_detect_light_dark: Some(det_bg.is_some()), auto_detect_light_dark: Some(det_bg.is_some()),
@@ -1061,6 +1291,7 @@ fn create_config(
distro: logo_chosen, distro: logo_chosen,
pride_month_disable: false, pride_month_disable: false,
custom_ascii_path, custom_ascii_path,
custom_presets: None,
}; };
debug!(?config, "created config"); debug!(?config, "created config");
@@ -1139,4 +1370,4 @@ fn init_tracing_subsriber(debug_mode: bool) -> Result<()> {
subscriber subscriber
.try_init() .try_init()
.context("failed to set the global default subscriber") .context("failed to set the global default subscriber")
} }
+1 -1
View File
@@ -55,7 +55,7 @@ pub fn options() -> OptionParser<Options> {
let preset = long("preset") let preset = long("preset")
.short('p') .short('p')
.help(&*format!( .help(&*format!(
"Use preset or comma-separated color list or comma-separated hex colors (e.g., \"#ff0000,#00ff00,#0000ff\") "Use preset or comma-separated color list or comma-separated hex colors (e.g., \"#ff0000,#00ff00,#0000ff\"). Comma-separated preset names will pick one randomly.
PRESET={{{presets}}}", PRESET={{{presets}}}",
presets = <Preset as VariantNames>::VARIANTS presets = <Preset as VariantNames>::VARIANTS
.iter() .iter()
+232
View File
@@ -0,0 +1,232 @@
use std::iter;
use std::num::{NonZeroU8, NonZeroUsize};
use anyhow::{anyhow, Result, Context as _};
use indexmap::IndexSet;
use palette::num::ClampAssign as _;
use palette::{IntoColorMut as _, LinSrgb, Okhsl, Srgb};
use tracing::debug;
use unicode_segmentation::UnicodeSegmentation as _;
use crate::color_util::{ForegroundBackground, Lightness, ToAnsiString as _};
use crate::types::{AnsiMode, TerminalTheme};
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct ColorProfile {
pub colors: Vec<Srgb<u8>>,
}
#[derive(Clone, PartialEq, Debug)]
pub enum AssignLightness {
Replace(Lightness),
ClampMax(Lightness),
ClampMin(Lightness),
}
impl ColorProfile {
pub fn new(colors: Vec<Srgb<u8>>) -> 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(|s| s.as_ref().parse())
.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() {
debug!(?weights, ?self.colors, "length mismatch between `weights` and `colors`");
return Err(anyhow!(
"`weights` should have the same number of elements as `colors`"
));
}
let mut weighted_colors = Vec::new();
for (i, w) in weights.into_iter().enumerate() {
weighted_colors.extend(iter::repeat(self.colors[i]).take(usize::from(w)));
}
Ok(Self::new(weighted_colors))
}
/// Creates a new color profile, with the colors spread to the specified
/// length.
pub fn with_length(&self, length: NonZeroU8) -> Result<Self> {
let orig_len = self.colors.len();
let orig_len: NonZeroUsize = orig_len.try_into().expect("`colors` should not be empty");
let orig_len: NonZeroU8 = orig_len
.try_into()
.expect("`colors` should not have more than 255 elements");
// TODO: I believe weird things can happen because of this...
// if length < orig_len {
// unimplemented!("compressing length of color profile not implemented");
// }
let center_i = usize::from(orig_len.get() / 2);
// How many copies of each color should be displayed at least?
let repeats = length.get().div_euclid(orig_len.get());
let mut weights = vec![repeats; NonZeroUsize::from(orig_len).get()];
// How many extra spaces left?
let mut extras = length.get().rem_euclid(orig_len.get());
// If there is an odd space left, extend the center by one space
if extras % 2 == 1 {
weights[center_i] = weights[center_i].checked_add(1).unwrap();
extras = extras.checked_sub(1).unwrap();
}
// Add weight to border until there's no space left (extras must be even at this
// point)
let weights_len = weights.len();
for border_i in 0..usize::from(extras / 2) {
weights[border_i] = weights[border_i].checked_add(1).unwrap();
let border_opp = weights_len
.checked_sub(border_i)
.unwrap()
.checked_sub(1)
.unwrap();
weights[border_opp] = weights[border_opp].checked_add(1).unwrap();
}
self.with_weights(weights)
}
/// Colors a text.
///
/// # Arguments
///
/// * `foreground_background` - Whether the color is shown on the foreground
/// text or the background block
/// * `space_only` - Whether to only color spaces
pub fn color_text<S>(
&self,
txt: S,
color_mode: AnsiMode,
foreground_background: ForegroundBackground,
space_only: bool,
) -> Result<String>
where
S: AsRef<str>,
{
let txt = txt.as_ref();
let txt: Vec<&str> = txt.graphemes(true).collect();
let ColorProfile { colors } = {
let length = txt.len();
let length: NonZeroUsize = length.try_into().context("`txt` should not be empty")?;
let length: NonZeroU8 = length.try_into().with_context(|| {
format!(
"`txt` should not have more than {limit} characters",
limit = u8::MAX
)
})?;
self.with_length(length)
.with_context(|| format!("failed to spread color profile to length {length}"))?
};
let mut buf = String::new();
for (i, &gr) in txt.iter().enumerate() {
if space_only && gr != " " {
if i > 0 && txt[i.checked_sub(1).unwrap()] == " " {
buf.push_str("\x1b[39;49m");
}
buf.push_str(gr);
} else {
buf.push_str(&colors[i].to_ansi_string(color_mode, foreground_background));
buf.push_str(gr);
}
}
buf.push_str("\x1b[39;49m");
Ok(buf)
}
/// Creates a new color profile, with the colors lightened by a multiplier.
pub fn lighten(&self, multiplier: f32) -> Self {
let mut rgb_f32_colors: Vec<LinSrgb> =
self.colors.iter().map(|c| c.into_linear()).collect();
{
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
for okhsl_f32_color in okhsl_f32_colors {
okhsl_f32_color.lightness *= multiplier;
}
}
let rgb_u8_colors: Vec<_> = rgb_f32_colors
.into_iter()
.map(Srgb::<u8>::from_linear)
.collect();
Self {
colors: rgb_u8_colors,
}
}
/// Creates a new color profile, with the colors set to the specified
/// [`Okhsl`] lightness value.
pub fn with_lightness(&self, assign_lightness: AssignLightness) -> Self {
let mut rgb_f32_colors: Vec<LinSrgb> =
self.colors.iter().map(|c| c.into_linear()).collect();
{
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
for okhsl_f32_color in okhsl_f32_colors {
match assign_lightness {
AssignLightness::Replace(lightness) => {
okhsl_f32_color.lightness = lightness.into();
},
AssignLightness::ClampMax(lightness) => {
okhsl_f32_color.lightness.clamp_max_assign(lightness.into());
},
AssignLightness::ClampMin(lightness) => {
okhsl_f32_color.lightness.clamp_min_assign(lightness.into());
},
}
}
}
let rgb_u8_colors: Vec<Srgb<u8>> = rgb_f32_colors
.into_iter()
.map(Srgb::<u8>::from_linear)
.collect();
Self {
colors: rgb_u8_colors,
}
}
/// Creates a new color profile, with the colors set to the specified
/// [`Okhsl`] lightness value, adapted to the terminal theme.
pub fn with_lightness_adaptive(&self, lightness: Lightness, theme: TerminalTheme) -> Self {
match theme {
TerminalTheme::Dark => self.with_lightness(AssignLightness::ClampMin(lightness)),
TerminalTheme::Light => self.with_lightness(AssignLightness::ClampMax(lightness)),
}
}
/// Creates another color profile with only the unique colors.
pub fn unique_colors(&self) -> Self {
let unique_colors: IndexSet<[u8; 3]> = self.colors.iter().map(|&c| c.into()).collect();
let unique_colors: Vec<Srgb<u8>> = unique_colors.into_iter().map(|c| c.into()).collect();
Self::new(unique_colors)
}
}
+1
View File
@@ -9,3 +9,4 @@ pub mod presets;
pub mod pride_month; pub mod pride_month;
pub mod types; pub mod types;
pub mod utils; pub mod utils;
pub mod color_profile;
+70 -1
View File
@@ -1,12 +1,16 @@
use std::collections::HashMap;
use anyhow::{Context as _, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::color_profile::ColorProfile;
use crate::color_util::Lightness; use crate::color_util::Lightness;
use crate::neofetch_util::ColorAlignment; use crate::neofetch_util::ColorAlignment;
use crate::types::{AnsiMode, Backend, TerminalTheme}; use crate::types::{AnsiMode, Backend, TerminalTheme};
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Config { pub struct Config {
pub preset: String, pub preset: PresetValue,
pub mode: AnsiMode, pub mode: AnsiMode,
pub auto_detect_light_dark: Option<bool>, pub auto_detect_light_dark: Option<bool>,
pub light_dark: Option<TerminalTheme>, pub light_dark: Option<TerminalTheme>,
@@ -19,6 +23,7 @@ pub struct Config {
pub distro: Option<String>, pub distro: Option<String>,
pub pride_month_disable: bool, pub pride_month_disable: bool,
pub custom_ascii_path: Option<String>, pub custom_ascii_path: Option<String>,
pub custom_presets: Option<HashMap<String, Vec<String>>>,
} }
impl Config { impl Config {
@@ -32,6 +37,40 @@ impl Config {
}, },
} }
} }
pub fn custom_preset_profiles(&self) -> Result<HashMap<String, ColorProfile>> {
let mut profiles = HashMap::new();
if let Some(custom_presets) = &self.custom_presets {
for (preset_name, colors) in custom_presets {
if preset_name == "random" {
return Err(anyhow::anyhow!("custom preset key `random` is reserved"));
}
let color_profile = build_hex_color_profile(colors).with_context(|| {
format!("failed to validate custom preset key `{preset_name}`")
})?;
profiles.insert(preset_name.clone(), color_profile);
}
}
Ok(profiles)
}
}
pub fn build_hex_color_profile(hex_colors: &[String]) -> Result<ColorProfile> {
if hex_colors.is_empty() {
return Err(anyhow::anyhow!("hex color list cannot be empty"));
}
for color in hex_colors {
if !color.starts_with('#')
|| (color.len() != 4 && color.len() != 7)
|| !color[1..].chars().all(|c| c.is_ascii_hexdigit())
{
return Err(anyhow::anyhow!("invalid hex color: {color}"));
}
}
ColorProfile::from_hex_colors(hex_colors.to_vec())
.context("failed to create color profile from hex")
} }
mod args_serde { mod args_serde {
@@ -117,3 +156,33 @@ mod args_serde {
deserializer.deserialize_option(OptionVisitor) deserializer.deserialize_option(OptionVisitor)
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PresetValue {
Single(String),
Multiple(Vec<String>),
}
impl From<String> for PresetValue {
fn from(s: String) -> Self {
PresetValue::Single(s)
}
}
impl PresetValue {
pub fn get_random_if_multiple(&self) -> String {
match self {
PresetValue::Single(s) => s.clone(),
PresetValue::Multiple(v) => {
if v.is_empty() {
"random".to_owned()
} else {
let mut rng = fastrand::Rng::new();
let selected_index = rng.usize(0..v.len());
v[selected_index].clone()
}
}
}
}
}
+64 -87
View File
@@ -2,7 +2,9 @@ use std::borrow::Cow;
use std::ffi::OsStr; use std::ffi::OsStr;
#[cfg(feature = "macchina")] #[cfg(feature = "macchina")]
use std::fs; use std::fs;
use std::io::{self, Write as _}; use std::io::{Write as _};
#[cfg(windows)]
use std::io::{self};
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::sync::OnceLock; use std::sync::OnceLock;
@@ -153,7 +155,13 @@ pub fn add_pkg_path() -> Result<()> {
// Get PATH // Get PATH
let pv = &env::var_os("PATH").context("`PATH` env var is not set or invalid")?; let pv = &env::var_os("PATH").context("`PATH` env var is not set or invalid")?;
let mut path = env::split_paths(pv).collect::<Vec<_>>(); let mut path = env::split_paths(pv).collect::<Vec<_>>();
let exe = env::current_exe().context("failed to get path of current running executable")?; let exe = match env::current_exe() {
Ok(exe) => exe,
Err(e) => {
debug!("Failed to get path of current running executable: {}", e);
return Ok(());
}
};
let base = exe.parent().unwrap(); let base = exe.parent().unwrap();
// Add from bin: ../git, ../fastfetch, ../scripts // Add from bin: ../git, ../fastfetch, ../scripts
@@ -233,27 +241,27 @@ pub fn get_distro_ascii<S>(distro: Option<S>, backend: Backend) -> Result<RawAsc
where where
S: AsRef<str> + fmt::Debug, S: AsRef<str> + fmt::Debug,
{ {
let distro: Cow<_> = if let Some(distro) = distro.as_ref() { let distro_name: Cow<_> = if let Some(distro) = distro.as_ref() {
distro.as_ref().into() distro.as_ref().into()
} else { } else {
get_distro_name(backend) get_distro_name(backend)
.context("failed to get distro name")? .context("failed to get distro name")?
.into() .into()
}; };
debug!(%distro, "distro name"); debug!(%distro_name, "distro name");
// Try new codegen-based detection method // Try new codegen-based detection method
if let Some(distro) = Distro::detect(&distro) { if let Some(distro) = Distro::detect(&distro_name) {
let asc = distro.ascii_art().to_owned(); let asc = distro.ascii_art().to_owned();
let fg = ascii_foreground(&distro); let fg = ascii_foreground(&distro);
return Ok(RawAsciiArt { asc, fg }); return Ok(RawAsciiArt { asc, fg });
} }
debug!(%distro, "could not find a match for distro; falling back to neofetch"); debug!(%distro_name, "could not find a match for distro; falling back to neofetch");
// Old detection method that calls neofetch // Old detection method that calls neofetch
let asc = run_neofetch_command_piped(&["print_ascii", "--ascii_distro", distro.as_ref()]) let asc = run_neofetch_command_piped(&["print_ascii", "--ascii_distro", distro_name.as_ref()])
.context("failed to get ascii art from neofetch")?; .context("failed to get ascii art from neofetch")?;
// Unescape backslashes here because backslashes are escaped in neofetch for // Unescape backslashes here because backslashes are escaped in neofetch for
@@ -314,31 +322,53 @@ where
/// Gets the absolute path of the bash command. /// Gets the absolute path of the bash command.
#[cfg(windows)] #[cfg(windows)]
fn bash_path() -> Result<PathBuf> { fn bash_path() -> Result<PathBuf> {
// Find `bash.exe` in `PATH`, but exclude the known bad paths // 1. Try to find a good bash.exe in PATH
if let Some(bash_path) = find_in_path("bash.exe").context("bash.exe not found")? { let bash_in_path = find_in_path("bash.exe").unwrap_or(None);
// Check if it's not MSYS bash https://stackoverflow.com/a/58418686/1529493 if let Some(pth) = &bash_in_path {
if !bash_path.ends_with(r"Git\usr\bin\bash.exe") { // Check if it's not WSL bash
// Check if it's not WSL bash // See https://github.com/hykilpikonna/hyfetch/issues/233
// See https://github.com/hykilpikonna/hyfetch/issues/233 let is_wsl = (|| {
let windir = env::var_os("windir").context("`windir` environ not found")?; let windir = env::var_os("windir")?;
match is_same_file(&bash_path, Path::new(&windir).join(r"System32\bash.exe")) { let wsl_bash = Path::new(&windir).join(r"System32\bash.exe");
Ok(false) => return Ok(bash_path), Some(is_same_file(pth, &wsl_bash).unwrap_or(false))
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(bash_path), })()
_ => {} .unwrap_or(false);
if !is_wsl {
// Check if it's not MSYS bash https://stackoverflow.com/a/58418686/1529493
// We prefer the Git wrapper bash if possible, but we'll accept this if it's all we have.
if !pth.ends_with(r"Git\usr\bin\bash.exe") {
return Ok(pth.clone());
} }
} }
} }
if let Some(bash_path) = find_in_path("git.exe").context("failed to find `git.exe` in `PATH`")? { // 2. Try to find git.exe in PATH and look for bash.exe relative to it
if bash_path.ends_with(r"Git\cmd\git.exe") { if let Ok(Some(git_path)) = find_in_path("git.exe") {
let pth = bash_path.parent().unwrap().parent().unwrap().join(r"bin\bash.exe"); let mut current = git_path.clone();
if pth.is_file() { for _ in 0..3 {
return Ok(pth); if let Some(parent) = current.parent() {
let bin_bash = parent.join(r"bin\bash.exe");
if bin_bash.is_file() {
return Ok(bin_bash);
}
let usr_bin_bash = parent.join(r"usr\bin\bash.exe");
if usr_bin_bash.is_file() {
return Ok(usr_bin_bash);
}
current = parent.to_path_buf();
} else {
break;
} }
} }
} }
Err(anyhow!("bash.exe not found")) // 3. Fallback to whatever bash we found in PATH (even if it was the MSYS one)
if let Some(pth) = bash_in_path {
return Ok(pth);
}
Err(anyhow!("bash.exe not found. Please ensure Git for Windows is installed and in your PATH."))
} }
/// Runs neofetch command, returning the piped stdout output. /// Runs neofetch command, returning the piped stdout output.
@@ -501,7 +531,7 @@ pub fn get_distro_name(backend: Backend) -> Result<String> {
doc["spacing"] = value(0); doc["spacing"] = value(0);
doc["padding"] = value(0); doc["padding"] = value(0);
// See https://github.com/Macchina-CLI/macchina/issues/319 // See https://github.com/Macchina-CLI/macchina/issues/319
// doc["hide_ascii"] = value(true); doc["hide_ascii"] = value(false);
doc["separator"] = value(""); doc["separator"] = value("");
doc["custom_ascii"] = Item::Table(Table::from_iter([( doc["custom_ascii"] = Item::Table(Table::from_iter([(
"path", "path",
@@ -532,8 +562,11 @@ pub fn get_distro_name(backend: Backend) -> Result<String> {
]; ];
run_macchina_command_piped(&args[..]) run_macchina_command_piped(&args[..])
.map(|s| { .map(|s| {
anstream::adapter::strip_str(&s) let s = anstream::adapter::strip_str(&s).to_string();
.to_string() let s = s.trim();
s.splitn(2, '-')
.last()
.expect("splitn with 2 should always have at least 1 element")
.trim() .trim()
.to_owned() .to_owned()
}) })
@@ -653,6 +686,7 @@ fn run_macchina(asc: String, args: Option<&Vec<String>>) -> Result<()> {
.context("failed to create temp file for macchina theme")?; .context("failed to create temp file for macchina theme")?;
let theme_doc = { let theme_doc = {
let mut doc = DocumentMut::new(); let mut doc = DocumentMut::new();
doc["hide_ascii"] = value(false);
doc["custom_ascii"] = Item::Table(Table::from_iter([( doc["custom_ascii"] = Item::Table(Table::from_iter([(
"path", "path",
&*asc_file_path.to_string_lossy(), &*asc_file_path.to_string_lossy(),
@@ -694,65 +728,8 @@ fn run_macchina(asc: String, args: Option<&Vec<String>>) -> Result<()> {
/// Gets the color indices that should be considered as foreground, for a /// Gets the color indices that should be considered as foreground, for a
/// particular distro's ascii art. /// particular distro's ascii art.
fn ascii_foreground(distro: &Distro) -> Vec<NeofetchAsciiIndexedColor> { fn ascii_foreground(distro: &Distro) -> Vec<NeofetchAsciiIndexedColor> {
let fg: Vec<u8> = match distro { distro.foreground()
Distro::Anarchy => vec![2], .iter()
Distro::Android => vec![2], .map(|&f| f.try_into().expect("neofetch color index should be valid"))
Distro::Antergos => vec![1],
Distro::ArchStrike => vec![2],
Distro::Arkane => vec![1],
Distro::Asahi => vec![5],
Distro::Astra_Linux => vec![2],
Distro::BlackArch => vec![3],
Distro::CelOS => vec![3],
Distro::Chapeau => vec![2],
Distro::Chrom => vec![5],
Distro::Clear_Linux_OS => vec![2],
Distro::Container_Linux_by_CoreOS => vec![3],
Distro::CRUX => vec![3],
Distro::EuroLinux => vec![2],
Distro::eweOS => vec![3],
Distro::Fedora => vec![2],
Distro::Fedora_Sericea => vec![2],
Distro::Fedora_Silverblue => vec![2],
Distro::GalliumOS => vec![2],
Distro::Gentoo => vec![1],
Distro::HarDClanZ => vec![2],
Distro::Kibojoe => vec![3],
Distro::KrassOS => vec![2],
Distro::Kubuntu => vec![2],
Distro::Linux => vec![1],
Distro::LinuxFromScratch => vec![1, 3],
Distro::Lubuntu => vec![2],
Distro::openEuler => vec![2],
Distro::orchid => vec![1],
Distro::Panwah => vec![1],
Distro::Peppermint => vec![2],
Distro::PNM_Linux => vec![2],
Distro::Pop__OS => vec![2],
Distro::Reborn_OS => vec![1],
Distro::SalentOS => vec![4],
Distro::Septor => vec![2],
Distro::Ubuntu_Cinnamon => vec![2],
Distro::Ubuntu_Kylin => vec![2],
Distro::Ubuntu_MATE => vec![2],
Distro::Ubuntu_old => vec![2],
Distro::Ubuntu_Studio => vec![2],
Distro::Ubuntu_Sway => vec![2],
Distro::Ultramarine_Linux => vec![2],
Distro::Univention => vec![2],
Distro::uwuntu => vec![2],
Distro::Vanilla => vec![2],
Distro::VNux => vec![3, 5],
Distro::Void => vec![2],
Distro::Xray_OS => vec![2, 3],
Distro::Xubuntu => vec![2],
_ => Vec::new(),
};
fg.into_iter()
.map(|fore| {
fore.try_into()
.expect("`fore` should be a valid neofetch color index")
})
.collect() .collect()
} }
+2 -931
View File
@@ -1,932 +1,3 @@
use std::iter; #![allow(non_camel_case_types)]
use std::num::{NonZeroU8, NonZeroUsize};
use anyhow::{anyhow, Context as _, Result}; include!(concat!(env!("OUT_DIR"), "/presets.rs"));
use indexmap::IndexSet;
use palette::num::ClampAssign as _;
use palette::{IntoColorMut as _, LinSrgb, Okhsl, Srgb};
use serde::{Deserialize, Serialize};
use strum::{AsRefStr, EnumCount, EnumString, VariantArray, VariantNames};
use tracing::debug;
use unicode_segmentation::UnicodeSegmentation as _;
use crate::color_util::{ForegroundBackground, Lightness, ToAnsiString as _};
use crate::types::{AnsiMode, TerminalTheme};
#[derive(
Copy,
Clone,
Hash,
Debug,
AsRefStr,
Deserialize,
EnumCount,
EnumString,
Serialize,
VariantArray,
VariantNames,
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
pub enum Preset {
Rainbow,
Transgender,
Nonbinary,
Xenogender,
Agender,
Queer,
Genderfluid,
Bisexual,
Pansexual,
Polysexual,
Omnisexual,
Omniromantic,
GayMen,
Lesbian,
Abrosexual,
Asexual,
Aromantic,
Fictosexual,
Aroace1,
Aroace2,
Aroace3,
Greysexual,
Autosexual,
Intergender,
Greygender,
Akiosexual,
Bigender,
Demigender,
Demiboy,
Demigirl,
Transmasculine,
Transfeminine,
Genderfaun,
Demifaun,
Genderfae,
Demifae,
Neutrois,
Biromantic1,
Autoromantic,
Boyflux2,
Girlflux,
Genderflux,
Nullflux,
Hypergender, Hyperboy, Hypergirl, Hyperandrogyne, Hyperneutrois,
Finsexual,
Unlabeled1,
Unlabeled2,
Pangender,
/// High-contrast version of pangender flag
#[serde(rename = "pangender.contrast")]
#[strum(serialize = "pangender.contrast")]
PangenderContrast,
#[serde(rename = "gendernonconforming1")]
#[strum(serialize = "gendernonconforming1")]
GenderNonconforming1,
#[serde(rename = "gendernonconforming2")]
#[strum(serialize = "gendernonconforming2")]
GenderNonconforming2,
Femboy,
Tomboy,
Gynesexual,
Androsexual,
Gendervoid,
Voidgirl,
Voidboy,
NonhumanUnity,
/// For all the dogs
Caninekin,
Plural,
Fraysexual,
Bear,
Butch,
Leather,
Otter,
Twink,
Adipophilia,
Kenochoric,
Veldian,
Solian,
Lunian,
Polyam,
Sapphic,
Androgyne,
Interprogress,
Progress,
Intersex,
OldPolyam,
EqualRights,
Drag,
Pronounfluid,
Pronounflux,
Exipronoun,
Neopronoun,
Neofluid,
Genderqueer,
Cisgender,
/// Colors from Gilbert Baker's original 1978 flag design
Baker,
/// Meme flag
Beiyang,
/// Meme flag
Burger,
/// Meme flag
#[serde(rename = "throatlozenges")]
#[strum(serialize = "throatlozenges")]
ThroatLozenges,
/// Meme flag
Band,
Libragender, Librafeminine, Libramasculine, Libraandrogyne, Libranonbinary,
Fluidfluxa, Fluidfluxb,
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct ColorProfile {
pub colors: Vec<Srgb<u8>>,
}
#[derive(Clone, PartialEq, Debug)]
pub enum AssignLightness {
Replace(Lightness),
ClampMax(Lightness),
ClampMin(Lightness),
}
impl Preset {
pub fn color_profile(&self) -> ColorProfile {
(match self {
Self::Rainbow => ColorProfile::from_hex_colors(vec![
"#E50000", "#FF8D00", "#FFEE00", "#028121", "#004CFF", "#770088",
]),
Self::Transgender => ColorProfile::from_hex_colors(vec![
"#55CDFD", "#F6AAB7", "#FFFFFF", "#F6AAB7", "#55CDFD",
]),
Self::Nonbinary => {
ColorProfile::from_hex_colors(vec!["#FCF431", "#FCFCFC", "#9D59D2", "#282828"])
},
// sourced from https://commons.wikimedia.org/wiki/File:Xenogender_pride_flag.svg
Self::Xenogender => ColorProfile::from_hex_colors(vec![
"#FF6692", "#FF9A98", "#FFB883", "#FBFFA8", "#85BCFF", "#9D85FF", "#A510FF",
]),
Self::Agender => ColorProfile::from_hex_colors(vec![
"#000000", "#BABABA", "#FFFFFF", "#BAF484", "#FFFFFF", "#BABABA", "#000000",
]),
Self::Queer => ColorProfile::from_hex_colors(vec!["#B57FDD", "#FFFFFF", "#49821E"]),
Self::Genderfluid => ColorProfile::from_hex_colors(vec![
"#FE76A2", "#FFFFFF", "#BF12D7", "#000000", "#303CBE",
]),
Self::Bisexual => ColorProfile::from_hex_colors(vec!["#D60270", "#9B4F96", "#0038A8"]),
Self::Pansexual => ColorProfile::from_hex_colors(vec!["#FF1C8D", "#FFD700", "#1AB3FF"]),
Self::Polysexual => {
ColorProfile::from_hex_colors(vec!["#F714BA", "#01D66A", "#1594F6"])
},
// sourced from https://www.flagcolorcodes.com/omnisexual
Self::Omnisexual => ColorProfile::from_hex_colors(vec![
"#FE9ACE", "#FF53BF", "#200044", "#6760FE", "#8EA6FF",
]),
Self::Omniromantic => ColorProfile::from_hex_colors(vec![
"#FEC8E4", "#FDA1DB", "#89739A", "#ABA7FE", "#BFCEFF",
]),
// sourced from https://www.flagcolorcodes.com/gay-men
Self::GayMen => ColorProfile::from_hex_colors(vec![
"#078D70", "#98E8C1", "#FFFFFF", "#7BADE2", "#3D1A78",
]),
Self::Lesbian => ColorProfile::from_hex_colors(vec![
"#D62800", "#FF9B56", "#FFFFFF", "#D462A6", "#A40062",
]),
// 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::Asexual => {
ColorProfile::from_hex_colors(vec!["#000000", "#A4A4A4", "#FFFFFF", "#810081"])
},
Self::Aromantic => ColorProfile::from_hex_colors(vec![
"#3BA740", "#A8D47A", "#FFFFFF", "#ABABAB", "#000000",
]),
// https://orientation.fandom.com/wiki/Fictosexual
Self::Fictosexual => ColorProfile::from_hex_colors(vec![
"#000000", "#C4C4C4", "#A349A5", "#C4C4C4", "#000000",
]),
// 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",
]),
// sourced from https://www.flagcolorcodes.com/greysexual
Self::Greysexual => ColorProfile::from_hex_colors(vec![
"#740194", "#AEB1AA", "#FFFFFF", "#AEB1AA", "#740194",
]),
// sourced from https://www.flagcolorcodes.com/autosexual
Self::Autosexual => ColorProfile::from_hex_colors(vec!["#99D9EA", "#7F7F7F"]),
// sourced from https://www.flagcolorcodes.com/intergender
Self::Intergender => {
ColorProfile::from_hex_colors(vec!["#900DC2", "#FFE54F", "#900DC2"])
.and_then(|c| c.with_weights(vec![2, 1, 2]))
},
// sourced from https://www.flagcolorcodes.com/greygender
Self::Greygender => ColorProfile::from_hex_colors(vec![
"#B3B3B3", "#FFFFFF", "#062383", "#FFFFFF", "#535353",
])
.and_then(|c| c.with_weights(vec![2, 1, 2, 1, 2])),
// sourced from https://www.flagcolorcodes.com/akiosexual
Self::Akiosexual => ColorProfile::from_hex_colors(vec![
"#F9485E", "#FEA06A", "#FEF44C", "#FFFFFF", "#000000",
]),
// sourced from https://www.flagcolorcodes.com/bigender
Self::Bigender => ColorProfile::from_hex_colors(vec![
"#C479A2", "#EDA5CD", "#D6C7E8", "#FFFFFF", "#D6C7E8", "#9AC7E8", "#6D82D1",
]),
// 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/demiboy
Self::Demiboy => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C4C4C4", "#9DD7EA", "#FFFFFF", "#9DD7EA", "#C4C4C4", "#7F7F7F",
]),
// sourced from https://www.flagcolorcodes.com/demigirl
Self::Demigirl => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C4C4C4", "#FDADC8", "#FFFFFF", "#FDADC8", "#C4C4C4", "#7F7F7F",
]),
// sourced from https://www.flagcolorcodes.com/transmasculine
Self::Transmasculine => ColorProfile::from_hex_colors(vec![
"#FF8ABD", "#CDF5FE", "#9AEBFF", "#74DFFF", "#9AEBFF", "#CDF5FE", "#FF8ABD",
]),
// 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",
]),
// sourced from https://www.flagcolorcodes.com/genderfaun
Self::Genderfaun => ColorProfile::from_hex_colors(vec![
"#FCD689", "#FFF09B", "#FAF9CD", "#FFFFFF", "#8EDED9", "#8CACDE", "#9782EC",
]),
// sourced from https://www.flagcolorcodes.com/demifaun
Self::Demifaun => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C6C6C6", "#FCC688", "#FFF19C", "#FFFFFF", "#8DE0D5", "#9682EC",
"#C6C6C6", "#7F7F7F",
])
.and_then(|c| c.with_weights(vec![2, 2, 1, 1, 1, 1, 1, 2, 2])),
// sourced from https://www.flagcolorcodes.com/genderfae
Self::Genderfae => ColorProfile::from_hex_colors(vec![
"#97C3A5", "#C3DEAE", "#F9FACD", "#FFFFFF", "#FCA2C4", "#DB8AE4", "#A97EDD",
]),
// used colorpicker to source form https://www.deviantart.com/pride-flags/art/Demifae-870194777
Self::Demifae => ColorProfile::from_hex_colors(vec![
"#7F7F7F", "#C5C5C5", "#97C3A4", "#C4DEAE", "#FFFFFF", "#FCA2C5", "#AB7EDF",
"#C5C5C5", "#7F7F7F",
])
.and_then(|c| c.with_weights(vec![2, 2, 1, 1, 1, 1, 1, 2, 2])),
// sourced from https://www.flagcolorcodes.com/neutrois
Self::Neutrois => ColorProfile::from_hex_colors(vec!["#FFFFFF", "#1F9F00", "#000000"]),
// sourced from https://www.flagcolorcodes.com/biromantic-alternate-2
Self::Biromantic1 => ColorProfile::from_hex_colors(vec![
"#8869A5", "#D8A7D8", "#FFFFFF", "#FDB18D", "#151638",
]),
// sourced from https://www.flagcolorcodes.com/autoromantic
Self::Autoromantic => ColorProfile::from_hex_colors(
// symbol interpreted
vec!["#99D9EA", "#3DA542", "#7F7F7F"],
)
.and_then(|c| c.with_weights(vec![2, 1, 2])),
// 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])),
// 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.deviantart.com/pride-flags/art/Genderflux-1-543925589
Self::Genderflux => ColorProfile::from_hex_colors(vec![
"f47694", "f2a2b9", "cecece", "7ce0f7", "3ecdf9", "fff48d",
]),
Self::Nullflux => ColorProfile::from_hex_colors(vec![
"#0B0C0E", "#A28DB9", "#E1D4EF", "#F0E6DD", "#665858",
]),
Self::Hypergender => ColorProfile::from_hex_colors(vec![
"#EFEFEF", "#FFFFFF", "#FBFF75", "#000000", "#FBFF75", "#FFFFFF", "#EFEFEF",
]),
Self::Hyperboy => ColorProfile::from_hex_colors(vec![
"#EFEFEF", "#FFFFFF", "#74D7FE", "#000000", "#74D7FE", "#FFFFFF", "#EFEFEF",
]),
Self::Hypergirl => ColorProfile::from_hex_colors(vec![
"#EFEFEF", "#FFFFFF", "#FC76D3", "#000000", "#FC76D3", "#FFFFFF", "#EFEFEF",
]),
Self::Hyperandrogyne => ColorProfile::from_hex_colors(vec![
"#EFEFEF", "#FFFFFF", "#BB83FF", "#000000", "#BB83FF", "#FFFFFF", "#EFEFEF",
]),
Self::Hyperneutrois => ColorProfile::from_hex_colors(vec![
"#EFEFEF", "#FFFFFF", "#BAFA74", "#000000", "#BAFA74", "#FFFFFF", "#EFEFEF",
]),
// sourced from https://lgbtqia.wiki/wiki/Finsexual
Self::Finsexual => ColorProfile::from_hex_colors(vec![
"#B18EDF", "#D7B1E2", "#F7CDE9", "#F39FCE", "#EA7BB3",
]),
// 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",
]),
Self::Pangender => ColorProfile::from_hex_colors(vec![
"#FFF798", "#FEDDCD", "#FFEBFB", "#FFFFFF", "#FFEBFB", "#FEDDCD", "#FFF798",
]),
// high-contrast version of pangender flag
Self::PangenderContrast => ColorProfile::from_hex_colors(vec![
"#ffe87f", "#fcbaa6", "#fbc9f3", "#FFFFFF", "#fbc9f3", "#fcbaa6", "#ffe87f",
]),
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",
]),
Self::Femboy => ColorProfile::from_hex_colors(vec![
"#d260a5", "#e4afcd", "#fefefe", "#57cef8", "#fefefe", "#e4afcd", "#d260a5",
]),
Self::Tomboy => ColorProfile::from_hex_colors(vec![
"#2f3fb9", "#613a03", "#fefefe", "#f1a9b7", "#fefefe", "#613a03", "#2f3fb9",
]),
// sourced from https://lgbtqia.fandom.com/wiki/Gynesexual
Self::Gynesexual => {
ColorProfile::from_hex_colors(vec!["#F4A9B7", "#903F2B", "#5B953B"])
},
// sourced from https://lgbtqia.fandom.com/wiki/Androsexual
Self::Androsexual => {
ColorProfile::from_hex_colors(vec!["#01CCFF", "#603524", "#B799DE"])
},
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Gendervoid => ColorProfile::from_hex_colors(vec![
"#081149", "#4B484B", "#000000", "#4B484B", "#081149",
]),
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Voidgirl => ColorProfile::from_hex_colors(vec![
"#180827", "#7A5A8B", "#E09BED", "#7A5A8B", "#180827",
]),
// sourced from: https://gender.fandom.com/wiki/Gendervoid
Self::Voidboy => ColorProfile::from_hex_colors(vec![
"#0B130C", "#547655", "#66B969", "#547655", "#0B130C",
]),
// used https://twitter.com/foxbrained/status/1667621855518236674/photo/1 as source and colorpicked
Self::NonhumanUnity => {
ColorProfile::from_hex_colors(vec!["#177B49", "#FFFFFF", "#593C90"])
},
// used https://www.tumblr.com/zombpawcoins/745062851267493888/caninekin-canine-therian-flag
Self::Caninekin => ColorProfile::from_hex_colors(vec![
"#2d2822", "#543d25", "#9c754d", "#e8dac2", "#cfad8c", "#b77b55", "#954e31",
]),
// 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",
]),
// 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://commons.wikimedia.org/wiki/File:Bear_Brotherhood_flag.svg
Self::Bear => ColorProfile::from_hex_colors(vec![
"#623804", "#D56300", "#FEDD63", "#FEE6B8", "#FFFFFF", "#555555",
]),
// colorpicked from https://commons.wikimedia.org/wiki/File:Butch_Flag.png
Self::Butch => ColorProfile::from_hex_colors(vec![
"#D72800", "#F17623", "#FF9C56", "#FFFDF6", "#FFCE89", "#FEAF02", "#A37000",
]),
// colorpicked from https://commons.wikimedia.org/wiki/File:Leather,_Latex,_and_BDSM_pride_-_Light.svg
Self::Leather => ColorProfile::from_hex_colors(vec![
"#000000", "#252580", "#000000", "#252580", "#FFFFFF", "#252580", "#000000",
"#252580", "#000000",
]),
// colorpicked from https://commons.wikimedia.org/wiki/File:Official_Otter_Pride_Flag_by_Bearbackgear.jpg
Self::Otter => ColorProfile::from_hex_colors(vec![
"#263881", "#5C9DC9", "#FFFFFF", "#3A291D", "#5C9DC9", "#263881",
]),
// colorpicked from https://commons.wikimedia.org/wiki/File:Twink_Pride_Flag_(proposed).svg
Self::Twink => ColorProfile::from_hex_colors(vec!["#FFB2FF", "#FFFFFF", "#FFFF81"]),
// https://en.wikipedia.org/wiki/File:FatFetishFlag.png
Self::Adipophilia => ColorProfile::from_hex_colors(vec![
"#000000", "#E16180", "#FFF9BE", "#603E41", "#000000",
]),
Self::Kenochoric => {
ColorProfile::from_hex_colors(vec!["#000000", "#2E1569", "#824DB7", "#C7A1D6"])
},
Self::Veldian => ColorProfile::from_hex_colors(vec![
"#D182A8", "#FAF6E0", "#69ACBE", "#5D448F", "#3A113E",
]),
Self::Solian => ColorProfile::from_hex_colors(vec![
"#FFF8ED", "#FFE7A8", "#F1B870", "#A56058", "#46281E",
]),
Self::Lunian => ColorProfile::from_hex_colors(vec![
"#2F0E62", "#6F41B1", "#889FDF", "#7DDFD5", "#D2F2E2",
]),
// pulled from https://polyamproud.com/flag
Self::Polyam => ColorProfile::from_hex_colors(vec![
"#FFFFFF", "#FCBF00", "#009FE3", "#E50051", "#340C46",
]),
Self::Sapphic => ColorProfile::from_hex_colors(vec![
"#FD8BA8", "#FBF2FF", "#C76BC5", "#FDD768", "#C76BC5", "#FBF2FF", "#FD8BA8",
]),
Self::Androgyne => ColorProfile::from_hex_colors(vec!["#FE007F", "#9832FF", "#00B8E7"]),
Self::Interprogress => ColorProfile::from_hex_colors(vec![
"#FFD800", "#7902AA", "#FFFFFF", "#FFAFC8", "#74D7EE", "#613915", "#000000",
"#E50000", "#FF8D00", "#FFEE00", "#028121", "#004CFF", "#770088",
]),
Self::Progress => ColorProfile::from_hex_colors(vec![
"#FFFFFF", "#FFAFC8", "#74D7EE", "#613915", "#000000", "#E50000", "#FF8D00",
"#FFEE00", "#028121", "#004CFF", "#770088",
]),
Self::Intersex => ColorProfile::from_hex_colors(vec!["#FFD800", "#7902AA", "#FFD800"])
.and_then(|c| c.with_weights(vec![2, 1, 2])),
Self::OldPolyam => ColorProfile::from_hex_colors(vec![
"#0000FF", "#FF0000", "#FFFF00", "#FF0000", "#000000",
]),
Self::EqualRights => ColorProfile::from_hex_colors(vec![
"#0000FF", "#FFFF00", "#0000FF", "#FFFF00", "#0000FF",
])
.and_then(|c| c.with_weights(vec![2, 1, 2, 1, 2])),
Self::Drag => ColorProfile::from_hex_colors(vec![
"#CC67FF", "#FFFFFF", "#FFA3E3", "#FFFFFF", "#3366FF",
]),
Self::Pronounfluid => ColorProfile::from_hex_colors(vec![
"#FFB3F9", "#FFFFFF", "#D1FDCB", "#C7B0FF", "#000000", "#B8CCFF",
]),
Self::Pronounflux => ColorProfile::from_hex_colors(vec![
"#FDB3F8", "#B6CCFA", "#18DDD3", "#64FF89", "#FF7690", "#FFFFFF",
]),
Self::Exipronoun => {
ColorProfile::from_hex_colors(vec!["#1C3D34", "#FFFFFF", "#321848", "#000000"])
},
Self::Neopronoun => {
ColorProfile::from_hex_colors(vec!["#BCEC64", "#FFFFFF", "#38077A"])
},
Self::Neofluid => ColorProfile::from_hex_colors(vec![
"#FFECA0", "#FFFFFF", "#FFECA0", "#38087A", "#BCEC64",
]),
Self::Genderqueer => ColorProfile::from_hex_colors(vec![
"#B57EDC", "#FFFFFF", "#4A8123"
]),
Self::Cisgender => ColorProfile::from_hex_colors(vec![
"#D70270", "#0038A7"
]),
// 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",
]),
Self::Burger => ColorProfile::from_hex_colors(vec![
"#F3A26A", "#498701", "#FD1C13", "#7D3829", "#F3A26A",
]),
Self::ThroatLozenges => ColorProfile::from_hex_colors(vec![
"#2759DA", "#03940D", "#F5F100", "#F59B00", "#B71212",
]),
Self::Band => ColorProfile::from_hex_colors(vec![
"#2670C0", "#F5BD00", "#DC0045", "#E0608E"
]),
Self::Libragender => ColorProfile::from_hex_colors(vec![
"#000000", "#808080", "#92D8E9", "#FFF544", "#FFB0CA", "#808080", "#000000"
]),
Self::Librafeminine => ColorProfile::from_hex_colors(vec![
"#000000", "#A3A3A3", "#FFFFFF", "#C6568F", "#FFFFFF", "#A3A3A3", "#000000"
]),
Self::Libramasculine => ColorProfile::from_hex_colors(vec![
"#000000", "#A3A3A3", "#FFFFFF", "#56C5C5", "#FFFFFF", "#A3A3A3", "#000000"
]),
Self::Libraandrogyne => ColorProfile::from_hex_colors(vec![
"#000000", "#A3A3A3", "#FFFFFF", "#9186B1", "#FFFFFF", "#A3A3A3", "#000000"
]),
Self::Libranonbinary => ColorProfile::from_hex_colors(vec![
"#000000", "#A3A3A3", "#FFFFFF", "#FFF987", "#FFFFFF", "#A3A3A3", "#000000"
]),
Self::Fluidfluxa => ColorProfile::from_hex_colors(vec![
"#ff115f", "#a34aa3", "#00a4e7", "#ffdf00", "#000000", "#ffed71", "#85daff", "#dbadda", "#fe8db1"
]),
Self::Fluidfluxb => ColorProfile::from_hex_colors(vec![
"#c6d1d2", "#f47b9d", "#f09f9b", "#e3f09e", "#75eeea", "#52d2ed", "#c6d1d2"
]),
})
.expect("preset color profiles should be valid")
}
}
impl ColorProfile {
pub fn new(colors: Vec<Srgb<u8>>) -> 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(|s| s.as_ref().parse())
.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() {
debug!(?weights, ?self.colors, "length mismatch between `weights` and `colors`");
return Err(anyhow!(
"`weights` should have the same number of elements as `colors`"
));
}
let mut weighted_colors = Vec::new();
for (i, w) in weights.into_iter().enumerate() {
weighted_colors.extend(iter::repeat(self.colors[i]).take(usize::from(w)));
}
Ok(Self::new(weighted_colors))
}
/// Creates a new color profile, with the colors spread to the specified
/// length.
pub fn with_length(&self, length: NonZeroU8) -> Result<Self> {
let orig_len = self.colors.len();
let orig_len: NonZeroUsize = orig_len.try_into().expect("`colors` should not be empty");
let orig_len: NonZeroU8 = orig_len
.try_into()
.expect("`colors` should not have more than 255 elements");
// TODO: I believe weird things can happen because of this...
// if length < orig_len {
// unimplemented!("compressing length of color profile not implemented");
// }
let center_i = usize::from(orig_len.get() / 2);
// How many copies of each color should be displayed at least?
let repeats = length.get().div_euclid(orig_len.get());
let mut weights = vec![repeats; NonZeroUsize::from(orig_len).get()];
// How many extra spaces left?
let mut extras = length.get().rem_euclid(orig_len.get());
// If there is an odd space left, extend the center by one space
if extras % 2 == 1 {
weights[center_i] = weights[center_i].checked_add(1).unwrap();
extras = extras.checked_sub(1).unwrap();
}
// Add weight to border until there's no space left (extras must be even at this
// point)
let weights_len = weights.len();
for border_i in 0..usize::from(extras / 2) {
weights[border_i] = weights[border_i].checked_add(1).unwrap();
let border_opp = weights_len
.checked_sub(border_i)
.unwrap()
.checked_sub(1)
.unwrap();
weights[border_opp] = weights[border_opp].checked_add(1).unwrap();
}
self.with_weights(weights)
}
/// Colors a text.
///
/// # Arguments
///
/// * `foreground_background` - Whether the color is shown on the foreground
/// text or the background block
/// * `space_only` - Whether to only color spaces
pub fn color_text<S>(
&self,
txt: S,
color_mode: AnsiMode,
foreground_background: ForegroundBackground,
space_only: bool,
) -> Result<String>
where
S: AsRef<str>,
{
let txt = txt.as_ref();
let txt: Vec<&str> = txt.graphemes(true).collect();
let ColorProfile { colors } = {
let length = txt.len();
let length: NonZeroUsize = length.try_into().context("`txt` should not be empty")?;
let length: NonZeroU8 = length.try_into().with_context(|| {
format!(
"`txt` should not have more than {limit} characters",
limit = u8::MAX
)
})?;
self.with_length(length)
.with_context(|| format!("failed to spread color profile to length {length}"))?
};
let mut buf = String::new();
for (i, &gr) in txt.iter().enumerate() {
if space_only && gr != " " {
if i > 0 && txt[i.checked_sub(1).unwrap()] == " " {
buf.push_str("\x1b[39;49m");
}
buf.push_str(gr);
} else {
buf.push_str(&colors[i].to_ansi_string(color_mode, foreground_background));
buf.push_str(gr);
}
}
buf.push_str("\x1b[39;49m");
Ok(buf)
}
/// Creates a new color profile, with the colors lightened by a multiplier.
pub fn lighten(&self, multiplier: f32) -> Self {
let mut rgb_f32_colors: Vec<LinSrgb> =
self.colors.iter().map(|c| c.into_linear()).collect();
{
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
for okhsl_f32_color in okhsl_f32_colors {
okhsl_f32_color.lightness *= multiplier;
}
}
let rgb_u8_colors: Vec<_> = rgb_f32_colors
.into_iter()
.map(Srgb::<u8>::from_linear)
.collect();
Self {
colors: rgb_u8_colors,
}
}
/// Creates a new color profile, with the colors set to the specified
/// [`Okhsl`] lightness value.
pub fn with_lightness(&self, assign_lightness: AssignLightness) -> Self {
let mut rgb_f32_colors: Vec<LinSrgb> =
self.colors.iter().map(|c| c.into_linear()).collect();
{
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
for okhsl_f32_color in okhsl_f32_colors {
match assign_lightness {
AssignLightness::Replace(lightness) => {
okhsl_f32_color.lightness = lightness.into();
},
AssignLightness::ClampMax(lightness) => {
okhsl_f32_color.lightness.clamp_max_assign(lightness.into());
},
AssignLightness::ClampMin(lightness) => {
okhsl_f32_color.lightness.clamp_min_assign(lightness.into());
},
}
}
}
let rgb_u8_colors: Vec<Srgb<u8>> = rgb_f32_colors
.into_iter()
.map(Srgb::<u8>::from_linear)
.collect();
Self {
colors: rgb_u8_colors,
}
}
/// Creates a new color profile, with the colors set to the specified
/// [`Okhsl`] lightness value, adapted to the terminal theme.
pub fn with_lightness_adaptive(&self, lightness: Lightness, theme: TerminalTheme) -> Self {
match theme {
TerminalTheme::Dark => self.with_lightness(AssignLightness::ClampMin(lightness)),
TerminalTheme::Light => self.with_lightness(AssignLightness::ClampMax(lightness)),
}
}
/// Creates another color profile with only the unique colors.
pub fn unique_colors(&self) -> Self {
let unique_colors: IndexSet<[u8; 3]> = self.colors.iter().map(|&c| c.into()).collect();
let unique_colors: Vec<Srgb<u8>> = unique_colors.into_iter().map(|c| c.into()).collect();
Self::new(unique_colors)
}
}
+1 -6
View File
@@ -85,12 +85,7 @@ where
let metadata = match fs::metadata(path) { let metadata = match fs::metadata(path) {
Ok(metadata) => metadata, Ok(metadata) => metadata,
Err(err) if err.kind() == io::ErrorKind::NotFound => { Err(_) => return Ok(None)
return Ok(None);
},
Err(err) => {
return Err(err).with_context(|| format!("failed to get metadata for {path:?}"));
},
}; };
if !metadata.is_file() { if !metadata.is_file() {
+6 -4
View File
@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH VERSION: "1" "September 2025" "Version: 2.0.2" "User Commands" .TH VERSION: "1" "April 2026" "Version: 2.1.0-rc1" "User Commands"
.SH NAME .SH NAME
Version: \- manual page for Version: 2.0.2 Version: \- manual page for Version: 2.1.0-rc1
.SH SYNOPSIS .SH SYNOPSIS
.B hyfetch .B hyfetch
[\fI\,-c\/\fR] [\fI\,-C=CONFIG_FILE\/\fR] [\fI\,-p=PRESET\/\fR] [\fI\,-m=MODE\/\fR] [\fI\,-b=BACKEND\/\fR] [\fI\,--args=ARGS\/\fR] [\fI\,--c-scale=\/\fR [\fI\,-c\/\fR] [\fI\,-C=CONFIG_FILE\/\fR] [\fI\,-p=PRESET\/\fR] [\fI\,-m=MODE\/\fR] [\fI\,-b=BACKEND\/\fR] [\fI\,--args=ARGS\/\fR] [\fI\,--c-scale=\/\fR
@@ -20,8 +20,10 @@ Use another config file
[default: "/home/azalea/.config/hyfetch.json"] [default: "/home/azalea/.config/hyfetch.json"]
.TP .TP
\fB\-p\fR, \fB\-\-preset\fR=\fI\,PRESET\/\fR \fB\-p\fR, \fB\-\-preset\fR=\fI\,PRESET\/\fR
Use preset Use preset or comma\-separated color list or comma\-separated hex colors
PRESET={rainbow,transgender,nonbinary,xenogender,agender,queer,genderfluid,bisexual,pansexual,polysexual,omnisexual,omniromantic,gay\-men,lesbian,abrosexual,asexual,aromantic,fictosexual,aroace1,aroace2,aroace3,greysexual,autosexual,intergender,greygender,akiosexual,bigender,demigender,demiboy,demigirl,transmasculine,transfeminine,genderfaun,demifaun,genderfae,demifae,neutrois,biromantic1,autoromantic,boyflux2,girlflux,genderflux,nullflux,hypergender,hyperboy,hypergirl,hyperandrogyne,hyperneutrois,finsexual,unlabeled1,unlabeled2,pangender,pangender.contrast,gendernonconforming1,gendernonconforming2,femboy,tomboy,gynesexual,androsexual,gendervoid,voidgirl,voidboy,nonhuman\-unity,caninekin,plural,fraysexual,bear,butch,leather,otter,twink,adipophilia,kenochoric,veldian,solian,lunian,polyam,sapphic,androgyne,interprogress,progress,intersex,old\-polyam,equal\-rights,drag,pronounfluid,pronounflux,exipronoun,neopronoun,neofluid,genderqueer,cisgender,baker,beiyang,burger,throatlozenges,band,random} (e.g., "#ff0000,#00ff00,#0000ff"). Comma\-separated preset names will
pick one randomly.
PRESET={rainbow,transgender,nonbinary,xenogender,agender,queer,genderfluid,bisexual,pansexual,polysexual,omnisexual,omniromantic,gay\-men,lesbian,abrosexual,asexual,aromantic,fictosexual,aroace1,aroace2,aroace3,autosexual,intergender,greygender,akiosexual,bigender,demigender,demiboy,demigirl,transmasculine,transfeminine,genderfaun,demifaun,genderfae,demifae,neutrois,biromantic1,biromantic2,autoromantic,boyflux2,girlflux,genderflux,nullflux,hypergender,hyperboy,hypergirl,hyperandrogyne,hyperneutrois,finsexual,unlabeled1,unlabeled2,pangender,pangender.contrast,gendernonconforming1,gendernonconforming2,femboy,tomboy,gynesexual,androsexual,gendervoid,voidgirl,voidboy,nonhuman\-unity,plural,fraysexual,bear,butch,femme,leather,otter,twink,adipophilia,kenochoric,veldian,solian,lunian,polyam,sapphic,androgyne,interprogress,progress,intersex,old\-polyam,equal\-rights,drag,pronounfluid,pronounflux,exipronoun,neopronoun,neofluid,genderqueer,cisgender,baker,caninekin,libragender,librafeminine,libramasculine,libraandrogyne,libranonbinary,fluidflux1,fluidflux2,transbian,autism,cenelian,transneutral,beiyang,burger,throatlozenges,band,petergriffin,rubber,haruhi,random}
.TP .TP
\fB\-m\fR, \fB\-\-mode\fR=\fI\,MODE\/\fR \fB\-m\fR, \fB\-\-mode\fR=\fI\,MODE\/\fR
Color mode MODE={8bit,rgb} Color mode MODE={8bit,rgb}
+23 -21
View File
@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH NEOFETCH "1" "September 2025" "Neofetch 8.0.2" "User Commands" .TH NEOFETCH "1" "April 2026" "Neofetch 8.1.0" "User Commands"
.SH NAME .SH NAME
Neofetch \- manual page for Neofetch 8.0.2 Neofetch \- manual page for Neofetch 8.1.0
.SH SYNOPSIS .SH SYNOPSIS
.B neofetch .B neofetch
\fI\,func_name --option "value" --option "value"\/\fR \fI\,func_name --option "value" --option "value"\/\fR
@@ -326,13 +326,13 @@ BigLinux_large, Bitrig, BlackArch, BlackMesa, blackPanther, BLAG,
BlankOn, BlueLight, Bodhi, bonsai, BSD, BunsenLabs, CachyOS, BlankOn, BlueLight, Bodhi, bonsai, BSD, BunsenLabs, CachyOS,
Calculate, CalinixOS, Carbs, CBL\-Mariner, CelOS, Center, CentOS, Calculate, CalinixOS, Carbs, CBL\-Mariner, CelOS, Center, CentOS,
Chakra, ChaletOS, Chapeau, Chimera, ChonkySealOS, Chrom, Cleanjaro, Chakra, ChaletOS, Chapeau, Chimera, ChonkySealOS, Chrom, Cleanjaro,
Clear Linux OS, ClearOS, Clover, Cobalt, Condres, Container Linux by Clear Linux OS, ClearOS, Clover, Cobalt, Codex Linux, Condres,
CoreOS, CRUX, Crystal Linux, Cucumber, CutefishOS, CuteOS, CyberOS, Container Linux by CoreOS, CRUX, Crystal Linux, Cucumber,
dahlia, DarkOs, Darwin, Debian, Deepin, DesaOS, Devuan, DietPi, CutefishOS, CuteOS, CyberOS, dahlia, DarkOs, Darwin, Debian, Deepin,
digital UNIX, DracOS, DragonFly, Drauger, Droidian, Elementary, DesaOS, Devuan, DietPi, digital UNIX, DracOS, DragonFly, Drauger,
Elive, EncryptOS, EndeavourOS, Endless, Enso, EuroLinux, Droidian, Elementary, Elive, EncryptOS, EndeavourOS, Endless, Enso,
EvolutionOS, eweOS, Exherbo, Exodia Predator OS, Fedora, Fedora EuroLinux, EvolutionOS, eweOS, Exherbo, Exodia Predator OS, Fedora,
Kinoite, Fedora Sericea, Fedora Silverblue, Fedora_unicode, Fedora Kinoite, Fedora Sericea, Fedora Silverblue, Fedora_unicode,
FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeMiNT, Frugalware, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeMiNT, Frugalware,
Funtoo, Furreto, GalliumOS, Garuda, Gentoo, GhostBSD, glaucus, Funtoo, Furreto, GalliumOS, Garuda, Gentoo, GhostBSD, glaucus,
Gloire, gNewSense, GNOME, GNU, GoboLinux, GrapheneOS, Grombyang, Gloire, gNewSense, GNOME, GNU, GoboLinux, GrapheneOS, Grombyang,
@@ -352,22 +352,24 @@ Tumbleweed, openSUSE Tumbleweed\-Slowroll, OPNsense, Oracle, orchid,
OS Elbrus, PacBSD, Panwah, Parabola, parch, Pardus, Parrot, Parsix, OS Elbrus, PacBSD, Panwah, Parabola, parch, Pardus, Parrot, Parsix,
PCBSD, PCLinuxOS, pearOS, Pengwin, Pentoo, Peppermint, Peropesis, PCBSD, PCLinuxOS, pearOS, Pengwin, Pentoo, Peppermint, Peropesis,
phyOS, PikaOS, Pisi, PNM Linux, Pop!_OS, Porteus, PostMarketOS, phyOS, PikaOS, Pisi, PNM Linux, Pop!_OS, Porteus, PostMarketOS,
Profelis SambaBOX, Proxmox, PuffOS, Puppy, PureOS, Q4OS, Qubes, Profelis SambaBOX, Proxmox, PuffOS, Puppy, PureOS, Q4OS, QNX, Qubes,
Qubyt, Quibian, Radix, Raspbian, ravynOS, Reborn OS, Red Star, Qubyt, Quibian, Radix, Raspbian, ravynOS, Reborn OS, Red Star,
Redcore, Redhat, Refracted Devuan, Regata, Regolith, RhaymOS, Rhino Redcore, Redhat, Refracted Devuan, Regata, Regolith, RhaymOS, Rhino
Linux, rocky, Rosa, Sabayon, sabotage, Sailfish, SalentOS, Salient Linux, rocky, Rosa, Sabayon, sabotage, Sailfish, SalentOS, Salient
OS, Salix, Sasanqua, Scientific, semc, Septor, Serene, SharkLinux, OS, Salix, Sasanqua, Scientific, secureblue, semc, Septor, Serene,
ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SliTaz, SmartOS, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware,
Soda, Solus, Source Mage, Sparky, Star, SteamOS, Stock Linux, Sulin, SliTaz, SmartOS, Soda, Solus, Source Mage, Sparky, Star, SteamOS,
SunOS, SwagArch, t2, Tails, Tatra, TeArch, TorizonCore, Trisquel, Stock Linux, Sulin, SunOS, SwagArch, t2, Tails, Tatra, TeArch,
Twister, Ubuntu, Ubuntu Budgie, Ubuntu Cinnamon, Ubuntu Kylin, TorizonCore, Trisquel, Twister, Ubuntu, Ubuntu Budgie, Ubuntu
Ubuntu MATE, Ubuntu Studio, Ubuntu Sway, Ubuntu Touch, Ubuntu\-GNOME, Cinnamon, Ubuntu Kylin, Ubuntu MATE, Ubuntu Studio, Ubuntu Sway,
ubuntu_old02, Ultramarine Linux, unicodearch, Univalent, Univention, Ubuntu Touch, Ubuntu\-GNOME, ubuntu_old02, Ultramarine Linux,
Uos, UrukOS, uwuntu, Vanilla, Venom, VNux, Void, VzLinux, wii\-linuxngx, Windows, Windows 10, Windows 11, Windows95, Wrt, Xenia, Xenia2, unicodearch, Univalent, Univention, Uos, UrukOS, uwuntu, Vanilla,
XFerience, Xray_OS, Xubuntu, yiffOS, Zorin have ascii logos. Venom, VNux, Void, VzLinux, wii\-linux\-ngx, Windows, Windows 10,
Windows 11, Windows95, Wrt, Xenia, Xenia2, XFerience, Xray_OS,
Xubuntu, yiffOS, Zirconium, Zorin have ascii logos.
.TP .TP
NOTE: arch, dragonfly, Fedora, LangitKetujuh, nixos, redhat, Ubuntu NOTE: arch, dragonfly, Fedora, LangitKetujuh, nixos, redhat, Ubuntu,
have 'old' logo variants, use {distro}_old to use them. void have 'old' logo variants, use {distro}_old to use them.
.TP .TP
NOTE: alpine, android, arch, arcolinux, artix, CalinixOS, centos, NOTE: alpine, android, arch, arcolinux, artix, CalinixOS, centos,
cleanjaro, crux, debian, dragonfly, elementary, endeavouros, fedora, cleanjaro, crux, debian, dragonfly, elementary, endeavouros, fedora,
+2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os import os
from .py import run_py from .py import run_py
+3 -1
View File
@@ -1 +1,3 @@
VERSION = '2.0.2' from __future__ import annotations
VERSION = '2.1.0-rc1'
+3 -3
View File
@@ -141,9 +141,9 @@ class RGB:
g = int(hex[2:4], 16) g = int(hex[2:4], 16)
b = int(hex[4:6], 16) b = int(hex[4:6], 16)
elif len(hex) == 3: elif len(hex) == 3:
r = int(hex[0], 16) r = int(hex[0] * 2, 16)
g = int(hex[1], 16) g = int(hex[1] * 2, 16)
b = int(hex[2], 16) b = int(hex[2] * 2, 16)
else: else:
raise ValueError(f"Error: invalid hex length") raise ValueError(f"Error: invalid hex length")
return cls(r, g, b) return cls(r, g, b)
+1
View File
@@ -9,6 +9,7 @@ from .types import LightDark
from .__version__ import VERSION from .__version__ import VERSION
CONFIG_PATH = Path.home() / '.config/hyfetch.json' CONFIG_PATH = Path.home() / '.config/hyfetch.json'
SRC = Path(__file__).parent
TEST_ASCII = r""" TEST_ASCII = r"""
+17
View File
@@ -0,0 +1,17 @@
{"match": "\"Ad\u00e9lie\"* | \"Adelie\"*", "color": "4 7 6"}
${c1} ${c3} ,-^-___
${c3} /\\\\\\///
${c2}refined.${c1} /\\\\\\\\//
${c2}reliable.${c1} /\\\\\\///
${c2}ready.${c1} /\\\\/////\\
__///\\\\\\\\/////\\
${c3} _//////\\\\\\\\\\\\\\////
${c1} ///////${c3}\\\\\\\\\\\\\\\\\\\\//
//////${c1}\\\\\\\\\\/
/////\\\\\\\\\\/
/////${c3}\\\\\\\\/
/\\\\///\\\\\\/
/\\\\\\/${c1}\\\/
/\\\\\\\\//
//////
/// ${c3}\\\\\\\\\\
+15
View File
@@ -0,0 +1,15 @@
{"match": "\"Aeon\"*", "color": "38;5;36 38;5;36"}
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷
⣿⡇ ⢸⣿
⣿⡇ ⢀⣀ ⣀⡀ ⢸⣿
⣿⣇ ⠸⣿⣄ ⣠⣿⠇ ⣸⣿
⢹⣿⡄ ⠙⠻⠿⠿⠟⠋ ⢠⣿⡏
⠹⣿⣦⡀ ⢀⣴⣿⠏
⠈⠛⢿⣶⣤⣄ ⣠⣤⣶⡿⠛⠁
${c2} ⣠⣴⡿⠿⠛ ⠛⠿⢿⣦⣄
⣠⣾⠟⠉ ⠉⠻⣷⣄
⢰⣿⠏ ⢀⣤⣶⣶⣤⡀ ⠹⣿⡆
⣿⡟ ⢰⣿⠏⠁⠈⠹⣿⡆ ⢿⣿
⣿⡇ ⠈⠋ ⠙⠁ ⢸⣿
⣿⡇ ⢸⣿
⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"aerOS\"*", "color": "fg 0 0 0"}
from . import AsciiArt
aeros = AsciiArt(match=r'''"aerOS"*''', color='fg 0 0 0', ascii=r"""
${c1} ${c1}
ooo OOO OOO ooo ooo OOO OOO ooo
oOO OOo oOO OOo
@@ -24,6 +20,4 @@ ${c1}
oO OOo oO OOo
oOO OOo oOO OOo
oOO OOo oOO OOo
ooo OOO OOO ooo ooo OOO OOO ooo
""")
+17
View File
@@ -0,0 +1,17 @@
{"match": "\"AerynOS\"*", "color": "7 5"}
;llll.
0MMMMMM:
NMMMMMMMMd
.@ .cccccccccoWMMMMMMMMMM0
@@ .MMMMMMMMMMMMMMMMMMMMMMMN
OMMMMMMMMMMMMMMMW.
.@ .MMMMMMMMMMMMMMMMMMM.
.@ dMMMMMMMMMMMMMMMMMMl OMMMMMMMMk
.OWMMMMM; dMMMMMMMMMk
.MMMMMMMMMk
@@ ooooooooooooooooooo .MMMMMMMMMN
.@ oooooMMMMMMMMMMMMP NMMMMMMMMW.
KMMMMMMMMMM. 0MMMMMMMMM:
NMMMMMMMMM. dMMMMMMMMMd
.WMMMMMMMW. XMMMMMMMMO
.MMMMMMMk. xMMMMMMMMX
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Afterglow\"*", "color": "5 1 3 4"}
from . import AsciiArt
afterglow = AsciiArt(match=r'''"Afterglow"*''', color='5 1 3 4', ascii=r"""
${c2} . ${c2} .
${c1}. ${c2}.{! ${c1}. ${c2}.{!
${c1}.L! ${c2}J@||* ${c1}.L! ${c2}J@||*
@@ -17,6 +13,4 @@ ${c2} .
${c3}.@FJJJF`${c4},@LFFFF` ${c3}.@FJJJF`${c4},@LFFFF`
${c3}_@FFFFF ${c4}VLLLP` ${c3}_@FFFFF ${c4}VLLLP`
${c3}J@@LL@" ${c4}`" ${c3}J@@LL@" ${c4}`"
${c3}V@@" ${c3}V@@"
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"AIX\"*", "color": "2 7"}
from . import AsciiArt
aix = AsciiArt(match=r'''"AIX"*''', color='2 7', ascii=r"""
${c1} `:+ssssossossss+-` ${c1} `:+ssssossossss+-`
.oys///oyhddddhyo///sy+. .oys///oyhddddhyo///sy+.
/yo:+hNNNNNNNNNNNNNNNNh+:oy/ /yo:+hNNNNNNNNNNNNNNNNh+:oy/
@@ -22,6 +18,4 @@ h//NNNNh ossss` +h md- .hm/ `sNNNNN:+y
:h+-yNNNNNNNNNNNNNNNNNNNNNNs-oh- :h+-yNNNNNNNNNNNNNNNNNNNNNNs-oh-
:ys:/yNNNNNNNNNNNNNNNmy/:sy: :ys:/yNNNNNNNNNNNNNNNmy/:sy:
.+ys///osyhhhhys+///sy+. .+ys///osyhhhhys+///sy+.
-/osssossossso/- -/osssossossso/-
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"AlmaLinux\"*", "color": "1 3 4 2 6"}
from . import AsciiArt
almalinux = AsciiArt(match=r'''"AlmaLinux"*''', color='1 3 4 2 6', ascii=r"""
${c1} 'c:. ${c1} 'c:.
${c1} lkkkx, .. ${c2}.. ,cc, ${c1} lkkkx, .. ${c2}.. ,cc,
${c1} okkkk:ckkx' ${c2}.lxkkx.okkkkd ${c1} okkkk:ckkx' ${c2}.lxkkx.okkkkd
@@ -22,6 +18,4 @@ ${c3} ..... ${c5}.;dk:. ${c5}lkk. ${c4}:;,
,c,,;;;:xkkd. ,c,,;;;:xkkd.
;kkkkl... ;kkkkl...
;kkkkl ;kkkkl
,od; ,od;
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Alpine\"*", "color": "4 5 7 6"}
from . import AsciiArt
alpine = AsciiArt(match=r'''"Alpine"*''', color='4 5 7 6', ascii=r"""
${c1} .hddddddddddddddddddddddh. ${c1} .hddddddddddddddddddddddh.
:dddddddddddddddddddddddddd: :dddddddddddddddddddddddddd:
/dddddddddddddddddddddddddddd/ /dddddddddddddddddddddddddddd/
@@ -22,6 +18,4 @@ hdddyo+ohddyosdddddddddho+oydddy++ohdddh
+dddddddddddddddddddddddddddddd+ +dddddddddddddddddddddddddddddd+
/dddddddddddddddddddddddddddd/ /dddddddddddddddddddddddddddd/
:dddddddddddddddddddddddddd: :dddddddddddddddddddddddddd:
.hddddddddddddddddddddddh. .hddddddddddddddddddddddh.
""")
+18
View File
@@ -0,0 +1,18 @@
{"match": "\"Alpine2\"*", "color": "4 7"}
.:::::::::::::::::::::.
.:::::::::::::::::::::::.
.:::::::::::::::::::::::::.
.:::::::::::::::::::::::::::.
.:::::::::${c2},db,${c1}::::::::::::::::.
.::::::::${c2},d%%%%b,${c1}::${c2},db,${c1}:::::::::.
.:::::::${c2},%%%%P'%%%b,d%%%b,${c1}::::::::.
.::::::${c2},%%%%P,${c1}:::${c2}`%%%b'^q%%b,${c1}:::::::.
'::::${c2},%%%%P,d|${c1}:::::${c2}`%%%b:'^%%b,${c1}:::::'
'::${c2}`%%%'${c1}:${c2}'q$|${c1}:::::::${c2}'q%%b'`q%%b'${c1}::'
':::::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::'
':::::::::::::::::::::::::'
':::::::::::::::::::::::'
':::::::::::::::::::::'
+7
View File
@@ -0,0 +1,7 @@
{"match": "\"alpine2_small\"*", "color": "4 7"}
${c1} /\ /\
/${c2}/ ${c1}\ \
/${c2}// ${c1}\ \
/${c2}// ${c1}\ \
${c2}// ${c1}\ \
\
+8
View File
@@ -0,0 +1,8 @@
{"match": "\"alpine3_small\"*", "color": "7"}
,db,
,d%%%%b, ,db,
,%%%%P'%%%b,d%%%b,
,%%%%P, `%%%b'^q%%b,
,%%%%P,d| `%%%b '^%%b,
`%%%' 'q$| 'q%%b'`q%%b
+7
View File
@@ -0,0 +1,7 @@
{"match": "\"alpine_small\"", "color": "4 7"}
${c1} /\\ /\\
/${c2}/ ${c1}\\ \\
/${c2}/ ${c1}\\ \\
/${c2}// ${c1}\\ \\
${c2}// ${c1}\\ \\
\\
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Alter\"*", "color": "6 6"}
from . import AsciiArt
alter = AsciiArt(match=r'''"Alter"*''', color='6 6', ascii=r"""
${c1} %, ${c1} %,
^WWWw ^WWWw
'wwwwww 'wwwwww
@@ -22,6 +18,4 @@ ${c1} %,
@~:~~: ~:~~:~:(zltlltlO a,wwwwww @~:~~: ~:~~:~:(zltlltlO a,wwwwww
8~~:~~:~~~~:~~~~_1ltltu ,www 8~~:~~:~~~~:~~~~_1ltltu ,www
5~~:~~:~~:~~:~~:~~~_1ltq N,, 5~~:~~:~~:~~:~~:~~~_1ltq N,,
g~:~~:~~~:~~:~~:~:~~~~1q N, g~:~~:~~~:~~:~~:~:~~~~1q N,
""")
+23
View File
@@ -0,0 +1,23 @@
{"match": "\"ALTLinux\"*", "color": "3 8 7"}
##############
######################
##########################
##+${c2}####${c1}#######################
#####${c2}#${c1}*${c2}###%+${c1}######################
########${c2}%${c1}*#${c2}%#####${c1}###################
##########${c2}##${c1}*#*${c2}#######%+${c1}##############
#############${c2}%#############%${c1}############
#############${c2}+################${c1}##########
##############${c2}################*${c1}#########
##############${c2}+################+${c1}########
###############${c2}##########${c1}###${c2}+##%${c1}########
###############${c2}+########${c1}######${c2}###${c1}#######
#############${c2}*####${c1}############${c2}%#+${c1}#######
############${c2}+###${c3}####${c1}##########${c2}%#*${c1}#######
##########${c2}###*${c3}######${c2}+#+${c1}#####${c2}+##*${c1}######
#########${c2}##%${c3}#####${c2}:%#####${c1}###${c2}###*${c1}#####
########${c2}%#+${c3}######${c2}#############${c1}####
#####${c2}##%:${c3}######${c2}:############${c1}##
##${c2}+##*${c3}########${c2}############${c1}
${c2}###${c3}#########${c2}##########${c1}
${c3}########${c2}######
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Amazon\"*", "color": "3 7"}
from . import AsciiArt
amazon = AsciiArt(match=r'''"Amazon"*''', color='3 7', ascii=r"""
${c1} `-/oydNNdyo:.` ${c1} `-/oydNNdyo:.`
`.:+shmMMMMMMMMMMMMMMmhs+:.` `.:+shmMMMMMMMMMMMMMMmhs+:.`
-+hNNMMMMMMMMMMMMMMMMMMMMMMNNho- -+hNNMMMMMMMMMMMMMMMMMMMMMMNNho-
@@ -21,6 +17,4 @@ dMMMMMMMMMMMMMMMMh yMMMMMMMMMMMMMMMMd
dMMMMMMMMMMMMMMMMh yMMMMMMMMMMMMMMMMd dMMMMMMMMMMMMMMMMh yMMMMMMMMMMMMMMMMd
.:+ydNMMMMMMMMMMMh yMMMMMMMMMMMNdy+:. .:+ydNMMMMMMMMMMMh yMMMMMMMMMMMNdy+:.
`.:+shNMMMMMh yMMMMMNhs+:`` `.:+shNMMMMMh yMMMMMNhs+:``
`-+shy shs+:` `-+shy shs+:`
""")
+11
View File
@@ -0,0 +1,11 @@
{"match": "\"Amazon Linux\"*|\"amzn\"*", "color": "7 38;5;178"}
, ${c2}#_${c1}
~\_ ${c2}####_${c1}
~~ \_${c2}#####\${c1}
~~ \${c2}###|${c1}
~~ \${c2}#/${c1} ___
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
+15
View File
@@ -0,0 +1,15 @@
{"match": "\"Amiga\"*", "color": "1 1 3 4 6 3 2"}
----.---
:-==.-==-
${c2} -=== ===:
===-:===.
${c3} -+++:=++=
=+++ +++.
${c6} .+++-=++=
${c4}.::. ::: ${c6} :**+ +**-
${c4} :--:.---. ${c6} .+**=-***.
${c5} :--- ---::${c6}***:***+
${c5} .---::-${c6}=##*.*##-
${c7} ----+${c6}##=:##*.
${c7} :-${c6}###-*##+
+20
View File
@@ -0,0 +1,20 @@
{"match": "\"AmogOS\"*", "color": "15 6"}
${c1} ___________
/ \\
/ ${c2}______${c1} \\
/ ${c2}/ \\${c1} \\
| ${c2}( )${c1} \\
/ ${c2}\\______/${c1} |
| |
/ \\
| |
| |
/ |
| |
| _______ |
____/ / \\ |
/ | | |
| / ____/ |
\\_________/ / |
\\ __/
\\_______/
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Anarchy\"*", "color": "7 4", "foreground": [2]}
from . import AsciiArt
anarchy = AsciiArt(match=r'''"Anarchy"*''', color='7 4', ascii=r"""
${c2}..${c1} ${c2}..${c1}
${c2}..${c1} ${c2}..${c1}
${c2}:..${c1} ${c2}:..${c1}
@@ -30,6 +26,4 @@ anarchy = AsciiArt(match=r'''"Anarchy"*''', color='7 4', ascii=r"""
${c2}.${c1} ${c2}.:+++${c1}. ${c2}.${c1} ${c2}.:+++${c1}.
${c2}.:${c1}: ${c2}.:${c1}:
${c2}..${c1} ${c2}..${c1}
${c2}..${c1} ${c2}..${c1}
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Android\"*", "color": "2 7", "foreground": [2]}
from . import AsciiArt
android = AsciiArt(match=r'''"Android"*''', color='2 7', ascii=r"""
${c1} -o o- ${c1} -o o-
+hydNNNNdyh+ +hydNNNNdyh+
+mMMMMMMMMMMMMm+ +mMMMMMMMMMMMMm+
@@ -20,6 +16,4 @@ ${c1} -o o-
`/++MMMMh++hMMMM++/` `/++MMMMh++hMMMM++/`
MMMMo oMMMM MMMMo oMMMM
MMMMo oMMMM MMMMo oMMMM
oNMm- -mMNs oNMm- -mMNs
""")
+7
View File
@@ -0,0 +1,7 @@
{"match": "\"android_small\"*", "color": "2 7"}
${c1} ;, ,;
';,.-----.,;'
,' ',
/ O O \\
| |
'-----------------'
+21
View File
@@ -0,0 +1,21 @@
{"match": "\"anduinos\"*", "color": "6 4"}
${c1}+++++++++++
+++++++++++++++++++++
+++++++++++++++++++++++++++++++
=+++++++++++++++++++++++++++++++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++
=++++++++++++++++++++++++++++++++++++++++++++
==+++++++++++++++++++++++++++++++++==
+++++++++++++++++++++++++++
${c2}**** ${c1}++=+++++++++++=++ ${c2}****
********** ${c1}+++++++ ${c2}**********
************** **************
**************** ****************
***********************
****** ************* ******
*********** *** ***********
*************** ***************
*************** ***************
*********************
***********
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Antergos\"*", "color": "4 6", "foreground": [1]}
from . import AsciiArt
antergos = AsciiArt(match=r'''"Antergos"*''', color='4 6', ascii=r"""
${c2} `.-/::/-`` ${c2} `.-/::/-``
.-/osssssssso/. .-/osssssssso/.
:osyysssssssyyys+- :osyysssssssyyys+-
@@ -21,6 +17,4 @@ dmmmdddddddhhhyso${c1}++++++${c2}shhhhhddddddmmmmh
-dmmmdddddddhhys${c1}o++++o${c2}shhhhdddddddmmmmd- -dmmmdddddddhhys${c1}o++++o${c2}shhhhdddddddmmmmd-
.smmmmddddddddhhhhhhhhhdddddddddmmmms. .smmmmddddddddhhhhhhhhhdddddddddmmmms.
`+ydmmmdddddddddddddddddddmmmmdy/. `+ydmmmdddddddddddddddddddmmmmdy/.
`.:+ooyyddddddddddddyyso+:.` `.:+ooyyddddddddddddyyso+:.`
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"antiX\"*", "color": "1 7 3"}
from . import AsciiArt
antix = AsciiArt(match=r'''"antiX"*''', color='1 7 3', ascii=r"""
${c1} ${c1}
\ \
, - ~ ^ ~ - \ / , - ~ ^ ~ - \ /
@@ -15,6 +11,4 @@ ${c1}
\,_/\_/ | |_/|_/|_/_/ \, \,_/\_/ | |_/|_/|_/_/ \,
, / ,\ , / ,\
, / , ' \ , / , ' \
' - , _ _ _ , ' ' - , _ _ _ , '
""")
+22
View File
@@ -0,0 +1,22 @@
{"match": "\"AnushOS\"*", "color": "7 8 3 6 1"}
${c4}#######################
${c4}# ${c2}##### ${c4}#
${c4}# ${c2}####### ${c4}#
${c4}# ${c2}##${c5}O${c2}#${c5}O${c2}## ${c4}#
${c4}# ${c2}#${c3}#####${c2}# ${c4}#
${c4}# ${c2}##${c1}##${c3}###${c1}##${c2}## ${c4}#
${c4}# ${c2}#${c1}##########${c2}## ${c4}#
${c4}# ${c2}#${c1}############${c2}## ${c4}#
${c4}# ${c2}#${c1}######${c5}A_O${c1}####${c2}### ${c4}#
${c4}# ${c3}##${c2}#${c1}############${c2}##${c3}## ${c4}#
${c4}#${c3}######${c2}#${c1}#######${c2}#${c3}######${c4}#
${c4}#${c3}#######${c2}#${c1}#####${c2}#${c3}#######${c4}#
${c4}# ${c3}#####${c2}#######${c3}##### ${c4}#
${c4}#######################
${c4}#${c5}╔═╗╔╗╔╦ ╦╔═╗╦ ╦╔═╗╔═╗${c4}#
${c4}#${c5}╠═╣║║║║ ║╚═╗╠═╣║ ║╚═╗${c4}#
${c4}#${c5}╩ ╩╝╚╝╚═╝╚═╝╩ ╩╚═╝╚═╝${c4}#
${c4}#######################
${c4}# ${c3}WWW.ANUSHOS.ORG ${c4}#
${c4}#######################
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"AOSC OS\"*", "color": "4 0 1 3"}
from . import AsciiArt
aosc_os = AsciiArt(match=r'''"AOSC OS"*''', color='4 0 1 3', ascii=r'''
${c2} __ ${c2} __
${c2}gpBBBBBBBBBP ${c2}gpBBBBBBBBBP
${c2}_gBBBBBBBBBRP ${c2}_gBBBBBBBBBRP
@@ -19,6 +15,4 @@ ${c2} __
${c3}_gBNNNNNNNNNNNNNNNNNP" ${c3}_gBNNNNNNNNNNNNNNNNNP"
${c3}_wNNNNNNNNNNNNNNNNNNNM^ ${c3}_wNNNNNNNNNNNNNNNNNNNM^
${c3}""Y^^MNNNNNNNNNNNNP` ${c3}""Y^^MNNNNNNNNNNNNP`
${c3}`""""""" ${c3}`"""""""
''')
+21
View File
@@ -0,0 +1,21 @@
{"match": "\"Aosc OS_old\"*|\"aoscos_old\"*", "color": "7"}
.:+syhhhhys+:.
.ohNMMMMMMMMMMMMMMNho.
`+mMMMMMMMMMMmdmNMMMMMMMMm+`
+NMMMMMMMMMMMM/ `./smMMMMMN+
.mMMMMMMMMMMMMMMo -yMMMMMm.
:NMMMMMMMMMMMMMMMs .hMMMMN:
.NMMMMhmMMMMMMMMMMm+/- oMMMMN.
dMMMMs ./ymMMMMMMMMMMNy. sMMMMd
-MMMMN` oMMMMMMMMMMMN: `NMMMM-
/MMMMh NMMMMMMMMMMMMm hMMMM/
/MMMMh NMMMMMMMMMMMMm hMMMM/
-MMMMN` :MMMMMMMMMMMMy. `NMMMM-
dMMMMs .yNMMMMMMMMMMMNy/. sMMMMd
.NMMMMo -/+sMMMMMMMMMMMmMMMMN.
:NMMMMh. .MMMMMMMMMMMMMMMN:
.mMMMMMy- NMMMMMMMMMMMMMm.
+NMMMMMms/.` mMMMMMMMMMMMN+
`+mMMMMMMMMNmddMMMMMMMMMMm+`
.ohNMMMMMMMMMMMMMMNho.
.:+syhhhhys+:.
+19
View File
@@ -0,0 +1,19 @@
{"match": "\"Aosc OS/Retro\"*|\"aoscosretro\"*", "color": "4 7"}
${c2} .........
...................
.....................${c1}################${c2}
.............. ....${c1}################${c2}
.............. ...${c1}################${c2}
............. ..${c1}****************${c2}
............ . .${c1}****************${c2}
........... ... ${c1}................${c2}
.......... ..... ${c1}...............${c2}
......... ....... ...
.${c3}...... ${c2}.
${c3}..... .....${c2}.... ${c4}...........
${c3}.... ......${c2}. ${c4}...........
${c3}... ....... ${c4}...........
${c3}................ ${c4}***********
${c3}................ ${c4}###########
${c3}****************
${c3}################
@@ -0,0 +1,10 @@
{"match": "\"Aosc OS/Retro_small\"*|\"aoscosretro_small\"*", "color": "4 7"}
${c2} _____ ${c1}_____${c2}
-' '-${c1}| |${c2}
/ ___ ${c1}| |${c2}
| / _ \${c1}|_____|${c2}
' / /_\ \
\ / _____ \${c4}___
${c3}|${c2}/_/ ${c3}| ${c4}| |
${c3}| | ${c4}|___|
${c3}|_____|
@@ -0,0 +1,5 @@
{"match": "\"Aperio GNU/Linux\"*", "color": "255"}
${c2}
_.._ _ ._.. _
(_][_)(/,[ |(_)
| GNU/Linux
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Aperture\"*", "color": "6 6 7 1"}
from . import AsciiArt
aperture = AsciiArt(match=r'''"Aperture"*''', color='6 6 7 1', ascii=r"""
${c1} .,-:;//;:=, ${c1} .,-:;//;:=,
. :H@@@MM@M#H/.,+%;, . :H@@@MM@M#H/.,+%;,
,/X+ +M@@M@MM%=,-%HMMM@X/, ,/X+ +M@@M@MM%=,-%HMMM@X/,
@@ -22,6 +18,4 @@ ${c1} .,-:;//;:=,
=XMMM@MM@MM#H;,-+HMM@M+ /MMMX= =XMMM@MM@MM#H;,-+HMM@M+ /MMMX=
=%@M@M#@$-.=$@MM@@@M; %M%= =%@M@M#@$-.=$@MM@@@M; %M%=
,:+$+-,/H#MMMMMMM@= =, ,:+$+-,/H#MMMMMMM@= =,
=++%%%%+/:-. =++%%%%+/:-.
""")
+18
View File
@@ -0,0 +1,18 @@
{"match": "\"Apple\"*", "color": "2 3 1 1 5 4"}
..'
,xNMM.
.OMMMMo
lMM"
.;loddo:. .olloddol;.
cKMMMMMMMMMMNWMMMMMMMMMM0:
${c2}.KMMMMMMMMMMMMMMMMMMMMMMMWd.
XMMMMMMMMMMMMMMMMMMMMMMMX.
${c3};MMMMMMMMMMMMMMMMMMMMMMMM:
:MMMMMMMMMMMMMMMMMMMMMMMM:
${c4}.MMMMMMMMMMMMMMMMMMMMMMMMX.
kMMMMMMMMMMMMMMMMMMMMMMMMWd.
${c5}'XMMMMMMMMMMMMMMMMMMMMMMMMMMk
'XMMMMMMMMMMMMMMMMMMMMMMMMK.
${c6}kMMMMMMMMMMMMMMMMMMMMMMd
;KMMMMMMMWXXWMMMMMMMk.
"cooc*" "*coo'"
+8
View File
@@ -0,0 +1,8 @@
{"match": "\"Apple_small\"*", "color": "2 3 1 5 4"}
${c1} .:'
__ :'__
${c2} .'`__`-'__``.
${c3}:__________.-'
${c4}:_________:
:_________`-;
${c5} `.__.-.__.'
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Apricity\"*", "color": "4 7 1"}
from . import AsciiArt
apricity = AsciiArt(match=r'''"Apricity"*''', color='4 7 1', ascii=r"""
${c2} ./o- ${c2} ./o-
``...`` `:. -/: ``...`` `:. -/:
`-+ymNMMMMMNmho-` :sdNNm/ `-+ymNMMMMMNmho-` :sdNNm/
@@ -20,6 +16,4 @@ MMMMMM/`.-/ohmNMMMMMMy-
MMMMMMNmNNMMMMMMMMmo. MMMMMMNmNNMMMMMMMMmo.
MMMMMMMMMMMMMMMms:` MMMMMMMMMMMMMMMms:`
MMMMMMMMMMNds/. MMMMMMMMMMNds/.
dhhyys+/-` dhhyys+/-`
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Arch\"*", "color": "6 6 7 1"}
from . import AsciiArt
arch = AsciiArt(match=r'''"Arch"*''', color='6 6 7 1', ascii=r"""
${c1} -` ${c1} -`
.o+` .o+`
`ooo/ `ooo/
@@ -21,6 +17,4 @@ ${c2} .oossssso-````/ossssss+`
`/ossssso+/:- -:/+osssso+- `/ossssso+/:- -:/+osssso+-
`+sso+:-` `.-/+oso: `+sso+:-` `.-/+oso:
`++:. `-/+/ `++:. `-/+/
.` `/ .` `/
""")
+20
View File
@@ -0,0 +1,20 @@
{"match": "\"arch2\"*", "color": "6 6"}
▟█▙
▟███▙
▟█████▙
▟███████▙
▂▔▀▜██████▙
▟██▅▂▝▜█████▙
▟█████████████▙
▟███████████████▙
▟█████████████████▙
▟███████████████████▙
${c2} ▟█████████▛▀▀▜████████▙
▟████████▛ ▜███████▙
▟█████████ ████████▙
▟██████████ █████▆▅▄▃▂
▟██████████▛ ▜█████████▙
▟██████▀▀▀ ▀▀██████▙
▟███▀▘ ▝▀███▙
▟▛▀ ▀▜▙
+20
View File
@@ -0,0 +1,20 @@
{"match": "\"arch3\"*", "color": "6 6"}
.
/ \
/ \
/ \
/ \
/>, \
/ `*. \
/ ` \
/ \
/ \
${c2} / ,.-+-.. \
/ ,/' `\. \
/ .|' `|. _ \
/ :|. ,|; `+.\
/ .\: ;/, "<\
/ __,--+" "+--.__ \
/ _,+'" "'+._ \
/,-' `-.\
' '
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"arch_old\"", "color": "6 7 1"}
from . import AsciiArt
arch_old = AsciiArt(match=r'''"arch_old"''', color='6 7 1', ascii=r"""
${c1} __ ${c1} __
_=(SDGJT=_ _=(SDGJT=_
_GTDJHGGFCVS) _GTDJHGGFCVS)
@@ -18,6 +14,4 @@ ${c1}JSNRVW'${c2} __+MNAEC${c1}\IOI,${c2}\BN'
${c1}HELK['${c2} __,=OFFXCBGHC${c1}\FD) ${c1}HELK['${c2} __,=OFFXCBGHC${c1}\FD)
${c1}?KGHE ${c2}\_-#DASDFLSV='${c1} 'EF ${c1}?KGHE ${c2}\_-#DASDFLSV='${c1} 'EF
'EHTI !H 'EHTI !H
`0F' '! `0F' '!
""")
+8
View File
@@ -0,0 +1,8 @@
{"match": "\"arch_small\"", "color": "6 7 1"}
${c1} /\\
/ \\
/\\ \\
${c2} / \\
/ ,, \\
/ | | -\\
/_-'' ''-_\\
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ArchBox\"*", "color": "2 7 1"}
from . import AsciiArt
archbox = AsciiArt(match=r'''"ArchBox"*''', color='2 7 1', ascii=r"""
${c1} ...:+oh/:::.. ${c1} ...:+oh/:::..
..-/oshhhhhh` `::::-. ..-/oshhhhhh` `::::-.
.:/ohhhhhhhhhhhh` `-::::. .:/ohhhhhhhhhhhh` `-::::.
@@ -21,6 +17,4 @@ ${c1} ...:+oh/:::..
/:::+`hhhhoos` `hhhhhhhhhhhhhhhhhs+` /:::+`hhhhoos` `hhhhhhhhhhhhhhhhhs+`
`--/:` /: `hhhhhhhhhhhho/- `--/:` /: `hhhhhhhhhhhho/-
-/:. `hhhhhhs+:-` -/:. `hhhhhhs+:-`
::::/ho/-` ::::/ho/-`
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Archcraft\"*", "color": "6 1 2 3 4 5"}
from . import AsciiArt
archcraft = AsciiArt(match=r'''"Archcraft"*''', color='6 1 2 3 4 5', ascii=r"""
${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢰⡆${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄ ${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢰⡆${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢠⣿⣿⡄${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄ ${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢠⣿⣿⡄${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⡀${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄ ${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⡀${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
@@ -22,6 +18,4 @@ ${c4}⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⣿⣿⣿⣷⣤⡀${c4}⠄⠄⠄${c1}⠻⣿
${c5}⠄⠄⠄${c1}⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀${c5}⠄⠄⠄ ${c5}⠄⠄⠄${c1}⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀${c5}⠄⠄⠄
${c6}⠄⠄${c1}⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄${c6}⠄⠄ ${c6}⠄⠄${c1}⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄${c6}⠄⠄
${c1}⠄${c1}⣠⣿⣿⣿⣿⠿⠛⠋⠁${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠻⢿⣿⣿⣿⣿⣆${c1}⠄ ${c1}⠄${c1}⣠⣿⣿⣿⣿⠿⠛⠋⠁${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠻⢿⣿⣿⣿⣿⣆${c1}⠄
${c1}⡰⠟⠛⠉⠁${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠛⠿⢆ ${c1}⡰⠟⠛⠉⠁${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠛⠿⢆
""")
@@ -1,9 +1,5 @@
# This file is automatically generated. Please do not modify. {"match": "\"Archcraft2\"*", "color": "6"}
-o\
from . import AsciiArt
archcraft_ascii = AsciiArt(match=r'''"archcraft_ascii"*''', color='6 1 2 3 4 5', ascii=r"""
${c1} -o\
:ooo: :ooo:
.ooooo. .ooooo.
ooooooo. ooooooo.
@@ -23,5 +19,3 @@ ${c1} -o\
.+osossos+-` `-+osososs+. .+osossos+-` `-+osososs+.
:sss+=-:` `:-=+ssss: :sss+=-:` `:-=+ssss:
:=-:` `-=+: :=-:` `-=+:
""")
@@ -0,0 +1,21 @@
{"match": "\"archcraft_ascii\"*", "color": "6 1 2 3 4 5"}
${c1} -o\
:ooo:
.ooooo.
ooooooo.
+oooooooo.
-oooooooooo.
--:-+oooooooo.
yooo+=+sooooooo.
yoooooosooooooooo.
y+ooooooooooooooooo.
yoooooooooooooooooooo`
yoooooo+oo= :oo++ooooo`
:oooooo. +ooooo-
-ooooooo. .::. +ooosoo=
-oooooo` .oooo` +os-=o=
=ooooooo=: `oo+ :=ooo=--`.
+ooooooooos. .=sooooooo+-
.+osossos+-` `-+osososs+.
:sss+=-:` `:-=+ssss:
:=-:` `-=+:
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"archcraft_minimal\"*", "color": "6 1 2 3 4 5"}
from . import AsciiArt
archcraft_minimal = AsciiArt(match=r'''"archcraft_minimal"*''', color='6 1 2 3 4 5', ascii=r"""
${c1} ⢰⡆ ${c1} ⢰⡆
⢠⣿⣿⡄ ⢠⣿⣿⡄
⢀⣾⣿⣿⣿⡀ ⢀⣾⣿⣿⣿⡀
@@ -22,6 +18,4 @@ ${c1} ⢰⡆
⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀ ⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀
⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁ ⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄ ⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁ ⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄
⣠⣿⣿⣿⣿⠿⠛⠋⠁ ⠉⠙⠻⢿⣿⣿⣿⣿⣆ ⣠⣿⣿⣿⣿⠿⠛⠋⠁ ⠉⠙⠻⢿⣿⣿⣿⣿⣆
⡰⠟⠛⠉⠁ ⠉⠙⠛⠿⢆ ⡰⠟⠛⠉⠁ ⠉⠙⠛⠿⢆
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ARCHlabs\"*", "color": "6 6 7 1"}
from . import AsciiArt
archlabs = AsciiArt(match=r'''"ARCHlabs"*''', color='6 6 7 1', ascii=r"""
${c1} 'c' ${c1} 'c'
'kKk, 'kKk,
.dKKKx. .dKKKx.
@@ -23,6 +19,4 @@ ${c1} 'c'
'xKXXXXK0kdl:. ${c4}.ok; ${c1}.cdk0KKXXXKx' 'xKXXXXK0kdl:. ${c4}.ok; ${c1}.cdk0KKXXXKx'
'xKK0koc,.. ${c4}'c, ${c1} ..,cok0KKk, 'xKK0koc,.. ${c4}'c, ${c1} ..,cok0KKk,
,xko:'. ${c4}.. ${c1} .':okx; ,xko:'. ${c4}.. ${c1} .':okx;
.,'. .',. .,'. .',.
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ArchMerge\"*", "color": "6 6 7 1"}
from . import AsciiArt
archmerge = AsciiArt(match=r'''"ArchMerge"*''', color='6 6 7 1', ascii=r"""
${c1} y: ${c1} y:
sMN- sMN-
+MMMm` +MMMm`
@@ -22,6 +18,4 @@ ${c1} y:
-NMMMMMMMMMh `mNMMMMMMMMd` -NMMMMMMMMMh `mNMMMMMMMMd`
/NMMMNds+:.` `-/oymMMMm. /NMMMNds+:.` `-/oymMMMm.
+Mmy/. `:smN: +Mmy/. `:smN:
/+. -o. /+. -o.
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ArchStrike\"*", "color": "8 6", "foreground": [2]}
from . import AsciiArt
archstrike = AsciiArt(match=r'''"ArchStrike"*''', color='8 6', ascii=r"""
${c1} * ${c1} *
**. **.
**** ****
@@ -19,6 +15,4 @@ ${c1} *
****${c2}/${c1}**** ${c2}/////${c1}***${c2}/${c1}**** ****${c2}/${c1}**** ${c2}/////${c1}***${c2}/${c1}****
******${c2}/${c1}*** ${c2}//// ${c1}**${c2}/${c1}****** ******${c2}/${c1}*** ${c2}//// ${c1}**${c2}/${c1}******
********${c2}/${c1}* ${c2}/// ${c1}*${c2}/${c1}******** ********${c2}/${c1}* ${c2}/// ${c1}*${c2}/${c1}********
,****** ${c2}// ______ / ${c1}******, ,****** ${c2}// ______ / ${c1}******,
""")
+21
View File
@@ -0,0 +1,21 @@
{"match": "\"arco\"*|\"arcolinux\"*", "color": "4 7"}
/-
ooo:
yoooo/
yooooooo
yooooooooo
yooooooooooo
.yooooooooooooo
.oooooooooooooooo
.oooooooarcoooooooo
.ooooooooo-oooooooooo
.ooooooooo- oooooooooo
:ooooooooo. :ooooooooo
:ooooooooo. :ooooooooo
:oooarcooo .oooarcooo
:ooooooooy .ooooooooo
${c1}:ooooooooo ${c2}/ooooooooooooooooooo
${c1}:ooooooooo ${c2}.-ooooooooooooooooo.
${c1}ooooooooo- ${c2}-ooooooooooooo.
${c1}ooooooooo- ${c2}.-oooooooooo.
${c1}ooooooooo. ${c2}-ooooooooo
+12
View File
@@ -0,0 +1,12 @@
{"match": "\"arco_small\"*|\"arcolinux_small\"*", "color": "4 7"}
A
ooo
ooooo
ooooooo
ooooooooo
ooooo ooooo
ooooo ooooo
ooooo ooooo
ooooo ${c2}<oooooooo>${c1}
ooooo ${c2}<oooooo>${c1}
ooooo ${c2}<oooo>
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ArcoLinux\"*", "color": "7 4"}
from . import AsciiArt
arcolinux = AsciiArt(match=r'''"ArcoLinux"*''', color='7 4', ascii=r"""
${c2} /- ${c2} /-
ooo: ooo:
yoooo/ yoooo/
@@ -22,6 +18,4 @@ ${c2} /-
:ooooooooo ${c1}.-ooooooooooooooooo.${c2} :ooooooooo ${c1}.-ooooooooooooooooo.${c2}
ooooooooo- ${c1}-ooooooooooooo.${c2} ooooooooo- ${c1}-ooooooooooooo.${c2}
ooooooooo- ${c1}.-oooooooooo.${c2} ooooooooo- ${c1}.-oooooooooo.${c2}
ooooooooo. ${c1}-ooooooooo${c2} ooooooooo. ${c1}-ooooooooo${c2}
""")
@@ -0,0 +1,12 @@
{"match": "\"arcolinux_small\"*", "color": "7 4"}
${c2} A
ooo
ooooo
ooooooo
ooooooooo
ooooo ooooo
ooooo ooooo
ooooo ooooo
ooooo ${c1}<oooooooo>${c2}
ooooo ${c1}<oooooo>${c2}
ooooo ${c1}<oooo>${c2}
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Arkane\"*", "color": "7 130 237", "foreground": [1]}
from . import AsciiArt
arkane = AsciiArt(match=r'''"Arkane"*''', color='7 130 237', ascii=r"""
${c3} .:.. ${c3} .:..
..:::...... ..:::......
${c2}.${c3} .${c2}.${c3}..... ${c2}.${c3} .${c2}.${c3}.....
@@ -25,6 +21,4 @@ ${c2}.-==+++***++*${c1}*#########${c3}=:::.
${c2}.-=++++*++++**${c1}#######%%###${c3}= ${c2}.-=++++*++++**${c1}#######%%###${c3}=
${c2}.:==++++++**${c1}#############${c3}: ${c2}.:==++++++**${c1}#############${c3}:
${c2}.${c3}-+*++*+++==${c1}###${c3}+ ${c2}.${c3}-+*++*+++==${c1}###${c3}+
-${c1}*+${c3}: -${c1}*+${c3}:
""")
+12
View File
@@ -0,0 +1,12 @@
{"match": "\"Armbian\"*", "color": "7 1"}
..
`:]x**j-,'
.,+t***********z\<"
?******************;
'*n` .'`^,;;,^`'. ,cc.
-<. .[l
// ^^ ^^ \\
!^ ${c2}^^${c1} ":
'tt}` ${c2}!~]rj_${c1} ")t/.
Itttt?' ${c2}~~]rr]${c1} `{tttt,
\tttttt!""I${c2}_]r(${c1}
+15
View File
@@ -0,0 +1,15 @@
{"match": "\"Armbian2\"*", "color": "1"}
█ █ █ █ █ █ █ █ █ █ █
███████████████████████
▄▄██ ██▄▄
▄▄██ ███████████ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ █████████████ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██▄▄
███████████████████████
█ █ █ █ █ █ █ █ █ █ █
+16
View File
@@ -0,0 +1,16 @@
{"match": "\"arse\"*|\"arselinux\"*|\"arse-linux\"*", "color": "4 7"}
⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⣴⣶⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣄⠀⠀⠀⠀⣼⠟⠁⠀⠀⢀⣀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⢀⣤⡀⠀⠀⠀⠉⢻⣷⡄⠀⠀⠁⠀⢀⣤⣾⡿⠟⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣷⣿⠏⠀⠀⠀⠀⠀⠀⠹⣿⡄⠀⠀⠀⠙⠉⠁⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⡄⠀⠀⠀⠀⠀⠀⠀⢹⣿⠀⠀⠀⠀⠠⣶⣶⣶⡶
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⢠⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠂⠀⠀⠀⠀⠀⢀⣾⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⠇⠀⠀⠀⠀⠀⣠⣾⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣿⣇⣀⣀⣀⣠⣴⣾⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢸⣿⠀⠀⠀⠀⠀⣤⣤⣴⣶⣾⠿⠟⣿⡏⠙⠛⠛⠛⠋⠉⢀⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣿⡄⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⠇⠀⠀⠀⠀⠀⠀⠘⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"ArseLinux\"*", "color": "4 7"}
from . import AsciiArt
arselinux = AsciiArt(match=r'''"ArseLinux"*''', color='4 7', ascii=r"""
${c1} ${c1}
⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⣴⣶⠀⠀⠀⠀⠀ ⠀⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⣴⣶⠀⠀⠀⠀⠀
@@ -18,6 +14,4 @@ ${c1}
⢸⣿⠀⠀⠀⠀⠀⣤⣤⣴⣶⣾⠿⠟⣿⡏⠙⠛⠛⠛⠋⠉⢀⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⢸⣿⠀⠀⠀⠀⠀⣤⣤⣴⣶⣾⠿⠟⣿⡏⠙⠛⠛⠛⠋⠉⢀⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣿⡄⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⣿⡄⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⠇⠀⠀⠀⠀⠀⠀⠘⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⠇⠀⠀⠀⠀⠀⠀⠘⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Artix\"*", "color": "6 6 7 1"}
from . import AsciiArt
artix = AsciiArt(match=r'''"Artix"*''', color='6 6 7 1', ascii=r"""
${c1} ' ${c1} '
'o' 'o'
'ooo' 'ooo'
@@ -22,6 +18,4 @@ ${c1} '
'ooooxooi::'` .:iiixkxxo' 'ooooxooi::'` .:iiixkxxo'
'ooooi:'` `'';ioxxo' 'ooooi:'` `'';ioxxo'
'i:'` '':io' 'i:'` '':io'
'` `' '` `'
""")
+9
View File
@@ -0,0 +1,9 @@
{"match": "\"artix2_small\"*", "color": "6"}
/\
/ \
/`'.,\
/ ',
/ ,`\
/ ,.'`. \
/.,'` `'.\
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"artix_small\"*", "color": "6 6 7 1"}
from . import AsciiArt
artix_small = AsciiArt(match=r'''"artix_small"*''', color='6 6 7 1', ascii=r"""
${c1} ' ${c1} '
'A' 'A'
'ooo' 'ooo'
@@ -15,6 +11,4 @@ ${c1} '
'ookxxkoo'` .'oo' 'ookxxkoo'` .'oo'
'ooxoo'` .:ooxxo' 'ooxoo'` .:ooxxo'
'io'` `'oo' 'io'` `'oo'
'` `' '` `'
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Arya\"*", "color": "2 1"}
from . import AsciiArt
arya = AsciiArt(match=r'''"Arya"*''', color='2 1', ascii=r"""
${c1} `oyyy/${c2}-yyyyyy+ ${c1} `oyyy/${c2}-yyyyyy+
${c1} -syyyy/${c2}-yyyyyy+ ${c1} -syyyy/${c2}-yyyyyy+
${c1} .syyyyy/${c2}-yyyyyy+ ${c1} .syyyyy/${c2}-yyyyyy+
@@ -17,6 +13,4 @@ ${c1} +yyyyyys :yyyyyy/${c2}-yyyyyy+
${c1} .oyyyyyyo. :yyyyyy/${c2}-yyyyyy+ --------- ${c1} .oyyyyyyo. :yyyyyy/${c2}-yyyyyy+ ---------
${c1} .syyyyyy+` :yyyyyy/${c2}-yyyyy+-+syyyyyyyy ${c1} .syyyyyy+` :yyyyyy/${c2}-yyyyy+-+syyyyyyyy
${c1} -syyyyyy/ :yyyyyy/${c2}-yyys:.syyyyyyyyyy ${c1} -syyyyyy/ :yyyyyy/${c2}-yyys:.syyyyyyyyyy
${c1}:syyyyyy/ :yyyyyy/${c2}-yyo.:syyyyyyyyyyy ${c1}:syyyyyy/ :yyyyyy/${c2}-yyo.:syyyyyyyyyyy
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Asahi\"*", "color": "3 2 1 8 7 6 4", "foreground": [5]}
from . import AsciiArt
asahi = AsciiArt(match=r'''"Asahi"*''', color='3 2 1 8 7 6 4', ascii=r"""
${c1} ## ${c2}** ${c1} ## ${c2}**
${c1}*####${c2}****. ${c1}*####${c2}****.
${c1}###${c2}, ${c1}###${c2},
@@ -20,6 +16,4 @@ ${c3}(((((((((((((((((((((${c5}@@@${c6}&%&${c5}@@@%${c4},..........
${c3}/((((((((((((${c5}@@@@@@/${c4}.../&& ${c3}/((((((((((((${c5}@@@@@@/${c4}.../&&
${c3}.(((((((((${c5}@@@@(${c4}.... ${c3}.(((((((((${c5}@@@@(${c4}....
${c3}/(((((${c5}@@#${c4}... ${c3}/(((((${c5}@@#${c4}...
${c3}.((${c4}&, ${c3}.((${c4}&,
""")
+19
View File
@@ -0,0 +1,19 @@
{"match": "\"asahi2\"*|\"asahi-linux2\"*", "color": "3 6 1 1 7 8 6"}
${c1}_wwM ${c2}_ww
${c1}MMM${c2}MMMM
${c1}MM
${c3}_ww##############yy_
${c4}wMMMMM${c3}###########${c4}MMMMm
${c4},MMMMMMMMM${c3}######${c4}MMMMMMMM0_
${c4}wMMMMMMMMMMMMM${c5}MM${c6}0MMMMMMMMMMm
${c4},MMMMMMMMMMMMMMM${c5}MMMM${c6}0MMMMMMMMM0,
${c4}wMMMMMMMMMMMMMMMM${c5}MMMMM0${c6}MMMMMMMMMMb
${c4}_MMMMMMMMMMMMMMMMMM${c5}MMMMMMM0${c6}MMMMMMMMM0,
${c4}_MMMMMMMMMMMMMMMMMMM${c5}MMMM${c7}M${c5}MMMW${c6}MMMMMMMMMM_
${c4}_MMMMMMMMMMMMMMMMMMMM${c5}MMMM${c7}M0${c5}MMMW${c6}MMMMMMMMMM_
${c4}~MMMMMMMMMMMMMMMMM${c5}MMMM${c7}M${c5}MMMW${c6}MMMMM00~
${c4}~MMMMMMMMMMMMM${c5}MMMWMMM${c6}0MM${c5}MMM${c6}~
${c4}~MMMMMMMMMM${c5}MMMMM${c6}0MMM~~
${c4}~MMMMMM${c5}MMM${c6}0MM~
${c4}~MM${c5}M${c6}@~
${c4}M
+19
View File
@@ -0,0 +1,19 @@
{"match": "\"aster\"*", "color": "6"}
...''...
.;oOXWMWNXXXNMMN0d:.
.oXMWOo;.. ..:oO;
;KMWx, co,
'KMNl dMMW.
oMMx xMMMMk
xMM: dMMMMMM;
cMMl dMMMMMMMW
NMK xMMMx::dXMx
,MMl xMMN' .o.
cMM; dMMW'
;MMc oMMW,
WMK dMMW, ccccccc.
lMMl oMMM; ooooooo.
OMMc ...
xMMx
;XMN:
,.
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"AsteroidOS\"*", "color": "160 208 202 214"}
from . import AsciiArt
asteroidos = AsciiArt(match=r'''"AsteroidOS"*''', color='160 208 202 214', ascii=r"""
${c1} *** ${c1} ***
${c1} ***** ${c1} *****
${c1} ********** ${c1} **********
@@ -19,6 +15,4 @@ ${c3} /######## ########
${c4} #######%####### ${c4} #######%#######
${c4} (#%%%%%%%# ${c4} (#%%%%%%%#
${c4} %%%%% ${c4} %%%%%
${c4} %%% ${c4} %%%
""")
@@ -1,30 +1,24 @@
# This file is automatically generated. Please do not modify. {"match": "\"astOS\"*", "color": "8"}
from . import AsciiArt
astos = AsciiArt(match=r'''"astOS"*''', color='8', ascii=r"""
${c1} oQA#$%UMn ${c1} oQA#$%UMn
H 9 H 9
G # G #
6 % 6 %
?#M#%KW3" ?#M#%KW3"
// \\ // \\\
// \\ // \\\
// \\ // \\\
// \\ // \\\
n%@$DK&ML .0O3#@&M_ n%@$DK&ML .0O3#@&M_
P # 8 W P # 8 W
H U G # H U G #
B N O @ B N O @
C&&#%HNAR 'WS3QMHB" C&&#%HNAR 'WS3QMHB"
// \\ \\ // \\\ \\\
// \\ \\ // \\\ \\\
// \\ \\ // \\\ \\\
// \\ \\ // \\\ \\\
uURF$##Bv nKWB$%ABc aM@3R@D@b uURF$##Bv nKWB$%ABc aM@3R@D@b
8 M @ O # % 8 M @ O # %
% & G U @ @ % & G U @ @
& @ # % % # & @ # % % #
!HGN@MNCf t&$9#%HQr ?@G#6S@QP !HGN@MNCf t&$9#%HQr ?@G#6S@QP
""")
+23
View File
@@ -0,0 +1,23 @@
{"match": "\"Astra\"*|\"Astra Linux\"*|\"astralinux\"*", "color": "1 7"}
AA
AaaA
Aa${c2}/\${c1}aA
${c1} Aa${c2}/${c1}aa${c2}\${c1}aA
${c1} Aa${c2}/${c1}aAAa${c2}\${c1}aA
${c1} aA${c2}/${c1}aaAAaa${c2}\${c1}Aa
${c1} aA${c2}/${c1}aaAAAAaa${c2}\${c1}Aa
${c1} aaaaaaAAAAa${c2}/${c1}aaAAAAAAaa${c2}\${c1}aAAAAaaaaa
${c1}aAAa${c2}-----${c1}aaaaaAAAAAAAAAAaaaaa${c2}-----${c1}aAAa
${c1} aAA${c2}\ ${c1}aAAAAAAAAAAAAAAAAAAAAAAa${c2} /${c1}AAa
${c1} aAa${c2}\${c1}aAAA${c2}\${c1}AAAA${c2}\${c1}AAAA${c2}\${c1}AAA${c2}\${c1}AAa${c2}/${c1}aAa
${c1} aAa${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\${c1}AA${c2}\\/${c1}aAa
${c1} aAA${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\${c1}Aa${c2}/${c1}AAa
${c1} aA${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\/${c1}Aa
${c1} aA${c2}/${c1}AA${c2}\\\${c1}AA${c2}\\\${c1}AA${c2}\\\${c1}Aa
${c1} aA${c2}/\${c1}AAa${c2}\\\${c1}Aa${c2}\\\${c1}Aa${c2}\\\${c1}Aa
${c1} aA${c2}/\\${c1}AAa${c2}\\/\${c1}a${c2}\\\${c1}Aa${c2}\\${c1}Aa
${c1} aA${c2}/${c1}a${c2}\\\${c1}Aa${c2}\/${c1}AA${c2}\\\\\${c1}Aa${c2}\\${c1}Aa
${c1} aA${c2}/${c1}aA${c2}\\/${c1}aAa aAa${c2}\\\${c1}Aa${c2}\${c1}Aa
${c1} aA${c2}/\${c1}A${c2}\/${c1}Aa aA${c2}\\${c1}A${c2}\\${c1}Aa
${c1} A${c2}|/${c1}aaAa aAaa${c2}\|${c1}A
${c1} aAaa aaAa
+23
View File
@@ -0,0 +1,23 @@
{"match": "\"Astra Linux\"*", "color": "160 231", "foreground": [2]}
${c1} AA
${c1} AaaA
${c1} Aa${c2}/\\${c1}aA
${c1} Aa${c2}/${c1}aa${c2}\\${c1}aA
${c1} Aa${c2}/${c1}aAAa${c2}\\${c1}aA
${c1} aA${c2}/${c1}aaAAaa${c2}\\${c1}Aa
${c1} aA${c2}/${c1}aaAAAAaa${c2}\\${c1}Aa
${c1} aaaaaaAAAAa${c2}/${c1}aaAAAAAAaa${c2}\\${c1}aAAAAaaaaa
${c1} aAAa${c2}-----${c1}aaaaaAAAAAAAAAAaaaaa${c2}-----${c1}aAAa
${c1} aAA${c2}\ ${c1}aAAAAAAAAAAAAAAAAAAAAAAa${c2} /${c1}AAa
${c1} aAa${c2}\\${c1}aAAA${c2}\\${c1}AAAA${c2}\\${c1}AAAA${c2}\\${c1}AAA${c2}\\${c1}AAa${c2}/${c1}aAa
${c1} aAa${c2}\\${c1}aA${c2}\\\\${c1}AAA${c2}\\\\${c1}AAA${c2}\\\\${c1}AA${c2}\\\\/${c1}aAa
${c1} aAA${c2}\\${c1}aA${c2}\\\\${c1}AAA${c2}\\\\${c1}AAA${c2}\\\\${c1}Aa${c2}/${c1}AAa
${c1} aA${c2}\\${c1}aA${c2}\\\\${c1}AAA${c2}\\\\${c1}AAA${c2}\\\\/${c1}Aa
${c1} aA${c2}/${c1}AA${c2}\\\\\\${c1}AA${c2}\\\\\\${c1}AA${c2}\\\\\\${c1}Aa
${c1} aA${c2}/\\${c1}AAa${c2}\\\\\\${c1}Aa${c2}\\\\\\${c1}Aa${c2}\\\\\\${c1}Aa
${c1} aA${c2}/\\\\${c1}AAa${c2}\\\\/\\${c1}a${c2}\\\\\\${c1}Aa${c2}\\\\${c1}Aa
${c1} aA${c2}/${c1}a${c2}\\\\\\${c1}Aa${c2}\\/${c1}AA${c2}\\\\\\\\\\${c1}Aa${c2}\\\\${c1}Aa
${c1} aA${c2}/${c1}aA${c2}\\\\/${c1}aAa aAa${c2}\\\\\\${c1}Aa${c2}\\${c1}Aa
${c1} aA${c2}/\\${c1}A${c2}\\/${c1}Aa aA${c2}\\\\${c1}A${c2}\\\\${c1}Aa
${c1} A${c2}|/${c1}aaAa aAaa${c2}\\|${c1}A
${c1} aAaa aaAa
@@ -1,9 +1,5 @@
# This file is automatically generated. Please do not modify. {"match": "\"Ataraxia Linux\"*|\"Ataraxia\"*", "color": "4 5"}
'l:
from . import AsciiArt
januslinux = AsciiArt(match=r'''"januslinux"*|"janus"*|"Ataraxia Linux"*|"Ataraxia"*''', color='4 5 6 2', ascii=r"""
${c1} 'l:
loooooo loooooo
loooo coooool loooo coooool
looooooooooooooooooool looooooooooooooooooool
@@ -27,5 +23,3 @@ ${c1} cooo: ${c2}coooooooooooooooooool
:oooool, coool:, looool:, :oooool, coool:, looool:,
looool: ooooooooooooooo: looool: ooooooooooooooo:
cooolc .ooooooooooool cooolc .ooooooooooool
""")
+25
View File
@@ -0,0 +1,25 @@
{"match": "\"Athena\"*", "color": "7 3"}
${c1} . ..
${c1} :####: ####.
${c1} .################
${c1} :##################
${c1}.###################.
${c1}######## #######
${c1}####### ${c2}####${c1} #####
${c1}:#######. ####
${c1} ######### ${c2}#${c1} ## #
${c1} ####### ${c2}##${c1} ####
${c1}######## ${c2}####${c1} #######
${c1}######## ${c2}#####${c1} ########
${c1}######## ${c2}#######${c1} #######
${c1} ####### ${c2}########${c1} #######
${c1} ######## ${c2}#########${c1} ######
${c1} ######## ${c2}#########${c1} #####
${c1} ####### ${c2}#########${c1} ####
${c1} ####### ${c2}#########${c1} ##
${c1} ####### ${c2}########${c1} ##
${c1} ###### ${c2}########${c1} #
${c1} ### ${c2}#######${c1}
${c1} ${c2}######${c1}
${c1} ${c2}####${c1}
${c1} ${c2}##${c1}
+30
View File
@@ -0,0 +1,30 @@
{"match": "\"AthenaOS\"*", "color": "4 4"}
u.
..:Y
.Y..1
..::i::.. .br7S.
.::::...::::. 5dDr:
..:::.. .:i::.. Y7:
..:::::.. ..::::.
...:i:i:i:.. ${c2}... ${c1}:.:..:i:::...
::i:. ${c2}.USL Yr ${c1}..i::.
.:::. ${c2}:K :u. ${c1}.::.
:... ${c2}jB. .:vUi: 77 KB: ${c1}..::
...: ${c2}iBR vP::5X5PgSKXvLjS. iBB ${c1}.::.
:i:: ${c2}BBQr jgDIuj1UuJjXbbi 2BBP ${c1}:::;
'i:: ${c2}sQBg: i2S55121XSSU. YBQZ: ${c1}.:::
r::: ${c2}r:JgBMu. Q :BqEqZEB: Q :qBBK7i: ${c1}:i:i
.rir. ${c2}IBqPDgQBDr P rB :q 1QBRgEqgB ${c1}.::i.
:i:i ${c2}:JsXPDDRQQPBL P qQXBQRDDPIYY ${c1}rir:
:iii ${c2}5qvLUDDMgMgBB5 :DBQZRgMDdJ7Ygi ${c1}iir:
iri: ${c2}MBRgdZZggQgRBMIBQQRRggdZdMBBr ${c1}riri
irii ${c2}IBQgdZbDDRRRgQgQQMZDdZdgBB. ${c1}iiri
i7rr ${c2}.BBQZZbEEMQQDBQMEZdDDBBP ${c1}.rir:
:7ir. ${c2}7BBQMDMQSbB5ZBggQBBQ. ${c1}ivr7.
:r7r. ${c2}7BBBB:rBbQ.1BBBM. ${c1}:r7vi
::rLrr. ${c2}.b:rBQ7QB uU. ${c1}:7vLi.
.BB .iLYv: ${c1}idL B1 ${c1}:r77r.
LBB :vrvvr rvu7r:
ZB. ':7v177Lsvurr:'
.d2 ''::r:''
:'
@@ -1,9 +1,5 @@
# This file is automatically generated. Please do not modify. {"match": "\"AthenaOS_old\"*", "color": "7 3"}
. ..
from . import AsciiArt
athena = AsciiArt(match=r'''"Athena"*''', color='7 3', ascii=r"""
${c1} . ..
${c1} :####: ####. ${c1} :####: ####.
${c1} .################ ${c1} .################
${c1} :################## ${c1} :##################
@@ -27,5 +23,3 @@ ${c1} ### ${c2}#######${c1}
${c1} ${c2}######${c1} ${c1} ${c2}######${c1}
${c1} ${c2}####${c1} ${c1} ${c2}####${c1}
${c1} ${c2}##${c1} ${c1} ${c2}##${c1}
""")
+29
View File
@@ -0,0 +1,29 @@
{"match": "\"Aurora\"*", "color": "4 5 1 7"}
+++++++++
+++++${c4}+${c1}++++++${c4}+${c1}++
++++++${c4}+${c1}+++ +++++++++++
+++++++++++ ${c2}+${c1} +++++${c4}+${c1}+++++
++++++${c4}+${c1}++++ ${c4}+++${c1} +++++++++++
++++++++++${c4} + +++++ ++ ${c2}+++++${c4}+${c2}++++
+++${c4}+${c1}++++${c4} + + + +++++++ + + ${c2}+++++${c4}+${c2}++
++++++${c4} ${c2}+${c4} +++ +++++++++ +++ ${c2}++++++++
+++${c4}+${c1}++${c4} + +++++ +++++ +
++++++${c4} ${c2}+${c4} +++++ +++++ +++++
++${c4}+${c2}+++${c4} + +++++ ++++++ ++++++++++
++++++${c4} +++++ +++++ + +++++++++++++++++++
++++++${c4} + +++++ + +++++++++++++++
+++${c4}++${c2}+${c4} ++++++ +++++++++++++
++++++${c4} + ++++++ +++++++++++++ ${c2}+++ ${c4}++
++++++${c4} ++++++++++++++++ ${c2}++${c4}+${c2}+ ${c4}++ ${c1}+
++++++${c4} ++++++++++++++ ${c3}+ ${c2}++++
++++++${c4} +++++++++++ + ${c4}+ ${c3}++++++
++${c4}+${c3}+++${c4} ++++++++++ +++ ${c3}+++++++++++++
+++++ ${c4}+++++++++ + ${c3}+++++++++++++
+++ ${c4}++++++++ ${c2}++${c4} + ${c3}++++++++++++++ ++++
++ ${c4}++++++++ ${c3}+ ++++++++++++++ +++++++
${c4}++++++ ${c2}+ ${c3}+++++++++++++ +++++++${c2}++
${c4}++++ ${c3}+++++++++++++ ++++++${c2}+++
+++++++++++ ++++++${c2}+++
+++++ ++++++${c2}+++
++++++${c2}++
+++++
+17
View File
@@ -0,0 +1,17 @@
{"match": "\"AxOS\"*", "color": "38;2;222;6;255 38;2;222;6;255"}
▂🬭𜴧⎻𜷗𜴗𜴦𜵎⎻𜴧🬭▂
▁▂𜴧━𜵼𜵶𜶮▂🬭🬭𜴐🭗 🬁𜴜🬭🬭▂𜶮▁𜵁━𜴧▂▁
𜷓𜵐🬂🬂🮂𜶮𜴸𜴪━𜴆🮂▔ ▔🮂𜴆━𜴩𜵳𜴸🮂🬂🬂𜶚🬿
🭄🬨▍ 🬜🮂▔ ▁▂▂🬭🬭▂▂▁ ▔🮂🬪 🮈🬕𜶿
🭄🭙▐▎𜵫 🭃██████████🭎 🭢𜶡🮇▌🭤𜶿
🭄🭙 ▐🭄🭙 🭋█████🭜𜴦█████🭀 🭤🭏▌ 🭤🭏
𜵫🭗 🮉🭛 🭃███🭝🭙 🭥🭒███🭎 🭦▋ 🭢𜶡
▟🬮𜴧━🭷🭘 🭋████▄▂ ▂▄████🭀 🭣𜴇━𜴧🬯🭏
🭕𜴸𜴆╾🭺🬽 🭃██🭡 🭖██🭐 🭈𜵡╼𜴆🬡🭠
𜴤🬼 🮉🭀 🭋███΄ 🭤███🭀 🭋▊ 🭇𜵐
𜴠🬾 ▐𜴢🬾▁▁ 🭃██𜴍 𜶘██🭐 ▁▁🭉🭫▌ 🭉🭠
𜴠🬾🮈▎𜶚 ▔🮂🬂▀🬎🬎 🮅🬎▀🬂🮂▔ 𜵐🮇▌🭉𜴏
𜴢🭿▍ 𜴬▂▁ ▁▂🬜΄🮈🬲𜴏
🭥𜶡🬭🬭▂𜶭▁𜵁━𜴧▂▁ ▁▂𜴧━𜶷𜶭𜶮▂🬭🬭𜵫🭚
▔⎺𜴆━𜴩▔𜶮🮂🬂🬂𜴜🬼 🭇𜴐🬂🬂🮂𜶮▔𜴨━𜴆⎺▔
⠈🮂🭷𜴆╾𜶦𜷞🭄𜴬╼𜴆🬂🮂΄
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"azos\"*", "color": "6 1"}
from . import AsciiArt
azos = AsciiArt(match=r'''"azos"*''', color='6 1', ascii=r"""
${c1} ////. ${c2} ((((( ${c1} ////. ${c2} (((((
${c1} //////// ${c2} @(((((((( ${c1} //////// ${c2} @((((((((
${c1} //////// ${c2} @(((((((( ${c1} //////// ${c2} @((((((((
@@ -19,6 +15,4 @@ ${c1} //////// ///////// ${c2} &(((((((( @((((((((
${c1} //////// ////// ${c2} @(((( @(((((((( ${c1} //////// ////// ${c2} @(((( @((((((((
${c1} //////// ${c2} @(((((((( ${c1} //////// ${c2} @((((((((
${c1} //////// ${c2} @(((((((( ${c1} //////// ${c2} @((((((((
${c1} ///// ${c2} ((((( ${c1} ///// ${c2} (((((
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"Bazzite\"*", "color": "5 5"}
from . import AsciiArt
bazzite = AsciiArt(match=r'''"Bazzite"*''', color='5 5', ascii=r"""
${c1} %%%%%%====%%%%%%%%%% ${c1} %%%%%%====%%%%%%%%%%
%%%%%%%% %%%%%%%%%%%%%% %%%%%%%% %%%%%%%%%%%%%%
%%%%%%%%% %%%%%%%%%%%%%%%% %%%%%%%%% %%%%%%%%%%%%%%%%
@@ -21,6 +17,4 @@ ${c1} %%%%%%====%%%%%%%%%%
%#######==========######### %#######==========#########
####################### #######################
################### ###################
########### ###########
""")
+18
View File
@@ -0,0 +1,18 @@
{"match": "\"Bedrock\"*", "color": "8 7"}
${c1}--------------------------------------
--------------------------------------
--------------------------------------
---${c2}\\\\\\\\\\\\\\\\\\\\\\\\${c1}-----------------------
----${c2}\\\\\\ \\\\\\${c1}----------------------
-----${c2}\\\\\\ \\\\\\${c1}---------------------
------${c2}\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\${c1}------
-------${c2}\\\\\\ \\\\\\${c1}-----
--------${c2}\\\\\\ \\\\\\${c1}----
---------${c2}\\\\\\ ______ \\\\\\${c1}---
----------${c2}\\\\\\ ///${c1}---
-----------${c2}\\\\\\ ///${c1}----
------------${c2}\\\\\\ ///${c1}-----
-------------${c2}\\\\\\////////////////${c1}------
--------------------------------------
--------------------------------------
--------------------------------------
+8
View File
@@ -0,0 +1,8 @@
{"match": "\"bedrock_small\"*", "color": "8 7"}
_________
| ${c2}__ ${c1} |
| ${c2}\ \___ ${c1} |
| ${c2} \ _ \${c1} |
| ${c2} \___/${c1} |
|_________|
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"BigLinux\"*", "color": "6 11 4"}
from . import AsciiArt
biglinux = AsciiArt(match=r'''"BigLinux"*''', color='6 11 4', ascii=r"""
${c1} ... ${c1} ...
:OWMMMNd. :OWMMMNd.
:NMMMMMMMMWc :NMMMMMMMMWc
@@ -21,6 +17,4 @@ ${c3} .X. oMMMMW. l.
dMk:..;xWMMMMW, dMk:..;xWMMMMW,
kMMMMMMMMMMX. kMMMMMMMMMMX.
:XMMMMMMK: :XMMMMMMK:
':MM:" Made in Brazil ':MM:" Made in Brazil
""")
@@ -1,8 +1,4 @@
# This file is automatically generated. Please do not modify. {"match": "\"BigLinux_large\"*", "color": "2 3 4 7"}
from . import AsciiArt
biglinux_large = AsciiArt(match=r'''"BigLinux_large"*''', color='2 3 4 7', ascii=r"""
${c4} ${c4}
${c3}.cd0KXXX${c4}0${c3}x; ${c3}.cd0KXXX${c4}0${c3}x;
${c3}.oXM${c4}M${c3}MMMMMMMMMWo ${c3}.oXM${c4}M${c3}MMMMMMMMMWo
@@ -24,6 +20,4 @@ ${c4}
${c1}0MMMX0O0XMMMMMMMMMMo ${c1}0MMMX0O0XMMMMMMMMMMo
${c1}oWMMMMMMMMMMMMMMk. ${c1}oWMMMMMMMMMMMMMMk.
${c1}.oXMMMMMMMMW0c. ${c1}.oXMMMMMMMMW0c.
${c1}.;ccc:,. ${c1}.;ccc:,.
""")

Some files were not shown because too many files have changed in this diff Show More