r-lib / cli
1

2
cray_wrapper_fun <- function(style) {
3 1
  style
4 1
  fun <- function(...) {
5 1
    txt <- paste0(...)
6 1
    structure(style(txt), class = "ansi_string")
7
  }
8 1
  class(fun) <- "ansi_style"
9 1
  attr(fun, "crayon_style") <- style
10 1
  fun
11
}
12

13
cray_wrapper <- function(name) {
14 0
  cray_wrapper_fun(asNamespace("crayon")[[name]])
15
}
16

17
#' @export
18

19
print.ansi_string <- function(x, ...) {
20 0
  cat("<ansi_string>\n")
21 0
  if (length(x)) {
22 0
    cat(format(paste0("[", seq_along(x), "] ", format(x))), sep = "\n")
23
  }
24 0
  invisible(x)
25
}
26

27
#' Create a new ANSI style
28
#'
29
#' Create a function that can be used to add ANSI styles to text.
30
#' All arguments are passed to [crayon::make_style()], but see the
31
#' Details below.
32
#'
33
#' @param ... The style to create. See details and examples below.
34
#' @param bg Whether the color applies to the background.
35
#' @param grey Whether to specifically create a grey color.
36
#'   This flag is included, because ANSI 256 has a finer color scale
37
#'   for greys, then the usual 0:5 scale for red, green and blue components.
38
#'   It is only used for RGB color specifications (either numerically
39
#'   or via a hexa string), and it is ignored on eigth color ANSI
40
#'   terminals.
41
#' @param colors Number of colors, detected automatically
42
#'   by default.
43
#' @return A function that can be used to color (style) strings.
44
#'
45
#' @details
46
#' The styles (elements of `...`) can be any of the
47
#' following:
48
#' * An R color name, see [grDevices::colors()].
49
#' * A 6- or 8-digit hexa color string, e.g. `#ff0000` means
50
#'   red. Transparency (alpha channel) values are ignored.
51
#' * A one-column matrix with three rows for the red, green
52
#'   and blue channels, as returned by [grDevices::col2rgb()].
53
#'
54
#' `make_ansistyle()` detects the number of colors to use
55
#' automatically (this can be overridden using the `colors`
56
#' argument). If the number of colors is less than 256 (detected or given),
57
#' then it falls back to the color in the ANSI eight color mode that
58
#' is closest to the specified (RGB or R) color.
59
#'
60
#'
61
#' @family ANSI styling
62
#' @export
63
#' @examples
64
#' make_ansi_style("orange")
65
#' make_ansi_style("#123456")
66
#' make_ansi_style("orange", bg = TRUE)
67
#'
68
#' orange <- make_ansi_style("orange")
69
#' orange("foobar")
70
#' cat(orange("foobar"))
71

72
make_ansi_style <- function(..., bg = FALSE, grey = FALSE,
73
                            colors = crayon::num_colors()) {
74

75 1
  dots <- lapply(list(...), function(x) {
76 1
    if (identical(x, "dim")) return("blurred") else x
77
  })
78 1
  args <- c(dots, list(bg = bg , grey = grey, colors = colors))
79 1
  style <- do.call(crayon::make_style, args)
80 1
  cray_wrapper_fun(style)
81
}
82

83
#' @export
84

85
print.ansi_style <- function(x, ...) {
86 0
  cat("<ansi_style>\n")
87 0
  cat(x("Example output"))
88 0
  cat("\n")
89 0
  invisible(x)
90
}
91

92

93
#' Combine two or more ANSI styles
94
#'
95
#' Combine two or more styles or style functions into a new style function
96
#' that can be called on strings to style them.
97
#'
98
#' It does not usually make sense to combine two foreground
99
#' colors (or two background colors), because only the first one
100
#' applied will be used.
101
#'
102
#' It does make sense to combine different kind of styles,
103
#' e.g. background color, foreground color, bold font.
104
#'
105
#' @param ... The styles to combine. For character strings, the
106
#'   [make_ansi_style()] function is used to create a style first.
107
#'   They will be applied from right to left.
108
#' @return The combined style function.
109
#'
110
#' @family ANSI styling
111
#' @export
112
#' @examples
113
#' ## Use style names
114
#' alert <- combine_ansi_styles("bold", "red4")
115
#' cat(alert("Warning!"), "\n")
116
#'
117
#' ## Or style functions
118
#' alert <- combine_ansi_styles(style_bold, col_red, bg_cyan)
119
#' cat(alert("Warning!"), "\n")
120
#'
121
#' ## Combine a composite style
122
#' alert <- combine_ansi_styles(
123
#'   "bold",
124
#'   combine_ansi_styles("red", bg_cyan))
125
#' cat(alert("Warning!"), "\n")
126

127
combine_ansi_styles <- function(...) {
128 1
  args <- list(...)
129 1
  args <- lapply(args, function(x) {
130 1
    if (inherits(x, "ansi_style")) attr(x, "crayon_style") else x
131
  })
132 1
  style <- do.call(crayon::combine_styles, args)
133 1
  cray_wrapper_fun(style)
134
}
135

