Linking to an S4 method in a .rd file? - r

I'm writing a package with an S4 class, and I've written methods for as.POSIXct and as.POSIXlt for the class. I've written the documentation and everything looks fine, except that I would like to reference the as.POSIXct method in the documentation for as.POSIXlt, and vice versa. I tried \S4method{coerce}{abc, POSIXct}(from, to), (where 'abc' is the S4 class), but that is only supposed to be put in the \usage section, which isn't where I want it. Is there a way to do this? It seems odd to me that it would not be allowed.
I realize that it is possible to combine these .rd files and avoid this issue, but I'm trying to learn as much as possible about classes and packages in R, so this is of interest to me anyway.
Here is the skeleton of one of the .Rd files:
\name{as.POSIXct-methods}
\docType{methods}
\alias{as.POSIXct-methods}
\alias{as.POSIXct,ANY-method}
\alias{as.POSIXct,abc-method}
\title{\code{abc} Method for Function \code{as.POSIXct}}
\description{
\code{as.POSIXct} method to coerce timestamps in \code{abc} objects into
\code{POSIXct} format.
}
\section{Methods}{
\describe{
~~description here~~
\item{\code{signature(x = "ANY")}}{
default implementation (from base)
}
\item{\code{signature(x = "abc")}}{
implementation for \code{\link{abc}} objects.
~~more description of function~~
See \code{\linkS4class{abc}} for more about abc objects.
See also \code{\link[abc]{as.POSIXlt}} for the corresponding \code{POSIXlt} method.
}
}}
\keyword{methods}
The line fourth from the bottom is the one that is causing problems.

The basic format for a link is
\link{foo}
where foo appears in some help page (in the same package) as \alias{foo}. So if your other package has \alias{as.POSIXlt,abc-method} (pay attention to the absence of spaces) then
\link{as.POSIXlt,abc-method}
Adding [abc] is only necessary when linking to other packages, and then the semantics are confusing (in \link[abc]{foo}, foo is the name of the HTML help page, rather than, e.g., an alias). Adding \code{} is mark-up, so not directly relevant to establishing a link. The link above inserts "as.POSIXlt,abc-method" into the help page, which might be more informative (or not) than an arbitrary \alias tag that might be present.

