You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
roxygen2 is extensible, and this vignette will show you how.
15
-
It starts with an introduction to the basic workflow of `roxygenize()` and the key data structures that power it. Then we'll show you how you can use its two extension points:
16
+
It starts with an introduction to the basic workflow of `roxygenize()` and the key data structures that power it.
17
+
Then we'll show you how you can use its two extension points:
16
18
17
-
- Add a new tag to generate a new top-level section in an `.Rd` file. This allows you to repeat yourself less when documenting your package. (See `vignette("reuse")` for other techniques.)
19
+
- Add a new tag to generate a new top-level section in an `.Rd` file.
20
+
This allows you to repeat yourself less when documenting your package.
21
+
(See `vignette("reuse")` for other techniques.)
18
22
19
-
- Add a new roclet. This lets you take full advantage of the computational machinery behind `roxygenize()` to compute anything you want or produce any artefact you can imagine.
23
+
- Add a new roclet.
24
+
This lets you take full advantage of the computational machinery behind `roxygenize()` to compute anything you want or produce any artefact you can imagine.
20
25
21
-
```{r setup}
26
+
```{r}
27
+
#| label: setup
22
28
library(roxygen2)
23
29
```
24
30
@@ -29,11 +35,15 @@ But if you're going to extend roxygen2, you'll need to know exactly what's happe
29
35
30
36
- Loads the package under roxygenizing, as well as any further packages ("packages" in `load_options()`).
31
37
32
-
- Parses all R files in the package, using available tags.
38
+
- Parses all R files in the package, using available tags.
33
39
34
-
- Finds the roclets (see `roclet()`) from its `roclets` argument or the "roclets" option (`load_options()`). It defaults to using the Collate "roclet", the Rd roclet, and NAMESPACE roclet, but you can also add your own.
40
+
- Finds the roclets (see `roclet()`) from its `roclets` argument or the "roclets" option (`load_options()`).
41
+
It defaults to using the Collate "roclet", the Rd roclet, and NAMESPACE roclet, but you can also add your own.
35
42
36
-
- Runs the different methods of all those roclets, in order and independently: clean (`roclet_clean`), preprocess (`roclet_preprocess()`), process (`roclet_process()`), and output (`roclet_output()`). Only process and output are routinely used. For example, if you think of the Rd roclet, its process method digests information from the tag parsing, combines inherits, etc. to create the content of each documentation topic, and its output method writes those topics to disk.
43
+
- Runs the different methods of all those roclets, in order and independently: clean (`roclet_clean`), preprocess (`roclet_preprocess()`), process (`roclet_process()`), and output (`roclet_output()`).
44
+
Only process and output are routinely used.
45
+
For example, if you think of the Rd roclet, its process method digests information from the tag parsing, combines inherits, etc.
46
+
to create the content of each documentation topic, and its output method writes those topics to disk.
37
47
38
48
## Key data structures
39
49
@@ -44,14 +54,15 @@ Before we dive into extending roxygen2, we need to first discuss two important d
44
54
A tag (a list with S3 class `roxy_tag`) represents a single tag.
45
55
It has the following fields:
46
56
47
-
-`tag`: the name of the tag.
57
+
-`tag`: the name of the tag.
48
58
49
-
-`raw`: the raw contents of the tag (i.e. everything from the end of this tag to the beginning of the next).
59
+
-`raw`: the raw contents of the tag (i.e.
60
+
everything from the end of this tag to the beginning of the next).
50
61
51
-
-`val`: the parsed value, which we'll come back to shortly.
62
+
-`val`: the parsed value, which we'll come back to shortly.
52
63
53
-
-`file` and `line`: the location of the tag in the package.
54
-
Used with `roxy_tag_warning()` to produce informative error messages.
64
+
-`file` and `line`: the location of the tag in the package.
65
+
Used with `roxy_tag_warning()` to produce informative error messages.
55
66
56
67
You *can* construct tag objects by hand with `roxy_tag()`:
57
68
@@ -67,10 +78,10 @@ However, you should rarely need to do so (except in tests), because you'll typic
67
78
A block (a list with S3 class `roxy_block`) represents a single roxygen block.
68
79
It has the following fields:
69
80
70
-
-`tags`: a list of `roxy_tags`.
71
-
-`call`: the R code associated with the block (usually a function call).
72
-
-`file` and `line`: the location of the R code.
73
-
-`object`: the evaluated R object associated with the code.
81
+
-`tags`: a list of `roxy_tags`.
82
+
-`call`: the R code associated with the block (usually a function call).
83
+
-`file` and `line`: the location of the R code.
84
+
-`object`: the evaluated R object associated with the code.
74
85
75
86
The easiest way to see the basic structure of a `roxy_block()` is to generate one by parsing a roxygen block with `parse_text()`:
76
87
@@ -92,21 +103,21 @@ block
92
103
93
104
You'll notice that some of the tags didn't exist in the original block:
94
105
95
-
*`@title` and `@description` are extracted from the text that appears before the first explicit tag.
96
-
*`@usage` is generated automatically from the function formals.
97
-
*`@.formals` is an "internal" tag that doesn't generate any output but is used to pass some important data around.
98
-
*`@backref` stores the source location of the block so we can later record which `.R` files contributed to each `.Rd` file.
106
+
-`@title` and `@description` are extracted from the text that appears before the first explicit tag.
107
+
-`@usage` is generated automatically from the function formals.
108
+
-`@.formals` is an "internal" tag that doesn't generate any output but is used to pass some important data around.
109
+
-`@backref` stores the source location of the block so we can later record which `.R` files contributed to each `.Rd` file.
99
110
100
111
## Adding a new `.Rd` tag
101
112
102
113
The most common way to extend roxygen2 is to create a new tag that adds output to `.Rd` files.
103
114
This requires defining a few methods:
104
115
105
-
1.Define a `roxy_tag_parse()` method that describes how to parse our new tag.
116
+
1. Define a `roxy_tag_parse()` method that describes how to parse our new tag.
106
117
107
-
2.Define a `roxy_tag_rd()` method that describes how to convert the tag into `.Rd` commands.
118
+
2. Define a `roxy_tag_rd()` method that describes how to convert the tag into `.Rd` commands.
108
119
109
-
3.If the tag's content is meant to appear in a custom section (as opposed to, say, the examples section), define a `format()` method that describes how to create the `.Rd` string.
120
+
3. If the tag's content is meant to appear in a custom section (as opposed to, say, the examples section), define a `format()` method that describes how to create the `.Rd` string.
110
121
111
122
To illustrate the basic idea, we'll create a new `@tip` tag that will create a bulleted list of tips about how to use a function.
112
123
The idea is to take something like this:
@@ -118,7 +129,7 @@ The idea is to take something like this:
118
129
119
130
That generates Rd like this:
120
131
121
-
```latex
132
+
```latex
122
133
\section{Tips and tricks}{
123
134
\itemize{
124
135
\item The mean of a logical vector is the proportion of \code{TRUE} values.
@@ -218,12 +232,14 @@ Note that there is no namespacing so if you're defining multiple new tags I reco
218
232
219
233
### Using your new tag
220
234
221
-
Now that the three methods are created, we still need to make them available to `roxygenize()`. First, you need to export the method:
235
+
Now that the three methods are created, we still need to make them available to `roxygenize()`.
236
+
First, you need to export the method:
222
237
223
-
* If the package defining the tag _imports_ roxygen2, use `@export`.
224
-
* If the package defining the tag only _suggests_ roxygen2, use `@exportMethod`.
238
+
- If the package defining the tag *imports* roxygen2, use `@export`.
239
+
- If the package defining the tag only *suggests* roxygen2, use `@exportMethod`.
225
240
226
-
Next, you'll need to load the tag-defining package in the package where you want to use it. For example, if you created some new tags in {packageFoo}, and would like to use these tags in your documentation for {packageBar}, append this line to the `DESCRIPTION` of {packageBar}:
241
+
Next, you'll need to load the tag-defining package in the package where you want to use it.
242
+
For example, if you created some new tags in {packageFoo}, and would like to use these tags in your documentation for {packageBar}, append this line to the `DESCRIPTION` of {packageBar}:
227
243
228
244
```
229
245
Config/roxygen2/packages: packageFoo
@@ -237,7 +253,8 @@ Creating a new roclet is usually a two part process.
237
253
First, you define new tags that your roclet will work with, unless your roclet only needs information from existing tags, or only needs the path to the package source[^vignette].
238
254
Second, you define a roclet that tells `roxygenize()` what to compute and produce based on this information.
239
255
240
-
[^vignette]: For example, the no-longer recommended `vignette_roclet()` only needs the path to the package source as input; it does not use information from the tag parsing step. Or the {roxylint} package only uses existing tags; its job is to warn you about suboptimal roxygen2 style.
256
+
[^vignette]: For example, the no-longer recommended `vignette_roclet()` only needs the path to the package source as input; it does not use information from the tag parsing step.
257
+
Or the {roxylint} package only uses existing tags; its job is to warn you about suboptimal roxygen2 style.
241
258
242
259
### Custom tags
243
260
@@ -254,7 +271,8 @@ For example:
254
271
#' @memo [EFFICIENCY] Currently brute-force; find better algorithm.
255
272
```
256
273
257
-
As above, we first define a parse method. This time we use custom format based on a regular expression:
274
+
As above, we first define a parse method.
275
+
This time we use custom format based on a regular expression:
Your package only needs to be installed when the user documents the package, which doesn't correspond precisely to any field in the `DESCRIPTION`. However, you can think of it as a development dependency and hence put it in the `Suggests:` field:
422
+
Your package only needs to be installed when the user documents the package, which doesn't correspond precisely to any field in the `DESCRIPTION`.
423
+
However, you can think of it as a development dependency and hence put it in the `Suggests:` field:
@@ -411,5 +433,5 @@ You don't have to do this, but it will help other developers working on the targ
411
433
This vignette is quite rough, so you might want to also read some roxygen2 source code to understand all the extension points.
412
434
413
435
Do not hesitate to also look for examples of roxygen2 extensions.
414
-
For instance, the [roxygenlabs](https://github.com/gaborcsardi/roxygenlabs) package (former incubator of roxygen2 features) used a third extension point: it _extended_ the Rd roclet with further methods, thus creating a supercharged Rd roclet rather than a brand-new roclet.
436
+
For instance, the [roxygenlabs](https://github.com/gaborcsardi/roxygenlabs) package (former incubator of roxygen2 features) used a third extension point: it *extended* the Rd roclet with further methods, thus creating a supercharged Rd roclet rather than a brand-new roclet.
415
437
Or, the [plumber2](https://github.com/posit-dev/plumber2) package only uses the parsing features from roxygen2, and does not use `roxygenize()` at all.
0 commit comments