Search code examples
c++cterminalansi-escape

How to convert printf xterm code to ostringstream?


PROBLEM

I am trying to turn some C printf code into std::ostringstream, but I am having trouble with hex/terminal encodings. I think maybe, the sequence \x1b[48;5; needs to be translated at once, but I'm not sure what the equivalent is, in C++.

Bad Result, Partial (C++)

Color cube, 6x6x6:
1b[48;5;10m  1b[48;5;10m  1b[48;5;11m  1b[48;5;11m  1b[48;5;12m  1b[48;5;12m  1b[48;5;13m  1b[48;5;13m  1b[48;5;14m  1b[48;5;14m  1b[48;5;15m  1b[48;5;15m  1b[0m 1b[48;5;34m  1b[48;5;34m  1b[48;5;35m  

Good Result, xterm (C)

enter image description here

C code

void Color_Cube()
{
  for (unsigned green=0; green<6; ++green)
  {
    for (unsigned red=0; red<6; ++red)
    {
      for (unsigned blue=0; blue<6; ++blue)
      {
        unsigned color = 16 + (red * 36) + (green * 6) + blue;
        printf( "\x1b[48;5;%dm  ", color );
      }
      printf( "\x1b[0m " );
    }
    printf( "\n" );
  }
}

Failed C++ Code

void Color_Cube_cpp()
{
  std::ostringstream  oss;
  for (unsigned green=0; green<6; ++green)
  {
    for (unsigned red=0; red<6; ++red)
    {
      for (unsigned blue=0; blue<6; ++blue)
      {
        unsigned color = 16 + (red * 36) + (green * 6) + blue;
        oss << std::hex << static_cast<int>(0x1b) << std::dec
          << "[48;5;" << color << "m  ";
      }
      oss << std::hex << static_cast<int>(0x1b) << std::dec << "[0m ";
    }
    oss << "\n";
  }
  std::cerr << oss.str() << "\n";
}

Solution

  • You are almost there. You need to stream the escape character '\x1b' instead of integer 0x1b:

    #include <sstream>
    #include <iostream>
    
    void Color_Cube_cpp()
    {
      std::ostringstream  oss;
      for (unsigned green=0; green<6; ++green)
      {
        for (unsigned red=0; red<6; ++red)
        {
          for (unsigned blue=0; blue<6; ++blue)
          {
            unsigned color = 16 + (red * 36) + (green * 6) + blue;
              oss << "\x1b[48;5;" << color << "m  ";
          }
          oss << "\x1b[0m ";
        }
        oss << "\n";
      }
      std::cerr << oss.str() << "\n";
    }