Per the Cross-references section of Writing R extensions, you can create links to other help pages like this:
\code{\link[base]{as.POSIXct}}
Where "base" is the name of the package (I don't think [base] is necessary, but if it were another package, it would be)

Related

How to get roxygen2 to interpret backticks as code formatting?

The standard way of writing documentation with code formatting is by using \code{}.
That is, #' #param foo value passed on to \code{bar()} becomes
Arguments
foo    value passed on to bar()
However, I've seen some packages (i.e. dplyr) using backticks instead of \code{} to the same effect. This is much better, since it's less clunky and allows for very nice syntax highlighting.
However, if I try that on my own package, the backticks get interpreted as... just backticks, like any other character.
The documentation for dplyr::across(), for example, starts with:
#' #description
#' `across()` makes it easy to apply the same transformation to multiple [...]
which gets compiled and displayed in the man page as:
Description
across() makes it easy to apply the same transformation to multiple [...]
But if I try something similar on my package, I get:
Description
`across()` makes it easy to apply the same transformation to multiple [...]
Weirdly, I've forked the package glue (which also manages to use backticks for code formatting) for a simple PR, and if I build the package locally, the backticks work (I get code formatting). Can't for the life of me figure out why it works there but not for my package.
So, is there some setting I need to modify to get this to work? I checked the dplyr.Rproj but found nothing relevant. I also glanced at the Doxyfile, but didn't know what it did or what I'd even be looking for there.
All credit goes to #rawr's comment to the question, just formalizing it with an answer:
The secret is in the roxygen2 documentation: just add the following to the end of the package DESCRIPTION file:
# DESCRIPTION file
# [... rest of file ...]
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.2 # actually works since 6.0.0
As that code would imply, this sets roxygen2 to interpret the commands as good ol' Markdown like we're used to using here on SO and elsewhere. This also implies all the other standard Markdown commands such as **bold** and *italics*, as well as [text](http://www.url.com), code blocks defined by ```, itemized and enumerated lists, etc. It's a huge improvement across the board.
Though be careful and take a look at the documentation, since there are a few gotchas. For instance, an empty line isn't necessary to start lists, so don't start any lines with #' 1. [...] or #' * [...] or you'll accidentally create a list!). There's also a few things which don't work yet, but they're pretty minor.

Atom editor: list and jump to definition(s) in project

As already mentioned I'm using the Atom text editor.
I'm currently working on a project written in c++. Of course it is desirable to jump to the definition of a function (in another project file), or other uses of this function (within the project). As far as I know this can be achieved with the packages I'll mention below. I want the package to display me the definition along with the path to the corresponding file which holds the definition and ideally the line where it occurs.
I'll welcome any comments and suggestions on how to solve the below mentioned problem(s) I have with (one of) the packages. Moreover I'm also thankful about pointers to possible solutions or posts concerning my problem(s), or how I can achieve this with another package.
Here is what I found / tried / did so far.
goto
Currently I'm using this package, although it is rather slow and does not show the arguments of the function as e.g. atom-ctags does, but it's the only package which displays me the files I need to see.
It shows me where the function is defined as well as where it is also used. However it does not show me the path to the file corresponding file it refers to.
atom-ctags
I also tried this package, building the tags is quite fast and moreover it show me the path to the file. But this package only lists the .cc files and not the .h files. It appears to me as if it only shows me the other uses but not the definition, which is obviously a problem.
I also tried generating the ctags myself and changing the command options in the settings of the package, unfortunately without any success.
Atoms built-in symbols-view
In order to get this to work, one needs to generate the symbols. This can be, for example, achieved with the symbol-gen package. However, it shows me some of the definitions, but also no .h files. Moreover, jumping to the definition results in a Selected file does not exist., therefore it is not usable at all.
goto-definition
Just for completeness, there is also this package. It does not work for me, since c++ is not supported but maybe others will find it useful.
symbols-plus
Again, for completeness, this should be a replacement for the atom built-in, but when disabling the build-in it does not show me any jump functionality nor is a short cut mentioned.
So, basically, nothing really works well. I have tried Symbol Tree View but it but barely works.

how to use utils::globalVariables

Following your recommendations (or trying to do it, at least), I have tried some options, but the problem remains, so there must be something I am missing.
I have included a more complete code
setwd("C:/naapp")
#' #import utils
#' #import devtools
I have tried with and without using suppressForeignCheck
if(getRversion() >= "2.15.1"){
utils::globalVariables(c("eleven"))
utils::suppressForeignCheck(c("eleven"))
}
myFunctionSum <- function(X){print(X+eleven)}
myFunctionMul <- function(X){print(X*eleven)}
myFunction11 <- function(X){
assign("eleven",11,envir=environment(myFunctionMul))
}
maybe I should use a particular environment?
package.skeleton(name = "myPack11", list=ls(),
path = "C:/naapp", force = TRUE,
code_files = character())
I remove the "man" directory from the directory myPack11,
otherwise I would get an error because the help files are empty.
I add the imports utils, and devtools to the descrption
Then I run check
devtools::check("myPack11")
And I still get this note
#checking R code for possible problems ... NOTE
#myFunctionMul: no visible binding for global variable 'eleven'
#myFunctionSum: no visible binding for global variable 'eleven'
#Undefined global functions or variables:eleven
I have tried also to make an enviroment, combining Tomas Kalibera's suggetion and an example I found in the Internet.
myEnvir <- new.env()
myEnvir$eleven <- 11
etc
In this case, I get the same note, but with "myEnvir", instead of "eleven"
First version of the question
I trying to use "globalVariables" from the package utils. I am building an interface in R and I am planning to submit to CRAN. This is my first time, so, sorry if the question is very basic.I have read the help and I have tried to find examples, but I still don't know how to use it.
I have made a little silly example to ilustrate my question, which is:
Where do I have to place this line exactly?:
if(getRversion() >= "2.15.1"){utils::globalVariables("eleven")}
My example has three functions. myFunction11 creates the global variable "eleven" and the other two functions manipulate it. In my real code, I cannot use arguments in the functions that are called by means of a button. Consider that this is just a silly example to learn how to use globalVariables (to avoid binding notes).
myFunction11 <- function(){
assign("eleven",11,envir=environment(myFunctionSum))
}
myFunctionSum <- function(X){
print(X+eleven)
}
myFunctionMul <- function(X){
print(X*eleven)
}
Thank you in advance
I thought that the file globals.R would be automatically generated when using globalsVariables. The problem was that I needed to create the package skeleton, then create the file globals.R, add it to the R directory in the package and check the package.
So, I needed to place this in a different file:
#' #import utils
utils::globalVariables(c("eleven"))
and save it
The documentation clearly says:
## In the same source file (to remind you that you did it) add:
if(getRversion() >= "2.15.1") utils::globalVariables(c(".obj1", "obj2"))
so put it in the same source file as your functions. It can go in any of your R source files, but the comment above recommends you put it close to your code. Looking at a bunch of github packages reveals another common pattern is to have a globals.R function with it in, but this is probably a bad idea. If you later remove the global from your package but neglect to update globals.R you could mask a problem. Putting it right close to the functions that use it will hopefully remind you when you edit those functions.
Make sure you put it outside any function definitions in the file, or it won't get seen.
You cannot modify bindings in a package namespace once the package is loaded (and namespace sealed, and bindings locked). The check tool helps you to spot violations of this restriction, so you find out about the problem when checking the package rather than while running it. globalVariables is just a call to silence check when looking for these violations, which is undesirable in almost all cases. If you really need mutable state in a package, you can create a new environment (using new.env) and bind it to an (unexported) "global" variable in your namespace. This binding will be locked, but this is ok, because in R you can change an environment in place (add/remove elements, effectively modifying the elements).
The best situation is however when you can keep all mutable state in user objects (passed in as arguments into functions, and their modified versions returned as output values of functions).

why roxygen2 does not automatically update "Imports" in DESCRIPTION file?

I am trying to follow closely #hadley's book to learn best practices in writing R packages. And I was thrilled to read these lines about the philosophy of the book:
anything that can be automated, should be automated. Do as little as
possible by hand. Do as much as possible with functions.
So when I was reading about dependencies and the (sort of) confusing differences between import directives in the NAMESPACE file and the "Imports:" field in the DESCRIPTION file, I was hoping that roxygen2 would automatically handle both of them. After all
Every package mentioned in NAMESPACE must also be present in the
Imports or Depends fields.
I was hoping that roxygen2 would take every #import in my functions and make sure it is included in the DESCRIPTION file. But it does not do that automatically.
So I either have to add it manually to the DESCRIPTION file or almost manually using devtools::use_package.
Looking around for an answer, I found this question in SO, where #hadley confirms in the comments that
Currently, the namespace roclet will modify NAMESPACE but not
DESCRIPTION
and other posts (e.g. here or here) where collate_roclet is discussed, but "This only matters if your code has side-effects; most commonly because you’re using S4".
I wonder:
the reason that DESCRIPTION is not automatically updated (sort of contradicting the aforementioned philosophy, which is presumably shared by roxygen2) and
If someone has already crafted a way to do it
I have written a little R package for that task:
https://github.com/markusdumke/pkghelper
It scans the R Code and NAMESPACE for packages in use and adds them to the Imports section.
The namespace_roclet edits the NAMESPACE file based on the tags added in the script before the function. As there are three types of dependencies (Depends, Imports, and Suggests), a similar method as used by the namespace_roclet would require three different tags (notice Imports should be a different one, to differentiate it from the packages to attach in NAMESPACE).
If you are willing to take a semi-automated process, you could identify the packages you have used and add the missing ones to DESCRIPTION, in the adequate sections.
library(reinstallr)
package.dir <- getwd()
base_path <- normalizePath(package.dir)
files <- list.files(file.path(base_path, "R"), full.names = TRUE)
packages <- unique(reinstallr:::scan_for_packages(files)$package)
packages
Regarding the two bullets you wonder about at the bottom:
Updates to the DESCRIPTION file could be further automated with additional roclets, however already >4 years ago such a pull request was deferred:
https://github.com/klutometis/roxygen/pull/76
I have to assume that the guys would indeed rather have you use the devtools package for updating the DESCRIPTION file, instead of adding this to roxygen2. So in that sense, devtools would be the first available choice

Changing the load order of files in an R package

I'm writing a package for R in which the exported functions are decorated by a higher-order function that adds error checking and some other boilerplate code.
However, because this code is at the top-level it is evaluated after parsing. These means that
the load order of the package files is important.
To give an equivalent but simplified example, suppose I have a package with two files (Negate2 and Utils), and I require Negate2.R to be loaded first for the function 'isfalse( )' to be defined without throwing an error.
# /Negate2.R
Negate2 <- Negate
# -------------------
# /Utils.R
istrue <- isTRUE
isfalse <- Negate2(istrue)
Is it possible to structure NAMESPACE, DESCRIPTION (collate) or another package file in order to change the load order of files? The internal working of the R package structure and CRAN are still black magic to me.
It is possible to get around this problem using awkward hacks, but the least repetitive way of solving this problem. The wrapper function must be a higher-order function, since it also changes the function call semantics of its input function. The package is code heavy (~6000 lines, 100 functions) so repetition would be...problematic.
Solution
As #Manetheran points out, to change the load order you just change the order of the file names in the DESCRIPTION file.
# /DESCRIPTION
Collate:
'Negate2.R'
'Utils.R'
The Collate: field of the DESCRIPTION file allows you to change the order files are loaded when the package is built.
I stumbled across the answer to this question yesterday while reading up on Roxygen. If you've been documenting your functions with Roxygen, it can try to intelligently order your R source files in the Collate: field (based on where S4 class and method definitions are). This can be done by adding "collate" to the roclets argument of roxygenize. Alternatively if you're developing in RStudio there is a simple box that can be checked under Build->Configure Build Tools->Configure... (Button next to "Generate documentation with Roxygen").
R loads files in alphabetical order. To change the order, Collate field could be used from the DESCRIPTION file.
roxygen2 provides an explicit way of saying that one file must be loaded before another: #include. The #include tag gives a space separated list of file names that should be loaded before the current file:
#' #include class-a.r
setClass("B", contains = "A")
If any #include tags are present in the package, roxygen2 will set the Collate field in the DESCRIPTION.
You need to run generation of roxygen2 documentation in order to changes to take effect.

Resources