[+] Distro - Add 6-color lambda support for NixOS logo (#543)

This commit is contained in:
Azalea
2026-10-16 05:28:12 +00:00
parent 520f3799f1
commit a50d5077e4
8 changed files with 193 additions and 142 deletions

View File

@@ -145,6 +145,7 @@ cargo install --git https://github.com/hykilpikonna/hyfetch
**✨ Features & Enhancements**
* Added `berrisexual` & `almondsexual` flags ([#545](https://github.com/hykilpikonna/hyfetch/issues/545)).
* Added 6-color lambda support for NixOS logo ([#543](https://github.com/hykilpikonna/hyfetch/issues/543)).
* Published crate to crates.io with automated OIDC publishing ([#544](https://github.com/hykilpikonna/hyfetch/issues/544)).
**🐛 Bug Fixes**

View File

@@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::BTreeSet;
use std::fmt::Write as _;
use std::ops::Range;
@@ -107,10 +108,7 @@ pub fn get_random_alignment(preset: &ColorProfile, asc: &NormalizedAsciiArt) ->
let mut rng = fastrand::Rng::new();
rng.shuffle(&mut preset_indices);
let colors = slots
.into_iter()
.zip(preset_indices)
.collect();
let colors = slots.into_iter().zip(preset_indices).collect();
ColorAlignment::Custom { colors }
}
@@ -362,6 +360,21 @@ impl NormalizedAsciiArt {
.fill_starting()
.context("failed to fill in starting neofetch color codes")?;
let slots: BTreeSet<NeofetchAsciiIndexedColor> = {
let asc = lines.join("\n");
let ac = NEOFETCH_COLORS_AC
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
ac.find_iter(&asc)
.map(|m| {
let ai_start = m.start().checked_add(3).unwrap();
let ai_end = m.end().checked_sub(1).unwrap();
asc[ai_start..ai_end]
.parse()
.expect("neofetch ascii color index should not be invalid")
})
.collect()
};
let ColorProfile { colors } = color_profile.unique_colors();
// Apply colors
@@ -371,13 +384,33 @@ impl NormalizedAsciiArt {
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
const N: usize = NEOFETCH_COLOR_PATTERNS.len();
let mut replacements = vec![Cow::from(""); N];
for (&ai, &pi) in custom_colors {
let ai: u8 = ai.into();
let pi: u8 = pi.into();
replacements[usize::from(ai.checked_sub(1).unwrap())] = colors
[usize::from(pi)]
.to_ansi_string(color_mode, ForegroundBackground::Foreground)
.into();
if !colors.is_empty() {
for (&ai, &pi) in custom_colors {
let ai: u8 = ai.into();
let pi: u8 = pi.into();
let color = &colors[usize::from(pi) % colors.len()];
replacements[usize::from(ai.checked_sub(1).unwrap())] = color
.to_ansi_string(color_mode, ForegroundBackground::Foreground)
.into();
}
// Fallback for slots in the art that aren't in custom_colors (e.g. backward compat)
for &ai in &slots {
let ai_u8: u8 = ai.into();
let idx = usize::from(ai_u8.checked_sub(1).unwrap());
if replacements[idx].is_empty() {
let fallback_slot =
NeofetchAsciiIndexedColor::try_from((ai_u8 - 1) % 2 + 1)
.unwrap();
let pi = custom_colors.get(&fallback_slot).copied().unwrap_or_else(
|| (((ai_u8 - 1) as usize % colors.len()) as u8).into(),
);
let pi_u8: u8 = pi.into();
let color = &colors[usize::from(pi_u8) % colors.len()];
replacements[idx] = color
.to_ansi_string(color_mode, ForegroundBackground::Foreground)
.into();
}
}
}
ac.replace_all(&asc, &replacements)
};
@@ -406,37 +439,37 @@ impl NormalizedAsciiArt {
NEOFETCH_COLORS_AC.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
let mut last = None;
let lines =
self.lines
.iter()
.map(|line| {
let line: &str = line.as_ref();
let lines = self
.lines
.iter()
.map(|line| {
let line: &str = line.as_ref();
let mut new = String::new();
let mut matches = ac.find_iter(line).peekable();
let mut new = String::new();
let mut matches = ac.find_iter(line).peekable();
match matches.peek() {
Some(m)
if m.start() == 0
|| line[0..m.start()].trim_end_matches(' ').is_empty() =>
{
// Line starts with neofetch color code
last = Some(&line[m.span()]);
},
_ => {
new.push_str(last.unwrap_or(NEOFETCH_COLOR_PATTERNS[0]));
},
}
new.push_str(line);
// Get the last placeholder for the next line
if let Some(m) = matches.last() {
match matches.peek() {
Some(m)
if m.start() == 0
|| line[0..m.start()].trim_end_matches(' ').is_empty() =>
{
// Line starts with neofetch color code
last = Some(&line[m.span()]);
}
},
_ => {
new.push_str(last.unwrap_or(NEOFETCH_COLOR_PATTERNS[0]));
},
}
new.push_str(line);
Ok(new)
})
.collect::<Result<_>>()?;
// Get the last placeholder for the next line
if let Some(m) = matches.last() {
last = Some(&line[m.span()]);
}
Ok(new)
})
.collect::<Result<_>>()?;
Ok(Self {
lines,
@@ -445,4 +478,3 @@ impl NormalizedAsciiArt {
})
}
}

View File

@@ -1319,7 +1319,7 @@ fn create_config(
let asc = asc.lines.join("\n");
let ac =
NEOFETCH_COLORS_AC.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
ac.find_iter(&asc)
let mut v: Vec<NeofetchAsciiIndexedColor> = ac.find_iter(&asc)
.map(|m| {
let ai_start = m.start().checked_add(3).unwrap();
let ai_end = m.end().checked_sub(1).unwrap();
@@ -1327,7 +1327,9 @@ fn create_config(
.parse()
.expect("neofetch ascii color index should not be invalid")
})
.collect()
.collect();
v.sort();
v.into_iter().collect()
};
// Loop for random rolling
@@ -1340,23 +1342,25 @@ fn create_config(
while preset_indices.len() < slots.len() {
preset_indices.extend_from_within(0..);
}
let ordered_p: Vec<PresetIndexedColor> = preset_indices[..slots.len()].to_vec();
let preset_index_permutations: IndexSet<Vec<PresetIndexedColor>> = preset_indices
.into_iter()
.permutations(slots.len())
.take(1000)
.collect();
let random_count = (ascii_per_row as usize * ascii_rows as usize).saturating_sub(arrangements.len()).clamp(0, u8::MAX.into()) as u8;
let choices: IndexSet<Vec<PresetIndexedColor>> =
if usize::from(random_count) > preset_index_permutations.len() {
preset_index_permutations
} else {
rng.choose_multiple(
preset_index_permutations.into_iter(),
usize::from(random_count),
)
.into_iter()
.collect()
};
let other_permutations: IndexSet<Vec<PresetIndexedColor>> = preset_index_permutations
.into_iter()
.filter(|p| p != &ordered_p)
.collect();
let mut choices: IndexSet<Vec<PresetIndexedColor>> = IndexSet::new();
choices.insert(ordered_p);
let sample_count = (usize::from(random_count)).saturating_sub(1);
if sample_count >= other_permutations.len() {
choices.extend(other_permutations);
} else {
choices.extend(rng.choose_multiple(other_permutations.into_iter(), sample_count));
}
let choices: Vec<IndexMap<NeofetchAsciiIndexedColor, PresetIndexedColor>> = choices
.into_iter()
.map(|c| {

View File

@@ -1,21 +1,21 @@
{"match": "\"NixOS\"*", "color": "4 6"}
${c1} ▗▄▄▄ ${c2}▗▄▄▄▄ ▄▄▄▖
${c1} ▜███▙ ${c2}▜███▙ ▟███▛
${c1} ▜███▙ ${c2}▜███▙▟███▛
${c1} ▜███▙ ${c2}▜██████▛
${c1} ▟█████████████████▙ ${c2}▜████▛ ${c1}▟▙
${c1} ▟███████████████████▙ ${c2}▜███▙ ${c1}▟██▙
${c2} ▄▄▄▄▖ ▜███▙ ${c1}▟███▛
${c2} ▟███▛ ▜██▛ ${c1}▟███▛
${c2} ▟███▛ ▜▛ ${c1}▟███▛
${c2}▟███████████▛ ${c1}▟██████████▙
${c2}▜██████████▛ ${c1}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ▟███▛
${c2} ▟███▛ ${c1}▟██▙ ▟███▛
${c2} ▟███▛ ${c1}▜███▙ ▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c2}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c2}▜████████████████▛
${c1} ▟██████▙ ${c2}▜███▙
${c1} ▟███▛▜███▙ ${c2}▜███▙
${c1} ▟███▛ ▜███▙ ${c2}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c2}▀▀▀▘
{"match": "\"NixOS\"*", "color": "4 6 4 6 4 6"}
${c3} ▗▄▄▄ ${c4}▗▄▄▄▄ ▄▄▄▖
${c3} ▜███▙ ${c4}▜███▙ ▟███▛
${c3} ▜███▙ ${c4}▜███▙▟███▛
${c3} ▜███▙ ${c4}▜██████▛
${c3} ▟█████████████████▙ ${c4}▜████▛ ${c5}▟▙
${c3} ▟███████████████████▙ ${c4}▜███▙ ${c5}▟██▙
${c2} ▄▄▄▄▖ ${c4}▜███▙ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜██▛ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜▛ ${c5}▟███▛
${c2}▟███████████▛ ${c5}▟██████████▙
${c2}▜██████████▛ ${c5}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▟██▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▜███▙ ${c5}▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c6}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c6}▜████████████████▛
${c1} ▟██████▙ ${c6}▜███▙
${c1} ▟███▛▜███▙ ${c6}▜███▙
${c1} ▟███▛ ▜███▙ ${c6}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c6}▀▀▀▘

View File

@@ -1,21 +1,21 @@
{"match": "\"nixos_colorful\"*", "color": "4 6 4 6 4 6"}
${c1} ▗▄▄▄ ${c2}▗▄▄▄▄ ▄▄▄▖
${c1} ▜███▙ ${c2}▜███▙ ▟███▛
${c1} ▜███▙ ${c2}▜███▙▟███▛
${c1} ▜███▙ ${c2}▜██████▛
${c1} ▟█████████████████▙ ${c2}▜████▛ ${c3}▟▙
${c1} ▟███████████████████▙ ${c2}▜███▙ ${c3}▟██▙
${c6} ▄▄▄▄▖ ${c2}▜███▙ ${c3}▟███▛
${c6} ▟███▛ ${c2}▜██▛ ${c3}▟███▛
${c6} ▟███▛ ${c2}▜▛ ${c3}▟███▛
${c6}▟███████████▛ ${c3}▟██████████▙
${c6}▜██████████▛ ${c3}▟███████████▛
${c6} ▟███▛ ${c5}▟▙ ${c3}▟███▛
${c6} ▟███▛ ${c5}▟██▙ ${c3}▟███▛
${c6} ▟███▛ ${c5}▜███▙ ${c3}▝▀▀▀▀
${c6} ▜██▛ ${c5}▜███▙ ${c4}▜██████████████████▛
${c6} ▜▛ ${c5}▟████▙ ${c4}▜████████████████▛
${c5} ▟██████▙ ${c4}▜███▙
${c5} ▟███▛▜███▙ ${c4}▜███▙
${c5} ▟███▛ ▜███▙ ${c4}▜███▙
${c5} ▝▀▀▀ ▀▀▀▀▘ ${c4}▀▀▀▘
${c3} ▗▄▄▄ ${c4}▗▄▄▄▄ ▄▄▄▖
${c3} ▜███▙ ${c4}▜███▙ ▟███▛
${c3} ▜███▙ ${c4}▜███▙▟███▛
${c3} ▜███▙ ${c4}▜██████▛
${c3} ▟█████████████████▙ ${c4}▜████▛ ${c5}▟▙
${c3} ▟███████████████████▙ ${c4}▜███▙ ${c5}▟██▙
${c2} ▄▄▄▄▖ ${c4}▜███▙ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜██▛ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜▛ ${c5}▟███▛
${c2}▟███████████▛ ${c5}▟██████████▙
${c2}▜██████████▛ ${c5}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▟██▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▜███▙ ${c5}▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c6}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c6}▜████████████████▛
${c1} ▟██████▙ ${c6}▜███▙
${c1} ▟███▛▜███▙ ${c6}▜███▙
${c1} ▟███▛ ▜███▙ ${c6}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c6}▀▀▀▘

View File

@@ -441,6 +441,8 @@ def create_config() -> Config:
ascii_per_row = max(1, term_size()[0] // (asc_width + 2))
ascii_rows = max(1, (term_size()[1] - 8) // asc_lines)
slots = sorted(set(map(int, re.findall(r'(?<=\${c)[0-9]+(?=})', asc))))
# Displays horizontal and vertical arrangements in the first iteration, but hide them in
# later iterations
hv_arrangements = [
@@ -455,15 +457,18 @@ def create_config() -> Config:
# Random color schemes
pis = list(range(len(_prs.unique_colors().colors)))
slots = list(set(map(int, re.findall('(?<=\\${c)[0-9](?=})', asc))))
slots = sorted(set(map(int, re.findall(r'(?<=\${c)[0-9]+(?=})', asc))))
while len(pis) < len(slots):
pis += pis
perm = {p[:len(slots)] for p in islice(permutations(pis), 1000)}
ordered_p = tuple(pis[:len(slots)])
other_perms = [p for p in perm if p != ordered_p]
random_count = max(0, ascii_per_row * ascii_rows - len(arrangements))
if random_count > len(perm):
choices = perm
choices = [ordered_p] + other_perms
else:
choices = random.sample(sorted(perm), random_count)
sample_count = max(0, random_count - 1)
choices = [ordered_p] + random.sample(sorted(other_perms), min(sample_count, len(other_perms)))
choices = [{slots[i]: n for i, n in enumerate(c)} for c in choices]
arrangements += [(f'random{i}', ColorAlignment('custom', r)) for i, r in enumerate(choices)]
asciis = [[*ca.recolor_ascii(asc, _prs).split('\n'), k.center(asc_width)] for k, ca in arrangements]

View File

@@ -202,12 +202,21 @@ class ColorAlignment:
asc = '\n'.join(preset.color_text(line) + color('&~&*') for line in lines)
else:
preset = preset.unique_colors()
colors = preset.unique_colors().colors
if colors:
slots = sorted(set(map(int, re.findall(r'(?<=\${c)[0-9]+(?=})', asc))))
color_map = {}
for s in slots:
if s in self.custom_colors:
pi = self.custom_colors[s]
elif ((s - 1) % 2 + 1) in self.custom_colors:
pi = self.custom_colors[(s - 1) % 2 + 1]
else:
pi = (s - 1)
color_map[s] = colors[pi % len(colors)].to_ansi()
# Apply colors
color_map = {ai: preset.colors[pi].to_ansi() for ai, pi in self.custom_colors.items()}
for ascii_i, c in color_map.items():
asc = asc.replace(f'${{c{ascii_i}}}', c)
for ascii_i, c in color_map.items():
asc = asc.replace(f'${{c{ascii_i}}}', c)
return asc

View File

@@ -12888,52 +12888,52 @@ EOF
"nixos_colorful"*)
set_colors 4 6 4 6 4 6
read -rd '' ascii_data <<'EOF'
${c1} ▗▄▄▄ ${c2}▗▄▄▄▄ ▄▄▄▖
${c1} ▜███▙ ${c2}▜███▙ ▟███▛
${c1} ▜███▙ ${c2}▜███▙▟███▛
${c1} ▜███▙ ${c2}▜██████▛
${c1} ▟█████████████████▙ ${c2}▜████▛ ${c3}▟▙
${c1} ▟███████████████████▙ ${c2}▜███▙ ${c3}▟██▙
${c6} ▄▄▄▄▖ ${c2}▜███▙ ${c3}▟███▛
${c6} ▟███▛ ${c2}▜██▛ ${c3}▟███▛
${c6} ▟███▛ ${c2}▜▛ ${c3}▟███▛
${c6}▟███████████▛ ${c3}▟██████████▙
${c6}▜██████████▛ ${c3}▟███████████▛
${c6} ▟███▛ ${c5}▟▙ ${c3}▟███▛
${c6} ▟███▛ ${c5}▟██▙ ${c3}▟███▛
${c6} ▟███▛ ${c5}▜███▙ ${c3}▝▀▀▀▀
${c6} ▜██▛ ${c5}▜███▙ ${c4}▜██████████████████▛
${c6} ▜▛ ${c5}▟████▙ ${c4}▜████████████████▛
${c5} ▟██████▙ ${c4}▜███▙
${c5} ▟███▛▜███▙ ${c4}▜███▙
${c5} ▟███▛ ▜███▙ ${c4}▜███▙
${c5} ▝▀▀▀ ▀▀▀▀▘ ${c4}▀▀▀▘
${c3} ▗▄▄▄ ${c4}▗▄▄▄▄ ▄▄▄▖
${c3} ▜███▙ ${c4}▜███▙ ▟███▛
${c3} ▜███▙ ${c4}▜███▙▟███▛
${c3} ▜███▙ ${c4}▜██████▛
${c3} ▟█████████████████▙ ${c4}▜████▛ ${c5}▟▙
${c3} ▟███████████████████▙ ${c4}▜███▙ ${c5}▟██▙
${c2} ▄▄▄▄▖ ${c4}▜███▙ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜██▛ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜▛ ${c5}▟███▛
${c2}▟███████████▛ ${c5}▟██████████▙
${c2}▜██████████▛ ${c5}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▟██▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▜███▙ ${c5}▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c6}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c6}▜████████████████▛
${c1} ▟██████▙ ${c6}▜███▙
${c1} ▟███▛▜███▙ ${c6}▜███▙
${c1} ▟███▛ ▜███▙ ${c6}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c6}▀▀▀▘
EOF
;;
"NixOS"*)
set_colors 4 6
set_colors 4 6 4 6 4 6
read -rd '' ascii_data <<'EOF'
${c1} ▗▄▄▄ ${c2}▗▄▄▄▄ ▄▄▄▖
${c1} ▜███▙ ${c2}▜███▙ ▟███▛
${c1} ▜███▙ ${c2}▜███▙▟███▛
${c1} ▜███▙ ${c2}▜██████▛
${c1} ▟█████████████████▙ ${c2}▜████▛ ${c1}▟▙
${c1} ▟███████████████████▙ ${c2}▜███▙ ${c1}▟██▙
${c2} ▄▄▄▄▖ ▜███▙ ${c1}▟███▛
${c2} ▟███▛ ▜██▛ ${c1}▟███▛
${c2} ▟███▛ ▜▛ ${c1}▟███▛
${c2}▟███████████▛ ${c1}▟██████████▙
${c2}▜██████████▛ ${c1}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ▟███▛
${c2} ▟███▛ ${c1}▟██▙ ▟███▛
${c2} ▟███▛ ${c1}▜███▙ ▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c2}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c2}▜████████████████▛
${c1} ▟██████▙ ${c2}▜███▙
${c1} ▟███▛▜███▙ ${c2}▜███▙
${c1} ▟███▛ ▜███▙ ${c2}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c2}▀▀▀▘
${c3} ▗▄▄▄ ${c4}▗▄▄▄▄ ▄▄▄▖
${c3} ▜███▙ ${c4}▜███▙ ▟███▛
${c3} ▜███▙ ${c4}▜███▙▟███▛
${c3} ▜███▙ ${c4}▜██████▛
${c3} ▟█████████████████▙ ${c4}▜████▛ ${c5}▟▙
${c3} ▟███████████████████▙ ${c4}▜███▙ ${c5}▟██▙
${c2} ▄▄▄▄▖ ${c4}▜███▙ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜██▛ ${c5}▟███▛
${c2} ▟███▛ ${c4}▜▛ ${c5}▟███▛
${c2}▟███████████▛ ${c5}▟██████████▙
${c2}▜██████████▛ ${c5}▟███████████▛
${c2} ▟███▛ ${c1}▟▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▟██▙ ${c5}▟███▛
${c2} ▟███▛ ${c1}▜███▙ ${c5}▝▀▀▀▀
${c2} ▜██▛ ${c1}▜███▙ ${c6}▜██████████████████▛
${c2} ▜▛ ${c1}▟████▙ ${c6}▜████████████████▛
${c1} ▟██████▙ ${c6}▜███▙
${c1} ▟███▛▜███▙ ${c6}▜███▙
${c1} ▟███▛ ▜███▙ ${c6}▜███▙
${c1} ▝▀▀▀ ▀▀▀▀▘ ${c6}▀▀▀▘
EOF
;;