Skip to content

Command causes subsequent ANSI codes to render incorrectly #68903

@vallentin

Description

@vallentin

I'm experiencing some odd behavior with ANSI codes and std::process::Command. The ANSI codes render differently after having executed a command.

  1. In Git Bash using \u{1b}[2m (gray/dim) does not render at all, which is understanble as it might not be supported. However, after executing some command, then it renders correctly.
  2. On the other hand, in CMD and PowerShell, then after running some command, then the ANSI codes appear literally in the output. (Which is the actual issue.)

The command being executed seem to be important, as changing it either results in the issue being triggered or no change at all.

Both spawn() + wait() and status() behave the same. Whereas output() does not trigger the issue. So I'm assuming the command is somehow able to affect the inherited stdin/stdout/stderr, causing the issue to persist after the command has finished.

Git Bash

It's understandable that some ANSI code might not be supported by my terminal. But it's quite odd, that executing some command using std::process::Command, results in it rendering correctly after.

command-git-bash

CMD

However, the real issue is in CMD (and PowerShell), where every ANSI code renders literally in the output, after having executed some command.

command-cmd

Minimal, Reproducible Example

I also tried using the clicolors-control crate to enable/disable ANSI colors. However the issue still persists, and I originally submitted the issue there earlier mitsuhiko/clicolors-control#15.

use std::process::Command;

fn main() {
    println!("Foo \u{1b}[36mBar\u{1b}[0m Baz"); // Cyan
    println!("Foo \u{1b}[2mBar\u{1b}[0m Baz <- Not colored"); // Dim
    println!("Foo \u{1b}[31mBar\u{1b}[0m Baz"); // Red
    println!();

    // ANSI codes render incorrectly if any of these commands are executed
    Command::new("git").arg("log").status().unwrap();
    // Command::new("git").arg("diff").status().unwrap();

    // However, ANSI codes are not affected if any of these commands are executed
    // Command::new("git").arg("--version").status().unwrap();
    // Command::new("cargo").arg("--version").status().unwrap();
    // Command::new("cargo").arg("build").status().unwrap();

    println!();
    println!("Foo \u{1b}[36mBar\u{1b}[0m Baz"); // Cyan
    println!("Foo \u{1b}[2mBar\u{1b}[0m Baz"); // Dim
    println!("Foo \u{1b}[31mBar\u{1b}[0m Baz"); // Red
    println!();
}

Python

I thought it might be my terminal being weird. So I test the equivalent in Python, and it rendered correctly.

command-python

from subprocess import run

print("Foo \u001b[36mBar\u001b[0m Baz") # Cyan
print("Foo \u001b[2mBar\u001b[0m Baz") # Dim
print("Foo \u001b[31mBar\u001b[0m Baz") # Red
print()

run(["git", "log"])

print()
print("Foo \u001b[36mBar\u001b[0m Baz") # Cyan
print("Foo \u001b[2mBar\u001b[0m Baz") # Dim
print("Foo \u001b[31mBar\u001b[0m Baz") # Red

I've tested in both debug and release mode, as well as stable and nightly. The issue remains the same.

$ rustc --version --verbose
rustc 1.41.0 (5e1a79984 2020-01-27)
binary: rustc
commit-hash: 5e1a799842ba6ed4a57e91f7ab9435947482f7d8
commit-date: 2020-01-27
host: x86_64-pc-windows-msvc
release: 1.41.0
LLVM version: 9.0

$ cargo --version --verbose
cargo 1.41.0 (626f0f40e 2019-12-03)
release: 1.41.0
commit-hash: 626f0f40efd32e6b3dbade50cd53fdfaa08446ba
commit-date: 2019-12-03

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-bugCategory: This is a bug.O-windowsOperating system: WindowsT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions