Skip to content

Commit

Permalink
Merge pull request #75 from jmbarbone/73-dashes
Browse files Browse the repository at this point in the history
73 dashes
  • Loading branch information
jmbarbone committed Mar 9, 2024
2 parents b4db8db + e00146a commit fb2fb42
Show file tree
Hide file tree
Showing 17 changed files with 436 additions and 111 deletions.
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: scribe
Title: Command Argument Parsing
Version: 0.3.0.9000
Version: 0.3.0.9001
Authors@R:
person(
given = "Jordan Mark",
Expand All @@ -16,7 +16,7 @@ License: MIT + file LICENSE
Encoding: UTF-8
Language: en-US
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.0
Depends:
R (>= 3.6)
Imports:
Expand All @@ -33,3 +33,4 @@ Config/testthat/edition: 3
VignetteBuilder: knitr
URL: https://jmbarbone.github.io/scribe/, https://github.com/jmbarbone/scribe
BugReports: https://github.com/jmbarbone/scribe/issues
Config/testthat/parallel: true
15 changes: 14 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
# scribe (development version)

- improves `ca$help()` printing
- `---help`, `---version` _super_ arguments (`scribeSuperArg` objects) are now included with `scribeCommandArgs`.
This are objects that (by default) can be called within any `scribeCommandArgs` and intended to hold additional information about the `{scribe}` package.
These are not meant to be user accessible.
- `scribeCommandArgs` gain a new `field`, `supers`; a list of `scribeSuperArg` objects
- `command_args(super = included)` added
- internal `scribe_version_arg()` function (used with `command_args(include = "verison")` and called with `--version`) is now deprecated. Using `---version` now returns the version of `{scribe}`
- internal `scribe_help_super()` now available via `---help` and returns information about `{scribe}`
`ca$get_args(super = TRUE)` returns `scribeSuerArg`s
- `ca$help()` printing has been improved
- corrects issue with `ca$parse()`
- `ca$get_values(empty, super, included)` added to prevent filtering of specific argument types and values
- internal linting improvements
- `new_arg()` now throws a more helpful error when _value doesn't convert to itself_
- `arg$show()` now denotes if the argument is resolves by display an `"R"` before the value
- `arg$show()` now prints values of class `"scribe_empty_value"` as `<empty>`

# scribe 0.3.0

Expand Down
115 changes: 75 additions & 40 deletions R/arg.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,12 @@ scribe_help_arg <- function() {
ca$help()
return(exit())
}

if (isFALSE(self$get_value())) {
# remove 'help'
values <- ca$get_values()
ca$field("values", values[-match("help", names(values))])
}
}
)
}

