Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

The existing custom language engines for knitr, `glue` and `glue_sql`, are documented in a new vignette (#71).

`glue_col()` gives special treatment to styling functions from the crayon package, e.g. `glue_col("{blue foo}")` "just works" now, even if crayon is not attached (but is installed) (#241).

Unterminated backticks trigger the same error as unterminated single or double quotes (#237).

# glue 1.5.0
Expand Down
17 changes: 14 additions & 3 deletions R/color.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#'
#' glue_col("{blue 1 + 1 = {1 + 1}}")
#'
#' glue_col("{blue 2 + 2 = {green {2 + 2}}}")
#'
#' white_on_grey <- bgBlack $ white
#' glue_col("{white_on_grey
#' Roses are {red {colors()[[552]]}}
Expand All @@ -35,14 +37,12 @@
#' }")
#' }
glue_col <- function(..., .envir = parent.frame(), .na = "NA") {
loadNamespace("crayon")
glue(..., .envir = .envir, .na = .na, .transformer = color_transformer)
}

#' @rdname glue_col
#' @export
glue_data_col <- function(.x, ..., .envir = parent.frame(), .na = "NA") {
loadNamespace("crayon")
glue_data(.x, ..., .envir = .envir, .na = .na, .transformer = color_transformer)
}

Expand All @@ -64,5 +64,16 @@ color_transformer <- function(code, envir) {
fun <- captures[[1]]
text <- captures[[2]]
out <- glue(text, .envir = envir, .transformer = color_transformer)
(get(fun, envir = envir, mode = "function"))(out)

color_fun <- get0(fun, envir = envir, mode = "function")
if (is.null(color_fun) && requireNamespace("crayon", quietly = TRUE)) {
color_fun <- get0(fun, envir = asNamespace("crayon"), mode = "function")
}

if (is.null(color_fun)) {
# let nature take its course, i.e. throw the usual error
get(fun, envir = envir, mode = "function")
} else {
color_fun(out)
}
}
2 changes: 2 additions & 0 deletions man/glue_col.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 54 additions & 38 deletions tests/testthat/test-color.R
Original file line number Diff line number Diff line change
@@ -1,50 +1,66 @@
skip_if_not_installed("crayon")
library(crayon)

describe("glue_col", {
it("returns the string if no substations needed", {
expect_identical(glue_col("foo"), as_glue("foo"))
})
it("works the same as glue for parsable expressions", {
expect_identical(glue_col("1 + 1 = {1 + 1}"), glue("1 + 1 = {1 + 1}"))
})
it("applies crayon functions", {
expect_identical(glue_col("{blue foo}"), as_glue(blue("foo")))

blue_and_white <- bgBlue $ white
expect_identical(glue_col("{blue_and_white foo}"), as_glue(blue_and_white("foo")))

expect_identical(glue_col("{blue_and_white {1 + 1}}"), as_glue(blue_and_white("2")))
})
it("works on multiline strings", {
expect_identical(
glue_col("
{red foo
test_that("glue_col() is just glue() when it should be", {
skip_if_not_installed("crayon")
expect_identical(glue_col("foo"), as_glue("foo"))
expect_identical(glue_col("1 + 1 = {1 + 1}"), glue("1 + 1 = {1 + 1}"))
})

test_that("glue_col() applies crayon functions, crayon not attached", {
skip_if_not_installed("crayon")
skip_if("crayon" %in% (.packages()))

expect_identical(glue_col("{blue foo}"), as_glue(crayon::blue("foo")))
})

test_that("glue_col() applies crayon functions, crayon is attached", {
skip_if_not_installed("crayon")
if( !"crayon" %in% (.packages())) {
withr::local_package("crayon")
}

blue_and_white <- bgBlue $ white
expect_identical(glue_col("{blue_and_white foo}"), as_glue(blue_and_white("foo")))
expect_identical(glue_col("{blue_and_white {1 + 1}}"), as_glue(blue_and_white("2")))
})

test_that("glue_col() works on multiline strings", {
skip_if_not_installed("crayon")
expect_identical(
glue_col("
{red foo
bar
}"), as_glue(red("foo\nbar")))
})
it("works on nested colors", {
expect_identical(glue_col("{red This is a {green serious} problem}"),
as_glue(red("This is a " %+% green("serious") %+% " problem")))
})

it("errors if there is invalid syntax or fun is not found", {
expect_error(glue_col("{_}"), "unexpected input")
}"), as_glue(crayon::red("foo\nbar")))
})

test_that("glue_col() works on nested colors", {
skip_if_not_installed("crayon")
if( !"crayon" %in% (.packages())) {
withr::local_package("crayon")
}
expect_identical(
glue_col("{red This is a {green serious} problem}"),
as_glue(red("This is a " %+% green("serious") %+% " problem"))
)
})

test_that("glue_col() errors for invalid syntax or when color_fun can't be found", {
expect_error(glue_col("{_}"), "unexpected input")
expect_error(glue_col("{foo _}"), "object 'foo' of mode 'function' was not found")

foo <- 1
expect_error(glue_col("{foo _}"), "object 'foo' of mode 'function' was not found")

foo <- crayon::blue
expect_identical(glue_col("{foo _}"), as_glue(foo("_")))
})
})

describe("glue_data_col", {
it("works as expected", {
mt <- head(mtcars)
expect_identical(glue_data_col(mt, "A {blue {gear}} speed car with {bold {hp}} hp!"),
as_glue("A " %+% blue(mt$gear) %+% " speed car with " %+% bold(mt$hp) %+% " hp!"))
})
test_that("glue_data_col() works", {
skip_if_not_installed("crayon")
if( !"crayon" %in% (.packages())) {
withr::local_package("crayon")
}
mt <- head(mtcars)
expect_identical(
glue_data_col(mt, "A {blue {gear}} speed car with {bold {hp}} hp!"),
as_glue("A " %+% blue(mt$gear) %+% " speed car with " %+% bold(mt$hp) %+% " hp!")
)
})