Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

One thing I've been wondering for a long time (and my Google-fu is apparently too weak to find on my own): how do certain console applications change the output color without inserting ANSI escape sequences into the output stream? The specific case I have in mind is when writing console programs in C#/.NET, and using the System.Console.ForegroundColor property to vary output colors on the fly. The resulting output text does not have ANSI escape characters in it, yet the colors are displayed properly in the terminal.


On Linux, .NET does write ANSI escape sequences to stdout for you. ConsolePal.Unix.cs (Pal in this context referring to 'platform abstraction layer') does the work for you behind the scenes: https://github.com/dotnet/runtime/blob/10eb1a9ff1c09de4a2a1f...


Is this on Windows? If so Windows provides a typical Win32 type of HANDLE API for the console which can be used to change the properties of the console among other things.


To clarify: .NET being cross platform, I write console apps that I run on both Windows and MacOS, and in both cases if I redirect the color output to a .txt file and open it in an editor, there are no ANSI escape sequences in the file. So I was wondering if there is some other standard for sending control codes to a terminal that is independent of the output stream.

Or is there some voodoo by which the ANSI sequences get stripped from the output when redirected to a file?


> Or is there some voodoo by which the ANSI sequences get stripped from the output when redirected to a file?

Not quite, but programs in general use some voodoo to detect when they are being redirected and won't output ANSI codes when they detect that.

Often there will be a flag to enable/disable color, or let it detect when color is desired. On Linux ls accepts the --color=WHEN parameter, where WHEN can be always (`ls --color=always > ls-with-ansi-codes.txt` will output color codes), it can be never (just don't output ANSI codes, no matter whether you detect output redirection) or it can be auto (will show colors when you execute `ls --color=auto` but not when you do `ls --color=auto > ls-without-ansi-codes.txt`).


On windows, there are APIs for setting color that could be ignored if STDOUT isn't a terminal.

On posix platforms, there's an API to check if a given file handle is a tty or not. https://github.com/corasaurus-hex/isatty/blob/main/isatty.c is an example of using the API, in a Janet context.

I assume that .NET's support for Linux/macOS is using that API decide if it should strip color codes or not.


Well yes like I said on Windows you can access the terminal and set its properties without encoding terminal escape sequences in the output stream. On Linux afaik escape sequences are the only way. On MacOS i have no idea. Generally speaking the escape sequences aren't "standard" but different terminals (and these days terminal emulators) all have their own codes. Hence ncurses which tries to encapsulate this and provide a uniform API so that the application doesn't have to deal with these murky details.

Have you double checked with s hex editor what is in the txt file? Suppose it could also be your text editor that doesn't want to render those codes.


Are you manually inserting the ANSI sequences into the stream? Or are you using a library that does this for you?

Often times libraries that let you specify output color will helpfully query the capabilities of the output device, and avoid writing the control codes if it’s (for example) a plain text file.


They are sometimes stripped when redirecting. Maybe try executing it headless and reading the output?


Personally I'm not a C#/.NET developer so wouldn't know where to look for the source code, but to check you can run the program in the examples of the post with the compiled binary on the other side (in place of the SHELL) and see what output you get.

I'm 99% sure it's inserting ANSI escape codes (I'm maintaining a terminal emulator myself, and really that's how everything works), but I could of course be wrong.


The Windows console is a bit more sophisticated than the traditional *nix "shuffle text back and forth" approach; the Windows Command Line blog goes into some detail here (and in the rest of this series): https://devblogs.microsoft.com/commandline/windows-command-l...

Short version: there is support for ANSI and VT sequences in the Windows console (which relatively recently got substantially expanded), but that's not what it speaks "natively"-- for Win32 console applications, there's a native console API that works by passing IOCTLs back and forth between the app and console driver.

(If you're writing a terminal emulator for Windows, you don't necessarily see this-- the new ConPTY mechanism you use to build these as of Windows 10 abstracts away the Windows specifics so you see text and VT sequences just as you would on *nix.)


WAY back in the DOS days Qbasic and command.com could both change foreground and background colours via system hooks (INT bios calls) without using ANSI. I know this because Qbasic console apps could be colourful without having to load ansi.sys in config.sys

I am thinking that .foregroundColor and .backgroundColor do the same thing via legacy emulation in conhost.


Most likely it was writing text and attribute data directly to video memory. You didn't even need to call into the BIOS to do that shit (though the BIOS may have helped from a convenience standpoint to set the video mode).


Turbo Pascal had a Crt library that did this.


True, but you could also get the address of the screen buffer and define a structured type to overlayed it that allowed you to put values directly into memory.

Each screen location was two bytes, one byte for the character value, and one for the character attributes which were a set of bits that controlled red, green, blue and intensity for both the foreground color and background color.

Then you could write routines that would fill in a rectangular region with a color, scroll the text of a region up or down, and do all sorts of other windowy things. There were also interrupt routines you could call that did some of these, and certainly routines in Crt that did some of this. Then you were on your way to developing your own TUI library!

Alternatively, you would issue an interrupt call to put the screen into 320x200 256 color mode, get the address of that buffer ($B800 if memory serves), similarly overlay it with a typed grid, then start poking byte values in and getting all sorts of nice colors out of it. Super fun!!


Maybe I'm biased, but I think learning to code in that environment was way better than today's Javascript-based in-browser graphics environment. I didn't know a damn thing about coding, but I was still able to make a rudimentary GUI paint program in one semester of high school.

I looked recently to see if an equivalent of Crt is still out there, but it doesn't look like any of the modern Pascal versions support it.


A000:0000 was the VGA graphics buffer. B800:0000 is the text mode buffer though. (Including the segment and offset since that works out to A0000 I believe.)


Wow, I got the right offset for the other mode! Not bad for a 30-year impressionistic memory!


This comment wins.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: