Skip to content

Commit

Permalink
Generate distros.rs on build
Browse files Browse the repository at this point in the history
  • Loading branch information
teohhanhui committed Jun 28, 2024
1 parent 7c874a8 commit 5cdc0d6
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
70 changes: 70 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
5 changes: 5 additions & 0 deletions crates/hyfetch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
173 changes: 173 additions & 0 deletions crates/hyfetch/build.rs
Original file line number Diff line number Diff line change
@@ -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 {
(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(
"
})
.trim()
}
}
",
);

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()
}
3 changes: 3 additions & 0 deletions crates/hyfetch/src/distros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#![allow(non_camel_case_types)]

include!(concat!(env!("OUT_DIR"), "/distros.rs"));
1 change: 1 addition & 0 deletions crates/hyfetch/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 5cdc0d6

Please sign in to comment.