ThinkR-open / golem

@@ -17,8 +17,10 @@
Loading
17 17
    list.files(path = directoryPath)
18 18
  ) == 0
19 19
  
20 -
  if ( list_f & warn_empty ) {
21 -
    warning("No resources to add from resource path (directory empty).")
20 +
  if ( list_f ) {
21 +
    if (warn_empty){
22 +
      warning("No resources to add from resource path (directory empty).")
23 +
    }
22 24
  } else {
23 25
    addResourcePath(prefix, directoryPath)
24 26
  }

@@ -46,43 +46,147 @@
Loading
46 46
    dir, sprintf("%s.js", name)
47 47
  )
48 48
  
49 -
  file_create(where)
49 +
  if (!file.exists(where)){
50 +
    file_create(where)
51 +
    
52 +
    if (with_doc_ready){
53 +
      write_there <- function(...){
54 +
        write(..., file = where, append = TRUE)
55 +
      }
56 +
      write_there("$( document ).ready(function() {")
57 +
      write_there("  ")
58 +
      write_there("});")
59 +
    } 
60 +
    file_created_dance(
61 +
      where, 
62 +
      after_creation_message_js, 
63 +
      pkg, 
64 +
      dir, 
65 +
      name,
66 +
      open
67 +
    )
68 +
  } else {
69 +
    file_already_there_dance(
70 +
     where = where, 
71 +
      open_file = open
72 +
    )
73 +
  }
74 +
  
