Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get displayed width of a string?

Tags:

c++

unix

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
like image 287
Jamie Wong Avatar asked Jul 20 '11 00:07

Jamie Wong


1 Answers

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;
}
like image 118
user433534 Avatar answered Oct 03 '22 17:10

user433534