optparse/0000755000176200001440000000000015170356312012112 5ustar liggesusersoptparse/tests/0000755000176200001440000000000014265323021013247 5ustar liggesusersoptparse/tests/test_help.R0000644000176200001440000000011313567265621015373 0ustar liggesuserslibrary("optparse") parser <- OptionParser() parse_args(parser, "--help") optparse/tests/run-all.R0000644000176200001440000000005412536077777014772 0ustar liggesuserslibrary("testthat") test_check("optparse") optparse/tests/testthat/0000755000176200001440000000000015161657135015123 5ustar liggesusersoptparse/tests/testthat/test-optparse.R0000644000176200001440000005701615161657135020071 0ustar liggesusers# Copyright 2010-2019 Trevor L Davis # Copyright 2013 Kirill Müller # Copyright 2008 Allen Day # # This file is free software: you may copy, redistribute and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the License, or (at your # option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . option_list <- list( make_option( c("-v", "--verbose"), action = "store_true", default = TRUE, help = "Print extra output [default]" ), make_option( c("-q", "--quietly"), action = "store_false", dest = "verbose", help = "Print little output" ), make_option( c("-c", "--count"), type = "integer", default = 5, help = "Number of random normals to generate [default \\%default]", metavar = "number" ), make_option( "--generator", default = "rnorm", help = "Function to generate random deviates [default \"\\%default\"]" ), make_option( "--mean", default = 0, help = "Mean if generator == \"rnorm\" [default \\%default]" ), make_option( "--sd", default = 1, metavar = "standard deviation", help = "Standard deviation if generator == \"rnorm\" [default \\%default]" ) ) parser_ol <- OptionParser(option_list = option_list) test_that("`make_option()` works as expected", { expect_equal( make_option("--integer", type = "integer", default = 5), make_option("--integer", default = as.integer(5)) ) expect_equal( make_option("--logical", type = "logical", default = "TRUE"), make_option("--logical", default = TRUE) ) expect_equal(make_option("--filename")@type, "character") expect_snapshot(error = TRUE, make_option("badflag")) expect_snapshot(error = TRUE, make_option(c("-cd", "--foo"))) expect_error(make_option("badflag"), class = "optparse_option_error") expect_error(make_option(c("-cd", "--foo")), class = "optparse_option_error") 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(c("- ", "--foo"))) expect_snapshot(error = TRUE, make_option(c("-=", "--foo"))) expect_snapshot(error = TRUE, make_option("--fo=o")) expect_snapshot(error = TRUE, make_option("--fo o")) expect_snapshot(error = TRUE, make_option("--foo", action = "storr")) expect_error(make_option("--foo", action = "storr"), class = "optparse_option_error") expect_snapshot(error = TRUE, make_option("--foo", type = "int")) expect_error(make_option("--foo", type = "int"), class = "optparse_option_error") }) get_long_flags <- function(parser) { sort(sapply(parser@options, function(x) x@long_flag)) } test_that("`add_option()` works as expected", { parser1 <- OptionParser(option_list = list(make_option("--generator"), make_option("--count"))) parser2 <- OptionParser() parser2 <- add_option(parser2, "--generator") parser2 <- add_option(parser2, "--count") expect_equal(get_long_flags(parser1), get_long_flags(parser2)) }) test_that("`required` argument works as expected", { parser <- OptionParser() parser <- add_option(parser, "--foo", required = TRUE) expect_snapshot(error = TRUE, parse_args(parser, args = character(0))) expect_error(parse_args(parser, args = character(0)), class = "optparse_missing_required_error") expect_equal( parse_args(parser, args = "--foo=bar")[["foo"]], "bar" ) parser2 <- OptionParser() parser2 <- add_option(parser2, "--foo", required = TRUE) parser2 <- add_option(parser2, "--bar", required = TRUE) expect_snapshot(error = TRUE, parse_args(parser2, args = character(0))) }) test_that("`parse_args()` works as expected", { # option_list took outside test_that option_list2 <- list( make_option( c("-n", "--add-numbers"), action = "store_true", default = FALSE, help = "Print line number at the beginning of each line [default]" ) ) parser <- OptionParser(usage = "\\%prog [options] file", option_list = option_list2) expect_equal( sort_list(parse_args(parser_ol, args = c("--sd=3", "--quietly"))), sort_list(list( sd = 3, verbose = FALSE, help = FALSE, count = 5, mean = 0, generator = "rnorm" )) ) expect_equal( sort_list(parse_args(parser_ol, args = character(0), positional_arguments = TRUE)), sort_list(list( options = list( sd = 1, help = FALSE, verbose = TRUE, count = 5, mean = 0, generator = "rnorm" ), args = character(0) )) ) expect_equal( sort_list(parse_args(parser_ol, args = c("-c", "10"))), sort_list(list( sd = 1, help = FALSE, verbose = TRUE, count = 10, mean = 0, generator = "rnorm" )) ) expect_equal( sort_list(parse_args( parser, args = c("--add-numbers", "example.txt"), positional_arguments = TRUE )), sort_list(list(options = list(`add-numbers` = TRUE, help = FALSE), args = c("example.txt"))) ) expect_equal( sort_list(parse_args(parser, args = c("--add-numbers"), positional_arguments = TRUE)), sort_list(list(options = list(`add-numbers` = TRUE, help = FALSE), args = character(0))) ) expect_equal( sort_list(parse_args( parser, args = c("--add-numbers"), positional_arguments = TRUE, convert_hyphens_to_underscores = TRUE )), sort_list(list(options = list(add_numbers = TRUE, help = FALSE), args = character(0))) ) expect_equal( sort_list(parse_args2(parser, args = c("--add-numbers"))), sort_list(list(options = list(add_numbers = TRUE, help = FALSE), args = character(0))) ) expect_snapshot( error = TRUE, parse_args(parser, args = c("-add-numbers", "example.txt"), positional_arguments = FALSE) ) expect_error( parse_args(parser, args = c("-add-numbers", "example.txt"), positional_arguments = FALSE), class = "optparse_bad_option_error" ) expect_error(parse_args( parser, args = c("-add-numbers", "example.txt"), positional_arguments = TRUE )) expect_equal( sort_list(parse_args( parser, args = c("--add-numbers", "example.txt"), positional_arguments = c(1, 3) )), sort_list(list(options = list(`add-numbers` = TRUE, help = FALSE), args = c("example.txt"))) ) expect_equal( sort_list(parse_args(parser, args = c("example.txt"), positional_arguments = 1)), sort_list(list( options = list(`add-numbers` = FALSE, help = FALSE), args = c("example.txt") )) ) expect_snapshot( error = TRUE, parse_args(parser, args = c("-add-numbers", "example.txt"), positional_arguments = c(0, 1)) ) expect_snapshot( error = TRUE, parse_args(parser, args = c("example.txt"), positional_arguments = c(2, Inf)) ) expect_error( parse_args(parser, args = c("example.txt"), positional_arguments = c(2, Inf)), class = "optparse_bad_positional_arguments_error" ) expect_snapshot( error = TRUE, parse_args(parser, args = c("example.txt"), positional_arguments = 2) ) expect_error( parse_args(parser, args = c("example.txt"), positional_arguments = 2), class = "optparse_bad_positional_arguments_error" ) expect_snapshot( error = TRUE, parse_args(parser, args = c("example.txt"), positional_arguments = "any") ) expect_snapshot( error = TRUE, parse_args(parser, args = c("example.txt"), positional_arguments = 1:3) ) }) test_that("--help raises an error in interactive mode", { parser <- OptionParser( usage = "%prog [options] file", option_list = list( make_option(c("-n", "--add-numbers"), action = "store_true", default = FALSE) ) ) local_mocked_bindings(is_interactive = function() TRUE) capture.output(expect_error(parse_args(parser, args = c("--help")), "help requested")) capture.output(expect_error( parse_args(parser, args = c("--help"), positional_arguments = c(1, 2)), "help requested" )) }) test_that("parse errors raise classed errors in interactive and non-interactive mode", { parser <- OptionParser() local_mocked_bindings(is_interactive = function() TRUE) expect_error( parse_args(parser, c("file.txt")), class = "optparse_bad_option_error" ) local_mocked_bindings(is_interactive = function() FALSE) capture.output( expect_error(parse_args(parser, c("file.txt")), class = "optparse_bad_option_error"), type = "message" ) }) test_that("bare -- separator treats everything after it as positional arguments", { parser <- OptionParser() parser <- add_option(parser, c("-v", "--verbose"), action = "store_true") expect_equal( sort_list(parse_args( parser, c("--verbose", "--", "--not-a-flag", "-x"), positional_arguments = TRUE )), sort_list(list( options = list(verbose = TRUE, help = FALSE), args = c("--not-a-flag", "-x") )) ) expect_equal( sort_list(parse_args(parser, c("--", "--verbose"), positional_arguments = TRUE)), sort_list(list(options = list(help = FALSE), args = c("--verbose"))) ) expect_equal( sort_list(parse_args(parser, c("--", "-v"), positional_arguments = TRUE)), sort_list(list(options = list(help = FALSE), args = c("-v"))) ) }) test_that("positional argument with positional_arguments = FALSE raises an error", { parser <- OptionParser() parser <- add_option(parser, c("-v", "--verbose"), action = "store_true") expect_snapshot(error = TRUE, parse_args(parser, c("file.txt"))) expect_snapshot(error = TRUE, parse_args(parser, c("--verbose", "file.txt"))) }) # Patch from Gyu Jin Choi. test_that("callback works as expected", { power <- function(x, n = 2) x^n callback_fn <- function(option, flag, option_value, parser, n = 2) { power(option_value, n) } parser0 <- OptionParser() parser1 <- add_option( parser0, c("-s", "--squared_distance"), type = "integer", action = "callback", help = "Squared distance between two points", callback = callback_fn, callback_args = list(2) ) opts <- parse_args(parser1, args = c("--squared_distance=16")) expect_equal(opts$squared_distance, 256) # Bug found by Ni Huang (#28) opts <- parse_args(parser1, positional_argument = TRUE, args = c("-s", "3")) expect_equal(opts$options$squared_distance, 9) # Bug found by Ni Huang (#29) expect_output(print_help(parser1), "SQUARED_DISTANCE") parser2 <- add_option( parser0, c("-v", "--value"), type = "integer", action = "callback", callback = callback_fn, callback_args = list(n = 3) ) opts <- parse_args(parser2, args = c("--value=2")) expect_equal(opts$value, 8) parser3 <- add_option( parser0, c("-v", "--value"), type = "integer", action = "callback", callback = callback_fn ) opts <- parse_args(parser3, args = c("--value=2")) expect_equal(opts$value, 4) expect_warning( add_option(parser0, "--warning", action = "store", callback = as.list), "callback argument is supplied for non-callback action" ) expect_warning( add_option(parser0, "--warning", callback_args = list(3, b = 4)), "callback_args argument is supplied for non-callback action" ) expect_warning( add_option(parser0, "--warning", action = "callback", type = "numeric", callback = "hello"), "callback argument is not a function" ) callback_fn <- function(option, flag, option_value, parser) { 42 } parser4 <- add_option(parser0, "--null_type", type = NULL, callback = callback_fn) opts <- parse_args(parser4, args = c("--null_type")) expect_equal(opts$null_type, 42) }) # Bug found by Miroslav Posta test_that("test using numeric instead of double", { option_list_neg <- list(make_option(c("-m", "--mean"), default = 0, type = "numeric")) parser <- OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg) opts <- parse_args(parser, args = c("-m", "-5.0")) expect_equal(opts$mean, -5.0) }) # Bug found by Juan Carlos Borrás test_that("test bug of multiple '=' signs", { optlist <- list( make_option( c("-s", "--substitutions"), type = "character", dest = "substitutions", default = NULL, help = 'String of the form "KEY1=VALUE1 KEY2=VALUE2 ... KEY=VALUE" stating the SQL template substitutions', metavar = "substitution-list" ) ) optparser <- OptionParser(option_list = optlist) opt <- parse_args(optparser, c("-s", "FOO=bar")) opt_alt <- parse_args(optparser, c("--substitutions=FOO=bar")) expect_equal(opt, opt_alt) # also check when positional_arguments is set to true, like later bug unit test opt <- parse_args(optparser, c("-s", "FOO=bar"), positional_arguments = TRUE) opt_alt <- parse_args(optparser, c("--substitutions=FOO=bar"), positional_arguments = TRUE) expect_equal(opt, opt_alt) }) # Bug found by Jim Nikelski test_that("test bug when multiple short flag options '-abc' with positional_arguments = TRUE", { sort_list <- function(unsorted_list) { for (ii in seq_along(unsorted_list)) { if (is.list(unsorted_list[[ii]])) { unsorted_list[[ii]] <- sort_list(unsorted_list[[ii]]) } } unsorted_list[sort(names(unsorted_list))] } expect_equal( sort_list(parse_args(parser_ol, args = c("-qc", "10"), positional_arguments = TRUE)), sort_list(list( options = list( sd = 1, help = FALSE, verbose = FALSE, count = 10, mean = 0, generator = "rnorm" ), args = character(0) )) ) expect_error(parse_args(parser_ol, args = c("-qcde", "10"), positional_arguments = TRUE)) expect_error(parse_args( parser_ol, args = c("a", "b", "c", "d", "e"), positional_arguments = c(1, 3) )) expect_equal( sort_list(parse_args( parser_ol, args = c("CMD", "-qc", "10", "bumblebee"), positional_arguments = TRUE )), sort_list(list( options = list( sd = 1, help = FALSE, verbose = FALSE, count = 10, mean = 0, generator = "rnorm" ), args = c("CMD", "bumblebee") )) ) args <- c("CMD", "-qc", "10", "bumblebee", "--qcdefg") expect_error( parse_args(parser_ol, args = args, positional_arguments = TRUE), 'long flag "qcdefg" is invalid' ) args <- c("-qxc", "10", "bumblebee") expect_error( parse_args(parser_ol, args = args, positional_arguments = TRUE), 'short flag "x" is invalid' ) }) # Bug found by Ino de Brujin and Benjamin Tyner test_that("test bug when long flag option with '=' with positional_arguments = TRUE", { expect_equal( sort_list(parse_args(parser_ol, args = c("--count=10"), positional_arguments = TRUE)), sort_list(list( options = list( sd = 1, help = FALSE, verbose = TRUE, count = 10, mean = 0, generator = "rnorm" ), args = character(0) )) ) }) # Bug found by Miroslav Posta optlist <- list(make_option(c("--tmin"), type = "numeric", help = "Startup time [sec]. ")) parser <- OptionParser(option_list = optlist, usage = "", epilogue = "") test_that("test bug with a NA short flag option with positional_arguments = TRUE", { expect_equal( sort_list(parse_args( args = c("-h", "foo"), parser, positional_arguments = TRUE, print_help_and_exit = FALSE )), sort_list(list(options = list(help = TRUE), args = "foo")) ) }) test_that("description and epilogue work as expected", { parser <- OptionParser() expect_output(print_help(parser), "Usage:") expect_output(print_help(parser), "Options:") parser2 <- OptionParser(usage = "program", description = "foo", epilogue = "bar") expect_output(print_help(parser2), "foo") expect_output(print_help(parser2), "bar$") expect_output(print_help(parser2), "^Usage: ") expect_equal( stringr::str_count( 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"), make_option( c("--null"), type = "character", default = NULL, help = "NULL default is %default" ), make_option( c("--str"), type = "character", default = "str", help = "str default is %default" ), make_option( c("--bool"), type = "logical", default = TRUE, help = "bool default is %default" ), make_option(c("--int"), type = "integer", default = 42, help = "int default is %default"), make_option( c("--dbl"), type = "double", default = 11.11, help = "double default is %default" ) ) parser <- OptionParser(option_list = optlist) expect_output(print_help(parser), "NA default is NA") expect_output(print_help(parser), "NULL default is NULL") expect_output(print_help(parser), "str default is str") expect_output(print_help(parser), "bool default is TRUE") expect_output(print_help(parser), "int default is 42") expect_output(print_help(parser), "double default is 11.11") # bug / feature request by Miroslav Posta parser <- OptionParser( usage = "test %prog test %prog", epilogue = "epilog test %prog %prog", description = "description %prog test %prog", prog = "unit_test.r" ) expect_output(print_help(parser), "Usage:.*unit_test.r.*unit_test.r") expect_output(print_help(parser), "description unit_test.r test unit_test.r") expect_output(print_help(parser), "epilog test unit_test.r unit_test.r") }) # Bug found by Benjamin Tyner test_that("Can set zero length default options", { option_list_neg <- list(make_option( c("-m", "--mean"), default = numeric(0), type = "numeric", help = "Default %default" )) parser <- OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg) expect_equal( sort_list(parse_args(parser, args = c("-m", "-5.0"))), sort_list(list(mean = -5, help = FALSE)) ) expect_equal(sort_list(parse_args(parser)), sort_list(list(mean = numeric(0), help = FALSE))) expect_output(print_help(parser), "Default double") }) # Bug found by Matthew Flickinger test_that("Can parse empty string", { option_list <- list(make_option(c("", "--string"))) parser <- OptionParser(usage = "\\%prog [options] file", option_list = option_list) expect_equal( sort_list(parse_args(parser, args = c("--string="))), sort_list(list(string = "", help = FALSE)) ) }) # nolint start # # Bug found by Rich FitzJohn # oo <- options() # on.exit(options(oo)) # options(warnPartialMatchArgs = TRUE) # test_that("Avoid partial matching of arguments", { # expect_that(seq(along = 1:10), gives_warning("partial argument match")) # expect_that(seq_along(1:10), not(gives_warning())) # expect_that(parse_args(args = c("-h", "foo"), parser, positional_arguments = TRUE, print_help_and_exit = FALSE), # not(gives_warning())) # expect_that(print_help(OptionParser()), not(gives_warning())) # }) # nolint end # Use h flag for non-help (Reported by Jeff Bruce) test_that("Use h option for non-help", { local_reproducible_output() option_list_neg <- list(make_option(c("-h", "--mean"), default = 0.0)) expect_snapshot( error = TRUE, OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg) ) expect_error( OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg), class = "optparse_option_conflict_error" ) expect_error( OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg), class = "optparse_option_error" ) option_list_neg <- list(make_option(c("-h", "--mean"), default = 0.0)) parser <- OptionParser( usage = "\\%prog [options] file", option_list = option_list_neg, add_help_option = FALSE ) args <- parse_args(parser, args = c("-h", "-5.0")) expect_equal(args, list(mean = -5.0)) }) test_that("no-argument actions reject --flag=value syntax", { parser <- OptionParser() parser <- add_option(parser, "--verbose", action = "store_true") parser <- add_option(parser, "--quiet", action = "store_false") parser <- add_option(parser, "--mode", action = "store_const", const = "fast") parser <- add_option(parser, "--tag", action = "append_const", const = "x", dest = "tags") parser <- add_option(parser, "--count", action = "count") expect_snapshot(error = TRUE, parse_args(parser, "--verbose=1")) expect_snapshot(error = TRUE, parse_args(parser, "--quiet=1")) expect_snapshot(error = TRUE, parse_args(parser, "--mode=1")) expect_snapshot(error = TRUE, parse_args(parser, "--tag=1")) expect_snapshot(error = TRUE, parse_args(parser, "--count=1")) expect_error(parse_args(parser, "--verbose=1"), class = "optparse_bad_option_error") }) test_that("store_const action works", { parser <- OptionParser() parser <- add_option(parser, c("-v", "--verbose"), action = "store_const", const = 42L) expect_null(parse_args(parser, c())$verbose) expect_equal(parse_args(parser, c("-v"))$verbose, 42L) expect_equal(parse_args(parser, c("--verbose"))$verbose, 42L) parser2 <- add_option( OptionParser(), "--verbose", action = "store_const", const = 42L, default = 0L ) expect_equal(parse_args(parser2, c())$verbose, 0L) expect_equal(parse_args(parser2, c("--verbose"))$verbose, 42L) }) test_that("append_const action works", { parser <- OptionParser() parser <- add_option(parser, "--foo", action = "append_const", const = "foo", dest = "items") parser <- add_option(parser, "--bar", action = "append_const", const = "bar", dest = "items") expect_null(parse_args(parser, c())$items) expect_equal(parse_args(parser, c("--foo"))$items, "foo") expect_equal(parse_args(parser, c("--foo", "--bar"))$items, c("foo", "bar")) expect_equal(parse_args(parser, c("--bar", "--foo", "--bar"))$items, c("bar", "foo", "bar")) parser2 <- OptionParser() parser2 <- add_option( parser2, "--foo", action = "append_const", const = "foo", dest = "items", default = "default" ) expect_equal(parse_args(parser2, c())$items, "default") expect_equal(parse_args(parser2, c("--foo"))$items, c("default", "foo")) }) test_that("multiple append options sharing a dest accumulate in command line order", { parser <- OptionParser() parser <- add_option(parser, "--file", action = "append", dest = "inputs") parser <- add_option(parser, "--dir", action = "append", dest = "inputs") expect_equal( parse_args(parser, c("--dir", "mydir", "--file", "a.txt"))$inputs, c("mydir", "a.txt") ) }) test_that("append action works", { parser <- OptionParser() parser <- add_option(parser, c("-f", "--file"), action = "append") expect_null(parse_args(parser, c())$file) expect_equal(parse_args(parser, c("--file", "a.txt"))$file, "a.txt") expect_equal(parse_args(parser, c("--file=a.txt"))$file, "a.txt") expect_equal(parse_args(parser, c("--file", "a.txt", "-f", "b.txt"))$file, c("a.txt", "b.txt")) parser2 <- add_option( OptionParser(), c("-f", "--file"), action = "append", default = "default.txt" ) expect_equal(parse_args(parser2, c())$file, "default.txt") expect_equal(parse_args(parser2, c("--file", "a.txt"))$file, c("default.txt", "a.txt")) }) test_that("count action works", { parser <- OptionParser() parser <- add_option(parser, c("-v", "--verbose"), action = "count") expect_null(parse_args(parser, c())$verbose) expect_equal(parse_args(parser, c("-v"))$verbose, 1L) expect_equal(parse_args(parser, c("-v", "-v", "--verbose"))$verbose, 3L) parser2 <- add_option(OptionParser(), c("-v", "--verbose"), action = "count", default = 2L) expect_equal(parse_args(parser2, c())$verbose, 2L) expect_equal(parse_args(parser2, c("-v", "-v"))$verbose, 4L) }) # Bug found by @husheng (#47) test_that("Don't coerce `default` of callback action match that of `type`", { parser <- OptionParser() str2bool <- function(option, flag, option_value, parser) as.logical(option_value) parser <- add_option(parser, "--bool", type = "character", default = FALSE, callback = str2bool) expect_equal(parse_args(parser, c())$bool, FALSE) expect_equal(parse_args(parser, "--bool=T")$bool, TRUE) }) optparse/tests/testthat/test-getopt.R0000644000176200001440000000666415161544056017536 0ustar liggesuserstest_that("flag that requires an argument raises optparse_bad_option_error", { parser <- OptionParser() parser <- add_option(parser, c("-n", "--number"), type = "integer") expect_error(parse_args(parser, c("--number")), class = "optparse_bad_option_error") expect_error(parse_args(parser, c("-n")), class = "optparse_bad_option_error") }) test_that("negative-number-looking bundle is passed as argument or expanded to short flags", { parser <- OptionParser() parser <- add_option(parser, c("-m", "--mean"), type = "double") # short flag preceding negative number bundle: treat as argument value (line 210-213) expect_equal(parse_args(parser, c("-m", "-12"))$mean, -12) # long flag without = preceding negative number bundle: treat as argument value (line 207) expect_equal(parse_args(parser, c("--mean", "-3.14"))$mean, -3.14) # long flag with = preceding negative number bundle: = already consumed value, # so prev_takes_argument() falls to else (line 215) and -3.14 is expanded → error expect_snapshot(error = TRUE, parse_args(parser, c("--mean=5", "-3.14"))) expect_error(parse_args(parser, c("--mean=5", "-3.14")), class = "optparse_bad_option_error") # standalone: expanded to -1, -2 which are invalid short flags expect_snapshot(error = TRUE, parse_args(parser, c("-12"))) expect_error(parse_args(parser, c("-12")), class = "optparse_bad_option_error") }) test_that("type coercion warns when value cannot be converted to expected type", { parser <- OptionParser() parser <- add_option(parser, "--count", type = "integer") parser <- add_option(parser, "--mean", type = "double") # "foo" triggers the warning inside storage.mode() itself (line 150) expect_snapshot(parse_args(parser, c("--count", "foo"))) # "" converts silently to NA_real_ without warning, triggering the post-coercion NA check (lines 154-157) expect_snapshot(parse_args(parser, c("--mean", ""))) }) test_that("abbreviated long flag matching two options raises ambiguous error", { parser <- OptionParser() parser <- add_option(parser, "--verbose", action = "store_true") parser <- add_option(parser, "--verbosity", type = "integer") expect_snapshot(error = TRUE, parse_args(parser, c("--verb"))) expect_error(parse_args(parser, c("--verb")), class = "optparse_ambiguous_option_error") expect_error(parse_args(parser, c("--verb")), class = "optparse_bad_option_error") expect_error(parse_args(parser, c("--verb")), class = "optparse_parse_error") }) test_that("get_Rscript_filename() ignores --file= after --args", { local_mocked_bindings( command_args = function() c("Rscript", "--file=script.R", "--args", "--file=fake.R") ) expect_equal(get_Rscript_filename(), "script.R") }) test_that("get_Rscript_filename() works with no --args", { local_mocked_bindings( command_args = function() c("Rscript", "--file=script.R") ) expect_equal(get_Rscript_filename(), "script.R") }) test_that("get_Rscript_filename() returns NA when no --file=", { local_mocked_bindings( command_args = function() character(0) ) expect_equal(get_Rscript_filename(), NA_character_) }) test_that("get_Rscript_filename() returns NA when no --file= before --args", { local_mocked_bindings( command_args = function() c("R", "--args", "--file=boo.r") ) expect_equal(get_Rscript_filename(), NA_character_) }) test_that("get_Rscript_filename() returns LITTLER_SCRIPT_PATH when set", { local_mocked_bindings( littler_script_path = function() "script.r" ) expect_equal(get_Rscript_filename(), "script.r") }) optparse/tests/testthat/_snaps/0000755000176200001440000000000015161657135016406 5ustar liggesusersoptparse/tests/testthat/_snaps/optparse.md0000644000176200001440000000752115162557710020571 0ustar liggesusers# `make_option()` works as expected Code make_option("badflag") Condition Error: ! We require a long flag option --- Code make_option(c("-cd", "--foo")) Condition Error: ! Short flag -cd must only be a '-' and a single non-dash character --- Code make_option(c("- ", "--foo")) Condition Error: ! Short flag - must not contain whitespace --- Code make_option(c("-=", "--foo")) Condition Error: ! Short flag -= must not contain '=' --- Code make_option("--fo=o") Condition Error: ! Long flag --fo=o must not contain '=' --- Code make_option("--fo o") Condition Error: ! Long flag --fo o must not contain whitespace --- Code make_option("--foo", action = "storr") Condition Error: ! "storr" is not a valid action; must be one of: "append", "append_const", "callback", "count", "store", "store_const", "store_false", "store_true" --- Code make_option("--foo", type = "int") Condition Error: ! "int" is not a valid type; must be one of: "character", "complex", "double", "integer", "logical", "NULL" # `required` argument works as expected Code parse_args(parser, args = character(0)) Condition Error: ! the following arguments are required: --foo --- Code parse_args(parser2, args = character(0)) Condition Error: ! the following arguments are required: --foo, --bar # `parse_args()` works as expected Code parse_args(parser, args = c("-add-numbers", "example.txt"), positional_arguments = FALSE) Condition Error: ! short flag "a" is invalid --- Code parse_args(parser, args = c("-add-numbers", "example.txt"), positional_arguments = c(0, 1)) Condition Error: ! short flag "a" is invalid --- Code parse_args(parser, args = c("example.txt"), positional_arguments = c(2, Inf)) Condition Error: ! required at least 2 positional arguments, got 1 --- Code parse_args(parser, args = c("example.txt"), positional_arguments = 2) Condition Error: ! required at least 2 positional arguments, got 1 --- Code parse_args(parser, args = c("example.txt"), positional_arguments = "any") Condition Error: ! positional_arguments must be logical or numeric --- Code parse_args(parser, args = c("example.txt"), positional_arguments = 1:3) Condition Error: ! positional_arguments must have length 1 or 2 # positional argument with positional_arguments = FALSE raises an error Code parse_args(parser, c("file.txt")) Condition Error: ! "file.txt" is not a valid option --- Code parse_args(parser, c("--verbose", "file.txt")) Condition Error: ! "file.txt" is not a valid option # Use h option for non-help Code OptionParser(usage = "\\%prog [options] file", option_list = option_list_neg) Condition Error in `validityMethod()`: ! duplicate short flag: -h (did you forget to set `add_help_option = FALSE` in `OptionParser()`?) # no-argument actions reject --flag=value syntax Code parse_args(parser, "--verbose=1") Condition Error: ! long flag "verbose" accepts no arguments --- Code parse_args(parser, "--quiet=1") Condition Error: ! long flag "quiet" accepts no arguments --- Code parse_args(parser, "--mode=1") Condition Error: ! long flag "mode" accepts no arguments --- Code parse_args(parser, "--tag=1") Condition Error: ! long flag "tag" accepts no arguments --- Code parse_args(parser, "--count=1") Condition Error: ! long flag "count" accepts no arguments optparse/tests/testthat/_snaps/getopt.md0000644000176200001440000000174315162557710020236 0ustar liggesusers# negative-number-looking bundle is passed as argument or expanded to short flags Code parse_args(parser, c("--mean=5", "-3.14")) Condition Error: ! short flag "3" is invalid --- Code parse_args(parser, c("-12")) Condition Error: ! short flag "1" is invalid # type coercion warns when value cannot be converted to expected type Code parse_args(parser, c("--count", "foo")) Condition Warning in `value[[3L]]()`: integer expected, got "foo" Output $help [1] FALSE $count [1] "foo" --- Code parse_args(parser, c("--mean", "")) Condition Warning in `getopt()`: double expected, got "" Output $help [1] FALSE $mean [1] NA # abbreviated long flag matching two options raises ambiguous error Code parse_args(parser, c("--verb")) Condition Error: ! long flag "verb" is ambiguous optparse/tests/test_help.Rout.save0000644000176200001440000000153613567307174017072 0ustar liggesusers R version 3.3.2 (2016-10-31) -- "Sincere Pumpkin Patch" Copyright (C) 2016 The R Foundation for Statistical Computing Platform: x86_64-pc-linux-gnu (64-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. Natural language support but running in an English locale R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > library("optparse") > > parser <- OptionParser() > parse_args(parser, "--help") Usage: %prog [options] Options: -h, --help Show this help message and exit optparse/MD50000644000176200001440000000336315170356312012427 0ustar liggesuserseb723b61539feef013de476e68b5c50a *COPYING e1adb4a824f93ce3ca7fb92a70a92c90 *DESCRIPTION 2c495a71e5ea92806855158f100dd341 *NAMESPACE 93dfa7c02dd6646da0661c4ce75e9dbc *NEWS.md 364beb5a67cfca22e300e9e86394feb7 *R/getopt.R bd31e3e3cb7ee29756563bc31f18fa26 *R/optparse-package.R 9137d468651451439ed5355f88299ebe *R/optparse.R d1df9af1da269ac0ec7527115532ff90 *README.md b6e286a601191c2000e013108895df6b *build/vignette.rds 09568616dd09c14ba7e1024df1993c30 *exec/display_file.R 26920be3e6c98473f96caf731cd0e6d0 *exec/example.R e8eabbd15e7e219df00a2aebe2d28c84 *inst/COPYRIGHTS d4718b74eaaffd8f6ca19530de43403e *inst/doc/optparse.R a54f6801964f3a6aab96174346246e1a *inst/doc/optparse.Rmd 3cd3fb00bfb0926ebf9212a5c3879eea *inst/doc/optparse.html 0a1ce882fa6abaf370808a6792da8194 *man/OptionParser-class.Rd 1414077ebe98b36ab668371f6e73b9ce *man/OptionParser.Rd 40ee53be0e219b72b7b3f8f7dafa4741 *man/OptionParserOption-class.Rd 242f7a8a6a4f7269f381c7e118773bc3 *man/add_make_option.Rd dfffdcf9ac83bc3e9e85a337bc9d9a99 *man/figures/logo.png c3a3cbe86d2aa11364afe65eedcfd08d *man/figures/logo.svg 6965444760002d29bb25fdaec0992468 *man/formatter.Rd ef3dcdc60c1dc548699cf7a379802f66 *man/optparse-package.Rd 98fff9b07f9afb9a1bada5c9e17c8532 *man/parse_args.Rd 48b80b258767fb3fd621ad8935e92f7e *man/print_help.Rd 398b710c16889ab67e30dbb3bad87137 *tests/run-all.R db4dd8c665d626beb66a70a7fd5ac1a6 *tests/test_help.R aa33491c5ca831201e373cb8ca1b3ddb *tests/test_help.Rout.save 269c433967a82727fa004a011c890e39 *tests/testthat/_snaps/getopt.md 474f80800a5d62d20c0ce884a83806a5 *tests/testthat/_snaps/optparse.md 00d15f782faedf06ff43eaa4cac825af *tests/testthat/test-getopt.R 878763099048b2e912061f7bb51ff1cf *tests/testthat/test-optparse.R a54f6801964f3a6aab96174346246e1a *vignettes/optparse.Rmd optparse/R/0000755000176200001440000000000015167740222012316 5ustar liggesusersoptparse/R/getopt.R0000644000176200001440000001715215161544056013752 0ustar liggesusers# Copyright (c) 2008-2010 Allen Day # Copyright (c) 2011-2026 Trevor L. Davis # # This file is free software: you may copy, redistribute and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the License, or (at your # option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . COL_LONG_NAME <- 1L COL_SHORT_NAME <- 2L COL_ACTION <- 3L COL_MODE <- 4L COL_DESCRIPTION <- 5L COL_DEST <- 6L # Fork of `getopt::getopt()` adapted for {optparse} getopt <- function( spec = NULL, opt = NULL, command = get_Rscript_filename(), operand = "after--only", defaults = list(), constants = list() ) { operand <- match.arg(operand, c("after--only", "strict")) dashdash <- match("--", opt, nomatch = NA_integer_) if (!is.na(dashdash)) { dashdash_operands <- opt[seq_len(length(opt) - dashdash) + dashdash] opt <- opt[seq_len(dashdash - 1L)] } else { dashdash_operands <- NULL } inline_operands <- NULL opt <- normalize_opt(opt, spec) result <- defaults i <- 1L while (i <= length(opt)) { optstring <- opt[i] if (is_long_flag(optstring)) { optstring <- substring(optstring, 3) if (grepl("=", optstring)) { kv <- strsplit(optstring, "=")[[1L]] this_flag <- kv[1L] this_argument <- paste(kv[-1L], collapse = "=") } else { this_flag <- optstring this_argument <- NA } rowmatch <- get_rowmatch(spec, long = this_flag) # if we have an argument embedded via '=' if (!is.na(this_argument)) { long_name <- spec[rowmatch, COL_LONG_NAME] action <- spec[rowmatch, COL_ACTION] dest_name <- spec[rowmatch, COL_DEST] # if we can't accept the argument, bail out if ( action %in% c("append_const", "count", "store_const", "store_false", "store_true") ) { bad_option_error_stop(paste0( 'long flag "', this_flag, '" accepts no arguments' )) } else if (action == "append") { result[[dest_name]] <- c(result[[dest_name]], this_argument) i <- i + 1L next } else { result[[dest_name]] <- this_argument i <- i + 1L next } } } else if (is_short_flag(optstring)) { this_flag <- substring(optstring, 2L) rowmatch <- get_rowmatch(spec, short = this_flag) } else if (operand == "strict") { inline_operands <- c(inline_operands, optstring) i <- i + 1L next } else { bad_option_error_stop(paste0('"', optstring, '" is not a valid option')) } long_name <- spec[rowmatch, COL_LONG_NAME] action <- spec[rowmatch, COL_ACTION] dest_name <- spec[rowmatch, COL_DEST] if (action == "store_const") { result[[dest_name]] <- constants[[long_name]] i <- i + 1L next } else if (action == "append_const") { result[[dest_name]] <- c(result[[dest_name]], constants[[long_name]]) i <- i + 1L next } else if (action == "count") { result[[dest_name]] <- (result[[dest_name]] %||% 0L) + 1L i <- i + 1L next } else if (action %in% c("store_true", "store_false")) { result[[dest_name]] <- action != "store_false" i <- i + 1L next } else { # append or store: peek ahead for argument if (length(opt) > i) { peek_optstring <- opt[i + 1L] if ( !is_long_flag(peek_optstring) && (is_negative_number(peek_optstring) || !is_short_flag(peek_optstring)) ) { if (action == "append") { result[[dest_name]] <- c(result[[dest_name]], peek_optstring) } else { result[[dest_name]] <- peek_optstring } i <- i + 2L next } } if (action %in% c("store", "append")) { flag_kind <- ifelse(is_long_flag(opt[i]), "long", "short") bad_option_error_stop(paste0( flag_kind, ' flag "', this_flag, '" requires an argument' )) } } } for (j in seq_len(nrow(spec))) { dest_name <- spec[j, COL_DEST] if (is.character(result[[dest_name]])) { mode <- spec[j, COL_MODE] val <- result[[dest_name]] tryCatch( storage.mode(result[[dest_name]]) <- mode, warning = function(w) { warning(paste(mode, "expected, got", dQuote(val))) } ) if (any(is.na(result[[dest_name]]) & !is.na(val))) { warning(paste( mode, "expected, got", paste(dQuote(val[is.na(result[[dest_name]]) & !is.na(val)]), collapse = ", ") )) } } } structure(result, class = "getopt", operand = c(inline_operands, dashdash_operands)) } getoperand <- function(x) { stopifnot(inherits(x, "getopt")) attr(x, "operand") } get_Rscript_filename <- function() { args <- command_args() args_idx <- match("--args", args) if (!is.na(args_idx)) { args <- args[seq_len(args_idx - 1L)] } prog <- sub("--file=", "", grep("^--file=", args, value = TRUE)[1L]) if (is.na(prog)) { prog <- littler_script_path() } if (!is.na(prog) && .Platform$OS.type == "windows") { prog <- gsub("\\\\", "\\\\\\\\", prog) } prog } command_args <- function() commandArgs() is_interactive <- function() interactive() littler_script_path <- function() Sys.getenv("LITTLER_SCRIPT_PATH", unset = NA_character_) is_negative_number <- function(x) { regexpr("^-[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$", x) > 0L } is_long_flag <- function(x) { startsWith(x, "--") && nchar(x) > 2L } is_short_flag <- function(x) { startsWith(x, "-") && !startsWith(x, "--") && nchar(x) == 2L } is_bundle <- function(o) { startsWith(o, "-") && !startsWith(o, "--") && nchar(o) > 2L } expand_bundle <- function(o) { paste0("-", strsplit(substring(o, 2L), "")[[1L]]) } prev_takes_argument <- function(prev, spec) { if (is_long_flag(prev) && !grepl("=", prev, fixed = TRUE)) { rowmatch <- tryCatch(get_rowmatch(spec, long = substring(prev, 3L)), error = function(e) { NA_integer_ }) } else if (is_short_flag(prev)) { rowmatch <- tryCatch(get_rowmatch(spec, short = substring(prev, 2L)), error = function(e) { NA_integer_ }) } else { return(FALSE) } actions <- c("append", "store") !is.na(rowmatch) && spec[rowmatch, COL_ACTION] %in% actions } normalize_opt <- function(opt, spec) { result <- character(0L) for (o in opt) { if (!is_bundle(o)) { result <- c(result, o) } else if (!is_negative_number(o)) { result <- c(result, expand_bundle(o)) } else if (length(result) > 0L && prev_takes_argument(result[length(result)], spec)) { result <- c(result, o) } else { result <- c(result, expand_bundle(o)) } } result } `%||%` <- function(x, y) if (is.null(x)) y else x get_rowmatch <- function(spec, long = NULL, short = NULL) { if (!is.null(long)) { rowmatch <- grep(long, spec[, COL_LONG_NAME], fixed = TRUE) if (length(rowmatch) == 0L) { bad_option_error_stop(paste0('long flag "', long, '" is invalid')) } else if (length(rowmatch) > 1L) { rowmatch <- which(long == spec[, COL_LONG_NAME]) if (length(rowmatch) == 0L) { ambiguous_option_error_stop(paste0('long flag "', long, '" is ambiguous')) } } } else { rowmatch <- grep(short, spec[, COL_SHORT_NAME], fixed = TRUE) if (length(rowmatch) == 0L) { bad_option_error_stop(paste0('short flag "', short, '" is invalid')) } } rowmatch } na_omit <- function(x) { Filter(Negate(is.na), x) } sort_list <- function(unsorted_list) { for (ii in seq(along = unsorted_list)) { if (is.list(unsorted_list[[ii]])) { unsorted_list[[ii]] <- sort_list(unsorted_list[[ii]]) } } unsorted_list[sort(names(unsorted_list))] } optparse/R/optparse-package.R0000644000176200001440000000407414607642373015702 0ustar liggesusers#'Command line option parser #' #'Goal is to create an R package of a command line parser inspired by Python's #'\dQuote{optparse} library. #' #'\code{optparse} is primarily intended to be used with #'\dQuote{Rscript}. It facilitates writing \dQuote{#!} shebang scripts that #'accept short and long flags/options. It can also be used from directly, but #'is probably less useful in this context. #' #'See package vignette for a more detailed example. #' #'Notes on naming convention in package: 1. An option is one of the shell-split #'input strings. 2. A flag is a type of option. a flag can be defined as having #'no argument (defined below), a required argument, or an optional argument. 3. #'An argument is a type of option, and is the value associated with a flag. 4. #'A long flag is a type of flag, and begins with the string \dQuote{--}. If the #'long flag has an associated argument, it may be delimited from the long flag #'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. %%% #' #'@name optparse-package #'@aliases optparse-package optparse #'@author Trevor L. Davis. #' #'Some documentation and unit tests ported from Allen Day's getopt package. #' #'The documentation for Python's optparse library, which this package is based #'on, is Copyright 1990-2009, Python Software Foundation. #'@seealso \code{\link[getopt]{getopt}} #'@references Python's \code{optparse} library, which this package is based on, #'is described here: \url{https://docs.python.org/3/library/optparse.html} #'@keywords package #'@examples #' #' example_file <- system.file("exec", "example.R", package = "optparse") #' example_file_2 <- system.file("exec", "display_file.R", package = "optparse") #' \dontrun{ #' readLines(example_file) #' readLines(example_file_2) #' } #' "_PACKAGE" optparse/R/optparse.R0000644000176200001440000007376715162557666014337 0ustar liggesusers# Copyright (c) 2010-2024 Trevor L. Davis # Copyright (c) 2015 Rick FitzJohn https://github.com/richfitz # Copyright (c) 2013 Kirill Müller https://github.com/krlmlr # Copyright (c) 2011 Jim Nikelski # Copyright (c) 2010 Steve Lianoglou # # This file is free software: you may copy, redistribute and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the License, or (at your # option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # This file incorporates work from the optparse module in Python 2.6.2. # # Copyright (c) 1990-2009 Python Software Foundation; All Rights Reserved # # See (inst/)COPYRIGHTS or http://docs.python.org/2/license.html for the full # Python (GPL-compatible) license stack. # # As mentioned above, this file incorporates some patches by Steve Lianoglou (c) 2010 # He explicitly gave me a non-exclusive unlimited license to code in his patches #' Option Parser #' #' @slot usage The program usage message that will printed out if #' [parse_args()] finds a help option, `\%prog` is substituted with the #' value of the `prog` argument. #' @slot options A list of of `OptionParserOption` instances that will #' define how [parse_args()] reacts to command line options. #' `OptionParserOption` instances are usually created by [make_option()] #' and can also be added to an existing `OptionParser` instance via the #' [add_option()] function. #' @slot description Additional text for [print_help()] to print out between #' usage statement and options statement #' @slot epilogue Additional text for [print_help()] to print out after #' the options statement #' @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()]. #' @seealso [OptionParserOption] #' @import methods #' @exportClass OptionParser setClass( "OptionParser", representation( usage = "character", options = "list", description = "character", epilogue = "character", formatter = "function" ) ) setValidity("OptionParser", function(object) { long_flags <- vapply(object@options, function(o) o@long_flag, character(1L)) if (anyDuplicated(long_flags)) { dup <- long_flags[duplicated(long_flags)][1L] msg <- paste0("duplicate long flag: ", dup) if (dup == "--help") { msg <- paste0( msg, " (did you forget to set `add_help_option = FALSE` in `OptionParser()`?)" ) } option_conflict_error_stop(msg) } short_flags <- na_omit(vapply(object@options, function(o) o@short_flag, character(1L))) if (anyDuplicated(short_flags)) { dup <- short_flags[duplicated(short_flags)][1L] msg <- paste0("duplicate short flag: ", dup) if (dup == "-h") { msg <- paste0( msg, " (did you forget to set `add_help_option = FALSE` in `OptionParser()`?)" ) } option_conflict_error_stop(msg) } TRUE }) setGeneric("options<-", function(x, value) standardGeneric("options<-")) setMethod("options<-", "OptionParser", function(x, value) { x@options <- value validObject(x) x }) #' Class to hold information about command-line options #' #' @slot short_flag String of the desired short flag #' 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` #' @slot default `r ro_default` #' @slot const `r ro_const` #' @slot required `r ro_required` #' @slot help `r ro_help` #' @slot metavar `r ro_metavar` #' @slot callback `r ro_callback` #' @slot callback_args `r ro_callback_args` #' @seealso [make_option()] #' @exportClass OptionParserOption #' @export OptionParserOption OptionParserOption <- setClass( "OptionParserOption", representation( short_flag = "character", # nolint long_flag = "character", action = "character", type = "character", dest = "character", default = "ANY", help = "character", metavar = "character", callback = "ANY", callback_args = "ANY", const = "ANY", required = "logical" ) ) check_action <- function(action) { valid_actions <- c( "append", "append_const", "callback", "count", "store", "store_const", "store_false", "store_true" ) if (!action %in% valid_actions) { option_error_stop( paste0( '"', action, '" is not a valid action; ', "must be one of: ", paste(paste0('"', valid_actions, '"'), collapse = ", ") ), call = NULL ) } } check_type <- function(type) { valid_types <- c("character", "complex", "double", "integer", "logical", "NULL") if (length(type) == 1L && !type %in% valid_types) { option_error_stop( paste0( '"', type, '" is not a valid type; ', "must be one of: ", paste(paste0('"', valid_types, '"'), collapse = ", ") ), call = NULL ) } } check_short <- function(short_flag) { if (is.na(short_flag)) { return(invisible(NULL)) } if (nchar(short_flag) > 2) { option_error_stop( paste("Short flag", short_flag, "must only be a '-' and a single non-dash character"), call = NULL ) } if (grepl("[[:space:]]", short_flag)) { option_error_stop( paste("Short flag", short_flag, "must not contain whitespace"), call = NULL ) } if (grepl("=", short_flag, fixed = TRUE)) { option_error_stop( paste("Short flag", short_flag, "must not contain '='"), call = NULL ) } } check_long <- function(long_flag) { if (length(long_flag) == 0) { option_error_stop("We require a long flag option", call = NULL) } if (grepl("=", long_flag, fixed = TRUE)) { option_error_stop( paste("Long flag", long_flag, "must not contain '='"), call = NULL ) } if (grepl("[[:space:]]", long_flag)) { option_error_stop( paste("Long flag", long_flag, "must not contain whitespace"), call = NULL ) } } # Currently redundant since these are called by `make_option()` # setValidity("OptionParserOption", function(object) { # check_short(object@short_flag) # check_long(object@long_flag) # check_action(object@action) # check_type(object@type) # TRUE # }) #' A function to create an instance of a parser object #' #' This function is used to create an instance of a parser object #' which when combined with the [parse_args()], [make_option()], and [add_option()] #' methods is very useful for parsing options from the command line. #' #' @param usage The program usage message that will printed out if #' [parse_args()] finds a help option, `\%prog` is substituted with the #' value of the `prog` argument. #' @param option_list A list of of `OptionParserOption` instances that will #' define how [parse_args()] reacts to command line options. #' `OptionParserOption` instances are usually created by [make_option()] #' and can also be added to an existing `OptionParser` instance via the #' [add_option()] function. #' @param add_help_option Whether a standard help option should be automatically #' added to the `OptionParser` instance. #' @param prog Program name to be substituted for `\%prog` in the usage #' message (including description and epilogue if present), #' the default is to use the actual Rscript file name if called by an #' Rscript file and otherwise keep `\%prog`. #' @param description Additional text for [print_help()] to print out between #' usage statement and options statement #' @param epilogue Additional text for [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 `OptionParser` class. #' #' @seealso [parse_args()] [make_option()] [add_option()] #' @references Python's `optparse` library, which inspired this package, #' is described here: \url{https://docs.python.org/3/library/optparse.html} #' @export OptionParser <- function( usage = "usage: %prog [options]", option_list = list(), # nolint add_help_option = TRUE, prog = NULL, description = "", epilogue = "", formatter = IndentedHelpFormatter ) { if (is.null(prog)) { prog <- get_Rscript_filename() } if (length(prog) && !is.na(prog)) { usage <- gsub("%prog", prog, usage, fixed = TRUE) description <- gsub("%prog", prog, description, fixed = TRUE) epilogue <- gsub("%prog", prog, epilogue, fixed = TRUE) } # Match behavior of usage string in Python optparse package usage <- sub("^usage: ", "Usage: ", usage) usage <- ifelse(grepl("^Usage: ", usage), usage, sub("^", "Usage: ", usage)) if (add_help_option) { option_list[[length(option_list) + 1]] <- make_option( c("-h", "--help"), action = "store_true", dest = "help", default = FALSE, help = "Show this help message and exit" ) } return(new( "OptionParser", usage = usage, options = option_list, description = description, epilogue = epilogue, formatter = formatter )) } option_error_stop <- function(msg, call = sys.call(-1)) { stop(errorCondition(msg, class = "optparse_option_error", call = call)) } option_conflict_error_stop <- function(msg, call = sys.call(-1)) { stop(errorCondition( msg, class = c("optparse_option_conflict_error", "optparse_option_error"), call = call )) } #' Functions to enable our OptionParser to recognize specific command line #' options. #' #' [add_option()] adds a option to a prexisting `OptionParser` instance #' whereas [make_option()] is used to create a list of #' `OptionParserOption` instances that will be used in the #' `option_list` argument of the `OptionParser` function to create a #' new `OptionParser` instance. #' #' @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 `--` 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` #' @param default `r ro_default` #' @param const `r ro_const` #' @param required `r ro_required` #' @param help `r ro_help` #' @param metavar `r ro_metavar` #' @param callback `r ro_callback` #' @param callback_args `r ro_callback_args` #' @return Both [make_option()] and [add_option()] return instances of #' class `OptionParserOption`. #' @section Errors: #' The following classed errors may be thrown: #' #' - `optparse_option_error`: invalid option definition (bad flag string, #' unrecognized action, etc.). #' - `optparse_option_conflict_error`: duplicate flag detected when #' adding an option to a parser. #' #' @seealso [parse_args()] [OptionParser()] #' @references Python's `optparse` library, which inspires this package, #' is described here: \url{https://docs.python.org/3/library/optparse.html} #' @examples #' #' make_option("--longflag") #' make_option(c("-l", "--longflag")) #' make_option("--integer", type = "integer", default = 5) #' make_option("--integer", default = as.integer(5)) # same as previous #' #' # examples from package vignette #' make_option(c("-v", "--verbose"), action = "store_true", default = TRUE, #' help = "Print extra output [default]") #' make_option(c("-q", "--quietly"), action = "store_false", #' dest = "verbose", help = "Print little output") #' make_option(c("-c", "--count"), type = "integer", default = 5, #' help = "Number of random normals to generate [default %default]", #' metavar = "number") #' make_option("--generator", default = "rnorm", #' help = "Function to generate random deviates [default \"%default\"]") #' make_option("--mean", default = 0, #' help = "Mean if generator == \"rnorm\" [default %default]") #' make_option("--sd", default = 1, metavar = "standard deviation", #' help = "Standard deviation if generator == \"rnorm\" [default %default]") #' #' @export make_option <- function( opt_str, action = NULL, type = NULL, dest = NULL, default = NULL, help = "", metavar = NULL, callback = NULL, callback_args = NULL, const = NULL, required = FALSE ) { action <- ifelse(is.null(action), ifelse(is.null(callback), "store", "callback"), action) # flags short_flag <- opt_str[grepl("^-[^-]", opt_str)] if (length(short_flag) == 0) { short_flag <- NA_character_ } else { check_short(short_flag) } long_flag <- opt_str[grepl("^--[^-]", opt_str)] check_long(long_flag) check_action(action) # type if (is.null(type)) { type <- infer_type(action, default, const) } if (type == "numeric") { type <- "double" } check_type(type) # default if ( !(action %in% c("callback", "store_const", "append_const")) && (type != typeof(default)) && !is.null(default) ) { storage.mode(default) <- type } # dest if (is.null(dest)) { dest <- sub("^--", "", long_flag) } # metavar if (is.null(metavar)) { if (option_needs_argument_helper(action, type)) { metavar <- sub("^--", "", long_flag) } else { metavar <- character(0) } } warn_callback(action, callback, callback_args) if (is.null(callback_args)) { callback_args <- list() } return(new( "OptionParserOption", short_flag = short_flag, long_flag = long_flag, action = action, type = type, dest = dest, default = default, const = const, required = required, help = help, metavar = metavar, callback = callback, callback_args = callback_args )) } infer_type <- function(action, default, const) { switch( action, store = ifelse(is.null(default), "character", typeof(default)), append = ifelse(is.null(default), "character", typeof(default[[1]])), store_const = typeof(const), append_const = typeof(const), store_false = "logical", store_true = "logical", count = "integer", callback = "NULL" ) } warn_callback <- function(action, callback, callback_args) { if (action == "callback") { if (!is.function(callback)) { warning(sprintf("callback argument is not a function")) } } else { if (!is.null(callback)) { warning(sprintf("callback argument is supplied for non-callback action")) } if (!is.null(callback_args)) { warning(sprintf("callback_args argument is supplied for non-callback action")) } } } #' @rdname add_make_option #' @export add_option <- function( object, opt_str, action = NULL, type = NULL, dest = NULL, default = NULL, help = "", metavar = NULL, callback = NULL, callback_args = NULL, const = NULL, required = FALSE ) { opts <- object@options opts[[length(opts) + 1L]] <- make_option( opt_str = opt_str, action = action, type = type, dest = dest, default = default, const = const, required = required, help = help, metavar = metavar, callback = callback, callback_args = callback_args ) options(object) <- opts return(object) } #' Printing an usage message from an OptionParser object #' #' [print_help()] print an usage message from an OptionParser object, usually #' called by [parse_args()] when it encounters a help option. #' #' @param object A `OptionParser` instance. #' @return [print_help()] uses the `cat` function to print out a usage #' message. It returns `invisible(NULL)`. #' #' @seealso [parse_args()] [OptionParser()] #' @references Python's `optparse` library, which inspired this package, #' is described here: \url{https://docs.python.org/3/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) { # nolint cat(object@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]] cat("\t") if (!is.na(option@short_flag)) { cat(option@short_flag) if (option_needs_argument(option)) { cat(" ", toupper(option@metavar), sep = "") } cat(", ") } if (!is.null(option@long_flag)) { cat(option@long_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)) } #' @rdname formatter #' @export TitledHelpFormatter <- function(object) { # nolint 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)) { "NULL" } else if (!length(default)) { paste0(typeof(default), "(0)") } else if (is.na(default)) { "NA" } else { as.character(default) } } #' Parse command line options. #' #' [parse_args()] parses command line options using an `OptionParser` #' instance for guidance. [parse_args2()] is a wrapper to [parse_args()] #' setting the options `positional_arguments` and `convert_hyphens_to_underscores` #' to `TRUE`. #' #' @param object An `OptionParser` instance. #' @param args A character vector containing command line options to be parsed. #' Default is everything after the Rscript program in the command line. If #' `positional_arguments` is not `FALSE` then [parse_args()] will #' look for positional arguments at the end of this vector. #' @param print_help_and_exit Whether [parse_args()] should call #' [print_help()] to print out a usage message and exit the program. Default #' is `TRUE`. #' @param positional_arguments Number of \emph{positional} arguments. A numeric #' denoting the exact number of supported arguments, or a numeric vector of #' length two denoting the minimum and maximum number of arguments #' (`Inf` for no limit). The value `TRUE` is equivalent to #' `c(0, Inf)`. The default `FALSE` is #' supported for backward compatibility only, as it alters #' the format of the return value. #' @param convert_hyphens_to_underscores If the names in the returned list of options #' contains hyphens then convert them to underscores. The default `FALSE` is #' supported for backward compatibility reasons as it alters the format of the return value #' @return Returns a list with field `options` containing our option values #' as well as another field `args` which contains a vector of #' positional arguments. For backward compatibility, if and only if #' `positional_arguments` is `FALSE`, returns a list containing #' option values. #' @section Errors: #' The following classed errors may be thrown: #' #' - `optparse_parse_error`: base class for all parse-time errors. #' - `optparse_bad_option_error`: unrecognized, misused, or #' argument-requiring option. #' - `optparse_ambiguous_option_error`: ambiguous abbreviated long #' flag. #' - `optparse_bad_positional_arguments_error`: wrong number of #' positional arguments supplied. #' - `optparse_missing_required_error`: a required option was not supplied. #' #' @seealso [OptionParser()] [print_help()] #' @references Python's `optparse` library, which inspired this package, #' is described here: \url{https://docs.python.org/3/library/optparse.html} #' @encoding latin1 #' @examples #' # example from vignette #' option_list <- list( #' make_option(c("-v", "--verbose"), action = "store_true", default = TRUE, #' help = "Print extra output [default]"), #' make_option(c("-q", "--quietly"), action = "store_false", #' dest = "verbose", help = "Print little output"), #' make_option(c("-c", "--count"), type = "integer", default = 5, #' help = "Number of random normals to generate [default %default]", #' metavar = "number"), #' make_option("--generator", default = "rnorm", #' help = "Function to generate random deviates [default \"%default\"]"), #' make_option("--mean", default = 0, #' help = "Mean if generator == \"rnorm\" [default %default]"), #' make_option("--sd", default = 1, metavar = "standard deviation", #' help = "Standard deviation if generator == \"rnorm\" [default %default]") #' ) #'parse_args(OptionParser(option_list = option_list), args = c("--sd=3", "--quietly")) #' #'# example from vignette using positional arguments #'option_list2 <- list( #' make_option(c("-n", "--add-numbers"), action = "store_true", default = FALSE, #' help = "Print line number at the beginning of each line [default]") #' ) #'parser <- OptionParser(usage = "%prog [options] file", option_list = option_list2) #' #'parse_args(parser, args = c("--add-numbers", "example.txt"), positional_arguments = TRUE) #' #'parse_args(parser, args = c("--add-numbers", "example.txt"), positional_arguments = TRUE, #' convert_hyphens_to_underscores = TRUE) #' #'parse_args2(parser, args = c("--add-numbers", "example.txt")) #' #' @export parse_args <- function( object, args = commandArgs(trailingOnly = TRUE), print_help_and_exit = TRUE, positional_arguments = FALSE, convert_hyphens_to_underscores = FALSE ) { tryCatch( parse_args_helper( object, args, print_help_and_exit, positional_arguments, convert_hyphens_to_underscores ), error = function(e) pa_stop(object, e) ) } quieter_error_handler <- function(e) { quit('no', status = 1, runLast = FALSE) } bad_option_error_stop <- function(msg) { stop(errorCondition( msg, class = c("optparse_bad_option_error", "optparse_parse_error"), call = NULL )) } ambiguous_option_error_stop <- function(msg) { stop(errorCondition( msg, class = c( "optparse_ambiguous_option_error", "optparse_bad_option_error", "optparse_parse_error" ), call = NULL )) } missing_required_error_stop <- function(msg) { stop(errorCondition( msg, class = c("optparse_missing_required_error", "optparse_parse_error"), call = NULL )) } bad_positional_arguments_error_stop <- function(msg) { stop(errorCondition( msg, class = c("optparse_bad_positional_arguments_error", "optparse_parse_error"), call = NULL )) } pa_stop <- function(object, e) { extra_classes <- setdiff(class(e), c("simpleError", "error", "condition")) classes <- unique(c(extra_classes, "optparse_parse_error")) cnd <- errorCondition( e$message, call = "optparse::parse_args_helper()", class = classes ) if (is_interactive()) { stop(cnd) } else { signalCondition(cnd) msg <- paste0("\n", get_Rscript_filename(), ": error: ", e$message) cat(object@usage, msg, sep = "\n", file = stderr()) opt <- options( error = getOption("error", quieter_error_handler), show.error.messages = FALSE ) on.exit(options(opt)) stop(cnd) } } parse_args_helper <- function( object, args = commandArgs(trailingOnly = TRUE), print_help_and_exit = TRUE, positional_arguments = FALSE, convert_hyphens_to_underscores = FALSE ) { validObject(object) pal <- should_include_any_args(positional_arguments) include_any_args <- pal$include_any_args positional_arguments <- pal$positional_arguments operand <- if (include_any_args) "strict" else "after--only" opt <- getopt_options(object, args, operand) arguments_positional <- character(0) if (include_any_args && length(args)) { oa <- getoperand(opt) if (!is.null(oa)) arguments_positional <- oa } options_list <- parse_options(object, opt, convert_hyphens_to_underscores) if (any(grepl("^help$", names(options_list)))) { if (options_list[["help"]] && print_help_and_exit) { print_help(object) if (is_interactive()) { stop("help requested") } else { quit(status = 0) } } } missing_required <- character(0) for (option in object@options) { if (isTRUE(option@required) && is.null(options_list[[option@dest]])) { missing_required <- c(missing_required, option@long_flag) } } if (length(missing_required)) { missing_required_error_stop(paste( "the following arguments are required:", paste(missing_required, collapse = ", ") )) } if (length(arguments_positional) < min(positional_arguments)) { bad_positional_arguments_error_stop(sprintf( "required at least %g positional arguments, got %g", min(positional_arguments), length(arguments_positional) )) } if (length(arguments_positional) > max(positional_arguments)) { bad_positional_arguments_error_stop(sprintf( "required at most %g positional arguments, got %g", max(positional_arguments), length(arguments_positional) )) } if (include_any_args) { return(list(options = options_list, args = arguments_positional)) } else { return(options_list) } } getopt_options <- function(object, args, operand = "after--only") { # Convert our option specification into ``getopt`` format n_options <- length(object@options) spec <- matrix(NA, nrow = n_options, ncol = 6) for (ii in seq_along(object@options)) { spec[ii, ] <- convert_to_getopt(object@options[[ii]]) } # Pre-seed result with defaults; last default wins for shared dest (matching Python's optparse) defaults <- list() constants <- list() for (ii in seq_along(object@options)) { option <- object@options[[ii]] if (option@action %in% c("store_const", "append_const")) { constants[[sub("^--", "", option@long_flag)]] <- option@const } if (option@action == "callback" || is.null(option@default)) { next } defaults[[option@dest]] <- option@default } if (length(args)) { opt <- getopt( spec = spec, opt = args, operand = operand, defaults = defaults, constants = constants ) } else { opt <- defaults } opt } should_include_any_args <- function(positional_arguments) { # pull out positional arguments if ``positional_arguments`` was set to TRUE # or not 0 or c(0, 0) if (!(length(positional_arguments) %in% 1L:2L)) { stop("positional_arguments must have length 1 or 2") } if (is.logical(positional_arguments)) { if (positional_arguments) { positional_arguments <- c(0, Inf) include_any_args <- TRUE } else { include_any_args <- FALSE } } else if (is.numeric(positional_arguments)) { include_any_args <- TRUE } else { stop("positional_arguments must be logical or numeric") } list(include_any_args = include_any_args, positional_arguments = positional_arguments) } parse_options <- function(object, opt, convert_hyphens_to_underscores) { options_list <- list() for (ii in seq_along(object@options)) { option <- object@options[[ii]] option_value <- opt[[option@dest]] if (option@action == "callback") { if (!is.null(option_value)) { options_list[[option@dest]] <- option_value callback_fn <- function(...) { option@callback(option, option@long_flag, option_value, object, ...) # nolint } options_list[[option@dest]] <- do.call(callback_fn, option@callback_args) } else if (!is.null(option@default)) { options_list[[option@dest]] <- option@default } } else if (!is.null(option_value)) { options_list[[option@dest]] <- option_value } } if (convert_hyphens_to_underscores) { names(options_list) <- gsub("-", "_", names(options_list)) } options_list } #' @rdname parse_args #' @export parse_args2 <- function( object, args = commandArgs(trailingOnly = TRUE), print_help_and_exit = TRUE ) { parse_args( object, args = args, print_help_and_exit = print_help_and_exit, positional_arguments = TRUE, convert_hyphens_to_underscores = TRUE ) } # Converts our representation of options to format getopt can understand convert_to_getopt <- function(object) { short_flag <- sub("^-", "", object@short_flag) long_flag <- sub("^--", "", object@long_flag) action <- if ( object@action %in% c("count", "append", "store_false", "store_const", "append_const") ) { object@action } else if (option_needs_argument(object)) { "store" } else { "store_true" } type <- ifelse(object@type == "NULL", "logical", object@type) return(c(long_flag, short_flag, action, type, object@help, object@dest)) } option_needs_argument <- function(option) { option_needs_argument_helper(option@action, option@type) } option_needs_argument_helper <- function(action, type) { switch(action, store = TRUE, append = TRUE, callback = !(type == "NULL"), FALSE) } optparse/exec/0000755000176200001440000000000015157707221013042 5ustar liggesusersoptparse/exec/display_file.R0000644000176200001440000000256415157707221015640 0ustar liggesusers#!/usr/bin/env Rscript # Copyright 2010-2013 Trevor L Davis # Copyright 2013 Kirill Müller # # This file is free software: you may copy, redistribute and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the License, or (at your # option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . suppressPackageStartupMessages(library("optparse")) parser <- OptionParser(usage = "%prog [options] file") parser <- add_option( parser, c("-n", "--add_numbers"), action = "store_true", default = FALSE, help = "Print line number at the beginning of each line [default]" ) arguments <- parse_args(parser, positional_arguments = 1) opt <- arguments$options file <- arguments$args if (!file.exists(file)) { stop(sprintf("Specified file ( %s ) does not exist", file)) } else { file_text <- readLines(file) } if (opt$add_numbers) { cat(paste(seq_along(file_text), file_text), sep = "\n") } else { cat(file_text, sep = "\n") } optparse/exec/example.R0000644000176200001440000000477715157707221014637 0ustar liggesusers#!/usr/bin/env Rscript # Copyright 2010-2013 Trevor L Davis # Copyright 2008 Allen Day # # This file is free software: you may copy, redistribute and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the License, or (at your # option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . suppressPackageStartupMessages(library("optparse")) suppressPackageStartupMessages(library("stats")) # specify our desired options in a list # by default OptionParser will add an help option equivalent to # make_option(c("-h", "--help"), action="store_true", default=FALSE, # help="Show this help message and exit") parser <- OptionParser() parser <- add_option( parser, c("-v", "--verbose"), action = "store_true", default = TRUE, help = "Print extra output [default %default]" ) parser <- add_option( parser, c("-q", "--quietly"), action = "store_false", dest = "verbose", help = "Print little output" ) parser <- add_option( parser, c("-c", "--count"), type = "integer", default = 5, help = "Number of random normals to generate [default %default]", metavar = "number" ) parser <- add_option( parser, "--generator", default = "rnorm", help = "Function to generate random deviates [default \"%default\"]" ) parser <- add_option( parser, "--mean", default = 0, help = "Mean if generator == \"rnorm\" [default %default]" ) parser <- add_option( parser, "--sd", default = 1, metavar = "standard deviation", help = "Standard deviation if generator == \"rnorm\" [default %default]" ) # get command line options, if help option encountered print help and exit, # otherwise if options not found on command line then set defaults, opt <- parse_args(parser) # print some progress messages to stderr if "quietly" wasn't requested if (opt$verbose) { write("writing some verbose output to standard error...\n", stderr()) } # do some operations based on user input if (opt$generator == "rnorm") { cat(paste(rnorm(opt$count, mean = opt$mean, sd = opt$sd), collapse = "\n")) } else { cat(paste(do.call(opt$generator, list(opt$count)), collapse = "\n")) } cat("\n") optparse/COPYING0000755000176200001440000004313312206447600013152 0ustar liggesusers GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. optparse/vignettes/0000755000176200001440000000000015167740222014125 5ustar liggesusersoptparse/vignettes/optparse.Rmd0000644000176200001440000001140415157707221016427 0ustar liggesusers--- title: "optparse Command Line Option Parsing" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{optparse Command Line Option Parsing} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r echo=FALSE} library("knitr") Rscript_executable <- paste(shQuote(file.path(R.home("bin"), "Rscript")), "--vanilla") opts_knit$set(root.dir = system.file("exec", package = "optparse")) opts_chunk$set(comment = NA, echo = FALSE) list_file_command <- "ls" chmod_command <- "chmod ug+x display_file.R example.R" path_command <- "export PATH=\\$PATH:\\$(pwd)" run_command <- function(string) suppressWarnings(cat(system(string, intern = TRUE), sep = "\n")) ``` optparse is a command line option parser inspired by Python's "optparse" library. Use this with Rscript to write "#!"-shebang scripts that accept short and long flags/options, generate a usage statement, and set default values for options that are not specified on the command line. In our working directory we have two example R scripts, named "example.R" and "display_file.R" illustrating the use of the optparse package. **`r paste("bash$",list_file_command)`** ```{r} run_command(sprintf("%s", list_file_command)) command <- "display_file.R example.R" # to show file ``` In order for a \*nix system to recognize a "#!"-shebang line you need to mark the file executable with the `chmod` command, it also helps to add the directory containing your Rscripts to your path: **`r paste("bash$",chmod_command)`** **`r paste("bash$",path_command)`** Here is what `example.R` contains: **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` ```{r} command <- "example.R --help" # same as system("Rscript example.R -h") ``` By default *optparse* will generate a help message if it encounters `--help` or `-h` on the command line. Note how `%default` in the example program was replaced by the actual default values in the help statement that *optparse* generated. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R" # rely only on defaults ``` If you specify default values when creating your `OptionParser` then *optparse* will use them as expected. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --mean=10 --sd=10 --count=3" ``` Or you can specify your own values. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --quiet -c 4 --generator=\"runif\"" ``` If you remember from the example program that `--quietly` had `action="store_false"` and `dest="verbose"`. This means that `--quietly` is a switch that turns the `verbose` option from its default value of `TRUE` to `FALSE`. Note how the `verbose` and `quietly` options store their value in the exact same variable. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --silent -m 5" ``` If you specify an illegal flag then *optparse* will throw an error. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R -c 100 -c 2 -c 1000 -c 7" ``` If you specify the same option multiple times then *optparse* will use the value of the last option specified. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` *optparse* can also recognize positional arguments if `parse_args` is given the option `positional_arguments = c(min_pa, max_pa)` where `min_pa` is the minimum and `max_pa` is the maximum number of supported positional arguments. (A single numeric corresponds to `min_pa == max_pa`, `TRUE` is equivalent to `c(0, Inf)`, and `FALSE`, the default, is equivalent to `0`.) Below we give an example program *display_file.R*, which is a program that prints out the contents of a single file (the required positional argument, not an optional argument) and which accepts the normal help option as well as an option to add line numbers to the output. Note that the positional arguments need to be placed *after* the optional arguments. ```{r} command <- "display_file.R --help" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R --add_numbers display_file.R" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R non_existent_file.txt" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` optparse/NAMESPACE0000644000176200001440000000050715157670241013340 0ustar liggesusers# 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) export(parse_args2) export(print_help) exportClasses(OptionParser) exportClasses(OptionParserOption) import(methods) optparse/NEWS.md0000644000176200001440000002014515167740175013224 0ustar liggesusersoptparse 1.8.2 ============== New features ------------ * `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. * `add_option()` (and `make_option()`) now support a `const` parameter (intended for new actions `"append_const"` and `"store_const"`). * Several new classed errors are now thrown, mirroring Python's `optparse` exception hierarchy: + `optparse_option_error`: invalid option definition in `make_option()` or `add_option()`. - `optparse_option_conflict_error`: duplicate flag in `OptionParser()` or `add_option()`. + `optparse_parse_error`: existing base class for all parse-time errors from `parse_args()`. - `optparse_bad_option_error`: unrecognized, misused, or argument-requiring option. * `optparse_ambiguous_option_error`: ambiguous abbreviated long flag. - `optparse_bad_positional_arguments_error`: wrong number of positional arguments supplied. - `optparse_missing_required_error`: a required option was not supplied. * `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 -------------------------------- * `parse_args()` (and `parse_args2()`) now correctly handle a bare `--` separator: all arguments after `--` are treated as positional arguments rather than options. * `parse_args()` (and `parse_args2()`) now support abbreviated long flags (e.g. `--verb` matching `--verbose`) when `positional_arguments` is not `FALSE`. Previously abbreviations were only supported when `positional_arguments = FALSE`. * `make_option()` now throws a classed `optparse_option_error` for invalid `action` or `type` arguments instead of a confusing error later at parse time. * `OptionParser()` now also checks the `LITTLER_SCRIPT_PATH` environment variable for the script name when performing `%prog` on the `usage` argument so it works when called from `littler`. optparse 1.7.5 ============== * We no longer coerce the type of an option `default` to match that of its `type` argument when `action = "callback"`. Thanks husheng (@hs3434) for bug report (#47). optparse 1.7.4 ============== * Revises vignette engine specification in the `DESCRIPTION` to suppress new CRAN check NOTE (#43). optparse 1.7.3 ============== * The errors raised by `parse_args()` (and `parse_args2()`) are now of class "optparse\_parse\_error". When `interactive()` is `FALSE` we now print out a usage string followed by a (less verbose) error message. * Throws a more informative error message for unknown short flags when ``positional_arguments=TRUE``. Thanks Greg Minshall for bug report (#42). optparse 1.7.1 ============== * 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 ============== * Throws an error for unknown short flags and long flags when ``positional_arguments=TRUE``. Thanks Greg Minshall for bug report (#34). * If the ``callback`` parameter of ``add_option`` / ``make_option`` is not ``NULL`` then the default of ``action`` is now ``"callback"``. Thanks Greg Minshall for suggestion (#35). * Better documentation of ``action=="callback"`` in the man page for ``add_option`` and ``make_option``. Thanks Greg Minshall for bug report (#35). optparse 1.6.4 ============== * Fixes bug in printing help for ``action=="callback"`` when ``metavar==NULL`` (#29). Thanks Ni Huang for bug report. * Throws an error when passed short flags more than one letter long (#32). Thanks Gautier Richard for bug report. optparse 1.6.2 ============== * Fixs a parsing bug when ``action=="callback"`` and ``positional_argument==TRUE`` (#28). Thanks Ni Huang for bug report. optparse 1.6.1 ============== * Improves accuracy of README (#27). Thanks Alex Penson for bug report. optparse 1.6.0 ============== * Supports callback actions (#26). Thanks Gyu Jin Choi for patch. * If ``interactive() == FALSE`` and ``print_help_and_exit == TRUE`` then ``optparse`` will now call ``quit(status=0)`` instead of ``quit(status=1)`` after printing the help message (this matches behaviour of the python package). * Better error message when forgetting to set ``add_help_option=FALSE`` when defining an ``-h`` or ``--help`` flag. Thanks Jeff P. Bruce for bug report. * Increment ``getopt`` requirement so that empty strings are parsed correctly. Thanks Matthew Flickinger for bug report. optparse 1.4.4 ============== * Minor documentation fixes. Thanks J. J. Ramsey and Daeyoung Kim for bug reports. * Fix bug when ``add_help_option`` in ``OptionParser`` set to ``FALSE``. Thanks to Jeff Bruce for bug report. * ``parse_args`` now supports ``convert_hyphens_to_underscores`` argument which converts any hyphens to underscores when returning the list of options * Now includes the convenience function ``parse_args2`` which wraps ``parse_args`` with ``positional_arguments`` set to ``TRUE`` and ``convert_hyphens_to_underscores`` set to ``TRUE``. optparse 1.3.2 ============== * ``optparse`` should no longer give any warnings when ``options(warnPartialMatchArgs=TRUE)``. Thanks Rich FitzJohn for patch. * ``print_help`` no longer throws an error if we have a default argument of length zero. Thanks Benjamin Tyner for bug report. optparse 1.3.0 ============== * ``OptionParser`` and ``OptionParserOption`` S4 classes are now exported. Thanks Peter Humburg for patch. optparse 1.2.0 ============== * Parameter ``positional_arguments`` of function ``parse_args`` now accepts one or two numeric values that denote the minimum and maximum number of supported positional arguments. Thanks Kirill Müller for patch. * If ``interactive() == TRUE`` then ``parse_args`` will no longer ``quit(status=1)`` after printing a help message but will instead throw an error. ``optparse`` will continue to ``quit(status=1)`` after printing a help message for non-interactive Rscripts unless ``print_help_and_exit == FALSE``. * In ``make_option`` argument ``type="numeric"`` automatically cast to ``double``. Previously users might have received an error passing negative numbers if they accidentally specified "numeric" instead of "double". * Bug fixed in printing usage message for options with default value of NA and a help string including "%default". Thanks Stefan Seemayer for bug report and patch. optparse 1.0.2 ============== * Project website moved to https://github.com/trevorld/optparse * We now replace all occurrences of %prog in usage message (including description and epilogue). Previously we would only replace one occurrence and didn't make replacements in description and epilogue. * Fix bug in ``parse_args`` when we have options with no short flag and positional_arguments=TRUE. Thanks Miroslav Posta for bug report. optparse 1.0.0 ============== * Added `description` and `epilogue` arguments to `OptionParser` to allow users to add more information to generated help messages * Slightly alters the generated usage string to match more closely what the Python module does * No longer exports S4 classes that represent OptionParser and OptionParserOption * Now requires package getopt (>= 1.19) which has also been moved to Imports field from Depends field in DESCRIPTION * Now also Suggests stringr package in DESCRIPTION optparse/inst/0000755000176200001440000000000015167740222013072 5ustar liggesusersoptparse/inst/doc/0000755000176200001440000000000015167740222013637 5ustar liggesusersoptparse/inst/doc/optparse.html0000644000176200001440000003614715167740222016375 0ustar liggesusers optparse Command Line Option Parsing

