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

ls: Start fix (see comment) color-term.sh GNU test #4867

Closed
wants to merge 25 commits into from

Conversation

alexkunde
Copy link
Contributor

@alexkunde alexkunde commented May 16, 2023

Fixes GNU test color-term.sh for LS (kind of)

Explaination

ls --color=always should honor the environment variables LS_COLOR and COLORTERM, if they are not set or empty it should honor the env variable TERM and use the default values for coloring. Additionally for TERM there is a terminal list in DIRCOLORS that needs to be checked and only if the value is in that list, it is allowed. Otherwise, even with --color=always no color should be set.
The rust version does not look for any env variables or check the terminal list in DIRCOLOR. This PR will fix it and implement the hirarchy as well as the list check.

I also added tests for the different scenarios. Beware, they need to be either run with cargo test -- --test-threads=1 or cargo nextest run otherwise all test will change the env variables at the same time and the tests will fail. fixed

Why is GNU test color-term.sh not green?

String Coloring in rust is done via LSCOLOR and nu-ansi-term and they do generally what is expected, but not 100% under the hood.

Test result:

FAIL: tests/ls/color-term
=========================

--- exp 2023-05-16 15:56:30.337121900 +0200
+++ out 2023-05-16 15:56:30.102644900 +0200
@@ -1,4 +1,4 @@
-^[[0m^[[01;32mexe^[[0m$
-^[[0m^[[01;32mexe^[[0m$
+^[[1;32mexe^[[0m$
+^[[1;32mexe^[[0m$
 exe$
 exe$
FAIL tests/ls/color-term.sh (exit status: 1)

As you can see all 4 tests are doing what they should be doing, but the rust version is using single-digit numbers for text while the gnu version uses double-digit numbers. Additionally the gnu version starts off by resetting any pre-styling, which the rust version does not.

As said it is working as expected but not technically. Hopefully this PR can still make it. For the next step changes on the underlying libraries are needed or an architectural decision to refrain from getting this test green.

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/tail-2/inotify-dir-recreate. tests/tail-2/inotify-dir-recreate is passing on 'main'. Maybe you have to rebase?

@alexkunde alexkunde changed the title LS: Start fix (see comment) color-term.sh GNU test draft: LS: Start fix (see comment) color-term.sh GNU test May 17, 2023
@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/tail-2/inotify-dir-recreate. tests/tail-2/inotify-dir-recreate is passing on 'main'. Maybe you have to rebase?

@cakebaker cakebaker marked this pull request as draft May 18, 2023 05:23
@cakebaker cakebaker changed the title draft: LS: Start fix (see comment) color-term.sh GNU test ls: Start fix (see comment) color-term.sh GNU test May 18, 2023
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!

@alexkunde alexkunde changed the title ls: Start fix (see comment) color-term.sh GNU test ls: Start fix (see comment) color-term.sh GNU test May 22, 2023
@alexkunde alexkunde changed the title ls: Start fix (see comment) color-term.sh GNU test ls: Start fix (see comment) color-term.sh GNU test May 22, 2023
@alexkunde alexkunde marked this pull request as ready for review May 22, 2023 12:39
@alexkunde
Copy link
Contributor Author

MacOS test is failing since macOS does not correctly support "LS_COLORS" env variable and the mac env var LSCOLORS is not supported by underlying crate -> sharkdp/lscolors#55

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!

Copy link
Member

@tertsdiepraam tertsdiepraam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting! I do think it's a bit of a shame that we have to parse the dircolors here. It'd be great if lscolors supported this.

/// # Returns
///
/// Boolean
fn check_env_variables_against_dircolors(dircolors: &str) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name could be more descriptive about what it's checking. If I understand correctly, it's checking that the terminal supports colors?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think the lscolors crate might be interested in a feature like this. It looks like something they might want to support.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tertsdiepraam LSCOLORS would need to hardcode the values since DIRCOLORS as in this repo does not exist. I can open an issue ofc.
Back to topic, we are not actually checking against is_terminal which is already provided in many places, LS is using the terminal list hardcoded in DIRCOLORS.h to check if the terminal provided via TERM environment variable is in that list. Sadly even the --color=always does this, so it basically works almost like --color=auto.
In addition to this check LS and rust LS are checking for terminal already.

I will think of a more descriptive name, I struggled because the whole topic is verymuch down the rabbit hole.

.map(|x| x.replace('*', ".*"))
.collect::<Vec<String>>();
let dircolors_set = RegexSet::new(terminals).unwrap();
dircolors_set.matches(term.as_str()).matched_any()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use a glob parser directly, without having to convert to regex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tertsdiepraam I will have a look and circle back

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the check to glob, it should be more consistent now

///
/// Boolean
fn check_env_variables_against_dircolors(dircolors: &str) -> bool {
let ls_colors = env::var("LS_COLORS").unwrap_or(String::new()).is_empty();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that the case where LS_COLORS is empty and where it is missing have the same effect?

Copy link
Contributor Author

@alexkunde alexkunde Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @tertsdiepraam , sorry for taking so long. I just did the test:
When LS_COLORS is set and empty or unset -> use TERM or COLORTERM
below only applies when above is true
when TERM is empty, unset or not in DIRCOLORS.h and COLORTERM is empty or unset
do not color even when --color=always
when COLORTERM has any value or TERM has a glob value fitting with the table in DIRCOLORS.h use internal default values for coloring

If you like I can put this in a shell file somewhere and make it a test. I would just need to know where a good space would be.

@tertsdiepraam
Copy link
Member

tertsdiepraam commented May 26, 2023

but not 100% under the hood.

I think this is OK as long as it looks the same. Maybe we should just patch the GNU tests to match our results in util/build-gnu.sh

@tertsdiepraam
Copy link
Member

Beware, they need to be either run with cargo test -- --test-threads=1 or cargo nextest run otherwise all test will change the env variables at the same time and the tests will fail.

This is a bit unfortunate and not really sustainable. Is there any way we can remove this restriction? Maybe we can make the function pure by giving it the env variables as arguments, which we can then test and we add the actual env::var calls only in the rest of the code:

// Use this for testing
fn check_variables_against_dircolors(dircolors: &str, ls_colors: Option<String>, colorterm: Option<String>, term: Option<String>) -> bool {
    ...
}

// Use this in `ls`
fn check_env_vars(dircolors: &str) {
     check_variables_against_dircolors(dircolors: &str, env::var("LS_COLORS"), ...)
}

@alexkunde
Copy link
Contributor Author

I already did some work on nu-ansi-term and lscolors has an open PR to support gnu legacy Mode aka double digit styles and reset before apply. Once it's done we will be able to use that feature here and do not need to change tests.

@tertsdiepraam
Copy link
Member

@sylvestre We can fix the tests with the nu-ansi-term patch later, but my original comments still hold.

@tertsdiepraam
Copy link
Member

Hey! Love this work, but I'm marking it as a draft, so that we don't accidentally merge the git dependency. Once lscolors has a new release, we can mark this ready again.

@tertsdiepraam tertsdiepraam marked this pull request as draft June 8, 2023 09:57
@alexkunde
Copy link
Contributor Author

thank you, it turned out that lscolors and nu-ansi-term were incredible helpful with the changes there and we got this going in a much better way than initially thought. I will update accordingly and ping you once it's in a better state.

@github-actions
Copy link

github-actions bot commented Jun 8, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!
GNU test failed: tests/tail-2/inotify-dir-recreate. tests/tail-2/inotify-dir-recreate is passing on 'main'. Maybe you have to rebase?

@alexkunde
Copy link
Contributor Author

alexkunde commented Jun 9, 2023

Beware, they need to be either run with cargo test -- --test-threads=1 or cargo nextest run otherwise all test will change the env variables at the same time and the tests will fail.

This is a bit unfortunate and not really sustainable. Is there any way we can remove this restriction? Maybe we can make the function pure by giving it the env variables as arguments, which we can then test and we add the actual env::var calls only in the rest of the code:

// Use this for testing
fn check_variables_against_dircolors(dircolors: &str, ls_colors: Option<String>, colorterm: Option<String>, term: Option<String>) -> bool {
    ...
}

// Use this in `ls`
fn check_env_vars(dircolors: &str) {
     check_variables_against_dircolors(dircolors: &str, env::var("LS_COLORS"), ...)
}

Hi, I updated the function to take in env variables as results, so the actual unpacking etc happens inside the function and is tested as well.
This also means cargo test is now usable again.

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!
GNU test failed: tests/tail-2/inotify-dir-recreate. tests/tail-2/inotify-dir-recreate is passing on 'main'. Maybe you have to rebase?

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/multihardlink is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!
Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!

@sylvestre
Copy link
Contributor

Sweet:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/multihardlink is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/ls/color-term is no longer failing!
Congrats! The gnu test tests/ls/multihardlink is no longer failing!
Congrats! The gnu test tests/ls/root-rel-symlink-color is no longer failing!
Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!

@sylvestre
Copy link
Contributor

sorry we didn't merge this yet. I tried to rebase it, let's see if it works

@sylvestre
Copy link
Contributor

@alexkunde sorry but do you have plans to finish it?

@sylvestre
Copy link
Contributor

no activity for a while, closing

@sylvestre sylvestre closed this Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants