Skip to content

Commit e1c800d

Browse files
authored
Remove ellipsis from theme (#1762)
Fixes #1744 * Modify theme to have named arguments
1 parent 70ae16c commit e1c800d

File tree

6 files changed

+408
-327
lines changed

6 files changed

+408
-327
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
* Themes are more homogeneous visually, and match `theme_grey` better.
5757
(@jiho, #1679)
5858

59+
* The `theme()` constructor now has named arguments rather than ellipsis. This
60+
should make autocomplete substantially more useful.
61+
5962
* `position_stack()` and `position_fill()` now sorts the stacking order so it
6063
matches the order of the grouping. Use level reordering to alter the stacking
6164
order. The default legend and stacking order is now also in line. The default

R/theme.r

Lines changed: 158 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -80,163 +80,143 @@ print.theme <- function(x, ...) utils::str(x)
8080
#' To see a graphical representation of the inheritance tree, see the
8181
#' last example below.
8282
#'
83-
#' @section Theme elements:
84-
#' The individual theme elements are:
85-
#'
86-
#' \tabular{ll}{
87-
#' line \tab all line elements
88-
#' (\code{element_line}) \cr
89-
#' rect \tab all rectangular elements
90-
#' (\code{element_rect}) \cr
91-
#' text \tab all text elements
92-
#' (\code{element_text}) \cr
93-
#' title \tab all title elements: plot, axes, legends
94-
#' (\code{element_text}; inherits from \code{text}) \cr
95-
#' aspect.ratio \tab aspect ratio of the panel \cr
96-
#'
97-
#' axis.title \tab label of axes
98-
#' (\code{element_text}; inherits from \code{text}) \cr
99-
#' axis.title.x \tab x axis label
100-
#' (\code{element_text}; inherits from \code{axis.title}) \cr
101-
#' axis.title.x.top \tab x axis label on top axis
102-
#' (\code{element_text}; inherits from \code{axis.title.x}) \cr
103-
#' axis.title.y \tab y axis label
104-
#' (\code{element_text}; inherits from \code{axis.title}) \cr
105-
#' axis.title.y.right \tab y axis label on right axis
106-
#' (\code{element_text}; inherits from \code{axis.title.y}) \cr
107-
#' axis.text \tab tick labels along axes
108-
#' (\code{element_text}; inherits from \code{text}) \cr
109-
#' axis.text.x \tab x axis tick labels
110-
#' (\code{element_text}; inherits from \code{axis.text}) \cr
111-
#' axis.text.x.top \tab x axis tick labels on top axis
112-
#' (\code{element_text}; inherits from \code{axis.text.x}) \cr
113-
#' axis.text.y \tab y axis tick labels
114-
#' (\code{element_text}; inherits from \code{axis.text}) \cr
115-
#' axis.text.y.right \tab y axis tick labels on right axis
116-
#' (\code{element_text}; inherits from \code{axis.text.y}) \cr
117-
#' axis.ticks \tab tick marks along axes
118-
#' (\code{element_line}; inherits from \code{line}) \cr
119-
#' axis.ticks.x \tab x axis tick marks
120-
#' (\code{element_line}; inherits from \code{axis.ticks}) \cr
121-
#' axis.ticks.y \tab y axis tick marks
122-
#' (\code{element_line}; inherits from \code{axis.ticks}) \cr
123-
#' axis.ticks.length \tab length of tick marks
124-
#' (\code{unit}) \cr
125-
#' axis.line \tab lines along axes
126-
#' (\code{element_line}; inherits from \code{line}) \cr
127-
#' axis.line.x \tab line along x axis
128-
#' (\code{element_line}; inherits from \code{axis.line}) \cr
129-
#' axis.line.y \tab line along y axis
130-
#' (\code{element_line}; inherits from \code{axis.line}) \cr
131-
#'
132-
#' legend.background \tab background of legend
133-
#' (\code{element_rect}; inherits from \code{rect}) \cr
134-
#' legend.margin \tab the margin around each legend
135-
#' (\code{margin}) \cr
136-
#' legend.spacing \tab the spacing between legends
137-
#' (\code{unit}) \cr
138-
#' legend.spacing.x \tab the horizontal spacing between legends
139-
#' (\code{unit}); inherits from \code{legend.spacing} \cr
140-
#' legend.spacing.y \tab the horizontal spacing between legends
141-
#' (\code{unit}); inherits from \code{legend.spacing} \cr
142-
#' legend.key \tab background underneath legend keys
143-
#' (\code{element_rect}; inherits from \code{rect}) \cr
144-
#' legend.key.size \tab size of legend keys
145-
#' (\code{unit}) \cr
146-
#' legend.key.height \tab key background height
147-
#' (\code{unit}; inherits from \code{legend.key.size}) \cr
148-
#' legend.key.width \tab key background width
149-
#' (\code{unit}; inherits from \code{legend.key.size}) \cr
150-
#' legend.text \tab legend item labels
151-
#' (\code{element_text}; inherits from \code{text}) \cr
152-
#' legend.text.align \tab alignment of legend labels
153-
#' (number from 0 (left) to 1 (right)) \cr
154-
#' legend.title \tab title of legend
155-
#' (\code{element_text}; inherits from \code{title}) \cr
156-
#' legend.title.align \tab alignment of legend title
157-
#' (number from 0 (left) to 1 (right)) \cr
158-
#' legend.position \tab the position of legends
159-
#' ("none", "left", "right", "bottom", "top", or two-element
160-
#' numeric vector) \cr
161-
#' legend.direction \tab layout of items in legends
162-
#' ("horizontal" or "vertical") \cr
163-
#' legend.justification \tab anchor point for positioning legend inside plot
164-
#' ("center" or two-element numeric vector) or the
165-
#' justification according to the plot area when positioned
166-
#' outside the plot \cr
167-
#' legend.box \tab arrangement of multiple legends
168-
#' ("horizontal" or "vertical") \cr
169-
#' legend.box.just \tab justification of each legend within the overall
170-
#' bounding box, when there are multiple legends
171-
#' ("top", "bottom", "left", or "right")\cr
172-
#' legend.box.margin \tab margins around the full legend area, as specified
173-
#' using \code{\link{margin}} \cr
174-
#' legend.box.background \tab background of legend area
175-
#' (\code{element_rect}; inherits from \code{rect}) \cr
176-
#' legend.box.spacing \tab The spacing between the plotting area and the
177-
#' legend box (\code{unit}) \cr
178-
#'
179-
#' panel.background \tab background of plotting area, drawn underneath plot
180-
#' (\code{element_rect}; inherits from \code{rect}) \cr
181-
#' panel.border \tab border around plotting area, drawn on top of plot
182-
#' so that it covers tick marks and grid lines. This should
183-
#' be used with \code{fill=NA}
184-
#' (\code{element_rect}; inherits from \code{rect}) \cr
185-
#' panel.spacing \tab spacing between facet panels
186-
#' (\code{unit}) \cr
187-
#' panel.spacing.x \tab horizontal spacing between facet panels
188-
#' (\code{unit}; inherits from \code{panel.spacing}) \cr
189-
#' panel.spacing.y \tab vertical spacing between facet panels
190-
#' (\code{unit}; inherits from \code{panel.spacing}) \cr
191-
#' panel.grid \tab grid lines
192-
#' (\code{element_line}; inherits from \code{line}) \cr
193-
#' panel.grid.major \tab major grid lines
194-
#' (\code{element_line}; inherits from \code{panel.grid}) \cr
195-
#' panel.grid.minor \tab minor grid lines
196-
#' (\code{element_line}; inherits from \code{panel.grid}) \cr
197-
#' panel.grid.major.x \tab vertical major grid lines
198-
#' (\code{element_line}; inherits from \code{panel.grid.major}) \cr
199-
#' panel.grid.major.y \tab horizontal major grid lines
200-
#' (\code{element_line}; inherits from \code{panel.grid.major}) \cr
201-
#' panel.grid.minor.x \tab vertical minor grid lines
202-
#' (\code{element_line}; inherits from \code{panel.grid.minor}) \cr
203-
#' panel.grid.minor.y \tab horizontal minor grid lines
204-
#' (\code{element_line}; inherits from \code{panel.grid.minor}) \cr
205-
#' panel.ontop \tab option to place the panel (background, gridlines)
206-
#' over the data layers. Usually used with a transparent
207-
#' or blank \code{panel.background}. (\code{logical}) \cr
208-
#'
209-
#' plot.background \tab background of the entire plot
210-
#' (\code{element_rect}; inherits from \code{rect}) \cr
211-
#' plot.title \tab plot title (text appearance)
212-
#' (\code{element_text}; inherits from \code{title})
213-
#' left-aligned by default\cr
214-
#' plot.subtitle \tab plot subtitle (text appearance)
215-
#' (\code{element_text}; inherits from \code{title})
216-
#' left-aligned by default\cr
217-
#' plot.caption \tab caption below the plot (text appearance)
218-
#' (\code{element_text}; inherits from \code{title})
219-
#' right-aligned by default\cr
220-
#' plot.margin \tab margin around entire plot
221-
#' (\code{unit} with the sizes of the top, right, bottom, and
222-
#' left margins) \cr
223-
#'
224-
#' strip.background \tab background of facet labels
225-
#' (\code{element_rect}; inherits from \code{rect}) \cr
226-
#' strip.text \tab facet labels
227-
#' (\code{element_text}; inherits from \code{text}) \cr
228-
#' strip.text.x \tab facet labels along horizontal direction
229-
#' (\code{element_text}; inherits from \code{strip.text}) \cr
230-
#' strip.text.y \tab facet labels along vertical direction
231-
#' (\code{element_text}; inherits from \code{strip.text}) \cr
232-
#' strip.switch.pad.grid \tab space between strips and axes when strips are switched
233-
#' (\code{unit}) \cr
234-
#' strip.switch.pad.wrap \tab space between strips and axes when strips are switched
235-
#' (\code{unit}) \cr
236-
#' }
237-
#'
238-
#' @param ... a list of element name, element pairings that modify the
239-
#' existing theme.
83+
#' @param line all line elements (\code{element_line})
84+
#' @param rect all rectangular elements (\code{element_rect})
85+
#' @param text all text elements (\code{element_text})
86+
#' @param title all title elements: plot, axes, legends (\code{element_text};
87+
#' inherits from \code{text})
88+
#' @param aspect.ratio aspect ratio of the panel
89+
#'
90+
#' @param axis.title label of axes (\code{element_text}; inherits from
91+
#' \code{text})
92+
#' @param axis.title.x x axis label (\code{element_text}; inherits from
93+
#' \code{axis.title})
94+
#' @param axis.title.x.top x axis label on top axis (\code{element_text};
95+
#' inherits from \code{axis.title.x})
96+
#' @param axis.title.y y axis label (\code{element_text}; inherits from
97+
#' \code{axis.title})
98+
#' @param axis.title.y.right y axis label on right axis (\code{element_text};
99+
#' inherits from \code{axis.title.y})
100+
#' @param axis.text tick labels along axes (\code{element_text}; inherits from
101+
#' \code{text})
102+
#' @param axis.text.x x axis tick labels (\code{element_text}; inherits from
103+
#' \code{axis.text})
104+
#' @param axis.text.x.top x axis tick labels on top axis (\code{element_text};
105+
#' inherits from \code{axis.text.x})
106+
#' @param axis.text.y y axis tick labels (\code{element_text}; inherits from
107+
#' \code{axis.text})
108+
#' @param axis.text.y.right y axis tick labels on right axis
109+
#' (\code{element_text}; inherits from \code{axis.text.y})
110+
#' @param axis.ticks tick marks along axes (\code{element_line}; inherits from
111+
#' \code{line})
112+
#' @param axis.ticks.x x axis tick marks (\code{element_line}; inherits from
113+
#' \code{axis.ticks})
114+
#' @param axis.ticks.y y axis tick marks (\code{element_line}; inherits from
115+
#' \code{axis.ticks})
116+
#' @param axis.ticks.length length of tick marks (\code{unit})
117+
#' @param axis.line lines along axes (\code{element_line}; inherits from
118+
#' \code{line})
119+
#' @param axis.line.x line along x axis (\code{element_line}; inherits from
120+
#' \code{axis.line})
121+
#' @param axis.line.y line along y axis (\code{element_line}; inherits from
122+
#' \code{axis.line})
123+
#'
124+
#' @param legend.background background of legend (\code{element_rect}; inherits
125+
#' from \code{rect})
126+
#' @param legend.margin the margin around each legend (\code{margin})
127+
#' @param legend.spacing the spacing between legends (\code{unit})
128+
#' @param legend.spacing.x the horizontal spacing between legends (\code{unit});
129+
#' inherits from \code{legend.spacing}
130+
#' @param legend.spacing.y the horizontal spacing between legends (\code{unit});
131+
#' inherits from \code{legend.spacing}
132+
#' @param legend.key background underneath legend keys (\code{element_rect};
133+
#' inherits from \code{rect})
134+
#' @param legend.key.size size of legend keys (\code{unit})
135+
#' @param legend.key.height key background height (\code{unit}; inherits from
136+
#' \code{legend.key.size})
137+
#' @param legend.key.width key background width (\code{unit}; inherits from
138+
#' \code{legend.key.size})
139+
#' @param legend.text legend item labels (\code{element_text}; inherits from
140+
#' \code{text})
141+
#' @param legend.text.align alignment of legend labels (number from 0 (left) to
142+
#' 1 (right))
143+
#' @param legend.title title of legend (\code{element_text}; inherits from
144+
#' \code{title})
145+
#' @param legend.title.align alignment of legend title (number from 0 (left) to
146+
#' 1 (right))
147+
#' @param legend.position the position of legends ("none", "left", "right",
148+
#' "bottom", "top", or two-element numeric vector)
149+
#' @param legend.direction layout of items in legends ("horizontal" or
150+
#' "vertical")
151+
#' @param legend.justification anchor point for positioning legend inside plot
152+
#' ("center" or two-element numeric vector) or the justification according to
153+
#' the plot area when positioned outside the plot
154+
#' @param legend.box arrangement of multiple legends ("horizontal" or
155+
#' "vertical")
156+
#' @param legend.box.just justification of each legend within the overall
157+
#' bounding box, when there are multiple legends ("top", "bottom", "left", or
158+
#' "right")
159+
#' @param legend.box.margin margins around the full legend area, as specified
160+
#' using \code{\link{margin}}
161+
#' @param legend.box.background background of legend area (\code{element_rect};
162+
#' inherits from \code{rect})
163+
#' @param legend.box.spacing The spacing between the plotting area and the
164+
#' legend box (\code{unit})
165+
#'
166+
#' @param panel.background background of plotting area, drawn underneath plot
167+
#' (\code{element_rect}; inherits from \code{rect})
168+
#' @param panel.border border around plotting area, drawn on top of plot so that
169+
#' it covers tick marks and grid lines. This should be used with
170+
#' \code{fill=NA}
171+
#' (\code{element_rect}; inherits from \code{rect})
172+
#' @param panel.spacing spacing between facet panels (\code{unit})
173+
#' @param panel.spacing.x horizontal spacing between facet panels (\code{unit};
174+
#' inherits from \code{panel.spacing})
175+
#' @param panel.spacing.y vertical spacing between facet panels (\code{unit};
176+
#' inherits from \code{panel.spacing})
177+
#' @param panel.grid grid lines (\code{element_line}; inherits from \code{line})
178+
#' @param panel.grid.major major grid lines (\code{element_line}; inherits from
179+
#' \code{panel.grid})
180+
#' @param panel.grid.minor minor grid lines (\code{element_line}; inherits from
181+
#' \code{panel.grid})
182+
#' @param panel.grid.major.x vertical major grid lines (\code{element_line};
183+
#' inherits from \code{panel.grid.major})
184+
#' @param panel.grid.major.y horizontal major grid lines (\code{element_line};
185+
#' inherits from \code{panel.grid.major})
186+
#' @param panel.grid.minor.x vertical minor grid lines (\code{element_line};
187+
#' inherits from \code{panel.grid.minor})
188+
#' @param panel.grid.minor.y horizontal minor grid lines (\code{element_line};
189+
#' inherits from \code{panel.grid.minor})
190+
#' @param panel.ontop option to place the panel (background, gridlines) over
191+
#' the data layers. Usually used with a transparent or blank
192+
#' \code{panel.background}. (\code{logical})
193+
#'
194+
#' @param plot.background background of the entire plot (\code{element_rect};
195+
#' inherits from \code{rect})
196+
#' @param plot.title plot title (text appearance) (\code{element_text}; inherits
197+
#' from \code{title}) left-aligned by default
198+
#' @param plot.subtitle plot subtitle (text appearance) (\code{element_text};
199+
#' inherits from \code{title}) left-aligned by default
200+
#' @param plot.caption caption below the plot (text appearance)
201+
#' (\code{element_text}; inherits from \code{title}) right-aligned by default
202+
#' @param plot.margin margin around entire plot (\code{unit} with the sizes of
203+
#' the top, right, bottom, and left margins)
204+
#'
205+
#' @param strip.background background of facet labels (\code{element_rect};
206+
#' inherits from \code{rect})
207+
#' @param strip.text facet labels (\code{element_text}; inherits from
208+
#' \code{text})
209+
#' @param strip.text.x facet labels along horizontal direction
210+
#' (\code{element_text}; inherits from \code{strip.text})
211+
#' @param strip.text.y facet labels along vertical direction
212+
#' (\code{element_text}; inherits from \code{strip.text})
213+
#' @param strip.switch.pad.grid space between strips and axes when strips are
214+
#' switched (\code{unit})
215+
#' @param strip.switch.pad.wrap space between strips and axes when strips are
216+
#' switched (\code{unit})
217+
#'
218+
#' @param ... additional element specifications not part of base ggplot2. If
219+
#' supplied \code{validate} needs to be set to \code{FALSE}.
240220
#' @param complete set this to TRUE if this is a complete theme, such as
241221
#' the one returned \code{by theme_grey()}. Complete themes behave
242222
#' differently when added to a ggplot object. Also, when setting
@@ -387,8 +367,27 @@ print.theme <- function(x, ...) utils::str(x)
387367
#' p + mytheme
388368
#'
389369
#' }
390-
theme <- function(..., complete = FALSE, validate = TRUE) {
391-
elements <- list(...)
370+
theme <- function(line, rect, text, title, aspect.ratio, axis.title,
371+
axis.title.x, axis.title.x.top, axis.title.y,
372+
axis.title.y.right, axis.text, axis.text.x, axis.text.x.top,
373+
axis.text.y, axis.text.y.right, axis.ticks, axis.ticks.x,
374+
axis.ticks.y, axis.ticks.length, axis.line, axis.line.x,
375+
axis.line.y, legend.background, legend.margin, legend.spacing,
376+
legend.spacing.x, legend.spacing.y, legend.key,
377+
legend.key.size, legend.key.height, legend.key.width,
378+
legend.text, legend.text.align, legend.title,
379+
legend.title.align, legend.position, legend.direction,
380+
legend.justification, legend.box, legend.box.just,
381+
legend.box.margin, legend.box.background, legend.box.spacing,
382+
panel.background, panel.border, panel.spacing,
383+
panel.spacing.x, panel.spacing.y, panel.grid,
384+
panel.grid.major, panel.grid.minor, panel.grid.major.x,
385+
panel.grid.major.y, panel.grid.minor.x, panel.grid.minor.y,
386+
panel.ontop, plot.background, plot.title, plot.subtitle,
387+
plot.caption, plot.margin, strip.background, strip.text,
388+
strip.text.x, strip.text.y, strip.switch.pad.grid,
389+
strip.switch.pad.wrap, ..., complete = FALSE, validate = TRUE) {
390+
elements <- find_args(..., complete = NULL, validate = NULL)
392391

393392
if (!is.null(elements$axis.ticks.margin)) {
394393
warning("`axis.ticks.margin` is deprecated. Please set `margin` property ",

R/utilities.r

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,20 @@ dispatch_args <- function(f, ...) {
281281
f
282282
}
283283

284+
is_missing_arg <- function(x) identical(x, quote(expr = ))
285+
# Get all arguments in a function as a list. Will fail if an ellipsis argument
286+
# named .ignore
287+
# @param ... passed on in case enclosing function uses ellipsis in argument list
288+
find_args <- function(...) {
289+
env <- parent.frame()
290+
args <- names(formals(sys.function(sys.parent(1))))
291+
292+
vals <- mget(args, envir = env)
293+
vals <- vals[!vapply(vals, is_missing_arg, logical(1))]
294+
295+
modifyList(vals, list(..., `...` = NULL))
296+
}
297+
284298
# Used in annotations to ensure printed even when no
285299
# global data
286300
dummy_data <- function() data.frame(x = NA)

0 commit comments

Comments
 (0)