optparse Command Line Option Parsing

optparse is a command line option parser inspired by Python’s “optparse” library. Use this with Rscript to write “#!”-shebang scripts that accept short and long flags/options, generate a usage statement, and set default values for options that are not specified on the command line.

In our working directory we have two example R scripts, named “example.R” and “display_file.R” illustrating the use of the optparse package.

bash$ ls

display_file.R
example.R

In order for a *nix system to recognize a “#!”-shebang line you need to mark the file executable with the chmod command, it also helps to add the directory containing your Rscripts to your path:

bash$ chmod ug+x display_file.R example.R

bash$ export PATH=$PATH:$(pwd)

Here is what example.R contains:

bash$ display_file.R example.R

#!/usr/bin/env Rscript
# Copyright 2010-2013 Trevor L Davis <trevor.l.davis@gmail.com>
# Copyright 2008 Allen Day
#
#  This file is free software: you may copy, redistribute and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation, either version 2 of the License, or (at your
#  option) any later version.
#
#  This file is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
suppressPackageStartupMessages(library("optparse"))
suppressPackageStartupMessages(library("stats"))

# specify our desired options in a list
# by default OptionParser will add an help option equivalent to
# make_option(c("-h", "--help"), action="store_true", default=FALSE,
#               help="Show this help message and exit")
parser <- OptionParser()
parser <- add_option(
    parser,
    c("-v", "--verbose"),
    action = "store_true",
    default = TRUE,
    help = "Print extra output [default %default]"
)
parser <- add_option(
    parser,
    c("-q", "--quietly"),
    action = "store_false",
    dest = "verbose",
    help = "Print little output"
)
parser <- add_option(
    parser,
    c("-c", "--count"),
    type = "integer",
    default = 5,
    help = "Number of random normals to generate [default %default]",
    metavar = "number"
)
parser <- add_option(
    parser,
    "--generator",
    default = "rnorm",
    help = "Function to generate random deviates [default \"%default\"]"
)
parser <- add_option(
    parser,
    "--mean",
    default = 0,
    help = "Mean if generator == \"rnorm\" [default %default]"
)
parser <- add_option(
    parser,
    "--sd",
    default = 1,
    metavar = "standard deviation",
    help = "Standard deviation if generator == \"rnorm\" [default %default]"
)

