docopt/0000755000176200001440000000000013674611673011560 5ustar liggesusersdocopt/NAMESPACE0000644000176200001440000000022113674446016012767 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(print,docopt) export(docopt) import(methods) importFrom(utils,str) importFrom(utils,tail) docopt/LICENSE0000644000176200001440000000007713671356716012572 0ustar liggesusersYEAR: 2015 COPYRIGHT HOLDER: Vladimir Keleshev, Edwin de Jonge docopt/man/0000755000176200001440000000000013671664652012335 5ustar liggesusersdocopt/man/as.character-Pattern-method.Rd0000644000176200001440000000044713671664652020060 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Pattern.R \name{as.character,Pattern-method} \alias{as.character,Pattern-method} \title{as.character.Pattern} \usage{ \S4method{as.character}{Pattern}(x, ...) } \description{ as.character.Pattern } \keyword{internal} docopt/man/subset-Tokens-method.Rd0000644000176200001440000000037513671664652016655 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Tokens.R \name{[<-,Tokens-method} \alias{[<-,Tokens-method} \title{index tokens} \usage{ \S4method{[}{Tokens}(x, i) <- value } \description{ index tokens } \keyword{internal} docopt/man/docopt.Rd0000644000176200001440000000360713671664652014122 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docopt.R \name{docopt} \alias{docopt} \title{Parse \code{args} based on command-line interface described in \code{doc}.} \usage{ docopt( doc, args = commandArgs(TRUE), name = NULL, help = TRUE, version = NULL, strict = FALSE, strip_names = !strict, quoted_args = !strict ) } \arguments{ \item{doc}{\code{character} vector with command line specification} \item{args}{\code{character} vector of commandline arguments. If \code{args} is missing \code{commandArgs(trailingOnly=TRUE)} will be used.} \item{name}{Currently not used} \item{help}{\code{logical} should "-h" or "--help" generate a usage string?} \item{version}{\code{character}. If supplied the option "-v" generates the given version number and stops.} \item{strict}{\code{logical} if \code{TRUE} docopt will conform to docopt.py in and output (\code{strip_names=FALSE} and \code{quoted_args=FALSE})} \item{strip_names}{if \code{TRUE} it will remove dashes and angles from the resulting names and add these to the resulting list. Note that this is different from docopt standard!} \item{quoted_args}{if \code{TRUE} it will accept quoted arguments. Note that this is different from docopt standard!} } \value{ named list with all parsed options, arguments and commands. } \description{ \code{docopt} creates your command-line interface based on its description that you pass as \code{doc}. Such description can contain --options, , commands, which could be [optional], (required), (mutually | exclusive) or repeated... } \examples{ "Usage: my_program.R [-hso FILE] [--quiet | --verbose] [INPUT ...] -h --help show this -s --sorted sorted output -o FILE specify output file [default: ./test.txt] --quiet print less text --verbose print more text" -> doc docopt(doc, "-s --quiet") } \references{ \url{http://docopt.org}, } docopt/man/sub-Tokens-method.Rd0000644000176200001440000000037513671664652016141 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Tokens.R \name{[,Tokens-method} \alias{[,Tokens-method} \title{index tokens} \usage{ \S4method{[}{Tokens}(x, i, drop = TRUE) } \description{ index tokens } \keyword{internal} docopt/man/as.character-Tokens-method.Rd0000644000176200001440000000042313671664652017700 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Tokens.R \name{as.character,Tokens-method} \alias{as.character,Tokens-method} \title{to character} \usage{ \S4method{as.character}{Tokens}(x, ...) } \description{ to character } \keyword{internal} docopt/man/docopt-package.Rd0000644000176200001440000000056313671356716015510 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pkg.R \docType{package} \name{docopt-package} \alias{docopt-package} \title{Docopt command line specification} \description{ docopt helps you to define an interface for your command-line app, and automatically generate a parser for it. } \details{ For more information see http://docopt.org } docopt/DESCRIPTION0000644000176200001440000000113113674611673013262 0ustar liggesusersPackage: docopt Type: Package Title: Command-Line Interface Specification Language Version: 0.7.1 Author: Edwin de Jonge (edwindjonge@gmail.com) Maintainer: Edwin de Jonge Description: Define a command-line interface by just giving it a description in the specific format. License: MIT + file LICENSE URL: https://github.com/docopt/docopt.R BugReports: https://github.com/docopt/docopt.R/issues Imports: methods Suggests: testthat RoxygenNote: 7.1.0 NeedsCompilation: no Packaged: 2020-06-23 18:38:08 UTC; edwindj Repository: CRAN Date/Publication: 2020-06-24 08:50:03 UTC docopt/tests/0000755000176200001440000000000013671664652012724 5ustar liggesusersdocopt/tests/testthat/0000755000176200001440000000000013674611673014562 5ustar liggesusersdocopt/tests/testthat/test-issues.R0000644000176200001440000000345313672152700017167 0ustar liggesuserscontext("Issues") test_that("quoted arguments work (#2)", { doc <- " Usage: exampleScript " opt <- docopt(doc, "\"quoted arg\"") expect_equal(opt$arg1, "quoted arg") }) test_that("quoted arguments work (#4)", { doc <- 'Usage: do.R [...]' opt <- docopt(doc, "some_directory '--quoted test'", quoted_args=T ) expect_equal(opt$other, "--quoted test") }) test_that("multivalued options work (#8)",{ " Usage: install.r [-r repo]... Options: -r=repo Repository " -> doc opt <- docopt(doc, "-r repo1 -r repo2") expect_equal(opt$r, c("repo1", "repo2")) }) test_that("strings containing spaces are passed correctly (#11)", { " Usage: foo.R [-i ] Options: -i , --integers= Integers [default: 1] " -> doc opt <- docopt(doc, "-i ' c(1, 8)'") expect_equal(opt$integers, " c(1, 8)") }) test_that("quoted options are ok (#19)",{ ' Usage: style_files [--arg=] ... Options: --arg= Package where the style guide is stored [default: Arg1]. ' -> doc arguments <- docopt::docopt(doc, "--arg='bla bla' f1") expect_equal(arguments$arg, "bla bla") expect_equal(arguments$files, "f1") }) test_that("kebab case option to snake case",{ ' Usage: foo.R Options: --do-the-thing= Do the Thing! [default: yeah]. ' -> doc opt <- docopt::docopt(doc) expect_equal(names(opt), c("--do-the-thing", "do_the_thing")) }) test_that("quotes inside options are preserved",{ "style files. Usage: style_files [--arg=] ... Options: --arg= Package where the style guide is stored [default: Arg1]. " -> doc # expected behavior opt = docopt(doc, c("--arg='tidyverse_style(scope= \"none\")'", "R/test.R")) expect_equal(opt$arg, "tidyverse_style(scope= \"none\")") }) docopt/tests/testthat/test-quotedargs.R0000644000176200001440000000115613671664652020045 0ustar liggesuserscontext("Issues") test_that("quoted arguments work (#2)", { doc <- " Usage: exampleScript " opt <- docopt(doc, "\"quoted arg\"") expect_equal(opt$arg1, "quoted arg") }) test_that("quoted arguments work (#4)", { doc <- 'Usage: do.R [...]' opt <- docopt(doc, "some_directory '--quoted test'", quoted_args=T ) expect_equal(opt$other, "--quoted test") }) test_that("multivalued options work (#8)",{ " Usage: install.r [-r repo]... Options: -r=repo Repository " -> doc opt <- docopt(doc, "-r repo1 -r repo2") expect_equal(opt$r, c("repo1", "repo2")) })docopt/tests/testthat/test-specs.R0000644000176200001440000013725413671664652017015 0ustar liggesusers ##################### context('doc01') doc <- 'Usage: prog' test_that('parsing "" works',{ #$ prog #{} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 0) expect_equivalent(res[NULL], list()) }) test_that('parsing "--xxx" works',{ #$ prog --xxx #"user-error" expect_error(docopt(doc, '--xxx', strict=TRUE)) }) ##################### context('doc02') doc <- 'Usage: prog [options] Options: -a All.' test_that('parsing "" works',{ #$ prog #{"-a": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-a"], list("-a" = FALSE)) }) test_that('parsing "-a" works',{ #$ prog -a #{"-a": true} res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-a"], list("-a" = TRUE)) }) test_that('parsing "-x" works',{ #$ prog -x #"user-error" expect_error(docopt(doc, '-x', strict=TRUE)) }) ##################### context('doc03') doc <- 'Usage: prog [options] Options: --all All.' test_that('parsing "" works',{ #$ prog #{"--all": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--all"], list("--all" = FALSE)) }) test_that('parsing "--all" works',{ #$ prog --all #{"--all": true} res <- docopt(doc, '--all', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--all"], list("--all" = TRUE)) }) test_that('parsing "--xxx" works',{ #$ prog --xxx #"user-error" expect_error(docopt(doc, '--xxx', strict=TRUE)) }) ##################### context('doc04') doc <- 'Usage: prog [options] Options: -v, --verbose Verbose.' test_that('parsing "--verbose" works',{ #$ prog --verbose #{"--verbose": true} res <- docopt(doc, '--verbose', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--verbose"], list("--verbose" = TRUE)) }) test_that('parsing "--ver" works',{ #$ prog --ver #{"--verbose": true} res <- docopt(doc, '--ver', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--verbose"], list("--verbose" = TRUE)) }) test_that('parsing "-v" works',{ #$ prog -v #{"--verbose": true} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--verbose"], list("--verbose" = TRUE)) }) ##################### context('doc05') doc <- 'Usage: prog [options] Options: -p PATH' test_that('parsing "-p home/" works',{ #$ prog -p home/ #{"-p": "home/"} res <- docopt(doc, '-p home/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-p"], list("-p" = "home/")) }) test_that('parsing "-phome/" works',{ #$ prog -phome/ #{"-p": "home/"} res <- docopt(doc, '-phome/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-p"], list("-p" = "home/")) }) test_that('parsing "-p" works',{ #$ prog -p #"user-error" expect_error(docopt(doc, '-p', strict=TRUE)) }) ##################### context('doc06') doc <- 'Usage: prog [options] Options: --path ' test_that('parsing "--path home/" works',{ #$ prog --path home/ #{"--path": "home/"} res <- docopt(doc, '--path home/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "home/")) }) test_that('parsing "--path=home/" works',{ #$ prog --path=home/ #{"--path": "home/"} res <- docopt(doc, '--path=home/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "home/")) }) test_that('parsing "--pa home/" works',{ #$ prog --pa home/ #{"--path": "home/"} res <- docopt(doc, '--pa home/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "home/")) }) test_that('parsing "--pa=home/" works',{ #$ prog --pa=home/ #{"--path": "home/"} res <- docopt(doc, '--pa=home/', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "home/")) }) test_that('parsing "--path" works',{ #$ prog --path #"user-error" expect_error(docopt(doc, '--path', strict=TRUE)) }) ##################### context('doc07') doc <- 'Usage: prog [options] Options: -p PATH, --path= Path to files.' test_that('parsing "-proot" works',{ #$ prog -proot #{"--path": "root"} res <- docopt(doc, '-proot', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "root")) }) ##################### context('doc08') doc <- 'Usage: prog [options] Options: -p --path PATH Path to files.' test_that('parsing "-p root" works',{ #$ prog -p root #{"--path": "root"} res <- docopt(doc, '-p root', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "root")) }) test_that('parsing "--path root" works',{ #$ prog --path root #{"--path": "root"} res <- docopt(doc, '--path root', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "root")) }) ##################### context('doc09') doc <- 'Usage: prog [options] Options: -p PATH Path to files [default: ./]' test_that('parsing "" works',{ #$ prog #{"-p": "./"} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-p"], list("-p" = "./")) }) test_that('parsing "-phome" works',{ #$ prog -phome #{"-p": "home"} res <- docopt(doc, '-phome', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-p"], list("-p" = "home")) }) ##################### context('doc10') doc <- 'UsAgE: prog [options] OpTiOnS: --path= Path to files [dEfAuLt: /root]' test_that('parsing "" works',{ #$ prog #{"--path": "/root"} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "/root")) }) test_that('parsing "--path=home" works',{ #$ prog --path=home #{"--path": "home"} res <- docopt(doc, '--path=home', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--path"], list("--path" = "home")) }) ##################### context('doc11') doc <- 'usage: prog [options] options: -a Add -r Remote -m Message' test_that('parsing "-a -r -m Hello" works',{ #$ prog -a -r -m Hello #{"-a": true, "-r": true, "-m": "Hello"} res <- docopt(doc, '-a -r -m Hello', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-a", "-r", "-m")], list("-a" = TRUE, "-r" = TRUE, "-m" = "Hello")) }) test_that('parsing "-armyourass" works',{ #$ prog -armyourass #{"-a": true, "-r": true, "-m": "yourass"} res <- docopt(doc, '-armyourass', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-a", "-r", "-m")], list("-a" = TRUE, "-r" = TRUE, "-m" = "yourass")) }) test_that('parsing "-a -r" works',{ #$ prog -a -r #{"-a": true, "-r": true, "-m": null} res <- docopt(doc, '-a -r', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-a", "-r", "-m")], list("-a" = TRUE, "-r" = TRUE, "-m" = NULL)) }) ##################### context('doc12') doc <- 'Usage: prog [options] Options: --version --verbose' test_that('parsing "--version" works',{ #$ prog --version #{"--version": true, "--verbose": false} res <- docopt(doc, '--version', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--version", "--verbose")], list("--version" = TRUE, "--verbose" = FALSE)) }) test_that('parsing "--verbose" works',{ #$ prog --verbose #{"--version": false, "--verbose": true} res <- docopt(doc, '--verbose', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--version", "--verbose")], list("--version" = FALSE, "--verbose" = TRUE)) }) test_that('parsing "--ver" works',{ #$ prog --ver #"user-error" expect_error(docopt(doc, '--ver', strict=TRUE)) }) test_that('parsing "--verb" works',{ #$ prog --verb #{"--version": false, "--verbose": true} res <- docopt(doc, '--verb', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--version", "--verbose")], list("--version" = FALSE, "--verbose" = TRUE)) }) ##################### context('doc13') doc <- 'usage: prog [-a -r -m ] options: -a Add -r Remote -m Message' test_that('parsing "-armyourass" works',{ #$ prog -armyourass #{"-a": true, "-r": true, "-m": "yourass"} res <- docopt(doc, '-armyourass', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-a", "-r", "-m")], list("-a" = TRUE, "-r" = TRUE, "-m" = "yourass")) }) ##################### context('doc14') doc <- 'usage: prog [-armmsg] options: -a Add -r Remote -m Message' test_that('parsing "-a -r -m Hello" works',{ #$ prog -a -r -m Hello #{"-a": true, "-r": true, "-m": "Hello"} res <- docopt(doc, '-a -r -m Hello', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-a", "-r", "-m")], list("-a" = TRUE, "-r" = TRUE, "-m" = "Hello")) }) ##################### context('doc15') doc <- 'usage: prog -a -b options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #{"-a": true, "-b": true} res <- docopt(doc, '-a -b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-b -a" works',{ #$ prog -b -a #{"-a": true, "-b": true} res <- docopt(doc, '-b -a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-a" works',{ #$ prog -a #"user-error" expect_error(docopt(doc, '-a', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc16') doc <- 'usage: prog (-a -b) options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #{"-a": true, "-b": true} res <- docopt(doc, '-a -b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-b -a" works',{ #$ prog -b -a #{"-a": true, "-b": true} res <- docopt(doc, '-b -a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-a" works',{ #$ prog -a #"user-error" expect_error(docopt(doc, '-a', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc17') doc <- 'usage: prog [-a] -b options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #{"-a": true, "-b": true} res <- docopt(doc, '-a -b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-b -a" works',{ #$ prog -b -a #{"-a": true, "-b": true} res <- docopt(doc, '-b -a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-a" works',{ #$ prog -a #"user-error" expect_error(docopt(doc, '-a', strict=TRUE)) }) test_that('parsing "-b" works',{ #$ prog -b #{"-a": false, "-b": true} res <- docopt(doc, '-b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = FALSE, "-b" = TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc18') doc <- 'usage: prog [(-a -b)] options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #{"-a": true, "-b": true} res <- docopt(doc, '-a -b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-b -a" works',{ #$ prog -b -a #{"-a": true, "-b": true} res <- docopt(doc, '-b -a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = TRUE)) }) test_that('parsing "-a" works',{ #$ prog -a #"user-error" expect_error(docopt(doc, '-a', strict=TRUE)) }) test_that('parsing "-b" works',{ #$ prog -b #"user-error" expect_error(docopt(doc, '-b', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #{"-a": false, "-b": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = FALSE, "-b" = FALSE)) }) ##################### context('doc19') doc <- 'usage: prog (-a|-b) options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #"user-error" expect_error(docopt(doc, '-a -b', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) test_that('parsing "-a" works',{ #$ prog -a #{"-a": true, "-b": false} res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = FALSE)) }) test_that('parsing "-b" works',{ #$ prog -b #{"-a": false, "-b": true} res <- docopt(doc, '-b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = FALSE, "-b" = TRUE)) }) ##################### context('doc20') doc <- 'usage: prog [ -a | -b ] options: -a -b' test_that('parsing "-a -b" works',{ #$ prog -a -b #"user-error" expect_error(docopt(doc, '-a -b', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #{"-a": false, "-b": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = FALSE, "-b" = FALSE)) }) test_that('parsing "-a" works',{ #$ prog -a #{"-a": true, "-b": false} res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = FALSE)) }) test_that('parsing "-b" works',{ #$ prog -b #{"-a": false, "-b": true} res <- docopt(doc, '-b', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = FALSE, "-b" = TRUE)) }) ##################### context('doc21') doc <- 'usage: prog ' test_that('parsing "10" works',{ #$ prog 10 #{"": "10"} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = "10")) }) test_that('parsing "10 20" works',{ #$ prog 10 20 #"user-error" expect_error(docopt(doc, '10 20', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc22') doc <- 'usage: prog []' test_that('parsing "10" works',{ #$ prog 10 #{"": "10"} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = "10")) }) test_that('parsing "10 20" works',{ #$ prog 10 20 #"user-error" expect_error(docopt(doc, '10 20', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #{"": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = NULL)) }) ##################### context('doc23') doc <- 'usage: prog ' test_that('parsing "10 20 40" works',{ #$ prog 10 20 40 #{"": "10", "": "20", "": "40"} res <- docopt(doc, '10 20 40', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "", "")], list("" = "10", "" = "20", "" = "40")) }) test_that('parsing "10 20" works',{ #$ prog 10 20 #"user-error" expect_error(docopt(doc, '10 20', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc24') doc <- 'usage: prog [ ]' test_that('parsing "10 20 40" works',{ #$ prog 10 20 40 #{"": "10", "": "20", "": "40"} res <- docopt(doc, '10 20 40', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "", "")], list("" = "10", "" = "20", "" = "40")) }) test_that('parsing "10 20" works',{ #$ prog 10 20 #{"": "10", "": "20", "": null} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "", "")], list("" = "10", "" = "20", "" = NULL)) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc25') doc <- 'usage: prog [ | ]' test_that('parsing "10 20 40" works',{ #$ prog 10 20 40 #"user-error" expect_error(docopt(doc, '10 20 40', strict=TRUE)) }) test_that('parsing "20 40" works',{ #$ prog 20 40 #{"": null, "": "20", "": "40"} res <- docopt(doc, '20 40', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "", "")], list("" = NULL, "" = "20", "" = "40")) }) test_that('parsing "" works',{ #$ prog #{"": null, "": null, "": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "", "")], list("" = NULL, "" = NULL, "" = NULL)) }) ##################### context('doc26') doc <- 'usage: prog ( --all | ) options: --all' test_that('parsing "10 --all" works',{ #$ prog 10 --all #{"": "10", "--all": true, "": null} res <- docopt(doc, '10 --all', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "--all", "")], list("" = "10", "--all" = TRUE, "" = NULL)) }) test_that('parsing "10" works',{ #$ prog 10 #{"": null, "--all": false, "": "10"} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("", "--all", "")], list("" = NULL, "--all" = FALSE, "" = "10")) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc27') doc <- 'usage: prog [ ]' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #{"": ["10"]} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = "10")) }) test_that('parsing "" works',{ #$ prog #{"": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = list())) }) ##################### context('doc28') doc <- 'usage: prog [( )]' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #"user-error" expect_error(docopt(doc, '10', strict=TRUE)) }) test_that('parsing "" works',{ #$ prog #{"": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = list())) }) ##################### context('doc29') doc <- 'usage: prog NAME...' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"NAME": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #{"NAME": ["10"]} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = "10")) }) test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) ##################### context('doc30') doc <- 'usage: prog [NAME]...' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"NAME": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #{"NAME": ["10"]} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = "10")) }) test_that('parsing "" works',{ #$ prog #{"NAME": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = list())) }) ##################### context('doc31') doc <- 'usage: prog [NAME...]' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"NAME": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #{"NAME": ["10"]} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = "10")) }) test_that('parsing "" works',{ #$ prog #{"NAME": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = list())) }) ##################### context('doc32') doc <- 'usage: prog [NAME [NAME ...]]' test_that('parsing "10 20" works',{ #$ prog 10 20 #{"NAME": ["10", "20"]} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = c("10", "20"))) }) test_that('parsing "10" works',{ #$ prog 10 #{"NAME": ["10"]} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = "10")) }) test_that('parsing "" works',{ #$ prog #{"NAME": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = list())) }) ##################### context('doc33') doc <- 'usage: prog (NAME | --foo NAME) options: --foo' test_that('parsing "10" works',{ #$ prog 10 #{"NAME": "10", "--foo": false} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("NAME", "--foo")], list(NAME = "10", "--foo" = FALSE)) }) test_that('parsing "--foo 10" works',{ #$ prog --foo 10 #{"NAME": "10", "--foo": true} res <- docopt(doc, '--foo 10', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("NAME", "--foo")], list(NAME = "10", "--foo" = TRUE)) }) test_that('parsing "--foo=10" works',{ #$ prog --foo=10 #"user-error" expect_error(docopt(doc, '--foo=10', strict=TRUE)) }) ##################### context('doc34') doc <- 'usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar' test_that('parsing "10" works',{ #$ prog 10 #{"NAME": ["10"], "--foo": false, "--bar": false} res <- docopt(doc, '10', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("NAME", "--foo", "--bar")], list(NAME = "10", "--foo" = FALSE, "--bar" = FALSE)) }) test_that('parsing "10 20" works',{ #$ prog 10 20 #{"NAME": ["10", "20"], "--foo": false, "--bar": false} res <- docopt(doc, '10 20', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("NAME", "--foo", "--bar")], list(NAME = c("10", "20"), "--foo" = FALSE, "--bar" = FALSE)) }) test_that('parsing "--foo --bar" works',{ #$ prog --foo --bar #{"NAME": [], "--foo": true, "--bar": true} res <- docopt(doc, '--foo --bar', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("NAME", "--foo", "--bar")], list(NAME = list(), "--foo" = TRUE, "--bar" = TRUE)) }) ##################### context('doc35') doc <- 'Naval Fate. Usage: prog ship new ... prog ship [] move [--speed=] prog ship shoot prog mine (set|remove) [--moored|--drifting] prog -h | --help prog --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Mored (anchored) mine. --drifting Drifting mine.' test_that('parsing "ship Guardian move 150 300 --speed=20" works',{ #$ prog ship Guardian move 150 300 --speed=20 #{"--drifting": false, "--help": false, "--moored": false, "--speed": "20", "--version": false, "": ["Guardian"], "": "150", "": "300", "mine": false, "move": true, "new": false, "remove": false, "set": false, "ship": true, "shoot": false} res <- docopt(doc, 'ship Guardian move 150 300 --speed=20', strict=TRUE) expect_equivalent(length(res), 15) expect_equivalent(res[c("--drifting", "--help", "--moored", "--speed", "--version","", "", "", "mine", "move", "new", "remove", "set", "ship", "shoot")], list("--drifting" = FALSE, "--help" = FALSE, "--moored" = FALSE, "--speed" = "20", "--version" = FALSE, "" = "Guardian", "" = "150", "" = "300", mine = FALSE, move = TRUE, new = FALSE, remove = FALSE, set = FALSE, ship = TRUE, shoot = FALSE)) }) ##################### context('doc36') doc <- 'usage: prog --hello' test_that('parsing "--hello" works',{ #$ prog --hello #{"--hello": true} res <- docopt(doc, '--hello', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = TRUE)) }) ##################### context('doc37') doc <- 'usage: prog [--hello=]' test_that('parsing "" works',{ #$ prog #{"--hello": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = NULL)) }) test_that('parsing "--hello wrld" works',{ #$ prog --hello wrld #{"--hello": "wrld"} res <- docopt(doc, '--hello wrld', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = "wrld")) }) ##################### context('doc38') doc <- 'usage: prog [-o]' test_that('parsing "" works',{ #$ prog #{"-o": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = FALSE)) }) test_that('parsing "-o" works',{ #$ prog -o #{"-o": true} res <- docopt(doc, '-o', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = TRUE)) }) ##################### context('doc39') doc <- 'usage: prog [-opr]' test_that('parsing "-op" works',{ #$ prog -op #{"-o": true, "-p": true, "-r": false} res <- docopt(doc, '-op', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-o", "-p", "-r")], list("-o" = TRUE, "-p" = TRUE, "-r" = FALSE)) }) ##################### context('doc40') doc <- 'usage: prog --aabb | --aa' test_that('parsing "--aa" works',{ #$ prog --aa #{"--aabb": false, "--aa": true} res <- docopt(doc, '--aa', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--aabb", "--aa")], list("--aabb" = FALSE, "--aa" = TRUE)) }) ##################### context('doc41') doc <- 'Usage: prog -v' test_that('parsing "-v" works',{ #$ prog -v #{"-v": true} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = TRUE)) }) ##################### context('doc42') doc <- 'Usage: prog [-v -v]' test_that('parsing "" works',{ #$ prog #{"-v": 0} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 0)) }) test_that('parsing "-v" works',{ #$ prog -v #{"-v": 1} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 1)) }) test_that('parsing "-vv" works',{ #$ prog -vv #{"-v": 2} res <- docopt(doc, '-vv', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 2)) }) ##################### context('doc43') doc <- 'Usage: prog -v ...' test_that('parsing "" works',{ #$ prog #"user-error" expect_error(docopt(doc, '', strict=TRUE)) }) test_that('parsing "-v" works',{ #$ prog -v #{"-v": 1} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 1)) }) test_that('parsing "-vv" works',{ #$ prog -vv #{"-v": 2} res <- docopt(doc, '-vv', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 2)) }) test_that('parsing "-vvvvvv" works',{ #$ prog -vvvvvv #{"-v": 6} res <- docopt(doc, '-vvvvvv', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 6)) }) ##################### context('doc44') doc <- 'Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant.' test_that('parsing "" works',{ #$ prog #{"-v": 0} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 0)) }) test_that('parsing "-v" works',{ #$ prog -v #{"-v": 1} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 1)) }) test_that('parsing "-vv" works',{ #$ prog -vv #{"-v": 2} res <- docopt(doc, '-vv', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-v"], list("-v" = 2)) }) test_that('parsing "-vvvv" works',{ #$ prog -vvvv #"user-error" expect_error(docopt(doc, '-vvvv', strict=TRUE)) }) ##################### context('doc45') doc <- 'usage: prog [--ver --ver]' test_that('parsing "--ver --ver" works',{ skip("not implemented") #$ prog --ver --ver #{"--ver": 2} res <- docopt(doc, '--ver --ver', strict=TRUE) expect_equivalent(length(res), 1) skip_on_cran() expect_equivalent(res["--ver"], list("--ver" = 2)) }) ##################### context('doc46') doc <- 'usage: prog [go]' test_that('parsing "go" works',{ #$ prog go #{"go": true} res <- docopt(doc, 'go', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["go"], list(go = TRUE)) }) ##################### context('doc47') doc <- 'usage: prog [go go]' test_that('parsing "" works',{ #$ prog #{"go": 0} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["go"], list(go = 0)) }) test_that('parsing "go" works',{ #$ prog go #{"go": 1} skip("not implemented") res <- docopt(doc, 'go', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["go"], list(go = 1)) }) test_that('parsing "go go" works',{ #$ prog go go #{"go": 2} skip("not implemented") res <- docopt(doc, 'go go', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["go"], list(go = 2)) }) test_that('parsing "go go go" works',{ #$ prog go go go #"user-error" expect_error(docopt(doc, 'go go go', strict=TRUE)) }) ##################### context('doc48') doc <- 'usage: prog go...' test_that('parsing "go go go go go" works',{ #$ prog go go go go go #{"go": 5} skip("not implemented") res <- docopt(doc, 'go go go go go', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["go"], list(go = 5)) }) test_that('parsing "-a" works',{ #$ prog -a #{"-a": true, "-b": false} skip("not implemented") res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-a", "-b")], list("-a" = TRUE, "-b" = FALSE)) }) test_that('parsing "-aa" works',{ #$ prog -aa #"user-error" expect_error(docopt(doc, '-aa', strict=TRUE)) }) ##################### context('doc49') doc <- 'Usage: prog [options] A Options: -q Be quiet -v Be verbose.' test_that('parsing "arg" works',{ #$ prog arg #{"A": "arg", "-v": false, "-q": false} res <- docopt(doc, 'arg', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("A", "-v", "-q")], list(A = "arg", "-v" = FALSE, "-q" = FALSE)) }) test_that('parsing "-v arg" works',{ #$ prog -v arg #{"A": "arg", "-v": true, "-q": false} res <- docopt(doc, '-v arg', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("A", "-v", "-q")], list(A = "arg", "-v" = TRUE, "-q" = FALSE)) }) test_that('parsing "-q arg" works',{ #$ prog -q arg #{"A": "arg", "-v": false, "-q": true} res <- docopt(doc, '-q arg', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("A", "-v", "-q")], list(A = "arg", "-v" = FALSE, "-q" = TRUE)) }) ##################### context('doc50') doc <- 'usage: prog [-]' test_that('parsing "-" works',{ #$ prog - #{"-": true} res <- docopt(doc, '-', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-"], list("-" = TRUE)) }) test_that('parsing "" works',{ #$ prog #{"-": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-"], list("-" = FALSE)) }) ##################### context('doc51') doc <- 'usage: prog [NAME [NAME ...]]' test_that('parsing "a b" works',{ #$ prog a b #{"NAME": ["a", "b"]} res <- docopt(doc, 'a b', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = c("a", "b"))) }) test_that('parsing "" works',{ #$ prog #{"NAME": []} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["NAME"], list(NAME = list())) }) ##################### context('doc52') doc <- 'usage: prog [options] options: -a Add -m Message' test_that('parsing "-a" works',{ #$ prog -a #{"-m": null, "-a": true} res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-m", "-a")], list("-m" = NULL, "-a" = TRUE)) }) ##################### context('doc53') doc <- 'usage: prog --hello' test_that('parsing "--hello" works',{ #$ prog --hello #{"--hello": true} res <- docopt(doc, '--hello', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = TRUE)) }) ##################### context('doc54') doc <- 'usage: prog [--hello=]' test_that('parsing "" works',{ #$ prog #{"--hello": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = NULL)) }) test_that('parsing "--hello wrld" works',{ #$ prog --hello wrld #{"--hello": "wrld"} res <- docopt(doc, '--hello wrld', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--hello"], list("--hello" = "wrld")) }) ##################### context('doc55') doc <- 'usage: prog [-o]' test_that('parsing "" works',{ #$ prog #{"-o": false} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = FALSE)) }) test_that('parsing "-o" works',{ #$ prog -o #{"-o": true} res <- docopt(doc, '-o', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = TRUE)) }) ##################### context('doc56') doc <- 'usage: prog [-opr]' test_that('parsing "-op" works',{ #$ prog -op #{"-o": true, "-p": true, "-r": false} res <- docopt(doc, '-op', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("-o", "-p", "-r")], list("-o" = TRUE, "-p" = TRUE, "-r" = FALSE)) }) ##################### context('doc57') doc <- 'usage: git [-v | --verbose]' test_that('parsing "-v" works',{ #$ prog -v #{"-v": true, "--verbose": false} res <- docopt(doc, '-v', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("-v", "--verbose")], list("-v" = TRUE, "--verbose" = FALSE)) }) ##################### context('doc58') doc <- 'usage: git remote [-v | --verbose]' test_that('parsing "remote -v" works',{ #$ prog remote -v #{"remote": true, "-v": true, "--verbose": false} res <- docopt(doc, 'remote -v', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("remote", "-v", "--verbose")], list(remote = TRUE, "-v" = TRUE, "--verbose" = FALSE)) }) ##################### context('doc59') doc <- 'usage: prog' test_that('parsing "" works',{ #$ prog #{} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 0) expect_equivalent(res[NULL], list()) }) ##################### context('doc60') doc <- 'usage: prog prog ' test_that('parsing "1 2" works',{ #$ prog 1 2 #{"": "1", "": "2"} res <- docopt(doc, '1 2', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("", "")], list("" = "1", "" = "2")) }) test_that('parsing "" works',{ #$ prog #{"": null, "": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("", "")], list("" = NULL, "" = NULL)) }) ##################### context('doc61') doc <- 'usage: prog prog' test_that('parsing "" works',{ #$ prog #{"": null, "": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("", "")], list("" = NULL, "" = NULL)) }) ##################### context('doc62') doc <- 'usage: prog [--file=]' test_that('parsing "" works',{ #$ prog #{"--file": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--file"], list("--file" = NULL)) }) ##################### context('doc63') doc <- 'usage: prog [--file=] options: --file ' test_that('parsing "" works',{ #$ prog #{"--file": null} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--file"], list("--file" = NULL)) }) ##################### context('doc64') doc <- 'Usage: prog [-a ] Options: -a, --address TCP address [default: localhost:6283].' test_that('parsing "" works',{ #$ prog #{"--address": "localhost:6283"} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--address"], list("--address" = "localhost:6283")) }) ##################### context('doc65') doc <- 'usage: prog --long= ...' test_that('parsing "--long one" works',{ #$ prog --long one #{"--long": ["one"]} res <- docopt(doc, '--long one', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--long"], list("--long" = "one")) }) test_that('parsing "--long one --long two" works',{ #$ prog --long one --long two #{"--long": ["one", "two"]} res <- docopt(doc, '--long one --long two', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--long"], list("--long" = c("one", "two"))) }) ##################### context('doc66') doc <- 'usage: prog (go --speed=)...' test_that('parsing "go left --speed=5 go right --speed=9" works',{ skip("not implemented") #$ prog go left --speed=5 go right --speed=9 #{"go": 2, "": ["left", "right"], "--speed": ["5", "9"]} res <- docopt(doc, 'go left --speed=5 go right --speed=9', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("go", "", "--speed")], list(go = 2, "" = c("left", "right"), "--speed" = c("5", "9"))) }) ##################### context('doc67') doc <- 'usage: prog [options] -a options: -a' skip("not implemented") test_that('parsing "-a" works',{ #$ prog -a #{"-a": true} res <- docopt(doc, '-a', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-a"], list("-a" = TRUE)) }) ##################### context('doc68') doc <- 'usage: prog [-o ]... options: -o [default: x]' test_that('parsing "-o this -o that" works',{ #$ prog -o this -o that #{"-o": ["this", "that"]} res <- docopt(doc, '-o this -o that', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = c("this", "that"))) }) test_that('parsing "" works',{ #$ prog #{"-o": ["x"]} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = "x")) }) ##################### context('doc69') doc <- 'usage: prog [-o ]... options: -o [default: x y]' test_that('parsing "-o this" works',{ #$ prog -o this #{"-o": ["this"]} res <- docopt(doc, '-o this', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-o"], list("-o" = "this")) }) test_that('parsing "" works',{ #$ prog #{"-o": ["x", "y"]} res <- docopt(doc, '', strict=TRUE) expect_equivalent(length(res), 1) skip("not implemented") expect_equivalent(res["-o"], list("-o" = c("x", "y"))) }) ##################### context('doc70') doc <- 'usage: prog -pPATH options: -p PATH' test_that('parsing "-pHOME" works',{ #$ prog -pHOME #{"-p": "HOME"} res <- docopt(doc, '-pHOME', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["-p"], list("-p" = "HOME")) }) ##################### context('doc71') doc <- 'Usage: foo (--xx=x|--yy=y)...' test_that('parsing "--xx=1 --yy=2" works',{ #$ prog --xx=1 --yy=2 #{"--xx": ["1"], "--yy": ["2"]} res <- docopt(doc, '--xx=1 --yy=2', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--xx", "--yy")], list("--xx" = "1", "--yy" = "2")) }) ##################### context('doc72') doc <- 'usage: prog []' test_that('parsing "f.txt" works',{ #$ prog f.txt #{"": "f.txt"} res <- docopt(doc, 'f.txt', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res[""], list("" = "f.txt")) }) ##################### context('doc73') doc <- 'usage: prog [--input=]...' test_that('parsing "--input a.txt --input=b.txt" works',{ #$ prog --input a.txt --input=b.txt #{"--input": ["a.txt", "b.txt"]} res <- docopt(doc, '--input a.txt --input=b.txt', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--input"], list("--input" = c("a.txt", "b.txt"))) }) ##################### context('doc74') doc <- 'usage: prog good [options] prog fail [options] options: --loglevel=N' test_that('parsing "fail --loglevel 5" works',{ #$ prog fail --loglevel 5 #{"--loglevel": "5", "fail": true, "good": false} res <- docopt(doc, 'fail --loglevel 5', strict=TRUE) expect_equivalent(length(res), 3) expect_equivalent(res[c("--loglevel", "fail", "good")], list("--loglevel" = "5", fail = TRUE, good = FALSE)) }) ##################### context('doc75') doc <- 'usage:prog --foo' test_that('parsing "--foo" works',{ #$ prog --foo #{"--foo": true} res <- docopt(doc, '--foo', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--foo"], list("--foo" = TRUE)) }) ##################### context('doc76') doc <- 'PROGRAM USAGE: prog --foo' test_that('parsing "--foo" works',{ #$ prog --foo #{"--foo": true} res <- docopt(doc, '--foo', strict=TRUE) expect_equivalent(length(res), 1) expect_equivalent(res["--foo"], list("--foo" = TRUE)) }) ##################### context('doc77') doc <- 'Usage: prog --foo prog --bar NOT PART OF SECTION' test_that('parsing "--foo" works',{ #$ prog --foo #{"--foo": true, "--bar": false} res <- docopt(doc, '--foo', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--foo", "--bar")], list("--foo" = TRUE, "--bar" = FALSE)) }) ##################### context('doc78') doc <- 'Usage: prog --foo prog --bar NOT PART OF SECTION' test_that('parsing "--foo" works',{ #$ prog --foo #{"--foo": true, "--bar": false} res <- docopt(doc, '--foo', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--foo", "--bar")], list("--foo" = TRUE, "--bar" = FALSE)) }) ##################### context('doc79') doc <- 'Usage: prog --foo prog --bar NOT PART OF SECTION' test_that('parsing "--foo" works',{ #$ prog --foo #{"--foo": true, "--bar": false} res <- docopt(doc, '--foo', strict=TRUE) expect_equivalent(length(res), 2) expect_equivalent(res[c("--foo", "--bar")], list("--foo" = TRUE, "--bar" = FALSE)) }) ##################### context('doc80') doc <- 'Usage: prog [options] global options: --foo local options: --baz --bar other options: --egg --spam -not-an-option-' test_that('parsing "--baz --egg" works',{ #$ prog --baz --egg #{"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false} res <- docopt(doc, '--baz --egg', strict=TRUE) skip("not implemented") expect_equivalent(length(res), 5) expect_equivalent(res[c("--foo", "--baz", "--bar", "--egg", "--spam")], list("--foo" = FALSE, "--baz" = TRUE, "--bar" = FALSE, "--egg" = TRUE, "--spam" = FALSE)) }) docopt/tests/testthat.R0000644000176200001440000000006713671664652014712 0ustar liggesuserslibrary(testthat) library(docopt) test_check("docopt")docopt/NEWS0000644000176200001440000000274713674445355012273 0ustar liggesusersversion 0.7.1 - fixed a debugging statement, thanks to @eddelbuettel version 0.7.0 - activated tests - Implemented arguments and options with spaces (quoted) thanks to @ajmazurie and @lorenzwalthert - options with hyphens in the name are changed into snake_case, thanks to @t-kalinowski version 0.6.2 - improved README.md thanks to @andreysmelter - improved error message (showing options) issue #24 version 0.6.1 - changed methods dependency to import (issue #35, thanks to @eddelbuettel). Should have be done earlier, but did work with R version <= 3.3 version 0.6 - removed stringr dependency version 0.4.5 - Fixed single argument which embed a space (issue #11, thanks to @malcook) version 0.4.4 - Fixed arguments which embed a space (issue #11, thanks to @jennybc) - Added `print` method for docopt (issue @12, thanks to @eddelbuettel) version 0.4.3.1 - Fixed stringr dependency thanks to (@eddelbuettel) version 0.4 - Fixed repeating options (issue #8, thanks to @cboettig) - Fixed parsing after double -- (thanks to @ljos) - Fixed printing multiple usage statements (issue #7, thanks to @rgrannell1) version 0.3 - Breaking change! By default stripped names (no dashes and angles) are added to the return list - added support for quoted strings as arguments (thanks to @aniketschneider/issue #4) - added extra "\n" to --help output (thanks to @eddelbuettel) - added `strip_names` to docopt (suggestion of @eddelbuettel) - changed "Imports: methods"" into "Depends: methods" (thanks to @pschulam) docopt/R/0000755000176200001440000000000013674445222011754 5ustar liggesusersdocopt/R/parse.R0000644000176200001440000001775113672606652013230 0ustar liggesusersparse_shorts <- function(tokens, optionlist){ left <- substring(tokens$move(), 2) parsed <- list() while(nchar(left) > 0){ r <- paste0("-", substr(left, 1, 1)) left <- substring(left, 2) simular <- Filter( function(o){ !is.null(o$short) && substring(o$short, 1, 3) == r } , optionlist$options) if (length(simular) > 1){ tokens$error(r, "is specified ambiguously ", length(simular), " times") } if (length(simular) < 1){ o = Option(r, NULL) if (tokens$strict){ o = Option(r, value=TRUE) # needed for version and help } else { optionlist$push(o) } } else { simular = tail(simular, 1)[[1]] o <- Option(simular$short, simular$long, simular$argcount, simular$value) value <- "" if (simular$argcount != 0){ if (left == ""){ if (tokens$current() %in% c("", "--")) tokens$error(o$short, "requires argument") value <- tokens$move() } else { value <- left } left = "" } if (tokens$strict){ o$value <- if (value != "") value else TRUE } } parsed <- c(parsed, o) } parsed } starts_with <- function(x, start){ identical(str_sub(x, 1, nchar(start)), start) } # # # parse_long = (tokens, options) -> parse_long <- function(tokens, optionlist){ # using move, because it strips quotation (and current not) token <- tokens$move() m <- str_match(token, "(.*?)=(.*)") if (!any(is.na(m))){ raw <- m[,2] value <- m[,3] } else { raw <- token value <- NULL } check <- if (tokens$strict) starts_with else identical simular <- Filter(function(o){ (nchar(o$long) && check(o$long, raw)) }, optionlist$options) if (length(simular) > 1){ simular <- Filter(function(o){ identical(o$long, raw) }, simular) if (length(simular) != 1){ tokens$error(raw, " is specified ambigously") } } # if simular.length < 1 if (length(simular) < 1){ argcount <- if (is.null(value)) 0 else 1 o <- Option(NULL, raw, argcount) if (tokens$strict){ o <- Option(NULL, raw, argcount, if (argcount > 0) value else TRUE) } else { optionlist$push(o) } return(list(o)) } simular <- simular[[1]] o <- Option(simular$short, simular$long, simular$argcount, simular$value) if (o$argcount == 1){ if (is.null(value)){ if (tokens$current() == ""){ tokens$error(o$name(), " requires argument") } value <- tokens$move() } } else if (!is.null(value)){ tokens$error(o$name(), " must not have an argument") } o$value <- if (is.null(value) || identical(value, FALSE)) TRUE else value list(o) } parse_pattern <- function(src, optionlist){ src <- gsub("([\\(\\)\\|]|\\[|\\]|\\.\\.\\.)", ' \\1 ', src) tokens <- Tokens(src, cat) result <- parse_expr(tokens, optionlist) if (tokens$current() != ''){ stop("unexpected ending:'", tokens$join(" "),"'", call. = FALSE) } Required(result) } parse_expr <- function(tokens, optionlist){ seq <- parse_seq(tokens, optionlist) if (tokens$current() != "|"){ return(seq) } optional <- FALSE result <- if(length(seq)>1) list(Required(seq)) else seq if (length(seq) == 0) optional <- TRUE while(tokens$current() == "|"){ tokens$move() seq <- parse_seq(tokens, optionlist) if (length(seq) == 0) optional <- TRUE result <- c(result, if (length(seq)>1)list(Required(seq)) else seq) } if (length(result)>1){ result <- list(Either(result)) } if (optional){ result <- list(Optional(result)) } result } parse_seq <- function(tokens, optionlist){ # seq ::= ( atom [ '...' ] )* ; result <- list() while(!isTRUE(tokens$current() %in% c("", "]", ")", "|"))){ atom <- parse_atom(tokens, optionlist) if (isTRUE(tokens$current() == '...')){ atom <- OneOrMore(atom) tokens$move() } result <- c(result, atom) } result } parse_atom <- function(tokens, optionlist){ # atom ::= '(' expr ')' | '[' expr ']' | '[' 'options' ']' | '--' # | long | shorts | argument | command ; token <- tokens$current() result <- list() if (token == '('){ tokens$move() result <- list(Required(parse_expr(tokens, optionlist))) if (tokens$move() != ")"){ tokens$error("Unmatched '('") } result } else if (token == '['){ tokens$move() if (tokens$current() == 'options'){ result = list(Optional(list(AnyOptions()))) tokens$move() } else { result <- list(Optional(parse_expr(tokens, optionlist))) } if (tokens$move() != "]"){ tokens$error("Unmatched '['") } result } else if (substr(token, 1, 2) == '--' ){ if (token == '--'){ list(Command(tokens$move())) } else { parse_long(tokens, optionlist) } } else if (substr(token,1,1) == '-' && token != '-'){ parse_shorts(tokens, optionlist) } else if (grepl("^<.+>$", token) || grepl("^[^a-z]*[A-Z]+[^a-z]*$", token)){ list(Argument(tokens$move())) } else{ # [new Command tokens.move()] list(Command(tokens$move())) } } # # parse_args = (source, options) -> parse_args <- function(src, optionlist){ # tokens = new TokenStream source, DocoptExit QUOTED <- "^'(.*?)'$" cmdargs <- length(src) > 1 || any(str_detect(src, QUOTED)) if (cmdargs){ src <- sub(QUOTED, "\\1", src) } tokens <- Tokens(src, as_is = cmdargs) #browser() # #options = options.slice(0) # shallow copy, not sure if necessary # opts = [] opts = list() # while (token = tokens.current()) isnt null while ((token <- tokens$current()) != "") if (token == '--'){ ## if token is '--' then this and the rest of the arguments ## are positional arguments. return(c(opts, lapply(tokens$tokens, function(x) Argument(NULL, x)))) } else if (grepl("^--", token)){ # else if token[0...2] is '--' # long = parse_long tokens, options # opts = opts.concat long long <- parse_long(tokens, optionlist) opts <- c(opts, long) } else if (grepl("^-.+", token)){ # else if token[0] is '-' and token isnt '-' # shorts = parse_shorts tokens, options # opts = opts.concat shorts shorts = parse_shorts(tokens, optionlist) opts <- c(opts, shorts) } else { opts <- c(opts, Argument(NULL, tokens$move())) } return(opts) } parse_option <- function(description){ # description = description.replace(/^\s*|\s*$/g, '') # strip whitespaces description <- str_trim(description) # [_, options, # description] = description.match(/(.*?) (.*)/) ? [null, description, ''] # split on first occurence of 2 consecutive spaces (' ') m <- str_match(description, "(.*?) (.*)") if (any(is.na(m))){ options <- description } else { options <- m[,2] } # # replace ',' or '=' with ' ' # options = options.replace /,|=/g, ' ' options <- gsub(",|=", " ", options) # # set some defaults short <- NULL long <- NULL argcount <- 0 value <- FALSE for (s in strsplit(options, "\\s+")[[1]]){ if (substring(s, 1, 2) == "--"){ long <- s } else if (substring(s, 1,1) == '-'){ short <- s } else { argcount <- 1 } } # if argcount is 1 if (argcount == 1){ matched <- str_match(description, "(?i)\\[default:\\s+(.*)\\]") value <- matched[,2] if (is.na(value)) value <- NULL } Option(short, long, argcount, value) # new Option short, long, argcount, value } # parse_doc_options = (doc) -> parse_doc_options <- function(doc){ # (Option.parse('-' + s) for s in doc.split(/^\s*-|\n\s*-/)[1..]) opts <- str_split(doc, "(?i)(\\n|Options:)\\s*-")[[1]] opts <- tail(opts, -1) # OptionList(lapply(tail(unlist(str_split(doc, "(?i)^\\s*-|\\n\\s*-|Options:\\s*-")),-1), function(s){ # parse_option(paste0('-', s)) # })) OptionList(lapply(opts, function(s){ parse_option(paste0('-', s)) })) } docopt/R/Tokens.R0000644000176200001440000000570713672161516013352 0ustar liggesusersQUOTED <- "'(.*?)'" DQUOTED <- "\"(.*?)\"" # utility function store_ws <- function(x, invert=FALSE){ if (invert){ gsub("___", " ", x, fixed = TRUE) } else { gsub(" ", "___", x, fixed = TRUE) } } # replaces values with white spaces ws_replace <- function(pattern, x){ # pattern <- "'(.*?)'" m <- gregexpr(pattern, x) ms <- regmatches(x, m) ms <- lapply(ms, store_ws) regmatches(x, m) <- ms x } Tokens <- setRefClass( "Tokens" , fields=list( tokens="character" , error="function" , strict="logical" , defining=function(){!strict} ) , methods=list( initialize = function(tokens=character(), error=stop, as_is=FALSE){ if (as_is){ .tokens <- tokens } else { # browser() # trimws .tokens <- gsub("^\\s+|\\s+$", "", tokens) if (length(.tokens)){ .tokens <- ws_replace("(<.*?>)", .tokens) .tokens <- ws_replace(QUOTED, .tokens) .tokens <- ws_replace(DQUOTED, .tokens) .tokens <- strsplit(.tokens, "\\s+")[[1]] .tokens <- store_ws(.tokens, invert = TRUE) # remove quotation # .tokens <- gsub("^'(.*)'$", "\\1", .tokens) # .tokens <- gsub('^"(.*)"$', "\\1", .tokens) } } tokens <<- .tokens if (missing(error)){ strict <<- TRUE } else { strict <<- FALSE } error <<- error }, current = function(){ if (length(tokens)){ tokens[1] } else { "" } }, shift = function(){ h <- head(tokens, 1) tokens <<- tail(tokens, -1) if (length(h)) h else "" }, move = function(){ h <- head(tokens, 1) tokens <<- tail(tokens, -1) #remove optional quotes... h <- gsub("^'(.*)'$", "\\1", h) h <- gsub("='(.*)'$", "=\\1", h) h <- gsub('^"(.*)"$', "\\1", h) h <- gsub('="(.*)"$', "=\\1", h) if (length(h)) h else "" }, # toString: -> ([].slice.apply @).toString() toString = function(){ tokens }, show = function(){ cat("Tokens:", toString()) }, # # join: (glue) -> ([].join.apply @, glue) join = function(glue){ paste0(tokens, collapse=glue) } ) ) #' index tokens #' #' index tokens #' @keywords internal setMethod("[", signature(x = "Tokens"), function (x, i, drop = TRUE) { x$tokens[i] } ) #' index tokens #' #' index tokens #' @keywords internal setMethod("[<-", signature(x = "Tokens"), function (x, i, value) { x$tokens[i] <- value } ) #' to character #' #' to character #' @keywords internal setMethod("as.character", signature(x="Tokens"), function(x, ...){x$tokens}) # # testing 1, 2, 3 # t <- Tokens(c("a", "b")) # t$current() # t$shift() # tdocopt/R/docopt.R0000644000176200001440000001340513674445223013373 0ustar liggesusers#' Parse \code{args} based on command-line interface described in \code{doc}. #' #' \code{docopt} creates your command-line interface based on its #' description that you pass as \code{doc}. #' Such description can contain #' --options, , commands, which could be #' [optional], (required), (mutually | exclusive) or repeated... #' #' @examples #' "Usage: my_program.R [-hso FILE] [--quiet | --verbose] [INPUT ...] #' #' -h --help show this #' -s --sorted sorted output #' -o FILE specify output file [default: ./test.txt] #' --quiet print less text #' --verbose print more text" -> doc #' docopt(doc, "-s --quiet") #' @param doc \code{character} vector with command line specification #' @param args \code{character} vector of commandline arguments. #' If \code{args} is missing #' \code{commandArgs(trailingOnly=TRUE)} will be used. #' @param name Currently not used #' @param help \code{logical} should "-h" or "--help" generate a usage string? #' @param version \code{character}. If supplied the option "-v" generates #' the given version number and stops. #' @param strict \code{logical} if \code{TRUE} docopt will conform to docopt.py #' in and output (\code{strip_names=FALSE} and \code{quoted_args=FALSE}) #' @param strip_names if \code{TRUE} it will remove dashes and angles from the #' resulting names and add these to the resulting list. #' Note that this is different from docopt standard! #' @param quoted_args if \code{TRUE} it will accept quoted arguments. #' Note that this is different from docopt standard! #' @return named list with all parsed options, arguments and commands. #' @references \url{http://docopt.org}, #' @export #' @import methods docopt <- function( doc, args=commandArgs(TRUE), name=NULL, help=TRUE, version=NULL , strict=FALSE, strip_names=!strict, quoted_args=!strict ){ if (missing(args)) { # littler compatibility - map argv vector to args if (exists("argv", where = .GlobalEnv, inherits = FALSE)) { args = get("argv", envir = .GlobalEnv); } else { args <- quote_spaced(args) } } #print(args) #browser() #args <- fix_quoted_options(args) #args <- str_c(args, collapse=" ") usage <- printable_usage(doc, name) pot_options <- parse_doc_options(doc) pattern <- parse_pattern(formal_usage(usage), pot_options) for (anyopt in pattern$flat("AnyOptions")){ #TODO remove options that are present in pattern if (class(anyopt) == "AnyOptions") anyopt$children <- pot_options$options } args <- parse_args(args, pot_options) extras(help, version, args, doc) m <- pattern$fix()$match(args) if (m$matched && length(m$left) == 0){ cl <- sapply(m$collected, class) options <- m$collected[cl == "Option"] pot_arguments <- pattern$flat() pot_arguments <- pot_arguments[sapply(pot_arguments, class) %in% c("Argument", "Command")] arguments <- m$collected arguments <- arguments[sapply(arguments, class) %in% c("Argument", "Command")] dict <- list() class(dict) <- c("docopt", "list") for(kv in c(pot_options$options, options, pot_arguments, arguments)){ value <- kv$value dict[kv$name()] <- list(value) } if (isTRUE(strip_names)){ nms <- gsub("(^<)|(^\\-\\-?)|(>$)", "", names(dict)) # kebab case to snake case nms <- gsub("-", "_", nms) dict[nms] <- dict } return(dict) } stop(doc, call. = FALSE) #stop(paste("\n",usage, collapse="\n "), call. = FALSE) } # print help help <- function(doc){ cat(doc, "\n") } #print version version <- function(version=NULL){ if (!is.null(version)){ cat("Version: ", version, "\n") } } extras <- function(help, version=NULL, options, doc){ opts <- list() for (opt in options){ if (!is.null(opt$value)){ opts[opt$name()] <- TRUE } } if (help && any(names(opts) %in% c("-h","--help"))){ help <- str_replace_all(doc, "^\\s*|\\s*$", "") cat(help,"\n") if (interactive()) stop(call. = FALSE) else { quit(save="no") } } if (!is.null(version) && any(names(opts) %in% "--version")){ cat(version) if (interactive()) stop(call. = FALSE) else quit(save="no") } } printable_usage <- function(doc, name){ usage_split <- str_split(doc, "(?i)usage:\\s*")[[1]] if (length(usage_split) < 2){ stop("'usage:' (case-insensitive) not found", call. = FALSE) } else if (length(usage_split) > 2){ stop('More than one "usage:" (case-insensitive).', call. = FALSE) } usage <- str_split(usage_split[2], "\n\\s*")[[1]] firstword <- str_extract(usage, "^\\w+") progs <- which(firstword == firstword[1]) usage <- str_c("usage: ", usage[progs]) str_trim(usage) } # formal_usage <- function(printable_usage){ # formal_usage = (printable_usage) -> # pu = printable_usage.split(/\s+/)[1..] # split and drop "usage:" # ((if s == pu[0] then '|' else s) for s in pu[1..]).join ' ' formal <- str_replace(printable_usage, "^usage:\\s*", "") pu <- unlist(str_split(formal, "\\s+")) prog <- pu[1] pu[pu==prog] <- "|" formal <- str_c(tail(pu, -1), collapse=" ") formal } quote_spaced <- function(x){ ifelse( str_detect(x, "\\s") , shQuote(x) , x ) } # fix wrong shell quoting fix_quoted_options <- function(x){ x <- gsub("'(--?[[:alpha:]]+=)", "\\1'", x) } # # class Dict extends Object # # constructor: (pairs) -> # (@[key] = value for [key, value] in pairs) # # toString: () -> # atts = (k for k of @ when k not in ['constructor', 'toString']) # atts.sort() # '{' + (k + ': ' + @[k] for k in atts).join(',\n ') + '}' # #' @export print.docopt <- function(x, ...) { print(str(x, give.attr=FALSE)) # convenient shortcut invisible(x) } docopt/R/Pattern.R0000644000176200001440000004027713671356716013534 0ustar liggesusersPattern <- setRefClass( "Pattern" , fields=list(children="list") , methods=list( initialize = function(.children=list()){ children <<- .children }, toString = function(){ formals = paste0(sapply(children, as.character), collapse=", ") paste0(class(.self),"(",formals,")") }, show = function(){ cat(toString()) }, match = function(){ stop("classes inheriting from Pattern must overload the match method") }, flat = function(...){ types = list(...) if (class(.self) %in% types){ return(list(.self)) } if (length(children) == 0){ return(list(.self)) } unlist(lapply(children, function(child){child$flat(...)})) }, fix = function(){ fix_identities() fix_repeating_arguments() }, #Make pattern-tree tips point to same object if they are equal. fix_identities = function(uniq=NULL){ #browser() if (length(children) == 0) { return(.self) } if (is.null(uniq)){ uniq <- flat() names(uniq) <- sapply(uniq, as.character) } for (i in seq_along(children)){ child <- children[[i]] if (length(child$children)){ #TODO check what uniq does. child$fix_identities(uniq) } else { children[[i]] <<- uniq[[child$toString()]] } } uniq }, # Find arguments that should accumulate values and fix them. fix_repeating_arguments = function(){ eith <- lapply(either()$children, function(c) c$children) for (child in eith){ nms <- as.character(sapply(child, as.character)) #browser() counts <- table(nms) for (e in child){ if (isTRUE(unname(counts[as.character(e)] > 1))){ if (class(e)=="Argument" ||(class(e)=="Option" && e$argcount>0)){ if (is.null(e$value)){ e$value <- list() } else if (class(e$value) != "list"){ e$value <- as.list(e$value) } } if ( class(e) == "Command" || (class(e) == "Option" && e$argcount == 0)){ e$value <- 0L } } } } .self }, either = function(){ if (length(children) == 0L){ return(Either(list(Required(list(.self))))) } #browser() ret <- list() # groups = [[@]] groups <- list(list(.self)) # while groups.length while (length(groups)){ # children = groups.shift() .children <- head(groups, 1)[[1]] groups <- tail(groups, -1) type <- c("Either", "Required","Optional", "OneOrMore", "AnyOptions") childtype <- sapply(.children, class) m <- base::match(childtype, type, nomatch=0L) if (any(m > 0)){ # take first child bigger than zero idx <- which(m > 0L)[1] child <- .children[[idx]] .children <- .children[-idx] if (class(child) == "Either"){ for (ci in child$children){ group <- c(ci, .children) groups[[length(groups)+1]] <- group } } else if (class(child) == "OneOrMore"){ group <- c(child$children, child$children, .children) groups[[length(groups)+1]] <- group } else { group <- c(child$children, .children) groups[[length(groups)+1]] <- group } } else{ ret[[length(ret)+1]] <- .children } } Either(lapply(ret, function(e) Required(e))) } )) # LeafPattern <- setRefClass( "LeafPattern" # , fields=c("name", "value") # , methods=list( # flat = function(...){ # types <- list(...) # if (length(l)==0 || class(.self) %in% types){ # return(list(.self)) # } # list() # }, # match = function(left, collected=list()){ # browser() # m <- single_match(left) # # if match is None: # # return False, left, collected # if (is.null(m$match)){ # return(matched(FALSE, left, collected)) # } # # left_ = left[:pos] + left[pos + 1:] # left_ <- left[-m$pos] # # same_name = [a for a in collected if a.name == self.name] # same_name <- Filter(function(a){a$name == name}, collected) # # if type(self.value) in (int, list): # if (class(value) %in% c("integer", "list")){ # browser() # # if type(self.value) is int: # if (is.integer(value)){ # # increment = 1 # increment <- 1 # } else { # # else: # # increment = ([match.value] if type(match.value) is str # # else match.value) # increment <- m$match$value # if (is.character(increment)){ # increment <- list(increment) # } # } # # if not same_name: # if (length(same_name)==0){ # # match.value = increment # match$value <- increment # # return True, left_, collected + [match] # return(matched(TRUE, left_, c(collected, match))) # } # val <- same_name[[1]]$value # # same_name[0].value += increment # # return True, left_, collected # same_name[[1]]$value <- if (is.integer(val)) val + increment else c(val, increment) # return(matched(TRUE, left_, collected)) # } # # return True, left_, collected + [match] # return(matched(TRUE, left_, c(collected, match))) # } # ) # ) # BranchPattern <- setRefClass("BranchPattern", contains="Pattern" # , methods=list( # initialize = function(.children=list()){ # children <<- .children # }, # flat=function(...){ # types <- list(...) # if (class(.self) %in% types){ # return(list(.self)) # } # if (length(children) == 0){ # return(list()) # } # unlist(lapply(children, function(child){child$flat(...)})) # } # ) # ) # # class BranchPattern(Pattern): # # """Branch/inner node of a pattern tree.""" # # def __init__(self, *children): # self.children = list(children) # # def __repr__(self): # return '%s(%s)' % (self.__class__.__name__, # ', '.join(repr(a) for a in self.children)) # # def flat(self, *types): # if type(self) in types: # return [self] # return sum([child.flat(*types) for child in self.children], []) # class Argument extends Pattern Argument <- setRefClass("Argument", contains="Pattern" , fields = c("argname", "value") , methods = list( initialize=function(argname, value=NULL){ argname <<- argname value <<- value }, # # name: -> @argname name = function(){ argname }, # toString: -> "Argument(#{@argname}, #{@value})" toString = function(){ paste0("Argument(",argname,",",value,")") }, # match: (left, collected=[]) -> match = function(left, collected=list()){ # args = (l for l in left when l.constructor is Argument) argsidx <- which(sapply(left, class) == "Argument") arg <- head(argsidx,1) if (!length(arg)){ return(matched(FALSE, left, collected)) } arg <- left[[arg]] left <- Filter(function(l){!identical(l, arg)}, left) if (is.null(value) || !is.list(value)){ collected <- c(collected, list(Argument(name(), arg$value))) return(matched(TRUE, left, collected)) } same_name <- Filter(function(a){ class(a) == "Argument" && identical(a$name(), name()) } , collected) if (length(same_name)){ same_name[[1]]$value <- c(same_name[[1]]$value, arg$value) return(matched(TRUE, left, collected)) } else{ collected <- c(collected, Argument(name(), arg$value)) return(matched(TRUE, left, collected)) } } )) # # # class Command extends Pattern Command <- setRefClass("Command" , contains="Pattern" , fields = c("cmdname", "value") , methods=list( initialize = function(cmdname, value=FALSE){ cmdname <<- cmdname value <<- value }, # name: -> @cmdname name = function(){ cmdname }, toString = function(){ paste0("Command(",cmdname,",",value,")") }, # match: (left, collected=[]) -> match = function(left, collected=list()){ #browser() argsidx <- which(sapply(left, class) == "Argument") firstarg <- head(argsidx,1) # args = (l for l in left when l.constructor is Argument) # if not args.length or args[0].value isnt @name() if (!length(firstarg) || left[[firstarg]]$value != name()){ # return [false, left, collected]{ return(matched(FALSE, left, collected)) } # left.splice(left.indexOf(args[0]), 1) left <- left[-firstarg] # collected.push new Command @name(), true collected <- c(collected, Command(name(), TRUE)) # [true, left, collected] matched(TRUE, left, collected) } )) # # # class Option extends Pattern Option <- setRefClass("Option", contains="Pattern" , fields = c("short", "long", "argcount", "value", "cardinality") , methods = list( initialize= function(short=NULL, long=NULL, argcount=0L, value=FALSE){ short <<- short long <<- long argcount <<- argcount if (argcount && missing(value)){ value <<- NULL } else value <<- value cardinality <<- 1L }, toString = function(){ val <- value if (length(val) > 1){ val <- paste0("[",paste0(val, collapse = ","),"]") } paste0("Option(",short,",",long,",",argcount,",", val,")") }, name = function(){ if (!is.null(long)) long else short }, match = function(left, collected=list()){ pos <- single_match(left) if (pos == 0){ return(matched(FALSE, left, collected)) } match = left[[pos]] left_ = left[-pos] same_name <- Filter( function(l) identical(name(), l$name()) , collected) if (class(value) %in% c("list", "integer")){ if (is.integer(value)){ match$value <- 1L } if (length(same_name)){ if (is.integer(value)){ same_name[[1]]$value <- same_name[[1]]$value + match$value } else { same_name[[1]]$value <- c(same_name[[1]]$value, match$value) } #print(collected) return(matched(TRUE, left_, collected)) } } #print(ls.str()) matched(TRUE, left_, c(collected,match)) }, single_match = function(left){ base::match( name() , sapply(left, function(l) l$name()) , nomatch = 0 ) } )) # class Required extends Pattern Required <- setRefClass("Required", contains="Pattern" , methods=list( match = function(left, collected=list()){ m <- matched(TRUE, left, collected) for (p in children){ m <- p$match(m$left, m$collected) if (!m$matched){ return(matched(FALSE, left, collected)) } } m } )) # # class Optional extends Pattern Optional <- setRefClass("Optional", contains="Pattern" , methods=list( match = function(left, collected=list()){ m <- matched(FALSE, left, collected) for (p in children){ m <- p$match(m$left, m$collected) } m$matched <- TRUE m } )) # class AnyOptions extends Optional AnyOptions <- setRefClass("AnyOptions", contains="Optional") # # class OneOrMore extends Pattern OneOrMore <- setRefClass("OneOrMore", contains="Pattern" , methods=list( # match: (left, collected=[]) -> match = function(left, collected=list()){ m <- matched(TRUE, left, collected) # l_ = [] l_ <- character() # times = 0 times <- 0L # while matched while (m$matched){ # # could it be that something didn't match but changed l or c? # [matched, l, c] = @children[0].match(l, c) m <- children[[1]]$match(m$left, m$collected) # times += if matched then 1 else 0 if (m$matched){ times <- times + 1L } # if l_.join(', ') is l.join(', ') then break if (identical(paste0(l_, collapse=", "), paste0(m$left, collapse=", "))){ break } # l_ = l #copy(l) l_ <- m$left } # if times >= 1 then return [true, l, c] if (times >= 1){ matched(TRUE, m$left, m$collected) } else { # [false, left, collected] matched(FALSE, left, collected) } } )) # # class Either extends Pattern Either <- setRefClass("Either", contains="Pattern" , methods=list( # match: (left, collected=[]) -> match = function(left, collected=list()){ # outcomes = [] m <- matched(FALSE, left, collected) outcomes <- lapply(children, function(p){ p$match(left, collected) }) outcomes <- Filter(function(p){ p$matched }, outcomes) # if outcomes.length > 0 if (length(outcomes)){ # outcomes.sort((a,b) -> sizes <- sapply(outcomes, function(o) length(o$left)) # if a[1].length > b[1].length # 1 # else if a[1].length < b[1].length # -1 # else # 0) # return outcomes[0] return(outcomes[[which.min(sizes)]]) } # [false, left, collected] matched(FALSE, left, collected) } )) #' as.character.Pattern #' #' as.character.Pattern #' @keywords internal setMethod("as.character", "Pattern", function(x, ...){ x$toString() }) # utility function for returning a tuple of a match matched <- function(matched, left, collected){ list(matched=matched, left=left, collected=collected) } # utility function for collecting options OptionList <- setRefClass( "OptionList" , fields = list(options="list") , methods=list( initialize = function(.options=list()){ options <<- .options }, push = function(o){ options <<- append(options, o) } ))docopt/R/pkg.R0000644000176200001440000000044113671356716012665 0ustar liggesusers#' Docopt command line specification #' #' docopt helps you to define an interface for your command-line app, and #' automatically generate a parser for it. #' #' For more information see http://docopt.org #' #' @name docopt-package #' @importFrom utils tail str #' @docType package {} docopt/R/stringr_dropin.R0000644000176200001440000000407613671356716015157 0ustar liggesusersstr_extract <- function(text, pattern){ m <- regexpr(pattern=pattern, text = text, perl = TRUE) rstart <- as.integer(m) rstop <- rstart + attr(m, "match.length") - 1 rstart[rstart < 0] <- 0 rstop[rstop < 0] <- 0 substr(text, rstart, rstop) } str_extract_all <- function(text, pattern){ m_all <- gregexpr(pattern=pattern, text = text, perl=TRUE) lapply(seq_along(m_all), function(i){ m <- m_all[[i]] rstart <- as.integer(m) rstop <- rstart + attr(m, "match.length") - 1 rstart[rstart < 0] <- 0 rstop[rstop < 0] <- 0 mapply(function(start, stop){ s <- substr(text[[i]],start, stop) if (s == ''){ character() } else { s } } , rstart, rstop) }) } str_trim <- function(x){ gsub("^\\s+|\\s+$","", x) } str_c <- function(x, ...){ paste0(x, ...) } str_split <- function(string, pattern){ strsplit(string, split = pattern, perl=TRUE) } str_detect <- function(string, pattern){ grepl(pattern, string) } str_sub <- function(string, start=1L, stop=-1L){ substr(string, start = start, stop = stop) } str_replace <- function(string, pattern, replacement){ sub(pattern, replacement = replacement, x = string, perl = TRUE) } str_replace_all <- function(string, pattern, replacement){ gsub(pattern, replacement = replacement, x = string, perl = TRUE) } str_match <- function(string, pattern){ ms <- regexpr(pattern=pattern, text = string, perl = TRUE) ms_stop <- ms + attr(ms, "match.length") - 1 cap_start <- attr(ms, "capture.start") cap_stop <- cap_start + attr(ms, "capture.length") - 1 cap_n <- ncol(cap_start) m <- t( sapply(seq_along(string), function(i){ s <- string[i] c( substr(s, ms[i], ms_stop[i]) , sapply(seq_len(cap_n), function(j){ substr(s, cap_start[i,j], cap_stop[i,j]) }) ) }) ) is.na(m) <- nchar(m) == 0 m } text = c("hallo", "test", "baadd") pattern = "(\\w)\\1(.)" # #str_extract(text = text, pattern = pattern) # strextract_all(text = text, pattern = pattern) string <- text str_match(string, pattern) docopt/MD50000644000176200001440000000247313674611673012076 0ustar liggesusers4a17072e0dc75af0bb937e8dc782ce81 *DESCRIPTION 12d743725f2dd0dbfc12e166b146307c *LICENSE 41d3ea8cc0835121e0e33bc3c2c11a3e *NAMESPACE 06dbbeb4b5f7edfcd72f866dc813d9a8 *NEWS 4a48c008e6e2f04a667440e7adfca937 *R/Pattern.R 9e5d3228c262db5cdc217e28619375cd *R/Tokens.R 4039ed441253e356c946f6ecdf684969 *R/docopt.R 668f85599beaefe87a655e2582a6ba08 *R/parse.R caefeaba5fa6149ef8ac143885ab6013 *R/pkg.R 4c3349104af9e5ba120f4727664f307f *R/stringr_dropin.R 4f09a35236f0e5048e133415c311bb65 *inst/paper/docopt.bib b1017ffa840f6b6e46f8acf3e3d36e0d *inst/paper/docopt.tex 8ee838e6a3bf6354e7d0ff34d3e9d15b *inst/spec/docopt.py d418fee3293fcd3d1521e5bdd4f84557 *inst/spec/generate_tests.R 0ef792693c4de46737337e37eac1ff38 *inst/spec/testcases.docopt b7a30d05144a82ae22dc2402258bc03e *man/as.character-Pattern-method.Rd 1a7fd8bbfd167d06572a87247ae95160 *man/as.character-Tokens-method.Rd 53b3845a34745c3baa0a484f9d0ddf3b *man/docopt-package.Rd 21874b1f351670e9fa6e4f98b61a82ce *man/docopt.Rd 1a898cac8d36d5bdf1fcb7de8b8be82d *man/sub-Tokens-method.Rd d015b3fe5fbcff77e776a2805f1196ea *man/subset-Tokens-method.Rd 5942a0224da98332a7ada296f8830873 *tests/testthat.R e5c0ef8572d683f4005e3f6ba2d3bf15 *tests/testthat/test-issues.R e13e545229e77dc350c25ef127e8f963 *tests/testthat/test-quotedargs.R ea40614389981ca7f4a4316a7f0b5127 *tests/testthat/test-specs.R docopt/inst/0000755000176200001440000000000013671356716012536 5ustar liggesusersdocopt/inst/paper/0000755000176200001440000000000013671356716013645 5ustar liggesusersdocopt/inst/paper/docopt.bib0000644000176200001440000000175513671356716015623 0ustar liggesusers@misc{docopt, author = {Vladimir Keleshev}, title = {(docopt), Command-line interface description language}, howpublished = {\url{http://docopt.org}}, year = {2012} } @misc{docoptR, author = {Edwin de Jonge}, title = {(docopt), Command-line interface description language for R}, howpublished = {\url{http://github.com/edwindj/docopt.R}}, year = {2013} } @inproceedings{van2007python, title={Python Programming Language.}, author={Van Rossum, Guido and others}, booktitle={USENIX Annual Technical Conference}, year={2007} } @Manual{optparse, title = {optparse: Command line option parser.}, author = {Trevor L Davis, Steve Lianoglou and Jim Nikelski.}, year = {2013}, note = {R package version 1.0.2}, url = {http://CRAN.R-project.org/package=optparse}, } @Manual{getopt, title = {getopt: C-like getopt behavior.}, author = {Allen Day,Trevor L Davis.}, year = {2013}, note = {R package version 1.20.0}, url = {http://CRAN.R-project.org/package=getopt}, } docopt/inst/paper/docopt.tex0000644000176200001440000000612213671356716015660 0ustar liggesusers\documentclass[11pt, a4paper]{article} \usepackage{amsfonts, amsmath, hanging, hyperref, parskip, times} \usepackage[numbers]{natbib} \usepackage[pdftex]{graphicx} \hypersetup{ colorlinks, linkcolor=blue, urlcolor=blue, citecolor=blue } \let\section=\subsubsection \newcommand{\pkg}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\proglang=\textit \let\code=\texttt \renewcommand{\title}[1]{\begin{center}{\bf \LARGE #1}\end{center}} \newcommand{\affiliations}{\footnotesize\centering} \newcommand{\keywords}{\paragraph{Keywords:}} \setlength{\topmargin}{-15mm} \setlength{\oddsidemargin}{-2mm} \setlength{\textwidth}{165mm} \setlength{\textheight}{250mm} \begin{document} \pagestyle{empty} \title{docopt, add beautiful command line options to \proglang{R} scripts} \begin{center} {\bf Edwin de Jonge$^{1,^\star}$} \end{center} \begin{affiliations} 1. Statistics Netherlands (CBS) \\[-2pt] $^\star$Contact author: \href{mailto:e.dejonge@cbs.nl}{e.dejonge@cbs.nl}\\ \end{affiliations} \keywords Options, Rscript, docopt, programming \vskip 0.8cm With its increasing popularity \proglang{R} scripts are more and more executed in batch mode from the command line. When a script matures and becomes more generic it often is desirable to add command-line options to it. Starting simple you may use \code{cmdArgs} to parse the extra options given to the script, but it quickly becomes complicated: parsing multiple options, long and short names for options, default values for options, generating sensible information when incorrect input is given and documenting all options for usage can take quite some code and time. The packages \pkg{getopt}~\cite{getopt} and \pkg{optparse}~\cite{optparse} can be of great help for parsing command-line arguments, but \pkg{docopt} makes it super easy. The R-package \pkg{docopt}~\citep{docoptR} is a port of the \proglang{Python} package \code{docopt}. Docopt is a command-line interface description language, and helps you to formulate a command-line interface and automatically generate a parser for it, that will parse the command-line arguments automatically for you. The nice part is that the documentation given to the user is equal to its definition. As an appetizer: \code{docopt("Usage: prog [-a -b=value]")} will generate a parser and test if \code{a} and \code{b} were set in the command line. It returns a list in which the values for \code{a} and \code{b} are included. The presentation will introduce \pkg{docopt}, describe its usage, specification format and some of its implementation details. %% The \proglang, \code, and \pkg macros may be reused %% references: \nocite{docopt,van2007python} \bibliographystyle{chicago} \bibliography{docopt} %% references can alternatively be entered by hand %\subsubsection*{References} %\begin{hangparas}{.25in}{1} %AuthorA (2007). Title of a web resource, \url{http://url/of/resource/}. %AuthorC (2008a). Article example in proceedings. In \textit{useR! 2008, The R %User Conference, (Dortmund, Germany)}, pp. 31--37. %AuthorC (2008b). Title of an article. \textit{Journal name 6}, 13--17. %\end{hangparas} \end{document} docopt/inst/spec/0000755000176200001440000000000013674446020013457 5ustar liggesusersdocopt/inst/spec/docopt.py0000644000176200001440000004651013671356716015340 0ustar liggesusers"""Pythonic command-line interface parser that will make you smile. * http://docopt.org * Repository and issue-tracker: https://github.com/docopt/docopt * Licensed under terms of MIT license (see LICENSE-MIT) * Copyright (c) 2013 Vladimir Keleshev, vladimir@keleshev.com """ import sys import re __all__ = ['docopt'] __version__ = '0.6.1' class DocoptLanguageError(Exception): """Error in construction of usage-message by developer.""" class DocoptExit(SystemExit): """Exit in case user invoked program with incorrect arguments.""" usage = '' def __init__(self, message=''): SystemExit.__init__(self, (message + '\n' + self.usage).strip()) class Pattern(object): def __eq__(self, other): return repr(self) == repr(other) def __hash__(self): return hash(repr(self)) def fix(self): self.fix_identities() self.fix_repeating_arguments() return self def fix_identities(self, uniq=None): """Make pattern-tree tips point to same object if they are equal.""" if not hasattr(self, 'children'): return self uniq = list(set(self.flat())) if uniq is None else uniq for i, child in enumerate(self.children): if not hasattr(child, 'children'): assert child in uniq self.children[i] = uniq[uniq.index(child)] else: child.fix_identities(uniq) def fix_repeating_arguments(self): """Fix elements that should accumulate/increment values.""" either = [list(child.children) for child in transform(self).children] for case in either: for e in [child for child in case if case.count(child) > 1]: if type(e) is Argument or type(e) is Option and e.argcount: if e.value is None: e.value = [] elif type(e.value) is not list: e.value = e.value.split() if type(e) is Command or type(e) is Option and e.argcount == 0: e.value = 0 return self def transform(pattern): """Expand pattern into an (almost) equivalent one, but with single Either. Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d) Quirks: [-a] => (-a), (-a...) => (-a -a) """ result = [] groups = [[pattern]] while groups: children = groups.pop(0) parents = [Required, Optional, OptionsShortcut, Either, OneOrMore] if any(t in map(type, children) for t in parents): child = [c for c in children if type(c) in parents][0] children.remove(child) if type(child) is Either: for c in child.children: groups.append([c] + children) elif type(child) is OneOrMore: groups.append(child.children * 2 + children) else: groups.append(child.children + children) else: result.append(children) return Either(*[Required(*e) for e in result]) class LeafPattern(Pattern): """Leaf/terminal node of a pattern tree.""" def __init__(self, name, value=None): self.name, self.value = name, value def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value) def flat(self, *types): return [self] if not types or type(self) in types else [] def match(self, left, collected=None): collected = [] if collected is None else collected pos, match = self.single_match(left) if match is None: return False, left, collected left_ = left[:pos] + left[pos + 1:] same_name = [a for a in collected if a.name == self.name] if type(self.value) in (int, list): if type(self.value) is int: increment = 1 else: increment = ([match.value] if type(match.value) is str else match.value) if not same_name: match.value = increment return True, left_, collected + [match] same_name[0].value += increment return True, left_, collected return True, left_, collected + [match] class BranchPattern(Pattern): """Branch/inner node of a pattern tree.""" def __init__(self, *children): self.children = list(children) def __repr__(self): return '%s(%s)' % (self.__class__.__name__, ', '.join(repr(a) for a in self.children)) def flat(self, *types): if type(self) in types: return [self] return sum([child.flat(*types) for child in self.children], []) class Argument(LeafPattern): def single_match(self, left): for n, pattern in enumerate(left): if type(pattern) is Argument: return n, Argument(self.name, pattern.value) return None, None @classmethod def parse(class_, source): name = re.findall('(<\S*?>)', source)[0] value = re.findall('\[default: (.*)\]', source, flags=re.I) return class_(name, value[0] if value else None) class Command(Argument): def __init__(self, name, value=False): self.name, self.value = name, value def single_match(self, left): for n, pattern in enumerate(left): if type(pattern) is Argument: if pattern.value == self.name: return n, Command(self.name, True) else: break return None, None class Option(LeafPattern): def __init__(self, short=None, long=None, argcount=0, value=False): assert argcount in (0, 1) self.short, self.long, self.argcount = short, long, argcount self.value = None if value is False and argcount else value @classmethod def parse(class_, option_description): short, long, argcount, value = None, None, 0, False options, _, description = option_description.strip().partition(' ') options = options.replace(',', ' ').replace('=', ' ') for s in options.split(): if s.startswith('--'): long = s elif s.startswith('-'): short = s else: argcount = 1 if argcount: matched = re.findall('\[default: (.*)\]', description, flags=re.I) value = matched[0] if matched else None return class_(short, long, argcount, value) def single_match(self, left): for n, pattern in enumerate(left): if self.name == pattern.name: return n, pattern return None, None @property def name(self): return self.long or self.short def __repr__(self): return 'Option(%r, %r, %r, %r)' % (self.short, self.long, self.argcount, self.value) class Required(BranchPattern): def match(self, left, collected=None): collected = [] if collected is None else collected l = left c = collected for pattern in self.children: matched, l, c = pattern.match(l, c) if not matched: return False, left, collected return True, l, c class Optional(BranchPattern): def match(self, left, collected=None): collected = [] if collected is None else collected for pattern in self.children: m, left, collected = pattern.match(left, collected) return True, left, collected class OptionsShortcut(Optional): """Marker/placeholder for [options] shortcut.""" class OneOrMore(BranchPattern): def match(self, left, collected=None): assert len(self.children) == 1 collected = [] if collected is None else collected l = left c = collected l_ = None matched = True times = 0 while matched: # could it be that something didn't match but changed l or c? matched, l, c = self.children[0].match(l, c) times += 1 if matched else 0 if l_ == l: break l_ = l if times >= 1: return True, l, c return False, left, collected class Either(BranchPattern): def match(self, left, collected=None): collected = [] if collected is None else collected outcomes = [] for pattern in self.children: matched, _, _ = outcome = pattern.match(left, collected) if matched: outcomes.append(outcome) if outcomes: return min(outcomes, key=lambda outcome: len(outcome[1])) return False, left, collected class Tokens(list): def __init__(self, source, error=DocoptExit): self += source.split() if hasattr(source, 'split') else source self.error = error @staticmethod def from_pattern(source): source = re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source) source = [s for s in re.split('\s+|(\S*<.*?>)', source) if s] return Tokens(source, error=DocoptLanguageError) def move(self): return self.pop(0) if len(self) else None def current(self): return self[0] if len(self) else None def parse_long(tokens, options): """long ::= '--' chars [ ( ' ' | '=' ) chars ] ;""" long, eq, value = tokens.move().partition('=') assert long.startswith('--') value = None if eq == value == '' else value similar = [o for o in options if o.long == long] if tokens.error is DocoptExit and similar == []: # if no exact match similar = [o for o in options if o.long and o.long.startswith(long)] if len(similar) > 1: # might be simply specified ambiguously 2+ times? raise tokens.error('%s is not a unique prefix: %s?' % (long, ', '.join(o.long for o in similar))) elif len(similar) < 1: argcount = 1 if eq == '=' else 0 o = Option(None, long, argcount) options.append(o) if tokens.error is DocoptExit: o = Option(None, long, argcount, value if argcount else True) else: o = Option(similar[0].short, similar[0].long, similar[0].argcount, similar[0].value) if o.argcount == 0: if value is not None: raise tokens.error('%s must not have an argument' % o.long) else: if value is None: if tokens.current() in [None, '--']: raise tokens.error('%s requires argument' % o.long) value = tokens.move() if tokens.error is DocoptExit: o.value = value if value is not None else True return [o] def parse_shorts(tokens, options): """shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;""" token = tokens.move() assert token.startswith('-') and not token.startswith('--') left = token.lstrip('-') parsed = [] while left != '': short, left = '-' + left[0], left[1:] similar = [o for o in options if o.short == short] if len(similar) > 1: raise tokens.error('%s is specified ambiguously %d times' % (short, len(similar))) elif len(similar) < 1: o = Option(short, None, 0) options.append(o) if tokens.error is DocoptExit: o = Option(short, None, 0, True) else: # why copying is necessary here? o = Option(short, similar[0].long, similar[0].argcount, similar[0].value) value = None if o.argcount != 0: if left == '': if tokens.current() in [None, '--']: raise tokens.error('%s requires argument' % short) value = tokens.move() else: value = left left = '' if tokens.error is DocoptExit: o.value = value if value is not None else True parsed.append(o) return parsed def parse_pattern(source, options): tokens = Tokens.from_pattern(source) result = parse_expr(tokens, options) if tokens.current() is not None: raise tokens.error('unexpected ending: %r' % ' '.join(tokens)) return Required(*result) def parse_expr(tokens, options): """expr ::= seq ( '|' seq )* ;""" seq = parse_seq(tokens, options) if tokens.current() != '|': return seq result = [Required(*seq)] if len(seq) > 1 else seq while tokens.current() == '|': tokens.move() seq = parse_seq(tokens, options) result += [Required(*seq)] if len(seq) > 1 else seq return [Either(*result)] if len(result) > 1 else result def parse_seq(tokens, options): """seq ::= ( atom [ '...' ] )* ;""" result = [] while tokens.current() not in [None, ']', ')', '|']: atom = parse_atom(tokens, options) if tokens.current() == '...': atom = [OneOrMore(*atom)] tokens.move() result += atom return result def parse_atom(tokens, options): """atom ::= '(' expr ')' | '[' expr ']' | 'options' | long | shorts | argument | command ; """ token = tokens.current() result = [] if token in '([': tokens.move() matching, pattern = {'(': [')', Required], '[': [']', Optional]}[token] result = pattern(*parse_expr(tokens, options)) if tokens.move() != matching: raise tokens.error("unmatched '%s'" % token) return [result] elif token == 'options': tokens.move() return [OptionsShortcut()] elif token.startswith('--') and token != '--': return parse_long(tokens, options) elif token.startswith('-') and token not in ('-', '--'): return parse_shorts(tokens, options) elif token.startswith('<') and token.endswith('>') or token.isupper(): return [Argument(tokens.move())] else: return [Command(tokens.move())] def parse_argv(tokens, options, options_first=False): """Parse command-line argument vector. If options_first: argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ; else: argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ; """ parsed = [] while tokens.current() is not None: if tokens.current() == '--': return parsed + [Argument(None, v) for v in tokens] elif tokens.current().startswith('--'): parsed += parse_long(tokens, options) elif tokens.current().startswith('-') and tokens.current() != '-': parsed += parse_shorts(tokens, options) elif options_first: return parsed + [Argument(None, v) for v in tokens] else: parsed.append(Argument(None, tokens.move())) return parsed def parse_defaults(doc): defaults = [] for s in parse_section('options:', doc): # FIXME corner case "bla: options: --foo" _, _, s = s.partition(':') # get rid of "options:" split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:] split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])] options = [Option.parse(s) for s in split if s.startswith('-')] defaults += options return defaults def parse_section(name, source): pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)', re.IGNORECASE | re.MULTILINE) return [s.strip() for s in pattern.findall(source)] def formal_usage(section): _, _, section = section.partition(':') # drop "usage:" pu = section.split() return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )' def extras(help, version, options, doc): if help and any((o.name in ('-h', '--help')) and o.value for o in options): print(doc.strip("\n")) sys.exit() if version and any(o.name == '--version' and o.value for o in options): print(version) sys.exit() class Dict(dict): def __repr__(self): return '{%s}' % ',\n '.join('%r: %r' % i for i in sorted(self.items())) def docopt(doc, argv=None, help=True, version=None, options_first=False): """Parse `argv` based on command-line interface described in `doc`. `docopt` creates your command-line interface based on its description that you pass as `doc`. Such description can contain --options, , commands, which could be [optional], (required), (mutually | exclusive) or repeated... Parameters ---------- doc : str Description of your command-line interface. argv : list of str, optional Argument vector to be parsed. sys.argv[1:] is used if not provided. help : bool (default: True) Set to False to disable automatic help on -h or --help options. version : any object If passed, the object will be printed if --version is in `argv`. options_first : bool (default: False) Set to True to require options precede positional arguments, i.e. to forbid options and positional arguments intermix. Returns ------- args : dict A dictionary, where keys are names of command-line elements such as e.g. "--verbose" and "", and values are the parsed values of those elements. Example ------- >>> from docopt import docopt >>> doc = ''' ... Usage: ... my_program tcp [--timeout=] ... my_program serial [--baud=] [--timeout=] ... my_program (-h | --help | --version) ... ... Options: ... -h, --help Show this screen and exit. ... --baud= Baudrate [default: 9600] ... ''' >>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30'] >>> docopt(doc, argv) {'--baud': '9600', '--help': False, '--timeout': '30', '--version': False, '': '127.0.0.1', '': '80', 'serial': False, 'tcp': True} See also -------- * For video introduction see http://docopt.org * Full documentation is available in README.rst as well as online at https://github.com/docopt/docopt#readme """ argv = sys.argv[1:] if argv is None else argv usage_sections = parse_section('usage:', doc) if len(usage_sections) == 0: raise DocoptLanguageError('"usage:" (case-insensitive) not found.') if len(usage_sections) > 1: raise DocoptLanguageError('More than one "usage:" (case-insensitive).') DocoptExit.usage = usage_sections[0] options = parse_defaults(doc) pattern = parse_pattern(formal_usage(DocoptExit.usage), options) # [default] syntax for argument is disabled #for a in pattern.flat(Argument): # same_name = [d for d in arguments if d.name == a.name] # if same_name: # a.value = same_name[0].value argv = parse_argv(Tokens(argv), list(options), options_first) pattern_options = set(pattern.flat(Option)) for options_shortcut in pattern.flat(OptionsShortcut): doc_options = parse_defaults(doc) options_shortcut.children = list(set(doc_options) - pattern_options) #if any_options: # options_shortcut.children += [Option(o.short, o.long, o.argcount) # for o in argv if type(o) is Option] extras(help, version, argv, doc) matched, left, collected = pattern.fix().match(argv) if matched and left == []: # better error message if left? return Dict((a.name, a.value) for a in (pattern.flat() + collected)) raise DocoptExit() docopt/inst/spec/generate_tests.R0000644000176200001440000000370113671356716016630 0ustar liggesuserslibrary(rjson) library(stringr) library(whisker) #TODO extract comments and introduce sections. cases <- c(readLines("testcases.docopt"), "\n") cases <- paste0(cases, collapse="\n") # remove comments (TODO improve) cases <- str_replace_all(cases, "#.+?\n", "") cases <- str_replace_all(cases, ",\n", ",") cases <- unlist(str_split(cases, "\nr")) #case1 <- cases[1] p_usage <- 'r?\\"\\"\\"(.*?)\\"\\"\\"\n' p_test <- '^([^\n]+)\n(.+?)\n\n' p_prog <- '\\$ prog([^\n]*)\n([^\n]*)\n' i <- 1 cases <- lapply(cases, function(x){ case <- list() # extract usage text case$usage <- str_trim(str_match(x, p_usage)[,2]) case$name <- str_c("doc", str_pad(i, 2, pad="0")) i <<- i + 1 tests <- str_match_all(x, p_prog)[[1]] if (length(tests)==0){ case$failed <- str_replace_all(x, "(^|\n)", "\\1\t\t#") return(case) } case$tests <- apply(tests, 1, function(r){ if (str_sub(r[3],1,1) == "{"){ json <- fromJSON(r[3]) output <- deparse(json, control="keepNA", width.cutoff = 500) error <- FALSE } else { json <- list() output <- r[3] error <- TRUE } test <- str_replace_all(str_trim(r[1]), "(^|\n)", "\\1\t\t#") keys <- deparse(names(json)) list(test=test, args=str_trim(r[2]), output=output, error=error, keys=keys , len=length(json)) }) case }) template <- " {{#cases}} ##################### context('{{{name}}}') doc <- '{{{usage}}}' {{#failed}} # # TEST GENERATION FAILED # {{{.}}} test_that('failed', stop()) {{/failed}} {{#tests}} test_that('parsing \"{{{args}}}\" works',{ {{{test}}} {{^error}} res <- docopt(doc, '{{{args}}}', strict=TRUE) expect_equivalent(length(res), {{{len}}}) expect_equivalent(res[{{{keys}}}], {{{output}}}) {{/error}} {{#error}} expect_error(docopt(doc, '{{{args}}}', strict=TRUE)) {{/error}} }) {{/tests}} {{/cases}} " writeLines(whisker.render(template), "../../tests/testthat/test_specs.R") docopt/inst/spec/testcases.docopt0000644000176200001440000002730213671356716016704 0ustar liggesusersr"""Usage: prog """ $ prog {} $ prog --xxx "user-error" r"""Usage: prog [options] Options: -a All. """ $ prog {"-a": false} $ prog -a {"-a": true} $ prog -x "user-error" r"""Usage: prog [options] Options: --all All. """ $ prog {"--all": false} $ prog --all {"--all": true} $ prog --xxx "user-error" r"""Usage: prog [options] Options: -v, --verbose Verbose. """ $ prog --verbose {"--verbose": true} $ prog --ver {"--verbose": true} $ prog -v {"--verbose": true} r"""Usage: prog [options] Options: -p PATH """ $ prog -p home/ {"-p": "home/"} $ prog -phome/ {"-p": "home/"} $ prog -p "user-error" r"""Usage: prog [options] Options: --path """ $ prog --path home/ {"--path": "home/"} $ prog --path=home/ {"--path": "home/"} $ prog --pa home/ {"--path": "home/"} $ prog --pa=home/ {"--path": "home/"} $ prog --path "user-error" r"""Usage: prog [options] Options: -p PATH, --path= Path to files. """ $ prog -proot {"--path": "root"} r"""Usage: prog [options] Options: -p --path PATH Path to files. """ $ prog -p root {"--path": "root"} $ prog --path root {"--path": "root"} r"""Usage: prog [options] Options: -p PATH Path to files [default: ./] """ $ prog {"-p": "./"} $ prog -phome {"-p": "home"} r"""UsAgE: prog [options] OpTiOnS: --path= Path to files [dEfAuLt: /root] """ $ prog {"--path": "/root"} $ prog --path=home {"--path": "home"} r"""usage: prog [options] options: -a Add -r Remote -m Message """ $ prog -a -r -m Hello {"-a": true, "-r": true, "-m": "Hello"} $ prog -armyourass {"-a": true, "-r": true, "-m": "yourass"} $ prog -a -r {"-a": true, "-r": true, "-m": null} r"""Usage: prog [options] Options: --version --verbose """ $ prog --version {"--version": true, "--verbose": false} $ prog --verbose {"--version": false, "--verbose": true} $ prog --ver "user-error" $ prog --verb {"--version": false, "--verbose": true} r"""usage: prog [-a -r -m ] options: -a Add -r Remote -m Message """ $ prog -armyourass {"-a": true, "-r": true, "-m": "yourass"} r"""usage: prog [-armmsg] options: -a Add -r Remote -m Message """ $ prog -a -r -m Hello {"-a": true, "-r": true, "-m": "Hello"} r"""usage: prog -a -b options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog "user-error" r"""usage: prog (-a -b) options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog "user-error" r"""usage: prog [-a] -b options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog -b {"-a": false, "-b": true} $ prog "user-error" r"""usage: prog [(-a -b)] options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog -b "user-error" $ prog {"-a": false, "-b": false} r"""usage: prog (-a|-b) options: -a -b """ $ prog -a -b "user-error" $ prog "user-error" $ prog -a {"-a": true, "-b": false} $ prog -b {"-a": false, "-b": true} r"""usage: prog [ -a | -b ] options: -a -b """ $ prog -a -b "user-error" $ prog {"-a": false, "-b": false} $ prog -a {"-a": true, "-b": false} $ prog -b {"-a": false, "-b": true} r"""usage: prog """ $ prog 10 {"": "10"} $ prog 10 20 "user-error" $ prog "user-error" r"""usage: prog []""" $ prog 10 {"": "10"} $ prog 10 20 "user-error" $ prog {"": null} r"""usage: prog """ $ prog 10 20 40 {"": "10", "": "20", "": "40"} $ prog 10 20 "user-error" $ prog "user-error" r"""usage: prog [ ]""" $ prog 10 20 40 {"": "10", "": "20", "": "40"} $ prog 10 20 {"": "10", "": "20", "": null} $ prog "user-error" r"""usage: prog [ | ]""" $ prog 10 20 40 "user-error" $ prog 20 40 {"": null, "": "20", "": "40"} $ prog {"": null, "": null, "": null} r"""usage: prog ( --all | ) options: --all """ $ prog 10 --all {"": "10", "--all": true, "": null} $ prog 10 {"": null, "--all": false, "": "10"} $ prog "user-error" r"""usage: prog [ ]""" $ prog 10 20 {"": ["10", "20"]} $ prog 10 {"": ["10"]} $ prog {"": []} r"""usage: prog [( )]""" $ prog 10 20 {"": ["10", "20"]} $ prog 10 "user-error" $ prog {"": []} r"""usage: prog NAME...""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog "user-error" r"""usage: prog [NAME]...""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog [NAME...]""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog [NAME [NAME ...]]""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog (NAME | --foo NAME) options: --foo """ $ prog 10 {"NAME": "10", "--foo": false} $ prog --foo 10 {"NAME": "10", "--foo": true} $ prog --foo=10 "user-error" r"""usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar """ $ prog 10 {"NAME": ["10"], "--foo": false, "--bar": false} $ prog 10 20 {"NAME": ["10", "20"], "--foo": false, "--bar": false} $ prog --foo --bar {"NAME": [], "--foo": true, "--bar": true} r"""Naval Fate. Usage: prog ship new ... prog ship [] move [--speed=] prog ship shoot prog mine (set|remove) [--moored|--drifting] prog -h | --help prog --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Mored (anchored) mine. --drifting Drifting mine. """ $ prog ship Guardian move 150 300 --speed=20 {"--drifting": false, "--help": false, "--moored": false, "--speed": "20", "--version": false, "": ["Guardian"], "": "150", "": "300", "mine": false, "move": true, "new": false, "remove": false, "set": false, "ship": true, "shoot": false} r"""usage: prog --hello""" $ prog --hello {"--hello": true} r"""usage: prog [--hello=]""" $ prog {"--hello": null} $ prog --hello wrld {"--hello": "wrld"} r"""usage: prog [-o]""" $ prog {"-o": false} $ prog -o {"-o": true} r"""usage: prog [-opr]""" $ prog -op {"-o": true, "-p": true, "-r": false} r"""usage: prog --aabb | --aa""" $ prog --aa {"--aabb": false, "--aa": true} $ prog --a "user-error" # not a unique prefix # # Counting number of flags # r"""Usage: prog -v""" $ prog -v {"-v": true} r"""Usage: prog [-v -v]""" $ prog {"-v": 0} $ prog -v {"-v": 1} $ prog -vv {"-v": 2} r"""Usage: prog -v ...""" $ prog "user-error" $ prog -v {"-v": 1} $ prog -vv {"-v": 2} $ prog -vvvvvv {"-v": 6} r"""Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant. """ $ prog {"-v": 0} $ prog -v {"-v": 1} $ prog -vv {"-v": 2} $ prog -vvvv "user-error" r"""usage: prog [--ver --ver]""" $ prog --ver --ver {"--ver": 2} # # Counting commands # r"""usage: prog [go]""" $ prog go {"go": true} r"""usage: prog [go go]""" $ prog {"go": 0} $ prog go {"go": 1} $ prog go go {"go": 2} $ prog go go go "user-error" r"""usage: prog go...""" $ prog go go go go go {"go": 5} # # [options] does not include options from usage-pattern # r"""usage: prog [options] [-a] options: -a -b """ $ prog -a {"-a": true, "-b": false} $ prog -aa "user-error" # # Test [options] shourtcut # r"""Usage: prog [options] A Options: -q Be quiet -v Be verbose. """ $ prog arg {"A": "arg", "-v": false, "-q": false} $ prog -v arg {"A": "arg", "-v": true, "-q": false} $ prog -q arg {"A": "arg", "-v": false, "-q": true} # # Test single dash # r"""usage: prog [-]""" $ prog - {"-": true} $ prog {"-": false} # # If argument is repeated, its value should always be a list # r"""usage: prog [NAME [NAME ...]]""" $ prog a b {"NAME": ["a", "b"]} $ prog {"NAME": []} # # Option's argument defaults to null/None # r"""usage: prog [options] options: -a Add -m Message """ $ prog -a {"-m": null, "-a": true} # # Test options without description # r"""usage: prog --hello""" $ prog --hello {"--hello": true} r"""usage: prog [--hello=]""" $ prog {"--hello": null} $ prog --hello wrld {"--hello": "wrld"} r"""usage: prog [-o]""" $ prog {"-o": false} $ prog -o {"-o": true} r"""usage: prog [-opr]""" $ prog -op {"-o": true, "-p": true, "-r": false} r"""usage: git [-v | --verbose]""" $ prog -v {"-v": true, "--verbose": false} r"""usage: git remote [-v | --verbose]""" $ prog remote -v {"remote": true, "-v": true, "--verbose": false} # # Test empty usage pattern # r"""usage: prog""" $ prog {} r"""usage: prog prog """ $ prog 1 2 {"": "1", "": "2"} $ prog {"": null, "": null} r"""usage: prog prog """ $ prog {"": null, "": null} # # Option's argument should not capture default value from usage pattern # r"""usage: prog [--file=]""" $ prog {"--file": null} r"""usage: prog [--file=] options: --file """ $ prog {"--file": null} r"""Usage: prog [-a ] Options: -a, --address TCP address [default: localhost:6283]. """ $ prog {"--address": "localhost:6283"} # # If option with argument could be repeated, # its arguments should be accumulated into a list # r"""usage: prog --long= ...""" $ prog --long one {"--long": ["one"]} $ prog --long one --long two {"--long": ["one", "two"]} # # Test multiple elements repeated at once # r"""usage: prog (go --speed=)...""" $ prog go left --speed=5 go right --speed=9 {"go": 2, "": ["left", "right"], "--speed": ["5", "9"]} # # Required options should work with option shortcut # r"""usage: prog [options] -a options: -a """ $ prog -a {"-a": true} # # If option could be repeated its defaults should be split into a list # r"""usage: prog [-o ]... options: -o [default: x] """ $ prog -o this -o that {"-o": ["this", "that"]} $ prog {"-o": ["x"]} r"""usage: prog [-o ]... options: -o [default: x y] """ $ prog -o this {"-o": ["this"]} $ prog {"-o": ["x", "y"]} # # Test stacked option's argument # r"""usage: prog -pPATH options: -p PATH """ $ prog -pHOME {"-p": "HOME"} # # Issue 56: Repeated mutually exclusive args give nested lists sometimes # r"""Usage: foo (--xx=x|--yy=y)...""" $ prog --xx=1 --yy=2 {"--xx": ["1"], "--yy": ["2"]} # # POSIXly correct tokenization # r"""usage: prog []""" $ prog f.txt {"": "f.txt"} r"""usage: prog [--input=]...""" $ prog --input a.txt --input=b.txt {"--input": ["a.txt", "b.txt"]} # # Issue 85: `[options]` shourtcut with multiple subcommands # r"""usage: prog good [options] prog fail [options] options: --loglevel=N """ $ prog fail --loglevel 5 {"--loglevel": "5", "fail": true, "good": false} # # Usage-section syntax # r"""usage:prog --foo""" $ prog --foo {"--foo": true} r"""PROGRAM USAGE: prog --foo""" $ prog --foo {"--foo": true} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} # # Options-section syntax # r"""Usage: prog [options] global options: --foo local options: --baz --bar other options: --egg --spam -not-an-option- """ $ prog --baz --egg {"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false}