75 +
}
76 +
77 +
#' @export
78 +
#' @rdname add_files
79 +
#' @importFrom fs path_abs path file_create file_exists
80 +
add_js_handler <- function(
81 +
  name, 
82 +
  pkg = get_golem_wd(), 
83 +
  dir = "inst/app/www",
84 +
  open = TRUE, 
85 +
  dir_create = TRUE
86 +
){
87 +
  attempt::stop_if(
88 +
    rlang::is_missing(name),
89 +
    msg = "Name is required"
90 +
  )
91 +
  
92 +
  name <- file_path_sans_ext(name)
50 93
  
51 -
  if (with_doc_ready){
94 +
  old <- setwd(path_abs(pkg))
95 +
  on.exit(setwd(old))
96 +
  
97 +
  dir_created <- create_if_needed(
98 +
    dir, type = "directory"
99 +
  )
100 +
  
101 +
  if (!dir_created){
102 +
    cat_red_bullet(
103 +
      "File not added (needs a valid directory)"
104 +
    )
105 +
    return(invisible(FALSE))
106 +
  }
107 +
  
108 +
  dir <- path_abs(dir) 
109 +
  
110 +
  where <- file.path(
111 +
    dir, sprintf("%s.js", name)
112 +
  )
113 +
  
114 +
  if (!file.exists(where)){
115 +
    
116 +
    file_create(where)
117 +
    
52 118
    write_there <- function(...){
53 119
      write(..., file = where, append = TRUE)
54 120
    }
121 +
    
55 122
    write_there("$( document ).ready(function() {")
123 +
    write_there("  Shiny.addCustomMessageHandler('fun', function(arg) {")
56 124
    write_there("  ")
125 +
    write_there("  })")
57 126
    write_there("});")
127 +
    file_created_dance(
128 +
      where, 
129 +
      after_creation_message_js, 
130 +
      pkg, 
131 +
      dir, 
132 +
      name,
133 +
      open_file = open
134 +
    )
135 +
  } else {
136 +
    file_already_there_dance(
137 +
      where, 
138 +
      open_file = open
139 +
    )
58 140
  }
59 141
  
60 -
  file_created_dance(
61 -
    where, 
62 -
    after_creation_message_js, 
63 -
    pkg, 
64 -
    dir, 
65 -
    name,
66 -
    open
67 -
  )
142 +
  
68 143
  
69 144
}
70 145
146 +
147 +
148 +
149 +
71 150
#' @export
72 151
#' @rdname add_files
152 +
#' @param initialize Whether to add the initialize method. Default to FALSE. Some JavaScript API 
153 +
#' require to initialize components before using them.
154 +
#' @param dev Whether to insert console.log calls in the most important methods of the binding.
155 +
#' This is only to help building the input binding. Default to FALSE
156 +
#' @param events List of events to generate event listeners in the subscribe method. For instance,
157 +
#' \code{list(name = c("click", "keyup"), rate_policy = c(FALSE, TRUE))}.
158 +
#' The list contain names and rate policies to apply to each event. If a rate policy is found, 
159 +
#' the debounce method with a default delay of 250 ms is applied. You may edit manually according to 
160 +
#' \url{https://shiny.rstudio.com/articles/building-inputs.html}. 
73 161
#' @importFrom fs path_abs path file_create file_exists
74 -
add_js_handler <- function(
162 +
add_js_binding <- function(
75 163
  name, 
76 164
  pkg = get_golem_wd(), 
77 165
  dir = "inst/app/www",
78 166
  open = TRUE, 
79 -
  dir_create = TRUE
167 +
  dir_create = TRUE,
168 +
  initialize = FALSE,
169 +
  dev = FALSE,
170 +
  events = list(
171 +
    name = "click",
172 +
    rate_policy = FALSE
173 +
  )
80 174
){
81 175
  attempt::stop_if(
82 176
    rlang::is_missing(name),
83 177
    msg = "Name is required"
84 178
  )
85 179
  
180 +
  attempt::stop_if(
181 +
    length(events$name) == 0,
182 +
    msg = "At least one event is required"
183 +
  )
184 +
  
185 +
  attempt::stop_if(
186 +
    length(events$name) != length(events$rate_policy),
187 +
    msg = "Incomplete events list"
188 +
  )
189 +
  
86 190
  name <- file_path_sans_ext(name)
87 191
  
88 192
  old <- setwd(path_abs(pkg))
@@ -105,29 +209,104 @@
Loading
105 209
    dir, sprintf("%s.js", name)
106 210
  )
107 211
  
108 -
  file_create(where)
109 -
  
110 -
  write_there <- function(...){
111 -
    write(..., file = where, append = TRUE)
212 +
  if (!file.exists(where)){
213 +
    
214 +
    file_create(where)
215 +
    
216 +
    write_there <- function(...){
217 +
      write(..., file = where, append = TRUE)
218 +
    }
219 +
    
220 +
    # If we find at least 1 event with a rate policy, we allow
221 +
    # the getRatePolicy method
222 +
    global_rate_policy <- sum(sapply(events$rate_policy, `[[`, 1)) > 0
223 +
    
224 +
    write_there(sprintf("var %s = new Shiny.InputBinding();", name))
225 +
    write_there(sprintf("$.extend(%s, {", name))
226 +
    # find
227 +
    write_there("  find: function(scope) {")
228 +
    write_there("    // JS logic $(scope).find('whatever')")
229 +
    write_there("  },")
230 +
    # initialize
231 +
    if (initialize) {
232 +
      write_there("  initialize: function(el) {")
233 +
      write_there("    // optional part. Only if the input relies on a JS API with specific initialization.")
234 +
      write_there("  },") 
235 +
    }
236 +
    # get value
237 +
    write_there("  getValue: function(el) {")
238 +
    if (dev) write_there("    console.log($(el));")
239 +
    write_there("    // JS code to get value")
240 +
    write_there("  },")
241 +
    # set value
242 +
    write_there("  setValue: function(el, value) {")
243 +
    if (dev) write_there("    console.log('New value is: ' + value);")
244 +
    write_there("    // JS code to set value")
245 +
    write_there("  },")
246 +
    # receive
247 +
    write_there("  receiveMessage: function(el, data) {")
248 +
    write_there("    // this.setValue(el, data);")
249 +
    if (dev) write_there("    console.log('Updated ...');")
250 +
    write_there("  },")
251 +
    # subscribe
252 +
    write_there("  subscribe: function(el, callback) {")
253 +
    # list of event listeners
254 +
    lapply(seq_along(events$name), function(i) {
255 +
      write_there(sprintf("    $(el).on('%s.%s', function(e) {", events$name[i], name))
256 +
      if (events$rate_policy[i]) {
257 +
        write_there("      callback(true);")
258 +
      } else {
259 +
        write_there("      callback();")
260 +
      }
261 +
      if (dev) write_there("      console.log('Subscribe ...');")
262 +
      write_there("    });")
263 +
      write_there("")
264 +
    })
265 +
    write_there("  },")
266 +
    
267 +
    # rate policy if any
268 +
    if (global_rate_policy) {
269 +
      write_there("  getRatePolicy: function() {")
270 +
      write_there("    return {")
271 +
      write_there("      policy: 'debounce',")
272 +
      write_there("      delay: 250")
273 +
      write_there("    };")
274 +
      write_there("  },")
275 +
    }
276 +
    
277 +
    # unsubscribe
278 +
    write_there("  unsubscribe: function(el) {")
279 +
    write_there(sprintf("    $(el).off('.%s');", name))
280 +
    write_there("  }")
281 +
    
282 +
    # end
283 +
    write_there("});")
284 +
    write_there(sprintf("Shiny.inputBindings.register(%s, 'shiny.whatever');", name))
285 +
    
286 +
    
287 +
    file_created_dance(
288 +
      where, 
289 +
      after_creation_message_js, 
290 +
      pkg, 
291 +
      dir, 
292 +
      name,
293 +
      open_file = open
294 +
    )
295 +
  } else {
296 +
    file_already_there_dance(
297 +
      where, 
298 +
      open_file = open
299 +
    )
112 300
  }
113 301
  
114 -
  write_there("$( document ).ready(function() {")
115 -
  write_there("  Shiny.addCustomMessageHandler('fun', function(arg) {")
116 -
  write_there("  ")
117 -
  write_there("  })")
118 -
  write_there("});")
119 302
  
120 -
  file_created_dance(
121 -
    where, 
122 -
    after_creation_message_js, 
123 -
    pkg, 
124 -
    dir, 
125 -
    name,
126 -
    open
127 -
  )
128 303
  
129 304
}
130 305
306 +
307 +
308 +
309 +
131 310
#' @export
132 311
#' @rdname add_files
133 312
#' @importFrom fs path_abs path file_create file_exists
@@ -168,15 +347,23 @@
Loading
168 347
    )
169 348
  )