# get command line options, if help option encountered print help and exit,
# otherwise if options not found on command line then set defaults,
opt <- parse_args(parser)

# print some progress messages to stderr if "quietly" wasn't requested
if (opt$verbose) {
    write("writing some verbose output to standard error...\n", stderr())
}

# do some operations based on user input
if (opt$generator == "rnorm") {
    cat(paste(rnorm(opt$count, mean = opt$mean, sd = opt$sd), collapse = "\n"))
} else {
    cat(paste(do.call(opt$generator, list(opt$count)), collapse = "\n"))
}
cat("\n")

By default optparse will generate a help message if it encounters --help or -h on the command line. Note how %default in the example program was replaced by the actual default values in the help statement that optparse generated.

bash$ example.R –help

Usage: example.R [options]


Options:
    -h, --help
        Show this help message and exit

    -v, --verbose
        Print extra output [default TRUE]

    -q, --quietly
        Print little output

    -c NUMBER, --count=NUMBER
        Number of random normals to generate [default 5]

    --generator=GENERATOR
        Function to generate random deviates [default "rnorm"]

    --mean=MEAN
        Mean if generator == "rnorm" [default 0]

    --sd=STANDARD DEVIATION
        Standard deviation if generator == "rnorm" [default 1]

If you specify default values when creating your OptionParser then optparse will use them as expected.

