Compared to many other R packages, ‘box’ uses a somewhat different development workflow:
While ‘box’ uses ‘devtools’ and ‘roxygen2’ to generate documentation
and package infrastructure, generated code and data is not checked
into version control! This means in particular that the project
does not contain a NAMESPACE
file, since that is
auto-(re)generated by tools. Therefore, attempting to install the
current development version of ‘box’ via
pak::pak('klmr/box')
or equivalent means will
fail!
Instead, an up-to-date, automatically generated build of the development version of ‘box’ should be installed from R-Universe:
… or from the corresponding build
branch:
Alternatively it can be built manually using the instructions below.
The project contains a Makefile
written in the GNU Make
dialect that contains various development utilities. Invoking
make
without target will show a list of available targets
with short descriptions. Using this Makefile
isn’t
necessary, but it helps. In particular:
make documentation
builds the NAMESPACE
file, the shared C library and the package documentation.make test
runs the unit tests.make check
runs checks, and should run cleanly before
submitting a pull request: of note, make check
performs
additional checks that are not performed by either
R CMD check
or rcmdcheck::rcmdcheck()
(these
checks can be found as individual scripts under scripts/
;
they roughly correspond to some undocumented checks performed internally
on CRAN).All new code should be developed on a new branch with a name prefixed
fix/
(for bug fixes), feature/
(for new
features/enhancements), and chore/
(for any other
contributions: fixed typos, project infrastructure, tests, etc.).
Branches for pull requests will be merged into the main
branch.
The code style of ‘box’ is similar to the Tidyverse style guide, but with several notable differences:
The file extension for R code files is lowercase .r
(not uppercase .R
). The file extension for R Markdown files
is lowercase .rmd
(not uppercase .Rmd
).
Use =
for assignment, not <-
.
On the (very rare!) occasions where assignment inside a function
call is required, use additional parentheses to make =
syntactically an assignment rather than named argument passing.
<<-
is banned. Instead of
name <<- value
, use env$name = value
,
where env
is a previously-defined name referring to the
desired target environment. This pattern is used in various places in
the code, and good, context-dependent names for env
are
ns
, self
, or similar. assign()
should generally not be used when the name of the assignee is statically
known.
# GOOD:
self = parent.frame()
# … later, inside a nested closure:
self$x = TRUE
# BAD:
x <<- TRUE
# BAD:
assign('x', TRUE, envir = caller)
<<-
leaves it unclear
where assignment will happen. Subset-assignment via $
makes
the assignment target scope explicit, which makes the code clearer and
less error-prone.
Leave a space between function
and the following
opening parenthesis.
if
and while
, so the same
formatting conventions apply.
Use single quotes, not double quotes, around strings. — Even when
the string contains '
, which should be escaped.
Use four spaces for indentation. Do not add extra spaces to align assignments or named function call arguments.
The line length is hard-limited to 120 columns. Most lines should be shorter, but there is no (soft, or otherwise) limit at 80 columns.
Explicitly use integer literals where the logical type of the expression is integer.