170 349
  
171 -
  file_create(where)
172 -
  file_created_dance(
173 -
    where, 
174 -
    after_creation_message_css, 
175 -
    pkg, 
176 -
    dir, 
177 -
    name,
178 -
    open
179 -
  )
350 +
  if (!file_exists(where)){
351 +
    file_create(where)
352 +
    file_created_dance(
353 +
      where, 
354 +
      after_creation_message_css, 
355 +
      pkg, 
356 +
      dir, 
357 +
      name,
358 +
      open
359 +
    )
360 +
  } else {
361 +
    file_already_there_dance(
362 +
      where = where, 
363 +
      open_file = open
364 +
    )
365 +
  }
366 +
  
180 367
}
181 368
182 369
@@ -209,37 +396,42 @@
Loading
209 396
  # UI
210 397
  where <- path( dir, "ui.R")
211 398
  
212 -
  file_create(where)
213 -
  
214 -
  write_there <- function(...) write(..., file = where, append = TRUE)
215 -
  
216 -
  if (is.null(getOption('golem.pkg.name'))){
217 -
    pkg <- pkgload::pkg_name()
399 +
  if (!file_exists(where)){
400 +
    file_create(where)
401 +
    
402 +
    write_there <- function(...) write(..., file = where, append = TRUE)
403 +
    
404 +
    pkg <- get_golem_name()
405 +
    
406 +
    write_there(
407 +
      sprintf( "%s:::app_ui()", pkg )
408 +
    )
409 +
    
410 +
    cat_created(where, "ui file")
218 411
  } else {
219 -
    pkg <- getOption('golem.pkg.name')
412 +
    cat_green_tick("UI file already exists.")
220 413
  }
221 414
  
222 -
  write_there(
223 -
    sprintf( "%s:::app_ui()", pkg )
224 -
  )
225 -
  
226 -
  cat_created(where, "ui file")
227 -
  
228 415
  # server
229 416
  where <- file.path(
230 417
    dir, "server.R"
231 418
  )
232 419
  
233 -
  file_create(where)
234 -
  
235 -
  write_there <- function(...) write(..., file = where, append = TRUE)
236 420
  
237 -
  write_there(
238 -
    sprintf(
239 -
      "%s:::app_server",
240 -
      pkg
421 +
  if (!file_exists(where)){
422 +
    file_create(where)
423 +
    
424 +
    write_there <- function(...) write(..., file = where, append = TRUE)
425 +
    
426 +
    write_there(
427 +
      sprintf(
428 +
        "%s:::app_server",
429 +
        pkg
430 +
      )
241 431
    )
242 -
  )
243 -
  cat_created(where, "server file")
432 +
    cat_created(where, "server file")
433 +
  } else {
434 +
    cat_green_tick("server file already exists.")
435 +
  }
244 436
  
245 437
}

@@ -271,12 +271,16 @@
Loading
271 271
  use_parent = TRUE, 
272 272
  path = pkgload::pkg_path()
273 273
){
274 -
  get_golem_things(
274 +
  nm <- get_golem_things(
275 275
    value = "golem_name", 
276 276
    config = config, 
277 277
    use_parent = use_parent, 
278 278
    path = path
279 279
  )
280 +
  if (is.null(nm)){
281 +
    nm <- pkgload::pkg_name()
282 +
  }
283 +
  nm
280 284
}
281 285
282 286
#' @export

@@ -57,54 +57,61 @@
Loading
57 57
    "R", paste0("mod_", name, ".R")
58 58
  )
