How can I work around Windows 10 command prompt stripping modified output of ANSI colors? (Ansicon)

1.3k Views Asked by At

I am writing a program for Windows Command Prompt. I was originally working on it in Windows 7, but have since upgraded to Windows 10 where it has broken.

The batch file starts with this:

rem _bc  == Background Color (NOT ANSI)
rem _bc2 == ANSI BGCOLOR
rem _hc  == Highlight Color
rem _hc2  == NOT Highlighted Color

set _hc=[1;36;
set _hc2=[1;37;
set _bc=[0m
set _bc2=46m
set color2=f

ansicon cmd /K

In my program, I want to take a line of output and then append to the beginning and end of the line (not strictly but as an example) a variable that has ANSI code to color my text. I have always used sed for this. Using sed was more flexible than hardcoding the variables into each output...

echo  Keep your eye out for %_hc%%_bc2%Highlighted%_bc%%_hc2%%_bc2% information!

This is in comparison to something like this:

echo THIS IS THE TEST OUTPUT:|sed "s/^/%_hc%%_bc2%/"|sed "s/$/%_bc%/"

rem ================[Result]=======================
rem Displays "THIS IS THE TEST OUTPUT" in color
rem This is broken in Windows 10's Command Prompt.

It appears that using sed, sort, or basically anything except the echo or type commands, it strips the output of color and just outputs the ANSI code instead. This never happened in Windows 7 or XP. For example:

echo %_hc%%_bc2%THIS IS THE TEST OUTPUT:%_bc%|sort

rem ================[Result]=======================
rem Displays "←[1;36;46mTHIS IS THE TEST OUTPUT←[0m"
rem This works if you don't pipe it to sort.
rem Outputting to a file and then using type also works.

The problem is that echo doesn't support pipe so I can't pipe it post-modification to echo (as it would be redundant for almost all purposes). I don't want to redirect it to a file for use with Type, though I guess a pipeable type command alternative would do the trick but I searched around and wasn't able to find one.

It should remain flexible so that using sed, etc... I could insert the highlight anywhere in the text line via keywords, field numbers, etc. I could accomplish this still for example:

Keep your eye out for Highlighted information!

rem ================[Result]=======================
rem Displays "Keep your eye out for Highlighted information!"
rem Where "Highlighted" is the only word in color.

Any help tackling this without piping to a file or hardcoding the ansi variables into set positions would be greatly appreciated.

1

There are 1 best solutions below

0
On

Here's one possible solution. Instead of using ansicon and sed, borrow from PowerShell. As a bonus, you remove your dependency on 3rd party utilities for functionality that can be handled internally. Here's an example involving a powershell command macro that parses each line of piped input, splits the string at the word that should be bolded, etc. Save this with a .bat extension and give it a try.

@echo off
setlocal

set "doHighlight=powershell -noprofile -noninteractive "^
$s=\"%%bold%%\";^
foreach ($i in $input) {^
    $m=0;^
    $h = $i ^| select-string $s -allmatches;^
    $i -split $s ^| %%{^
        if ($m++) {^
            write-host -nonewline $h.matches[$m-2] -f darkblue -b yellow;^
        }^
        write-host -nonewline $_^
    };^
    ''^
}""


set "bold=some highlighted text"
echo This is some highlighted text with another HighLiGhT here. | call %doHighlight%

set "bold=highlight"
type "%~f0" | call %doHighlight%