docopt / docopt.R

Command-line interface description language for R (http://docopt.org)
Other
210 stars 17 forks source link

Embedded space in parameter values #11

Closed jennybc closed 8 years ago

jennybc commented 9 years ago

Thanks for providing this docopt implementation for R!

I was pleased to see it can handle quoted arguments. I'm a little surprised that the example below -- where I have spaces embedded in a parameter value -- doesn't work.

Homework & context:

Sample R script foo.R:

#!/usr/bin/Rscript

suppressPackageStartupMessages(library(docopt))

"docopt practice script

Usage: foo.R [-i <integers>]

Options:
     -i <integers>, --integers=<integers>  Integers [default: 1]
" -> doc

"%||%" <- function(a, b) if (!is.null(a)) a else b
opts <- docopt(doc)
my_ints <- opts$integers %||% opts$i
my_ints <- as.integer(eval(parse(text = my_ints)))
cat(sprintf("integers = %s\n", paste(my_ints, collapse = ", ")))

Basically I want to pass an R expression that will generate an atomic vector of integers. Some successful usage and some less successful:

Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R
integers = 1
Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R -i 4
integers = 4
Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R -i 2:4
integers = 2, 3, 4
Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R -i 'c(1,8)'
integers = 1, 8
Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R -i 'c(1, 8)'
Error in docopt(doc) : usage: foo.R [-i <integers>]
Execution halted
Jennifers-MacBook-Pro-3:scripts jenny$ ./foo.R -i 'c(1,\ 8)'
Error in docopt(doc) : usage: foo.R [-i <integers>]
Execution halted

Obviously I can just avoid using spaces! But it got me wondering about the general question. Any thoughts?

BTW you might find it interesting that something special and bad happens if you try to use an option with short form -g: a question I asked on stackoverflow.

keleshev commented 9 years ago

The try.docopt.org doesn't handle shell escaping rules—it just splits the string on whitespace unfortunately.

However, the reference implementation does what you expect:

"""docopt practice script

Usage: foo.R [-i <integers>]

Options:
     -i <integers>, --integers=<integers>  Integers [default: 1]

"""
from docopt import docopt

print(docopt(__doc__))

Given '-i c(1, 8)' this prints {'--integers': ' c(1, 8)'}. -i 'c(1, 8)' also works.

So this seems to be an error in R port.

edwindj commented 9 years ago

Thanks for reporting! I will look into it tommorow.

Best regards,

Edwin

edwindj commented 9 years ago

@jennybc: I have added a test with your example and it seems to works with the latest github version.

The problem was that base::commandArgs which is used by docopt.R removes quotes.

Question: I would like to change the methods "Depends" into an "Imports". Before R 3.2 this was a problem (aka R bug). Would it be a problem for you if the CRAN update is (R >= 3.2)? Otherwise I save that change for later.

Best,

Edwin

jennybc commented 9 years ago

Thanks @edwindj for the fix! I would be fine if the CRAN update requires R >= 3.2, so go right ahead as far as I'm concerned.

malcook commented 9 years ago

Hi @edwindj,

I'm not seeing this as fixed (or not understanding the intention of quoted_args)

My script, qtest, is as follows:

#!/usr/bin/env Rscript
'usage: qtest <s> [<more>...]
' -> doc

str(commandArgs(TRUE))
suppressPackageStartupMessages({
    ## load the docopt library
    library(docopt)
})

opt <- docopt(doc, quoted_args=TRUE)
str(opt)  

I would expect that opt$s would be "hello world" when called as below, but, alas it is not.

./qtest "hello world"
 chr "hello world"
List of 4
 $ <s>   : chr "hello"
 $ <more>: chr "world"
 $ s     : chr "hello"
 $ more  : chr "world"
 - attr(*, "class")= chr [1:2] "docopt" "list"

Can you advise?

Note the script shows that commandArgs is seeing "hello world" as a single value.

I am using docopt_0.4.4 on R version 3.2.1 (2015-06-18)

edwindj commented 9 years ago

@malcook Thanks for reporting: it is a bug, that only happens when one argument is given:

../qtest "hello world" more does work...

I will look into it tomorrow

Best,

Edwin

edwindj commented 9 years ago

@malcook: should be fixed...

cysouw commented 9 years ago

It still does not work here, even after installing the latest updates. Try this really minimal example:

#!/usr/bin/env Rscript
library(docopt)
DOC <- "USAGE: foo ARG"
attach(docopt(DOC))
print(ARG)

It will work without spaces, but not with spaces, e.g. foo bla works, but not foo 'bla bla'

Also note that passing a star does not work (which is useful to mimic typical bash usage to execute something on a whole directory): foo * does not work, you have to use foo '*', which is rather un-bash-like...

Great work though, and please keep up this great project!

randomee commented 8 years ago

This seems to be still broken.

I'm working around it for now by embedding _ where I'd like a space, then using gsub inside R to clean it up. Not ideal.

Any chance this could get another look? Thanks

edwindj commented 8 years ago

I will be working on it the end of this week

randomee commented 8 years ago

Any luck on this?

Thanks

ajwnewkirk commented 8 years ago

I'm also curious about the status of this. Just taught a class on docopt to 40+ people in my agency yesterday, and this question generated a lot of interest when it came up.

edwindj commented 8 years ago

I may have solved this a long time ago, but did not upload it yet to CRAN. Could you please check if your problem is solved with the current version on github

devtools::install_github('docopt/docopt.R')

If fixed, I will uploaded it to CRAN asap, so it will be official.

Best, Edwin

ajwnewkirk commented 8 years ago

Thanks for the response, Edwin.

I installed the GitHub version and ran a minimal example similar to the one cysouw used above:

#!/usr/bin/Rscript

library(docopt)
doc <- "USAGE: foo ARG"
args <- docopt(doc = doc, quoted_args = TRUE)
print(sessionInfo())
print(args$ARG)

I get the following output on my system:

GIGte_programmaticR$ ./test.R Jo Loading required package: methods R version 3.2.5 (2016-04-14) Platform: x86_64-pc-linux-gnu (64-bit) Running under: Ubuntu 14.04.4 LTS

locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages: [1] methods stats graphics grDevices utils datasets base

other attached packages: [1] docopt_0.4.5

loaded via a namespace (and not attached): [1] magrittr_1.5 tools_3.2.5 stringi_1.0-1 stringr_1.0.0 [1] "Jo"

GIGte_programmaticR$ ./test.R "Jo Williams" Loading required package: methods Error: usage: foo ARG Execution halted GIGte_programmaticR$ ./test.R 'Jo Williams' Loading required package: methods Error: usage: foo ARG Execution halted

Am I missing something? Thank you for your help.

edwindj commented 8 years ago

Thanks for your detailed report! I think I found the problem; it was a subtle difference between Windows and Ubuntu.

I have made some changes: Could you check again if your problem is solved? (your code is now running fine on my Ubuntu 15.10).

cysouw commented 8 years ago

YES! works here now spaces work. I'll make a new issue about stars :-) best michael

R version 3.2.2 (2015-08-14) Platform: x86_64-apple-darwin13.4.0 (64-bit) Running under: OS X 10.11.4 (El Capitan)

locale: [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages: [1] methods stats graphics grDevices utils datasets base

other attached packages: [1] docopt_0.4.5

loaded via a namespace (and not attached): [1] magrittr_1.5 tools_3.2.2 stringi_1.0-1 stringr_1.0.0

ajwnewkirk commented 8 years ago

The minimal example I posted is now working on my system as well - thank you!

burgerga commented 8 years ago

Any idea on when this will make it to CRAN?

edwindj commented 8 years ago

Thx for reminding :-), I will send it to CRAN within two days.

edwindj commented 8 years ago

on its way to CRAN (will close it when accepted)