Skip to content

Instantly share code, notes, and snippets.

@kar9222
Last active March 31, 2024 02:32
Show Gist options
  • Save kar9222/0e1130c15bfaba3a71f0cf6d1d08931f to your computer and use it in GitHub Desktop.
Save kar9222/0e1130c15bfaba3a71f0cf6d1d08931f to your computer and use it in GitHub Desktop.
My {colorout}

My {colorout}

First of all, thank you jalvesaq for the great package! 🙏🙏

If you'd like to colorize R terminal output you can use {jalvesaq/colorout}

I customize extra color patterns for

Click to enlarge image

Imgur

Usage

Simply install with remotes::install_github('jalvesaq/colorout'). And it just works out of the box.

Feel free to use these in your .Rprofile

I think it's good idea to generate some popular premade themes for the community and they can further customize them with hex color codes with some helpers together with this awesome package.

NOTE

  • The customized patterns are not perfect as the package has limited regex support (...only two types of regular expression...) (see ?colorout::addPattern) (for performance, i believe. And it's written in C) and this is my first attempt for customizing the patterns (subject to change).
  • To customize patterns, see ?colorout::addPattern
  • For more info, see {jalvesaq/colorout}

Theme

  • Premade theme
    • Popular themes like Nord, Monokai
    • Feel free to ping me for additional themes & I'll try my best to generate codes for you, when I'm free 🤣
  • Custom theme
    • Edit premade themes or customize your brand new theme
    • Don't be shy to share with #Rstats community 😎

Premade theme

Pick your theme and copy the codes at the collapsible code section and put them in your .Rprofile

NOTE Focus on the terminal output, as the terminal input is controlled by my terminal.

Put @ .Rprofile

# General ---------------------------------------- 

colorout::setOutputColors(
  
  index    = '\x1b[38;2;76;86;106m',
  normal   = '\x1b[38;2;216;222;233m',

  number   = '\x1b[38;2;236;239;244m',
  negnum   = '\x1b[38;2;180;142;173m',
  zero     = '\x1b[38;2;136;192;208m', zero.limit = 0.01,
  infinite = '\x1b[38;2;236;239;244m',

  string   = '\x1b[38;2;235;203;139m',
  date     = '\x1b[38;2;236;239;244m',
  const    = '\x1b[38;2;136;192;208m',
  
  true     = '\x1b[38;2;163;190;140m',
  false    = '\x1b[38;2;191;97;106m',

  warn     = '\x1b[38;2;235;203;139m',
  stderror = '\x1b[38;2;191;97;106m', error = '\x1b[38;2;191;97;106m',

  verbose  = FALSE
)

# Custom patterns --------------------------------

# NOTE Do not copy all. Pick what you use/like.

# _ {data.table} ---------------------------------

colorout::addPattern('[0-9]*:',  '\x1b[38;2;143;188;187m')  # Row num
colorout::addPattern('---',      '\x1b[38;2;76;86;106m')    # Row splitter 
colorout::addPattern('<[A-z]*>', '\x1b[38;2;143;188;187m')  # Col class 

# _ `str` ----------------------------------------

# List
colorout::addPattern('List of [0-9]*', '\x1b[38;2;235;203;139;48;2;76;86;106;1m')
# Class
colorout::addPattern(' num ',          '\x1b[38;2;143;188;187m')
colorout::addPattern(' int ',          '\x1b[38;2;143;188;187m')
colorout::addPattern(' dbl ',          '\x1b[38;2;143;188;187m')
colorout::addPattern(' chr ',          '\x1b[38;2;143;188;187m')
colorout::addPattern(' logi ',         '\x1b[38;2;143;188;187m')
colorout::addPattern(' lglc ',         '\x1b[38;2;143;188;187m')
colorout::addPattern(' Factor ',       '\x1b[38;2;143;188;187m')
colorout::addPattern(' Ord.factor ',   '\x1b[38;2;143;188;187m')
colorout::addPattern(' POSIXct, ',     '\x1b[38;2;143;188;187m')
colorout::addPattern('function ',      '\x1b[38;2;143;188;187m')
colorout::addPattern(' lgcl ',         '\x1b[38;2;143;188;187m')
colorout::addPattern(' cplx ',         '\x1b[38;2;143;188;187m')
# Misc
colorout::addPattern('$ ',             '\x1b[38;2;76;86;106m')

# _ `str`, {mlr3} --------------------------------

# R6 field name
colorout::addPattern('* [A-z]*:',                      '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]*:",               '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]*:",        '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]* [A-z]*:", '\x1b[38;2;235;203;139m')
colorout::addPattern('[A-z]* ([0-9]*):',               '\x1b[38;2;235;203;139m')  # `- dbl (10):`
colorout::addPattern('- [A-z]* ([0-9]*):',             '\x1b[38;2;235;203;139m')  # `- dbl (10):`
# So on...

