1# nocov start 2keep_empty <- function(fun) { 3 function(x) { 4 ret <- rep_along(x, "") 5 update <- which(is.na(x) | x != "") 6 ret[update] <- fun(x[update]) 7 ret 8 } 9} 10# nocov end 11 12#' Styling helpers 13#' 14#' Functions that allow implementers of formatters for custom data types to 15#' maintain a consistent style with the default data types. 16#' 17#' `style_subtle()` is affected by the `subtle` [option][pillar_options]. 18#' 19#' @param x The character vector to style. 20#' @export 21#' @seealso [pillar_options] for a list of options 22#' @examples 23#' style_subtle("text") 24style_subtle <- keep_empty(function(x) { 25 force(x) 26 if (isTRUE(get_pillar_option_subtle())) { 27 crayon_grey_0.6(x) 28 } else { 29 x 30 } 31}) 32 33#' @rdname style_subtle 34#' @details 35#' `style_subtle_num()` is affected by the 36#' `subtle_num` [option][pillar_options], 37#' which is `FALSE` by default. 38#' 39#' @export 40#' @examples 41#' style_subtle_num(0.01 * 1:3, c(TRUE, FALSE, TRUE)) 42style_subtle_num <- function(x, negative) { 43 if (isTRUE(get_pillar_option_subtle_num())) { 44 style_subtle(x) 45 } else { 46 ifelse(negative, style_neg(x), x) 47 } 48} 49 50style_hint <- keep_empty(function(x) { 51 force(x) 52 if (isTRUE(get_pillar_option_subtle())) { 53 crayon_grey_0.8(x) 54 } else { 55 x 56 } 57}) 58 59style_spark_na <- function(x) { 60 crayon_yellow(x) 61} 62 63#' @details 64#' `style_bold()` is affected by the `bold` [option][pillar_options], 65#' which is `FALSE` by default. 66#' 67#' @rdname style_subtle 68#' @export 69#' @examples 70#' style_bold("Petal.Width") 71style_bold <- keep_empty(function(x) { 72 if (isTRUE(get_pillar_option_bold())) { 73 crayon_bold(x) 74 } else { 75 x 76 } 77}) 78 79#' @rdname style_subtle 80#' @export 81#' @examples 82#' style_na("NA") 83style_na <- function(x) { 84 crayon_red(x) 85} 86 87#' @details 88#' `style_neg()` is affected by the `pillar.neg` [option][pillar_options]. 89#' 90#' @rdname style_subtle 91#' @export 92#' @examples 93#' style_neg("123") 94style_neg <- keep_empty(function(x) { 95 if (isTRUE(get_pillar_option_neg())) { 96 crayon_red(x) 97 } else { 98 x 99 } 100}) 101 102pillar_na <- function(use_brackets_if_no_color = FALSE) { 103 if (use_brackets_if_no_color && !has_color()) { 104 "<NA>" 105 } else { 106 style_na("NA") 107 } 108} 109 110style_list <- function(x) { 111 style_subtle(x) 112} 113 114# Only check if we have color support once per session 115num_colors <- local({ 116 num_colors <- NULL 117 function(forget = FALSE) { 118 if (is.null(num_colors) || forget) { 119 num_colors <<- crayon::num_colors(forget = forget) 120 } 121 num_colors 122 } 123}) 124 125has_color <- function() { 126 num_colors() > 1 127} 128 129# nocov start 130# Crayon functions call crayon::num_colors() every call 131make_style_fast <- function(...) { 132 # Force has_color to be true when making styles 133 # Use prefix to avoid problems with empty NAMESPACE 134 rlang::local_options(cli.num_colors = 16L) 135 136 style_16 <- crayon::make_style(..., colors = 16) 137 start_16 <- stats::start(style_16) 138 finish_16 <- crayon::finish(style_16) 139 140 style_256 <- crayon::make_style(..., colors = 256) 141 start_256 <- stats::start(style_256) 142 finish_256 <- crayon::finish(style_256) 143 144 function(...) { 145 if (has_color()) { 146 colors <- num_colors() 147 if (colors >= 256) { 148 paste0(start_256, ..., finish_256) 149 } else { 150 paste0(start_16, ..., finish_16) 151 } 152 } else { 153 paste0(...) 154 } 155 } 156} 157 158# Placeholders, assigned in .onLoad() 159crayon_underline <- function(...) {} 160crayon_italic <- function(...) {} 161crayon_red <- function(...) {} 162crayon_yellow <- function(...) {} 163crayon_bold <- function(...) {} 164crayon_grey_0.6 <- function(...) {} 165crayon_grey_0.8 <- function(...) {} 166 167assign_crayon_styles <- function() { 168 crayon_underline <<- make_style_fast("underline") 169 crayon_italic <<- make_style_fast("italic") 170 crayon_red <<- make_style_fast("red") 171 crayon_yellow <<- make_style_fast("yellow") 172 crayon_bold <<- make_style_fast("bold") 173 crayon_grey_0.6 <<- make_style_fast(grDevices::grey(0.6), grey = TRUE) 174 crayon_grey_0.8 <<- make_style_fast(grDevices::grey(0.8), grey = TRUE) 175} 176# nocov end 177