136
#' ANSI colored text
137
#'
138
#' cli has a number of functions to color and style text at the command
139
#' line. These all use the crayon package under the hood, but provide a
140
#' slightly simpler interface.
141
#'
142
#' The `col_*` functions change the (foreground) color to the text.
143
#' These are the eight original ANSI colors. Note that in some terminals,
144
#' they might actually look differently, as terminals have their own
145
#' settings for how to show them.
146
#'
147
#' The `bg_*` functions change the background color of the text.
148
#' These are the eight original ANSI background colors. These, too, can
149
#' vary in appearence, depending on terminal settings.
150
#'
151
#' The `style_*` functions apply other styling to the text. The currently
152
#' supported styling funtions are:
153
#' * `style_reset()` to remove any style, including color,
154
#' * `style_bold()` for boldface / strong text, although some terminals
155
#'   show a bright, high intensity text instead,
156
#' * `style_dim()` (or `style_blurred()` reduced intensity text.
157
#' * `style_italic()` (not widely supported).
158
#' * `style_underline()`,
159
#' * `style_inverse()`,
160
#' * `style_hidden()`,
161
#' * `style_strikethrough() (not widely supported).
162
#'
163
#' The style functions take any number of character vectors as arguments,
164
#' and they concatenate them using `paste0()` before adding the style.
165
#'
166
#' Styles can also be nested, and then inner style takes precedence, see
167
#' examples below.
168
#'
169
#' @param ... Character strings, they will be pasted together with
170
#'   `paste0()`, before applying the style function.
171
#' @return An ANSI string (class `ansi_string`), that contains ANSI
172
#'   sequences, if the current platform supports them. You can simply
173
#'   use `cat()` to print them to the terminal.
174
#'
175
#' @family ANSI styling
176
#' @name ansi-styles
177
#' @examples
178
#' col_blue("Hello ", "world!")
179
#' cat(col_blue("Hello ", "world!"))
180
#'
181
#' cat("... to highlight the", col_red("search term"),
182
#'     "in a block of text\n")
183
#'
184
#' ## Style stack properly
185
#' cat(col_green(
186
#'  "I am a green line ",
187
#'  col_blue(style_underline(style_bold("with a blue substring"))),
188
#'  " that becomes green again!"
189
#' ))
190
#'
191
#' error <- combine_ansi_styles("red", "bold")
192
#' warn <- combine_ansi_styles("magenta", "underline")
193
#' note <- col_cyan
194
#' cat(error("Error: subscript out of bounds!\n"))
195
#' cat(warn("Warning: shorter argument was recycled.\n"))
196
#' cat(note("Note: no such directory.\n"))
197
#'
198
NULL
199

200
#' @export
201
#' @name ansi-styles
202
bg_black    <- cray_wrapper("bgBlack")
203
#' @export
204
#' @name ansi-styles
205
bg_blue     <- cray_wrapper("bgBlue")
206
#' @export
207
#' @name ansi-styles
208
bg_cyan     <- cray_wrapper("bgCyan")
209
#' @export
210
#' @name ansi-styles
211
bg_green    <- cray_wrapper("bgGreen")
212
#' @export
213
#' @name ansi-styles
214
bg_magenta  <- cray_wrapper("bgMagenta")
215
#' @export
216
#' @name ansi-styles
217
bg_red      <- cray_wrapper("bgRed")
218
#' @export
219
#' @name ansi-styles
220
bg_white    <- cray_wrapper("bgWhite")
221
#' @export
222
#' @name ansi-styles
223
bg_yellow   <- cray_wrapper("bgYellow")
224

225
#' @export
226
#' @name ansi-styles
227
col_black   <- cray_wrapper("black")
228
#' @export
229
#' @name ansi-styles
230
col_blue    <- cray_wrapper("blue")
231
#' @export
232
#' @name ansi-styles
233
col_cyan    <- cray_wrapper("cyan")
234
#' @export
235
#' @name ansi-styles
236
col_green   <- cray_wrapper("green")
237
#' @export
238
#' @name ansi-styles
239
col_magenta <- cray_wrapper("magenta")
240
#' @export
241
#' @name ansi-styles
242
col_red     <- cray_wrapper("red")
243
#' @export
244
#' @name ansi-styles
245
col_white   <- cray_wrapper("white")
246
#' @export
247
#' @name ansi-styles
248
col_yellow  <- cray_wrapper("yellow")
249
#' @export
250
#' @name ansi-styles
251
col_grey    <- cray_wrapper("silver")
252
#' @export
253
#' @name ansi-styles
254
col_silver  <- cray_wrapper("silver")
255

256
#' @export
257
#' @name ansi-styles
258
style_dim           <- cray_wrapper("blurred")
259
#' @export
260
#' @name ansi-styles
261
style_blurred       <- cray_wrapper("blurred")
262
#' @export
263
#' @name ansi-styles
264
style_bold          <- cray_wrapper("bold")
265
#' @export
266
#' @name ansi-styles
267
style_hidden        <- cray_wrapper("hidden")
268
#' @export
269
#' @name ansi-styles
270
style_inverse       <- cray_wrapper("inverse")
271
#' @export
272
#' @name ansi-styles
273
style_italic        <- cray_wrapper("italic")
274
#' @export
275
#' @name ansi-styles
276
style_reset         <- cray_wrapper("reset")
277
#' @export
278
#' @name ansi-styles
279
style_strikethrough <- cray_wrapper("strikethrough")
280
#' @export
281
#' @name ansi-styles
282
style_underline     <- cray_wrapper("underline")

Read our documentation on viewing source code .

Loading