-1

I am working on a toy project. Basically, it's a set of classes and functions for making games that run in terminal. I want to use ANSI escape codes to change text color, style, background color and etc. I am trying to input shapes and colors from text files. I'm storing them in a class, which contains an array of strings (for the shapes) and a 2D array of strings (for the colors). When I hard code the colors it works fine, but when I input them from a file (using ifstream) it just outputs the codes and does nothing to the text style.

Is there a way to solve this problem without writing a separate function to process the inputted codes?

The load function:

void charbox::load(std::string path, std::string path2) {
    std::ifstream txt;
    std::string s;
    
    txt.open(path);
    if (txt.is_open() == 0) {
        std::cout << "ERROR 404, " << path << " NOT FOUND!\n";
    }

    while (std::getline(txt,s)) {
        frame.push_back(s);
    }
    txt.close();
        
    txt.open(path2);
    if (txt.is_open() == 0) {
        std::cout << "ERROR 404, " << path2 << " NOT FOUND!\n";
    }
    
    std::vector <std::string> v(frame[0].size(), ""); 
    color.resize(frame.size(), v);
    
    for (int i = 0, height = frame.size(); i < height; i++) {
        for (int j = 0, width = frame[i].size(); j < width; j++) {
            txt >> color[i][j];
        }
    }
    txt.close();
    
}

The class:

class charbox {
    public:
                
        std::vector <std::string> frame;
        std::vector <std::vector <std::string>> color;

        void load(std::string path, std::string path2);
        charbox(int p_width, int p_height);
        charbox(){};
    
    private:
};

When I output:

std::cout << <some object>.color[<some index>][<some index>] << "test\n";

I want the color of the "test" to be changed based on the input, but it just outputs the code in form of plain text.

An example of files in path and path2:

path contains:

[][]
[][]

path2 contains:

\033[1;31;41m \033[1;31;41m \033[1;31;41m \033[1;31;41m
\033[1;31;41m \033[1;31;41m \033[1;31;41m \033[1;31;41m

Thanks in advance!

P.S. I am running Linux (windows-specific solutions won't work for me).

  • C and C++ are different languages. Show some [mre] in your question (some code with a `main` and example input and desired output). I am able to output ANSI escape code in the [RefPerSys](http://refpersys.org/) open source C++ project; take inspiration from its source code – Basile Starynkevitch Feb 14 '21 at 06:55
  • 1
    Impossible to say without having a [mcve] or any piece of code – Sami Kuhmonen Feb 14 '21 at 06:55
  • Create an, e.g. `ANSI_colors.h` header with the needed color class, etc.. and include the information instead of reading it from a file. – David C. Rankin Feb 14 '21 at 06:57
  • "I am trying to input shapes and colors from text files" - what does that mean, textual files don't have shapes and colors! You could use [cat(1)](https://man7.org/linux/man-pages/man1/cat.1.html) to display them! Please [edit](https://stackoverflow.com/posts/66193114/edit) your question to improve it. Add some code in it. Also explain why you don't want to write a separate function! – Basile Starynkevitch Feb 14 '21 at 06:58
  • **The [fish](http://fishsshell.com/) shell is for Linux**, open source, in C++, and can show colored characters. **Study its source code for inspiration** – Basile Starynkevitch Feb 14 '21 at 07:01
  • 1
    Seems like you made some mistake in the way you read these codes from a file. But without seeing any of your code how can anyone know what that mistake is? To answer the question you actually ask, yes it is possible. – john Feb 14 '21 at 07:02
  • @SamiKuhmonen I added an example. – Luka Rapava Feb 14 '21 at 07:13
  • @BasileStarynkevitch By shapes I mean ASCII art. Also, I added an example of code. – Luka Rapava Feb 14 '21 at 07:14
  • What is the actual contents of the `path2` file? If it's printable then please include some examples. Also remember that `txt >> color[i][j]` will read *space-delimited* "words". If you have special characters in the file (like the actual escape `0x1b` character) it might need some extra processing to read. – Some programmer dude Feb 14 '21 at 07:17
  • @Someprogrammerdude > will read space-delimited "words" That's what I'm counting on. (also, edited the question) – Luka Rapava Feb 14 '21 at 07:23
  • @LukaRapava Seems like you need to interpret your codes, `\033` is a sequence of four characters, a backslash followed by three digits, it's not the escape character. – john Feb 14 '21 at 07:25
  • @john `\033` [is an escape character](https://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal), it's just my program recognizing it as a string of characters. – Luka Rapava Feb 14 '21 at 07:29
  • @LukaRapava You don;t understand how escaping works in C++. I'll write up an answer. – john Feb 14 '21 at 07:30
  • @LukaRapava See answer below – john Feb 14 '21 at 07:43
  • Escape codes like `\033` are parsed by the *compiler* in literal strings or characters. There is no such parsing at run-time. – Some programmer dude Feb 14 '21 at 07:59

1 Answers1

1

The problem is your interpretation of escape sequences. If you write \033 in a string literal then that will be interpreted as the escape character (ASCII 27). So

std::string seq = "\033[1;31;41m";

is a string of ten characters because the compiler interprets \033 as a single character.

But if you put the same token in a file and read it then there is no special interpretation and it will be understood as thirteen characters starting with a backslash, instead of ten characters starting with an escape.

What I suggest you do is write the code to replace the \033 sequence with the escape character. Something like this

{
    txt >> color[i][j];
    size_t pos = color[i][j].find("\\033");  // look for \033
    if (pos != std::string::npos)            // if found
        color[i][j].replace(pos, 4, "\033"); // replace with ESC
}

VERY IMPORTANT

Double backslash \\ in the find and single backslash \ in the replace

john
  • 85,011
  • 4
  • 57
  • 81