1-
21as_app <- function (x , complete = TRUE ) {
3- if (inherits(x , " Rapp" ))
2+ if (inherits(x , " Rapp" )) {
43 return (x )
4+ }
55
66 # TODO: present a nice error message in case of parse errors
77 filepath <- x
88 lines <- readLines(filepath )
99 exprs <- parse(
10- text = lines , keep.source = TRUE ,
11- srcfile = srcfilecopy(filepath , lines ,
12- file.mtime(filepath ), isFile = TRUE ))
10+ text = lines ,
11+ keep.source = TRUE ,
12+ srcfile = srcfilecopy(filepath , lines , file.mtime(filepath ), isFile = TRUE )
13+ )
1314
1415 app <- new.env(parent = emptyenv())
1516 attr(app , " class" ) <- " Rapp"
@@ -19,7 +20,7 @@ as_app <- function(x, complete = TRUE) {
1920 app $ line_is_hashpipe <- startsWith(lines , " #| " )
2021 app $ exprs <- exprs
2122
22- if (complete ) {
23+ if (complete ) {
2324 app $ data <- get_app_data(app )
2425 inputs <- get_app_inputs(app )
2526 app $ opts <- inputs $ opts
@@ -31,29 +32,28 @@ as_app <- function(x, complete = TRUE) {
3132
3233
3334get_app_data <- function (app ) {
34-
3535 app <- as_app(app , complete = FALSE )
3636
3737 data <-
38- if (app $ line_is_hashpipe [1 ] ||
39- startsWith(app $ lines [1 ], " #!/" ) && app $ line_is_hashpipe [2 ]) {
38+ if (
39+ app $ line_is_hashpipe [1 ] ||
40+ startsWith(app $ lines [1 ], " #!/" ) && app $ line_is_hashpipe [2 ]
41+ ) {
4042 # allow frontmatter to start on 2nd line if first line is a shebang
4143
4244 hashpipe_start <- which.max(app $ line_is_hashpipe )
43- hashpipe_end <- which.min(c(TRUE , app $ line_is_hashpipe [- 1L ])) - 1L
45+ hashpipe_end <- which.min(c(TRUE , app $ line_is_hashpipe [- 1L ])) - 1L
4446
4547 parse_hashpipe_yaml(app $ lines [hashpipe_start : hashpipe_end ])
4648 } else {
4749 as_yaml(list ())
4850 }
4951
50-
5152 data
5253}
5354
5455
5556get_app_inputs <- function (app ) {
56-
5757 app <- as_app(app , complete = FALSE )
5858 lines <- app $ lines
5959 exprs <- app $ exprs
@@ -66,47 +66,58 @@ get_app_inputs <- function(app) {
6666 for (i in seq_along(exprs )) {
6767 e <- exprs [[i ]]
6868
69- if (! is.call(e ))
69+ if (! is.call(e )) {
7070 next
71+ }
7172
7273 op <- e [[1L ]]
73- if (op != quote(`=` ) && op != quote(`<-` ))
74+ if (op != quote(`=` ) && op != quote(`<-` )) {
7475 next
76+ }
7577
76- if (typeof(e [[2L ]]) != " symbol" )
78+ if (typeof(e [[2L ]]) != " symbol" ) {
7779 next
80+ }
7881
7982 name <- as.character(e [[2L ]])
8083
8184 # already encountered this same symbol as a flag earlier
82- if (name %in% names(args ) ||
83- name %in% names(opts ))
85+ if (name %in% names(args ) || name %in% names(opts )) {
8486 next
87+ }
8588
8689 default <- e [[3L ]]
8790 if (is.call(default )) {
88-
89- if (! is.symbol(call_sym <- default [[1 ]]))
91+ if (! is.symbol(call_sym <- default [[1 ]])) {
9092 next
93+ }
9194
9295 call_sym <- as.character(call_sym )
9396
94- if (! call_sym %in% c(" c" , " character" , " +" ))
97+ if (! call_sym %in% c(" c" , " character" , " +" )) {
9598 next
99+ }
96100
97- if (all.names(default ) %in% c(" c" , " character" , " -" , " +" ))
101+ if (all.names(default ) %in% c(" c" , " character" , " -" , " +" )) {
98102 default <- eval(default , envir = baseenv())
103+ }
99104 # # TODO: complex are `+` calls, eval, all else, next
100105 # # TODO: special syntax for var len values? `vals <- c("a", "b")`, injected as `[a,b]`
101106 }
102107
103- if (! typeof(default ) %in%
104- c(" double" , " integer" , " character" , " logical" , " NULL" ))
108+ if (
109+ ! typeof(default ) %in%
110+ c(" double" , " integer" , " character" , " logical" , " NULL" )
111+ ) {
105112 next
113+ }
106114
107- if (! (identical(length(default ), 1L ) ||
108- identical(length(default ), 0L )))
115+ if (
116+ ! (identical(length(default ), 1L ) ||
117+ identical(length(default ), 0L ))
118+ ) {
109119 next
120+ }
110121
111122 # # three types of cli args:
112123 # # --foo bar (option: option that takes a val)
@@ -125,40 +136,43 @@ get_app_inputs <- function(app) {
125136 " integer" = " integer" ,
126137 " NULL" = " string"
127138 ),
128- arg_type =
129- if (isTRUE(default ) || isFALSE(default )) " switch"
130- else if (length(default )) " option"
131- else " positional" ,
139+ arg_type = if (isTRUE(default ) || isFALSE(default )) {
140+ " switch"
141+ } else if (length(default )) {
142+ " option"
143+ } else {
144+ " positional"
145+ },
132146 .val_pos_in_exprs = c(i , 3L ) # pos 3 in call expr: `<-`(name, 'val')
133147 )
134148
135149 lineno <- utils :: getSrcLocation(exprs [i ], " line" )
136150 # look for adjacent anno hints about this flag
137151 if (is_hashpipe [lineno - 1L ]) {
138152 anno_start <- anno_end <- lineno - 1L
139- while (is_hashpipe [anno_start - 1L ])
153+ while (is_hashpipe [anno_start - 1L ]) {
140154 subtract(anno_start ) <- 1L
155+ }
141156
142- anno <- parse_hashpipe_yaml(lines [anno_start : anno_end ],
143- handlers = list (" bool#yes" = identity ,
144- " bool#no" = identity ))
157+ anno <- parse_hashpipe_yaml(
158+ lines [anno_start : anno_end ],
159+ handlers = list (" bool#yes" = identity , " bool#no" = identity )
160+ )
145161
146162 arg <- utils :: modifyList(arg , anno )
147163 }
148164
149- if (arg $ arg_type == " positional" )
165+ if (arg $ arg_type == " positional" ) {
150166 args [[name ]] <- arg
151- else
167+ } else {
152168 opts [[name ]] <- arg
153-
169+ }
154170 }
155171
156-
157172 list (args = args , opts = opts )
158173}
159174
160175
161-
162176# ' Run an R app.
163177# '
164178# ' @param app A filepath to an Rapp.
@@ -201,13 +215,15 @@ get_app_inputs <- function(app) {
201215# ' Sys.setenv(PATH = old_path)
202216run <- function (app , args = commandArgs(TRUE )) {
203217 args <- textConnection(args )
204- if (missing(app ))
218+ if (missing(app )) {
205219 app <- readLines(args , 1L )
220+ }
206221
207222 app <- as_app(app )
208223
209- if (process_args(args , app ))
224+ if (process_args(args , app )) {
210225 eval(app $ exprs , new.env(parent = globalenv()))
226+ }
211227
212228 invisible ()
213229}
0 commit comments