Skip to content

Commit 9202a47

Browse files
authored
Alt text label can be function (#5079)
* Allow functions as `labs(alt = ...)` input * Alt functions are called with plot as input * Add test for alt text functions * Add NEWS bullet * Avoid recursion * deal with changes in {glue}
1 parent b74570c commit 9202a47

File tree

5 files changed

+40
-11
lines changed

5 files changed

+40
-11
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ggplot2 (development version)
22

3+
* A function can be provided to `labs(alt = <...>)` that takes the plot as input
4+
and returns text as output (@teunbrand, #4795).
35
* Position scales combined with `coord_sf()` can now use functions in the
46
`breaks` argument. In addition, `n.breaks` works as intended and
57
`breaks = NULL` removes grid lines and axes (@teunbrand, #4622).

R/labels.R

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ update_labels <- function(p, labels) {
4444
#' @param tag The text for the tag label which will be displayed at the
4545
#' top-left of the plot by default.
4646
#' @param alt,alt_insight Text used for the generation of alt-text for the plot.
47-
#' See [get_alt_text] for examples.
47+
#' See [get_alt_text] for examples. `alt` can also be a function that
48+
#' takes the plot as input and returns text as output. `alt` also accepts
49+
#' rlang [lambda][rlang::as_function()] function notation.
4850
#' @param ... A list of new name-value pairs. The name should be an aesthetic.
4951
#' @export
5052
#'
@@ -76,7 +78,8 @@ labs <- function(..., title = waiver(), subtitle = waiver(), caption = waiver(),
7678
tag = waiver(), alt = waiver(), alt_insight = waiver()) {
7779
# .ignore_empty = "all" is needed to allow trailing commas, which is NOT a trailing comma for dots_list() as it's in ...
7880
args <- dots_list(..., title = title, subtitle = subtitle, caption = caption,
79-
tag = tag, alt = alt, alt_insight = alt_insight, .ignore_empty = "all")
81+
tag = tag, alt = allow_lambda(alt), alt_insight = alt_insight,
82+
.ignore_empty = "all")
8083

8184
is_waive <- vapply(args, is.waive, logical(1))
8285
args <- args[!is_waive]
@@ -140,11 +143,15 @@ get_alt_text <- function(p, ...) {
140143
}
141144
#' @export
142145
get_alt_text.ggplot <- function(p, ...) {
143-
p$labels[["alt"]] %||% ""
146+
alt <- p$labels[["alt"]] %||% ""
147+
p$labels[["alt"]] <- NULL
148+
if (is.function(alt)) alt(p) else alt
144149
}
145150
#' @export
146151
get_alt_text.ggplot_built <- function(p, ...) {
147-
p$plot$labels[["alt"]] %||% ""
152+
alt <- p$plot$labels[["alt"]] %||% ""
153+
p$plot$labels[["alt"]] <- NULL
154+
if (is.function(alt)) alt(p$plot) else alt
148155
}
149156
#' @export
150157
get_alt_text.gtable <- function(p, ...) {
@@ -197,11 +204,16 @@ get_alt_text.gtable <- function(p, ...) {
197204
#'
198205
generate_alt_text <- function(p) {
199206
# Combine titles
200-
title <- glue(glue_collapse(
201-
sub("\\.?$", "", c(p$labels$title, p$labels$subtitle)),
202-
last = ": "
203-
), ". ")
204-
title <- safe_string(title)
207+
if (!is.null(p$label$title %||% p$labels$subtitle)) {
208+
title <- glue(glue_collapse(
209+
sub("\\.?$", "", c(p$labels$title, p$labels$subtitle)),
210+
last = ": "
211+
), ". ")
212+
title <- safe_string(title)
213+
} else {
214+
title <- ""
215+
}
216+
205217

206218
# Get axes descriptions
207219
axes <- glue(" showing ", glue_collapse(
@@ -218,7 +230,7 @@ generate_alt_text <- function(p) {
218230
if (length(layers) == 1) "a " else "",
219231
glue_collapse(layers, sep = ", ", last = " and "),
220232
" layer",
221-
if (length(layers) == 1) "" else "s",
233+
if (length(layers) == 1) "" else "s"
222234
)
223235
layers <- safe_string(layers)
224236

man/labs.Rd

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/labels.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# alt text can take a function
2+
3+
Code
4+
get_alt_text(p)
5+
Output
6+
[1] "A plot showing class on the x-axis and count on the y-axis using a bar layer"
7+
18
# plot.tag.position rejects invalid input
29

310
The `plot.tag.position` theme element must be a <character/numeric/integer> object.

tests/testthat/test-labels.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ test_that("alt text is returned", {
6969
expect_equal(get_alt_text(p), "An alt text")
7070
})
7171

72+
test_that("alt text can take a function", {
73+
p <- ggplot(mpg, aes(class)) +
74+
geom_bar() +
75+
labs(alt = ~ generate_alt_text(.x))
76+
expect_snapshot(get_alt_text(p))
77+
})
7278

7379
test_that("plot.tag.position rejects invalid input", {
7480
p <- ggplot(mtcars, aes(mpg, disp)) + geom_point() + labs(tag = "Fig. A)")

0 commit comments

Comments
 (0)