scribe_version_arg <- function() {
# TODO deprecate for ---version
new_arg(
aliases = "--version",
action = "flag",
Expand All @@ -71,32 +66,28 @@ scribe_version_arg <- function() {
stop = "hard",
execute = function(self, ca) {
if (isTRUE(self$get_value())) {
.Deprecated("For {scribe} package version, use ---version instead")
ca$version()
return(exit())
}

if (isFALSE(self$get_value())) {
# remove 'version'
values <- ca$get_values()
ca$field("values", values[-match("version", names(values))])
}
}
)
}

# wrappers ----------------------------------------------------------------

arg_initialize <- function( # nolint: cyclocomp_linter.
self,
aliases = "",
action = arg_actions(),
default = NULL,
convert = scribe_convert(),
n = NA_integer_,
info = NA_character_,
options = list(),
stop = c("none", "hard", "soft"),
execute = invisible
# nolint next: cyclocomp_linter.
arg_initialize <- function(
self,
aliases = "",
action = arg_actions(),
default = NULL,
convert = scribe_convert(),
n = NA_integer_,
info = NA_character_,
options = list(),
stop = c("none", "hard", "soft"),
execute = invisible
) {
action <- match.arg(action, arg_actions())
info <- info %||% NA_character_
Expand Down Expand Up @@ -181,9 +172,21 @@ arg_initialize <- function( # nolint: cyclocomp_linter.
}
)

if (!is.null(default)) {
if (!identical(value_convert(default, to = convert), default)) {
stop("default value doesn't convert to itself", call. = FALSE)
if (!is.null(default) && !is.null(convert)) {
attempt <- value_convert(default, to = convert)
if (!identical(attempt, default)) {
stop(
"default value doesn't convert to itself:\n",
"default:\n",
utils::capture.output(utils::str(default)),
"\nconverted:\n",
utils::capture.output(utils::str(attempt)),
"\n\n",
"to disable this check, use",
" `new_arg(convert = scribe_convert(\"none\"))`",
" or review the `convert` argument in `?scribe_arg`",
call. = FALSE
)
}
}

Expand Down Expand Up @@ -213,9 +216,17 @@ arg_initialize <- function( # nolint: cyclocomp_linter.
positional <- !dash_args

if (action == "flag" && isTRUE(options$no)) {
dash2 <- grep("^--", aliases)
if (dash2 && length(dash2)) {
aliases <- c(aliases, paste0("--no-", sub("^--", "", aliases[dash2])))
dashes <- n_dashes(aliases)
ok <- dashes >= 2L
if (any(ok)) {
aliases <- c(
aliases,
paste0(
strrep("-", dashes[ok]),
"no-",
sub("^-{2,3}", "", aliases[ok])
)
)
} else if (positional) {
aliases <- c(aliases, paste0("no-", aliases))
}
Expand Down Expand Up @@ -251,18 +262,30 @@ arg_initialize <- function( # nolint: cyclocomp_linter.
}

arg_show <- function(self) {
value <- self$get_default()
value <-
if (self$is_resolved()) {
self$get_value()
} else {
self$get_default()
}

value <-
if (is.null(value)) {
"<null>"
} else if (inherits(value, "scribe_empty_value")) {
"<empty>"
} else {
paste(vapply(value, format, NA_character_), collapse = " ")
}

aliases <- self$get_aliases()
aliases <- to_string(aliases)

print_line(sprintf("Argument [%s] : %s", aliases, value))
print_line(sprintf(
"Argument [%s] %s: %s",
aliases,
if (self$is_resolved()) "R " else "",
value
))
invisible(self)
}

Expand Down Expand Up @@ -340,7 +363,12 @@ arg_get_name <- function(self, clean = TRUE) {
nm <- aliases[n]

if (clean) {
nm <- sub("^--?", "", nm)
nm <-
if (startsWith(nm, "---")) {
paste0("_", substr(nm, 4L, nchar(nm)))
} else {
sub("^-{1,2}", "", nm)
}
}

nm
Expand Down Expand Up @@ -372,12 +400,13 @@ arg_is_resolved <- function(self) {

# internal ----------------------------------------------------------------

arg_parse_value <- function(self, ca) { # nolint: cyclocomp_linter.
# nolint next: cyclocomp_linter.
arg_parse_value <- function(self, ca) {
default <-
if (is_arg(self$default)) {
self$default$get_value()
} else {
self$default
self$get_default()
}

if (ca$stop == "soft") {
Expand Down Expand Up @@ -442,18 +471,18 @@ arg_parse_value <- function(self, ca) { # nolint: cyclocomp_linter.
},
list = {
m <- m + seq.int(0L, self$n)
value <- ca_get_working(ca)[m[-off]]
value <- ca_get_working(ca, m[-off])

if (self$positional && is.na(value)) {
if (self$positional && !isFALSE(is.na(value))) {
default <- TRUE
value <- self$get_default()
}

ca_remove_working(ca, m)
},
flag = {
value <- !grepl("^--?no-", ca_get_working(ca)[m + off])
ca_remove_working(ca, m)
value <- !grepl("^-{2,3}no-", ca_get_working(ca, m + off))
ca_remove_working(ca, m + off)
}
)

Expand All @@ -479,7 +508,7 @@ is_arg <- function(x) {
methods::is(x, "scribeArg")
}

ARG_PAT <- "^-[a-z]$|^--[a-z]+$|^--[a-z](+[-]?[a-z]+)+$" # nolint: object_name_linter, line_length_linter.
ARG_PAT <- "^-[a-z]$|^---?[a-z]+$|^--?[a-z](+[-]?[a-z]+)+$" # nolint: object_name_linter, line_length_linter.

arg_actions <- function() {
c("default", "list", "flag", "dots")
Expand All @@ -488,3 +517,9 @@ arg_actions <- function() {
scribe_empty_value <- function() {
structure(list(), class = c("scribe_empty_value"))
}

n_dashes <- function(x) {
n <- attr(regexpr("^-+", x), "match.length")
n[n == -1] <- 0L
n
}
23 changes: 22 additions & 1 deletion R/class-args.R
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
#' new_arg("...", info = "list of values") # defaults when alias is "..."
#' @family scribe
#' @export
scribeArg <- methods::setRefClass( # nolint: object_name_linter.
# nolint next: object_name_linter.
scribeArg <- methods::setRefClass(
"scribeArg",
fields = list(
aliases = "character",
Expand Down Expand Up @@ -171,3 +172,23 @@ scribeArg$methods(
arg_is_resolved(.self)
}
)

# nolint next: object_name_linter.
scribeSuperArg <- methods::setRefClass("scribeSuperArg", contains = "scribeArg")

scribeSuperArg$methods(
initialize = function(
aliases = "",
...
) {
if (!all(startsWith(aliases, "---"))) {
stop("super args aliases must start with ---")
}

arg_initialize(
self = .self,
aliases = aliases,
...
)
}
)
Loading

0 comments on commit fb2fb42

Please sign in to comment.