Management of customized (and nested) project/package options
require("devtools")
## Dependencies //
devtools::install_github("Rappster/conditionr")
devtools::install_github("Rappster/yamlr")
devtools::install_github("Rappster/typr")
devtools::install_github("Rappster/reactr")
devtools::install_github("Rappster/nestr")
## Actual package //
devtools::install_github("Rappster/optionr")
require("optionr")
The package provides an extendable interface to conveniently create customized project/package options. Options can be specified and retrieved based on path-like names/identifiers (e.g. output/print/type = "pdf"
will be translated into the following nested environment structure: output$print$type
with the value being "pdf"
).
Also, it allows to specify reactive options, i.e. options that are dynamically linked to other options and thus automatically stay synced.
The package aims at providing a clearly structured and easy to use interface for other programmers. For almost all of the function custom S4 methods can be specified.
None so fare
All examples assume that your working directory points to a directory containing an R package project. Running devtools::as.package(".")$package
should result in the package/project name.
By default, a so called option container (which simply an empty environment
) is created and assigned to the name corresponding to the package/project name (determined via devtools::as.package(".")$package
).
The function that takes care of this is ensureOptionContainer()
.
Assuming that your package/project has name my.package
, ensureOptionContainer()
assigns an empty environment
to the R option .my.package
(or my.package
if hidden = FALSE
). You can retrieve the option container via the convenience function getOptionContainer()
or via getOption(".my.package")
.
For package optionr
itself this would look like this:
## Hidden //
ensureOptionContainer(overwrite = TRUE)
".optionr" %in% names(options())
## --> only TRUE for package `optionr`; use your package name instead
## Not hidden //
ensureOptionContainer(overwrite = TRUE, hidden = FALSE)
"optionr" %in% names(options())
## --> only TRUE for package `optionr`; use your package name instead
## Retrieve container //
container <- getOptionContainer()
ls(container, all.names = TRUE)
## --> empty
A slightly more pre-configured version of such an option container is created/ensured via initializeOptionContainer()
which is the preferred top-level function to making sure an option container exists.
The container already has three elements (which in turn are environment
s) for reasons of a better encapsulation of option container components:
options
:
Initialized via initializeProjectOptions()
and used for storing and retrieving actual project options via setProjectOption()
and getProjectOption()
.
.meta
:
Initialized via initializeMeta()
and used for storing and retrieving certain meta information via setMetaValue()
and getMetaValue()
(if desired; can be omitted by changing the value of components
in call to initializeOptionContainer()
).
.registry
:
Initialized via initializeRegistry()
and used for storing and retrieving certain registry information via setRegistryValue()
and getRegistryValue()
(if desired; can be omitted by changing the value of components
in call to initializeOptionContainer()
).
For each of the functions mentioned in this chapter custom S4 methods can be defined. Thus, the entire initialization process can be fully customized in a clean and extendable way.
For package optionr
itself this would look like this:
## Initialize //
container <- initializeOptionContainer(overwrite = TRUE)
## Inspect //
ls(container, all.names = TRUE)
## --> pre-configured
The following functions are convenience wrappers around setAnywhereOption()
and getAnywhereOption()
(see section below).
setProjectOption(id = "x_1", value = TRUE)
existsProjectOption(id = "x_1")
getProjectOption(id = "x_1")
rmProjectOption(id = "x_1")
existsProjectOption(id = "x_1")
## --> removed
setProjectOption(id = "x_2/a/b", value = 10)
getProjectOption(id = "x_2")
## --> branch
getProjectOption(id = "x_2/a")
## --> branch
getProjectOption(id = "x_2/a/b")
## --> leaf, i.e. the actual option and its value
Implicit typing by remembering the type/class when setting an option:
setProjectOption(id = "a", value = "abc", typed = TRUE, strict = 2)
## --> `strict` controls how strict you would like to be with respect to
## what happens when trying to assign values of the wrong type/class
setProjectOption(id = "a", value = 1:3)
getProjectOption(id = "a")
## --> value is still "abc"
setProjectOption(id = "a", value = "def")
getProjectOption(id = "a")
## --> as "def" has the correct type/class, the option value is changed
setProjectOption(id = "dirs/wd", value = getwd(), reactive = TRUE)
setProjectOption(
id = "dirs/reactive_subdir",
value = reactiveOption(file.path(getProjectOption("dirs/wd"), "my_directory"))
)
getProjectOption(id = "dirs/wd")
getProjectOption(id = "dirs/reactive_subdir")
setProjectOption(id = "dirs/wd", value = "c:/temp")
getProjectOption(id = "dirs/reactive_subdir")
setProjectOption(id = "x_1", value = TRUE, sub_id = "a")
getProjectOption(id = "x_1", sub_id = "a")
setProjectOption(id = "x/y", value = list(a = 1, b = 2), sub_id = "a")
getProjectOption(id = "x/y", sub_id = "a")
Sometimes I found it usefull to have a central place for keeping certain meta information.
By default, they live in environment .meta
below the root level of the option container. The existence of this environment can be suppressed by specifying components
accordingly in the call to initializeOptionContainer()
.
Also see the function controlling the initialization: initializeMeta()
The following functions are convenience wrappers around setAnywhereOption()
and getAnywhereOption()
(see section below).
setMetaValue(id = "a/b/c", value = 10)
existsMetaValue(id = "a/b/c")
getMetaValue(id = "a/b/c")
identical(getMetaValue(id = "a/b/c"), container$.meta$a$b$c)
rmMetaValue(id = "a/b/c")
existsMetaValue(id = "a/b/c")
## Sub ID //
setMetaValue(id = "a/b/c", value = 20, sub_id = "a")
getMetaValue(id = "a/b/c", sub_id = "a")
Sometimes I found it usefull to have a central place for keeping certain registry information (e.g. see package reactr).
By default, they live in environment .registry
below the root level of the option container. The existence of this environment can be suppressed by specifying components
accordingly in the call to initializeOptionContainer()
.
Also see the function controlling the initialization: initializeRegistry()
The following functions are convenience wrappers around setAnywhereOption()
and getAnywhereOption()
(see section below).
setRegistryValue(id = "a/b/c", value = 10)
existsRegistryValue(id = "a/b/c")
getRegistryValue(id = "a/b/c")
identical(getRegistryValue(id = "a/b/c"), container$.registry$a$b$c)
rmRegistryValue(id = "a/b/c")
existsRegistryValue(id = "a/b/c")
## Sub ID //
setRegistryValue(id = "a/b/c", value = 20, sub_id = "a")
getRegistryValue(id = "a/b/c", sub_id = "a")
The actual workhorse functions that are called by the convenvience function described above are setAnywhereOption()
and getAnywhereOption()
.
These let you set (retrieve) options (from) anywhere in an option container.
setAnywhereOption("directly/below/option/container", 1:3)
existsAnywhereOption("directly/below/option/container")
getAnywhereOption("directly/below/option/container")
ls(container, all.names = TRUE)
container$directly$below$option$container
rmAnywhereOption("directly/below/option/container")
existsAnywhereOption("directly/below/option/container")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.