diff --git a/DESCRIPTION b/DESCRIPTION index 921f499..013e579 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: argparse Type: Package Title: Command Line Optional and Positional Argument Parser -Version: 2.1.5 -Authors@R: c(person("Trevor L", "Davis", role=c("aut", "cre"), +Version: 2.1.6 +Authors@R: c(person("Trevor L", "Davis", role=c("aut", "cre"), email="trevor.l.davis@gmail.com", comment = c(ORCID = "0000-0001-6341-4639")), person("Allen", "Day", role="ctb", comment="Some documentation and examples ported from the getopt package."), @@ -16,6 +16,8 @@ Copyright: See file (inst/)COPYRIGHTS. URL: https://github.com/trevorld/r-argparse BugReports: https://github.com/trevorld/r-argparse/issues LazyLoad: yes +Depends: + R (>= 3.6.0) Imports: R6, findpython, diff --git a/NEWS.md b/NEWS.md index 954f4cd..b491b76 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,19 @@ +argparse 2.1.6 +============== + +* The errors raised by `ArgumentParser()$parse_args()` are now of class "argparse_parse_error". + + They are now less verbose when `interactive()` is `FALSE` (#40). + + There may still a trailing "Execution halted" line output by R's default error handler + (when `interactive()` is `FALSE`). + This can be silenced by setting a new error handler near the top of your Rscript e.g. + + ```r + if (!interactive()) + options(error=function(e) quit('no', status = 1, runLast = FALSE)) + ``` + argparse 2.1.5 ============== diff --git a/R/argparse.R b/R/argparse.R index 2b55161..030c40e 100644 --- a/R/argparse.R +++ b/R/argparse.R @@ -202,27 +202,27 @@ parse_args_output <- function(output) { has_positional_arguments <- any(grepl("^positional arguments:", output)) has_optional_arguments <- any(grepl("^optional arguments:|^options:", output)) if (has_positional_arguments || has_optional_arguments) { - .print_message_and_exit(output, "help requested:") + print_message_and_exit(output, "help requested:") } else { - .stop(output, "parse error:") + pa_stop(output) } } else if (grepl("^Traceback", output[1])) { - .stop(output, "Error: python error") + pa_stop(output) } else if (any(grepl("^SyntaxError: Non-ASCII character", output))) { message <- paste("Non-ASCII character detected.", "If you wish to use Unicode arguments/options", "please upgrade to Python 3.2+", "Please see file INSTALL for more details.") - .stop(message, "non-ascii character error:") + pa_stop(message) } else if (any(grepl("^SyntaxError: positional argument follows keyword argument", output)) || grepl("^SyntaxError: non-keyword arg after keyword arg", output[2])) { message <- "Positional argument following keyword argument." - .stop(message, "syntax error:") + pa_stop(message) } else if (grepl("^\\{|^\\[", output)) { args <- jsonlite::fromJSON(paste(output, collapse = "")) return(args) } else { # presumably version number request - .print_message_and_exit(output, "version requested:") + print_message_and_exit(output, "version requested:") } } @@ -358,16 +358,28 @@ find_python_cmd <- function(python_cmd = NULL) { python_cmd } -.stop <- function(message, r_note) { - stop(paste(r_note, paste(message, collapse = "\n"), sep = "\n")) +pa_stop <- function(message) { + msg <- paste(c("argparse_parse_error", message), collapse = "\n") + cnd <- errorCondition(msg, + call = "argparse::parse_args_output(output)", + class = "argparse_parse_error") + if (interactive()) { + stop(cnd) + } else { + signalCondition(cnd) + cat(message, sep = "\n", file = stderr()) + opt <- options(show.error.messages = FALSE) + on.exit(options(opt)) + stop(cnd) + } } # Internal function to print message -.print_message_and_exit <- function(message, r_note) { +print_message_and_exit <- function(message, r_note, status = 0) { if (interactive()) { - .stop(message, r_note) + pa_stop(message, r_note) } else { cat(message, sep = "\n") - quit(status = 0) + quit(status = status) } } diff --git a/README.rst b/README.rst index c1f0601..edafb4f 100644 --- a/README.rst +++ b/README.rst @@ -124,7 +124,7 @@ as well as mutually exclusive groups:: $foo [1] FALSE > parser$parse_args(c('--foo', '--bar')) - Error in .stop(output, "parse error:") : parse error: + Error in "argparse::parse_args_output(output)" : parse error: usage: PROG [-h] [--foo | --bar] PROG: error: argument --bar: not allowed with argument --foo diff --git a/cran-comments.rst b/cran-comments.rst index 7924d1e..1f0247c 100644 --- a/cran-comments.rst +++ b/cran-comments.rst @@ -4,7 +4,7 @@ Rscript) if ``parse_args()`` observes a help flag it will print a usage message and then call ``quit()``. Additionally if a user specifically adds a 'version' argument to the command-line parser with `action='version'` then - if ``parse_args()`` also observes a version flag while in a non-interactive + if ``parse_args()`` observes a version flag while in a non-interactive session then it will print the version number and then call ``quit()``. * This package has a Python dependency most easily satisfied having (C)Python @@ -12,7 +12,7 @@ ## Test environments -* local (linux), R 4.1.3 +* local (linux), R 4.2.1 * win-builder (windows), R devel * Github Actions (linux), R devel, release, oldrel * Github Actions (windows), R release