R/cli.R

Defines functions print.cli_function parse_cli_args

parse_cli_args <- function() {
  ## Parse command-line arguments
  cli_args <- commandArgs(trailingOnly = TRUE)
  ## Allow for testing different CLI options
  cli_args <- getOption(".port4me.commandArgs", cli_args)
  
  args <- list()
  while (length(cli_args) > 0) {
    arg <- cli_args[1]
    if (grepl(pattern <- "^--args$", arg)) {
      ## Ignore --args
    } else if (grepl(pattern <- "^--([[:alpha:]][[:alnum:]]*)=(.*)$", arg)) {
      name <- gsub(pattern, "\\1", arg)
      value <- gsub(pattern, "\\2", arg)
      if (grepl("^[+-]?[[:digit:]]+$", value)) {
        value_int <- suppressWarnings(as.integer(value))
        if (!is.na(value_int)) value <- value_int
      }
      args[[name]] <- value
    } else if (grepl(pattern <- "^--([[:alpha:]][[:alnum:]]*)$", arg)) {
      name <- gsub(pattern, "\\1", arg)
      args[[name]] <- I(TRUE)
    } else if (grepl(pattern <- "^--", arg)) {
      stop(sprintf("Unknown command-line argument: %s", arg))
    } else {
      args[[length(args) + 1L]] <- arg
    }
    cli_args <- cli_args[-1]
  }
  
  args
}


cli_help_string <- '
{{ package }}: {{ title }}

Usage:
 Rscript -e port4me::port4me [options]

Options:  
 --help             Display the full help page with examples
 --version          Output version of this software
 --debug            Output detailed debug information

 --user=<string>    User name (default: $USER)
 --tool=<string>    Name of software tool
 --include=<ports>  Set of ports to be included
                    (default: 1024-65535)
 --exclude=<ports>  Set of ports to be excluded
 --prepend=<ports>  Set of ports to be considered first

 --skip=<n>         Number of ports to skip
 --list=<n>         List the first \'n\', available or not, ports

 --test=<port>      Return 0 if port is available, otherwise 1

Examples:
Rscript -e port4me::port4me --version

Rscript -e port4me::port4me
Rscript -e port4me::port4me --tool=rstudio
Rscript -e port4me::port4me --include=11000-11999 --exclude=11500,11509 --tool=rstudio
Rscript -e port4me::port4me rstudio    ## short for --tool=rstudio

rserver --www-port "$(Rscript -e port4me::port4me rstudio)"
jupyter notebook --port "$(Rscript -e port4me::port4me jupyter-notebook)"

Rscript -e port4me::port4me --test=8087 && echo "free" || echo "taken"

Version: {{ version }}
Copyright: Henrik Bengtsson (2022-2024)
License: MIT
'


#' @importFrom utils packageDescription packageVersion
#' @export
print.cli_function <- function(x, ..., envir = parent.frame()) {
  if (interactive()) return(NextMethod())

  args <- parse_cli_args()

  if (isTRUE(args$debug)) {
    Sys.setenv(PORT4ME_DEBUG = "true")
    args$debug <- NULL
  }

  if (isTRUE(args$version)) {
    cat(as.character(packageVersion(.packageName)), "\n", sep = "")
  } else if (isTRUE(args$help)) {
    msg <- cli_help_string
    msg <- sub("{{ package }}", .packageName, msg, fixed = TRUE)
    msg <- sub("{{ title }}", packageDescription(.packageName)[["Title"]], msg, fixed = TRUE)
    msg <- sub("{{ version }}", packageVersion(.packageName), msg, fixed = TRUE)
    cat(msg)
  } else {
    res <- withVisible(do.call(x, args = args, envir = envir))
    
    # Should the result be printed?
    if (res$visible) {
      value <- res$value
      if (is.integer(value)) {
        cat(sprintf("%i\n", value), collapse = "", sep = "")
      } else if (is.logical(value)) {
        quit(save = "no", status = as.integer(!value))
      }
    }
  }
  invisible()
}

Try the port4me package in your browser

Any scripts or data that you put into this service are public.

port4me documentation built on May 29, 2024, 3:23 a.m.