bash$ example.R

writing some verbose output to standard error...

1.41264109567518
-0.779564831143886
-1.23622999520547
0.119929588733938
1.42498571408384

Or you can specify your own values.

bash$ example.R –mean=10 –sd=10 –count=3

writing some verbose output to standard error...

12.9747492282234
11.6133792697492
-3.49399887964845

If you remember from the example program that --quietly had action="store_false" and dest="verbose". This means that --quietly is a switch that turns the verbose option from its default value of TRUE to FALSE. Note how the verbose and quietly options store their value in the exact same variable.

bash$ example.R –quiet -c 4 –generator=“runif”

0.720334429992363
0.071449444629252
0.239036649698392
0.265581218758598

If you specify an illegal flag then optparse will throw an error.

bash$ example.R –silent -m 5

Usage: example.R [options]

example.R: error: long flag "silent" is invalid

If you specify the same option multiple times then optparse will use the value of the last option specified.

bash$ example.R -c 100 -c 2 -c 1000 -c 7

writing some verbose output to standard error...

0.797204792397212
-0.182394785369143
-0.04490988099242
0.562906275827394
-0.0443860969096171
0.681366292224717
-0.301278807414258

optparse can also recognize positional arguments if parse_args is given the option positional_arguments = c(min_pa, max_pa) where min_pa is the minimum and max_pa is the maximum number of supported positional arguments. (A single numeric corresponds to min_pa == max_pa, TRUE is equivalent to c(0, Inf), and FALSE, the default, is equivalent to 0.) Below we give an example program display_file.R, which is a program that prints out the contents of a single file (the required positional argument, not an optional argument) and which accepts the normal help option as well as an option to add line numbers to the output. Note that the positional arguments need to be placed after the optional arguments.

