crayon/ 0000755 0001762 0000144 00000000000 14315342710 011545 5 ustar ligges users crayon/NAMESPACE 0000644 0001762 0000144 00000002354 14217635707 013004 0 ustar ligges users # Generated by roxygen2: do not edit by hand
S3method("$",crayon)
S3method("-",crayon)
S3method(as.character,crayon)
S3method(finish,crayon)
S3method(print,crayon)
S3method(start,crayon)
export("%+%")
export(bgBlack)
export(bgBlue)
export(bgCyan)
export(bgGreen)
export(bgMagenta)
export(bgRed)
export(bgWhite)
export(bgYellow)
export(black)
export(blue)
export(blurred)
export(bold)
export(chr)
export(col_align)
export(col_nchar)
export(col_strsplit)
export(col_substr)
export(col_substring)
export(combine_styles)
export(cyan)
export(drop_style)
export(finish)
export(green)
export(has_color)
export(has_hyperlink)
export(has_style)
export(hidden)
export(hyperlink)
export(inverse)
export(italic)
export(magenta)
export(make_style)
export(num_ansi_colors)
export(num_colors)
export(red)
export(reset)
export(show_ansi_colors)
export(silver)
export(strikethrough)
export(strip_style)
export(style)
export(styles)
export(underline)
export(white)
export(yellow)
importFrom(grDevices,col2rgb)
importFrom(grDevices,colors)
importFrom(grDevices,grey)
importFrom(grDevices,rgb)
importFrom(methods,is)
importFrom(stats,start)
importFrom(utils,head)
importFrom(utils,install.packages)
importFrom(utils,package.skeleton)
importFrom(utils,tail)
importFrom(utils,tar)
crayon/LICENSE 0000644 0001762 0000144 00000000057 14201156733 012556 0 ustar ligges users YEAR: 2014-2016
COPYRIGHT HOLDER: Gabor Csardi
crayon/tools/ 0000755 0001762 0000144 00000000000 14201156733 012707 5 ustar ligges users crayon/tools/ansi-palettes.txt 0000644 0001762 0000144 00000003147 14201156733 016226 0 ustar ligges users black red green yellow blue magenta cyan white br_black br_red br_green br_yellow br_blue br_magenta br_cyan br_white
dichro #000000 #882255 #117733 #ddcc77 #332288 #aa4499 #88ccee #e5e5e5 #000000 #cc6677 #999933 #ddcc77 #44aa99 #aa4499 #88ccee #ffffff
vga #000000 #aa0000 #00aa00 #aa5500 #0000aa #aa00aa #00aaaa #aaaaaa #555555 #ff5555 #55ff55 #ffff55 #5555ff #ff55ff #55ffff #ffffff
winxp #000000 #800000 #008000 #808000 #000080 #800080 #008080 #c0c0c0 #808080 #ff0000 #00ff00 #ffff00 #0000ff #ff00ff #00ffff #ffffff
vscode #000000 #cd3131 #0dbc79 #e5e510 #2472c8 #bc3fbc #11a8cd #e5e5e5 #666666 #f14c4c #23d18b #f5f543 #3b8eea #d670d6 #29b8db #e5e5e5
win10 #0c0c0c #c50f1f #13a10e #c19c00 #0037da #881798 #3a96dd #cccccc #767676 #e74856 #16c60c #f9f1a5 #3b78ff #b4009e #61d6d6 #f2f2f2
macos #000000 #c23621 #25bc24 #adad27 #492ee1 #d338d3 #33bbc8 #cbcccd #818383 #fc391f #31e722 #eaec23 #5833ff #f935f8 #14f0f0 #e9ebeb
putty #000000 #bb0000 #00bb00 #bbbb00 #0000bb #bb00bb #00bbbb #bbbbbb #555555 #ff5555 #55ff55 #ffff55 #5555ff #ff55ff #55ffff #ffffff
mirc #000000 #7f0000 #009300 #fc7f00 #00007f #9c009c #009393 #d2d2d2 #7f7f7f #ff0000 #00fc00 #ffff00 #0000fc #ff00ff #00ffff #ffffff
xterm #000000 #cd0000 #00cd00 #cdcd00 #0000ee #cd00cd #00cdcd #e5e5e5 #7f7f7f #ff0000 #00ff00 #ffff00 #5c5cff #ff00ff #00ffff #ffffff
ubuntu #010101 #de382b #39b54a #ffc706 #006fb8 #762671 #2cb5e9 #cccccc #808080 #ff0000 #00ff00 #ffff00 #0000ff #ff00ff #00ffff #ffffff
eclipse #000000 #cd0000 #00cd00 #cdcd00 #0000ee #cd00cd #00cdcd #e5e5e5 #000000 #ff0000 #00ff00 #ffff00 #5c5cff #ff00ff #00ffff #ffffff
crayon/tools/ansi-iterm-palettes.txt 0000644 0001762 0000144 00000001702 14201156733 017337 0 ustar ligges users black red green yellow blue magenta cyan white br_black br_red br_green br_yellow br_blue br_magenta br_cyan br_white
iterm #000000 #c91b00 #00c200 #c7c400 #0225c7 #ca30c7 #00c5c7 #c7c7c7 #686868 #ff6e67 #5ffa68 #fffc67 #6871ff #ff77ff #60fdff #ffffff
iterm-pastel #626262 #ff8373 #b4fb73 #fffdc3 #a5d5fe #ff90fe #d1d1fe #f1f1f1 #8f8f8f #ffc4be #d6fcba #fffed5 #c2e3ff #ffb2fe #e6e7fe #ffffff
iterm-smoooooth #14191e #b43c2a #00c200 #c7c400 #2744c7 #c040be #00c5c7 #c7c7c7 #686868 #dd7975 #58e790 #ece100 #a7abf2 #e17ee1 #60fdff #ffffff
iterm-snazzy #000000 #ff5c57 #5af78e #f3f99d #57c7ff #ff6ac1 #9aedfe #f1f1f0 #686868 #ff5c57 #5af78e #f3f99d #57c7ff #ff6ac1 #9aedfe #f1f1f0
iterm-solarized #073642 #dc322f #859900 #b58900 #268bd2 #d33682 #2aa198 #eee8d5 #002b36 #cb4b16 #586e75 #657b83 #839496 #6c71c4 #93a1a1 #fdf6e3
iterm-tango #000000 #d81e00 #5ea702 #cfae00 #427ab3 #89658e #00a7aa #dbded8 #686a66 #f54235 #99e343 #fdeb61 #84b0d8 #bc94b7 #37e6e8 #f1f1f0
crayon/README.md 0000644 0001762 0000144 00000007473 14315027352 013041 0 ustar ligges users
## 🚀 crayon is now superseded by the cli package. 🚀
> Please use [cli](https://github.com/r-lib/cli) for new projects.
>
> crayon is still supported and will receive important bug fixes,
> but no new features.
> Stylish terminal output in R
[](https://lifecycle.r-lib.org/articles/stages.html#superseded)
[](https://github.com/r-lib/crayon/actions)
[](https://r-pkg.org/pkg/crayon)
[](https://r-pkg.org/pkg/crayon)
[](https://codecov.io/github/r-lib/crayon?branch=master)
With crayon it is easy to add color to terminal output, create styles for notes, warnings, errors; and combine styles.
ANSI color support is automatically detected and used. Crayon was largely
inspired by [chalk](https://github.com/chalk/chalk).
## Installation
```r
install.packages("crayon")
```
## Styles
Crayon defines several styles that can be combined. Each style in the list
has a corresponding function with the same name.
### General styles
* `reset`
* `bold`
* `blurred` (usually called `dim`, renamed to avoid name clash)
* `italic` (not widely supported)
* `underline`
* `inverse`
* `hidden`
* `strikethrough` (not widely supported)
### Text colors
* `black`
* `red`
* `green`
* `yellow`
* `blue`
* `magenta`
* `cyan`
* `white`
* `silver` (usually called `gray`, renamed to avoid name clash)
### Background colors
* `bgBlack`
* `bgRed`
* `bgGreen`
* `bgYellow`
* `bgBlue`
* `bgMagenta`
* `bgCyan`
* `bgWhite`
### Screenshot on OSX

## Usage
The styling functions take any number of character vectors as arguments,
and they concatenate and style them:
```r
library(crayon)
cat(blue("Hello", "world!\n"))
```
Crayon defines the `%+%` string concatenation operator to make it easy
to assemble strings with different styles.
```r
cat("... to highlight the " %+% red("search term") %+% " in a block of text\n")
```
Styles can be combined using the `$` operator:
```r
cat(yellow$bgMagenta$bold('Hello world!\n'))
```
Styles can also be nested, and then inner style takes precedence:
```r
cat(green(
'I am a green line ' %+%
blue$underline$bold('with a blue substring') %+%
' that becomes green again!\n'
))
```
It is easy to define your own themes:
```r
error <- red $ bold
warn <- magenta $ underline
note <- cyan
cat(error("Error: subscript out of bounds!\n"))
cat(warn("Warning: shorter argument was recycled.\n"))
cat(note("Note: no such directory.\n"))
```
## 256 colors
Most modern terminals support the ANSI standard for 256 colors,
and you can define new styles that make use of them. The `make_style`
function defines a new style. It can handle R's built in color names
(see the output of `colors()`) as well as RGB specifications via the
`rgb()` function. It automatically chooses the ANSI colors that
are closest to the specified R and RGB colors, and it also has
a fallback to terminals with 8 ANSI colors only.
```r
ivory <- make_style("ivory")
bgMaroon <- make_style("maroon", bg = TRUE)
fancy <- combine_styles(ivory, bgMaroon)
cat(fancy("This will have some fancy colors"), "\n")
```

## License
MIT @ Gábor Csárdi
crayon/man/ 0000755 0001762 0000144 00000000000 14201156733 012322 5 ustar ligges users crayon/man/hyperlink.Rd 0000644 0001762 0000144 00000001443 14201156733 014620 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/link.R
\name{hyperlink}
\alias{hyperlink}
\alias{has_hyperlink}
\title{Terminal Hyperlinks}
\usage{
hyperlink(text, url)
has_hyperlink()
}
\arguments{
\item{text}{Text to show. \code{text} and \code{url} are recycled to match their
length, via a \code{paste0()} call.}
\item{url}{URL to link to.}
}
\value{
Logical scalar, for \code{has_hyperlink()}.
}
\description{
Terminal Hyperlinks
}
\details{
hyperlink()` creates an ANSI hyperlink.
\code{has_hyperlink()} checks if the current \code{stdout()} supports hyperlinks.
terminal links.
See also
\url{https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda}.
}
\examples{
cat("This is an", hyperlink("R", "https://r-project.org"), "link.\n")
has_hyperlink()
}
crayon/man/show_ansi_colors.Rd 0000644 0001762 0000144 00000000756 14201156733 016174 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/show.r
\name{show_ansi_colors}
\alias{show_ansi_colors}
\title{Show the ANSI color table on the screen}
\usage{
show_ansi_colors(colors = num_colors())
}
\arguments{
\item{colors}{Number of colors to show, meaningful values
are 8 and 256. It is automatically set to the number of
supported colors, if not specified.}
}
\value{
The printed string, invisibly.
}
\description{
Show the ANSI color table on the screen
}
crayon/man/strip_style.Rd 0000644 0001762 0000144 00000000620 14201156733 015170 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/has_ansi.r
\name{strip_style}
\alias{strip_style}
\title{Remove ANSI escape sequences from a string}
\usage{
strip_style(string)
}
\arguments{
\item{string}{The input string.}
}
\value{
The cleaned up string.
}
\description{
Remove ANSI escape sequences from a string
}
\examples{
strip_style(red("foobar")) == "foobar"
}
crayon/man/num_ansi_colors.Rd 0000644 0001762 0000144 00000012673 14201220600 015775 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/aab-num-ansi-colors.R
\name{num_ansi_colors}
\alias{num_ansi_colors}
\alias{detect_tty_colors}
\title{Detect the number of ANSI colors to use}
\usage{
num_ansi_colors(stream = "auto")
detect_tty_colors()
}
\arguments{
\item{stream}{The stream that will be used for output, an R connection
object. It can also be a string, one of \code{"auto"}, \code{"message"},
\code{"stdout"}, \code{"stderr"}. \code{"auto"} will select \code{stdout()} if the session is
interactive and there are no sinks, otherwise it will select \code{stderr()}.}
}
\value{
Integer, the number of ANSI colors the current R session
supports for \code{stream}.
}
\description{
Certain Unix and Windows terminals, and also certain R GUIs, e.g.
RStudio, support styling terminal output using special control
sequences (ANSI sequences).
\code{num_ansi_colors()} detects if the current R session supports ANSI
sequences, and if it does how many colors are supported.
}
\details{
The detection mechanism is quite involved and it is designed to work
out of the box on most systems. If it does not work on your system,
please report a bug. Setting options and environment variables to turn
on ANSI support is error prone, because they are inherited in other
environments, e.g. knitr, that might not have ANSI support.
If you want to \emph{turn off} ANSI colors, set the \code{NO_COLOR} environment
variable to a non-empty value.
The exact detection mechanism is as follows:
\enumerate{
\item If the \code{cli.num_colors} options is set, that is returned.
\item If the \code{R_CLI_NUM_COLORS} environment variable is set to a
non-empty value, then it is used.
\item If the \code{crayon.enabled} option is set to \code{FALSE}, 1L is returned.
(This is for compatibility with code that uses the crayon package.)
\item If the \code{crayon.enabled} option is set to \code{TRUE} and the
\code{crayon.colors} option is not set, then the value of the
\code{cli.default_num_colors} option, or if it is unset, then 8L is
returned.
\item If the \code{crayon.enabled} option is set to \code{TRUE} and the
\code{crayon.colors} option is also set, then the latter is returned.
(This is for compatibility with code that uses the crayon package.)
\item If the \code{NO_COLOR} environment variable is set, then 1L is returned.
\item If we are in knitr, then 1L is returned, to turn off colors in
\code{.Rmd} chunks.
\item If \code{stream} is \code{"auto"} (the default) and there is an active
sink (either for \code{"output"} or \code{"message"}), then we return 1L.
(In theory we would only need to check the stream that will be
be actually used, but there is no easy way to tell that.)
\item If \code{stream} is not \code{"auto"}, but it is \code{stderr()} and there is an
active sink for it, then 1L is returned.
(If a sink is active for "output", then R changes the \code{stdout()}
stream, so this check is not needed.)
\item If R is running inside RGui on Windows, or R.app on macOS, then we
return 1L.
\item If R is running inside RStudio, with color support, then the
appropriate number of colors is returned, usually 256L.
\item If R is running on Windows, inside an Emacs version that is recent
enough to support ANSI colors, then the value of the
\code{cli.default_num_colors} option, or if unset 8L is returned.
(On Windows, Emacs has \code{isatty(stdout()) == FALSE}, so we need to
check for this here before dealing with terminals.)
\item If \code{stream} is not the standard output or standard error in a
terminal, then 1L is returned.
\item Otherwise we use and cache the result of the terminal color
detection (see below).
}
The terminal color detection algorithm:
\enumerate{
\item If the \code{COLORTERM} environment variable is set to \code{truecolor} or
\verb{24bit}, then we return 16 million colors.
\item If the \code{COLORTERM} environment variable is set to anything else,
then we return the value of the \code{cli.num_default_colors} option,
8L if unset.
\item If R is running on Unix, inside an Emacs version that is recent
enough to support ANSI colors, then the value of the
\code{cli.default_num_colors} option is returned, or 8L if unset.
\item If we are on Windows in an RStudio terminal, then apparently
we only have eight colors, but the \code{cli.default_num_colors} option
can be used to override this.
\item If we are in a recent enough Windows 10 terminal, then there
is either true color (from build 14931) or 256 color (from
build 10586) support. You can also use the \code{cli.default_num_colors}
option to override these.
\item If we are on Windows, under ConEmu or cmder, or ANSICON is loaded,
then the value of \code{cli.default_num_colors}, or 8L if unset, is
returned.
\item Otherwise if we are on Windows, return 1L.
\item Otherwise we are on Unix and try to run \verb{tput colors} to determine
the number of colors. If this succeeds, we return its return value.
If the \code{TERM} environment variable is \code{xterm} and \code{tput}
returned 8L, we return 256L, because xterm compatible terminals
tend to support 256 colors
(\url{https://github.com/r-lib/crayon/issues/17})
You can override this with the \code{cli.default_num_colors} option.
\item If \code{TERM} is set to \code{dumb}, we return 1L.
\item If \code{TERM} starts with \code{screen}, \code{xterm}, or \code{vt100}, we return 8L.
\item If \code{TERM} contains \code{color}, \code{ansi}, \code{cygwin} or \code{linux}, we return 8L.
\item Otherwise we return 1L.
}
}
\examples{
num_ansi_colors()
}
\concept{ANSI styling}
crayon/man/col_align.Rd 0000644 0001762 0000144 00000001732 14201156733 014543 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string_operations.r
\name{col_align}
\alias{col_align}
\title{Align an ANSI colored string}
\usage{
col_align(
text,
width = getOption("width"),
align = c("left", "center", "right"),
type = "width"
)
}
\arguments{
\item{text}{The character vector to align.}
\item{width}{Width of the field to align in.}
\item{align}{Whether to align \code{"left"}, \code{"center"} or \code{"right"}.}
\item{type}{Passed on to \code{\link[=col_nchar]{col_nchar()}} and there to \code{\link[=nchar]{nchar()}}}
}
\value{
The aligned character vector.
}
\description{
Align an ANSI colored string
}
\examples{
col_align(red("foobar"), 20, "left")
col_align(red("foobar"), 20, "center")
col_align(red("foobar"), 20, "right")
}
\seealso{
Other ANSI string operations:
\code{\link{col_nchar}()},
\code{\link{col_strsplit}()},
\code{\link{col_substring}()},
\code{\link{col_substr}()}
}
\concept{ANSI string operations}
crayon/man/col_substring.Rd 0000644 0001762 0000144 00000003174 14201156733 015473 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string_operations.r
\name{col_substring}
\alias{col_substring}
\title{Substring(s) of an ANSI colored string}
\usage{
col_substring(text, first, last = 1000000L)
}
\arguments{
\item{text}{Character vector, potentially ANSI styled, or a vector to
coarced to character. It is recycled to the longest of \code{first}
and \code{last}.}
\item{first}{Starting index or indices, recycled to match the length
of \code{x}.}
\item{last}{Ending index or indices, recycled to match the length
of \code{x}.}
}
\value{
Character vector of the same length as \code{x}, containing
the requested substrings. ANSI styles are retained.
}
\description{
This is the color-aware counterpart of \code{\link[base:substr]{base::substring()}}.
It works exactly like the original, but keeps the colors in the
substrings. The ANSI escape sequences are ignored when
calculating the positions within the string.
}
\examples{
str <- paste(
red("red"),
"default",
green("green")
)
cat(str, "\n")
cat(col_substring(str, 1, 5), "\n")
cat(col_substring(str, 1, 15), "\n")
cat(col_substring(str, 3, 7), "\n")
substring(strip_style(str), 1, 5)
substring(strip_style(str), 1, 15)
substring(strip_style(str), 3, 7)
str2 <- "another " \%+\%
red("multi-", sep = "", underline("style")) \%+\%
" text"
cat(str2, "\n")
cat(col_substring(str2, c(3,5), c(7, 18)), sep = "\n")
substring(strip_style(str2), c(3,5), c(7, 18))
}
\seealso{
Other ANSI string operations:
\code{\link{col_align}()},
\code{\link{col_nchar}()},
\code{\link{col_strsplit}()},
\code{\link{col_substr}()}
}
\concept{ANSI string operations}
crayon/man/style.Rd 0000644 0001762 0000144 00000001327 14201156733 013754 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/style-var.r
\name{style}
\alias{style}
\title{Add style to a string}
\usage{
style(string, as = NULL, bg = NULL)
}
\arguments{
\item{string}{Character vector to style.}
\item{as}{Style function to apply, either the function object,
or its name, or an object to pass to \code{\link[=make_style]{make_style()}}.}
\item{bg}{Background style, a style function, or a name that
is passed to \code{\link[=make_style]{make_style()}}.}
}
\value{
Styled character vector.
}
\description{
See \code{names(styles)}, or the crayon manual for available styles.
}
\examples{
## These are equivalent
style("foobar", bold)
style("foobar", "bold")
bold("foobar")
}
crayon/man/col_nchar.Rd 0000644 0001762 0000144 00000001763 14201156733 014550 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string_operations.r
\name{col_nchar}
\alias{col_nchar}
\title{Count number of characters in an ANSI colored string}
\usage{
col_nchar(x, ...)
}
\arguments{
\item{x}{Character vector, potentially ANSO styled, or a vector to be
coarced to character.}
\item{...}{Additional arguments, passed on to \code{base::nchar()}
after removing ANSI escape sequences.}
}
\value{
Numeric vector, the length of the strings in the character
vector.
}
\description{
This is a color-aware counterpart of \code{\link[base:nchar]{base::nchar()}},
which does not do well, since it also counts the ANSI control
characters.
}
\examples{
str <- paste(
red("red"),
"default",
green("green")
)
cat(str, "\n")
nchar(str)
col_nchar(str)
nchar(strip_style(str))
}
\seealso{
Other ANSI string operations:
\code{\link{col_align}()},
\code{\link{col_strsplit}()},
\code{\link{col_substring}()},
\code{\link{col_substr}()}
}
\concept{ANSI string operations}
crayon/man/concat.Rd 0000644 0001762 0000144 00000001320 14201156733 014054 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string.r
\name{concat}
\alias{concat}
\alias{\%+\%}
\title{Concatenate character vectors}
\usage{
lhs \%+\% rhs
}
\arguments{
\item{lhs}{Left hand side, character vector.}
\item{rhs}{Right hand side, character vector.}
}
\value{
Concatenated vectors.
}
\description{
The length of the two arguments must match, or
one of them must be of length one. If the length of
one argument is one, then the output's length will
match the length of the other argument. See examples
below.
}
\examples{
"foo" \%+\% "bar"
letters[1:10] \%+\% chr(1:10)
letters[1:10] \%+\% "-" \%+\% chr(1:10)
## This is empty (unlike for parse)
character() \%+\% "*"
}
crayon/man/chr.Rd 0000644 0001762 0000144 00000000644 14201156733 013371 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string.r
\name{chr}
\alias{chr}
\title{Convert to character}
\usage{
chr(x, ...)
}
\arguments{
\item{x}{Object to be coerced.}
\item{...}{Further arguments to pass to \code{as.character()}.}
}
\value{
Character value.
}
\description{
This function just calls \code{\link[=as.character]{as.character()}}, but it is
easier to type and read.
}
crayon/man/start.crayon.Rd 0000644 0001762 0000144 00000001416 14201156733 015242 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/parts.r
\name{start.crayon}
\alias{start.crayon}
\alias{finish}
\alias{finish.crayon}
\title{Switch on or off a style}
\usage{
\method{start}{crayon}(x, ...)
finish(x, ...)
\method{finish}{crayon}(x, ...)
}
\arguments{
\item{x}{Style.}
\item{...}{Ignored.}
}
\description{
Make a style active. The text printed to the screen from now
on will use this style.
}
\details{
This function is very rarely needed, e.g. for colored user
input. For other reasons, just call the style as a function on
the string.
}
\examples{
## The input is red (if color is supported)
get_name <- function() {
cat("Enter your name:", start(red))
input <- readline()
cat(finish(red))
input
}
name <- get_name()
name
}
crayon/man/has_color.Rd 0000644 0001762 0000144 00000000636 14201156733 014567 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/has_color.r
\name{has_color}
\alias{has_color}
\title{Does the current R session support ANSI colors?}
\usage{
has_color()
}
\value{
\code{TRUE} if the current R session supports color.
}
\description{
From crayon 2.0.0, this function is simply a wrapper on
\code{\link[=num_ansi_colors]{num_ansi_colors()}}.
}
\examples{
has_color()
}
crayon/man/has_style.Rd 0000644 0001762 0000144 00000001023 14201156733 014600 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/has_ansi.r
\name{has_style}
\alias{has_style}
\title{Check if a string has some ANSI styling}
\usage{
has_style(string)
}
\arguments{
\item{string}{The string to check. It can also be a character
vector.}
}
\value{
Logical vector, \code{TRUE} for the strings that have some
ANSI styling.
}
\description{
Check if a string has some ANSI styling
}
\examples{
## The second one has style if crayon is enabled
has_style("foobar")
has_style(red("foobar"))
}
crayon/man/col_strsplit.Rd 0000644 0001762 0000144 00000003016 14201156733 015332 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string_operations.r
\name{col_strsplit}
\alias{col_strsplit}
\title{Split an ANSI colored string}
\usage{
col_strsplit(x, split, ...)
}
\arguments{
\item{x}{Character vector, potentially ANSI styled, or a vector to
coarced to character.}
\item{split}{Character vector of length 1 (or object which can be coerced to
such) containing regular expression(s) (unless \code{fixed = TRUE}) to use
for splitting. If empty matches occur, in particular if \code{split} has
zero characters, \code{x} is split into single characters.}
\item{...}{Extra arguments are passed to \code{base::strsplit()}.}
}
\value{
A list of the same length as \code{x}, the \eqn{i}-th element of
which contains the vector of splits of \code{x[i]}. ANSI styles are
retained.
}
\description{
This is the color-aware counterpart of \code{\link[base:strsplit]{base::strsplit()}}.
It works almost exactly like the original, but keeps the colors in the
substrings.
}
\examples{
str <- red("I am red---") \%+\%
green("and I am green-") \%+\%
underline("I underlined")
cat(str, "\n")
# split at dashes, keep color
cat(col_strsplit(str, "[-]+")[[1]], sep = "\n")
strsplit(strip_style(str), "[-]+")
# split to characters, keep color
cat(col_strsplit(str, "")[[1]], "\n", sep = " ")
strsplit(strip_style(str), "")
}
\seealso{
Other ANSI string operations:
\code{\link{col_align}()},
\code{\link{col_nchar}()},
\code{\link{col_substring}()},
\code{\link{col_substr}()}
}
\concept{ANSI string operations}
crayon/man/num_colors.Rd 0000644 0001762 0000144 00000001127 14201156733 014772 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/has_color.r
\name{num_colors}
\alias{num_colors}
\title{Number of colors the terminal supports}
\usage{
num_colors(forget = FALSE)
}
\arguments{
\item{forget}{Ignored. Included for backwards compatibility.}
}
\value{
Number of ANSI colors.
}
\description{
From crayon version 2.0.0, this function is a simple wrapper on
\code{\link[=num_ansi_colors]{num_ansi_colors()}}, with the additional twist that the \code{crayon.colors}
option is still obseved, and takes precedence, for compatibility.
}
\examples{
num_colors()
}
crayon/man/col_substr.Rd 0000644 0001762 0000144 00000003031 14201156733 014765 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/string_operations.r
\name{col_substr}
\alias{col_substr}
\title{Substring(s) of an ANSI colored string}
\usage{
col_substr(x, start, stop)
}
\arguments{
\item{x}{Character vector, potentially ANSI styled, or a vector to
coarced to character.}
\item{start}{Starting index or indices, recycled to match the length
of \code{x}.}
\item{stop}{Ending index or indices, recycled to match the length
of \code{x}.}
}
\value{
Character vector of the same length as \code{x}, containing
the requested substrings. ANSI styles are retained.
}
\description{
This is a color-aware counterpart of \code{\link[base:substr]{base::substr()}}.
It works exactly like the original, but keeps the colors
in the substrings. The ANSI escape sequences are ignored when
calculating the positions within the string.
}
\examples{
str <- paste(
red("red"),
"default",
green("green")
)
cat(str, "\n")
cat(col_substr(str, 1, 5), "\n")
cat(col_substr(str, 1, 15), "\n")
cat(col_substr(str, 3, 7), "\n")
substr(strip_style(str), 1, 5)
substr(strip_style(str), 1, 15)
substr(strip_style(str), 3, 7)
str2 <- "another " \%+\%
red("multi-", sep = "", underline("style")) \%+\%
" text"
cat(str2, "\n")
cat(col_substr(c(str, str2), c(3,5), c(7, 18)), sep = "\n")
substr(strip_style(c(str, str2)), c(3,5), c(7, 18))
}
\seealso{
Other ANSI string operations:
\code{\link{col_align}()},
\code{\link{col_nchar}()},
\code{\link{col_strsplit}()},
\code{\link{col_substring}()}
}
\concept{ANSI string operations}
crayon/man/styles.Rd 0000644 0001762 0000144 00000001134 14201156733 014133 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/machinery.r
\name{styles}
\alias{styles}
\title{ANSI escape sequences of crayon styles}
\usage{
styles()
}
\value{
A named list. Each list element is a list of two
strings, named \sQuote{open} and \sQuote{close}.
}
\description{
You can use this function to list all availables crayon styles,
via \code{names(styles())}, or to explicitly apply an ANSI
escape seauence to a string.
}
\examples{
names(styles())
cat(styles()[["bold"]]$close)
}
\seealso{
\code{\link[=crayon]{crayon()}} for the beginning of the crayon manual.
}
crayon/man/crayon.Rd 0000644 0001762 0000144 00000006520 14201156733 014107 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/crayon-package.r, R/machinery.r
\docType{package}
\name{crayon}
\alias{crayon}
\alias{reset}
\alias{bold}
\alias{blurred}
\alias{italic}
\alias{underline}
\alias{inverse}
\alias{hidden}
\alias{strikethrough}
\alias{black}
\alias{red}
\alias{green}
\alias{yellow}
\alias{blue}
\alias{magenta}
\alias{cyan}
\alias{white}
\alias{silver}
\alias{bgBlack}
\alias{bgRed}
\alias{bgGreen}
\alias{bgYellow}
\alias{bgBlue}
\alias{bgMagenta}
\alias{bgCyan}
\alias{bgWhite}
\title{Colored terminal output}
\usage{
## Simple styles
red(...)
bold(...)
# ...
## See more styling below
}
\arguments{
\item{...}{Strings to style.}
}
\description{
With crayon it is easy to add color to terminal output, create styles
for notes, warnings, errors; and combine styles.
}
\details{
ANSI color support is automatically detected and used. Crayon was largely
inspired by chalk \url{https://github.com/chalk/chalk}.
Crayon defines several styles, that can be combined. Each style in the list
has a corresponding function with the same name.
}
\section{Genaral styles}{
\itemize{
\item reset
\item bold
\item blurred (usually called \sQuote{dim}, renamed to avoid name clash)
\item italic (not widely supported)
\item underline
\item inverse
\item hidden
\item strikethrough (not widely supported)
}
}
\section{Text colors}{
\itemize{
\item black
\item red
\item green
\item yellow
\item blue
\item magenta
\item cyan
\item white
\item silver (usually called \sQuote{gray}, renamed to avoid name clash)
}
}
\section{Background colors}{
\itemize{
\item bgBlack
\item bgRed
\item bgGreen
\item bgYellow
\item bgBlue
\item bgMagenta
\item bgCyan
\item bgWhite
}
}
\section{Styling}{
The styling functions take any number of character vectors as arguments,
and they concatenate and style them: \preformatted{ library(crayon)
cat(blue("Hello", "world!\n"))
}
Crayon defines the \code{\%+\%} string concatenation operator, to make it easy
to assemble stings with different styles. \preformatted{ cat("... to highlight the " \%+\% red("search term") \%+\%
" in a block of text\n")
}
Styles can be combined using the \code{$} operator: \preformatted{ cat(yellow$bgMagenta$bold('Hello world!\n'))
} See also \code{\link[=combine_styles]{combine_styles()}}.
Styles can also be nested, and then inner style takes
precedence: \preformatted{ cat(green(
'I am a green line ' \%+\%
blue$underline$bold('with a blue substring') \%+\%
' that becomes green again!\n'
))
}
It is easy to define your own themes: \preformatted{ error <- red $ bold
warn <- magenta $ underline
note <- cyan
cat(error("Error: subscript out of bounds!\n"))
cat(warn("Warning: shorter argument was recycled.\n"))
cat(note("Note: no such directory.\n"))
}
}
\examples{
cat(blue("Hello", "world!"))
cat("... to highlight the " \%+\% red("search term") \%+\%
" in a block of text")
cat(yellow$bgMagenta$bold('Hello world!'))
cat(green(
'I am a green line ' \%+\%
blue$underline$bold('with a blue substring') \%+\%
' that becomes green again!'
))
error <- red $ bold
warn <- magenta $ underline
note <- cyan
cat(error("Error: subscript out of bounds!\n"))
cat(warn("Warning: shorter argument was recycled.\n"))
cat(note("Note: no such directory.\n"))
}
\seealso{
\code{\link[=make_style]{make_style()}} for using the 256 ANSI colors.
}
crayon/man/combine_styles.Rd 0000644 0001762 0000144 00000002724 14201156733 015635 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/combine.r
\name{combine_styles}
\alias{combine_styles}
\alias{$.crayon}
\title{Combine two or more ANSI styles}
\usage{
combine_styles(...)
\method{$}{crayon}(crayon, style)
}
\arguments{
\item{...}{The styles to combine. They will be applied from
right to left.}
\item{crayon}{A style function.}
\item{style}{A style name that is included in \code{names(styles())}.}
}
\value{
The combined style function.
}
\description{
Combine two or more styles or style functions into a new style function
that can be called on strings to style them.
}
\details{
It does not usually make sense to combine two foreground
colors (or two background colors), because only the first one
applied will be used.
It does make sense to combine different kind of styles,
e.g. background color, foreground color, bold font.
The \code{$} operator can also be used to combine styles.
Note that the left hand side of \code{$} is a style function,
and the right hand side is the name of a style in \code{\link[=styles]{styles()}}.
}
\examples{
## Use style names
alert <- combine_styles("bold", "red4", "bgCyan")
cat(alert("Warning!"), "\n")
## Or style functions
alert <- combine_styles(bold, red, bgCyan)
cat(alert("Warning!"), "\n")
## Combine a composite style
alert <- combine_styles(bold, combine_styles(red, bgCyan))
cat(alert("Warning!"), "\n")
## Shorter notation
alert <- bold $ red $ bgCyan
cat(alert("Warning!"), "\n")
}
crayon/man/drop_style.Rd 0000644 0001762 0000144 00000001063 14201156733 014775 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/machinery.r
\name{drop_style}
\alias{drop_style}
\title{Remove a style}
\usage{
drop_style(style)
}
\arguments{
\item{style}{The name of the style to remove. No error is given
for non-existing names.}
}
\value{
Nothing.
}
\description{
Remove a style
}
\examples{
make_style(new_style = "maroon", bg = TRUE)
cat(style("I am maroon", "new_style"), "\n")
drop_style("new_style")
"new_style" \%in\% names(styles())
}
\seealso{
Other styles:
\code{\link{make_style}()}
}
\concept{styles}
crayon/man/make_style.Rd 0000644 0001762 0000144 00000006071 14201156733 014752 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/machinery.r
\name{make_style}
\alias{make_style}
\title{Create an ANSI color style}
\usage{
make_style(..., bg = FALSE, grey = FALSE, colors = num_colors())
}
\arguments{
\item{...}{The style to create. See details and examples below.}
\item{bg}{Whether the color applies to the background.}
\item{grey}{Whether to specifically create a grey color.
This flag is included because ANSI 256 has a finer color scale
for greys than the usual 0:5 scale for R, G and B components.
It is only used for RGB color specifications (either numerically
or via a hexa string) and is ignored on eigth color ANSI
terminals.}
\item{colors}{Number of colors, detected automatically
by default.}
}
\value{
A function that can be used to color strings.
}
\description{
Create a style, or a style function, or both. This function
is intended for those who wish to use 256 ANSI colors,
instead of the more widely supported eight colors.
}
\details{
The crayon package comes with predefined styles (see
\code{\link[=styles]{styles()}} for a list) and functions for the basic eight-color
ANSI standard (\code{red}, \code{blue}, etc., see \link{crayon}).
There are no predefined styles or style functions for the 256 color
ANSI mode, however, because we simply did not want to create that
many styles and functions. Instead, \code{make_style()} can be
used to create a style (or a style function, or both).
There are two ways to use this function: \enumerate{
\item If its first argument is not named, then it returns a function
that can be used to color strings.
\item If its first argument is named, then it also creates a
style with the given name. This style can be used in
\code{\link[=style]{style()}}. One can still use the return value
of the function, to create a style function.
}
The style (the code{...} argument) can be anything of the
following: \itemize{
\item An R color name, see \code{\link[=colors]{colors()}}.
\item A 6- or 8-digit hexa color string, e.g. \verb{#ff0000} means
red. Transparency (alpha channel) values are ignored.
\item A one-column matrix with three rows for the red, green
and blue channels, as returned by \code{col2rgb} (in the base
grDevices package).
}
\code{make_style()} detects the number of colors to use
automatically (this can be overridden using the \code{colors}
argument). If the number of colors is less than 256 (detected or given),
then it falls back to the color in the ANSI eight color mode that
is closest to the specified (RGB or R) color.
See the examples below.
}
\examples{
## Create a style function without creating a style
pink <- make_style("pink")
bgMaroon <- make_style(rgb(0.93, 0.19, 0.65), bg = TRUE)
cat(bgMaroon(pink("I am pink if your terminal wants it, too.\n")))
## Create a new style for pink and maroon background
make_style(pink = "pink")
make_style(bgMaroon = rgb(0.93, 0.19, 0.65), bg = TRUE)
"pink" \%in\% names(styles())
"bgMaroon" \%in\% names(styles())
cat(style("I am pink, too!\n", "pink", bg = "bgMaroon"))
}
\seealso{
Other styles:
\code{\link{drop_style}()}
}
\concept{styles}
crayon/DESCRIPTION 0000644 0001762 0000144 00000003016 14315342710 013253 0 ustar ligges users Package: crayon
Title: Colored Terminal Output
Version: 1.5.2
Authors@R: c(
person("Gábor", "Csárdi", , "csardi.gabor@gmail.com",
role = c("aut", "cre")),
person(
"Brodie", "Gaslam", email="brodie.gaslam@yahoo.com",
role=c("ctb"))
)
Description: The crayon package is now superseded. Please use the 'cli' package
for new projects.
Colored terminal output on terminals that support 'ANSI'
color and highlight codes. It also works in 'Emacs' 'ESS'. 'ANSI'
color support is automatically detected. Colors and highlighting can
be combined and nested. New styles can also be created easily.
This package was inspired by the 'chalk' 'JavaScript' project.
License: MIT + file LICENSE
URL: https://github.com/r-lib/crayon#readme
BugReports: https://github.com/r-lib/crayon/issues
Collate: 'aaa-rstudio-detect.R' 'aaaa-rematch2.R'
'aab-num-ansi-colors.R' 'aac-num-ansi-colors.R' 'ansi-256.r'
'ansi-palette.R' 'combine.r' 'string.r' 'utils.r'
'crayon-package.r' 'disposable.r' 'enc-utils.R' 'has_ansi.r'
'has_color.r' 'link.R' 'styles.r' 'machinery.r' 'parts.r'
'print.r' 'style-var.r' 'show.r' 'string_operations.r'
Imports: grDevices, methods, utils
Suggests: mockery, rstudioapi, testthat, withr
RoxygenNote: 7.1.2
Encoding: UTF-8
NeedsCompilation: no
Packaged: 2022-09-29 06:24:10 UTC; gaborcsardi
Author: Gábor Csárdi [aut, cre],
Brodie Gaslam [ctb]
Maintainer: Gábor Csárdi
Repository: CRAN
Date/Publication: 2022-09-29 16:20:24 UTC
crayon/tests/ 0000755 0001762 0000144 00000000000 14220353764 012715 5 ustar ligges users crayon/tests/testthat/ 0000755 0001762 0000144 00000000000 14315342710 014547 5 ustar ligges users crayon/tests/testthat/test-styles.r 0000644 0001762 0000144 00000002310 14201156733 017230 0 ustar ligges users
test_that("new styles are local to importing package", {
skip("This is not implemented, yet.")
lib_dir <- tempfile()
on.exit(try(unloadNamespace("foo1"), silent = TRUE), add = TRUE)
on.exit(try(unloadNamespace("foo2"), silent = TRUE), add = TRUE)
on.exit(try(unlink(lib_dir, recursive = TRUE), silent = TRUE), add = TRUE)
make_packages(
lib_dir = lib_dir,
imports = "crayon",
foo1 = {
f <- function() {
make_style(pink = "pink")
}
g <- function() {
names(styles())
}
},
foo2 = {
f <- function() {
make_style(maroon = "maroon")
}
g <- function() {
names(styles())
}
}
)
## Add style in 'foo1', does not effect 'foo2', or attached crayon
foo1::f()
expect_true("pink" %in% foo1::g())
expect_false("pink" %in% foo2::g())
expect_false("pink" %in% names(styles()))
## Attached style change does not affect imports in packages
on.exit(drop_style("ivory444"), add = TRUE)
make_style(ivory444 = "ivory")
expect_true("ivory444" %in% names(styles()))
expect_false("ivory444" %in% foo1::g())
expect_false("ivory444" %in% foo2::g())
## TODO: what if the package(s) are not attached
})
crayon/tests/testthat/test-combine.R 0000644 0001762 0000144 00000002030 14201156733 017260 0 ustar ligges users
test_that("one style", {
# Need 3rd edition for testthat's comparison that works for these
# functions. `all_equal()`, used by the 2nd edition gives a
# deprecation warning.
local_edition(3)
expect_equal(combine_styles(red), red)
expect_equal(combine_styles(bold), bold)
})
test_that("style objects", {
withr::with_options(
list(crayon.enabled = TRUE, crayon.colors = 256), {
expect_equal(
combine_styles(red, bold)("blah"),
red(bold("blah"))
)
expect_equal(
combine_styles(red, bold, underline)("foo"),
red(bold(underline("foo")))
)
}
)
})
test_that("create styles on the fly", {
withr::with_options(
list(crayon.enabled = TRUE, crayon.colors = 256), {
expect_equal(
combine_styles("darkolivegreen", bold)("blah"),
make_style("darkolivegreen")((bold("blah")))
)
expect_equal(
combine_styles(bold, "darkolivegreen", underline)("foo"),
bold(make_style("darkolivegreen")(underline("foo")))
)
}
)
})
crayon/tests/testthat/test-hyperlink.R 0000644 0001762 0000144 00000000260 14201156733 017654 0 ustar ligges users
test_that("hyperlinks", {
withr::local_options(crayon.hyperlink = TRUE)
expect_equal(
hyperlink("foo", "https://bar"),
"\033]8;;https://bar\afoo\033]8;;\a"
)
})
crayon/tests/testthat/test-make-style.r 0000644 0001762 0000144 00000002515 14201156733 017767 0 ustar ligges users
test_that("make_style without name", {
st <- styles()
pink <- make_style("pink")
expect_true(is(pink, "crayon"))
expect_identical(st, styles())
})
test_that("make_style with name", {
st <- styles()
make_style(foobarnonono = "pink")
expect_true("foobarnonono" %in% names(styles()))
drop_style("foobarnonono")
expect_false("foobarnonono" %in% names(styles()))
})
test_that("hexa color regex works", {
positive <- c("#000000", "#ffffff", "#0f0f0f", "#f0f0f0",
"#00000000", "#ffffffff", "#0f0f0f00", "#f0f0f055")
negative <- c("", "#12345", "123456", "1234567", "12345678",
"#1234567", "#1234ffg", "#gggggx", "foo#123456",
"foo#123456bar")
for (color in positive) {
expect_true(grepl(hash_color_regex, color))
expect_true(grepl(hash_color_regex, toupper(color)))
}
for (color in negative) {
expect_false(grepl(hash_color_regex, color))
expect_false(grepl(hash_color_regex, toupper(color)))
}
})
test_that("we fall back for ANSI 8 if needed", {
yellow3 <- make_style("yellow3", colors = 8)
expect_equal(attr(yellow, "_styles")[[1]],
attr(yellow3, "_styles")[[1]])
})
test_that("we can create a style from an R color", {
red4 <- make_style("red4")
red_text <- red4("text")
expect_true(!has_color() || has_style(red_text))
})
crayon/tests/testthat/test-operations.R 0000644 0001762 0000144 00000017070 14201156733 020041 0 ustar ligges users
str <- c("",
"plain",
"\033[31m",
"\033[39m",
"\033[31mred\033[39m",
"\033[31mred\033[39m\033[31mred\033[39m",
"foo\033[31mred\033[39m",
"\033[31mred\033[39mfoo")
test_that("col_nchar", {
for (s in str) {
expect_equal(col_nchar(s), nchar(strip_style(s)), info = s)
}
})
test_that("col_substr", {
for (s in str) {
for (i in 1 %:% col_nchar(s)) {
for (j in i %:% col_nchar(s)) {
expect_equal(strip_style(col_substr(s, i, j)),
substr(strip_style(s), i, j), info = paste(s, i, j))
}
}
}
})
test_that("col_substr keeps color", {
expect_equal(col_substr("\033[31mred\033[39m", 1, 1),
"\033[31mr\033[39m")
expect_equal(col_substr("foo\033[31mred\033[39m", 4, 4),
"\033[31mr\033[39m")
expect_equal(col_substr("foo\033[31mred\033[39mbar", 4, 4),
"\033[31mr\033[39m")
expect_equal(col_substr("\033[31mred\033[39mfoo\033[31mred\033[39mbar", 7, 7),
"\033[31m\033[39m\033[31mr\033[39m")
})
test_that("col_substr, start after string end", {
expect_equal(col_substr("red", 4, 4), "")
expect_equal(col_substr("red", 4, 5), "")
expect_equal(strip_style(col_substr("\033[31mred\033[39m", 4, 4)), "")
expect_equal(strip_style(col_substr("\033[31mred\033[39m", 4, 5)), "")
expect_equal(col_substr("red", 3, 4), "d")
expect_equal(col_substr("red", 3, 5), "d")
expect_equal(strip_style(col_substr("\033[31mred\033[39m", 3, 4)), "d")
expect_equal(strip_style(col_substr("\033[31mred\033[39m", 3, 5)), "d")
})
test_that("col_substr, multiple strings", {
set.seed(42)
for (i in 1:100) {
strs <- sample(str, 4)
num_starts <- sample(1:5, 1)
num_stops <- sample(1:5, 1)
starts <- sample(1:5, num_starts, replace = TRUE)
stops <- sample(1:5, num_stops, replace = TRUE)
r1 <- strip_style(col_substr(strs, starts, stops))
r2 <- substr(strip_style(strs), starts, stops)
expect_equal(r1, r2)
}
})
test_that("col_substr corner cases", {
# Zero length input
c0 <- character(0L)
o0 <- structure(list(), class="abc")
co0 <- structure(character(0L), class="abc")
expect_identical(col_substr(c0, 1, 1), substr(c0, 1, 1))
expect_identical(col_substr(o0, 1, 1), substr(o0, 1, 1))
expect_identical(col_substr(co0, 1, 1), substr(co0, 1, 1))
expect_identical(col_substring(c0, 1, 1), substring(c0, 1, 1))
expect_identical(col_substring(o0, 1, 1), substring(o0, 1, 1))
expect_identical(col_substring(co0, 1, 1), substring(co0, 1, 1))
# Character start/stop
expect_identical(col_substr("abc", "1", 1), substr("abc", "1", 1))
expect_identical(col_substr("abc", 1, "1"), substr("abc", 1, "1"))
# non-numeric arguments cause errors; NOTE: this actually "works"
# with 'substr' but not implemented in 'col_substr'
suppressWarnings(
expect_error(col_substr("abc", "hello", 1), "non-numeric")
)
})
test_that("col_substring", {
for (s in str) {
for (i in 1 %:% col_nchar(s)) {
for (j in i %:% col_nchar(s)) {
expect_equal(strip_style(col_substring(s, i, j)),
substring(strip_style(s), i, j), info = paste(s, i, j))
}
}
}
})
test_that("col_substring, multiple strings", {
set.seed(42)
for (i in 1:100) {
strs <- sample(str, 4)
num_starts <- sample(1:5, 1)
num_stops <- sample(1:5, 1)
starts <- sample(1:5, num_starts, replace = TRUE)
stops <- sample(1:5, num_stops, replace = TRUE)
r1 <- strip_style(col_substring(strs, starts, stops))
r2 <- substring(strip_style(strs), starts, stops)
expect_equal(r1, r2)
}
})
test_that("col_substring corner cases", {
# Zero length input
c0 <- character(0L)
o0 <- structure(list(), class="abc")
co0 <- structure(character(0L), class="abc")
expect_identical(col_substring(c0, 1, 1), substring(c0, 1, 1))
expect_identical(col_substring(o0, 1, 1), substring(o0, 1, 1))
expect_identical(col_substring(co0, 1, 1), substring(co0, 1, 1))
})
test_that("col_strsplit", {
red <- "\033[31mred\033[39m"
str <- "plain-plain"
expect_equal(col_strsplit(str, "-"), strsplit(str, "-"))
str <- red %+% "-plain"
expect_equal(strip_style(col_strsplit(str, "-")[[1]]),
strsplit(strip_style(str), "-")[[1]])
expect_equal(col_strsplit(str, "e"),
list(c("\033[31mr\033[39m", "\033[31md\033[39m-plain")))
str <- red %+% "-" %+% red %+% "-" %+% red
expect_equal(strip_style(col_strsplit(str, "-")[[1]]),
strsplit(strip_style(str), "-")[[1]])
# with leading and trailing separators
str.2 <- "-" %+% red %+% "-" %+% red %+% "-" %+% red %+% "-"
expect_equal(strip_style(col_strsplit(str.2, "-")[[1]]),
strsplit(strip_style(str.2), "-")[[1]])
# greater than length 1
str.3 <- paste0("-", c(green("hello"), red("goodbye")), "-world-")
expect_equal(strip_style(unlist(col_strsplit(str.3, "-"))),
unlist(strsplit(strip_style(str.3), "-")))
})
test_that("col_strsplit multiple strings", {
red <- "\033[31mred\033[39m"
str <- c("plain-plain-" %+% red %+% "-plain-" %+% red,
red %+% "-" %+% red,
red)
r1 <- lapply(col_strsplit(str, "-"), strip_style)
r2 <- strsplit(strip_style(str), "-")
})
test_that("col_strsplit edge cases", {
expect_equal(col_strsplit("", "-"), list(character(0L)))
expect_equal(
strip_style(col_strsplit("\033[31m\033[39m", "-")[[1]]), character(0L)
)
# special cases
expect_equal(col_strsplit("", ""), strsplit("", ""))
expect_equal(col_strsplit("a", "a"), strsplit("a", "a"))
# this following test isn't working yet
expect_equal(col_strsplit("a", ""), strsplit("a", ""))
expect_equal(col_strsplit("", "a"), strsplit("", "a"))
# Longer strings
expect_identical(
col_strsplit(c("", "a", "aa"), "a"), strsplit(c("", "a", "aa"), "a")
)
expect_identical(
col_strsplit(c("abaa", "ababza"), "b."), strsplit(c("abaa", "ababza"), "b.")
)
})
test_that("Weird length 'split'", {
expect_error(col_strsplit(c("ab", "bd"), c("b", "d")), "must be character")
expect_identical(col_strsplit("ab", NULL), strsplit("ab", NULL))
expect_identical(
col_strsplit("ab", character(0L)), strsplit("ab", character(0L))
)
})
test_that("col_align", {
expect_equal(col_align(character()), character())
expect_equal(col_align("", 0), "")
expect_equal(col_align(" ", 0), " ")
expect_equal(col_align(" ", 1), " ")
expect_equal(col_align(" ", 2), " ")
expect_equal(col_align("a", 1), "a")
expect_equal(col_align(letters, 1), letters)
expect_equal(col_align(letters, 0), letters)
expect_equal(col_align(letters, -1), letters)
expect_equal(col_align(letters, 2), paste0(letters, " "))
expect_equal(col_align(letters, 3, "center"), paste0(" ", letters, " "))
expect_equal(col_align(letters, 2, "right"), paste0(" ", letters))
expect_equal(
col_align(c("foo", "foobar", "", "a"), 6, "left"),
c("foo ", "foobar", " ", "a "))
expect_equal(
col_align(c("foo", "foobar", "", "a"), 6, "center"),
c(" foo ", "foobar", " ", " a "))
expect_equal(
col_align(c("foo", "foobar", "", "a"), 6, "right"),
c(" foo", "foobar", " ", " a"))
# #54: alignment of wide characters
expect_equal(
col_align(c("foo", "\u6210\u4ea4\u65e5", "", "a"), 6, "left"),
c("foo ", "\u6210\u4ea4\u65e5", " ", "a "))
expect_equal(
col_align(c("foo", "\u6210\u4ea4\u65e5", "", "a"), 6, "center"),
c(" foo ", "\u6210\u4ea4\u65e5", " ", " a "))
expect_equal(
col_align(c("foo", "\u6210\u4ea4\u65e5", "", "a"), 6, "right"),
c(" foo", "\u6210\u4ea4\u65e5", " ", " a"))
})
crayon/tests/testthat/test-has-style.r 0000644 0001762 0000144 00000000671 14201156733 017626 0 ustar ligges users
test_that("has_style works", {
expect_false(has_style("foobar"))
for (st in names(styles)) {
expect_true(has_style(style("foobar", st)))
}
})
test_that("strip_style works", {
expect_equal("", strip_style(""))
expect_equal("foobar", strip_style("foobar"))
expect_equal("foobar", strip_style(red$underline$bold("foobar")))
for (st in names(styles)) {
expect_equal("foobar", strip_style(style("foobar", st)))
}
})
crayon/tests/testthat/test-ansi256.R 0000644 0001762 0000144 00000002535 14201156733 017045 0 ustar ligges users
## These are really basic cases...
test_that("ansi256", {
cases <- list(
list(c(0,0,0), 233),
list(c(255,0,0), 197),
list(c(0,255,0), 47),
list(c(0,0,255), 22),
list(c(255,255,255), 256)
)
for (case in cases) {
exp1 <- list(
open = paste0("\033[38;5;", case[[2]] - 1, "m"),
close = "\033[39m"
)
exp2 <- list(
open = paste0("\033[48;5;", case[[2]] - 1, "m"),
close = "\033[49m"
)
expect_equal(ansi256(case[[1]], bg = FALSE), exp1)
expect_equal(ansi256(case[[1]], bg = TRUE), exp2)
}
})
test_that("ansi256, grey", {
cases <- list(
list(c(0,0,0), 233),
list(c(128,128,128), 245),
list(c(255,255,255), 256)
)
for (case in cases) {
exp1 <- list(
open = paste0("\033[38;5;", case[[2]] - 1, "m"),
close = "\033[39m"
)
exp2 <- list(
open = paste0("\033[48;5;", case[[2]] - 1, "m"),
close = "\033[49m"
)
expect_equal(ansi256(case[[1]], grey = TRUE, bg = FALSE), exp1)
expect_equal(ansi256(case[[1]], grey = TRUE, bg = TRUE), exp2)
}
})
test_that("ansi256_rgb_index", {
cases <- list(
list(c(0,0,0), 233),
list(c(255,0,0), 197),
list(c(0,255,0), 47),
list(c(0,0,255), 22),
list(c(255,255,255), 256)
)
for (case in cases) {
expect_equal(do.call(ansi256_rgb_index, as.list(case[[1]])), case[[2]])
}
})
crayon/tests/testthat/test-color.r 0000644 0001762 0000144 00000003176 14201156733 017036 0 ustar ligges users
test_that("Coloring and highlighting works", {
local_colors()
expect_equal(underline("foo"), '\u001b[4mfoo\u001b[24m')
expect_equal(red('foo'), '\u001b[31mfoo\u001b[39m')
expect_equal(bgRed('foo'), '\u001b[41mfoo\u001b[49m')
})
test_that("Applying multiple styles at once works", {
local_colors()
expect_equal(red$bgGreen$underline('foo'),
'\u001b[31m\u001b[42m\u001b[4mfoo\u001b[24m\u001b[49m\u001b[39m')
expect_equal(underline$red$bgGreen('foo'),
'\u001b[4m\u001b[31m\u001b[42mfoo\u001b[49m\u001b[39m\u001b[24m')
})
test_that("Nested styles are supported", {
local_colors()
expect_equal(
red('foo' %+% underline$bgBlue('bar') %+% '!'),
'\u001b[31mfoo\u001b[4m\u001b[44mbar\u001b[49m\u001b[24m!\u001b[39m')
})
test_that("Nested styles of the same type are supported", {
local_colors()
expect_equal(
red('a' %+% blue('b' %+% green('c') %+% 'b') %+% 'c'),
'\u001b[31ma\u001b[34mb\u001b[32mc\u001b[34mb\u001b[31mc\u001b[39m')
})
test_that("Reset all styles", {
local_colors()
expect_equal(reset(red$bgGreen$underline('foo') %+% 'foo'),
'\033[0m\033[31m\033[42m\033[4mfoo\033[24m\033[49m\033[39mfoo\033[0m\033[22m\033[23m\033[24m\033[27m\033[28m\033[29m\033[39m\033[49m'
)
# reset, but only in middle of string
expect_equal(
red$bgGreen$underline('bunny bunny', reset(' foo '), 'foo'),
'\033[31m\033[42m\033[4mbunny bunny \033[0m foo \033[0m\033[22m\033[23m\033[4m\033[27m\033[28m\033[29m\033[31m\033[42m foo\033[24m\033[49m\033[39m'
)
})
test_that("Variable number of arguments", {
local_colors()
expect_equal(red('foo', 'bar'), '\u001b[31mfoo bar\u001b[39m')
})
crayon/tests/testthat/helper.R 0000644 0001762 0000144 00000000271 14201156733 016153 0 ustar ligges users
local_colors <- function(colors = 256, .local_envir = parent.frame()) {
withr::local_envvar(
list(R_CLI_NUM_COLORS = as.character(colors)),
.local_envir = .local_envir
)
}
crayon/tests/testthat/test-style-var.r 0000644 0001762 0000144 00000000247 14201156733 017642 0 ustar ligges users
test_that("style works", {
x1 <- style("foobar", bold)
x2 <- style("foobar", "bold")
x3 <- bold("foobar")
expect_equal(x1, x2)
expect_equal(x2, x3)
})
crayon/tests/testthat/test-utils.R 0000644 0001762 0000144 00000000465 14201156733 017016 0 ustar ligges users
test_that("non_matching", {
chr <- "abc"
splits <- crayon:::re_table("", chr)
res.mx <- cbind(start=c(1L, 1L:3L), end=0L:3L, length=c(0L, 1L, 1L, 1L))
expect_equal(crayon:::non_matching(splits, chr, empty=TRUE)[[1L]], res.mx)
expect_equal(crayon:::non_matching(splits, chr)[[1L]], res.mx[-1L,])
})
crayon/tests/testthat/test-vectors.r 0000644 0001762 0000144 00000004164 14201156733 017403 0 ustar ligges users
foobar <- c("foo", "bar")
bigyo <- c("bi", "gyo")
test_that("Coloring and highlighting works", {
local_colors()
expect_equal(underline(foobar),
c('\u001b[4mfoo\u001b[24m', '\u001b[4mbar\u001b[24m'))
expect_equal(red(foobar),
c('\u001b[31mfoo\u001b[39m', '\u001b[31mbar\u001b[39m'))
expect_equal(bgRed(foobar),
c('\u001b[41mfoo\u001b[49m', '\u001b[41mbar\u001b[49m'))
})
test_that("Applying multiple styles at once works", {
local_colors()
expect_equal(red$bgGreen$underline(foobar),
c('\u001b[31m\u001b[42m\u001b[4mfoo\u001b[24m\u001b[49m\u001b[39m',
'\u001b[31m\u001b[42m\u001b[4mbar\u001b[24m\u001b[49m\u001b[39m'))
expect_equal(underline$red$bgGreen(foobar),
c('\u001b[4m\u001b[31m\u001b[42mfoo\u001b[49m\u001b[39m\u001b[24m',
'\u001b[4m\u001b[31m\u001b[42mbar\u001b[49m\u001b[39m\u001b[24m'))
})
test_that("Nested styles are supported", {
local_colors()
expect_equal(
red(foobar %+% underline$bgBlue(bigyo) %+% '!'),
c('\u001b[31mfoo\u001b[4m\u001b[44mbi\u001b[49m\u001b[24m!\u001b[39m',
'\u001b[31mbar\u001b[4m\u001b[44mgyo\u001b[49m\u001b[24m!\u001b[39m'))
})
test_that("Nested styles of the same type are supported", {
local_colors()
aA <- c("a", "A")
bB <- c("b", "B")
cC <- c("c", "C")
expect_equal(
red(aA %+% blue(bB %+% green(cC) %+% bB) %+% cC),
c('\u001b[31ma\u001b[34mb\u001b[32mc\u001b[34mb\u001b[31mc\u001b[39m',
'\u001b[31mA\u001b[34mB\u001b[32mC\u001b[34mB\u001b[31mC\u001b[39m'))
})
test_that("Reset all styles", {
local_colors()
expect_equal(reset(red$bgGreen$underline(foobar) %+% foobar),
c("\033[0m\033[31m\033[42m\033[4mfoo\033[24m\033[49m\033[39mfoo\033[0m\033[22m\033[23m\033[24m\033[27m\033[28m\033[29m\033[39m\033[49m", "\033[0m\033[31m\033[42m\033[4mbar\033[24m\033[49m\033[39mbar\033[0m\033[22m\033[23m\033[24m\033[27m\033[28m\033[29m\033[39m\033[49m")
)
})
test_that("Variable number of arguments", {
local_colors()
expect_equal(red(foobar, 'bar'),
c('\u001b[31mfoo bar\u001b[39m',
'\u001b[31mbar bar\u001b[39m'))
})
crayon/tests/testthat.R 0000644 0001762 0000144 00000000070 14220353764 014675 0 ustar ligges users
library(crayon)
library(testthat)
test_check("crayon")
crayon/R/ 0000755 0001762 0000144 00000000000 14315032112 011736 5 ustar ligges users crayon/R/machinery.r 0000644 0001762 0000144 00000024125 14301445747 014125 0 ustar ligges users
## ----------------------------------------------------------------------
crayon_template <- function(...) {
my_styles <- attr(sys.function(), "_styles")
text <- mypaste(...)
nc <- num_ansi_colors()
if (nc > 1) {
for (st in rev(my_styles)) {
if (!is.null(st$palette)) st <- get_palette_color(st, nc)
text <- st$open %+%
gsub_(st$close, st$open, text, fixed = TRUE, useBytes = TRUE) %+%
st$close
}
}
text
}
hash_color_regex <- "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$"
is_builtin_style <- function(x) {
is_string(x) && x %in% names(builtin_styles)
}
#' @importFrom grDevices colors
is_r_color <- function(x) {
if (!is.character(x) || length(x) != 1 || is.na(x)) {
FALSE
} else {
x %in% grDevices::colors() || grepl(hash_color_regex, x)
}
}
is_rgb_matrix <- function(x) {
is.matrix(x) && is.numeric(x) && (nrow(x) == 3 || nrow(x) == 4)
}
#' @importFrom grDevices col2rgb
ansi_style_from_r_color <- function(color, bg, num_colors, grey) {
style_from_rgb(col2rgb(color), bg, num_colors, grey)
}
# multicolor depends on this name, apparently
style_from_r_color <- ansi_style_from_r_color
style_8_from_rgb <- function(rgb, bg) {
ansi_cols <- if (bg) ansi_bg_rgb else ansi_fg_rgb
dist <- colSums((ansi_cols - as.vector(rgb)) ^ 2 )
builtin_name <- names(which.min(dist))[1]
builtin_styles[[builtin_name]]
}
style_from_rgb <- function(rgb, bg, num_colors, grey) {
if (num_colors < 256) { return(style_8_from_rgb(rgb, bg)) }
ansi256(rgb, bg, grey)
}
#' Create an ANSI color style
#'
#' Create a style, or a style function, or both. This function
#' is intended for those who wish to use 256 ANSI colors,
#' instead of the more widely supported eight colors.
#'
#' @details
#' The crayon package comes with predefined styles (see
#' [styles()] for a list) and functions for the basic eight-color
#' ANSI standard (`red`, `blue`, etc., see \link{crayon}).
#'
#' There are no predefined styles or style functions for the 256 color
#' ANSI mode, however, because we simply did not want to create that
#' many styles and functions. Instead, `make_style()` can be
#' used to create a style (or a style function, or both).
#'
#' There are two ways to use this function: \enumerate{
#' \item If its first argument is not named, then it returns a function
#' that can be used to color strings.
#' \item If its first argument is named, then it also creates a
#' style with the given name. This style can be used in
#' [style()]. One can still use the return value
#' of the function, to create a style function.
#' }
#'
#' The style (the code{...} argument) can be anything of the
#' following: \itemize{
#' \item An R color name, see [colors()].
#' \item A 6- or 8-digit hexa color string, e.g. `#ff0000` means
#' red. Transparency (alpha channel) values are ignored.
#' \item A one-column matrix with three rows for the red, green
#' and blue channels, as returned by `col2rgb` (in the base
#' grDevices package).
#' }
#'
#' `make_style()` detects the number of colors to use
#' automatically (this can be overridden using the `colors`
#' argument). If the number of colors is less than 256 (detected or given),
#' then it falls back to the color in the ANSI eight color mode that
#' is closest to the specified (RGB or R) color.
#'
#' See the examples below.
#'
#' @param ... The style to create. See details and examples below.
#' @param bg Whether the color applies to the background.
#' @param grey Whether to specifically create a grey color.
#' This flag is included because ANSI 256 has a finer color scale
#' for greys than the usual 0:5 scale for R, G and B components.
#' It is only used for RGB color specifications (either numerically
#' or via a hexa string) and is ignored on eigth color ANSI
#' terminals.
#' @param colors Number of colors, detected automatically
#' by default.
#' @return A function that can be used to color strings.
#'
#' @family styles
#' @export
#' @examples
#' ## Create a style function without creating a style
#' pink <- make_style("pink")
#' bgMaroon <- make_style(rgb(0.93, 0.19, 0.65), bg = TRUE)
#' cat(bgMaroon(pink("I am pink if your terminal wants it, too.\n")))
#'
#' ## Create a new style for pink and maroon background
#' make_style(pink = "pink")
#' make_style(bgMaroon = rgb(0.93, 0.19, 0.65), bg = TRUE)
#' "pink" %in% names(styles())
#' "bgMaroon" %in% names(styles())
#' cat(style("I am pink, too!\n", "pink", bg = "bgMaroon"))
make_style <- function(..., bg = FALSE, grey = FALSE,
colors = num_colors()) {
args <- list(...)
stopifnot(length(args) == 1)
style <- args[[1]]
orig_style_name <- style_name <- names(args)[1]
stopifnot(is.character(style) && length(style) == 1 ||
is_rgb_matrix(style) && ncol(style) == 1,
is.logical(bg) && length(bg) == 1,
is.numeric(colors) && length(colors) == 1)
ansi_seqs <- if (is_builtin_style(style)) {
if (bg && substr(style, 1, 2) != "bg") {
style <- "bg" %+% capitalize(style)
}
if (is.null(style_name)) style_name <- style
builtin_styles[[style]]
} else if (is_r_color(style)) {
if (is.null(style_name)) style_name <- style
ansi_style_from_r_color(style, bg, colors, grey)
} else if (is_rgb_matrix(style)) {
style_from_rgb(style, bg, colors, grey)
} else {
stop("Unknown style specification: ", style)
}
if (!is.null(orig_style_name)) define_style(orig_style_name, ansi_seqs)
make_crayon(structure(list(ansi_seqs), names = style_name))
}
make_crayon <- function(ansi_seq) {
crayon <- crayon_template
attr(crayon, "_styles") <- ansi_seq
class(crayon) <- "crayon"
crayon
}
#' @include styles.r
#'
#' @usage
#' ## Simple styles
#' red(...)
#' bold(...)
#' # ...
#'
#' ## See more styling below
#'
#' @param ... Strings to style.
#' @name crayon
#
#' @details
#'
#' Crayon defines several styles, that can be combined. Each style in the list
#' has a corresponding function with the same name.
#'
#' @section Genaral styles:
#'
#' \itemize{
#' \item reset
#' \item bold
#' \item blurred (usually called \sQuote{dim}, renamed to avoid name clash)
#' \item italic (not widely supported)
#' \item underline
#' \item inverse
#' \item hidden
#' \item strikethrough (not widely supported)
#' }
#'
#' @section Text colors:
#'
#' \itemize{
#' \item black
#' \item red
#' \item green
#' \item yellow
#' \item blue
#' \item magenta
#' \item cyan
#' \item white
#' \item silver (usually called \sQuote{gray}, renamed to avoid name clash)
#' }
#'
#' @section Background colors:
#'
#' \itemize{
#' \item bgBlack
#' \item bgRed
#' \item bgGreen
#' \item bgYellow
#' \item bgBlue
#' \item bgMagenta
#' \item bgCyan
#' \item bgWhite
#' }
#'
#' @section Styling:
#'
#' The styling functions take any number of character vectors as arguments,
#' and they concatenate and style them: \preformatted{ library(crayon)
#' cat(blue("Hello", "world!\n"))
#' }
#'
#' Crayon defines the \code{\%+\%} string concatenation operator, to make it easy
#' to assemble stings with different styles. \preformatted{ cat("... to highlight the " \%+\% red("search term") \%+\%
#' " in a block of text\n")
#' }
#'
#' Styles can be combined using the `$` operator: \preformatted{ cat(yellow$bgMagenta$bold('Hello world!\n'))
#' } See also [combine_styles()].
#'
#' Styles can also be nested, and then inner style takes
#' precedence: \preformatted{ cat(green(
#' 'I am a green line ' \%+\%
#' blue$underline$bold('with a blue substring') \%+\%
#' ' that becomes green again!\n'
#' ))
#' }
#'
#' It is easy to define your own themes: \preformatted{ error <- red $ bold
#' warn <- magenta $ underline
#' note <- cyan
#' cat(error("Error: subscript out of bounds!\n"))
#' cat(warn("Warning: shorter argument was recycled.\n"))
#' cat(note("Note: no such directory.\n"))
#' }
#'
#' @aliases
#' reset bold blurred italic underline inverse hidden strikethrough
#' black red green yellow blue magenta cyan white silver
#' bgBlack bgRed bgGreen bgYellow bgBlue bgMagenta bgCyan bgWhite
#'
#' @export reset bold blurred italic underline inverse hidden strikethrough
#' @export black red green yellow blue magenta cyan white silver
#' @export bgBlack bgRed bgGreen bgYellow bgBlue bgMagenta bgCyan bgWhite
#'
#' @seealso [make_style()] for using the 256 ANSI colors.
#' @examples
#' cat(blue("Hello", "world!"))
#'
#' cat("... to highlight the " %+% red("search term") %+%
#' " in a block of text")
#'
#' cat(yellow$bgMagenta$bold('Hello world!'))
#'
#' cat(green(
#' 'I am a green line ' %+%
#' blue$underline$bold('with a blue substring') %+%
#' ' that becomes green again!'
#' ))
#'
#' error <- red $ bold
#' warn <- magenta $ underline
#' note <- cyan
#' cat(error("Error: subscript out of bounds!\n"))
#' cat(warn("Warning: shorter argument was recycled.\n"))
#' cat(note("Note: no such directory.\n"))
#'
NULL
#' ANSI escape sequences of crayon styles
#'
#' You can use this function to list all availables crayon styles,
#' via `names(styles())`, or to explicitly apply an ANSI
#' escape seauence to a string.
#'
#' @return A named list. Each list element is a list of two
#' strings, named \sQuote{open} and \sQuote{close}.
#'
#' @seealso [crayon()] for the beginning of the crayon manual.
#' @export
#' @examples
#' names(styles())
#' cat(styles()[["bold"]]$close)
styles <- function() {
data_env$my_styles
}
data_env <- new.env(parent = emptyenv())
data_env$my_styles <- structure(list(), names = character())
sapply(names(builtin_styles), function(style) {
data_env$my_styles[[style]] <- builtin_styles[[style]]
assign(style, make_style(style), envir = asNamespace("crayon"))
})
define_style <- function(name, ansi_seq) {
data_env$my_styles[[name]] <- ansi_seq
}
#' Remove a style
#'
#' @param style The name of the style to remove. No error is given
#' for non-existing names.
#' @return Nothing.
#'
#' @family styles
#' @export
#' @examples
#' make_style(new_style = "maroon", bg = TRUE)
#' cat(style("I am maroon", "new_style"), "\n")
#' drop_style("new_style")
#' "new_style" %in% names(styles())
drop_style <- function(style) {
data_env$my_styles[[style]] <- NULL
invisible()
}
crayon/R/has_color.r 0000644 0001762 0000144 00000001553 14201156733 014110 0 ustar ligges users
#' Does the current R session support ANSI colors?
#'
#' From crayon 2.0.0, this function is simply a wrapper on
#' [num_ansi_colors()].
#'
#' @return `TRUE` if the current R session supports color.
#'
#' @export
#' @examples
#' has_color()
has_color <- function() {
num_ansi_colors() > 1L
}
#' Number of colors the terminal supports
#'
#' From crayon version 2.0.0, this function is a simple wrapper on
#' [num_ansi_colors()], with the additional twist that the `crayon.colors`
#' option is still obseved, and takes precedence, for compatibility.
#'
#' @param forget Ignored. Included for backwards compatibility.
#' @return Number of ANSI colors.
#'
#' @export
#' @examples
#' num_colors()
num_colors <- function(forget = FALSE) {
cray_opt_num <- getOption("crayon.colors", NULL)
if (!is.null(cray_opt_num)) return(as.integer(cray_opt_num))
num_ansi_colors()
}
crayon/R/utils.r 0000644 0001762 0000144 00000006534 14301445731 013303 0 ustar ligges users
is_string <- function(x) {
is.character(x) && length(x) == 1 && !is.na(x)
}
check_string <- function(x) {
stopifnot(is_string(x))
}
mypaste <- function(..., sep = " ") {
args <- lapply(list(...), as.character)
len <- setdiff(sapply(args, length), 1)
if (length(len) > 1) {
stop("All character vectors must have the same length (or length 1)")
}
paste(..., sep = sep)
}
scale <- function(x, from = c(0, 255), to = c(0, 5), round = TRUE) {
y <- (x - from[1]) /
(from[2] - from[1]) *
(to[2] - to[1]) +
to[1]
if (round) {
round(y)
} else {
y
}
}
capitalize <- function(x) {
substr(x, 1, 1) <- toupper(substr(x, 1, 1))
x
}
multicol <- function(x) {
xs <- strip_style(x)
max_len <- max(nchar(xs))
to_add <- max_len - nchar(xs)
x <- paste0(x, substring(" ", 1, to_add))
screen_width <- getOption("width")
num_cols <- trunc(screen_width / max_len)
num_rows <- ceiling(length(x) / num_cols)
x <- c(x, rep("", num_cols * num_rows - length(x)))
xm <- matrix(x, ncol = num_cols, byrow = TRUE)
apply(xm, 1, paste, collapse = "") %+% "\n"
}
re_table <- function(...) {
lapply(gregexpr(...), function(x) {
res <- cbind(
start = x,
end = x + attr(x, "match.length") - 1,
length = attr(x, "match.length")
)
res <- res[res[, "start"] != -1, , drop=FALSE]
})
}
## Create the non-matching table from the matching table
non_matching <- function(table, str, empty = FALSE) {
mapply(table, str, SIMPLIFY = FALSE, FUN = function(t, s) {
if (! nrow(t)) {
cbind(start = 1, end = base::nchar(s), length = base::nchar(s))
} else {
start <- c(1, t[, "end"] + 1)
end <- c(t[, "start"] - 1, base::nchar(s))
res <- cbind(start = start, end = end, length = end - start + 1)
if (!empty) res[ res[, "length"] != 0, , drop = FALSE ] else res
}
})
}
myseq <- function(from, to, by = 1) {
stopifnot(by != 0)
if (by > 0) {
if (to < from) {
integer()
} else {
seq(from, to, by = by)
}
} else {
if (to > from) {
integer()
} else {
seq(from, to, by = by)
}
}
}
`%:%` <- myseq
emacs_version <- function() {
ver <- Sys.getenv("INSIDE_EMACS")
ver <- gsub("[^0-9\\.]+", "", ver)
if (ver == "") return(NA_integer_)
ver <- strsplit(ver, ".", fixed = TRUE)[[1]]
as.numeric(ver)
}
inside_emacs <- function() {
Sys.getenv("EMACS") != "" || Sys.getenv("INSIDE_EMACS") != ""
}
rstudio_with_ansi_support <- function() {
if (Sys.getenv("RSTUDIO", "") == "") return(FALSE)
## This is set *before* the rstudio initialization, in 1.1 and above
if ((cols <- Sys.getenv("RSTUDIO_CONSOLE_COLOR", "")) != "" &&
!is.na(as.numeric(cols))) {
return(TRUE)
}
## This only works if the initialization is complete
requireNamespace("rstudioapi", quietly = TRUE) &&
rstudioapi::isAvailable() &&
rstudioapi::hasFun("getConsoleHasColor")
}
rstudio_initialized <- function() {
## Not in RStudio, so no worries
rs <- Sys.getenv("RSTUDIO")
if (rs == "" || rs == "0") return(TRUE)
## Otherwise check
requireNamespace("rstudioapi", quietly = TRUE) &&
rstudioapi::isAvailable()
}
os_type <- function() {
.Platform$OS.type
}
rstudio_detect <- function() {
rstudio$detect()
}
is_count <- function(x) {
is.numeric(x) &&
length(x) == 1 &&
!is.na(x) &&
as.integer(x) == x &&
x >= 0
}
crayon/R/ansi-256.r 0000644 0001762 0000144 00000002374 14201156733 013405 0 ustar ligges users
# nocov start
fgcodes <- c(paste0('\x1b[38;5;', 0:255, 'm'), '\x1b[39m')
bgcodes <- c(paste0('\x1b[48;5;', 0:255, 'm'), '\x1b[49m')
rgb_index <- 17:232
gray_index <- 233:256
reset_index <- 257
#nocov end
ansi256 <- function(rgb, bg = FALSE, grey = FALSE) {
codes <- if (bg) bgcodes else fgcodes
if (grey) {
## Gray
list(
open = codes[gray_index][scale(rgb[1], to = c(0, 23)) + 1],
close = codes[reset_index]
)
} else {
## Not gray
list(
open = codes[ansi256_rgb_index(rgb[1L], rgb[2L], rgb[3L])],
close = codes[reset_index]
)
}
}
## This is based off the algorithm in the ruby "paint" gem, as
## implemented in rainbowrite.
ansi256_rgb_index <- function(red, green, blue) {
gray_possible <- TRUE
sep <- 42.5
while (gray_possible) {
if (red < sep || green < sep || blue < sep) {
gray <- red < sep && green < sep && blue < sep
gray_possible <- FALSE
}
sep <- sep + 42.5
}
## NOTE: The +1 here translates from base0 to base1 for the index
## that does the same. Not ideal, but that does get the escape
## characters in nicely.
if (gray) {
232 + round((red + green + blue) / 33) + 1
} else {
16 + sum(floor(6 * c(red, green, blue) / 256) * c(36, 6, 1)) + 1
}
}
crayon/R/show.r 0000644 0001762 0000144 00000002710 14201156733 013113 0 ustar ligges users
#' @include style-var.r
NULL
#' Show the ANSI color table on the screen
#'
#' @param colors Number of colors to show, meaningful values
#' are 8 and 256. It is automatically set to the number of
#' supported colors, if not specified.
#' @return The printed string, invisibly.
#'
#' @export
show_ansi_colors <- function(colors = num_colors()) {
if (colors < 8) {
cat("Colors are not supported")
} else if (colors < 256) {
cat(ansi_colors_8(), sep = "")
invisible(ansi_colors_8)
} else {
cat(ansi_colors_256(), sep = "")
invisible(ansi_colors_256)
}
}
#' @importFrom grDevices rgb
ansi_colors_256_col <- function() {
sapply(0:5, function(r) {
sapply(0:5, function(g) {
c(sapply(0:5, function(b) {
s <- paste0("r:", r, " g:", g, " b:", b, " ")
style(s, as = "grey", bg = rgb(r, g, b, maxColorValue = 5))
}), "\n")
})
})
}
#' @importFrom grDevices grey
ansi_colors_256_grey <- function() {
sapply(0:23, function(g) {
s <- paste0(" grey ", format(g, width = 2), " ")
style(s, as = "grey",
bg = make_style(grey(g / 23), grey = TRUE, bg = TRUE)) %+%
(if ((g + 1) %% 6) "" else "\n")
})
}
ansi_colors_256 <- function() {
c(ansi_colors_256_col(), "\n", ansi_colors_256_grey())
}
ansi_colors_8 <- function () {
multicol(sapply(seq_along(builtin_styles), function(s) {
st <- names(builtin_styles)[s]
styled <- st %+% ": " %+% style("foobar", as = st) %+% " "
}))
}
crayon/R/string.r 0000644 0001762 0000144 00000003110 14201156733 013434 0 ustar ligges users
#' Convert to character
#'
#' This function just calls [as.character()], but it is
#' easier to type and read.
#'
#' @param x Object to be coerced.
#' @param ... Further arguments to pass to `as.character()`.
#' @return Character value.
#'
#' @export
chr <- function(x, ...) as.character(x, ...)
#' Concatenate character vectors
#'
#' The length of the two arguments must match, or
#' one of them must be of length one. If the length of
#' one argument is one, then the output's length will
#' match the length of the other argument. See examples
#' below.
#'
#' @param lhs Left hand side, character vector.
#' @param rhs Right hand side, character vector.
#' @return Concatenated vectors.
#'
#' @name concat
#' @export
#'
#' @examples
#' "foo" %+% "bar"
#'
#' letters[1:10] %+% chr(1:10)
#'
#' letters[1:10] %+% "-" %+% chr(1:10)
#'
#' ## This is empty (unlike for parse)
#' character() %+% "*"
`%+%` <- function(lhs, rhs) {
stopifnot(is.character(lhs), is.character(rhs))
stopifnot(length(lhs) == length(rhs) || length(lhs) == 1 || length(rhs) == 1)
if (length(lhs) == 0 && length(rhs) == 0) {
paste0(lhs, rhs)
} else if (length(lhs) == 0) {
lhs
} else if (length(rhs) == 0) {
rhs
} else {
paste0(lhs, rhs)
}
}
#' @export
as.character.crayon <- function(x, ...) {
start(x)
}
#' @export
`-.crayon` <- function(e1, e2) {
if (!missing(e2)) {
base::`-`(e1, e2)
}
my_styles <- attr(e1, "_styles")
if (has_color()) {
for (i in seq_along(my_styles)) {
my_styles[[i]]$open <- my_styles[[i]]$close
}
}
attr(e1, "_styles") <- my_styles
e1
}
crayon/R/aab-num-ansi-colors.R 0000644 0001762 0000144 00000025256 14301446023 015647 0 ustar ligges users
#' Detect the number of ANSI colors to use
#'
#' @description
#' Certain Unix and Windows terminals, and also certain R GUIs, e.g.
#' RStudio, support styling terminal output using special control
#' sequences (ANSI sequences).
#'
#' `num_ansi_colors()` detects if the current R session supports ANSI
#' sequences, and if it does how many colors are supported.
#'
#' @param stream The stream that will be used for output, an R connection
#' object. It can also be a string, one of `"auto"`, `"message"`,
#' `"stdout"`, `"stderr"`. `"auto"` will select `stdout()` if the session is
#' interactive and there are no sinks, otherwise it will select `stderr()`.
#' @return Integer, the number of ANSI colors the current R session
#' supports for `stream`.
#'
#' @family ANSI styling
#' @export
#' @examples
#' num_ansi_colors()
#'
#' @details
#' The detection mechanism is quite involved and it is designed to work
#' out of the box on most systems. If it does not work on your system,
#' please report a bug. Setting options and environment variables to turn
#' on ANSI support is error prone, because they are inherited in other
#' environments, e.g. knitr, that might not have ANSI support.
#'
#' If you want to _turn off_ ANSI colors, set the `NO_COLOR` environment
#' variable to a non-empty value.
#'
#' The exact detection mechanism is as follows:
num_ansi_colors <- function(stream = "auto") {
#' 1. If the `cli.num_colors` options is set, that is returned.
opt <- getOption("cli.num_colors", NULL)
if (!is.null(opt)) return(as.integer(opt))
#' 1. If the `R_CLI_NUM_COLORS` environment variable is set to a
#' non-empty value, then it is used.
if ((env <- Sys.getenv("R_CLI_NUM_COLORS", "")) != "") {
return(as.integer(env))
}
#' 1. If the `crayon.enabled` option is set to `FALSE`, 1L is returned.
#' (This is for compatibility with code that uses the crayon package.)
#' 1. If the `crayon.enabled` option is set to `TRUE` and the
#' `crayon.colors` option is not set, then the value of the
#' `cli.default_num_colors` option, or if it is unset, then 8L is
#' returned.
#' 1. If the `crayon.enabled` option is set to `TRUE` and the
#' `crayon.colors` option is also set, then the latter is returned.
#' (This is for compatibility with code that uses the crayon package.)
cray_opt_has <- getOption("crayon.enabled", NULL)
cray_opt_num <- getOption("crayon.colors", NULL)
if (!is.null(cray_opt_has) && !isTRUE(cray_opt_has)) return(1L)
if (isTRUE(cray_opt_has) && !is.null(cray_opt_num)) {
return(as.integer(cray_opt_num))
}
if (isTRUE(cray_opt_has) && is.null(cray_opt_num)) {
default <- get_default_number_of_colors()
return(default %||% 8L)
}
#' 1. If the `NO_COLOR` environment variable is set, then 1L is returned.
if (!is.na(Sys.getenv("NO_COLOR", NA_character_))) return(1L)
#' 1. If we are in knitr, then 1L is returned, to turn off colors in
#' `.Rmd` chunks.
if (isTRUE(getOption("knitr.in.progress"))) return(1L)
#' 1. If `stream` is `"auto"` (the default) and there is an active
#' sink (either for `"output"` or `"message"`), then we return 1L.
#' (In theory we would only need to check the stream that will be
#' be actually used, but there is no easy way to tell that.)
if (stream == "auto" && !no_sink()) return(1L)
# Defer computation on streams to speed up common case
# when environment variables are set
orig_stream <- stream
stream <- get_real_output(stream)
is_stdout <- is_stderr <- is_std <- FALSE
std <- "nope"
if (identical(stream, stdout())) {
is_stdout <- is_std <- TRUE
std <- "stdout"
} else if (identical(stream, stderr())) {
is_stderr <- is_std <- TRUE
std <- "stderr"
}
#' 1. If `stream` is not `"auto"`, but it is `stderr()` and there is an
#' active sink for it, then 1L is returned.
#' (If a sink is active for "output", then R changes the `stdout()`
#' stream, so this check is not needed.)
# If a sink is active for "message" (ie. stderr), then R does not update
# the `stderr()` stream, so we need to catch this case.
if (is_stderr && sink.number("message") != 2) return(1L)
#' 1. If R is running inside RGui on Windows, or R.app on macOS, then we
#' return 1L.
# RStudio sets GUI to RGui initially, so we'll handle that after RStudio.
if (.Platform$GUI == "AQUA") return(1L)
#' 1. If R is running inside RStudio, with color support, then the
#' appropriate number of colors is returned, usually 256L.
rstudio <- rstudio$detect()
rstudio_colors <- c(
"rstudio_console",
"rstudio_console_starting",
"rstudio_build_pane",
"rstudio_job"
)
if (is.na(rstudio$num_colors)) rstudio$num_colors <- 1L
if (rstudio$type %in% rstudio_colors && is_std) {
return(rstudio$num_colors)
}
# RGui? We need to do this after RStudio, because .Platform$GUI is
# "Rgui" in RStudio when we are starting up
if (.Platform$GUI == "Rgui") return(1L)
#' 1. If R is running on Windows, inside an Emacs version that is recent
#' enough to support ANSI colors, then the value of the
#' `cli.default_num_colors` option, or if unset 8L is returned.
#' (On Windows, Emacs has `isatty(stdout()) == FALSE`, so we need to
#' check for this here before dealing with terminals.)
# Windows Emacs? The top R process will have `--ess` in ESS, but the
# subprocesses won't. (Without ESS subprocesses will also report 8L
# colors, this is a problem, but we expect most people use ESS in Emacs.)
if (os_type() == "windows" &&
"--ess" %in% commandArgs() &&
is_emacs_with_color()) {
default <- get_default_number_of_colors()
return(default %||% 8L)
}
#' 1. If `stream` is not the standard output or standard error in a
#' terminal, then 1L is returned.
if (!isatty(stream)) return(1L)
if (!is_std) return(1L)
#' 1. Otherwise we use and cache the result of the terminal color
#' detection (see below).
# Otherwise use/set the cache
if (is.null(clienv$num_colors)) clienv$num_colors <- list()
clienv$num_colors[[std]] <- clienv$num_colors[[std]] %||% detect_tty_colors()
clienv$num_colors[[std]]
}
#' @rdname num_ansi_colors
#' @details
#' The terminal color detection algorithm:
detect_tty_colors <- function() {
default <- get_default_number_of_colors()
#' 1. If the `COLORTERM` environment variable is set to `truecolor` or
#' `24bit`, then we return 16 million colors.
#' 1. If the `COLORTERM` environment variable is set to anything else,
#' then we return the value of the `cli.num_default_colors` option,
#' 8L if unset.
ct <- Sys.getenv("COLORTERM", NA_character_)
if (!is.na(ct)) {
if (ct == "truecolor" || ct == "24bit") {
return(truecolor)
} else {
return(default %||% 8L)
}
}
#' 1. If R is running on Unix, inside an Emacs version that is recent
#' enough to support ANSI colors, then the value of the
#' `cli.default_num_colors` option is returned, or 8L if unset.
if (os_type() == "unix" && is_emacs_with_color()) return(default %||% 8L)
#' 1. If we are on Windows in an RStudio terminal, then apparently
#' we only have eight colors, but the `cli.default_num_colors` option
#' can be used to override this.
win10 <- win10_build()
if (os_type() == "windows" && win10 >= 10586 &&
rstudio_detect()$type == "rstudio_terminal") {
# this is rather weird, but echo turns on color support :D
system2("cmd", c("/c", "echo 1 >NUL"))
return(default %||% 8L)
}
#' 1. If we are in a recent enough Windows 10 terminal, then there
#' is either true color (from build 14931) or 256 color (from
#' build 10586) support. You can also use the `cli.default_num_colors`
#' option to override these.
if (os_type() == "windows" && win10 >= 10586) {
# this is rather weird, but echo turns on color support :D
system2("cmd", c("/c", "echo 1 >NUL"))
# https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/
if (win10 >= 14931) {
return(default %||% truecolor)
} else {
return(default %||% 256L)
}
}
if (os_type() == "windows") {
#' 1. If we are on Windows, under ConEmu or cmder, or ANSICON is loaded,
#' then the value of `cli.default_num_colors`, or 8L if unset, is
#' returned.
if (Sys.getenv("ConEmuANSI") == "ON" ||
Sys.getenv("CMDER_ROOT") != "") {
return(default %||% 8L)
}
if (Sys.getenv("ANSICON") != "") return(default %||% 8L)
#' 1. Otherwise if we are on Windows, return 1L.
return(1L)
}
#' 1. Otherwise we are on Unix and try to run `tput colors` to determine
#' the number of colors. If this succeeds, we return its return value.
cols <- suppressWarnings(try(
silent = TRUE,
as.numeric(system("tput colors 2>/dev/null", intern = TRUE))[1]
))
if (inherits(cols, "try-error") || !length(cols) || is.na(cols)) {
return(guess_tty_colors())
}
if (cols %in% c(-1, 0, 1)) { return(1) }
#' If the `TERM` environment variable is `xterm` and `tput`
#' returned 8L, we return 256L, because xterm compatible terminals
#' tend to support 256 colors
#' ()
#' You can override this with the `cli.default_num_colors` option.
if (cols == 8 && identical(Sys.getenv("TERM"), "xterm")) {
cols <- default %||% 256
}
#' 1. If `TERM` is set to `dumb`, we return 1L.
#' 1. If `TERM` starts with `screen`, `xterm`, or `vt100`, we return 8L.
#' 1. If `TERM` contains `color`, `ansi`, `cygwin` or `linux`, we return 8L.
#' 1. Otherwise we return 1L.
cols
}
get_default_number_of_colors <- function() {
dft <- getOption("cli.default_num_colors")
if (!is.null(dft)) {
if (!is_count(dft)) {
warning(
"The `cli.default_num_colors` option must be an integer scalar"
)
dft <- NULL
}
}
dft
}
guess_tty_colors <- function() {
term <- Sys.getenv("TERM")
if (term == "dumb") return (1L)
if (grepl(
"^screen|^xterm|^vt100|color|ansi|cygwin|linux",
term,
ignore.case = TRUE,
perl = TRUE
)) {
8L
} else {
1L
}
}
is_emacs_with_color <- function() {
(Sys.getenv("EMACS") != "" || Sys.getenv("INSIDE_EMACS") != "") &&
! is.na(emacs_version()[1]) && emacs_version()[1] >= 23
}
emacs_version <- function() {
ver <- Sys.getenv("INSIDE_EMACS")
if (ver == "") return(NA_integer_)
ver <- gsub("'", "", ver)
ver <- strsplit(ver, ",", fixed = TRUE)[[1]]
ver <- strsplit(ver, ".", fixed = TRUE)[[1]]
as.numeric(ver)
}
win10_build <- function() {
os <- utils::sessionInfo()$running %||% ""
if (!grepl("^Windows 10 ", os)) return(0L)
mch <- re_match(os, "[(]build (?[0-9]+)[)]")
mch <- suppressWarnings(as.integer(mch))
if (is.na(mch)) return(0L)
mch
}
crayon/R/disposable.r 0000644 0001762 0000144 00000006503 14201156733 014264 0 ustar ligges users
## nocov start
install_quietly <- TRUE
with_wd <- function(dir, expr) {
wd <- getwd()
on.exit(setwd(wd))
setwd(dir)
eval(substitute(expr), envir = parent.frame())
}
#' @importFrom utils tar
build_pkg <- function(path, pkg_file = NULL) {
if (!file.exists(path)) stop("path does not exist")
pkg_name <- basename(path)
if (is.null(pkg_file)) {
pkg_file <- file.path(dirname(path), paste0(pkg_name, "_1.0.tar.gz"))
}
with_wd(dirname(path),
tar(basename(pkg_file), pkg_name, compression = "gzip"))
pkg_file
}
#' @importFrom utils package.skeleton install.packages
install_tmp_pkg <- function(..., pkg_name, lib_dir, imports = character()) {
if (!file.exists(lib_dir)) stop("lib_dir does not exist")
if (!is.character(pkg_name) || length(pkg_name) != 1) {
stop("pkg_name is not a string")
}
## Create a directory that will contain the source package
src_dir <- tempfile()
on.exit(try(unlink(src_dir, recursive = TRUE), silent = TRUE), add = TRUE)
dir.create(src_dir)
## Create source package, need a non-empty environment,
## otherwise package.skeleton fails
tmp_env <- new.env()
assign("f", function(x) x, envir = tmp_env)
suppressMessages(package.skeleton(pkg_name, path = src_dir,
environment = tmp_env))
pkg_dir <- file.path(src_dir, pkg_name)
## Make it installable: remove man, add imports
unlink(file.path(pkg_dir, "man"), recursive = TRUE)
if (length(imports) != 0) {
cat("Imports: ", paste(imports, collapse = ", "), "\n",
file = file.path(pkg_dir, "DESCRIPTION"), append = TRUE)
cat(paste0("import(", imports, ")"), sep="\n",
file = file.path(pkg_dir, "NAMESPACE"), append = TRUE)
}
## Put the code in it, dput is noisy, so we need to redirect it to
## temporary file
exprs <- list(...)
unlink(file.path(pkg_dir, "R"), recursive = TRUE)
dir.create(file.path(pkg_dir, "R"))
code_file <- file.path(pkg_dir, "R", "code.R")
tmp_file <- tempfile()
on.exit(try(unlink(tmp_file), silent = TRUE), add = TRUE)
sapply(exprs, function(x)
cat(deparse(dput(x, file = tmp_file)),
file = code_file, append = TRUE, "\n", sep="\n"))
## Build it
pkg_file <- build_pkg(pkg_dir)
## Install it into the supplied lib_dir
install.packages(pkg_file, lib = lib_dir, repos = NULL, type = "source",
quiet = install_quietly)
}
with_libpath <- function(lib_path, ...) {
cur_lib_path <- .libPaths()
on.exit(.libPaths(cur_lib_path), add = TRUE)
.libPaths(c(lib_path, cur_lib_path))
exprs <- c(as.list(match.call(expand.dots = FALSE)$...))
sapply(exprs, eval, envir = parent.frame())
}
make_packages <- function(..., lib_dir = tempfile(),
imports = character()) {
if (!file.exists(lib_dir)) dir.create(lib_dir)
exprs <- c(as.list(match.call(expand.dots = FALSE)$...))
for (i in seq_along(exprs)) {
expr <- exprs[[i]]
name <- names(exprs)[i]
install_tmp_pkg(expr, pkg_name = name,
lib_dir = lib_dir, imports = imports)
## Unload everything if an error happens
on.exit(try(unloadNamespace(name), silent = TRUE), add = TRUE)
with_libpath(lib_dir, suppressMessages(library(name, quietly = TRUE,
character.only = TRUE)))
on.exit()
}
invisible(lib_dir)
}
## nocov end
crayon/R/has_ansi.r 0000644 0001762 0000144 00000001550 14301446207 013720 0 ustar ligges users
ansi_regex <- paste0("(?:(?:\\x{001b}\\[)|\\x{009b})",
"(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])",
"|\\x{001b}[A-M]")
#' Check if a string has some ANSI styling
#'
#' @param string The string to check. It can also be a character
#' vector.
#' @return Logical vector, `TRUE` for the strings that have some
#' ANSI styling.
#'
#' @export
#' @examples
#' ## The second one has style if crayon is enabled
#' has_style("foobar")
#' has_style(red("foobar"))
has_style <- function(string) {
grepl(ansi_regex, string, perl = TRUE)
}
#' Remove ANSI escape sequences from a string
#'
#' @param string The input string.
#' @return The cleaned up string.
#'
#' @export
#' @examples
#' strip_style(red("foobar")) == "foobar"
strip_style <- function(string) {
gsub_(ansi_regex, "", string, perl = TRUE, useBytes = TRUE)
}
crayon/R/parts.r 0000644 0001762 0000144 00000002073 14201156733 013266 0 ustar ligges users
#' Switch on or off a style
#'
#' Make a style active. The text printed to the screen from now
#' on will use this style.
#'
#' @details
#' This function is very rarely needed, e.g. for colored user
#' input. For other reasons, just call the style as a function on
#' the string.
#'
#' @param x Style.
#' @param ... Ignored.
#'
#' @export
#' @examples
#' ## The input is red (if color is supported)
#' get_name <- function() {
#' cat("Enter your name:", start(red))
#' input <- readline()
#' cat(finish(red))
#' input
#' }
#' name <- get_name()
#' name
start.crayon <- function(x, ...) {
if (has_color()) {
paste(
vapply(attr(x, "_styles"), "[[", "", "open"),
collapse = ""
)
} else {
""
}
}
#' @importFrom stats start
#' @rdname start.crayon
#' @export
finish <- function(x, ...)
UseMethod("finish")
#' @rdname start.crayon
#' @export
#' @method finish crayon
finish.crayon <- function(x, ...) {
if (has_color()) {
paste(
rev(vapply(attr(x, "_styles"), "[[", "", "close")),
collapse = ""
)
} else {
""
}
}
crayon/R/combine.r 0000644 0001762 0000144 00000003225 14201156733 013551 0 ustar ligges users
#' Combine two or more ANSI styles
#'
#' Combine two or more styles or style functions into a new style function
#' that can be called on strings to style them.
#'
#' It does not usually make sense to combine two foreground
#' colors (or two background colors), because only the first one
#' applied will be used.
#'
#' It does make sense to combine different kind of styles,
#' e.g. background color, foreground color, bold font.
#'
#' The `$` operator can also be used to combine styles.
#' Note that the left hand side of `$` is a style function,
#' and the right hand side is the name of a style in [styles()].
#'
#' @param ... The styles to combine. They will be applied from
#' right to left.
#' @return The combined style function.
#'
#' @export
#' @examples
#' ## Use style names
#' alert <- combine_styles("bold", "red4", "bgCyan")
#' cat(alert("Warning!"), "\n")
#'
#' ## Or style functions
#' alert <- combine_styles(bold, red, bgCyan)
#' cat(alert("Warning!"), "\n")
#'
#' ## Combine a composite style
#' alert <- combine_styles(bold, combine_styles(red, bgCyan))
#' cat(alert("Warning!"), "\n")
#'
#' ## Shorter notation
#' alert <- bold $ red $ bgCyan
#' cat(alert("Warning!"), "\n")
combine_styles <- function(...) {
styles <- lapply(list(...), use_or_make_style)
all_ansi <- unlist(lapply(styles, attr, "_styles"), recursive = FALSE)
make_crayon(all_ansi)
}
#' @rdname combine_styles
#' @param crayon A style function.
#' @param style A style name that is included in `names(styles())`.
#' @export
#' @method $ crayon
`$.crayon` <- function(crayon, style) {
attr(crayon, "_styles") <-
c(attr(crayon, "_styles"), data_env$my_styles[style])
crayon
}
crayon/R/styles.r 0000644 0001762 0000144 00000004403 14201156733 013457 0 ustar ligges users
palette_idx <- function(id) {
ifelse(
id < 38,
id - (30 - 1),
ifelse(
id < 48,
-(id - (40 - 1)),
ifelse(
id < 98,
id - (90 - 9),
-(id - (100 - 9))
)))
}
palette_color <- function(x) {
c(x, palette = palette_idx(x[[1]]))
}
## ----------------------------------------------------------------------
## Styles
codes <- list(
reset = list(0, c(0, 22, 23, 24, 27, 28, 29, 39, 49)),
bold = list(1, 22), # 21 isn't widely supported and 22 does the same thing
blurred = list(2, 22),
italic = list(3, 23),
underline = list(4, 24),
inverse = list(7, 27),
hidden = list(8, 28),
strikethrough = list(9, 29),
black = palette_color(list(30, 39)),
red = palette_color(list(31, 39)),
green = palette_color(list(32, 39)),
yellow = palette_color(list(33, 39)),
blue = palette_color(list(34, 39)),
magenta = palette_color(list(35, 39)),
cyan = palette_color(list(36, 39)),
white = palette_color(list(37, 39)),
silver = palette_color(list(90, 39)),
bgBlack = palette_color(list(40, 49)),
bgRed = palette_color(list(41, 49)),
bgGreen = palette_color(list(42, 49)),
bgYellow = palette_color(list(43, 49)),
bgBlue = palette_color(list(44, 49)),
bgMagenta = palette_color(list(45, 49)),
bgCyan = palette_color(list(46, 49)),
bgWhite = palette_color(list(47, 49))
)
## ANSI fg color -> R color
ansi_fg_r <- c(
"black" = "black",
"red" = "red",
"green" = "green",
"yellow" = "yellow",
"blue" = "blue",
"magenta" = "magenta",
"cyan" = "cyan",
"white" = "white",
"silver" = "grey"
)
ansi_fg_rgb <- col2rgb(ansi_fg_r)
ansi_bg_r <- c(
"bgBlack" = "black",
"bgRed" = "red",
"bgGreen" = "green",
"bgYellow" = "yellow",
"bgBlue" = "blue",
"bgMagenta" = "magenta",
"bgCyan" = "cyan",
"bgWhite" = "white"
)
ansi_bg_rgb <- col2rgb(ansi_bg_r)
# code can have length > 1, used to generate the closing tags for reset
make_chr_ansi_tag <- function(code)
paste0('\u001b[', chr(code), 'm', collapse="")
make_chr_style <- function(code) {
list(
open = make_chr_ansi_tag(codes[[code]][[1]]),
close = make_chr_ansi_tag(codes[[code]][[2]]),
palette = if (length(codes[[code]]) >= 3) codes[[code]][[3]]
)
}
builtin_styles <- lapply(names(codes), make_chr_style)
names(builtin_styles) <- names(codes)
crayon/R/aac-num-ansi-colors.R 0000644 0001762 0000144 00000001537 14201156733 015651 0 ustar ligges users
# Helper functions from cli, for the ANSI color detection
#' @include aab-num-ansi-colors.R
get_real_output <- function(output) {
cli_output_connection()
}
cli_output_connection <- function() {
if (is_interactive() && no_sink()) stdout() else stderr()
}
is_interactive <- function() {
opt <- getOption("rlib_interactive")
if (isTRUE(opt)) {
TRUE
} else if (identical(opt, FALSE)) {
FALSE
} else if (tolower(getOption("knitr.in.progress", "false")) == "true") {
FALSE
} else if (tolower(getOption("rstudio.notebook.executing", "false")) == "true") {
FALSE
} else if (identical(Sys.getenv("TESTTHAT"), "true")) {
FALSE
} else {
interactive()
}
}
no_sink <- function() {
sink.number() == 0 && sink.number("message") == 2
}
`%||%` <- function(l, r) if (is.null(l)) r else l
clienv <- new.env(parent = emptyenv())
crayon/R/aaa-rstudio-detect.R 0000644 0001762 0000144 00000013167 14301446132 015556 0 ustar ligges users
rstudio <- local({
standalone_env <- environment()
parent.env(standalone_env) <- baseenv()
# -- Collect data ------------------------------------------------------
data <- NULL
get_data <- function() {
envs <- c(
"R_BROWSER",
"R_PDFVIEWER",
"RSTUDIO",
"RSTUDIO_TERM",
"RSTUDIO_CONSOLE_COLOR",
"RSTUDIOAPI_IPC_REQUESTS_FILE",
"XPC_SERVICE_NAME",
"ASCIICAST")
d <- list(
pid = Sys.getpid(),
envs = Sys.getenv(envs),
api = tryCatch(
asNamespace("rstudioapi")$isAvailable(),
error = function(err) FALSE
),
tty = isatty(stdin()),
gui = .Platform$GUI,
args = commandArgs(),
search = search()
)
d$ver <- if (d$api) asNamespace("rstudioapi")$getVersion()
d$desktop <- if (d$api) asNamespace("rstudioapi")$versionInfo()$mode
d
}
# -- Auto-detect environment -------------------------------------------
is_rstudio <- function() {
Sys.getenv("RSTUDIO") == "1"
}
detect <- function(clear_cache = FALSE) {
# Check this up front, in case we are in a testthat 3e test block.
# We cannot cache this, because we might be in RStudio in reality.
if (!is_rstudio()) {
return(get_caps(type = "not_rstudio"))
}
# Cached?
if (clear_cache) data <<- NULL
if (!is.null(data)) return(get_caps(data))
# Otherwise get data
new <- get_data()
# Cache unless told otherwise
cache <- TRUE
new$type <- if (new$envs[["RSTUDIO"]] != "1") {
# 1. Not RStudio at all
"not_rstudio"
} else if (new$gui == "RStudio" && new$api) {
# 2. RStudio console, properly initialized
"rstudio_console"
} else if (! new$api && basename(new$args[1]) == "RStudio") {
# 3. RStudio console, initializing
cache <- FALSE
"rstudio_console_starting"
} else if (new$gui == "Rgui") {
# Still not RStudio, but Rgui that was started from RStudio
"not_rstudio"
} else if (new$tty && new$envs[["ASCIICAST"]] != "true") {
# 4. R in the RStudio terminal
# This could also be a subprocess of the console or build pane
# with a pseudo-terminal. There isn't really a way to rule that
# out, without inspecting some process data with ps::ps_*().
# At least we rule out asciicast
"rstudio_terminal"
} else if (! new$tty &&
new$envs[["RSTUDIO_TERM"]] == "" &&
new$envs[["R_BROWSER"]] == "false" &&
new$envs[["R_PDFVIEWER"]] == "false" &&
is_build_pane_command(new$args)) {
# 5. R in the RStudio build pane
# https://github.com/rstudio/rstudio/blob/master/src/cpp/session/
# modules/build/SessionBuild.cpp#L231-L240
"rstudio_build_pane"
} else if (new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
grepl("rstudio", new$envs[["XPC_SERVICE_NAME"]])) {
# RStudio job, XPC_SERVICE_NAME=0 in the subprocess of a job
# process. Hopefully this is reliable.
"rstudio_job"
} else if (new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
any(grepl("SourceWithProgress.R", new$args))) {
# Or we can check SourceWithProgress.R in the command line, see
# https://github.com/r-lib/cli/issues/367
"rstudio_job"
} else {
# Otherwise it is a subprocess of the console, terminal or
# build pane, and it is hard to say which, so we do not try.
"rstudio_subprocess"
}
installing <- Sys.getenv("R_PACKAGE_DIR", "")
if (cache && installing == "") data <<- new
get_caps(new)
}
is_build_pane_command <- function(args) {
cmd <- gsub("[\"']", "", args[[length(args)]], useBytes = TRUE)
rcmd <- sub("[(].*$", "", cmd)
rcmd %in% c("devtools::build", "devtools::test", "devtools::check")
}
# -- Capabilities ------------------------------------------------------
caps <- list()
caps$not_rstudio <- function(data) {
list(
type = "not_rstudio",
dynamic_tty = FALSE,
ansi_tty = FALSE,
ansi_color = FALSE,
num_colors = 1L
)
}
caps$rstudio_console <- function(data) {
list(
type = "rstudio_console",
dynamic_tty = TRUE,
ansi_tty = FALSE,
ansi_color = data$envs[["RSTUDIO_CONSOLE_COLOR"]] != "",
num_colors = as.integer(data$envs[["RSTUDIO_CONSOLE_COLOR"]])
)
}
caps$rstudio_console_starting <- function(data) {
res <- caps$rstudio_console(data)
res$type <- "rstudio_console_starting"
res
}
caps$rstudio_terminal <- function(data) {
list(
type = "rstudio_terminal",
dynamic_tty = TRUE,
ansi_tty = FALSE,
ansi_color = FALSE,
num_colors = 1L
)
}
caps$rstudio_build_pane <- function(data) {
list(
type = "rstudio_build_pane",
dynamic_tty = TRUE,
ansi_tty = FALSE,
ansi_color = data$envs[["RSTUDIO_CONSOLE_COLOR"]] != "",
num_colors = as.integer(data$envs[["RSTUDIO_CONSOLE_COLOR"]])
)
}
caps$rstudio_job <- function(data) {
list(
type = "rstudio_job",
dynamic_tty = FALSE,
ansi_tty = FALSE,
ansi_color = data$envs[["RSTUDIO_CONSOLE_COLOR"]] != "",
num_colors = as.integer(data$envs[["RSTUDIO_CONSOLE_COLOR"]])
)
}
caps$rstudio_subprocess <- function(data) {
list(
type = "rstudio_subprocess",
dynamic_tty = FALSE,
ansi_tty = FALSE,
ansi_color = FALSE,
num_colors = 1L
)
}
get_caps <- function(data, type = data$type) caps[[type]](data)
structure(
list(
.internal = standalone_env,
is_rstudio = is_rstudio,
detect = detect
),
class = c("standalone_rstudio_detect", "standalone")
)
})
crayon/R/print.r 0000644 0001762 0000144 00000000354 14201156733 013271 0 ustar ligges users
#' @export
#' @method print crayon
print.crayon <- function(x, ...) {
st <- paste(names(attr(x, "_styles")), collapse = ", ")
cat(sep = "",
"Crayon style function, ",
st,
": ",
x("example output."),
"\n"
)
}
crayon/R/style-var.r 0000644 0001762 0000144 00000002165 14201156733 014065 0 ustar ligges users
#' Add style to a string
#'
#' See `names(styles)`, or the crayon manual for available styles.
#'
#' @param string Character vector to style.
#' @param as Style function to apply, either the function object,
#' or its name, or an object to pass to [make_style()].
#' @param bg Background style, a style function, or a name that
#' is passed to [make_style()].
#' @return Styled character vector.
#'
#' @export
#' @importFrom methods is
#'
#' @examples
#' ## These are equivalent
#' style("foobar", bold)
#' style("foobar", "bold")
#' bold("foobar")
style <- function(string, as = NULL, bg = NULL) {
as <- use_or_make_style(as)
bg <- use_or_make_style(bg, bg = TRUE)
if (!is(as, "crayon")) stop("Cannot make style from 'as'")
if (!is(bg, "crayon")) stop("Cannot make style from 'bg'")
as(bg(string))
}
#' @importFrom methods is
use_or_make_style <- function(style, bg = FALSE) {
if (is.null(style)) {
structure(base::identity, class = "crayon")
} else if (is(style, "crayon")) {
style
} else if (style %in% names(styles())) {
make_crayon(styles()[style])
} else {
make_style(style, bg = bg)
}
}
crayon/R/crayon-package.r 0000644 0001762 0000144 00000000710 14201156733 015015 0 ustar ligges users
## ----------------------------------------------------------------------
#' Colored terminal output
#'
#' With crayon it is easy to add color to terminal output, create styles
#' for notes, warnings, errors; and combine styles.
#'
#' ANSI color support is automatically detected and used. Crayon was largely
#' inspired by chalk \url{https://github.com/chalk/chalk}.
#'
#' @include utils.r
#' @include string.r
#' @docType package
#' @name crayon
NULL
crayon/R/enc-utils.R 0000644 0001762 0000144 00000001311 14315032112 013760 0 ustar ligges users
# keep encoding, even if useBytes = TRUE
Encoding_ <- function(x) {
if (is.factor(x) && length(levels(x)) < length(x)) {
Encoding(levels(x))
} else {
if (!is.character(x)) x <- as.character(x)
Encoding(x)
}
}
sub_ <- function(pattern, replacement, x, ...) {
enc <- Encoding_(x)
ret <- sub(pattern, replacement, x, ...)
if (length(ret)) Encoding(ret) <- enc
ret
}
gsub_ <- function(pattern, replacement, x, ...) {
enc <- Encoding_(x)
ret <- gsub(pattern, replacement, x, ...)
if (length(ret)) Encoding(ret) <- enc
ret
}
strsplit_ <- function(x, ...) {
enc <- Encoding_(x)
ret <- strsplit(x, ...)
for (i in seq_along(ret)) {
Encoding(ret[[i]]) <- enc[i]
}
ret
}
crayon/R/link.R 0000644 0001762 0000144 00000003143 14201156733 013031 0 ustar ligges users
#' Terminal Hyperlinks
#'
#' @details
#' hyperlink()` creates an ANSI hyperlink.
#'
#' `has_hyperlink()` checks if the current `stdout()` supports hyperlinks.
#' terminal links.
#'
#' See also
#' .
#'
#' @param text Text to show. `text` and `url` are recycled to match their
#' length, via a `paste0()` call.
#' @param url URL to link to.
#' @return Logical scalar, for `has_hyperlink()`.
#'
#' @export
#' @examples
#' cat("This is an", hyperlink("R", "https://r-project.org"), "link.\n")
hyperlink <- function(text, url) {
if (has_hyperlink()) {
paste0("\u001B]8;;", url, "\u0007", text, "\u001B]8;;\u0007")
} else {
text
}
}
#' @export
#' @name hyperlink
#' @examples
#' has_hyperlink()
has_hyperlink <- function() {
## Hyperlinks forced?
enabled <- getOption("crayon.hyperlink")
if (!is.null(enabled)) { return(isTRUE(enabled)) }
## Are we in a terminal? No?
if (!isatty(stdout())) { return(FALSE) }
## Are we in a windows terminal?
if (os_type() == "windows") { return(TRUE) }
## Better to avoid it in CIs
if (nzchar(Sys.getenv("CI")) ||
nzchar(Sys.getenv("TEAMCITY_VERSION"))) { return(FALSE) }
## iTerm
if (nzchar(TERM_PROGRAM <- Sys.getenv("TERM_PROGRAM"))) {
version <- package_version(
Sys.getenv("TERM_PROGRAM_VERSION"),
strict = FALSE)
if (TERM_PROGRAM == "iTerm.app") {
if (!is.na(version) && version >= "3.1") return(TRUE)
}
}
if (nzchar(VTE_VERSION <- Sys.getenv("VTE_VERSION"))) {
if (package_version(VTE_VERSION) >= "0.50.1") return(TRUE)
}
FALSE
}
crayon/R/ansi-palette.R 0000644 0001762 0000144 00000011230 14315026215 014453 0 ustar ligges users
get_palette_color <- function(style, colors = num_ansi_colors()) {
opt <- getOption("cli.palette")
if (is.null(opt) || colors < 256) return(style)
cache_palette_color(opt, style$palette, colors)
}
palette_cache <- new.env(parent = emptyenv())
cache_palette_color <- function(pal, idx, colors = num_ansi_colors()) {
if (is_string(pal)) {
if (! pal %in% rownames(ansi_palettes)) {
stop("Cannot find cli ANSI palette '", pal, "'.")
}
pal <- ansi_palettes[pal, ]
}
bg <- idx < 0
idx <- abs(idx)
col <- pal[[idx]]
colkey <- as.character(colors)
key <- paste0(col, bg)
if (key %in% names(palette_cache[[colkey]])) {
return(palette_cache[[colkey]][[key]])
}
val <- ansi_style_from_r_color(
col,
bg = bg,
colors,
grey = FALSE
)
if (is.null(palette_cache[[colkey]])) {
palette_cache[[colkey]] <- new.env(parent = emptyenv())
}
palette_cache[[colkey]][[key]] <- val
return(val)
}
#' @details
#' `truecolor` is an integer constant for the number of 24 bit ANSI colors.
#'
#' @format `truecolor` is an integer scalar.
#'
#' @noRd
#' @rdname ansi_palettes
truecolor <- as.integer(256 ^ 3)
#' ANSI colors palettes
#'
#' If your platform supports at least 256 colors, then you can configure
#' the colors that cli uses for the eight base and the eight bright colors.
#' (I.e. the colors of [col_black()], [col_red()], and [col_br_black()],
#' [col_br_red()], etc.
#'
#' To customize the default palette, set the `cli.palette` option to the
#' name of a built-in palette (see `ansi_palettes()`), or the list of
#' 16 colors. Colors can be specified with RGB colors strings:
#' `#rrggbb` or R color names (see the output of [grDevices::colors()]).
#'
#' For example, you can put this in your R profile:
#' ```r
#' options(cli.palette = "vscode")
#' ```
#'
#' It is currently not possible to configure the background colors
#' separately, these will be always the same as the foreground colors.
#'
#' If your platform only has 256 colors, then the colors specified in the
#' palette have to be interpolated. On true color platforms they RGB
#' values are used as-is.
#'
#' `ansi_palettes` is a data frame of the built-in palettes, each row
#' is one palette.
#'
#' `ansi_palette_show()` shows the colors of an ANSI palette on the screen.
#'
#' @format `ansi_palettes` is a data frame with one row for each palette,
#' and one column for each base ANSI color. `attr(ansi_palettes, "info")`
#' contains a list with information about each palette.
#'
#' @noRd
#' @examples
#' ansi_palettes
#' ansi_palette_show("dichro", colors = truecolor)
ansi_palettes <- rbind(
utils::read.table(
"tools/ansi-palettes.txt",
comment.char = ";",
stringsAsFactors = FALSE
),
utils::read.table(
"tools/ansi-iterm-palettes.txt",
comment.char = ";",
stringsAsFactors = FALSE
)
)
attr(ansi_palettes, "info") <-
list(
dichro = paste(
"Colorblind friendly palette, from",
"https://github.com/romainl/vim-dichromatic#dichromatic."
),
vga = paste(
"Typical colors that are used when booting PCs and leaving them in",
"text mode, which used a 16-entry color table. The colors are",
"different in the EGA/VGA graphic modes.",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
winxp = paste(
"Windows XP Console. Seen in Windows XP through Windows 8.1.",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
vscode = paste(
"Visual Studio Debug console, 'Dark+' theme.",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
win10 = paste0(
"Campbell theme, used as of Windows 10 version 1709. Also used",
"by PowerShell 6.",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
macos = paste0(
"Terminal.app in macOS",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
putty = paste0(
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
mirc = paste0(
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
xterm = paste0(
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
ubuntu = paste0(
"For virtual terminals, from /etc/vtrgb.",
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
eclipse = paste0(
"From https://en.wikipedia.org/wiki/ANSI_escape_code#SGR."
),
iterm = "Built-in iTerm2 theme.",
"iterm-pastel" = "Built-In iTerm2 theme.",
"iterm-smoooooth" = "Built-In iTerm2 theme.",
"iterm-snazzy" = "From https://github.com/sindresorhus/iterm2-snazzy.",
"iterm-solarized" = "Built-In iTerm2 theme.",
"iterm-tango" = "Built-In iTerm2 theme."
)
crayon/R/string_operations.r 0000644 0001762 0000144 00000022507 14201156733 015712 0 ustar ligges users
## Create a mapping between the string and its style-less version.
## This is useful to work with the colored string.
#' @importFrom utils tail
map_to_ansi <- function(x, text = NULL) {
if (is.null(text)) {
text <- non_matching(re_table(ansi_regex, x), x, empty=TRUE)
}
map <- lapply(
text,
function(text) {
cbind(
pos = cumsum(c(1, text[, "length"], Inf)),
offset = c(text[, "start"] - 1, tail(text[, "end"], 1), NA)
)
})
function(pos) {
pos <- rep(pos, length.out = length(map))
mapply(pos, map, FUN = function(pos, table) {
if (pos < 1) {
pos
} else {
slot <- which(pos < table[, "pos"])[1] - 1
table[slot, "offset"] + pos - table[slot, "pos"] + 1
}
})
}
}
#' Count number of characters in an ANSI colored string
#'
#' This is a color-aware counterpart of [base::nchar()],
#' which does not do well, since it also counts the ANSI control
#' characters.
#'
#' @param x Character vector, potentially ANSO styled, or a vector to be
#' coarced to character.
#' @param ... Additional arguments, passed on to `base::nchar()`
#' after removing ANSI escape sequences.
#' @return Numeric vector, the length of the strings in the character
#' vector.
#'
#' @family ANSI string operations
#' @export
#' @examples
#' str <- paste(
#' red("red"),
#' "default",
#' green("green")
#' )
#'
#' cat(str, "\n")
#' nchar(str)
#' col_nchar(str)
#' nchar(strip_style(str))
col_nchar <- function(x, ...) {
base::nchar(strip_style(x), ...)
}
#' Substring(s) of an ANSI colored string
#'
#' This is a color-aware counterpart of [base::substr()].
#' It works exactly like the original, but keeps the colors
#' in the substrings. The ANSI escape sequences are ignored when
#' calculating the positions within the string.
#'
#' @param x Character vector, potentially ANSI styled, or a vector to
#' coarced to character.
#' @param start Starting index or indices, recycled to match the length
#' of `x`.
#' @param stop Ending index or indices, recycled to match the length
#' of `x`.
#' @return Character vector of the same length as `x`, containing
#' the requested substrings. ANSI styles are retained.
#'
#' @family ANSI string operations
#' @export
#' @examples
#' str <- paste(
#' red("red"),
#' "default",
#' green("green")
#' )
#'
#' cat(str, "\n")
#' cat(col_substr(str, 1, 5), "\n")
#' cat(col_substr(str, 1, 15), "\n")
#' cat(col_substr(str, 3, 7), "\n")
#'
#' substr(strip_style(str), 1, 5)
#' substr(strip_style(str), 1, 15)
#' substr(strip_style(str), 3, 7)
#'
#' str2 <- "another " %+%
#' red("multi-", sep = "", underline("style")) %+%
#' " text"
#'
#' cat(str2, "\n")
#' cat(col_substr(c(str, str2), c(3,5), c(7, 18)), sep = "\n")
#' substr(strip_style(c(str, str2)), c(3,5), c(7, 18))
col_substr <- function(x, start, stop) {
if(!is.character(x)) x <- as.character(x)
if(!length(x)) return(x)
start <- as.integer(start)
stop <- as.integer(stop)
if(!length(start) || !length(stop))
stop("invalid substring arguments")
if(anyNA(start) || anyNA(stop))
stop("non-numeric substring arguments not supported")
ansi <- re_table(ansi_regex, x)
text <- non_matching(ansi, x, empty=TRUE)
mapper <- map_to_ansi(x, text = text)
nstart <- mapper(start)
nstop <- mapper(stop)
bef <- base::substr(x, 1, nstart - 1)
aft <- base::substr(x, nstop + 1, base::nchar(x))
ansi_bef <- vapply(regmatches(bef, gregexpr(ansi_regex, bef)),
paste, collapse = "", FUN.VALUE = "")
ansi_aft <- vapply(regmatches(aft, gregexpr(ansi_regex, aft)),
paste, collapse = "", FUN.VALUE = "")
paste(sep = "", ansi_bef, base::substr(x, nstart, nstop), ansi_aft)
}
#' Substring(s) of an ANSI colored string
#'
#' This is the color-aware counterpart of [base::substring()].
#' It works exactly like the original, but keeps the colors in the
#' substrings. The ANSI escape sequences are ignored when
#' calculating the positions within the string.
#'
#' @param text Character vector, potentially ANSI styled, or a vector to
#' coarced to character. It is recycled to the longest of `first`
#' and `last`.
#' @param first Starting index or indices, recycled to match the length
#' of `x`.
#' @param last Ending index or indices, recycled to match the length
#' of `x`.
#' @return Character vector of the same length as `x`, containing
#' the requested substrings. ANSI styles are retained.
#'
#' @family ANSI string operations
#' @export
#' @examples
#' str <- paste(
#' red("red"),
#' "default",
#' green("green")
#' )
#'
#' cat(str, "\n")
#' cat(col_substring(str, 1, 5), "\n")
#' cat(col_substring(str, 1, 15), "\n")
#' cat(col_substring(str, 3, 7), "\n")
#'
#' substring(strip_style(str), 1, 5)
#' substring(strip_style(str), 1, 15)
#' substring(strip_style(str), 3, 7)
#'
#' str2 <- "another " %+%
#' red("multi-", sep = "", underline("style")) %+%
#' " text"
#'
#' cat(str2, "\n")
#' cat(col_substring(str2, c(3,5), c(7, 18)), sep = "\n")
#' substring(strip_style(str2), c(3,5), c(7, 18))
col_substring <- function(text, first, last = 1000000L) {
if (!is.character(text)) text <- as.character(text)
n <- max(lt <- length(text), length(first), length(last))
if (lt && lt < n) text <- rep_len(text, length.out = n)
col_substr(text, as.integer(first), as.integer(last))
}
#' Split an ANSI colored string
#'
#' This is the color-aware counterpart of [base::strsplit()].
#' It works almost exactly like the original, but keeps the colors in the
#' substrings.
#'
#' @param x Character vector, potentially ANSI styled, or a vector to
#' coarced to character.
#' @param split Character vector of length 1 (or object which can be coerced to
#' such) containing regular expression(s) (unless `fixed = TRUE`) to use
#' for splitting. If empty matches occur, in particular if `split` has
#' zero characters, `x` is split into single characters.
#' @param ... Extra arguments are passed to `base::strsplit()`.
#' @return A list of the same length as `x`, the \eqn{i}-th element of
#' which contains the vector of splits of `x[i]`. ANSI styles are
#' retained.
#'
#' @family ANSI string operations
#' @export
#' @importFrom utils head
#' @examples
#' str <- red("I am red---") %+%
#' green("and I am green-") %+%
#' underline("I underlined")
#'
#' cat(str, "\n")
#'
#' # split at dashes, keep color
#' cat(col_strsplit(str, "[-]+")[[1]], sep = "\n")
#' strsplit(strip_style(str), "[-]+")
#'
#' # split to characters, keep color
#' cat(col_strsplit(str, "")[[1]], "\n", sep = " ")
#' strsplit(strip_style(str), "")
col_strsplit <- function(x, split, ...) {
split <- try(as.character(split), silent=TRUE)
if(inherits(split, "try-error") || !is.character(split) || length(split) > 1L)
stop("`split` must be character of length <= 1, or must coerce to that")
if(!length(split)) split <- ""
plain <- strip_style(x)
splits <- re_table(split, plain, ...)
chunks <- non_matching(splits, plain, empty = TRUE)
# silently recycle `split`; doesn't matter currently since we don't support
# split longer than 1, but might in future
split.r <- rep(split, length.out=length(x))
# Drop empty chunks to align with `substr` behavior
chunks <- lapply(
seq_along(chunks),
function(i) {
y <- chunks[[i]]
# empty split means drop empty first match
if(nrow(y) && !nzchar(split.r[[i]]) && !head(y, 1L)[, "length"]) {
y <- y[-1L, , drop=FALSE]
}
# drop empty last matches
if(nrow(y) && !tail(y, 1L)[, "length"]) y[-nrow(y), , drop=FALSE] else y
}
)
zero.chunks <- !vapply(chunks, nrow, integer(1L))
# Pull out zero chunks from colored string b/c col_substring won't work
# with them
res <- vector("list", length(chunks))
res[zero.chunks] <- list(character(0L))
res[!zero.chunks] <- mapply(
chunks[!zero.chunks], x[!zero.chunks], SIMPLIFY = FALSE,
FUN = function(tab, xx) col_substring(xx, tab[, "start"], tab[, "end"])
)
res
}
#' Align an ANSI colored string
#'
#' @param text The character vector to align.
#' @param width Width of the field to align in.
#' @param align Whether to align `"left"`, `"center"` or `"right"`.
#' @param type Passed on to [col_nchar()] and there to [nchar()]
#' @return The aligned character vector.
#'
#' @family ANSI string operations
#' @export
#' @examples
#' col_align(red("foobar"), 20, "left")
#' col_align(red("foobar"), 20, "center")
#' col_align(red("foobar"), 20, "right")
col_align <- function(text, width = getOption("width"),
align = c("left", "center", "right"),
type = "width") {
align <- match.arg(align)
nc <- col_nchar(text, type = type)
if (!length(text)) return(text)
if (align == "left") {
paste0(text, make_space(width - nc))
} else if (align == "center") {
paste0(make_space(ceiling((width - nc) / 2)),
text,
make_space(floor((width - nc) / 2)))
} else {
paste0(make_space(width - nc), text)
}
}
make_space <- function(num, filling = " ") {
num <- pmax(0, num)
res <- strrep(filling, num)
Encoding(res) <- Encoding(filling)
res
}
strrep <- function (x, times) {
x = as.character(x)
if (length(x) == 0L) return(x)
mapply(
function(x, times) {
if (is.na(x) || is.na(times)) {
NA_character_
} else if (times <= 0L) {
""
} else {
paste0(rep(x, times), collapse = "")
}
},
x, times,
USE.NAMES = FALSE
)
}
crayon/R/aaaa-rematch2.R 0000644 0001762 0000144 00000001727 14201223632 014461 0 ustar ligges users
re_match <- function(text, pattern, perl = TRUE, ...) {
stopifnot(is.character(pattern), length(pattern) == 1, !is.na(pattern))
text <- as.character(text)
match <- regexpr(pattern, text, perl = perl, ...)
start <- as.vector(match)
length <- attr(match, "match.length")
end <- start + length - 1L
matchstr <- substring(text, start, end)
matchstr[ start == -1 ] <- NA_character_
empty <- data.frame(stringsAsFactors = FALSE, .text = text)[, numeric()]
res <- list(match = !is.na(matchstr), groups = empty)
if (!is.null(attr(match, "capture.start"))) {
gstart <- attr(match, "capture.start")
glength <- attr(match, "capture.length")
gend <- gstart + glength - 1L
groupstr <- substring(text, gstart, gend)
groupstr[ gstart == -1 ] <- NA_character_
dim(groupstr) <- dim(gstart)
res$groups <- cbind(groupstr, res$groups, stringsAsFactors = FALSE)
names(res$groups) <- attr(match, "capture.names")
}
res$groups
}
crayon/NEWS.md 0000644 0001762 0000144 00000006371 14315234656 012663 0 ustar ligges users # crayon 1.5.2
* crayon functions now mark their output with the right encoding,
if their input was marked (#136, #138).
# 1.5.1
* crayon now does not fail to install from source if the utils package
is not loaded (#133).
# 1.5.0
* You can use the new `cli.default_num_colors` option to set the default
number of ANSI colors, only if ANSI support is otherwise detected.
See the details in the manual of `num_ansi_colors()`. (From cli.)
* crayon now install cleanly on R 3.4.x and R 3.5.x on Windows (#131).
# 1.4.2
* Better ANSI support detection if there is an active `sink()`.
* Support ANSI markup in RStudio jobs.
# 1.4.1
* ANSI color support detection works correctly now in older RStudio (#112).
* ANSI color support detection works correctly now on older R versions
(#109).
# 1.4.0
* Overhauled and much improved detection of ANSI color support and
number of ANSI colors.
* `NO_COLOR` environment variable disables color (#64)
* Now colors are turned on if ANSICON ()
is active.
* New `hyperlink()` function to add hyperlinks to terminal output.
The new `has_hyperlink()` function tests if the current `stdout()`
supports this.
* `reset` style now restores previous style for text following it (@brodieG,
#35).
* Warnings are no longer generated when the INSIDE_EMACS environment variable is
set but does not include a version number.
# 1.3.4
* Style functions convert arguments to character now
* Autodetect RStudio ANSI support
* `col_align()` gains `type` argument, default `"width"` (#54).
# 1.3.2
* Removed dependency to `memoise` (@brodieG, #25)
* Fixed a test case that changed the `crayon.enabled`
setting, potentially (@brodieG)
* Added `crayon.colors` option, to specify the number of
colors explicitly
* `TERM=xterm` and `tput colors=8` will use 256 colors,
as 256 colors are usually supported in this case (#17)
* Support colors in ConEmu and cmder, on Windows
* Fix color detection in Emacs tramp
* `col_strsplit` and `col_substr` corner cases:
* handle empty chunks at beginning or end of strings
like `base::strsplit` (@brodieG, #26)
* explicitly deal with 'split' values that are not
length 1 as that is not currently supported
* handle zero length `x` argument in `col_substr`, and
add more explicit error messages for corner cases
* Some performance improvements to `col_substr` (@brodieG)
* Change rgb to ANSI code mapping, based on the "paint" ruby gem
(@richfitz, #33, #34)
# 1.3.1
* Fixed some `R CMD check` problems.
# 1.3.0
* Colors are turned on by default in Emacs ESS 23.x and above.
* Functions to turn on and off a style: `start`, `finish`.
* Really fix `tput` corner cases (@jimhester, #21)
# 1.2.1
* Fix detecting number of colors when `tput` exists, but
fails with an error and/or does not return anything useful.
(@jimhester, #18, #19)
# 1.2.0
* Fix detection of number of colors, it was cached from
installation time (#17).
* Color aware string operations. They are slow and experimental
currently.
# 1.1.0
* `show_ansi_colors()` prints all supported colors on the screen.
* 256 colors, on terminals that support it.
* Disable colors on Windows, they are not supported in the default setup.
# 1.0.0
* First released version.
crayon/MD5 0000644 0001762 0000144 00000006370 14315342710 012063 0 ustar ligges users eb6d5e7488da8f3b9da88ee7e9c62f0a *DESCRIPTION
71e081e70f89b75ba2781efdce97f3b4 *LICENSE
e2c013428a135455a1a7d0ae7a893385 *NAMESPACE
8cc4e7d4013c6621768affe4d3cee5a8 *NEWS.md
de9230c7f4e3c3c6a210aabff2cad858 *R/aaa-rstudio-detect.R
6d32216035fb4ac46d9401e1bdde9596 *R/aaaa-rematch2.R
a0e92f4d900eb1c2dc937c3e4c26cc32 *R/aab-num-ansi-colors.R
6d0c3010260e1bc8655a07f1d3c686d4 *R/aac-num-ansi-colors.R
3f3f25348f24cddea31d27e570e80f2d *R/ansi-256.r
f4a12dc1e64a85c459421a63dd2758dc *R/ansi-palette.R
c678ccd07b924a7d34cadef0bb8ef62c *R/combine.r
72e4ddff2c7012b962145fd53281ee48 *R/crayon-package.r
1dea456a152b15068d387e5293a9d356 *R/disposable.r
5dde55f00368e7e1227b74f8f6652824 *R/enc-utils.R
403c55be7e9aff35206d76470209d220 *R/has_ansi.r
2bc3fdc0b86805d39313a9bb8418ac7c *R/has_color.r
a29194027da7db8b6430271e1885b8bc *R/link.R
5fb244b4e89fe5b7dfb2f329b391dbb1 *R/machinery.r
b85d1e01ab403b8a09ae2346d325bcc1 *R/parts.r
d60aa06633288dddff27c30abbd93ae5 *R/print.r
946e0d722d4bf4b1e75fab3acb1cbb51 *R/show.r
7e76265f3a2abd1366dc806ff7f3b2d8 *R/string.r
4efe7ba7147a73d15cbfaa0eb25c8b77 *R/string_operations.r
4b59ab10cac98ddae1286489d03f2f15 *R/style-var.r
7f8959ca77f8b2af22010a0c5ee354a0 *R/styles.r
56e980d59ec90b7cd55f781fe0d933f3 *R/utils.r
1a8afd948af08a31a649379e96068d3d *README.md
1ec2951d9bc3714bd46316973a4d866e *man/chr.Rd
246679a1b0e33905f9f0a00292c83793 *man/col_align.Rd
cc17e4f753c4dd781462efd2fc6443b0 *man/col_nchar.Rd
41e27b4a502f23fbff64f27691991e5b *man/col_strsplit.Rd
071c125b30d48aae1d03fe312eb5721a *man/col_substr.Rd
31d9a0d0c44b91f28da4504e0fe26eab *man/col_substring.Rd
483d865928e96515c4a21e340811fcb3 *man/combine_styles.Rd
71589002458992bacfbed2a258231ec6 *man/concat.Rd
b724202c756cdba847f4179edafba6d9 *man/crayon.Rd
40cb25ff8372a5275aa0ae3c90206d8c *man/drop_style.Rd
83515fd734fec78d21f607b06ed798fd *man/has_color.Rd
4230bd0b59f6271490e96b77b8d1c0b2 *man/has_style.Rd
3951f9ca35cd595e8c45db1c45f41a7a *man/hyperlink.Rd
7448f1d8a0fb49a095206d1eede40656 *man/make_style.Rd
f1bb8290d52230d65fdaf7f6ff2ae217 *man/num_ansi_colors.Rd
f621b464760483e12b52ba82ae6a916c *man/num_colors.Rd
5c77b114f8f137cb57717c3a4cc2e9a8 *man/show_ansi_colors.Rd
ae5359585b92d4323fc3507488fbe92d *man/start.crayon.Rd
9a91f8fceb889eb55808c8aad13d8fc3 *man/strip_style.Rd
2fc0045cd3614113ad14a42789e6db7c *man/style.Rd
66308c7d1350128c2d1a3a1d6175d494 *man/styles.Rd
943758c7965d5d220d1162fb9ce9199b *tests/testthat.R
c5d9040bb16e9172523fe8e34545861c *tests/testthat/helper.R
2b80cfcf446505a85d98882c89d5fc30 *tests/testthat/test-ansi256.R
5a6ed65864bfca60399359ba25f097fe *tests/testthat/test-color.r
65c87f06a2ac074e34bbcfe0eab30f55 *tests/testthat/test-combine.R
8ec0ddbe300fa59dfc73833aa2d76075 *tests/testthat/test-has-style.r
d25040a92d1f3c87034bda961ea3266d *tests/testthat/test-hyperlink.R
15ca85bbfd2ee30f74274176b3616934 *tests/testthat/test-make-style.r
4bacfb4082bd5f4232f24314e96f3cd4 *tests/testthat/test-operations.R
7ce0b4834a4d6c8139e45f14c021e542 *tests/testthat/test-style-var.r
aca5c040a926de44ad8f3e6df1375b2b *tests/testthat/test-styles.r
a4c7a9c4564fe7512f24625738517b22 *tests/testthat/test-utils.R
5c9fae7a3d5bef26b5edcd8c522972b3 *tests/testthat/test-vectors.r
a9d484b6e7e5f9e472f0449a0b8f000f *tools/ansi-iterm-palettes.txt
211e6b484b96b9108bb28c2b376c9a54 *tools/ansi-palettes.txt