-1

I'm struggling with dealing with Ansi code strings. I'm getting the [32m, [37m, [K etc chars.

Is there a quicker way to eliminate/strip the ansi codes from the strings I get rather than doing it with the loop through chars searching for the beginning and end points of the ansi codes?

I know the declaration is something like this: #27'['#x';'#y';'#z'm'; where x, y, z... are the ANSI codes. So I assume I should be searching for #27 until I find "m;"

Are there any already made functions to achieve what I want? My search returned nothing except this article. Thanks

That Marc
  • 1,074
  • 3
  • 17
  • 38
  • Telnet has no concept of colors. You have to manually parse the strings you are receiving. – Remy Lebeau Apr 01 '16 at 17:09
  • I actually didn't mention telnet in either title, question nor tags. I just explained the case where I'm needing the Ansi code decoder... ;) – That Marc Apr 01 '16 at 17:11
  • "*I built a very simple **telnet** client to connect to specific device which accepts **telnet** connections*" – Remy Lebeau Apr 01 '16 at 17:13
  • *... -> "but it works with ansi color encoded strings.... So I'm getting the xyz chars inside the telnet buffer.... Is there a quicker way to eliminate/strip the ansi codes from the strings I get (or buffer directly)..."* ;) As said, I just explained what I'm doing, so it's clear where is the code. Also, just because maybe Telnet component could have some parser inside that I'm not aware of, so.. – That Marc Apr 01 '16 at 17:16
  • Ps: Just edited the question to leave out the Telnet part, if that matters that much. – That Marc Apr 01 '16 at 17:21

1 Answers1

2

You can treat this protocol very fast with code like this (simplest finite state machine):

var
  s: AnsiString;
  i: integer;
  InColorCode: Boolean;
begin
  s := 'test'#27'['#5';'#30';'#47'm colored text';

  InColorCode := False;

  for i := 1 to Length(s) do
    if InColorCode then
      case s[i] of
          #0: TextAttrib = Normal;
          ...
          #47: TextBG := White;
          'm': InColorCode := false;
        else;
         // I do nothing here for `;`, '[' and other chars.
         // treat them if necessary

      end;
     else
       if s[i] = #27 then
         InColorCode := True
       else
         output char with current attributes

Clearing string from ESC-codes:

procedure StripEscCode(var s: AnsiString);
const
  StartChar: AnsiChar = #27;
  EndChar: AnsiChar = 'm';
var
  i, cnt: integer;
  InEsc: Boolean;
begin
  Cnt := 0;
  InEsc := False;
  for i := 1 to Length(s) do
    if InEsc then begin
      InEsc := s[i] <> EndChar;
      Inc(cnt)
    end
    else begin
      InEsc := s[i] = StartChar;
      if InEsc then
        Inc(cnt)
      else
      s[i - cnt] :=s[i];
    end;
  setLength(s, Length(s) - cnt);
end;
MBo
  • 66,413
  • 3
  • 45
  • 68
  • I'm actually trying to completely remove everything from #27 to the m sign, aka all ansi codes, to get pure readable string. And single string can have multiple codes (aka color green, red and blue, for different words in it) so it needs to loop through it until it's done removing the ansi codes. Would you be kind enough to edit the answer to achieve that? Big thanks! – That Marc Apr 01 '16 at 18:45
  • 1
    Added simple routine for Esc/m case – MBo Apr 01 '16 at 18:59