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

--color does not work under Emacs #182

Closed
xuchunyang opened this issue Oct 15, 2016 · 28 comments · Fixed by #240
Closed

--color does not work under Emacs #182

xuchunyang opened this issue Oct 15, 2016 · 28 comments · Fixed by #240
Labels
bug A bug.

Comments

@xuchunyang
Copy link

I'm using rg 0.2.1 and Emacs 25. It looks like --color doesn't have effect under Emacs, while other tools such as grep works.

  • M-! echo hello | grep --color=always hello gives [01;31m�[Khello�[m�[K
  • M-! echo hello | rg --color=always hello gives hello (where is the escape code?)

see also emacs-helm/helm#1624 (comment)

@BurntSushi
Copy link
Owner

Tracking down why colors aren't working has historically been a very challenging task because a lot of it is dependent on your environment. For example:

$ TERM=foobar rg --color=always PATTERN --debug

Colors no longer work. The --debug flag might show a lot of other junk, but in my case, I do see this:

DEBUG:rg::out: error loading terminfo for coloring: could not find a terminfo entry for this terminal

If I try this with GNU grep, colors still work, even if my TERM setting is nonsensical:

TERM=foobar grep --color=always PATTERN *

So this could be one possible explanation. There may be other problems. For example, if TERM is unset:

$ unset TERM
$ rg --color=always PATTERN --debug

In the debug output, I see:

DEBUG:rg::out: error loading terminfo for coloring: TERM environment variable unset, unable to detect a terminal

Once again, GNU grep still works. It seems GNU grep will fall back to some default settings that ripgrep doesn't do, and maybe we should do that. In the mean time, my strong suspicion is that something about your environment isn't configured correctly and GNU grep is bailing you out.

So, can you run rg with --debug and see if you can find the relevant error message? If not, you can just post the entire output. If that doesn't turn up anything, what is the value of TERM when rg is run? What about TERMINFO?

Thanks!

@xuchunyang
Copy link
Author

M-! echo hello | rg --debug --color=always hello returns

DEBUG:grep::search: regex ast:
Literal {
    chars: [
        'h',
        'e',
        'l',
        'l',
        'o'
    ],
    casei: false
}
DEBUG:grep::literals: literal prefixes detected: Literals { lits: [Complete(hello)], limit_size: 250, limit_class: 10 }
DEBUG:rg::out: environment doesn't support coloring
hello

M-! echo $TERM returns dumb and TERMINFO is empty, probably not set.

@BurntSushi
Copy link
Owner

Having TERMINFO unset is OK. ripgrep will look in standard locations for your terminfo database.

Indeed, if I set TERM=dumb, then I also get the same error message as you.

So... It sounds like you need to change your TERM to a setting that supports colors. There's more info on the dumb setting here and here. Running infocmp dumb shows that a dumb terminal has very limited capabilities. If Emacs does indeed support colors, then it sounds like you'll need to change your TERM environment variable to something else.

@thierryvolpiatto
Copy link

Actually colors are working fine not only for GNU/grep, but also ag, pt, ack-grep and git-grep, so perhaps the question is: What is different in ripgrep than on e.g ag that make ripgrep failing with a DUMB terminal ?

@BurntSushi
Copy link
Owner

At least GNU grep hard codes ANSI color escape sequences and AFAIK doesn't actually respect the TERMINFO database. e.g.,

static const char *selected_match_color = "01;31";  /* bold red */

ripgrep isn't failing as far as I can see, it's simply respecting what the environment is saying, while all of the other tools aren't.

What is the correct behavior here? If TERM=dumb is set and --color=always is set, then how does ripgrep know which TERM settings to use? Should it forcefully pick a TERM other than dumb? Which one?

@BurntSushi
Copy link
Owner

@ticki You seem to know a thing or two about this sort of thing. Can you make sense of this? I notice in your termion library, you don't read from the TERMINFO database and hardcode escape sequences. Does this work correctly across all terminals? (I suppose you're in good company, since GNU grep does the same.) If so, what's the purpose of the TERMINFO database in the first place? For things more advanced than colors?

@thierryvolpiatto
Copy link

Andrew Gallant [email protected] writes:

At least GNU grep hard codes ANSI color escape sequences and AFAIK doesn't actually respect the TERMINFO database. e.g.,

static const char selected_match_color = "01;31"; / bold red */

ripgrep isn't failing as far as I can see, it's simply respecting what the environment is saying, while all of the other tools aren't.

What is the correct behavior here? If TERM=dumb is set and
--color=always is set, then how does ripgrep know which TERM settings
to use? Should it forcefully pick a TERM other than dumb? Which one?

Ok, just found that if I set TERM to eterm-color colors with ripgrep are
working, so perhaps it is the one to use when TERM=dumb ?

BTW ripgrep is using a basic red color, how do we configure which color
to use ?
Does ripgrep obey to GREP_COLORS env var ? Seems no.
Does it have a config file where we can set this ?

Thierry

@BurntSushi
Copy link
Owner

Ok, just found that if I set TERM to eterm-color colors with ripgrep are
working, so perhaps it is the one to use when TERM=dumb ?

"it works for me" isn't really a strong reason to assume "it always works," unfortunately.

BTW ripgrep is using a basic red color, how do we configure which color
to use ?
Does ripgrep obey to GREP_COLORS env var ? Seems no.
Does it have a config file where we can set this ?

Colors aren't yet configurable. See: #51

@BurntSushi
Copy link
Owner

From reading the source of termion, I wonder if it'd be better to stop using the term crate, switch to termion for POSIX compatible stuff and handroll Windows support. This would mean not supporting the TERMINFO database, and I'm not sure what the implications of that are. (But it would also mean that colors would work independently of a TERMINFO database.)

@BurntSushi
Copy link
Owner

@thierryvolpiatto @xuchunyang I think the bottom line here is that while ripgrep is technically respecting the letter of the law, it doesn't actually match up with user expectations and that's bad. That means I agree we should do something here, but the right answer might take a bit of time to happen. For now, I'd request setting TERM to something that makes ripgrep work as a temporary work-around. Hopefully that's feasible to do.

@BurntSushi BurntSushi added the bug A bug. label Oct 15, 2016
@thierryvolpiatto
Copy link

Andrew Gallant [email protected] writes:

@thierryvolpiatto @xuchunyang I think the bottom line here is that
while ripgrep is technically respecting the letter of the law, it
doesn't actually match up with user expectations and that's bad. That
means I agree we should do something here, but the right answer might
take a bit of time to happen.

There is no hurry, thanks for all your explanations and sorry to not be
able to help on this, my knowledge about all this is limited.

For now, I'd request setting TERM to something that makes ripgrep work
as a temporary work-around. Hopefully that's feasible to do.

Ok, we will use TERM=eterm-color as a workaround for now.

Thanks again for your help on this.

Thierry

@ticki
Copy link

ticki commented Oct 16, 2016

@BurntSushi So TERMINFO is mostly for detecting compatibility, but is only really relevant for very old terminals. Termion implements escapes which are supported by virtually every VTE used today (most of it is straight out of the ANSI standards, some are ones introduced by xterm). For the Windows stuff: I'm not that familiar with the Windows API, but I'm more than willing to accept a PR adding Windows support to Termion (i.e. adding the winapi calls to the formatter, I guess).

@BurntSushi
Copy link
Owner

@ticki Got ya. Given that every other tool in this space seems to not care about TERMINFO, it seems OK for ripgrep to do the same. With that in mind, I'd like to switch Unix handling to using termion, which I think should be straight-forward.

I would definitely recommend treading carefully with Windows. For Windows, you need to make synchronous API calls to the console you're writing to, which means that you can't really implement Windows support in some arbitrary formatter that can write to anything. For ripgrep, this is particularly bad because we want to write matches to an in memory buffer and only actually print them later. There are a couple ways of doing this, including writing an ANSI interpreter, but I opted for something simpler but just as hacky: https://github.com/BurntSushi/ripgrep/blob/master/src/terminal_win.rs

What I'm saying is: as a future user of termion, I don't expect you to support Windows for this. I expect to be subjected to grueling pain. :-)

@ticki
Copy link

ticki commented Oct 16, 2016

@BurntSushi I agree with that. It would definitely be incredibly hacky to add windows support.

@kaushalmodi
Copy link
Contributor

I'm wondering if resolving this issue would also solve that other issue where ripgrep is inserting strange escape characters to the colored text.

@BurntSushi
Copy link
Owner

@kaushalmodi I bet it will, considering the new approach should be isomorphic to what GNU grep does today, which doesn't suffer from the same issue (I think).

BurntSushi added a commit that referenced this issue Nov 20, 2016
This commit completely guts all of the color handling code and replaces
most of it with two new crates: wincolor and termcolor. wincolor
provides a simple API to coloring using the Windows console and
termcolor provides a platform independent coloring API tuned for
multithreaded command line programs. This required a lot more
flexibility than what the `term` crate provided, so it was dropped.
We instead switch to writing ANSI escape sequences directly and ignore
the TERMINFO database.

In addition to fixing several bugs, this commit also permits end users
to customize colors to a certain extent. For example, this command will
set the match color to magenta and the line number background to yellow:

    rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo

For tty handling, we've adopted a hack from `git` to do tty detection in
MSYS/mintty terminals. As a result, ripgrep should get both color
detection and piping correct on Windows regardless of which terminal you
use.

Finally, switch to line buffering. Performance doesn't seem to be
impacted and it's an otherwise more user friendly option.

Fixes #37, Fixes #51, Fixes #94, Fixes #117, Fixes #182, Fixes #231
@thierryvolpiatto
Copy link

Still not working in emacs with helm and from any emacs terminal (term or shell-mode, eshell) with rg version 0.3.2. However it is working fine with 0.2.3 and the workaround we found:

TERM=eterm-color rg --color=always --smart-case --no-heading --line-number %s %s %s

Here the command line used with 0.3.2 (not highlighting):

rg --color=always --smart-case --no-heading --line-number %s %s %s

capture d ecran_2017-01-13_18-03-37

Same result with the workaround:

TERM=eterm-color rg --color=always --smart-case --no-heading --line-number %s %s %s

Now with rg version 0.2.3 and this command line (now matches are highlighted as expected):

TERM=eterm-color rg --color=always --smart-case --no-heading --line-number %s %s %s

capture d ecran_2017-01-13_18-08-00

@BurntSushi
Copy link
Owner

@thierryvolpiatto Thanks for taking the time to try and confirm the fix! Sorry it isn't working right for you. It's hard for me to understand your comment, but you're saying you can't get ripgrep 0.3.2 to output colors at all in emacs, regardless of any workaround? Can you try --color ansi instead of --color always? Also, what operation system are you on?

I honestly have no clue what's going on. If you have --color always on non-Windows platforms, then it should always emit ANSI escape sequences now. On Windows however, --color always will always attempt to use the native console API for colors, which might not work in emacs. Instead, --color ansi will force the issue for ANSI escapes. Alternatively, --color auto with TERM=eterm-color should also work.

@thierryvolpiatto
Copy link

thierryvolpiatto commented Jan 13, 2017 via email

@BurntSushi
Copy link
Owner

@thierryvolpiatto Can you try to reproduce the issue outside of emacs? Basically, what you're reporting doesn't make any sense to me. :-)

@thierryvolpiatto
Copy link

thierryvolpiatto commented Jan 13, 2017 via email

@BurntSushi
Copy link
Owner

@thierryvolpiatto Sorry, I think I understand what you're saying. What I meant was, I don't understand how what you're reporting is actually possible. If you say --color ansi, then ANSI escape sequences should be emitted no questions asked.

I think the only thing I can do at this point is try to reproducing it, but I've never used emacs before. (I'm a vim user.) How hard would it be to explain how to reproduce your issue to someone who has never used emacs before?