59 59
  
60 -
  file_create(where)
61 -
  
62 -
  write_there <- function(...){
63 -
    write(..., file = where, append = TRUE)
64 -
  }
65 -
  
66 -
  write_there(sprintf("#' %s UI Function", name))
67 -
  write_there("#'")
68 -
  write_there("#' @description A shiny Module.")
69 -
  write_there("#'")
70 -
  write_there("#' @param id,input,output,session Internal parameters for {shiny}.")
71 -
  write_there("#'")
72 -
  if (export){
73 -
    write_there(sprintf("#' @rdname mod_%s", name))
74 -
    write_there("#' @export ") 
75 -
  } else {
76 -
    write_there("#' @noRd ") 
77 -
  }
78 -
  write_there("#'")
79 -
  write_there("#' @importFrom shiny NS tagList ") 
80 -
  write_there(sprintf("mod_%s_ui <- function(id){", name))
81 -
  write_there("  ns <- NS(id)")
82 -
  write_there("  tagList(")
83 -
  write_there(ph_ui)
84 -
  write_there("  )")
85 -
  write_there("}")
86 -
  write_there("    ")
87 -
  
88 -
  write_there(sprintf("#' %s Server Function", name))
89 -
  write_there("#'")
90 -
  if (export){
91 -
    write_there(sprintf("#' @rdname mod_%s", name))
92 -
    write_there("#' @export ") 
60 +
  if (!file_exists(where)){
61 +
    file_create(where)
62 +
    
63 +
    write_there <- function(...){
64 +
      write(..., file = where, append = TRUE)
65 +
    }
66 +
    
67 +
    write_there(sprintf("#' %s UI Function", name))
68 +
    write_there("#'")
69 +
    write_there("#' @description A shiny Module.")
70 +
    write_there("#'")
71 +
    write_there("#' @param id,input,output,session Internal parameters for {shiny}.")
72 +
    write_there("#'")
73 +
    if (export){
74 +
      write_there(sprintf("#' @rdname mod_%s", name))
75 +
      write_there("#' @export ") 
76 +
    } else {
77 +
      write_there("#' @noRd ") 
78 +
    }
79 +
    write_there("#'")
80 +
    write_there("#' @importFrom shiny NS tagList ") 
81 +
    write_there(sprintf("mod_%s_ui <- function(id){", name))
82 +
    write_there("  ns <- NS(id)")
83 +
    write_there("  tagList(")
84 +
    write_there(ph_ui)
85 +
    write_there("  )")
86 +
    write_there("}")
87 +
    write_there("    ")
88 +
    
89 +
    write_there(sprintf("#' %s Server Function", name))
90 +
    write_there("#'")
91 +
    if (export){
92 +
      write_there(sprintf("#' @rdname mod_%s", name))
93 +
      write_there("#' @export ") 
94 +
    } else {
95 +
      write_there("#' @noRd ") 
96 +
    }
97 +
    write_there(sprintf("mod_%s_server <- function(input, output, session){", name))
98 +
    write_there("  ns <- session$ns")
99 +
    write_there(ph_server)
100 +
    write_there("}")
101 +
    write_there("    ")
102 +
    
103 +
    write_there("## To be copied in the UI")
104 +
    write_there(sprintf('# mod_%s_ui("%s_ui_1")', name, name))
105 +
    write_there("    ")
106 +
    write_there("## To be copied in the server")
107 +
    write_there(sprintf('# callModule(mod_%s_server, "%s_ui_1")', name, name))
108 +
    write_there(" ")
109 +
    cat_created(where)
110 +
    open_or_go_to(where, open)
93 111
  } else {
94 -
    write_there("#' @noRd ") 
112 +
    file_already_there_dance(
113 +
      where = where, 
114 +
      open_file = open
115 +
    )
95 116
  }
96 -
  write_there(sprintf("mod_%s_server <- function(input, output, session){", name))
97 -
  write_there("  ns <- session$ns")
98 -
  write_there(ph_server)
99 -
  write_there("}")
100 -
  write_there("    ")
101 -
  
102 -
  write_there("## To be copied in the UI")
103 -
  write_there(sprintf('# mod_%s_ui("%s_ui_1")', name, name))
104 -
  write_there("    ")
105 -
  write_there("## To be copied in the server")
106 -
  write_there(sprintf('# callModule(mod_%s_server, "%s_ui_1")', name, name))
107 -
  write_there(" ")
108 -
  cat_created(where)
109 -
  open_or_go_to(where, open)
110 117
}