...

Imgur

Put @ .Rprofile

colorout::setOutputColors(
  
  index    = '\x1b[38;2;76;86;106m',
  normal   = '\x1b[38;2;236;239;244m',

  number   = '\x1b[38;2;236;239;244m',
  negnum   = '\x1b[38;2;253;151;31m',
  zero     = '\x1b[38;2;102;217;239m', zero.limit = 0.01,
  infinite = '\x1b[38;2;236;239;244m',

  string   = '\x1b[38;2;230;219;116m',
  date     = '\x1b[38;2;236;239;244m',
  const    = '\x1b[38;2;253;151;31m',
  
  true     = '\x1b[38;2;166;226;46m',
  false    = '\x1b[38;2;249;38;114m',

  warn     = '\x1b[38;2;230;159;102',
  stderror = '\x1b[38;2;249;38;114m', error = '\x1b[38;2;249;38;114m',

  verbose  = FALSE
)

# NOTE Do not copy all. Pick what you use/like.

# _ {data.table} ---------------------------------

colorout::addPattern('[0-9]*:',  '\x1b[38;2;117;113;94m')  # Row num
colorout::addPattern('---',      '\x1b[38;2;117;113;94m')  # Row splitter 
colorout::addPattern('<[A-z]*>', '\x1b[38;2;117;113;94m')  # Col class 

# _ `str` ----------------------------------------

# List
colorout::addPattern('List of [0-9]*', '\x1b[38;2;230;219;116;48;2;76;86;106;1m')
# Class
colorout::addPattern(' num ',          '\x1b[38;2;117;113;94m')
colorout::addPattern(' int ',          '\x1b[38;2;117;113;94m')
colorout::addPattern(' dbl ',          '\x1b[38;2;117;113;94m')
colorout::addPattern(' chr ',          '\x1b[38;2;117;113;94m')
colorout::addPattern(' logi ',         '\x1b[38;2;117;113;94m')
colorout::addPattern(' lglc ',         '\x1b[38;2;117;113;94m')
colorout::addPattern(' Factor ',       '\x1b[38;2;117;113;94m')
colorout::addPattern(' Ord.factor ',   '\x1b[38;2;117;113;94m')
colorout::addPattern(' POSIXct, ',     '\x1b[38;2;117;113;94m')
colorout::addPattern('function ',      '\x1b[38;2;117;113;94m')
colorout::addPattern(' lgcl ',         '\x1b[38;2;117;113;94m')
colorout::addPattern(' cplx ',         '\x1b[38;2;117;113;94m')
# Misc
colorout::addPattern('$ ',             '\x1b[38;2;76;86;106m')

# _ `str`, {mlr3} --------------------------------

