fun1 {topichelp} | R Documentation |
Examples of help system links that need to be handled carefully if we change the current lookup order.
fun1(x, ...) fun2(x, ...)
x |
An object. |
... |
Extra arguments. |
This file documents a proposed change to the lookup rule in R's dynamic HTML help system, and identifies existing links on CRAN that will need to be updated to continue working as intended. It is also meant to serve as a source of test cases for the proposed change.
The source of this documentation can be found at https://github.com/deepayan/misc/blob/master/helptopic/man/funs.Rd
The R help system includes a concept of hyperlinks to other help pages. Such hyperlinks are supported to a limited extent in PDF (e.g., within-package links in the manual) and to a greater extent in HTML help.
For potential problems with within-package links, see
fun3
. This discussion is limited to links to
other packages. These come in two forms:
\link[pkg:foo]{link-text}
, and
\link[pkg]{foo}
equivalent to \link[pkg:foo]{foo}
Here pkg
is the target package, and foo
has historically
been documented to be interpreted as a file link; i.e., both
links above are supposed to go to the file corresponding to
pkg/man/foo.Rd
. The explicit file specification is needed
because R manual pages often document multiple objects; e.g.,
grid/man/grid.rect.Rd
documents both grid.rect
and
rectGrob
, so
\link[grid]{grid.rect}
is fine:
grid.rect
links to grid.rect.html
,
\link[grid]{rectGrob}
will fail (for static HTML)
because the file rectGrob.html
does not exist:
rectGrob
,
\link[grid:rectGrob]{rectGrob}
will also fail (for
static HTML) because it is equivalent to the previous link:
rectGrob
,
\link[grid:grid.rect]{rectGrob}
is fine:
rectGrob
links to
grid.rect.html
.
In R 2.10.0 or thereabouts, a new dynamic help system was introduced
to enable features not possible in static HTML files, such as the
ability to include content generated dynamically at the time of
rendering the page. This new system also modified the interpretation
for \link[pkg:foo]{link-text}
:
If the file pkg/man/foo.Rd
exists, it would link to
the corresponding HTML file foo.html
.
However, if this file does not exist, it would link to
the file containing the topic foo
(i.e.,
\alias{foo}
).
However, the link URL continues to be of the form
foo.html
in either case.
Note that this means that the link to be embedded in the HTML file being rendered does not need to know anything about the target package pkg, and in particular, whether the link will at all be resolved. The actual lookup will happen only when the user clicks on the link, and may fail if the target package is not installed or the file / topic does not exist in it.
This also means that the links in the generated HTML is the same for
both static and dynamic help, but in the latter case a foo.html
link is resolved to first display the help page generated by
man/foo.Rd
if it exists, and then to display the help
page generated by man/bar.Rd
if man/bar.Rd
contains
\alias{foo}
.
This can be verified by following the grid links above and checking the URL shown (through dynamic help).
It is possible, in principle, for multiple help pages, say
man/bar.Rd
and man/baz.Rd
, to contain
\alias{foo}
. Such packages can be installed (e.g., fun1
is an alias both in this page and in fun3
), but R
CMD check
will produce a WARNING, so such packages will not get on
CRAN. Such a link will resolve to one of the two pages, but we do not
really care which one.
In the current setup, one infelicity is that non-file links do not
work with static HTML pages. To solve this without changing the
generated HTML in any way, we must have a topic.html
file
available for every topic (alias) in a package. This can be done
easily by creating small one-line HTTP redirect files pointing to the
actual target file while processing the package man files.
To ensure that filenames get priority over topics, we only need to ensure that
topic redirect files do not overwrite an existing (primary) file of the same name
primary files (foo.Rd -> foo.html
) do overwrite
existing (topic) files of the same name.
Although file links are natural with traditional hyperlinks, for the R
help system it is more natural to link to topics rather than
filenames. There is a general consensus that we should move to a
system where \link[pkg:foo]{link-text}
should be interpreted
as a link to the topic foo in package pkg, regardless of
whether there is a file called man/foo.Rd
in it. In fact, there
are many instances of packages on CRAN where this interpretation has
been assumed, because of the support for topic links in the dynamic
help system (such links do not currently work with static HTML).
Implementing this should not be difficult, but unfortunately, switching completely to a topic-only lookup rule would be unfair to careful package authors who have intentionally linked to files. So the proposal is only to prefer topics and fall back to files when the topic does not exist.
This still leaves open the possibility of penalizing careful package
authors under certain special circumstances; namely, the package
pkg has a file foo.Rd
, as well as a topic
\alias{foo}
but in a different file bar.Rd
. In
such cases, a link like \link[pkg:foo]{link-text}
would change
meaning; from being a link to foo.Rd
it will become a link to
bar.Rd
.
The example code below finds instances of such occurrences on CRAN
(yielding 79 such packages). Fortunately, in all these cases, the name
of the file (bar.Rd
) is not an alias in the package (i.e.,
there is no \alias{bar}
), so links of the form
\link[pkg:bar]{link-text}
would unambiguously link to
bar.Rd
.
This is still not a problem unless there are other packages that actually link to one of these ambiguous topic / file pairs. Pattern matching leads to the following extant examples, which we need to analyze. Fortunately, there are not many packages that potentially need fixing, but we do need to find a resolution that will work both in pre- and post-change versions of R.
The examples are organized by target package.
Topic genind
is documented in file new.genind.Rd
. File
genind.Rd
documents genind-class
and other related methods.
Topic genpop
is documented in file new.genind.Rd
. File
genpop.Rd
documents genpop-class
and other related methods.
The following packages link to either of these (genind.Rd
and
genpop.Rd
):
EcoGenetics/man/EcoGenetics-package.Rd: Conversion to and from genpop is defined.
pegas/man/conversion.Rd: genind
,
poppr/man/make_haplotypes-method.Rd: genind object.
popprxl/man/read.genalexcel.Rd: genind
poppr/man/aboot.Rd: adegenet::genind()
poppr/man/aboot.Rd: adegenet::genpop()
with the specified strata.
All these currently link to the class page and not the function page. This is probably as intended in several cases, although probably not in at least the last two examples. Under the new proposal, these will link to the function page.
Links of the following form should work both under the current and proposed rules:
For the class page:
\link[adegenet:genind-class]{link-text}
For the function page:
\link[adegenet:new.genind]{link-text}
The following instances of \link[callr:rcmd_safe]
both
currently link to the topic rcmd_safe_env
in
rcmd_safe.Rd
, which is likely not intended. The topic
rcmd_safe
is documented in file rcmd.Rd
.
fakemake/man/check_archive.Rd:
callr::rcmd_safe("check")
,
pkgbuild/man/rcmd_build_tools.Rd: wrapper around
callr::rcmd_safe()
These will work as intended under the proposed scheme, so probably
best to leave them alone. Alternatively, change
\link[callr:rcmd_safe]{link-text}
to
\link[callr:rcmd]{link-text}
.
The file lamW.Rd
documents several functions, whereas the topic
lamW
is documented in file lamW-package.Rd
. So the
following links are all explicit and correct file links that will stop
working in the proposed scheme.
LambertW/man/W.Rd: lambertW0_C
and
LambertW/man/W.Rd: lambertWm1_C
in
the lamW package
LambertW/man/W.Rd:W
is a wrapper for
lambert_W0C
LambertW/man/W.Rd: lambert_Wm1_C
in
the lamW package.
LambertW/man/W.Rd: lambertW0_C
and
LambertW/man/W.Rd: lambertWm1_C
in
the lamW package;
A fix that should work under both current and proposed schemes is to
change \link[lamW:lamW]{lambertW0_C}
to the simpler (and more
correct) \link[lamW]{lambertW0}
,
etc. (lambertW0_C
is an internal function, not supposed to be
user-callable, and not documented in lamW.Rd
). Unfortunately,
this will no longer work for static pages in the current scheme, but
that is hopefully a minor consideration.
The only problematic link here is topic fit
which is documented
in file reexports.Rd
(as a rexported generic), while the file
fit.Rd
documents the S3 method fit.model_spec
. For the
links below that have the form \link[parsnip:fit]{link-text}
, the
intent is almost certainly to link to fit.Rd
, as the links
below currently do, but that will change under the proposed scheme.
rules/man/C5_rules.Rd:converted to numeric indicator
values. Note that using parsnip::fit()
will
rules/man/C5_rules.Rd:
parsnip::fit()
,
parsnip::fit_xy()
, ...
rules/man/cubist_rules.Rd: Note that using
parsnip::fit()
will
rules/man/cubist_rules.Rd:
parsnip::fit()
,
parsnip::fit_xy()
, ...
rules/man/rule_fit.Rd:
parsnip::fit()
,
parsnip::fit_xy()
, ...
workflows/man/fit-workflow.Rd: using
parsnip::fit.model_spec()
A fix that would work with both current and proposed schemes would be
change to links of the form
\link[parsnip:fit.model_spec]{link-text}
.
Here the file perm.Rd
documents topics permTS
,
permKS
, etc., and the topic perm
is in file
perm-package.Rd
.
FHtest/man/FHtesticp.Rd: see details in perm
interval/man/ictest.Rd: see details in perm
interval/man/ictest.Rd: see perm
The links (all \link[perm]{perm}
) above currently link to the
file, which is likely as intended. To continue this in a
back-compatible manner, they should be changed to
\link[perm:permTS]{perm}
.
The file Matern.corr.Rd
documents topic MaternCorr
,
while the topic Matern.corr
is an alias in
spaMM-internal.Rd
. The link
IsoriX/man/isofit.Rd: Matern.corr
for information
is likely meant to be to the file Matern.corr.Rd
, and so should
be changed to
\link[spaMM:MaternCorr]{Matern.corr}
,
or probably more appropriately and simply, to
\link[spaMM]{MaternCorr}
.
a <- tools:::CRAN_aliases_db() fun <- function(e) { files <- tools::file_path_sans_ext(names(e)) topics <- Map(setdiff, e, files) intersect(files, unlist(topics)) } z <- lapply(a, fun) z <- Filter(length, z) ambiguousTopics <- function(pkg) { ## filenames which are also topics in a different file files <- z[[pkg]] ## which file the corresponding topic is in otherfiles <- character(length(files)) for (i in seq_along(files)) { otherfiles[i] <- names(which(sapply(a[[pkg]], function(x) files[i] %in% x))) } ## Is 'otherfile' also a topic somewhere in the package? also_topic <- otherfiles %in% unlist(a[[pkg]]) data.frame(pkg = pkg, file = files, topicfile = otherfiles, also_topic = also_topic) } options(width = 120) do.call(rbind, lapply(names(z), ambiguousTopics))