@@ -8,6 +8,7 @@
Loading
8 8
#' @inheritParams add_module
9 9
#' @inheritParams usethis::use_spell_check
10 10
#' @param recommended A vector of recommended packages.
11 +
#' @param spellcheck Whether or not to use a spellcheck test.
11 12
#' 
12 13
#' @importFrom usethis use_testthat use_package
13 14
#' @importFrom fs path_abs
@@ -31,10 +32,11 @@
Loading
31 32
#' @export
32 33
#' @importFrom usethis use_testthat use_package use_spell_check
33 34
#' @importFrom utils capture.output
34 -
#' @importFrom attempt without_warning
35 -
#' @importFrom fs path_abs path
35 +
#' @importFrom attempt without_warning stop_if
36 +
#' @importFrom fs path_abs path file_exists
36 37
use_recommended_tests <- function (
37 38
  pkg = get_golem_wd(), 
39 +
  spellcheck = TRUE,
38 40
  vignettes = TRUE, 
39 41
  lang = "en-US", 
40 42
  error = FALSE
@@ -48,17 +50,33 @@
Loading
48 50
  )){
49 51
    without_warning(use_testthat)()
50 52
  }
51 -
  capture.output(use_package("processx"))
53 +
  if (requireNamespace("processx")){
54 +
    capture.output(use_package("processx")) 
55 +
  } else {
56 +
    stop("Please install the {processx} package to add these tests.")
57 +
  }
58 +
  
59 +
  stop_if(
60 +
    path(old, "tests", "testthat", "test-golem-recommended.R"), 
61 +
    file_exists, 
62 +
    "test-golem-recommended.R already exists. \nPlease remove it first if you need to reinsert it."
63 +
  )
52 64
  
53 65
  file_copy(
54 66
    golem_sys("utils", "test-golem-recommended.R"), 
55 -
    path(old, "tests", "testthat")
56 -
  )
57 -
  use_spell_check(
58 -
    vignettes = vignettes, 
59 -
    lang = lang, 
60 -
    error = error
67 +
    path(old, "tests", "testthat"), 
68 +
    overwrite = TRUE
61 69
  )
70 +
  
71 +
  if (spellcheck){
72 +
    use_spell_check(
73 +
      vignettes = vignettes, 
74 +
      lang = lang, 
75 +
      error = error
76 +
    )
77 +
  }
78 +
  
79 +
  
62 80
  cat_green_tick("Tests added")
63 81
} 
64 82