@thierryvolpiatto
Copy link

thierryvolpiatto commented Jan 13, 2017 via email

@BurntSushi
Copy link
Owner

Interesting! That did the trick. Something is definitely a little weird, however, I am seeing that the match text is at least bolded, but it's not colored.

@BurntSushi
Copy link
Owner

Errrmm, but I am using latest master which has some fixes related to that, so that might not be the case for 0.3.2.

Anyway, I can reproduce the fundamental problem, so hopefully I can fix this. Thank you. :-)

@BurntSushi
Copy link
Owner

Ah! I figured it out. It looks like the emacs terminal has very limited support for ANSI escape sequences, and doesn't actually work with constructs like \x1B[38;5;4m to set the text to blue (for example). Instead, it needs \x1B[34m. I think I just need to straighten this out and we should be good.

BurntSushi added a commit that referenced this issue Jan 14, 2017
In Emacs, its terminal apparently doesn't support "extended" sets of
foreground/background colors. Unless we need to set an "intense" color,
we should instead use one of the eight basic color codes.

Also, remove the "intense" setting from the default set of colors. It
doesn't do much anyway and enables the default color settings to work
in Emacs out of the box.

Fixes #182 (again)
@BurntSushi
Copy link
Owner

All right, this should finally be fixed in master. I hope to get a release out soon.

@thierryvolpiatto
Copy link

thierryvolpiatto commented Jan 14, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants