Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,22 @@ animfetch # interactive: animfetch owns the prompt
scroll, then detaches and paints them while your own shell runs underneath with
its history, completion and aliases intact. Undo with `animfetch --unpin`.

A terminal holds one pin. A bare `animfetch --pin`, which is what a shell's
startup file runs, leaves a pin that is already there alone, so nested shells
stay quiet. `--pin` with settings (`animfetch --pin --no-color`) replaces it,
so a line you type takes effect at once. A run with `--save` does not: it
writes the settings, says so, and leaves this terminal as it is; terminals you
open after that start with them.

```sh
animfetch -a cat-tail # different animation, this run only
animfetch --style quad # half (default), quad, ramp, or raw
animfetch --width 40 # cap the art width (0 fills the screen)
animfetch --height 12 # both caps apply, aspect ratio is kept
animfetch --fps 20
animfetch --play -s 1.5 # shorter intro
animfetch --no-color
animfetch --no-color # everything in shades of grey
animfetch --def-color # the default colours, from your theme: undoes --no-color
```

Piping the output, or `NO_COLOR=1`, drops to the static path automatically.
Expand Down Expand Up @@ -180,6 +188,7 @@ and another along its bottom, drawn from PNG line art:

```sh
animfetch --pin --border-left 00 --border-bottom 03
animfetch --pin --lb 00 --db 03 # the same, shorter: --lb left, --db down
animfetch --list-borders # what is built in, and your own
animfetch --pin --no-border # for this run only
```
Expand All @@ -205,9 +214,10 @@ pictures even where they are not detected.
A bottom image is stored upright, hilt at the top, and is turned a quarter
clockwise so it lies along the bottom. The art and the info give up the room a
border takes, and it is left out on a terminal under 60 columns and when the
output is not a terminal. `--no-color` and `NO_COLOR` do not remove the
pictures, which have no colour to turn off; they do remove the `"cells"`
drawing, which is coloured text.
output is not a terminal. `--no-color` draws the pictures in grey, like the
rest. `NO_COLOR` and `color = false` leave the pictures as they are, which have
no colour to turn off, and remove the `"cells"` drawing, which is coloured
text.

