Search code examples
rcrayon

How can I get an accurate character count when using crayon-formatted strings?


crayon is a package for adding color to printed output, e.g.

library(crayon)
message(red('blue'), green('green'), blue('red'))

sample colored text

However, nchar used on its output is wrong:

# should be 4 characters
nchar(red('1234'))
# [1] 14

I tried all the different type= options for nchar, to no avail -- how can I get R to tell me the correct number of characters in this string (4)?


Solution

  • First, note that the output of red is just a plain string:

    r = red('1234')
    dput(r)
    # "\033[31m1234\033[39m"
    class(r)
    # [1] "character"
    

    The garbled-looking parts (\033[31m and \033[39m) are what are known as ANSI escape codes -- you can think of it here as signalling "start red" and "stop red". While the program that converts the character object into printed characters in your terminal is aware of and translates these, nchar is not. nchar in fact sees 14 characters:

    strsplit(r, NULL)[[1L]]
    #  [1] "\033" "["    "3"    "1"    "m"    "1"    "2"    "3"    "4"    "\033" "["   
    # [12] "3"    "9"    "m"
    

    To get the 4 we're after, crayon provides a helper function: col_nchar which first applies strip_style to get rid of the ANSI markup, then runs plain nchar:

    strip_style(r)
    # [1] "1234"
    col_nchar(r)
    # [1] 4
    

    So you can either do nchar(strip_style(x)) yourself if you find that more readable, or use col_nchar.