diff --git a/DESCRIPTION b/DESCRIPTION index 4eb1b97..9b40af0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Encoding: UTF-8 Package: optparse Type: Package Title: Command Line Option Parser -Version: 1.6.6 +Version: 1.7.0-1 Authors@R: c(person("Trevor L", "Davis", role = c("aut", "cre"), email="trevor.l.davis@gmail.com"), person("Allen", "Day", role="ctb", comment="Some documentation and examples ported from the getopt package."), person("Python Software Foundation", role="ctb", comment="Some documentation from the optparse Python module."), @@ -26,9 +26,9 @@ Imports: methods, getopt (>= 1.20.2) Suggests: - covr, knitr (>= 1.15.19), stringr, testthat VignetteBuilder: knitr -RoxygenNote: 7.0.2 +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.1.1 diff --git a/NAMESPACE b/NAMESPACE index d7d760e..ff8c3bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,9 @@ # Generated by roxygen2: do not edit by hand +export(IndentedHelpFormatter) export(OptionParser) export(OptionParserOption) +export(TitledHelpFormatter) export(add_option) export(make_option) export(parse_args) diff --git a/NEWS.md b/NEWS.md index dcc691b..6d17d7d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,11 @@ +optparse 1.7.0 +============== + +* Add a ``formatter`` argument to ``OptionParser()`` for a function to format the usage message (#30). + By default uses the new function ``IndentedHelpFormatter()``. + `{optparse}` also provides the new function ``TitledHelpFormatter()``. + Thanks Ni Huang for suggestion. + optparse 1.6.6 ============== diff --git a/R/optparse.R b/R/optparse.R index ab0c9f3..32e1614 100644 --- a/R/optparse.R +++ b/R/optparse.R @@ -41,12 +41,16 @@ #' usage statement and options statement #' @slot epilogue Additional text for \code{print_help} to print out after #' the options statement +#' @slot formatter A function that \code{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 \code{\link{OptionParserOption}} #' @import methods #' @exportClass OptionParser setClass("OptionParser", representation(usage = "character", options = "list", - description = "character", epilogue = "character")) + description = "character", epilogue = "character", + formatter = "function")) #' Class to hold information about command-line options #' @@ -118,6 +122,10 @@ OptionParserOption <- setClass("OptionParserOption", representation(short_flag = #' usage statement and options statement #' @param epilogue Additional text for \code{print_help} to print out after #' the options statement +#' @param formatter A function that formats usage text. +#' The function should take only one argument (an `OptionParser()` object). +#' Default is [IndentedHelpFormatter()]. +#' The other builtin formatter provided by this package is [TitledHelpFormatter()]. #' @return An instance of the \code{OptionParser} class. #' @author Trevor Davis. #' @@ -129,7 +137,8 @@ OptionParserOption <- setClass("OptionParserOption", representation(short_flag = #' @export OptionParser <- function(usage = "usage: %prog [options]", option_list = list(), # nolint add_help_option = TRUE, prog = NULL, - description = "", epilogue = "") { + description = "", epilogue = "", + formatter = IndentedHelpFormatter) { if (is.null(prog)) { prog <- get_Rscript_filename() @@ -150,7 +159,8 @@ OptionParser <- function(usage = "usage: %prog [options]", option_list = list(), } return(new("OptionParser", usage = usage, options = option_list, - description = description, epilogue = epilogue)) + description = description, epilogue = epilogue, + formatter = formatter)) } #' Functions to enable our OptionParser to recognize specific command line @@ -326,6 +336,29 @@ add_option <- function(object, opt_str, action = NULL, type = NULL, #' is described here: \url{http://docs.python.org/library/optparse.html} #' @export print_help <- function(object) { + object@formatter(object) +} + +#' Builtin help text formatters +#' +#' `IndentedHelpFormatter()` is the default help text formatter. +#' `TitledHelpFormatter()` is an alternative help text formatter. +#' +#' @param object An [OptionParser()] object. +#' @examples +#' parser <- OptionParser(formatter = IndentedHelpFormatter) +#' parser <- add_option(parser, "--generator", help = "Generator option") +#' parser <- add_option(parser, "--count", help = "Count option") +#' print_help(parser) +#' +#' parser <- OptionParser(formatter = TitledHelpFormatter) +#' parser <- add_option(parser, "--generator", help = "Generator option") +#' parser <- add_option(parser, "--count", help = "Count option") +#' print_help(parser) +#' @return `NULL` invisibly. As a side effect prints out help text. +#' @rdname formatter +#' @export +IndentedHelpFormatter <- function(object) { cat(object@usage, fill = TRUE) cat(object@description, fill = TRUE) cat("\n") @@ -356,6 +389,39 @@ print_help <- function(object) { return(invisible(NULL)) } +#' @rdname formatter +#' @export +TitledHelpFormatter <- function(object) { + usage <- c("Usage\n=====\n", gsub("Usage: ", "", object@usage)) + cat(usage, fill = TRUE) + cat(object@description, fill = TRUE) + cat("\n") + cat("Options", "=======", sep = "\n") + + options_list <- object@options + for (ii in seq_along(options_list)) { + option <- options_list[[ii]] + if (!is.null(option@long_flag)) { + cat(option@long_flag) + if (.option_needs_argument(option)) { + cat("=", toupper(option@metavar), sep = "") + } + } + if (!is.na(option@short_flag)) { + cat(", ") + cat(option@short_flag) + if (.option_needs_argument(option)) { + cat(" ", toupper(option@metavar), sep = "") + } + } + cat("\n\t\t") + cat(sub("%default", .as_string(option@default), option@help)) + cat("\n\n") + } + cat(object@epilogue, fill = TRUE) + return(invisible(NULL)) +} + # Turn default values into a string we can cat, handles NA's and NULL's .as_string <- function(default) { if (is.null(default)) { diff --git a/README.Rrst b/README.Rrst index b92b962..51ad451 100644 --- a/README.Rrst +++ b/README.Rrst @@ -5,13 +5,9 @@ optparse: Command line optional argument parser :target: https://cran.r-project.org/package=optparse :alt: CRAN Status Badge -.. image:: https://travis-ci.org/trevorld/r-optparse.svg?branch=master - :target: https://travis-ci.org/trevorld/r-optparse - :alt: Travis-CI Build Status - -.. image:: https://ci.appveyor.com/api/projects/status/github/trevorld/r-optparse?branch=master&svg=true - :target: https://ci.appveyor.com/project/trevorld/r-optparse - :alt: AppVeyor Build Status +.. image:: https://github.com/trevorld/r-optparse/workflows/R-CMD-check/badge.svg + :target: https://github.com/trevorld/r-optparse/actions + :alt: R-CMD-check .. image:: https://img.shields.io/codecov/c/github/trevorld/r-optparse/master.svg :target: https://codecov.io/github/trevorld/r-optparse?branch=master @@ -21,7 +17,6 @@ optparse: Command line optional argument parser :target: https://cran.r-project.org/package=optparse :alt: RStudio CRAN mirror downloads - A pure R language command line parser inspired by Python's 'optparse' library to be used with Rscript to write "#!" shebang scripts that accept short and long flag/options. @@ -125,12 +120,12 @@ Note by default when ``optparse::parse_args`` sees a ``--help`` flag it will fir have richer positional argument support: .. {r positional_example} - parse_args(parser, args = c("-v", "-c25", "75", "22"), positional_arguments = TRUE) + parse_args(parser, args = c("-vc", "25", "75", "22"), positional_arguments = TRUE) .. .. The function ``parse_args2`` wraps ``parse_args`` while setting ``positional_arguments=TRUE`` and ``convert_hyphens_to_underscores=TRUE``: .. {r parse_args2} - parse_args2(parser, args = c("-v", "-c25", "75", "22")) + parse_args2(parser, args = c("-vc", "25", "75", "22")) .. .. diff --git a/README.rst b/README.rst index cb1bc16..4545e57 100644 --- a/README.rst +++ b/README.rst @@ -5,13 +5,9 @@ optparse: Command line optional argument parser :target: https://cran.r-project.org/package=optparse :alt: CRAN Status Badge -.. image:: https://travis-ci.org/trevorld/r-optparse.svg?branch=master - :target: https://travis-ci.org/trevorld/r-optparse - :alt: Travis-CI Build Status - -.. image:: https://ci.appveyor.com/api/projects/status/github/trevorld/r-optparse?branch=master&svg=true - :target: https://ci.appveyor.com/project/trevorld/r-optparse - :alt: AppVeyor Build Status +.. image:: https://github.com/trevorld/r-optparse/workflows/R-CMD-check/badge.svg + :target: https://github.com/trevorld/r-optparse/actions + :alt: R-CMD-check .. image:: https://img.shields.io/codecov/c/github/trevorld/r-optparse/master.svg :target: https://codecov.io/github/trevorld/r-optparse?branch=master @@ -21,7 +17,6 @@ optparse: Command line optional argument parser :target: https://cran.r-project.org/package=optparse :alt: RStudio CRAN mirror downloads - A pure R language command line parser inspired by Python's 'optparse' library to be used with Rscript to write "#!" shebang scripts that accept short and long flag/options. @@ -159,7 +154,7 @@ have richer positional argument support: .. sourcecode:: r - parse_args(parser, args = c("-v", "-c25", "75", "22"), positional_arguments = TRUE) + parse_args(parser, args = c("-vc", "25", "75", "22"), positional_arguments = TRUE) :: @@ -172,11 +167,11 @@ have richer positional argument support: ## [1] TRUE ## ## $options$count - ## [1] 5 + ## [1] 25 ## ## ## $args - ## [1] "-c25" "75" "22" + ## [1] "75" "22" @@ -186,7 +181,7 @@ The function ``parse_args2`` wraps ``parse_args`` while setting ``positional_arg .. sourcecode:: r - parse_args2(parser, args = c("-v", "-c25", "75", "22")) + parse_args2(parser, args = c("-vc", "25", "75", "22")) :: @@ -199,10 +194,10 @@ The function ``parse_args2`` wraps ``parse_args`` while setting ``positional_arg ## [1] TRUE ## ## $options$count - ## [1] 5 + ## [1] 25 ## ## ## $args - ## [1] "-c25" "75" "22" + ## [1] "75" "22" diff --git a/man/OptionParser-class.Rd b/man/OptionParser-class.Rd index fc1db44..e782101 100644 --- a/man/OptionParser-class.Rd +++ b/man/OptionParser-class.Rd @@ -25,6 +25,10 @@ usage statement and options statement} \item{\code{epilogue}}{Additional text for \code{print_help} to print out after the options statement} + +\item{\code{formatter}}{A function that \code{print_help} will use to print out after +the options statement. Default is \code{\link[=IndentedHelpFormatter]{IndentedHelpFormatter()}}. This +package also provides the builtin formatter \code{\link[=TitledHelpFormatter]{TitledHelpFormatter()}}.} }} \seealso{ diff --git a/man/OptionParser.Rd b/man/OptionParser.Rd index 447d875..95187d9 100644 --- a/man/OptionParser.Rd +++ b/man/OptionParser.Rd @@ -10,7 +10,8 @@ OptionParser( add_help_option = TRUE, prog = NULL, description = "", - epilogue = "" + epilogue = "", + formatter = IndentedHelpFormatter ) } \arguments{ @@ -37,6 +38,11 @@ usage statement and options statement} \item{epilogue}{Additional text for \code{print_help} to print out after the options statement} + +\item{formatter}{A function that formats usage text. +The function should take only one argument (an \code{OptionParser()} object). +Default is \code{\link[=IndentedHelpFormatter]{IndentedHelpFormatter()}}. +The other builtin formatter provided by this package is \code{\link[=TitledHelpFormatter]{TitledHelpFormatter()}}.} } \value{ An instance of the \code{OptionParser} class. @@ -48,11 +54,11 @@ methods is very useful for parsing options from the command line. } \references{ Python's \code{optparse} library, which inspired this package, - is described here: \url{http://docs.python.org/library/optparse.html} +is described here: \url{http://docs.python.org/library/optparse.html} } \seealso{ \code{\link{parse_args}} \code{\link{make_option}} - \code{\link{add_option}} +\code{\link{add_option}} } \author{ Trevor Davis. diff --git a/man/add_make_option.Rd b/man/add_make_option.Rd index 5d6cd52..5a7f283 100644 --- a/man/add_make_option.Rd +++ b/man/add_make_option.Rd @@ -41,9 +41,9 @@ comprised of the \dQuote{-} followed by a letter.} should take when it encounters an option, either \dQuote{store}, \dQuote{store_true}, \dQuote{store_false}, or \dQuote{callback}. An action of \dQuote{store} signifies that \code{optparse} - should store the specified following value if the option is found on the command string. +should store the specified following value if the option is found on the command string. \dQuote{store_true} stores \code{TRUE} if the option is found - and \dQuote{store_false} stores \code{FALSE} if the option is found. +and \dQuote{store_false} stores \code{FALSE} if the option is found. \dQuote{callback} stores the return value produced by the function specified in the \code{callback} argument. If \code{callback} is not \code{NULL} then the default is \dQuote{callback} else \dQuote{store}.} @@ -81,7 +81,7 @@ the parser S4 object, and \code{...}.} } \value{ Both \code{make_option} and \code{add_option} return instances of - class \code{OptionParserOption}. +class \code{OptionParserOption}. } \description{ \code{add_option} adds a option to a prexisting \code{OptionParser} instance @@ -115,7 +115,7 @@ new \code{OptionParser} instance. } \references{ Python's \code{optparse} library, which inspires this package, - is described here: \url{http://docs.python.org/library/optparse.html} +is described here: \url{http://docs.python.org/library/optparse.html} } \seealso{ \code{\link{parse_args}} \code{\link{OptionParser}} diff --git a/man/formatter.Rd b/man/formatter.Rd new file mode 100644 index 0000000..5822d18 --- /dev/null +++ b/man/formatter.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/optparse.R +\name{IndentedHelpFormatter} +\alias{IndentedHelpFormatter} +\alias{TitledHelpFormatter} +\title{Builtin help text formatters} +\usage{ +IndentedHelpFormatter(object) + +TitledHelpFormatter(object) +} +\arguments{ +\item{object}{An \code{\link[=OptionParser]{OptionParser()}} object.} +} +\value{ +\code{NULL} invisibly. As a side effect prints out help text. +} +\description{ +\code{IndentedHelpFormatter()} is the default help text formatter. +\code{TitledHelpFormatter()} is an alternative help text formatter. +} +\examples{ + parser <- OptionParser(formatter = IndentedHelpFormatter) + parser <- add_option(parser, "--generator", help = "Generator option") + parser <- add_option(parser, "--count", help = "Count option") + print_help(parser) + + parser <- OptionParser(formatter = TitledHelpFormatter) + parser <- add_option(parser, "--generator", help = "Generator option") + parser <- add_option(parser, "--count", help = "Count option") + print_help(parser) +} diff --git a/man/optparse-package.Rd b/man/optparse-package.Rd index d3da4ae..9b802a7 100644 --- a/man/optparse-package.Rd +++ b/man/optparse-package.Rd @@ -27,7 +27,7 @@ by either a trailing =, or may be the subsequent option. 5. A short flag is a type of flag, and begins with the string \dQuote{-}. If a short flag has an associated argument, it is the subsequent option. short flags may be bundled together, sharing a single leading \dQuote{"-"}, but only the final short -flag is able to have a corresponding argument. %%% +flag is able to have a corresponding argument. \%\%\% } \examples{ diff --git a/man/parse_args.Rd b/man/parse_args.Rd index 5714b1a..346af64 100644 --- a/man/parse_args.Rd +++ b/man/parse_args.Rd @@ -46,10 +46,10 @@ supported for backward compatibility reasons as it alters the format of the retu } \value{ Returns a list with field \code{options} containing our option values - as well as another field \code{args} which contains a vector of - positional arguments. For backward compatibility, if and only if - \code{positional_arguments} is \code{FALSE}, returns a list containing - option values. +as well as another field \code{args} which contains a vector of +positional arguments. For backward compatibility, if and only if +\code{positional_arguments} is \code{FALSE}, returns a list containing +option values. } \description{ \code{parse_args} parses command line options using an \code{OptionParser} @@ -59,13 +59,13 @@ to \code{TRUE}. } \section{Acknowledgement}{ - A big thanks to Steve Lianoglou for a bug report and patch; - Juan Carlos \enc{Borrás}{Borras} for a bug report; - Jim Nikelski for a bug report and patch; - Ino de Brujin and Benjamin Tyner for a bug report; - 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. +A big thanks to Steve Lianoglou for a bug report and patch; +Juan Carlos \enc{Borrás}{Borras} for a bug report; +Jim Nikelski for a bug report and patch; +Ino de Brujin and Benjamin Tyner for a bug report; +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. } \examples{ @@ -104,7 +104,7 @@ parse_args2(parser, args = c("--add-numbers", "example.txt")) } \references{ Python's \code{optparse} library, which inspired this package, - is described here: \url{http://docs.python.org/library/optparse.html} +is described here: \url{http://docs.python.org/library/optparse.html} } \seealso{ \code{\link{OptionParser}} \code{\link{print_help}} diff --git a/man/print_help.Rd b/man/print_help.Rd index 239a395..239626a 100644 --- a/man/print_help.Rd +++ b/man/print_help.Rd @@ -19,7 +19,7 @@ called by \code{parse_args} when it encounters a help option. } \references{ Python's \code{optparse} library, which inspired this package, - is described here: \url{http://docs.python.org/library/optparse.html} +is described here: \url{http://docs.python.org/library/optparse.html} } \seealso{ \code{{parse_args}} \code{{OptionParser}} diff --git a/tests/testthat/test-optparse.R b/tests/testthat/test-optparse.R index 8055eb1..b9da19a 100644 --- a/tests/testthat/test-optparse.R +++ b/tests/testthat/test-optparse.R @@ -119,7 +119,6 @@ test_that("parse_args works as expected", { expect_that(capture.output(parse_args(parser, args = c("--help"), positional_arguments = c(1, 2))), throws_error("help requested")) } - }) # Patch from Gyu Jin Choi. @@ -255,6 +254,10 @@ test_that("description and epilogue work as expected", { capture.output(print_help(OptionParser("usage: foo bar")))[1], "[Uu]sage"), 1) + parser <- OptionParser(formatter = TitledHelpFormatter) + parser <- add_option(parser, c("-f", "--foo"), help = "Foobar") + expect_output(print_help(parser), "Usage\n=====") + # bug found by Stefan Seemayer for NA default optlist <- list( make_option(c("--na"), type = "character", default = NA, help = "NA default is %default"),