Put your own PNGs in `~/.config/animfetch/border/left_border/` and
`.../bottom_border/`; a file of yours shadows a built-in of the same name. They
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
6 changes: 4 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ fn main() {
/// Generates the `BORDERS` table from `assets/border/`.
///
/// Loose PNGs are left borders; `left_border/` and `bottom_border/` say so
/// outright, and win on a name clash. Anything that is not a PNG is left out
/// with a warning, since the decoder reads PNGs and nothing else.
/// outright, and win on a name clash. `down_border/` is the same folder as
/// `bottom_border/` under the name the `--db` flag uses. Anything that is not a
/// PNG is left out with a warning, since the decoder reads PNGs and nothing else.
fn borders() {
use std::collections::BTreeMap;

Expand All @@ -68,6 +69,7 @@ fn borders() {
scan(root, "left", &mut found);
scan(&root.join("left_border"), "left", &mut found);
scan(&root.join("bottom_border"), "bottom", &mut found);
scan(&root.join("down_border"), "bottom", &mut found);
}

let mut out = String::from(
Expand Down
6 changes: 6 additions & 0 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ gap = 4
# terminal or NO_COLOR is set.
color = true

# Draw in shades of grey: colour is sent, with no hue in it, so the light and
# dark of the art and the text stay. The same as --no-color; --def-color puts
# the default colours back. `color = false` is the other way to have no colour:
# no colour codes at all, so the terminal's own.
gray = false

# Rows in the info pane, in order. Leave this out to get the rows that suit
# `info_style`; set it and your list wins, whichever style is chosen.
# Available: os, host, kernel, uptime, packages, shell, shell_path, wm,
Expand Down
32 changes: 32 additions & 0 deletions src/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,15 @@ pub struct Animation {
}

impl Animation {
/// Take the colour out of every frame, once, rather than on every paint.
pub fn grayscale(&mut self) {
for frame in &mut self.frames {
for (_, rgb) in &mut frame.art {
*rgb = rgb.map(Rgb::gray);
}
}
}

fn from_texts(texts: impl IntoIterator<Item = String>) -> Option<Self> {
let frames: Vec<Frame> = texts.into_iter().map(|t| Frame::parse(&t)).collect();
if frames.is_empty() {
Expand Down Expand Up @@ -787,4 +796,27 @@ mod tests {
assert_eq!(err.kind(), io::ErrorKind::NotFound);
assert!(err.to_string().contains(missing), "{err}");
}

#[test]
fn grayscale_takes_the_hue_out_of_every_cell_and_keeps_the_rest() {
let mut anim = Animation::from_texts([
"\x1b[38;2;255;0;0m#\x1b[0m.\n".to_string(),
"\x1b[38;2;0;200;90m#\x1b[0m.\n".to_string(),
])
.unwrap();
let before: Vec<char> = anim.frames[0].art.iter().map(|(c, _)| *c).collect();

anim.grayscale();

for frame in &anim.frames {
for (_, rgb) in &frame.art {
if let Some(Rgb(r, g, b)) = rgb {
assert!(r == g && g == b, "{rgb:?} kept its hue");
}
}
assert!(frame.art.iter().any(|(_, rgb)| rgb.is_some()), "lost the colour cells");
}
let after: Vec<char> = anim.frames[0].art.iter().map(|(c, _)| *c).collect();
assert_eq!(before, after);
}
}
25 changes: 25 additions & 0 deletions src/border/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ impl Bitmap {
]
}

/// The same picture with the hue taken out of every pixel. Transparency is
/// left as it was.
pub fn grayscale(mut self) -> Self {
for px in self.rgba.as_chunks_mut::<4>().0 {
let crate::color::Rgb(y, _, _) = crate::color::Rgb(px[0], px[1], px[2]).gray();
px[..3].fill(y);
}
self
}

/// A quarter turn clockwise: what was the top is now the right.
pub fn rotated_cw(&self) -> Self {
let mut out = Self::blank(self.h, self.w);
Expand Down Expand Up @@ -485,4 +495,19 @@ mod tests {
assert_eq!(canvas.pixel(1, 1), [0, 0, 0, 0]);
assert_eq!(canvas.rgba.len(), 4 * 4 * 4, "nothing grew");
}

#[test]
fn grayscale_drops_the_hue_and_leaves_transparency_alone() {
let b = Bitmap {
w: 2,
h: 1,
rgba: vec![255, 0, 0, 255, 10, 200, 30, 0],
}
.grayscale();

for px in b.rgba.as_chunks::<4>().0 {
assert!(px[0] == px[1] && px[1] == px[2], "{px:?}");
}
assert_eq!((b.rgba[3], b.rgba[7]), (255, 0));
}
}
6 changes: 4 additions & 2 deletions src/border/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,10 @@ impl Borders {
// pictures and was not told to use text. A name that is wrong is still
// wrong, so it is still reported.
//
// Colour is not asked of a picture: `--no-color` is about the text.
// Colour is not asked of a picture: `color = false` is about the text.
// Only the text drawing of a border is a thing to colour, and without
// colour it is not drawn.
// colour it is not drawn. Grey is a colour setting of its own, and the
// pictures are taken to grey with the rest.
let mode = if to_terminal {
Mode::resolve(cfg.border_render, images && kitty::supported())
.filter(|m| *m == Mode::Image || cfg.color)
Expand All @@ -242,6 +243,7 @@ impl Borders {
let bitmap = Bitmap::decode(&bytes).map_err(|e| format!("border {spec:?}: {e}"))?;
bitmap
.trimmed()
.map(|b| if cfg.gray { b.grayscale() } else { b })
.map(Some)
.ok_or_else(|| format!("border {spec:?} has nothing visible in it"))
};
Expand Down
Loading
Loading