Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use font dimming to communicate modification/creation time #486

Closed
cohml opened this issue Oct 4, 2023 · 8 comments · Fixed by #628
Closed

feat: Use font dimming to communicate modification/creation time #486

cohml opened this issue Oct 4, 2023 · 8 comments · Fixed by #628

Comments

@cohml
Copy link

cohml commented Oct 4, 2023

Porting ogham/exa#1222. Original text below...


The title is probably a terrible description of the idea, but best I could do in limited space. Let me try to unpack it:

What I'm referring to is exactly what the project k does, where it calls this feature "rot" (gross to me, but I digress). Here is a visual example.

In prose: The font color of the date/time beside each file - be it creation, modification, or whatever - should be dimmer for dates that are older, and brighter for dates that are newer. This would give an immediate visual indication of which files are more important/relevant for the user at the present time.

I could see the dimming function coming in two modes, either of which would be very useful:

  1. absolute (e.g., if all files displayed were modified either today or yesterday, all should be bright; only files modified a while ago should be dim)
  2. relative to only the files displayed (e.g., regardless of absolute distance into the past, the least-recently-modified file would be dim, and the most-recently-modified file would be bright)

Ideally, the ability to toggle between these modes, or at least to set your preferred mode via an environment variable, would be super awesome. Not sure how feasible that would be to implement though.

For terminals which support the 256-color scheme, or even more, this should be doable regardless of hue, so not just black/white/gray.

Project k is written in shell code whereas exa is in Rust. But hopefully the former could still provide some useful ideas for implementation.

Anyway, curious to hear your thoughts of usability and feasibility!

@cafkafk
Copy link
Member

cafkafk commented Oct 4, 2023

Sounds cool, if anyone would want to make this I'd think it would be neat (let's not call it rot thou).

@aashirbadb
Copy link

Hi, can I work on this?

@cafkafk
Copy link
Member

cafkafk commented Oct 6, 2023

Hi, can I work on this?

go ahead!

@cgorski
Copy link
Contributor

cgorski commented Oct 7, 2023

I happened to be playing with this idea as well. One possible solution is to convert any color to LAB which allows luminance adjustments independent of color, change the luminance, and convert back to RGB:

// use palette crate

use palette::{Srgb, Lab, FromColor, IntoColor};

/// Adjust the luminance of an RGB triplet to the specified value.
///
/// `r`, `g`, `b` are the original RGB values.
/// `desired_luminance` should be between 0.0 and 1.0.
fn adjust_luminance(r: u8, g: u8, b: u8, desired_luminance: f32) -> (u8, u8, u8) {
    let color = Srgb::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0).into_linear();
    let lab: Lab = color.into_color();
    
    let adjusted_lab = Lab {
        l: desired_luminance * 100.0, // Lab L value is between 0 and 100
        a: lab.a,
        b: lab.b,
    };
    
    let adjusted_rgb: Srgb<f32> = Srgb::from_color(adjusted_lab);
    (
        (adjusted_rgb.red * 255.0).round() as u8,
        (adjusted_rgb.green * 255.0).round() as u8,
        (adjusted_rgb.blue * 255.0).round() as u8,
    )
}

fn main() {
    let (r, g, b) = (255, 127, 0); // Example RGB value
    let desired_luminance = 0.5;
    
    let (adjusted_r, adjusted_g, adjusted_b) = adjust_luminance(r, g, b, desired_luminance);
    println!("Adjusted RGB({}, {}, {}) with luminance {}", adjusted_r, adjusted_g, adjusted_b, desired_luminance);
}

Then an approach might be to map the oldest file timestamp and newest timestamp in a set to 0.0 and 1.0, call this relative_time, to luminance, say to 0.2 to 1.0 (0.2 as lowest level of brightness we might use). We could use an exponential function so that timestamps closer to the newest timestamp will have the biggest differences in brightness.

Here’s one such way

// use palette crate

use palette::{Srgb, Lab, FromColor, IntoColor};

fn luminance_from_relative_time(relative_time: f64) -> f64 {
    0.2 + 0.8 * (-5.0 * (1.0 - relative_time)).exp()
}

