[HN Gopher] Inspect ANSI control codes and escape sequences
       ___________________________________________________________________
        
       Inspect ANSI control codes and escape sequences
        
       Author : webpro
       Score  : 96 points
       Date   : 2025-07-15 08:07 UTC (3 days ago)
        
 (HTM) web link (ansi.tools)
 (TXT) w3m dump (ansi.tools)
        
       | webpro wrote:
       | Working with and debugging ANSI control codes and escape
       | sequences can be a challenge.
       | 
       | This free web-based tool helps to inspect the input, visualize
       | colors and styling, and list control codes. By using a proper
       | tokenizer and parser (not just regex hacks), it supports all
       | sorts of control codes. The parser is open source and available
       | too (find links in "about").
       | 
       | Type or paste text in the black text area, or try out the
       | examples. Use the lookup table to filter & find specific codes.
       | 
       | Feedback welcome, I'd love to know what's confusing, missing, or
       | especially useful.
        
         | michaelmior wrote:
         | Very cool! Seems like this should be a Show HN post.
        
       | JdeBP wrote:
       | The revealing shibboleth is when people call it "ANSI". (-:
       | "ANSI" is what people call it when they are working from paltry
       | and incomplete samizdat doco of how this stuff works, from
       | Microsoft's old ANSI.SYS appendix to its MS-DOS user manual, to
       | innumerable modern WWW sites all repeating received wisdom.
       | 
       | The thing to remember is that the "E" in "ECMA" does not stand
       | for "ANSI".
       | 
       | * https://ecma-international.org/publications-and-standards/st...
       | 
       | * https://ecma-international.org/publications-and-standards/st...
       | 
       | * https://www.itu.int/rec/T-REC-T.416-199303-I
       | 
       | If you read ECMA-35, you'll find that there's actually a whole
       | system to escape sequences and control sequences. As I pointed
       | out last month, it's often the case that people who haven't read
       | ECMA-35 don't realize that parameter characters can be more than
       | digits, don't handle intermediate characters, and don't grasp how
       | DEC's question mark and SCO's equals sign fit into the overall
       | picture. People who haven't read ECMA-48 and traced its history
       | don't realize that there's subtlety to missing parameters in
       | control sequences. And people who haven't read ITU/IEC T.416 do
       | what many of us did years ago and get 24-bit colour wrong. Twice
       | over.
       | 
       | * https://github.com/tattoy-org/tattoy/issues/105#issuecomment...
       | 
       | Other common errors include missing out on all of the _other_
       | 7-bit aliases for C1 characters. Or not realising that the
       | ECMA-35 /ECMA-48 syntax allows for _any_ control sequence to have
       | sub-parameters, not just SGR. Or using regular expressions and
       | pattern matching instead of a state machine. Only a state machine
       | truly handles the fact that in the real world terminals allowed,
       | and _enacted_ , various C0 and C1 control characters _in the
       | middle of control sequences_ , as well as had ways of cancelling
       | or restarting control sequences mid-sequence.
       | 
       | * https://github.com/jdebp/nosh/blob/trunk/source/ECMA48Decode...
       | 
       | But it gets even worse for a real world control sequence decoder.
       | 
       | In the real world, not only do terminals interpret the same
       | control sequences, and their parameters, differently depending
       | from whether the terminal is sending or receiving them; but
       | several terminal emulators like the one in Interix, rxvt, the one
       | built in to Linux, and even XTerm, _send_ control sequences that
       | not only break ECMA-35 but also conflict with _received_ control
       | sequences. So if one wants to be comprehensive and be cabable of
       | decoding real data, one needs a switch to tell the program
       | whether to decode the character stream as if it is being
       | _received_ by the terminal or as if it is being _sent_ by the
       | terminal.
       | 
       | * https://jdebp.uk/Softwares/nosh/guide/commands/console-decod...
       | 
       | Microsoft Terminal tries to do things properly, which many modern
       | terminal emulators and tools do not, and handles this with _two
       | distinct_ entire state machines, one for input and one for
       | output.
       | 
       | * https://github.com/microsoft/terminal/tree/main/src/terminal...
       | 
       | I handled it with a few goto statements and a handful of flags.
       | (-:
       | 
       | * https://github.com/jdebp/nosh/blob/trunk/source/console-deco...
        
         | blueflow wrote:
         | I think this rant is out-of-place here, type "\x1b[:<=>$t" and
         | check for yourself. It parses correctly. You do learn about the
         | allowed character ranges for CSI sequences from ECMA-48 only,
         | not from the Microsoft docs, so i guess the author did their
         | homework.
        
           | JdeBP wrote:
           | That tells me that you are writing from ignorance, as for
           | starters that's a truly pathetic test that even misses one of
           | the characters that I explicitly mentioned above, let alone
           | thoroughly tests the full range that the specs define. I had
           | an actual poke around the parser code, in contrast to your
           | superficial experimentation. (-: One can, with knowledge,
           | actually find the point where the only three unusual
           | characters that you in fact tested are special cased.
        
             | blueflow wrote:
             | They are not special cased:                 https://github.
             | com/webpro/ANSI.tools/blob/main/packages/parser/src/parsers
             | /csi.ts#L12
             | 
             | The comment correctly identifies the 0x30-0x3f range as
             | parameter bytes and the following as intermediate bytes.
             | Both the range and the names for the bytes are matching
             | ECMA-48 Chapter 5.4.
             | 
             | But you seem to think that everyone except yourself is
             | incompetent, are you trying to make up for something?
        
               | JdeBP wrote:
               | Of course they are. There's a file with all of the
               | special cased constants in, named constants.ts.
               | 
               | Your superficial test tested all three of the special
               | cases in the PRIVATE_OPENERS array, which is what the
               | parser.ts code actually checks. DEC's question mark,
               | which is special cased yet further off on its own, is in
               | reality another "private opener", too, and it isn't
               | limited to DEC (e.g. XQTMODKEYS), and neither does DEC
               | _not_ use the other non-digit parameter characters (e.g.
               | DECDA3).
               | 
               | (There's a hypothesis that DEC's own state machine didn't
               | care where these marker characters were, as it was a
               | simple state machine that had to fit in ROM and probably
               | just set a bitflag. A mistake that we're probably all
               | still making is assuming that they only take effect when
               | in the very first position.)
               | 
               | STRING_OPENERS is another widespread special casing that
               | people do, treating ESC plus a few characters as special
               | rather than handling all of the 7-bit aliases for the C1
               | characters as the general case.
               | 
               | You seem to think that people who share what the mistakes
               | are and where they themselves have made these very
               | mistakes over the years, to help other people not make
               | them and so that the world continues to remember this
               | hard-learned stuff, is somehow worthy of ad hominems,
               | straw men, insults, and vilification right off the bat.
               | That's a very poor show and you should be ashamed.
        
               | clucas wrote:
               | > people who share what the mistakes are and where they
               | themselves have made these very mistakes over the years,
               | to help other people not make them and so that the world
               | continues to remember this hard-learned stuff
               | 
               | But then we have this in your post:
               | 
               | > That tells me that you are writing from ignorance, as
               | for starters that's a truly pathetic test
               | 
               | and
               | 
               | > I had an actual poke around the parser code, in
               | contrast to your superficial experimentation.
               | 
               | Perhaps you really did intend for these lines to be
               | helpful and informative? If so, I encourage you to have a
               | moment of empathy for your interlocutor and ask yourself
               | if talking this way is actually the best way to
               | communicate and pass on this hard-earned knowledge.
               | 
               | > ad hominems, straw men, insults, and vilification
               | 
               | I didn't see this from the other poster. I did see it
               | from you. As a disinterested third party, I'm just
               | telling you, you come off way worse in this exchange.
               | Good luck out there buddy.
        
               | webpro wrote:
               | That's some interesting feedback, thanks for sharing.
               | I'll see what I can extract and apply from it. Please
               | bear with me, this is only my initial take on the whole
               | concept (and as you point out, it isn't that trivial).
               | Didn't have much examples to be inspired by, but we're on
               | our way anyway.
        
               | webpro wrote:
               | Thanks. Agreed. The way I see it, ignore the noise and
               | there might be something in there.
        
         | ForOldHack wrote:
         | Ill never forget the comments in termcap: "Brain dead", "Very
         | Brain dead" and "Brain? What brain!" I think most of that was
         | terminals that CTEOL Clear to end of line was just garbage.
         | 
         | We just knew that at some point in time, all the Hazeltine
         | terminals were going to end up in the garbage, which is what
         | they deserved, and no one would rescue them.
         | 
         | https://www.shallowsky.com/linux/noaltscreen.html
         | 
         | The parent post is SOLID GOLD.
        
         | j4_james wrote:
         | > "ANSI" is what people call it when they are working from
         | paltry and incomplete samizdat doco of how this stuff works
         | 
         | People just use "ANSI" as a shorthand for ANSI X3.64-1979. And
         | that was the standard that DEC used for their VT100+ range of
         | terminals, which in turn became the de facto standard from
         | which most modern terminal emulators are derived. If you read
         | the DEC documentation, you'll find many references to "ANSI
         | standard", "ANSI controls", "ANSI colors", etc. I don't think
         | this is because they were ignorant of the subject matter,
         | considering that they were members of the committee that
         | produced that standard.
         | 
         | And ECMA-48 is essentially just the European equivalent of ANSI
         | X3.64, and was developed in parallel. But obviously an American
         | company like DEC or Microsoft would more likely be working from
         | the American version of the standard rather than the European
         | one.
        
       | mnurzia wrote:
       | Neat tool, I could see this being handy for debugging TUI tools.
       | 
       | I noticed that it works with _escaped_ ESC characters ("\x1b",
       | "\u001b", "\033") but it didn't recognize raw ESC characters that
       | I had in my clipboard. It might be useful to support those (maybe
       | highlight them similarly to how VS Code highlights whitespace
       | characters). The characters show up as numbered unicode error
       | glyphs (I'm on Firefox, if that helps)
        
         | webpro wrote:
         | Thanks, this is great feedback. I'll see what I can do, stay
         | tuned.
        
           | webpro wrote:
           | Raw input should be cool now (there's "raw" in the examples
           | as well)
        
       | ryan-c wrote:
       | This is really cool - I've been experimenting with terminal
       | escape sequences recently, and they go deep. Thanks for sharing!
       | Get in touch (email in profile) if you'd like to collaborate.
        
         | webpro wrote:
         | Thanks! It's all open source (including the tokenizer/parser),
         | so feel free come collaborate on GitHub.
        
       | SpaceL10n wrote:
       | The things they don't prepare you for in school...
       | 
       | I was working at my first job and we had a ColdFusion app that
       | was displaying some data from the database. I get a ticket one
       | day saying our search page would crash when searching for a very
       | specific document. The other 1 million+ documents all loaded fine
       | to our knowledge, so why this one?
       | 
       | I was pretty junior back then and feeling mighty defeated as to
       | why I couldn't figure it out. I debugged every single line and
       | condition, trying to find some reason. After ruling out the code
       | as a culprit, I took the data we were loading and placed it into
       | Notepad++. Don't remember why exactly. I was wracking my brain
       | trying to come up with explanation and lazily moving the text
       | cursor left and right through the text, mostly out of boredom and
       | despair.
       | 
       | That's when I noticed that I had pressed the right arrow key in
       | my keyboard and the text cursor position hadn't changed! I
       | pressed it again and nothing. Again, nothin. It took eight key
       | presses to move the text cursor from one letter in a word to the
       | adjacent letter. I was utterly bamboozled. Why was the text
       | cursor getting stuck in the middle of this word?!
       | 
       | Shortly thereafter, I discovered "Show all hidden characters"
       | setting in the menu. I toggled it and sure enough there were
       | little black boxes with weird three letter strings in them. NUL,
       | ESC, and others - right where my cursor was getting hung up.
       | 
       | That was the day I learned about ANSI control characters and the
       | importance of data sanitization.
        
         | txdv wrote:
         | There are also zero-space width characters, yeah utf is a
         | rabbit hole
        
           | webpro wrote:
           | Emojis and other unicode characters may or may not be
           | rendered as a single-width character. I've been splitting
           | hairs and strings.
           | 
           | The tool currently counts any unicode character as a single-
           | width one.
        
         | wpm wrote:
         | Similarly, I once copied a shell script out of Slack and saw a
         | bunch of red errors from my IDE when I pasted it in. The errors
         | were on every line that had a new line on it. The error was "a:
         | Command not found", despite there being no such character on
         | the line.
         | 
         | Pasted it into a hex editor, tracked down the bytes, and while
         | I can't currently remember specifically what the encoding
         | problem was, it was something to do with going between UTF-8 >
         | ISO-8859 > UTF-8 again.
         | 
         | I've since aliased `pbpaste | xxd` (macOS, linux has similar
         | CLI tools for working with the clipboard depending on your
         | distro/DE), because weird shit like this comes up more often
         | than I'd care to admit. Last rabbit hole was discovering that
         | in macOS 15, Apple changed one of the the "space" characters in
         | the default Screenshot file names, but only if your Mac is set
         | to use 12-hour time from a normal ASCII 0x20 space, to a
         | Unicode 'U+202F NNBSP' "non-breaking space" between the time
         | and AM/PM, which was causing S3 uploads to fail.
        
         | ddd34drf3 wrote:
         | CudaText is better than Notepad++ in this regard. It shows
         | ASCII control chars always. The option for "unprinted chars"
         | only hides "arrows" over spaces/tabs.
        
       | tronster wrote:
       | This is a fantastic web util; bookmarked for the future.
       | 
       | I wish I had this when I was making, [Dragon's
       | Oven](https://tronster.itch.io/dragon). It was a lot of nights
       | and weekends of tinkering with ANSI codes in Typescript. I
       | learned a lot that surprised me, such as: most modern OS's still
       | don't support 16m colors out of the box and that the default
       | Linux shell doesn't support beyond 16 colors. Also no really good
       | modern ANSI editors out there. I tried bringing back "TheDraw" in
       | DosBOX for some art, but ended up using a mismatch of more modern
       | utilities, false starting one of my own, and working on an image
       | to ASCii/ANSI converter.
       | 
       | Maybe it's growing up in the BBS days, but something about ANSI
       | is really charming.
        
         | prometheus76 wrote:
         | TheDraw was a cornerstone of my teenage years. I would log into
         | different BBSs just to see their ANSI welcome screens, then I
         | would try and re-create them to learn the art. It was a unique
         | form of animation and I was hoping you had figured out how to
         | get TheDraw working.
         | 
         | I also later used ANSI to make my own cool command line prompts
         | in DOS and later, Linux.
        
           | ForOldHack wrote:
           | Recreate them? we would steal the stream, save it, run it
           | through a hex editor, while watching it draw in a separate
           | window. It got to be just a work of wonder what people came
           | up with, and then my friend got an Amiga, and those splash
           | screens... omg...
        
       | codesnik wrote:
       | I wonder how many languages have nice looking "\e" for "\u001b".
       | ruby, perl, bash, anything else?
        
       | 112233 wrote:
       | "\u001b[0m -- reset" ... what? Why SGR is not called by name,
       | while, e.g. CUU is? strange... According to which terminal or
       | standard it interperts sequences?
       | 
       | Is this tool really helpful? It does look nice! But it does not
       | help with the corneriest cases that would benefit from such tool
       | the most.
        
         | webpro wrote:
         | Got to start somewhere! Didn't see many examples to get
         | inspired by either. Here's the full table:
         | https://ansi.tools/lookup. This is my initial take on it.
         | Please bring in the corneriest cases! It's open source so bug
         | reports, RFCs and pull requests are most welcome.
        
           | 112233 wrote:
           | This thing is made out of corner cases:
           | https://www.invisible-island.net/vttest/
           | 
           | I am sure capturing it's output will provide endless source
           | of amusement and despair.
           | 
           | There are sequences from real terminal (e.g. stuff documented
           | at vt100.net), sequences from ECMA 48 and friends (most of it
           | likely never implemented), and de-facto behaviour of
           | different software. Infamous examples being original windows
           | terminal, rxvt (ugh), linux co nsole, emacs terminal.
           | 
           | Most vexing behaviour is background fill on newline,
           | incorrect characters in terminal reports, broken scroll
           | region, inability to write in bottom-right position etc.
           | 
           | This project looks fun! But it leads to endless narrow
           | abandoned places. Hopefully you will enjoy the experience!
        
           | wonger_ wrote:
           | Ghostty the terminal emulator has a cell inspector feature
           | along these same lines
        
       | gwbas1c wrote:
       | I was a teenager when BBS's were popular. I still sometimes think
       | I would enjoy writing an ANSI parser.
        
         | webpro wrote:
         | What would prevent you from starting? Could be fun :)
        
           | gwbas1c wrote:
           | Time: There's other nerd projects I'd like to do.
        
           | Xss3 wrote:
           | Probably their free time budget
        
       | taviso wrote:
       | I've used the tool sequin in the past to debug issues:
       | https://github.com/charmbracelet/sequin
       | 
       | It worked great for me, seems much easier to debug logs directly
       | in the terminal.
        
         | webpro wrote:
         | Thanks for sharing, haven't seen that one yet. Will see if I
         | can borrow ideas from it.
        
       | teddyh wrote:
       | No support for blinking text.
        
         | webpro wrote:
         | The parser has, but not the HTML renderer indeed. Using a
         | third-party lib for that currently, but noticed the limitations
         | too. Might replace it with my own!
        
           | teddyh wrote:
           | Great! Next step: torturetest.vt
        
             | webpro wrote:
             | There is https://github.com/webpro/ANSI.tools/blob/main/pac
             | kages/pars... and others
        
             | ForOldHack wrote:
             | Does it crash the tester?
             | 
             | https://invisible-island.net/ncurses/tctest.htm
        
               | webpro wrote:
               | There is some recovery in the lexer, but would love to
               | learn what would make it crash! The url you provide gives
               | a 404.
        
               | teddyh wrote:
               | s/htm/html/
               | 
               | I.e. <https://invisible-island.net/ncurses/tctest.html>
        
         | ForOldHack wrote:
         | Blinking text?
         | 
         | You do not know me, but believe me, I have a special skills
         | that I have developed for many years to deal with people like
         | you. And if I find you I will CREOL you.
        
           | teddyh wrote:
           | Bring it on. I'll feed you your own form, you insignificant
           | NUL character.
        
       | FlyingAvatar wrote:
       | I would have loved this in 1993. Not that I don't now, but I
       | would have had a real use for it then.
        
         | webpro wrote:
         | At least I tried to make it look like a 1993 website
        
       | imran9m wrote:
       | Nice. This is helpful for making jenkis ci output colorful!!
        
       ___________________________________________________________________
       (page generated 2025-07-18 23:01 UTC)