The purpose of cmdfun
is to significantly reduce the overhead involved in
wrapping shell programs in R. The tools are intended to be intuitive and
lightweight enough to use for data scientists trying to get things done quickly,
but robust and full-fledged enough for developers to extend them to more
advanced use cases.
Install the development version of cmdfun
with:
if (!requireNamespace("remotes")) install.packages("remotes") remotes::install_github("snystrom/cmdfun")
The cmdfun
framework provides mechanisms for capturing function arguments:
cmd_args_dots()
captures all arguments passed to ...
cmd_args_named()
captures all keyword arguments defined by the usercmd_args_all()
captures both named + dot argumentslibrary(cmdfun) myFunction <- function(input, ...){ cmd_args_all() } (argsList <- myFunction(input = "test", boolean_flag = TRUE))
cmd_list_interp
converts the captured argument list to a parsed list of
flag/value pairs.
(flagsList <- cmd_list_interp(argsList))
cmd_list_to_flags
converts a list to a vector of
commandline-style flags using the list names as flag names and the list values
as the flag values (empty values return only the flag). This output can be
directly fed to system2
or processx
.
cmd_list_to_flags(flagsList)
cmd_path_search()
allows package builders to search default locations for installed tools.
bin_path <- cmd_path_search(default_path = "/bin", utils = c("ls", "cut")) bin_path(util = "ls")
cmdfun
attempts to solve the problem of wrapping external software in R.
Calling external software is done with system2
or processx
.
For example, calling ls -l *.md
using system2
.
system2("ls", "-l *.md", stdout = TRUE)
However, when using multiple commandline flags each flag should be passed as a member of a character vector as follows:
When calling ls -l -i
system2("ls", c("-l", "-i", "*.md"), stdout = TRUE)
This becomes even more difficult if trying to support user input, as a significant amount of overhead is required to parse user inputs and optional flags into these vectors.
cmdfun
provides utilities for converting function arguments into lists
which can easily convert to character vectors suitable for use with
system2
or processx
.
library(cmdfun) myFunction <- function(input, option1){ # Grabs named arguments as key/value pairs cmd_args_named() } (argsList <- myFunction("myInput.txt", "foo"))
# Converts list to character vector of flags & values cmd_list_to_flags(argsList)
ls
with cmdfunThese tools can be used to easily wrap ls
library(magrittr) shell_ls <- function(dir = ".", ...){ # grab arguments passed to "..." in a list flags <- cmd_args_dots() %>% # prepare list for conversion to vector cmd_list_interp() %>% # Convert the list to a flag vector cmd_list_to_flags() # Run ls shell command system2("ls", c(flags, dir), stdout = TRUE) }
shell_ls("*.md")
ls -l
can be mimicked by passing l = TRUE
to '...'.
shell_ls("*.md", l = TRUE)
Commandline tools can have hundreds of arguments, many with uninformative, often
single-letter, names. To prevent developers from having to write aliased
function arguments for all, often conflicting flags, cmd_list_interp
can
additionally use a lookup table to allow developers to provide informative
function argument names for unintuitive flags.
For example, allowing long
to act as -l
in ls
.
shell_ls_alias <- function(dir = ".", ...){ # Named vector acts as lookup table # name = function argument # value = flag name names_arg_to_flag <- c("long" = "l") flags <- cmd_args_dots() %>% # Use lookup table to manage renames cmd_list_interp(names_arg_to_flag) %>% cmd_list_to_flags() system2("ls", c(flags, dir), stdout = TRUE) }
shell_ls_alias("*.md", long = TRUE)
cut
with cmdfunHere is another example wrapping cut
which separates text on a delimiter (set
with -d
) and returns selected fields (set with -f
) from the separation.
shell_cut <- function(text, ...){ names_arg_to_flag <- c("sep" = "d", "fields" = "f") flags <- cmd_args_dots() %>% cmd_list_interp(names_arg_to_flag) %>% cmd_list_to_flags() system2("cut", flags, stdout = T, input = text) }
shell_cut("hello_world", fields = 2, sep = "_")
shell_cut("hello_world_hello", fields = c(1,3), sep = "_")
Additionally, cmdfun
provides utilites for searching & checking valid tool
installs, expecting system behavior, and helpful error handling to allow simple
construction of external tool wrappers (see
vignette for details).
See https://snystrom.github.io/cmdfun/articles/cmdfun.html
for the most recent documentation and to learn about all cmdfun
features.
To file bug reports, please visit https://github.com/snystrom/cmdfun/issues while providing a reproducible example of your issue.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.