@@ -10,39 +10,49 @@
Loading
10 10
){
11 11
  service <- match.arg(service)
12 12
  where <- path(pkg, "app.R")
13 -
  file_create( where )
14 13
  
15 -
  write_there <- function(..., here = where){
16 -
    write(..., here, append = TRUE)
17 -
  }
18 14
  
19 -
  use_build_ignore( path_file(where) )
20 -
  use_build_ignore("rsconnect")
21 -
  write_there("# Launch the ShinyApp (Do not remove this comment)")
22 -
  write_there("# To deploy, run: rsconnect::deployApp()")
23 -
  write_there("# Or use the blue button on top of this file")
24 -
  write_there("")
25 -
  write_there("pkgload::load_all(export_all = FALSE,helpers = FALSE,attach_testthat = FALSE)")
26 -
  write_there("options( \"golem.app.prod\" = TRUE)")
27 -
  write_there(
28 -
    sprintf(
29 -
      "%s::run_app() # add parameters here (if any)", 
30 -
      getOption("golem.app.name", pkg_name())
15 +
  if (!file_exists(where)){
16 +
    file_create( where )
17 +
    
18 +
    write_there <- function(..., here = where){
19 +
      write(..., here, append = TRUE)
20 +
    }
21 +
    
22 +
    use_build_ignore( path_file(where) )
23 +
    use_build_ignore("rsconnect")
24 +
    write_there("# Launch the ShinyApp (Do not remove this comment)")
25 +
    write_there("# To deploy, run: rsconnect::deployApp()")
26 +
    write_there("# Or use the blue button on top of this file")
27 +
    write_there("")
28 +
    write_there("pkgload::load_all(export_all = FALSE,helpers = FALSE,attach_testthat = FALSE)")
29 +
    write_there("options( \"golem.app.prod\" = TRUE)")
30 +
    write_there(
31 +
      sprintf(
32 +
        "%s::run_app() # add parameters here (if any)", 
33 +
        get_golem_name()
34 +
      )
31 35
    )
32 -
  )
33 -
  #use_build_ignore(where)
34 -
  x <- capture.output(use_package("pkgload"))
35 -
  cat_created(where)
36 -
  cat_line("To deploy, run:")
37 -
  cat_bullet(darkgrey("rsconnect::deployApp()\n"))
38 -
  cat_red_bullet(
39 -
    sprintf(
40 -
      "Note that you'll need to upload the whole package to %s",
41 -
      service
36 +
    
37 +
    x <- capture.output(use_package("pkgload"))
38 +
    cat_created(where)
39 +
    cat_line("To deploy, run:")
40 +
    cat_bullet(darkgrey("rsconnect::deployApp()\n"))
41 +
    cat_red_bullet(
42 +
      sprintf(
43 +
        "Note that you'll need to upload the whole package to %s",
44 +
        service
45 +
      )
42 46
    )
43 -
  )
47 +
    
48 +
    open_or_go_to(where, open)
49 +
  } else {
50 +
    file_already_there_dance(
51 +
      where = where, 
52 +
      open_file = open
53 +
    )
54 +
  }
44 55
  
45 -
  open_or_go_to(where, open)
46 56
}
47 57
48 58
#' Add an app.R at the root of your package to deploy on RStudio Connect
@@ -153,7 +163,7 @@
Loading
153 163
  port = 80, 
154 164
  host = "0.0.0.0",
155 165
  sysreqs = TRUE,
156 -
  repos = "https://cran.rstudio.com/",
166 +
  repos = c(CRAN="https://cran.rstudio.com/"),
157 167
  expand = FALSE,
158 168
  open = TRUE,
159 169
  update_tar_gz = TRUE,
@@ -219,7 +229,7 @@
Loading
219 229
  ), 
220 230
  as = NULL,
221 231
  sysreqs = TRUE,
222 -
  repos = "https://cran.rstudio.com/",
232 +
  repos = c(CRAN="https://cran.rstudio.com/"),
223 233
  expand = FALSE,
224 234
  open = TRUE,
225 235
  update_tar_gz = TRUE,
@@ -281,7 +291,7 @@
Loading
281 291
  ), 
282 292
  as = NULL,
283 293
  sysreqs = TRUE,
284 -
  repos = "https://cran.rstudio.com/",
294 +
  repos = c(CRAN="https://cran.rstudio.com/"),
285 295
  expand = FALSE,
286 296
  open = TRUE,
287 297
  update_tar_gz = TRUE,