# R6 field name
colorout::addPattern('* [A-z]*:',                      '\x1b[38;2;174;129;255m')
colorout::addPattern("* [A-z]* [A-z]*:",               '\x1b[38;2;174;129;255m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]*:",        '\x1b[38;2;174;129;255m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]* [A-z]*:", '\x1b[38;2;174;129;255m')
colorout::addPattern('[A-z]* ([0-9]*):',               '\x1b[38;2;174;129;255m')  # `- dbl (10):`
colorout::addPattern('- [A-z]* ([0-9]*):',             '\x1b[38;2;174;129;255m')  # `- dbl (10):`
# So on...

...

Imgur

Custom theme

colorout::setOutputColors can be used for full customization without this helper. For more info, see ?colorout::setOutputColors. If you wish to generate ansi color codes with hex color codes, you can use this helper, for convenience. It's not recommended to put these helpers in .Rprofile. Simply use them separately for generating inputs for colorout::setOutputColors. If case you'd use them in .Rprofile, make sure to get rid of all the garbage.

Manually get colors in hex format from your favorite theme (ie Nord) and fill them in named list.

Let's do an example with Nord theme. First, get colors from Nord. Then...

Helper

#' Helper for generating ansi color codes with hex color codes.
#'
#' After generating ansi color codes, feed input to `colorout::setOutputColors`.
#'
#' @param fg Foreground color in hex format (ie '#000000'). Leave blank for default.
#' @param bg Background color in hex format (ie '#000000'). Leave blank for default.
#' @param fo Formatting (see details)
#' 
#' @details
#' Value	Formating
#' 0	No formating
#' 1	Bold or bright
#' 2	Faint
#' 3	Italic or inverse
#' 4	Underline
#' 5	Blink slowly
#' 6	Blink quickly
#' 7	Invert

to_ansi <- function(col, fg = '', bg = '', fo = '') {

  escape <- '\\x1b['
  
  if (fg != '') fg <- {
    rgb_fg <- col2rgb(fg)
    paste0("38;2;", rgb_fg[1], ";", rgb_fg[2], ";", rgb_fg[3])
  }
  if (bg != '') bg <- {
    rgb_bg <- col2rgb(bg)
    paste0(";48;2;", rgb_bg[1], ";", rgb_bg[2], ";", rgb_bg[3])
  }
  fo <- if (fo != '') paste0(';', fo)

  # Use `cat`, not `paste0`, for correctly printing escape char '\x1b['
  cat(col, ': ', escape, fg, bg, fo, 'm', '\n', sep = '')
}

Either

  • generate invididual style one-by-one
    • Useful for editing one/a few colors of premade themes
  • or generate all styles
    • Useful for creating brand new themes

Generate invididual style

to_ansi('white',            "#ECEFF4")                 # white foreground
to_ansi('white_black',      "#ECEFF4", "#4C566A")      # white foreground, black background
to_ansi('white_black_bold', "#ECEFF4", "#4C566A",  1)  # white foreground, black background, bold text
# white:            \x1b[38;2;236;239;244m
# white_black:      \x1b[38;2;236;239;244;48;2;76;86;106m
# white_black_bold: \x1b[38;2;236;239;244;48;2;76;86;106;1m

Then input the color codes (ie \x1b[38;2;236;239;244m) to colorout::setOutputColors

  • manually
  • assign to variables with your R skills & DO NOT forget to rm them to avoid contaminating your environments.

or...

Generate all styles

# Fill in color names, foreground colors, background colors and formatting (ie bold/italic). For default, leave it blank.
theme <- list(
  colors     = c('white',   'black',   'snow',    'turquoise', 'dark_red', 'dark_green', 'yellow',  'green',   'red',     'yellow_bold'),
  foreground = c("#ECEFF4", "#4C566A", '#D8DEE9', '#88C0D0',   "#B48EAD",  "#8FBCBB",    "#EBCB8B", "#A3BE8C", "#BF616A", "#EBCB8B"),
  background = c("",        "",        "",        "",          "",         "",           "",        "",        "",        ""),
  formatting = c("",        "",        "",        "",          "",         "",           "",        "",        "",        1)
)

# - Manually copy & paste color codes (in character type) to `colorout::setOutputColors`. It's okay because you only set it once-and-for-all. Otherwise, you can assign the colors to variables and remove them after calling `colorout::setOutputColors`
# - or assign them to variables AND make sure to remove them after calling `colorout::setOutputColors` because you don't want them to contaminate your environments.
invisible( mapply(to_ansi, theme[[1]], theme[[2]], theme[[3]], theme[[4]]) )

# white:       \x1b[38;2;236;239;244m
# black:       \x1b[38;2;76;86;106m
# snow:        \x1b[38;2;216;222;233m
# turquoise:   \x1b[38;2;136;192;208m
# dark_red:    \x1b[38;2;180;142;173m
# dark_green:  \x1b[38;2;143;188;187m
# yellow:      \x1b[38;2;235;203;139m
# green:       \x1b[38;2;163;190;140m
# red:         \x1b[38;2;191;97;106m
# yellow_bold: \x1b[38;2;235;203;139;1m

# General ---------------------------------------- 

colorout::setOutputColors(
  
  index    = '\x1b[38;2;76;86;106m',
  normal   = '\x1b[38;2;216;222;233m',

  number   = '\x1b[38;2;236;239;244m',
  negnum   = '\x1b[38;2;180;142;173m',
  zero     = '\x1b[38;2;136;192;208m', zero.limit = 0.01,
  infinite = '\x1b[38;2;236;239;244m',

  string   = '\x1b[38;2;235;203;139m',
  date     = '\x1b[38;2;236;239;244m',
  const    = '\x1b[38;2;136;192;208m',
  
  true     = '\x1b[38;2;163;190;140m',
  false    = '\x1b[38;2;191;97;106m',

  warn     = '\x1b[38;2;235;203;139m',
  stderror = '\x1b[38;2;191;97;106m', error = '\x1b[38;2;191;97;106m',

  verbose  = FALSE
)

# Custom patterns --------------------------------

# NOTE Do not copy all. Pick what you use/like.

# _ {data.table} ---------------------------------

colorout::addPattern('[0-9]*:',  '\x1b[38;2;143;188;187m')  # Row num
colorout::addPattern('---',      '\x1b[38;2;76;86;106m')    # Row splitter 
colorout::addPattern('<[A-z]*>', '\x1b[38;2;143;188;187m')  # Col class 

# _ `str` ----------------------------------------

# Class
colorout::addPattern(' num ',        '\x1b[38;2;143;188;187m')
colorout::addPattern(' int ',        '\x1b[38;2;143;188;187m')
colorout::addPattern(' chr ',        '\x1b[38;2;143;188;187m')
colorout::addPattern(' Factor ',     '\x1b[38;2;143;188;187m')
colorout::addPattern(' Ord.factor ', '\x1b[38;2;143;188;187m')
colorout::addPattern(' logi ',       '\x1b[38;2;143;188;187m')
colorout::addPattern('function ',    '\x1b[38;2;143;188;187m')
colorout::addPattern(' dbl ',        '\x1b[38;2;143;188;187m')
colorout::addPattern(' lgcl ',       '\x1b[38;2;143;188;187m')
colorout::addPattern(' cplx ',       '\x1b[38;2;143;188;187m')
# Misc
colorout::addPattern('$ ',           '\x1b[38;2;76;86;106m')

# _ `str`, {mlr3} --------------------------------

# R6 field name
colorout::addPattern('* [A-z]*:',                      '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]*:",               '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]*:",        '\x1b[38;2;235;203;139m')
colorout::addPattern("* [A-z]* [A-z]* [A-z]* [A-z]*:", '\x1b[38;2;235;203;139m')
# So on...

# Clean up
rm(theme, to_ansi)

My .Rprofile

My .Rprofile has slightly different styles than above and it works slightly better with my color codes. For example, I prefer minimalistic styles & colors and, it's meant for differentiating things that are supposed to be differentiated. Feel free to use it.

NOTE

  • Codes below works out of the box but the colors do not match the image shown above because...in short...my terminal emulator (Tmux with VSCode. Thanks Kun Ren for introducing me to Tmux & radian) has internal mapping of color codes. Simply learn how to customize colors with ?colorout::setOutputColors
#  NOTE 'whitespaces'

# General 

colorout::setOutputColors(
  
  index    = 8,
  normal   = 15,  # or 10

  number   = 15,
  negnum   = 2,
  zero     = 7, zero.limit = 0.01,
  infinite = '\x1b[38;2;178;227;229m',

  string   = 15,
  date     = 10,
  const    = 7,

  true     = '\x1b[38;2;178;227;229m',
  false    = '\x1b[38;2;255;161;170m',

  warn     = '\x1b[38;2;228;202;175m',
  stderror = 3, error = 3,

  verbose  = FALSE
)

# General

colorout::addPattern('[[[0-9]*]]', 4)

# {data.table}

colorout::addPattern('[0-9]*:',    4)  # row num
colorout::addPattern('---',        0)  # row splitter
colorout::addPattern('<[A-z]*>',   4)  # col class

# `str`

# List
colorout::addPattern('List of [0-9]*',     c(1, 5, 15))
# Var
# colorout::addPattern('$ [A-z]*:',          10)
# colorout::addPattern('$ [A-z]* [A-z]*:',   10)
# colorout::addPattern('$ [A-z]* *:',        10)
# colorout::addPattern('$ [A-z]*.[A-z]* *:', 10)
colorout::addPattern('[A-z]*:',          10)
colorout::addPattern('[A-z]* [A-z]*:',   10)
colorout::addPattern('[A-z]* *:',        10)
colorout::addPattern('[A-z]*.[A-z]* *:', 10)
# Class
colorout::addPattern(' num ',              4)
colorout::addPattern(' int ',              4)
# colorout::addPattern(' dbl ',              4)
colorout::addPattern(' chr ',              4)
colorout::addPattern(' logi ',              4)
colorout::addPattern(' lgcl ',             4)
colorout::addPattern(' Factor ',           4)
colorout::addPattern(' Ord.factor ',       4)
colorout::addPattern(' POSIXct, ',         4)
colorout::addPattern('function ',          4)
# colorout::addPattern(' cplx ',           4)
# Misc
colorout::addPattern('$',               8)
# colorout::addPattern(': ',               '\x1b[38;2;40;44;53m')

# `str`, {mlr3}

# R6 field name
# colorout::addPattern('* [A-z]*:',                      10)
# colorout::addPattern("* [A-z]* [A-z]*:",               10)
# colorout::addPattern("* [A-z]* [A-z]* [A-z]*:",        10)
# colorout::addPattern("* [A-z]* [A-z]* [A-z]* [A-z]*:", 10)
colorout::addPattern('[A-z]*:',                      10)
colorout::addPattern("[A-z]* [A-z]*:",               10)
colorout::addPattern("[A-z]* [A-z]* [A-z]*:",        10)
colorout::addPattern("[A-z]* [A-z]* [A-z]* [A-z]*:", 10)
colorout::addPattern('[A-z]* ([0-9]*):',               10)  # `- dbl (10):`
colorout::addPattern('- [A-z]* ([0-9]*):',             10)  # `- dbl (10):`
# mlr3 misc
colorout::addPattern('* ',                           0)

Test

Same codes used in screenshots for color validation, if needed.

# {data.table} -----------------------------------

data.table::data.table(
    postive_negative_and_near_zero = sample(c(1, - 1, .005), 200, replace = TRUE),
    true_false_NA                  = sample(c(TRUE, FALSE, NA), 200, replace = TRUE))

# {mlr3} -----------------------------------------

library(mlr3)
task <- tsk('iris')
learner <- lrn('classif.rpart')
learner$train(task, row_ids = 1:120)
learner

mlr3::msr("classif.auc")

# base R `str` -----------------------------------

str(iris)
str(diamonds)

str(list(col_a = rnorm(100), list(
  col_b = "This is string...",
  col_c = c(T, F, T, T, F),
  list(col_d = sum)
)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment