Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do ANSI escape codes sometimes work in CMD

ANSI escape codes do not work by default in cmd.

But however some application do some kind of initialization after which they seem to seem to work during that session.

How do they do this initialization? Here is an example -

I built a simple rust application that uses ANSI codes for colorful output.

Image showing cargo using ANSI escape codes.

However if I first build the project, then close that session and then again start cmd going to the directory in which my compiled project is and then run the executable (this time without using cargo at all in this session)-

ANSI escape codes without cargo

It seems like applications like cargo (and other applications also) do some kind of initialization step in the cmd after which the terminal seems to recognize ANSI codes.

And also in Python Calling os.system('') before using ANSIescape codes does the job -

ANSI escape codes work after os.system('')

It seems like os.system('') is a bug, and you shoudn't rely on bugs to make your code work. Is there a better way to initialize ANSI escape codes in cmd?

like image 740
Cool Developer Avatar asked Nov 02 '25 20:11

Cool Developer


1 Answers

What you're searching for is ENABLE_VIRTUAL_TERMINAL_PROCESSING. The reason it sometimes "stops working", is because some applications disable it before exiting. If it was already enabled, then this is when stuff breaks.

However, you can easily enable it (again) by calling SetConsoleMode() using the winapi crate. You can also use the winapi-util crate which makes it a bit easier.

#[cfg(windows)]
pub fn enable_virtual_terminal_processing() {
    use winapi_util::console::Console;

    if let Ok(mut term) = Console::stdout() {
        let _ = term.set_virtual_terminal_processing(true);
    }
    if let Ok(mut term) = Console::stderr() {
        let _ = term.set_virtual_terminal_processing(true);
    }
}
[target.'cfg(windows)'.dependencies]
winapi-util = "0.1"

To be safe you could call enable_virtual_terminal_processing() initially in main(). However, I definitely recommend calling it after executing a std::process::Command, e.g.:

let output = Command::new("...")
    .args(&["..."])
    .output()
    .expect("failed to execute process");

#[cfg(windows)]
enable_virtual_terminal_processing();
like image 83
vallentin Avatar answered Nov 05 '25 10:11

vallentin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!