@@ -366,7 +376,7 @@
Loading
366 376
  if ( ! build_golem_from_source ){
367 377
    cat_red_bullet(
368 378
      sprintf(
369 -
        "Be sure to keep your %s_%s.tar.gz file (generated using `devtools::build()` ) in the same folder as the %s file generated", 
379 +
        "Be sure to keep your %s_%s.tar.gz file (generated using `pkgbuild::build(vignettes = FALSE)` ) in the same folder as the %s file generated", 
370 380
        read.dcf(path)[1], 
371 381
        read.dcf(path)[1,][['Version']], 
372 382
        basename(output)
@@ -390,6 +400,7 @@
Loading
390 400
#' @importFrom utils installed.packages packageVersion
391 401
#' @importFrom remotes dev_package_deps
392 402
#' @importFrom desc desc_get_deps
403 +
#' @importFrom usethis use_build_ignore
393 404
#' @noRd
394 405
dock_from_desc <- function(
395 406
  path = "DESCRIPTION",
@@ -400,7 +411,7 @@
Loading
400 411
  ),
401 412
  AS = NULL,
402 413
  sysreqs = TRUE,
403 -
  repos = "https://cran.rstudio.com/",
414 +
  repos = c(CRAN="https://cran.rstudio.com/"),
404 415
  expand = FALSE,
405 416
  update_tar_gz = TRUE,
406 417
  build_golem_from_source = TRUE
@@ -476,18 +487,20 @@
Loading
476 487
    }
477 488
  }
478 489
  
490 +
  
491 +
  repos_as_character <- paste(capture.output(dput(repos)),collapse = "")
492 +
  repos_as_character <-  gsub(pattern = '\"',replacement = '\'',x=repos_as_character)
493 +
  
494 +
  
479 495
  dock$RUN(
480 496
    sprintf(
481 -
      "echo \"options(repos = c(CRAN = '%s'), download.file.method = 'libcurl')\" >> /usr/local/lib/R/etc/Rprofile.site",
482 -
      repos
497 +
      "echo \"options(repos = %s, download.file.method = 'libcurl')\" >> /usr/local/lib/R/etc/Rprofile.site",
498 +
      repos_as_character
483 499
    )
484 500
  )
485 501
  
486 502
  dock$RUN("R -e 'install.packages(\"remotes\")'")
487 503
  
488 -
  # We need to be sure install_cran is there
489 -
  dock$RUN("R -e 'remotes::install_github(\"r-lib/remotes\", ref = \"97bbf81\")'")
490 -
  
491 504
  if ( length(packages_on_cran>0)){
492 505
    ping <- mapply(function(dock, ver, nm){
493 506
      res <- dock$RUN(
@@ -553,15 +566,25 @@
Loading
553 566
        )
554 567
      }
555 568
      
556 -
      cat_green_tick(
557 -
        sprintf(
558 -
          " %s_%s.tar.gz created.", 
559 -
          read.dcf(path)[1], 
560 -
          read.dcf(path)[1,][['Version']]
561 -
        )
562 -
      )
569 +
563 570
      if (rlang::is_installed("pkgbuild")) {
564 -
        pkgbuild::build(".")
571 +
        out <- pkgbuild::build(path = ".", dest_path = ".", vignettes = FALSE)
572 +
        
573 +
        if (missing(out)){
574 +
          cat_red_bullet("Error during tar.gz building"          )
575 +
          
576 +
        } else {
577 +
          usethis::use_build_ignore(files = out)
578 +
        cat_green_tick(
579 +
          sprintf(
580 +
            " %s_%s.tar.gz created.", 
581 +
            read.dcf(path)[1], 
582 +
            read.dcf(path)[1,][['Version']]
583 +
          )
584 +
        )
585 +
        }
586 +
        
587 +
        
565 588
      } else {
566 589
        stop("please install {pkgbuild}")
567 590
      }

@@ -31,6 +31,7 @@
Loading
31 31
  )
32 32
  
33 33
  file_create(where)
34 +
  cat_created(where)
34 35
  open_or_go_to(where, open)
35 36
  
36 37
}
@@ -67,7 +68,7 @@
Loading
67 68
68 69
#' @rdname file_creation
69 70
#' @export
70 -
add_utils<- function(
71 +
add_utils <- function(
71 72
  name, 
72 73
  module = NULL,
73 74
  pkg = get_golem_wd(), 

@@ -13,7 +13,7 @@
Loading
13 13
#' @importFrom cli cat_rule cat_line
14 14
#' @importFrom utils getFromNamespace
15 15
#' @importFrom rstudioapi isAvailable openProject
16 -
#' @importFrom fs path_abs path_file path file_move
16 +
#' @importFrom fs path_abs path_file path dir_copy path_expand
17 17
#' @export
18 18
create_golem <- function(
19 19
  path, 
@@ -24,6 +24,8 @@
Loading
24 24
  ...
25 25
) {
26 26
  
27 +
  path <- path_expand(path)
28 +
  
27 29
  if (path == '.' & package_name == path_file(path)){
28 30
    package_name <- path_file(getwd())
29 31
  }
@@ -52,51 +54,36 @@
Loading
52 54
  
53 55
  cat_rule("Copying package skeleton")
54 56
  from <- golem_sys("shinyexample")
55 -
  ll <- list.files(
56 -
    path = from, 
57 -
    full.names = TRUE, 
58 -
    all.files = TRUE,
59 -
    no.. = TRUE
60 -
  )
61 -
  # remove `..`
62 -
  file.copy(
63 -
    ll, 
64 -
    path, 
65 -
    overwrite = TRUE, 
66 -
    recursive = TRUE
67 -
  )
68 -
  
69 -
  t1 <- list.files(
70 -
    path,
71 -
    all.files = TRUE,
72 -
    recursive = TRUE,
73 -
    include.dirs = FALSE,
74 -
    full.names = TRUE
75 -
  )
76 -
  t <- grep(
77 -
    x = t1, 
78 -
    pattern = "ico$",
79 -
    invert = TRUE,
80 -
    value = TRUE
81 -
  ) 
82 -
  
83 -
  
84 -
  for ( i in t ){
85 -
    file_move(
86 -
      path = i,
87 -
      new_path = gsub("REMOVEME", "", i)
88 -
    )
57 +
58 +
  # Copy over whole directory
59 +
  dir_copy(path = from, new_path = path, overwrite = TRUE)
60 +
  
61 +
  # Listing copied files ***from source directory***
62 +
  copied_files <- list.files(path = from,
63 +
                             full.names = FALSE,
64 +
                             all.files = TRUE,
65 +
                             recursive = TRUE)
66 +
67 +
  # Going through copied files to replace package name
68 +
  for (f in copied_files) {
69 +
    copied_file <- file.path(path, f)
70 +
71 +
    if (grepl("^REMOVEME", f)) {
72 +
      file.rename(from = copied_file,
73 +
                  to = file.path(path, gsub("REMOVEME", "", f)))
74 +
      copied_file <- file.path(path, gsub("REMOVEME", "", f))
75 +
    }
89 76
    
90 -
    try({
91 -
      replace_word(
92 -
        file =   i,
93 -
        pattern = "shinyexample",
94 -
        replace = package_name
95 -
      )
96 -
    },
97 -
    silent = TRUE
98 -
    )
77 +
    if (!grepl("ico$", copied_file)) {
78 +
      try({
79 +
        replace_word(
80 +
          file = copied_file,
81 +
          pattern = "shinyexample",
82 +
          replace = package_name)
83 +
      }, silent = TRUE)
84 +
    }
99 85
  }
86 +
100 87
  cat_green_tick("Copied app skeleton")
101 88
  
102 89
  cat_rule("Setting the default config")

@@ -166,11 +166,11 @@
Loading
166 166
167 167
open_or_go_to <- function(
168 168
  where,
169 -
  open
169 +
  open_file
170 170
){
171 171
  if (
172 172
    rstudioapi::isAvailable() && 
173 -
    open && 
173 +
    open_file && 
174 174
    rstudioapi::hasFun("navigateToFile")
175 175
  ){
176 176
    rstudioapi::navigateToFile(where)
@@ -242,15 +242,28 @@
Loading
242 242
  pkg, 
243 243
  dir, 
244 244
  name, 
245 -
  open
245 +
  open_file
246 246
){
247 247
  cat_created(where)
248 248
  
249 249
  fun(pkg, dir, name)
250 250
  
251 -
  open_or_go_to(where, open)
251 +
  open_or_go_to(
252 +
    where = where,
253 +
    open_file = open_file
254 +
  )
252 255
}
253 256
257 +
file_already_there_dance <- function(
258 +
  where, 
259 +
  open_file
260 +
){
261 +
  cat_green_tick("File already exists.")
262 +
  open_or_go_to(
263 +
    where = where,
264 +
    open_file = open_file
265 +
  )
266 +
}
254 267
# Minor toolings
255 268
256 269
if_not_null <- function(x, ...){

@@ -63,7 +63,7 @@
Loading
63 63
#' @export
64 64
#' @rdname testhelpers
65 65
#' @param sleep number of seconds
66 -
#' @importFrom testthat skip_on_cran skip_on_travis skip_on_appveyor
66 +
#' @importFrom testthat skip_on_cran skip_on_travis skip_on_appveyor expect_true
67 67
expect_running <- function(sleep){
68 68
  skip_on_cran()
69 69
  skip_on_travis()
Files Coverage
R 70.06%
Project Totals (24 files) 70.06%
1
comment: false
2

3
coverage:
4
  status:
5
    project:
6
      default:
7
        target: auto
8
        threshold: 1%
9
    patch:
10
      default:
11
        target: auto
12
        threshold: 1%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading