Generate distros.rs on build

This commit is contained in:
Teoh Han Hui 2024-06-29 07:17:07 +08:00
parent 7c874a8e9a
commit 11601933f9
No known key found for this signature in database
GPG key ID: D43E2BABAF97DCAE
6 changed files with 254 additions and 0 deletions

70
Cargo.lock generated
View file

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.86"
@ -49,11 +58,13 @@ dependencies = [
"anyhow",
"bpaf",
"indexmap",
"regex",
"rgb",
"shell-words",
"strum",
"tracing",
"tracing-subscriber",
"unicode-normalization",
]
[[package]]
@ -84,6 +95,12 @@ version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -136,6 +153,35 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rgb"
version = "0.8.37"
@ -221,6 +267,21 @@ dependencies = [
"once_cell",
]
[[package]]
name = "tinyvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tracing"
version = "0.1.40"
@ -284,6 +345,15 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "valuable"
version = "0.1.0"

View file

@ -17,8 +17,10 @@ anyhow = { version = "1.0.86", default-features = false }
bpaf = { version = "0.9.12", default-features = false }
derive_more = { version = "1.0.0-beta.6", default-features = false }
indexmap = { version = "2.2.6", default-features = false }
regex = { version = "1.10.5", default-features = false }
rgb = { version = "0.8.37", default-features = false }
shell-words = { version = "1.1.0", default-features = false }
strum = { version = "0.26.3", default-features = false }
tracing = { version = "0.1.40", default-features = false }
tracing-subscriber = { version = "0.3.18", default-features = false }
unicode-normalization = { version = "0.1.23", default-features = false }

View file

@ -20,6 +20,11 @@ strum = { workspace = true, features = ["derive", "std"] }
tracing = { workspace = true, features = ["attributes", "std"] }
tracing-subscriber = { workspace = true, features = ["ansi", "fmt", "smallvec", "std", "tracing-log"] }
[build-dependencies]
indexmap = { workspace = true, features = ["std"] }
regex = { workspace = true, features = ["perf", "std", "unicode"] }
unicode-normalization = { workspace = true, features = ["std"] }
[features]
default = ["autocomplete", "color"]
autocomplete = ["bpaf/autocomplete"]

173
crates/hyfetch/build.rs Normal file
View file

@ -0,0 +1,173 @@
use std::path::Path;
use std::{env, fs};
use indexmap::IndexMap;
use regex::Regex;
use unicode_normalization::UnicodeNormalization;
#[derive(Debug)]
struct AsciiDistro {
pattern: String,
art: String,
}
impl AsciiDistro {
fn friendly_name(&self) -> String {
self.pattern
.split('|')
.next()
.expect("invalid distro pattern")
.trim_matches(|c: char| c.is_ascii_punctuation() || c == ' ')
.replace(['"', '*'], "")
}
}
fn main() {
let neofetch_path = Path::new(env!("CARGO_WORKSPACE_DIR")).join("neofetch");
println!("cargo:rerun-if-changed={}", neofetch_path.display());
let out_dir = env::var("OUT_DIR").unwrap();
let out_path = Path::new(&out_dir);
export_distros(neofetch_path, out_path);
}
fn export_distros<P>(neofetch_path: P, out_path: &Path)
where
P: AsRef<Path>,
{
let distros = parse_ascii_distros(neofetch_path);
let mut variants = IndexMap::with_capacity(distros.len());
for distro in &distros {
let variant = distro
.friendly_name()
.replace(|c: char| c.is_ascii_punctuation() || c == ' ', "_")
.nfc()
.collect::<String>();
variants.insert(variant, distro);
}
let mut buf = "
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum Distro {
"
.to_owned();
for (variant, distro) in &variants {
buf.push_str(&format!(
"
// {})
{variant},
",
distro.pattern
));
}
buf.push_str(
"
}
",
);
buf.push_str(
"
impl Distro {
pub fn ascii_art(&self) -> &str {
let art = match self {
",
);
let quotes = "#".repeat(80);
for (variant, distro) in &variants {
buf.push_str(&format!(
"
Self::{variant} => r{quotes}\"
{}
\"{quotes},
",
distro.art
));
}
buf.push_str(
"
};
&art[1..(art.len() - 1)]
}
}
",
);
fs::write(out_path.join("distros.rs"), buf).expect("couldn't write distros.rs");
}
/// Parses ascii distros from neofetch script.
fn parse_ascii_distros<P>(neofetch_path: P) -> Vec<AsciiDistro>
where
P: AsRef<Path>,
{
let neofetch_path = neofetch_path.as_ref();
let nf = {
let nf = fs::read_to_string(neofetch_path).expect("couldn't read neofetch script");
// Get the content of "get_distro_ascii" function
let (_, nf) = nf
.split_once("get_distro_ascii() {\n")
.expect("couldn't find get_distro_ascii function");
let (nf, _) = nf
.split_once("\n}\n")
.expect("couldn't find end of get_distro_ascii function");
let mut nf = nf.replace('\t', &" ".repeat(4));
// Remove trailing spaces
while nf.contains(" \n") {
nf = nf.replace(" \n", "\n");
}
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![];
for b in case_re.split(&nf) {
blocks.extend(eof_re.split(b).map(|sub| sub.trim()));
}
// Parse blocks
fn parse_block(block: &str) -> Option<AsciiDistro> {
let (block, art) = block.split_once("'EOF'\n")?;
// Join \
//
// > A <backslash> that is not quoted shall preserve the literal value of the
// > following character, with the exception of a <newline>. If a <newline>
// > 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
// > entirely from the input and is not replaced by any white space, it cannot
// > serve as a token separator.
// See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_01
let block = block.replace("\\\n", "");
// Get case pattern
let pattern = block
.split('\n')
.next()
.and_then(|pattern| pattern.trim().strip_suffix(')'))?;
Some(AsciiDistro {
pattern: pattern.to_owned(),
art: art.to_owned(),
})
}
blocks
.iter()
.filter_map(|block| parse_block(block))
.collect()
}

View file

@ -0,0 +1,3 @@
#![allow(non_camel_case_types)]
include!(concat!(env!("OUT_DIR"), "/distros.rs"));

View file

@ -1,5 +1,6 @@
pub mod cli_options;
pub mod color_util;
pub mod distros;
pub mod neofetch_util;
pub mod presets;
pub mod types;