bash$ display_file.R –help

Usage: display_file.R [options] file


Options:
    -h, --help
        Show this help message and exit

    -n, --add_numbers
        Print line number at the beginning of each line [default]

bash$ display_file.R –add_numbers display_file.R

1 #!/usr/bin/env Rscript
2 # Copyright 2010-2013 Trevor L Davis <trevor.l.davis@gmail.com>
3 # Copyright 2013 Kirill Müller
4 #
5 #  This file is free software: you may copy, redistribute and/or modify it
6 #  under the terms of the GNU General Public License as published by the
7 #  Free Software Foundation, either version 2 of the License, or (at your
8 #  option) any later version.
9 #
10 #  This file is distributed in the hope that it will be useful, but
11 #  WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 suppressPackageStartupMessages(library("optparse"))
18 
19 parser <- OptionParser(usage = "%prog [options] file")
20 parser <- add_option(
21  parser,
22  c("-n", "--add_numbers"),
23  action = "store_true",
24  default = FALSE,
25  help = "Print line number at the beginning of each line [default]"
26 )
27 
28 arguments <- parse_args(parser, positional_arguments = 1)
29 opt <- arguments$options
30 file <- arguments$args
31 
32 if (!file.exists(file)) {
33  stop(sprintf("Specified file ( %s ) does not exist", file))
34 } else {
35  file_text <- readLines(file)
36 }
37 
38 if (opt$add_numbers) {
39  cat(paste(seq_along(file_text), file_text), sep = "\n")
40 } else {
41  cat(file_text, sep = "\n")
42 }

