Colorful Command Prompt

Posted by Wojtek Dziegielewski on Oct 16, 2019

TL;DR: How to add color to text displayed in the command prompt window.

Good Old DOS Prompt

Every once in a while, I find it convenient to use the good old command prompt window, aka the DOS prompt. For example, if a console application takes many arguments, it may be easiest to create a simple batch (.bat) file with the entire command line followed by the pause command. You then simply double click on the batch file to invoke the application on as-needed basis.

Typically console applications provide monochrome output, which makes the display look archaic. Before Windows 10, there was no easy way to display such text in colors (aside from changing foreground and background colors). In Windows 10, the command prompt window got overhauled and now supports control character sequence that can be used to adjust the looks of the window.

Sample Scenario

Let’s assume we have a job (batch file) that calls two console applications, one after another. For simplicity, we will simulate the output from these applications by two other batch files.

@echo off
cls

echo This sample job invokes two tasks, for example .NET console apps.
REM The tasks are simulated by FirstTask.bat and SecondTask.bat batch files

call FirstTask.bat
call SecondTask.bat

echo Both tasks have completed.
pause
REM This is a simulated output from an executable program, e.g. a .NET console application
echo The first task is starting.
echo There were 500 records processed with no errors.
echo The first task has completed processing in 0.001s.
REM This is a simulated output from an executable program, e.g. a .NET console application
echo The second task is starting.
echo Error occurred in record# 344: Invalid record type.
echo There were 500 records processed with 1 error.
echo The second task has completed processing in 0.003s.

When we double-click on out JobWithTwoTasks.bat file, our job will get executed and we will see this rather boring looking output:

Colorful Command Prompt baseline

Task Separators

When looking at this last output, it’s difficult to see what happened, in particular which part of the output was produced by which task. It seems as if the best we can do is to add some empty lines to separate sections of the output:

echo.
call FirstTask.bat
echo.
call SecondTask.bat
echo.

Upon making this change to JobWithTwoTasks.bat, our output looks like this:

Colorful Command Prompt tasks separated

Adding Color

When on Windows 10, we can do better. Basically, any part of the display can have it’s own color. So, if we add some special characters to the output:

REM Set text color to green
echo 
call FirstTask.bat
REM Set text color to yellow
echo 
call SecondTask.bat
REM Reset text color
echo 

, then the output from the first will show in green and the output from the second task will show in yellow:

Colorful Command Prompt colorful

Some explanation is in order here. The mysterious  character is the escape character with an ASCII code of 27 (decimal). Depending on the editor you’re using to edit the JobWithTwoTasks.bat file, it may be more or less challenging to enter this special character. Perhaps, the easiest approach is to use the clipboard, i.e. copy and paste. For example, it can copied directly from this page.

We’re also seeing some strange sequences following the escape character. How do we know that using  will set our text color to green? There are a few resources that you may need to google for. I found this file provided by Michele Locati very helpful. It makes the selection of a proper character sequence a breeze.

The basic idea is that each sequence starts with the escape character followed by an open bracket. It then contains up to 16 parameters separated by semicolons. The sequence ends with an m character. So, for example, our  contains 2 parameters: 0 means “reset the console to its original state” and 92 means “set text color to green”. The first parameter (0) is relevant in cases where text attributes other than color (e.g. underline) have been set previously. Feel free to experiment with different control character sequences.

No Extra Lines

Now that the tasks are displayed in different colors, we may no longer want the blank lines between them. To eliminate these extra lines, we need the echo command to suppress the line-feed character at end. There is a fairly known trick to do that:

REM Set text color to green
echo | set /p=
call FirstTask.bat
REM Set text color to yellow
echo | set /p=
call SecondTask.bat
REM Reset text color
echo | set /p=

A quick explanation on this trick in which the output from echo command is “piped” into the set command. The control character sequences are sent as a prompt by the set command, which expects an entry to be made to the console. This prompt is immediately satisfied by the line-feed character provided by the echo command and importantly the line-feed is not echoed to the screen. If you’re curious what variable is being set by the set command above, the answer is none. While it is OK to leave off the variable name (the part between /p and the equal sign), no variable is set in this case. But, we’re veering off topic here.

Now our output looks like the original one, but in color:

Colorful Command Prompt colorful no separators

Refinements

We now have the output we want, but our code can still be refined. All revisions presented below will result in the same output as on the last image above.

First, using echo and piping to supply data requested by set command is awkward and inefficient. Piping can be avoided by instead having set read from nul, i.e. a special device that yields EOF (end of file) immediately. So, our code might look like this instead (and still produce identical output):

REM Set text color to green
<nul set /p=
call FirstTask.bat
REM Set text color to yellow
<nul set /p=
call SecondTask.bat
REM Reset text color
<nul set /p=

You may not like the fact that a non-printable character (, i.e. escape) is proliferated throughout the script. We can make our code easier to read by assigning the escape characters to a variable and using this variable afterwards. The code below again provides the same output as before.

REM ESC character (Ascii code 27)
set esc=

REM Set text color to green
<nul set /p=%esc%[0;92m
call FirstTask.bat
REM Set text color to yellow
<nul set /p=%esc%[0;93m
call SecondTask.bat
REM Reset text color
<nul set /p=%esc%[0m

What if you don’t like the escape character to be present in your script at all? It can be done too! Something like this:

call SetTextColor green
call FirstTask.bat

call SetTextColor yellow
call SecondTask.bat

call SetTextColor

We have now delegated handling of the control character sequences to another batch file: SetTextColor.bat. Here is what it looks like:

@echo off
REM A script to set the color of text printed to the console.
REM Intended to be called from other .bat files like so:
REM    call SetTextColor <color>
REM , where <color> is one of: red, green, yellow, blue, magenta, cyan, white

REM ESC character (Ascii code 27)
set esc=

If "%1" == "red" (
  <nul set /p=%esc%[0;91m
  goto done
)
If "%1" == "green" (
  <nul set /p=%esc%[0;92m
  goto done
)
If "%1" == "yellow" (
  <nul set /p=%esc%[0;93m
  goto done
)
If "%1" == "blue" (
  <nul set /p=%esc%[0;38;2;64;128;255m
  goto done
)
)
If "%1" == "magenta" (
  <nul set /p=%esc%[0;95m
  goto done
)
)
If "%1" == "cyan" (
  <nul set /p=%esc%[0;96m
  goto done
)
)
If "%1" == "white" (
  <nul set /p=%esc%[0;97m
  goto done
)
REM TODO: add other colors and/or display attributes as needed

REM If color is unrecognized or omitted, then reset color (back to the console original).
<nul set /p=%esc%[0m

:done

The script can be expanded to support additional colors and text attributes, such as underline. Feel free to experiment with different control character sequences.

Conclusion

Windows 10 allows control over color and other display attributes in the command prompt window. This makes it possible for DOS batch scripts to output text looking just like output from modern tools, such as PowerShell or Linux scripts.

Source Code

The scripts presented in this article is available on GitHub in this repository.


Comments on this post are handled by utteranc.es, an open-source, lightweight commenting system that uses GitHub issues. To leave a comment, a GitHub account is needed and also utteranc.es must be authorized to post an issue on your behalf. This can be done by clicking the "Sign in to comment" button. No advertising or user tracking will be used.