66
77
88pkg.globals <- new.env()
9+ pkg.globals $ initialized <- FALSE
910
1011# ' Define an enum for different modes; access with argsType$<enum_element>
1112# ' ht https://stackoverflow.com/questions/33838392/enum-like-arguments-in-r
@@ -136,16 +137,20 @@ usage <- function() {
136137# ' @examples
137138# ' init_command_line_parser('MyCheckbook.R','My checkbook program', '1.0.0')
138139init_command_line_parser <- function (script , desc , ver = NA ) {
140+ pkg.globals $ initialized <- TRUE
139141 pkg.globals $ script <- script
140142 pkg.globals $ desc_str <- desc
141143 pkg.globals $ ver <- ver
142144 # tables to hold the possible command line params
143- pkg.globals $ args_table <- data.frame (lparam = c(NA ,' --help' ), sparam = c(NA ,' -?' ), var = c(NA ,' help' ),
144- default = c(NA ,FALSE ), argType = c(NA ,argsType $ TypeBool ),
145- help = c(NA ," Display help message" ), stringsAsFactors = FALSE )
145+ pkg.globals $ args_table <- data.frame (lparam = NA , sparam = NA , var = NA , default = NA , argType = NA ,
146+ help = NA , stringsAsFactors = FALSE )
146147 pkg.globals $ cmds_table <- data.frame (cmd = NA , help = NA , stringsAsFactors = FALSE )
147148 pkg.globals $ subcmds_table <- data.frame (subcmd = NA , parent = NA , help = NA , stringsAsFactors = FALSE )
148149
150+ # add a 'help' param
151+ reg_argument(lparam = ' --help' , sparam = ' -?' , var = ' help' , default = FALSE , argType = argsType $ TypeBool ,
152+ help = ' Display help message' )
153+
149154} # init_command_line_parser
150155
151156
@@ -160,7 +165,8 @@ init_command_line_parser <- function (script, desc, ver = NA) {
160165# # help: help string for the param, for usage()
161166# #
162167reg_command <- function (cmd , help = ' ' ) {
163- if (is.na(pkg.globals $ desc_str )) {
168+ # if (is.na(pkg.globals$desc_str)) {
169+ if (! pkg.globals $ initialized ) {
164170 stop(" Error: reg_command(): Command line parser not initialized." , call. = FALSE )
165171 }
166172
@@ -175,24 +181,24 @@ reg_command <- function(cmd, help = '') {
175181
176182# ' Register commands using a list
177183# '
178- # ' @param clist list of commands
184+ # ' @param clist list of lists of commands: command, help string
179185# '
180186# ' @export
181187# '
182188# ' @examples
183189# ' cmds <- list(
184- # ' c ("withdraw", "add a withdrawal"),
185- # ' c ("plot", "graph output"),
186- # ' c ("deposit", "add a deposit"),
187- # ' c ("edit", "update a record"),
188- # ' c ("find", "find a record")
190+ # ' list ("withdraw", "add a withdrawal"),
191+ # ' list ("plot", "graph output"),
192+ # ' list ("deposit", "add a deposit"),
193+ # ' list ("edit", "update a record"),
194+ # ' list ("find", "find a record")
189195# ' )
190196# ' reg_command_list(cmds)
191197reg_command_list <- function (clist ) {
192198 ids <- c(" cmd" ," help" )
193199 for (c in clist ) {
194200 stopifnot(length(c ) == length(ids ))
195- reg_command(cmd = c [1 ] , help = c [2 ])
201+ reg_command(cmd = c [[ 1 ]] , help = c [[ 2 ] ])
196202 }
197203} # reg_command_list
198204
@@ -209,7 +215,8 @@ reg_command_list <- function(clist) {
209215# # help: help string for the param, for usage()
210216# #
211217reg_subcmd <- function (subcmd = subcmd , parent = parent , help = ' ' ) {
212- if (is.na(pkg.globals $ desc_str )) {
218+ # if (is.na(pkg.globals$desc_str)) {
219+ if (! pkg.globals $ initialized ) {
213220 stop(" Error: reg_subcmd(): Command line parser not initialized." , call. = FALSE )
214221 }
215222
@@ -225,23 +232,23 @@ reg_subcmd <- function(subcmd = subcmd, parent = parent, help = '') {
225232
226233# ' Register subcommands using a list
227234# '
228- # ' @param slist list of subcommands
235+ # ' @param slist list of lists of subcommands: subcmd, parent, help string
229236# '
230237# ' @export
231238# '
232239# ' @examples
233240# ' subcmds <- list(
234- # ' c ("paycheck", "deposit", "add a paycheck deposit"),
235- # ' c ("reimbursement", "deposit", "add a reimbursement"),
236- # ' c ("bankfee", "withdraw", "add a bank fee"),
237- # ' c ("check", "deposit", "add a check deposit")
241+ # ' list ("paycheck", "deposit", "add a paycheck deposit"),
242+ # ' list ("reimbursement", "deposit", "add a reimbursement"),
243+ # ' list ("bankfee", "withdraw", "add a bank fee"),
244+ # ' list ("check", "deposit", "add a check deposit")
238245# ' )
239246# ' reg_subcmd_list(subcmds)
240247reg_subcmd_list <- function (slist ) {
241248 ids <- c(" subcmd" ," parent" ," help" )
242249 for (s in slist ) {
243250 stopifnot(length(s ) == length(ids ))
244- reg_subcmd(subcmd = s [1 ] , parent = s [2 ] , help = s [3 ])
251+ reg_subcmd(subcmd = s [[ 1 ]] , parent = s [[ 2 ]] , help = s [[ 3 ] ])
245252 }
246253} # reg_subcmd_list
247254
@@ -264,7 +271,8 @@ reg_subcmd_list <- function(slist) {
264271# # eg, "c("command1|subcmd1", "command2")
265272# #
266273reg_argument <- function (lparam , sparam , var , default , argType , help ) {
267- if (is.na(pkg.globals $ desc_str )) {
274+ # if (is.na(pkg.globals$desc_str)) {
275+ if (! pkg.globals $ initialized ) {
268276 stop(" Error: reg_argument(): Command line parser not initialized." , call. = FALSE )
269277 }
270278
@@ -273,6 +281,11 @@ reg_argument <- function(lparam, sparam, var, default, argType, help) {
273281 stop(paste(" Error: reg_argument(): duplicated param:" , lparam , sparam ), call. = FALSE )
274282 }
275283
284+ if (! argType %in% c(argsType $ TypeBool , argsType $ TypeValue , argsType $ TypeMultiVal ,
285+ argsType $ TypeCount , argsType $ TypeRange , argsType $ TypePositional ))
286+ stop(paste(" Error: reg_argument(): invalid argType:" , argType ))
287+ if (argType == argsType $ TypeBool ) default <- as.logical(default )
288+
276289 my_df <- data.frame (lparam = lparam , sparam = sparam , var = var , default = default , argType = argType ,
277290 help = help , stringsAsFactors = FALSE )
278291 pkg.globals $ args_table <- rbind(pkg.globals $ args_table , my_df )
@@ -281,51 +294,55 @@ reg_argument <- function(lparam, sparam, var, default, argType, help) {
281294
282295# ' Register command line arguments
283296# '
284- # ' @param plist list of arguments
297+ # ' @param plist list of lists of arguments: lparam, sparam, var, default, argType, help string
285298# '
286299# ' @export
287300# '
288301# ' @examples
289302# ' arguments <- list(
290- # ' c ("--outfile","-o","outfile",NA,argsType$TypeValue,'location of output file'),
291- # ' c ("--date","-d","date",NA,argsType$TypeValue,'specify date'),
292- # ' c ("--msg","-m","msg",NA,argsType$TypeValue,'memo line message'),
293- # ' c ("--amount","-a","amount",NA,argsType$TypeValue,'specify dollar amount'),
294- # ' c ("--payee","-p","payee",NA,argsType$TypeValue,'specify payee'))
303+ # ' list ("--outfile","-o","outfile",NA,argsType$TypeValue,'location of output file'),
304+ # ' list ("--date","-d","date",NA,argsType$TypeValue,'specify date'),
305+ # ' list ("--msg","-m","msg",NA,argsType$TypeValue,'memo line message'),
306+ # ' list ("--amount","-a","amount",NA,argsType$TypeValue,'specify dollar amount'),
307+ # ' list ("--payee","-p","payee",NA,argsType$TypeValue,'specify payee'))
295308# ' reg_argument_list(arguments)
296309reg_argument_list <- function (plist ) {
297310 # scope is not required. So, check for the 6 required params, and if no scope provided, set to NA
298311 ids <- c(" lparam" ," sparam" ," var" ," default" ," argType" ," help" )
299312
300313 for (p in plist ) {
301314 stopifnot (length(p ) == length(ids ))
302- reg_argument (lparam = p [1 ] , sparam = p [2 ] , var = p [3 ] , default = p [4 ],
303- argType = p [5 ] , help = p [6 ])
315+ reg_argument (lparam = p [[ 1 ]] , sparam = p [[ 2 ]] , var = p [[ 3 ]] , default = p [[ 4 ] ],
316+ argType = p [[ 5 ]] , help = p [[ 6 ] ])
304317 }
305318} # reg_argument_list
306319
307320
308321#
309322# Register a 'positional' command line argument (ie, the last argument in the list)
310323reg_positionals <- function (var , help ) {
324+ if (! pkg.globals $ initialized ) {
325+ stop(" Error: reg_positionals(): Command line parser not initialized." , call. = FALSE )
326+ }
327+
311328 reg_argument (lparam = NA , sparam = NA , var = var , default = NA , argType = argsType $ TypePositional , help = help )
312329} # reg_positionals
313330
314331
315332# ' Register a list of 'positional' arguments
316333# '
317- # ' @param plist list of positional arguments: variable name, help text
334+ # ' @param plist list of lists of positional arguments: variable name, help text
318335# '
319336# ' @export
320337# '
321338# ' @examples
322- # ' args <- list(c ("infile","input file"))
339+ # ' args <- list(list ("infile","input file"))
323340reg_positionals_list <- function (plist ) {
324341 ids <- c(" var" ," help" )
325342
326343 for (p in plist ) {
327344 stopifnot(length(p ) == length(ids ))
328- reg_positionals(var = p [1 ] , help = p [2 ])
345+ reg_positionals(var = p [[ 1 ]] , help = p [[ 2 ] ])
329346 }
330347} # reg_positionals_list
331348
@@ -403,6 +420,10 @@ parse_date <- function(d) {
403420# ' # writeLines (paste("infile:", mydata$infile))
404421# ' # writeLines (paste("outfile:",mydata$outfile))
405422parse_command_line <- function (args ) {
423+ if (! pkg.globals $ initialized ) {
424+ stop(" Error: parse_command_line(): Command line parser not initialized." , call. = FALSE )
425+ }
426+
406427 # remove the first line of the tables, which are all NA
407428 args_table <- pkg.globals $ args_table [- 1 ,]
408429 cmds_table <- pkg.globals $ cmds_table [- 1 ,]
@@ -413,7 +434,7 @@ parse_command_line <- function(args) {
413434 # if neither reg_arguments() nor reg_command() has been called, there's no table to process;
414435 # return the args as a list under the name 'unknowns'
415436 if (nrow(args_table ) == 0 && nrow(cmds_table ) == 0 ) {
416- writeLines (" Warning: new_parse_command_line (): no cmdline params or commands registered." )
437+ writeLines (" Warning: parse_command_line (): no cmdline params or commands registered." )
417438 return (list (unknowns = args ))
418439 }
419440
@@ -436,10 +457,10 @@ parse_command_line <- function(args) {
436457 mydata <- vector(" list" , nrow(args_table ))
437458 names(mydata ) <- args_table $ var
438459 for (name in names(mydata )) {
439- mydata [[ name ]] <- args_table $ default [args_table $ var == name ]
440- if ( args_table $ argType [ args_table $ var == name ] == argsType $ TypeBool ) {
441- mydata [[ name ]] <- as.logical( mydata [[ name ]])
442- }
460+ myrow <- args_table [args_table $ var == name , ]
461+ mydata [[ name ]] <- myrow $ default
462+ # ensure TypeBool is in fact a Bool
463+ if ( myrow $ argType == argsType $ TypeBool ) mydata [[ name ]] <- as.logical( mydata [[ name ]])
443464 }
444465
445466 # counter
@@ -610,37 +631,12 @@ parse_command_line <- function(args) {
610631 # ie, if more positionals provided than expected, copy the remainder into the last positional variable
611632 mydata [[myrow $ var ]] <- c(mydata [[myrow $ var ]], positionals [(i + 1 ): length(positionals )])
612633 }
613- # # if positional arguments are missing...
614- # if (length(index) > length(positionals)) {
615- # usage()
616- # writeLines(paste0("parse_command_line(): one or more positional arguments missing"))
617- # stop(call. = FALSE)
618- # }
619- # else if (length(index) == length(positionals)) {
620- # for (i in seq_along(index)) {
621- # myrow <- args_table[index[i],]
622- # mydata[[myrow$var]] <- positionals[i]
623- # }
624- # }
625- # else { # there are more positionals provided than required.
626- # for (i in seq_along(index)) {
627- # myrow <- args_table[index[i],]
628- # mydata[[myrow$var]] <- positionals[i]
629- # }
630- # # copy the remaining values into the last positional argument
631- # mydata[[myrow$var]] <- c(mydata[[myrow$var]], positionals[(i+1):length(positionals)])
632- # }
633634 } # positionals
634635 return (mydata )
635636} # new_parse_command_line
636637
637638
638639# HELPER FUNCTIONS
639- remove_dashes <- function (arg ) {
640- return (gsub(' -' , ' ' , arg ))
641- } # remove_dashes
642-
643-
644640is_lparam <- function (arg ) {
645641 return (grepl(' ^--' , arg ))
646642} # is_lparam
0 commit comments