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 doesn't work in windows mintty (git bash) #117

Closed
auxym opened this issue Sep 27, 2016 · 21 comments · Fixed by #240
Closed

Color doesn't work in windows mintty (git bash) #117

auxym opened this issue Sep 27, 2016 · 21 comments · Fixed by #240
Labels
bug A bug.

Comments

@auxym
Copy link

auxym commented Sep 27, 2016

I can't get rg to output color in mintty, ie the default term that comes with git for windows and MSYS2. Tried --color always and -p, to no avail. Color works fine (by default) in standard cmd.exe.

Color (--color=auto) works with standard grep in mintty, or at least the grep build that comes with git for windows.

@BurntSushi
Copy link
Owner

Do you know if mintty uses the Windows console for coloring? Or does it use something else? I wonder if ripgrep is supposed to be using ANSI escape sequences here and is instead trying to use the Windows console.

@auxym
Copy link
Author

auxym commented Sep 27, 2016

Here is the raw output from echo "AAAaaa" | grep --color=always aa > grepcolor.txt in mintty:

b'AAA\x1b[01;31m\x1b[Kaa\x1b[m\x1b[Ka\n'

I tried the same exercise with rg, but couldn't get it to output the escape codes, both in mintty and cmd.exe. It looks like rg doesn't detect terminal output and ignores the color=always options.

@BurntSushi
Copy link
Owner

It does detect terminal output, just apparently not on Windows. :-) I think the issue is that I baked an assumption into ripgrep that if it's on Windows, then it should do coloring with the Windows console. It looks like in the case of mintty, it should use ANSI escape codes? Is that right?

For cmd.exe, I don't think it should be printing escape codes.

cc @retep998 Would you be able to add any insight here? Thanks so much. :-)

@retep998
Copy link

retep998 commented Sep 27, 2016

@BurntSushi Basically with mintty you have a pipe instead of a console. Because of this there is no API you can call to determine whether a pipe is actually a terminal that accepts ansi escape codes. The best you can do is that if you're not talking to a console, then check whether TERM is set, if it is then you're probably in a terminal emulator (or being redirected to a file while inside a terminal emulator).

Conhost (which is what cmd.exe uses) doesn't support escape codes in older Windows, and in Windows 10 it only supports them if a certain mode is enabled.

@leafgarland
Copy link
Contributor

Perhaps the --color flag could support extra options such as ansi and wincon, which would behave the same as always but also force one or the other color output method. There are enough command line options in Windows that it seems unlikely a cmdline tool can guess the exact requirements (e.g. Windows 10 can support ansi, or when using something like Maximus5/ConEmu).

@BurntSushi
Copy link
Owner

@leafgarland That's plausible. Good idea.

@retep998
Copy link

I don't think you really need the user's help deciding which to use. If you're in a Windows console, then the Windows console API will work all the time. If you're not in a Windows console, then the Windows console API will work none of time and the only other option is ansi escape codes. So I'd probably enable color by default in the Windows console, and elsewhere support color using ansi escape codes only if enabled via --color=always.

@BurntSushi BurntSushi added the bug A bug. label Sep 29, 2016
@thierryvolpiatto
Copy link

We have the same problem in emacs where ripgrep is apparently not recognizing pseudo emacs terminal (pty) as a terminal, see emacs-helm/helm#1624.

@BurntSushi
Copy link
Owner

BurntSushi commented Oct 15, 2016

@thierryvolpiatto Is that on Windows? If not, it sounds like an entirely distinct issue.

@thierryvolpiatto
Copy link

Andrew Gallant notifications@github.com writes:

@thierryvolpiatto Is that on Windows?

No, on GNU/Linux.

If not, it sounds like an entire distinct issue.

Ok, should I open an other issue ?

Thierry

@BurntSushi
Copy link
Owner

@thierryvolpiatto I think #182 might be relevant.

@thierryvolpiatto
Copy link

Ok, yes I just see @chunyang have opened another issue, thanks.

@BurntSushi
Copy link
Owner

@retep998 I'm in the process of fixing this issue, and it actually looks like I can successfully get a handle to the Windows console when using mintty. Namely, no error occurs. Actually using the console has no effect, so it appears that we do indeed need a way to force ANSI escape sequences.

@retep998
Copy link

@BurntSushi GetStdHandle succeeding does not necessarily mean it is a Windows console. You have to call GetConsoleMode on that handle to determine whether it is actually a Windows console. If GetConsoleMode succeeds, then always use the console API. If GetConsoleMode fails, then you might be able to use ANSI escape codes, or you might be redirected to a file.

@BurntSushi
Copy link
Owner

@retep998 This is the code I'm using to get a console, and it doesn't appear to return an error in mintty:

    pub fn new() -> io::Result<Console> {
        let name = b"CONOUT$\0";
        let handle = unsafe {
            kernel32::CreateFileA(
                name.as_ptr() as *const i8,
                winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                winapi::FILE_SHARE_WRITE,
                ptr::null_mut(),
                winapi::OPEN_EXISTING,
                0,
                ptr::null_mut(),
            )
        };
        if handle == winapi::INVALID_HANDLE_VALUE {
            return Err(io::Error::last_os_error());
        }
        let mut info = unsafe { mem::zeroed() };
        let res = unsafe {
            kernel32::GetConsoleScreenBufferInfo(handle, &mut info)
        };
        if res == 0 {
            return Err(io::Error::last_os_error());
        }
        let attr = TextAttributes::from_word(info.wAttributes);
        Ok(Console {
            handle: handle,
            start_attr: attr,
            cur_attr: attr,
        })
    }

So I'm not using GetConsoleMode but I am using GetConsoleScreenBufferInfo. Should that call fail if there's no console available? The docs don't seem to say, but do seem to imply that it at least can fail.

@BurntSushi
Copy link
Owner

Hmm, I guess the difference here is that in that code above, I am opening CONOUT$, where as I do believe it fails if I do it on, say, stdout.

@retep998
Copy link

@BurntSushi Getting CONOUT$ is usually the wrong thing to do, because it ignores what stdout is set to, completely bypassing any redirection, and just gets whatever the active framebuffer is. Stick with GetStdHandle as the way to obtain the handle.

@BurntSushi
Copy link
Owner

@retep998 Ah I see now, OK that works! Thanks! My only problem now is figuring out how to detect whether stdout is tty or not inside of mintty. From searching, it seems like the problem is basically unsolveable, although I will note that grep from cygwin seems to get it right. git itself seems to have hacked around it and the mintty project doesn't have a good answer either.

sigh

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
@BurntSushi
Copy link
Owner

For those following this issue but not #94, this will be fixed in the next ripgrep release!

@lilianmoraru
Copy link
Contributor

Colors stopped working in one of the releases, on an ARM target I tested ripgrep on.
I'll test again and see if this fixed the issue.

@lilianmoraru
Copy link
Contributor

Yey, colors work again on that ARM target.

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.

6 participants