Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Encoding: UTF-8
Package: optparse
Type: Package
Title: Command Line Option Parser
Version: 1.8.0-4
Version: 1.8.0-5
Authors@R: c(person("Trevor L.", "Davis", role=c("aut", "cre"),
email="trevor.l.davis@gmail.com",
comment = c(ORCID = "0000-0001-6341-4639")),
Expand Down
8 changes: 5 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ optparse 1.8.0 (development)
New features
------------

* `make_option()` (and `add_option()`) now support the following new actions (#22):
* `add_option()` (and `make_option()`) now support the following new actions (#22):

+ `action = "append"` which appends each occurrence's value to `default`.
+ `action = "append_const"` which appends `const` to `default` each time the flag is seen.
+ `action = "count"`, which counts the number of times a flag is seen and adds it to `default` (treated as `0L` if not supplied). Returns `NULL` if the flag is never seen and no `default` was supplied.
+ `action = "store_const"` which stores `const` when the flag is seen.

* `make_option()` (and `add_option()`) now support a `const` parameter (intended for new actions `"append_const"` and `"store_const"`).
* `add_option()` (and `make_option()`) now support a `const` parameter (intended for new actions `"append_const"` and `"store_const"`).

* `make_option()` (and `add_option()`) now support a `required` argument.
* `add_option()` (and `make_option()`) now allow non-letter characters in short flags (e.g., `-1`) and at the beginning of long flags (e.g., `--1flag`), following Python's `optparse` convention. However long and short flags may not contain `=` or whitespace (or begin with hyphens).

* `add_option()` (and `make_option()`) now support a `required` argument.
If `TRUE`, `parse_args()` will throw an error if the option is not provided on the command line (#17).

Bug fixes and minor improvements
Expand Down
39 changes: 25 additions & 14 deletions R/optparse.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#' @slot formatter A function that [print_help()] will use to print out after
#' the options statement. Default is [IndentedHelpFormatter()]. This
#' package also provides the builtin formatter [TitledHelpFormatter()].
#' @author Trevor Davis.
#' @seealso [OptionParserOption]
#' @import methods
#' @exportClass OptionParser
Expand Down Expand Up @@ -97,9 +96,9 @@ setMethod("options<-", "OptionParser", function(x, value) {
#' Class to hold information about command-line options
#'
#' @slot short_flag String of the desired short flag
#' comprised of the \dQuote{-} followed by a letter.
#' @slot long_flag String of the desired long flag comprised of \dQuote{--}
#' followed by a letter and then a sequence of alphanumeric characters.
#' comprised of the `-` followed by a single non-dash character (but not `=` or a whitespace character).
#' @slot long_flag String of the desired long flag comprised of `--`
#' followed by a non-dash character and then (optionally) more characters (but not any `=` or whitespace characters).
#' @slot action `r ro_action`
#' @slot type `r ro_type`
#' @slot dest `r ro_dest`
Expand Down Expand Up @@ -160,7 +159,6 @@ OptionParserOption <- setClass(
#' Default is [IndentedHelpFormatter()].
#' The other builtin formatter provided by this package is [TitledHelpFormatter()].
#' @return An instance of the `OptionParser` class.
#' @author Trevor Davis.
#'
#' @seealso [parse_args()] [make_option()] [add_option()]
#' @references Python's `optparse` library, which inspired this package,
Expand Down Expand Up @@ -219,9 +217,9 @@ OptionParser <- function(
#' @rdname add_make_option
#' @param object An instance of the `OptionParser` class
#' @param opt_str A character vector containing the string of the desired long
#' flag comprised of \dQuote{--} followed by a letter and then a sequence of
#' alphanumeric characters and optionally a string of the desired short flag
#' comprised of the \dQuote{-} followed by a letter.
#' flag comprised of `--` followed by a non-dash character (and optionally more characters), and
#' optionally a string of the desired short flag comprised of the
#' `-` followed by a single non-dash character. We don't allow `=` or whitespace characters in flags.
#' @param action `r ro_action`
#' @param type `r ro_type`
#' @param dest `r ro_dest`
Expand All @@ -234,7 +232,6 @@ OptionParser <- function(
#' @param callback_args `r ro_callback_args`
#' @return Both [make_option()] and [add_option()] return instances of
#' class `OptionParserOption`.
#' @author Trevor Davis.
#'
#' @seealso [parse_args()] [OptionParser()]
#' @references Python's `optparse` library, which inspires this package,
Expand Down Expand Up @@ -278,18 +275,34 @@ make_option <- function(
action <- ifelse(is.null(action), ifelse(is.null(callback), "store", "callback"), action)

# flags
short_flag <- opt_str[grepl("^-[[:alpha:]]", opt_str)]
short_flag <- opt_str[grepl("^-[^-]", opt_str)]
if (length(short_flag) == 0) {
short_flag <- NA_character_
} else {
if (nchar(short_flag) > 2) {
stop(paste("Short flag", short_flag, "must only be a '-' and a single letter"))
stop(paste(
"Short flag",
short_flag,
"must only be a '-' and a single non-dash character"
))
}
if (grepl("[[:space:]]", short_flag)) {
stop(paste("Short flag", short_flag, "must not contain whitespace"))
}
if (grepl("=", short_flag, fixed = TRUE)) {
stop(paste("Short flag", short_flag, "must not contain '='"))
}
}
long_flag <- opt_str[grepl("^--[[:alpha:]]", opt_str)]
long_flag <- opt_str[grepl("^--[^-]", opt_str)]
if (length(long_flag) == 0) {
stop("We require a long flag option")
}
if (grepl("=", long_flag, fixed = TRUE)) {
stop(paste("Long flag", long_flag, "must not contain '='"))
}
if (grepl("[[:space:]]", long_flag)) {
stop(paste("Long flag", long_flag, "must not contain whitespace"))
}

# type
if (is.null(type)) {
Expand Down Expand Up @@ -414,7 +427,6 @@ add_option <- function(
#' @param object A `OptionParser` instance.
#' @return [print_help()] uses the `cat` function to print out a usage
#' message. It returns `invisible(NULL)`.
#' @author Trevor Davis.
#'
#' @seealso [parse_args()] [OptionParser()]
#' @references Python's `optparse` library, which inspired this package,
Expand Down Expand Up @@ -560,7 +572,6 @@ as_string <- function(default) {
#' Jonas Zimmermann for bug report; Miroslav Posta for bug reports;
#' Stefan Seemayer for bug report and patch;
#' Kirill \enc{Müller}{Muller} for patches; Steve Humburg for patch.
#' @author Trevor Davis.
#'
#' @seealso [OptionParser()] [print_help()]
#' @references Python's `optparse` library, which inspired this package,
Expand Down
3 changes: 0 additions & 3 deletions man/OptionParser-class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions man/OptionParser.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions man/OptionParserOption-class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions man/add_make_option.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions man/parse_args.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions man/print_help.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions tests/testthat/_snaps/optparse.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@
Error in `make_option()`:
! We require a long flag option

---

Code
make_option("- ")
Condition
Error in `make_option()`:
! Short flag - must not contain whitespace

---

Code
make_option("-=")
Condition
Error in `make_option()`:
! Short flag -= must not contain '='

---

Code
make_option("--fo=o")
Condition
Error in `make_option()`:
! Long flag --fo=o must not contain '='

---

Code
make_option("--fo o")
Condition
Error in `make_option()`:
! Long flag --fo o must not contain whitespace

# `required` argument works as expected

Code
Expand Down
7 changes: 7 additions & 0 deletions tests/testthat/test-optparse.R
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ test_that("`make_option()` works as expected", {
expect_equal(make_option("--filename")@type, "character")
expect_snapshot(error = TRUE, make_option("badflag"))
expect_error(make_option("-cd"), "must only be")
expect_equal(make_option(c("-1", "--one"))@short_flag, "-1")
expect_equal(make_option("--1flag")@long_flag, "--1flag")
expect_equal(make_option("--add-numbers")@long_flag, "--add-numbers")
expect_snapshot(error = TRUE, make_option("- "))
expect_snapshot(error = TRUE, make_option("-="))
expect_snapshot(error = TRUE, make_option("--fo=o"))
expect_snapshot(error = TRUE, make_option("--fo o"))
})

get_long_flags <- function(parser) {
Expand Down
Loading