[PR #11932] [MERGED] Add rbeesley's ansi-color.cmd, a CMD-based color tool (& more) #28805

Open
opened 2026-01-31 09:30:53 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/11932
Author: @rbeesley
Created: 12/13/2021
Status: Merged
Merged: 1/4/2022
Merged by: @undefined

Base: mainHead: 6470-Command-Shell-Script-ColorTool


📝 Commits (10+)

  • c353e6b Add ansi-color.cmd tool and several definitions
  • 3256bef Add README.md
  • 0c09451 Satisfy check-spelling-bot
  • 1796285 Fixed missing files for spell-check-bot script
  • b2b4e4e Deleting spell-check-bot file placed incorrectly
  • 8a95ab1 Improved spelling, comments, error handling
  • 7006e52 check-spelling-bot fix.
  • 78004c7 Fixed comment and macro casing
  • 23e489f Merge branch 'microsoft:main' into 6470-Command-Shell-Script-ColorTool
  • 21a936e Improved CHCP reliability and case insensitive IFs

📊 Changes

20 files changed (+3537 additions, -12 deletions)

View changed files

📝 .github/actions/spelling/expect/expect.txt (+20 -12)
📝 .github/actions/spelling/expect/web.txt (+9 -0)
📝 .github/actions/spelling/patterns/patterns.txt (+3 -0)
src/tools/ansi-color/README.md (+31 -0)
src/tools/ansi-color/ansi-color.cmd (+1560 -0)
src/tools/ansi-color/ansi-colortool.def (+57 -0)
src/tools/ansi-color/attrib.def (+449 -0)
src/tools/ansi-color/colortest.def (+52 -0)
src/tools/ansi-color/colortool.def (+45 -0)
src/tools/ansi-color/crisman.def (+80 -0)
src/tools/ansi-color/fgbg.def (+61 -0)
src/tools/ansi-color/lbl.def (+64 -0)
src/tools/ansi-color/plaid.def (+54 -0)
src/tools/ansi-color/rainbow.def (+52 -0)
src/tools/ansi-color/rosetta.def (+40 -0)
src/tools/ansi-color/separator.def (+124 -0)
src/tools/ansi-color/sgr-intensity.def (+160 -0)
src/tools/ansi-color/sgr.def (+348 -0)
src/tools/ansi-color/tsgr.def (+287 -0)
src/tools/ansi-color/ubuntu.def (+41 -0)

📄 Description

Adds the Ansi-Color tool, completing #6470.

What started out as an experiment to see the support of ANSI support to
conhost, I wanted to write a Windows equivalent of Daniel Crisman's
BASH script on tldp.org. I didn't like how the BASH script hard coded
in whitespace and I thought Windows could do better. I applied
techniques to speed up the execution and tried to use the Command Script
batch language in ways that pushed the limits for what I thought it
could do. Running this from withing PowerShell, &cmd /c ansi-color.cmd,
I found out that the active code page is already 65001, but when ran
from a Command Prompt, the active code page depends on the regional
settings and I would have a dependency on CHCP to detect the active code
page, change to 65001 if necessary, and restore the previous code page
after running. I found it useful for designing color schemes and writing
shaders, and I started using an earlier version for logging bugs.

Initially it was a single script which I would dump every SGR
combination I could think of, and many which weren't implemented yet,
but as I was looking at other tools which had been written I wanted to
mimic the same output so I could do side-by-side comparisons. First I
wrote crisman.def and then colortool.def. So I had to align text.
Then output was slow for big tables so I wrote to an outbuffer and made
use of macros. I wanted to handle flags instead of needing to change
settings every time, so I added argument parsing and loading external
files.

It's a batch file that has some really useful purposes and does nothing
I've seen before.

I've ran every definition in a Command Prompt, with CP 437 and CP 65001
to make sure it works. Posted as a Gist on my account for about year, a
Portuguese (Brazilian as I recall), speaking user tried the Gist and it
was failing because CHCP is localized. I've taken an approach to try and
make it work for different localizations, but this is a potential
problem. I also ran every definition in PowerShell 7, shelling down to
cmd to actually run it. Lastly, I went through using the flags and
made sure that help would be shown. Error messages generate error levels
when the script exits, so those could be used to use this in an
automated test and catch if there was a problem with the script
executing. It won't be able to validate if the generated output shows
correctly, but it would fail if a definition file is missing or if it
needed to switch to Unicode and wasn't flagged or configured to do so.
For trying to build the table stub and headers, there is some debug code
which will output what was parsed. This is the last debug code in the
script itself, but I found it to be useful at times, so there is a
configuration setting which can turn that debug output back on.
Technically there is also a debug statement to break after adding the
macros and parsing the arguments, but before it does any configuration
changes, changes the code page, or anything. This was useful for making
changes to macros and being able to test them as well as making sure
that flags and arguments are parsed correctly. It was a rather cryptic
discovery to call cmd /c exit -1073741510 to break out, so in part
that was my reason to leave this in. The definition files themselves
could be cleaned up further, but in both of them there are a lot of
Unicode codepoints that could be useful when defining division lines for
the headers so I opted to just comment them out. I initially had the
default definition to require Unicode, but now it just changes to a
non-Unicode output if it can't. And this brings up the last concern. The
way certain settings are set, is that they are defined in the
__TABLE__ section of the definition file. With PARSE_TABLE_DATA,
the script looks line by line for SET * or IF * and if found it will
effectively eval that line. The definition files are written so that for
instance SET "CELL= gYw " could be used to set the code which is used.
If was allow so that there could be a test if Unicode were available
and set something different for ASCII and Unicode. But it also opens the
possibility that a rogue actor could create a ansi-color.cmd
definition file something like SET "foo=bar" & DoSomethingBad.exe.
First of all I'd be flattered that anyone would use this very niche
tool, but it is something I think which needs to be called out.
Essentially the definition files are just batch files, but they are
extremely limited to executing only one line at a time and only
supporting IF and SET commands. I think this is a minimal risk because
at that point batch files would already be more effective, but there
should also be an expectation that a batch file will run something and
the same may not be true for the heavily degraded definition files. I
think the risk is minimal but it is a risk I wanted to make clear. This
really showcases some interesting techniques and ideas, and I hope that
it is useful. All told, there are a couple years of incremental changes
in this PR.

Closes #6470


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/11932 **Author:** [@rbeesley](https://github.com/rbeesley) **Created:** 12/13/2021 **Status:** ✅ Merged **Merged:** 1/4/2022 **Merged by:** [@undefined](undefined) **Base:** `main` ← **Head:** `6470-Command-Shell-Script-ColorTool` --- ### 📝 Commits (10+) - [`c353e6b`](https://github.com/microsoft/terminal/commit/c353e6b51fcb47c34c77a89168281927a482790a) Add ansi-color.cmd tool and several definitions - [`3256bef`](https://github.com/microsoft/terminal/commit/3256befcdd607f6e22705a1348ee49997f90330f) Add README.md - [`0c09451`](https://github.com/microsoft/terminal/commit/0c09451262c4ac03c259ed369a79232e161cee0f) Satisfy check-spelling-bot - [`1796285`](https://github.com/microsoft/terminal/commit/1796285c9569d9b7d1a8bf8e6cc12ded372bfd86) Fixed missing files for spell-check-bot script - [`b2b4e4e`](https://github.com/microsoft/terminal/commit/b2b4e4e2897b912a0cca7b21ecee1b9000d68fae) Deleting spell-check-bot file placed incorrectly - [`8a95ab1`](https://github.com/microsoft/terminal/commit/8a95ab1468f545baf4f38063fc7bd969b981aaa1) Improved spelling, comments, error handling - [`7006e52`](https://github.com/microsoft/terminal/commit/7006e52e960b8b8ab7e5b57d422d784f75c0b9d8) check-spelling-bot fix. - [`78004c7`](https://github.com/microsoft/terminal/commit/78004c7c8c543c2dda6d3bf5fc478777a1fbae2b) Fixed comment and macro casing - [`23e489f`](https://github.com/microsoft/terminal/commit/23e489f0edd7ee0db0cc295a57da08ef17a3d518) Merge branch 'microsoft:main' into 6470-Command-Shell-Script-ColorTool - [`21a936e`](https://github.com/microsoft/terminal/commit/21a936ee783d0a31f0bd87ca6453f0c2caa2ada7) Improved CHCP reliability and case insensitive IFs ### 📊 Changes **20 files changed** (+3537 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `.github/actions/spelling/expect/expect.txt` (+20 -12) 📝 `.github/actions/spelling/expect/web.txt` (+9 -0) 📝 `.github/actions/spelling/patterns/patterns.txt` (+3 -0) ➕ `src/tools/ansi-color/README.md` (+31 -0) ➕ `src/tools/ansi-color/ansi-color.cmd` (+1560 -0) ➕ `src/tools/ansi-color/ansi-colortool.def` (+57 -0) ➕ `src/tools/ansi-color/attrib.def` (+449 -0) ➕ `src/tools/ansi-color/colortest.def` (+52 -0) ➕ `src/tools/ansi-color/colortool.def` (+45 -0) ➕ `src/tools/ansi-color/crisman.def` (+80 -0) ➕ `src/tools/ansi-color/fgbg.def` (+61 -0) ➕ `src/tools/ansi-color/lbl.def` (+64 -0) ➕ `src/tools/ansi-color/plaid.def` (+54 -0) ➕ `src/tools/ansi-color/rainbow.def` (+52 -0) ➕ `src/tools/ansi-color/rosetta.def` (+40 -0) ➕ `src/tools/ansi-color/separator.def` (+124 -0) ➕ `src/tools/ansi-color/sgr-intensity.def` (+160 -0) ➕ `src/tools/ansi-color/sgr.def` (+348 -0) ➕ `src/tools/ansi-color/tsgr.def` (+287 -0) ➕ `src/tools/ansi-color/ubuntu.def` (+41 -0) </details> ### 📄 Description Adds the Ansi-Color tool, completing #6470. What started out as an experiment to see the support of ANSI support to conhost, I wanted to write a Windows equivalent of Daniel Crisman's [BASH script on tldp.org]. I didn't like how the BASH script hard coded in whitespace and I thought Windows could do better. I applied techniques to speed up the execution and tried to use the Command Script batch language in ways that pushed the limits for what I thought it could do. Running this from withing PowerShell, `&cmd /c ansi-color.cmd`, I found out that the active code page is already 65001, but when ran from a Command Prompt, the active code page depends on the regional settings and I would have a dependency on CHCP to detect the active code page, change to 65001 if necessary, and restore the previous code page after running. I found it useful for designing color schemes and writing shaders, and I started using an earlier version for logging bugs. Initially it was a single script which I would dump every SGR combination I could think of, and many which weren't implemented yet, but as I was looking at other tools which had been written I wanted to mimic the same output so I could do side-by-side comparisons. First I wrote `crisman.def` and then `colortool.def`. So I had to align text. Then output was slow for big tables so I wrote to an outbuffer and made use of macros. I wanted to handle flags instead of needing to change settings every time, so I added argument parsing and loading external files. It's a batch file that has some really useful purposes and does nothing I've seen before. I've ran every definition in a Command Prompt, with CP 437 and CP 65001 to make sure it works. Posted as a Gist on my account for about year, a Portuguese (Brazilian as I recall), speaking user tried the Gist and it was failing because CHCP is localized. I've taken an approach to try and make it work for different localizations, but this is a potential problem. I also ran every definition in PowerShell 7, shelling down to `cmd` to actually run it. Lastly, I went through using the flags and made sure that help would be shown. Error messages generate error levels when the script exits, so those could be used to use this in an automated test and catch if there was a problem with the script executing. It won't be able to validate if the generated output shows correctly, but it would fail if a definition file is missing or if it needed to switch to Unicode and wasn't flagged or configured to do so. For trying to build the table stub and headers, there is some debug code which will output what was parsed. This is the last debug code in the script itself, but I found it to be useful at times, so there is a configuration setting which can turn that debug output back on. Technically there is also a debug statement to break after adding the macros and parsing the arguments, but before it does any configuration changes, changes the code page, or anything. This was useful for making changes to macros and being able to test them as well as making sure that flags and arguments are parsed correctly. It was a rather cryptic discovery to call `cmd /c exit -1073741510` to break out, so in part that was my reason to leave this in. The definition files themselves could be cleaned up further, but in both of them there are a lot of Unicode codepoints that could be useful when defining division lines for the headers so I opted to just comment them out. I initially had the default definition to require Unicode, but now it just changes to a non-Unicode output if it can't. And this brings up the last concern. The way certain settings are set, is that they are defined in the `__TABLE__` section of the definition file. With `PARSE_TABLE_DATA`, the script looks line by line for `SET *` or `IF *` and if found it will effectively eval that line. The definition files are written so that for instance `SET "CELL= gYw "` could be used to set the code which is used. `If` was allow so that there could be a test if Unicode were available and set something different for ASCII and Unicode. But it also opens the possibility that a rogue actor could create a `ansi-color.cmd` definition file something like `SET "foo=bar" & DoSomethingBad.exe`. First of all I'd be flattered that anyone would use this very niche tool, but it is something I think which needs to be called out. Essentially the definition files are just batch files, but they are extremely limited to executing only one line at a time and only supporting IF and SET commands. I think this is a minimal risk because at that point batch files would already be more effective, but there should also be an expectation that a batch file will run something and the same may not be true for the heavily degraded definition files. I think the risk is minimal but it is a risk I wanted to make clear. This really showcases some interesting techniques and ideas, and I hope that it is useful. All told, there are a couple years of incremental changes in this PR. Closes #6470 [BASH script on tldp.org]: https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:30:53 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#28805