bash$ display_file.R non_existent_file.txt

Error: Specified file ( non_existent_file.txt ) does not exist
Execution halted

bash$ display_file.R

Usage: display_file.R [options] file

display_file.R: error: required at least 1 positional arguments, got 0
optparse/inst/doc/optparse.R0000644000176200001440000000561315167740222015624 0ustar liggesusers## ----echo=FALSE--------------------------------------------------------------- library("knitr") Rscript_executable <- paste(shQuote(file.path(R.home("bin"), "Rscript")), "--vanilla") opts_knit$set(root.dir = system.file("exec", package = "optparse")) opts_chunk$set(comment = NA, echo = FALSE) list_file_command <- "ls" chmod_command <- "chmod ug+x display_file.R example.R" path_command <- "export PATH=\\$PATH:\\$(pwd)" run_command <- function(string) suppressWarnings(cat(system(string, intern = TRUE), sep = "\n")) ## ----------------------------------------------------------------------------- run_command(sprintf("%s", list_file_command)) command <- "display_file.R example.R" # to show file ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ## ----------------------------------------------------------------------------- command <- "example.R --help" # same as system("Rscript example.R -h") ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R" # rely only on defaults ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --mean=10 --sd=10 --count=3" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --quiet -c 4 --generator=\"runif\"" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --silent -m 5" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R -c 100 -c 2 -c 1000 -c 7" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ## ----------------------------------------------------------------------------- command <- "display_file.R --help" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R --add_numbers display_file.R" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R non_existent_file.txt" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R" ## ----------------------------------------------------------------------------- run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) optparse/inst/doc/optparse.Rmd0000644000176200001440000001140415157707221016141 0ustar liggesusers--- title: "optparse Command Line Option Parsing" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{optparse Command Line Option Parsing} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r echo=FALSE} library("knitr") Rscript_executable <- paste(shQuote(file.path(R.home("bin"), "Rscript")), "--vanilla") opts_knit$set(root.dir = system.file("exec", package = "optparse")) opts_chunk$set(comment = NA, echo = FALSE) list_file_command <- "ls" chmod_command <- "chmod ug+x display_file.R example.R" path_command <- "export PATH=\\$PATH:\\$(pwd)" run_command <- function(string) suppressWarnings(cat(system(string, intern = TRUE), sep = "\n")) ``` optparse is a command line option parser inspired by Python's "optparse" library. Use this with Rscript to write "#!"-shebang scripts that accept short and long flags/options, generate a usage statement, and set default values for options that are not specified on the command line. In our working directory we have two example R scripts, named "example.R" and "display_file.R" illustrating the use of the optparse package. **`r paste("bash$",list_file_command)`** ```{r} run_command(sprintf("%s", list_file_command)) command <- "display_file.R example.R" # to show file ``` In order for a \*nix system to recognize a "#!"-shebang line you need to mark the file executable with the `chmod` command, it also helps to add the directory containing your Rscripts to your path: **`r paste("bash$",chmod_command)`** **`r paste("bash$",path_command)`** Here is what `example.R` contains: **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` ```{r} command <- "example.R --help" # same as system("Rscript example.R -h") ``` By default *optparse* will generate a help message if it encounters `--help` or `-h` on the command line. Note how `%default` in the example program was replaced by the actual default values in the help statement that *optparse* generated. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R" # rely only on defaults ``` If you specify default values when creating your `OptionParser` then *optparse* will use them as expected. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --mean=10 --sd=10 --count=3" ``` Or you can specify your own values. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --quiet -c 4 --generator=\"runif\"" ``` If you remember from the example program that `--quietly` had `action="store_false"` and `dest="verbose"`. This means that `--quietly` is a switch that turns the `verbose` option from its default value of `TRUE` to `FALSE`. Note how the `verbose` and `quietly` options store their value in the exact same variable. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R --silent -m 5" ``` If you specify an illegal flag then *optparse* will throw an error. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "example.R -c 100 -c 2 -c 1000 -c 7" ``` If you specify the same option multiple times then *optparse* will use the value of the last option specified. **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` *optparse* can also recognize positional arguments if `parse_args` is given the option `positional_arguments = c(min_pa, max_pa)` where `min_pa` is the minimum and `max_pa` is the maximum number of supported positional arguments. (A single numeric corresponds to `min_pa == max_pa`, `TRUE` is equivalent to `c(0, Inf)`, and `FALSE`, the default, is equivalent to `0`.) Below we give an example program *display_file.R*, which is a program that prints out the contents of a single file (the required positional argument, not an optional argument) and which accepts the normal help option as well as an option to add line numbers to the output. Note that the positional arguments need to be placed *after* the optional arguments. ```{r} command <- "display_file.R --help" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R --add_numbers display_file.R" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R non_existent_file.txt" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) command <- "display_file.R" ``` **`r paste("bash$",command)`** ```{r} run_command(sprintf("%s %s 2>&1", Rscript_executable, command)) ``` optparse/inst/COPYRIGHTS0000644000176200001440000003143714607642373014526 0ustar liggesusersFormat: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Files: * Copyright: 2010-2024 Trevor L Davis License: GPL-2+ File: exec/example.R Copyright: 2008 Allen Day 2010-2013 Trevor L Davis License: GPL-2+ File: exec/display_file.R Copyright: 2010-2013 Trevor L Davis 2013 Kirill Müller License: GPL-2+ File: NEWS.md Copyright: 2012-2022 Trevor L Davis 2013 Kirill Müller File: inst/tests/test-optparse.R Copyright: 2008 Allen Day 2010-2019 Trevor L Davis 2013 Kirill Müller 2015 Rich FitzJohn 2018 Gyu Jin Choi License: GPL-2+ File: R/optparse-package.R Copyright: 2008 Allen Day 2010-2013 Trevor L Davis License: GPL-2+ File: R/optparse.R Copyright: 1990-2009 Python Software Foundation 2011-2024 Trevor L Davis 2010 Steve Lianoglou 2011 Jim Nikelski 2013 Kirill Müller 2014 Peter Humburg 2015 Rich FitzJohn 2018 Gyu Jin Choi License: GPL-2+ and Python-2.6.2 Comment: The FSF considers recent Python licenses (post Python version 2.1.1) to be GPL-compatible (http://www.gnu.org/licenses/license-list.html#Python). Note that the "Python License" the FSF has on their website (http://directory.fsf.org/wiki?title=License:Python2.0.1) is the full Python license stack which includes the historical modified CNRI and BEOPEN licenses and not merely the PSF License Agreement at the top. In 2001 ago the FSF negotiated with CNRI to change the wording of an earlier Python license (https://www.gnu.org/licenses/license-list.html#PythonOld, http://directory.fsf.org/wiki/License:Python1.6b1) because it had an overly strong "governed in Virginia" clause but later Python license stacks have a version of the CNRI license with a weakened enough clause to satisfy the FSF lawyers as being GPL-compatible. License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA . The full text of the GNU General Public License version 2 can be found in the file COPYING (source) or `R_HOME/share/licenses/GPL-2' (installed). License: Python-2.6.2 PSF LICENSE AGREEMENT FOR PYTHON 2.6.2 . 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 2.6.2 software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.6.2 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright © 2001-2009 Python Software Foundation; All Rights Reserved" are retained in Python 2.6.2 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.6.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.6.2. 4. PSF is making Python 2.6.2 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.6.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.6.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.6.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python 2.6.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. . BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 . BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 . 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). 2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. 3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. 7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. . CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 . 1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright © 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013." 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1. 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. . ACCEPT . CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 . Copyright © 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. . Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. . STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. optparse/README.md0000644000176200001440000001326715161572253013406 0ustar liggesusers# optparse: Command line optional argument parser [![CRAN Status Badge](https://www.r-pkg.org/badges/version/optparse)](https://cran.r-project.org/package=optparse) [![R-CMD-check](https://github.com/trevorld/r-optparse/actions/workflows/R-CMD-check.yaml/badge.svg?branch=master)](https://github.com/trevorld/r-optparse/actions) [![Coverage Status](https://codecov.io/github/trevorld/r-optparse/branch/master/graph/badge.svg)](https://app.codecov.io/github/trevorld/r-optparse?branch=master) [![RStudio CRAN mirror downloads](https://cranlogs.r-pkg.org/badges/optparse)](https://cran.r-project.org/package=optparse) [![Dependencies](https://tinyverse.netlify.app/badge/optparse)](https://tinyverse.netlify.app/) optparse hex sticker A pure R language command line parser inspired by Python's [optparse](https://docs.python.org/3/library/optparse.html) library to be used with `Rscript` to write `#!` shebang scripts that accept short and long flag/options. To install the last version released on CRAN use the following command: install.packages("optparse") To install the development version use the following command: install.packages("remotes") remotes::install_github("trevorld/r-optparse") ## examples A simple example: library("optparse") parser <- OptionParser() |> add_option(c("-v", "--verbose"), action = "store_true", default = TRUE, help = "Print extra output [default]") |> add_option(c("-q", "--quietly"), action = "store_false", dest = "verbose", help = "Print little output") |> add_option(c("-c", "--count"), type = "integer", default = 5, help = "Number of random normals to generate [default %default]", metavar = "number") parse_args(parser, args = c("--quietly", "--count=15")) ## $help ## [1] FALSE ## ## $verbose ## [1] FALSE ## ## $count ## [1] 15 Note that the `args` argument of `parse_args()` default is `commandArgs(trailing=TRUE)` so it typically doesn't need to be explicitly set if writing an Rscript. [optparse](https://github.com/trevorld/r-optparse) automatically creates a help option: parse_args(parser, args = c("--help")) Usage: %prog [options] Options: -h, --help Show this help message and exit -v, --verbose Print extra output [default] -q, --quietly Print little output -c NUMBER, --count=NUMBER Number of random normals to generate [default 5] Error in parse_args(parser, args = c("--help")) : help requested Note by default when `optparse::parse_args()` sees a `--help` flag it will first print out a usage message and then either throw an error in interactive use or call `quit()` in non-interactive use (i.e. when used within an `Rscript` called by a shell). To disable the error/quit set `print_help_and_exit = FALSE` in `parse_args()` and to simply print out the usage string one can also use the function `print_usage()`. [optparse](https://github.com/trevorld/r-optparse) has limited positional argument support, other command-line parsers for R such as [argparse](https://github.com/trevorld/r-argparse) have richer positional argument support: parse_args(parser, args = c("-vc", "25", "75", "22"), positional_arguments = TRUE) ## $options ## $options$help ## [1] FALSE ## ## $options$verbose ## [1] TRUE ## ## $options$count ## [1] 25 ## ## ## $args ## [1] "75" "22" The function `parse_args2` wraps `parse_args` while setting `positional_arguments=TRUE` and `convert_hyphens_to_underscores=TRUE`: parse_args2(parser, args = c("-vc", "25", "75", "22")) ## $options ## $options$help ## [1] FALSE ## ## $options$verbose ## [1] TRUE ## ## $options$count ## [1] 25 ## ## ## $args ## [1] "75" "22" ## other R packages - When [optparse](https://github.com/trevorld/r-optparse) was originally written in 2009 the only option parsing package on CRAN was the comparatively low-level [getopt](https://github.com/trevorld/r-getopt) package but as of 2026 there are *at least* 13 R [R Argument/Option Parser Packages](https://github.com/trevorld/r-cli-pkgs). - Personally I use [optparse](https://github.com/trevorld/r-optparse) for most scripts I write: - It supports the most important features in an argument/option parsing packages with a reasonably high-level interface. - It is well-tested with [high code coverage](https://app.codecov.io/github/trevorld/r-optparse?branch=master) and lots of users with millions of cumulative downloads over the past 15+ years. - It has no dependencies. - It features a stable API with a semantic version number greater than 1.0. - Occasionally I'll also use the [argparse](https://github.com/trevorld/r-argparse) package when I need advanced features unsupported by [optparse](https://github.com/trevorld/r-optparse) like sub parsers and named positional arguments: - In general [argparse](https://github.com/trevorld/r-argparse) supports more advanced features than [optparse](https://github.com/trevorld/r-optparse) but depends on Python and three R packages whereas [optparse](https://github.com/trevorld/r-optparse) is a pure R package with no dependencies. - However, unlike [argparse](https://github.com/trevorld/r-argparse), [optparse](https://github.com/trevorld/r-optparse) does support a callback action and also allows writing custom help usage formatters. optparse/build/0000755000176200001440000000000015167740222013214 5ustar liggesusersoptparse/build/vignette.rds0000644000176200001440000000033515167740222015554 0ustar liggesusersmQ 0nVJB xѵ/xSHݎ\5p@ɳc9;}=! Bp.UKZ,Dn` 7J*p% J) \^ ?ֻjQi/#ӑTڐcV2wϏz5$-54ά琄l{z4N~Ow+D~w-詠SMsn'Uoptparse/man/0000755000176200001440000000000015161544056012671 5ustar liggesusersoptparse/man/OptionParserOption-class.Rd0000644000176200001440000000764315161544056020113 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optparse.R \docType{class} \name{OptionParserOption-class} \alias{OptionParserOption-class} \alias{OptionParserOption} \title{Class to hold information about command-line options} \description{ Class to hold information about command-line options } \section{Slots}{ \describe{ \item{\code{short_flag}}{String of the desired short flag comprised of the \code{-} followed by a single non-dash character (but not \code{=} or a whitespace character).} \item{\code{long_flag}}{String of the desired long flag comprised of \verb{--} followed by a non-dash character and then (optionally) more characters (but not any \code{=} or whitespace characters).} \item{\code{action}}{A character string describing the action \code{optparse} should take when it encounters an option. One of: \itemize{ \item \code{"append"}: appends each occurrence's value to \code{default} (or to an empty vector if \code{default} is \code{NULL}). Returns \code{NULL} if never seen and \code{default} is \code{NULL}. \item \code{"callback"}: stores the return value of the \code{callback} function. \item \code{"count"}: counts the number of times the flag is seen and adds it to \code{default} (treated as \code{0L} if not supplied). Returns \code{NULL} if never seen and no \code{default} was supplied. \item \code{"store"} (default): stores the specified following value. \item \code{"store_const"}: stores \code{const} if the flag is seen, otherwise \code{default}. Returns \code{NULL} if the flag is not seen and \code{default} is \code{NULL}. \item \code{"store_true"}: stores \code{TRUE} if the option is found. \item \code{"store_false"}: stores \code{FALSE} if the option is found. } If \code{callback} is not \code{NULL} the default action is \code{"callback"} otherwise it is \code{"store"}.} \item{\code{type}}{A character string specifying which data type to store: \code{"logical"}, \code{"integer"}, \code{"double"}, \code{"complex"}, or \code{"character"} (\code{"numeric"} is an alias for \code{"double"}). Defaults: \itemize{ \item if \code{action == "count"} then \code{"integer"} \item if \code{action \%in\% c("store_false", "store_true")} then \code{"logical"} \item if \code{action == "store"} and \code{default} is not \code{NULL} then \code{typeof(default)}else if \code{default} is \code{NULL} then \code{"character"} }} \item{\code{dest}}{A character string specifying what field in the list returned by \code{\link[=parse_args]{parse_args()}} should \code{optparse} store the option value. Default is derived from the long flag in \code{opt_str}.} \item{\code{default}}{The default value \code{optparse} should use if it does not find the option on the command line.} \item{\code{const}}{The value to store when \code{action = "store_const"} and the flag is seen. Ignored for all other actions.} \item{\code{required}}{If \code{TRUE}, \code{\link[=parse_args]{parse_args()}} will throw an error if this option is not provided on the command line. \strong{Note:} Required options are generally considered bad form because users expect \emph{options} to be \emph{optional}, and thus they should be avoided when possible.} \item{\code{help}}{A character string describing the option, used by \code{\link[=print_help]{print_help()}} in generating a usage message. \code{"\%default"} will be substituted by the value of \code{default}.} \item{\code{metavar}}{A character string that stands in for the option argument when printing help text. Default is the value of \code{dest}.} \item{\code{callback}}{A function that executes after the option value is fully parsed. Its return value is assigned to the option. Arguments are: the option S4 object, the long flag string, the value of the option, the parser S4 object, and \code{...}.} \item{\code{callback_args}}{A list of additional arguments passed to \code{callback} (via \code{\link[=do.call]{do.call()}}).} }} \seealso{ \code{\link[=make_option]{make_option()}} } optparse/man/OptionParser-class.Rd0000644000176200001440000000267615161544056016723 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optparse.R \docType{class} \name{OptionParser-class} \alias{OptionParser-class} \title{Option Parser} \description{ Option Parser } \section{Slots}{ \describe{ \item{\code{usage}}{The program usage message that will printed out if \code{\link[=parse_args]{parse_args()}} finds a help option, \verb{\\\%prog} is substituted with the value of the \code{prog} argument.} \item{\code{options}}{A list of of \code{OptionParserOption} instances that will define how \code{\link[=parse_args]{parse_args()}} reacts to command line options. \code{OptionParserOption} instances are usually created by \code{\link[=make_option]{make_option()}} and can also be added to an existing \code{OptionParser} instance via the \code{\link[=add_option]{add_option()}} function.} \item{\code{description}}{Additional text for \code{\link[=print_help]{print_help()}} to print out between usage statement and options statement} \item{\code{epilogue}}{Additional text for \code{\link[=print_help]{print_help()}} to print out after the options statement} \item{\code{formatter}}{A function that \code{\link[=print_help]{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{ \link{OptionParserOption} } optparse/man/print_help.Rd0000644000176200001440000000154615161544056015332 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optparse.R \name{print_help} \alias{print_help} \title{Printing an usage message from an OptionParser object} \usage{ print_help(object) } \arguments{ \item{object}{A \code{OptionParser} instance.} } \value{ \code{\link[=print_help]{print_help()}} uses the \code{cat} function to print out a usage message. It returns \code{invisible(NULL)}. } \description{ \code{\link[=print_help]{print_help()}} print an usage message from an OptionParser object, usually called by \code{\link[=parse_args]{parse_args()}} when it encounters a help option. } \references{ Python's \code{optparse} library, which inspired this package, is described here: \url{https://docs.python.org/3/library/optparse.html} } \seealso{ \code{\link[=parse_args]{parse_args()}} \code{\link[=OptionParser]{OptionParser()}} } optparse/man/optparse-package.Rd0000644000176200001440000000417414607642373016421 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optparse-package.R \docType{package} \name{optparse-package} \alias{optparse-package} \alias{optparse} \title{Command line option parser} \description{ Goal is to create an R package of a command line parser inspired by Python's \dQuote{optparse} library. } \details{ \code{optparse} is primarily intended to be used with \dQuote{Rscript}. It facilitates writing \dQuote{#!} shebang scripts that accept short and long flags/options. It can also be used from directly, but is probably less useful in this context. See package vignette for a more detailed example. Notes on naming convention in package: 1. An option is one of the shell-split input strings. 2. A flag is a type of option. a flag can be defined as having no argument (defined below), a required argument, or an optional argument. 3. An argument is a type of option, and is the value associated with a flag. 4. A long flag is a type of flag, and begins with the string \dQuote{--}. If the long flag has an associated argument, it may be delimited from the long flag 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. \%\%\% } \examples{ example_file <- system.file("exec", "example.R", package = "optparse") example_file_2 <- system.file("exec", "display_file.R", package = "optparse") \dontrun{ readLines(example_file) readLines(example_file_2) } } \references{ Python's \code{optparse} library, which this package is based on, is described here: \url{https://docs.python.org/3/library/optparse.html} } \seealso{ \code{\link[getopt]{getopt}} } \author{ Trevor L. Davis. Some documentation and unit tests ported from Allen Day's getopt package. The documentation for Python's optparse library, which this package is based on, is Copyright 1990-2009, Python Software Foundation. } \keyword{package} optparse/man/parse_args.Rd0000644000176200001440000001112315161544056015304 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optparse.R \encoding{latin1} \name{parse_args} \alias{parse_args} \alias{parse_args2} \title{Parse command line options.} \usage{ parse_args( object, args = commandArgs(trailingOnly = TRUE), print_help_and_exit = TRUE, positional_arguments = FALSE, convert_hyphens_to_underscores = FALSE ) parse_args2( object, args = commandArgs(trailingOnly = TRUE), print_help_and_exit = TRUE ) } \arguments{ \item{object}{An \code{OptionParser} instance.} \item{args}{A character vector containing command line options to be parsed. Default is everything after the Rscript program in the command line. If \code{positional_arguments} is not \code{FALSE} then \code{\link[=parse_args]{parse_args()}} will look for positional arguments at the end of this vector.} \item{print_help_and_exit}{Whether \code{\link[=parse_args]{parse_args()}} should call \code{\link[=print_help]{print_help()}} to print out a usage message and exit the program. Default is \code{TRUE}.} \item{positional_arguments}{Number of \emph{positional} arguments. A numeric denoting the exact number of supported arguments, or a numeric vector of length two denoting the minimum and maximum number of arguments (\code{Inf} for no limit). The value \code{TRUE} is equivalent to \code{c(0, Inf)}. The default \code{FALSE} is supported for backward compatibility only, as it alters the format of the return value.} \item{convert_hyphens_to_underscores}{If the names in the returned list of options contains hyphens then convert them to underscores. The default \code{FALSE} is supported for backward compatibility reasons as it alters the format of the return value} } \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. } \description{ \code{\link[=parse_args]{parse_args()}} parses command line options using an \code{OptionParser} instance for guidance. \code{\link[=parse_args2]{parse_args2()}} is a wrapper to \code{\link[=parse_args]{parse_args()}} setting the options \code{positional_arguments} and \code{convert_hyphens_to_underscores} to \code{TRUE}. } \section{Errors}{ The following classed errors may be thrown: \itemize{ \item \code{optparse_parse_error}: base class for all parse-time errors. \itemize{ \item \code{optparse_bad_option_error}: unrecognized, misused, or argument-requiring option. \itemize{ \item \code{optparse_ambiguous_option_error}: ambiguous abbreviated long flag. } \item \code{optparse_bad_positional_arguments_error}: wrong number of positional arguments supplied. \item \code{optparse_missing_required_error}: a required option was not supplied. } } } \examples{ # example from vignette option_list <- list( make_option(c("-v", "--verbose"), action = "store_true", default = TRUE, help = "Print extra output [default]"), make_option(c("-q", "--quietly"), action = "store_false", dest = "verbose", help = "Print little output"), make_option(c("-c", "--count"), type = "integer", default = 5, help = "Number of random normals to generate [default \%default]", metavar = "number"), make_option("--generator", default = "rnorm", help = "Function to generate random deviates [default \"\%default\"]"), make_option("--mean", default = 0, help = "Mean if generator == \"rnorm\" [default \%default]"), make_option("--sd", default = 1, metavar = "standard deviation", help = "Standard deviation if generator == \"rnorm\" [default \%default]") ) parse_args(OptionParser(option_list = option_list), args = c("--sd=3", "--quietly")) # example from vignette using positional arguments option_list2 <- list( make_option(c("-n", "--add-numbers"), action = "store_true", default = FALSE, help = "Print line number at the beginning of each line [default]") ) parser <- OptionParser(usage = "\%prog [options] file", option_list = option_list2) parse_args(parser, args = c("--add-numbers", "example.txt"), positional_arguments = TRUE) parse_args(parser, args = c("--add-numbers", "example.txt"), positional_arguments = TRUE, convert_hyphens_to_underscores = TRUE) parse_args2(parser, args = c("--add-numbers", "example.txt")) } \references{ Python's \code{optparse} library, which inspired this package, is described here: \url{https://docs.python.org/3/library/optparse.html} } \seealso{ \code{\link[=OptionParser]{OptionParser()}} \code{\link[=print_help]{print_help()}} } optparse/man/figures/0000755000176200001440000000000014127751625014340 5ustar liggesusersoptparse/man/figures/logo.svg0000644000176200001440000000354114130077664016022 0ustar liggesusers optparse/man/figures/logo.png0000644000176200001440000000201014130077664015775 0ustar liggesusersPNG  IHDR PLTEBRj~tRNSDP! pHYs  ~IDATx[ P/zГ/%tږ?jx]xO!ZCgL{\Yz d˟مV/,1uYiCVn}TV֛6Hde-WU#42+ŊO-W+2mveAh"x7M&ʊCY̍vbyY4 i m'=͌eL3uɌYV4M?!S.Xz4wo2ZօE"A\笯ZHV˚,,O ja»x*- Be՟2+Kj!e=)5yJ.OĔcur4`SPrӻnnC%`|8:[Ca>0a ~? ``F``÷N o_ـ-o/`&$L {Pj0A{Pj0A{Pja*nlP `ր A710#΍ [60nkUm ؠTq5`*nlP `oY|nH]`s$)8`ac\auF>i1ma0?w}vqob<`Tf㰸ϣe4>+4mUد~eW̛& HbIJUY!-Kr鱊),אRa9,X4+eIeYկ)LY4O"͛UtVm4q#K"F*RdEd,Ң)-jaZȴB]uA2IjedUK\= 2) Copyright: See file (inst/)COPYRIGHTS. URL: https://github.com/trevorld/r-optparse, https://trevorldavis.com/R/optparse/ BugReports: https://github.com/trevorld/r-optparse/issues LazyLoad: yes Depends: R (>= 3.6.0) Imports: methods Suggests: knitr (>= 1.15.19), rmarkdown, stringr, testthat Config/testthat/edition: 3 VignetteBuilder: knitr, rmarkdown RoxygenNote: 7.3.3 NeedsCompilation: no Packaged: 2026-04-15 16:45:06 UTC; trevorld Author: Trevor L. Davis [aut, cre] (ORCID: ), Allen Day [aut] (Code and documentation ported from the getopt package.), Python Software Foundation [ctb] (Some documentation from the optparse Python module.), Steve Lianoglou [ctb], Jim Nikelski [ctb], Kirill Müller [ctb], Peter Humburg [ctb], Rich FitzJohn [ctb], Gyu Jin Choi [ctb] Maintainer: Trevor L. Davis Repository: CRAN Date/Publication: 2026-04-17 07:10:02 UTC