fn adjust_rgb_luminance(r: u8, g: u8, b: u8, relative_time: f64) -> (u8, u8, u8) {
    let color = Srgb::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0).into_linear();
    let lab: Lab = color.into_color();
    
    let new_luminance = luminance_from_relative_time(relative_time) * 100.0; // Convert to Lab scale
    
    let adjusted_lab = Lab {
        l: new_luminance as f32,
        a: lab.a,
        b: lab.b,
    };
    
    let adjusted_rgb: Srgb<f32> = Srgb::from_color(adjusted_lab);
    (
        (adjusted_rgb.red * 255.0).round() as u8,
        (adjusted_rgb.green * 255.0).round() as u8,
        (adjusted_rgb.blue * 255.0).round() as u8,
    )
}

fn main() {
    let (r, g, b) = (255, 127, 0); // Example RGB value
    let relative_time = 0.5; // Example relative time
    
    let (adjusted_r, adjusted_g, adjusted_b) = adjust_rgb_luminance(r, g, b, relative_time);
    println!("Original RGB({}, {}, {})", r, g, b);
    println!("Adjusted RGB({}, {}, {}) with relative time {}", adjusted_r, adjusted_g, adjusted_b, relative_time);
}

@cgorski
Copy link
Contributor

cgorski commented Oct 7, 2023

If using the equation above here is the luminance vs relative time graph:

IMG_0442

May need to adjust the parameters according to what seems most aesthetically pleasing and practical, eg a steeper/flatter slope.

@aashirbadb
Copy link

Using adjust_rgb_luminance, I was able to get this(Date created is the default color). I'll experiment more with different equations/color spaces once I'm done adding relative time(this uses current_time - 1year).

image

@cgorski
Copy link
Contributor

cgorski commented Oct 7, 2023

Another possibility is relative_time = (file_mod_time - oldest_file_mod_time) / (newest_file_mod_time - oldest_file_mod_time)

With that the luminance will adjust according to the relative timespan of the displayed files.

Edit: reread your comment to see you mentioned that re: relative time

@RaffaeleBianc0
Copy link

+1 on this!
I find it very useful to have the "Size" column using different colours to highlight big files.
I would find it useful to have the same behaviour also on the "Date" column.
(and I love the "rot" name for this btw 🤣)

cafkafk added a commit that referenced this issue Nov 8, 2023
This is based on a series of commits done by aashirabadb in #526.

This introduces the `--color-scale` flag both for file age and size, as
well as `--color-scale-mode` which allows "fixed" and gradient".

The reason for reapplying from the diff of the PR instead of the patch
is that the commit history was messy, and introduced "breaking changes"
that were only locally breaking to the PR, that is, not the users.

Further, the PR had seemingly gone stale, and the rather long and
complicated commit history interwoven with merges made it seem more
efficient to just work from scratch.

Again, the work here is done by aashirbadb, my contribution is just
ensuring the quality of the code they've written.

Co-authored-by: aashirbadb <[email protected]>
Signed-off-by: Christina Sørensen <[email protected]>

Refs: #486
cafkafk added a commit that referenced this issue Nov 8, 2023
This is based on a series of commits done by aashirabadb in #526.

This introduces the `--color-scale` flag both for file age and size, as
well as `--color-scale-mode` which allows "fixed" and gradient".

The reason for reapplying from the diff of the PR instead of the patch
is that the commit history was messy, and introduced "breaking changes"
that were only locally breaking to the PR, that is, not the users.

Further, the PR had seemingly gone stale, and the rather long and
complicated commit history interwoven with merges made it seem more
efficient to just work from scratch.

Again, the work here is done by aashirbadb, my contribution is just
ensuring the quality of the code they've written.

Co-authored-by: aashirbadb <[email protected]>
Signed-off-by: Christina Sørensen <[email protected]>

Refs: #486
MartinFillon pushed a commit that referenced this issue Nov 11, 2023
This is based on a series of commits done by aashirabadb in #526.

This introduces the `--color-scale` flag both for file age and size, as
well as `--color-scale-mode` which allows "fixed" and gradient".

The reason for reapplying from the diff of the PR instead of the patch
is that the commit history was messy, and introduced "breaking changes"
that were only locally breaking to the PR, that is, not the users.

Further, the PR had seemingly gone stale, and the rather long and
complicated commit history interwoven with merges made it seem more
efficient to just work from scratch.

Again, the work here is done by aashirbadb, my contribution is just
ensuring the quality of the code they've written.

Co-authored-by: aashirbadb <[email protected]>
Signed-off-by: Christina Sørensen <[email protected]>

Refs: #486
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants