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