When you have non-fixed width characters (such as \t) in a string , or escape codes, such as those for ANSI color (such as \1xb[31m), these characters add to the .length() of an std::string, but do not add to the displayed length when printed.
Is there any way in C++ to get the displayed width of a string in *nix?
For instance:
displayed_width("a\tb") would be 4 if the displayed tab width is 2
displayed_width("\1xb[33mGREEN") would be 5
                Most commonly, a tab asks the terminal program to move the cursor to a column that's a multiple of 8, though many terminal programs let you configure that. With such behaviour, how much width a tab actually adds depends on where the cursor was beforehand relative to the tab stops. So, simply knowing the string content is not enough to calculate a printable width without some assumption or insight regarding prior cursor placement and tab stops.
Non-printable codes also vary per terminal type, though if you only need ANSI colour then that's pretty easy.  You can move along the string counting characters; when you see an ESCAPE skip through to the terminating m.  Something like (untested):
int displayed_width(const char* p)
{
    int result = 0;
    for ( ; *p; ++p)
    {
        if (p[0] == '\e' && p[1] == '[')
            while (*p != 'm')
                if (*p)
                    ++p;
                else
                    throw std::runtime_error("string terminates inside ANSI colour sequence");
        else
            ++result;
    }
    return result;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With