# Tips

# 1: Safely set autos

If you would like to account for potential syntax errors when sourcing in your `autos`, you can wrap `rprofile()` in `purrr::safely()`. This function will attempt to set the autos and return a list containing the result and any error that occurred.

Let’s show an example. First we’ll make an example configuration file that will automatically source your autos. We’ll intentionally add a syntax error to show how `safely()` works.

Here is our configuration file, which will automatically source the autos from the `DEV` and `PROD` directories:

    default:
      autos:
        projects: !expr list(
          "DEV" = file.path("demo", "DEV", "username", "project1", "functions"),
          "PROD" = file.path("demo", "PROD", "project1", "functions")
          )

We will do a little work here to create the directory, place a script into the directory. We’ll add a syntax error by leaving off a closing `}` in `test_error.R` script in the PROD folder.

    # create the temp directory
    dir <- fs::file_temp()
    dir.create(dir)
    dir.create(file.path(dir, "/demo/PROD/project1/functions"), recursive = TRUE)

    # write a function to the folder with an error
    file_conn <- file(file.path(dir, "/demo/PROD/project1/functions/test_error.R"))
    writeLines(
    "test <- function(){print('test')", file_conn)
    close(file_conn)

    # write the config
    config_path <- file.path(dir, "_envsetup.yml")
    file_conn <- file(config_path)
    writeLines(
      paste0(
    "default:
      autos:
        PROD: '", dir,"/demo/PROD/project1/functions'"
      ), file_conn)
    close(file_conn)

So if we call `rprofile()` passing in this config file, we will get an error because of the syntax error in `test_error.R`:

    library(envsetup)

    envsetup_config <- config::get(file = config_path)

    rprofile(envsetup_config)
    #> Assigned paths to R_GlobalEnv
    #> Sourcing file:  '/shared/R_Temp/nmasel/RtmpKbVJua/file1962b1314414d1/demo/PROD/project1/functions/test_error.R'
    #> Error in `map2()`:
    #> ℹ In index: 1.
    #> ℹ With name: PROD.
    #> Caused by error in `map()`:
    #> ℹ In index: 1.
    #> Caused by error in `parse()`:
    #> ! 2:0: unexpected end of input
    #> 1: test <- function(){print('test')
    #>    ^

To handle this error, we can use `purrr::safely()` to wrap the `rprofile()` function. This will allow us to catch the error and handle it gracefully.

    safely_rprofile <- purrr::safely(rprofile)

    ret <- safely_rprofile(envsetup_config)
    #> Assigned paths to R_GlobalEnv
    #> Sourcing file:  '/shared/R_Temp/nmasel/RtmpKbVJua/file1962b1314414d1/demo/PROD/project1/functions/test_error.R'

We still have an error, but safely allow the setup to continue. We can check the result of the `safely_rprofile()` function to see if there was an error, identify the issue and correct the syntax error in the function.

    # check for errors and return if any occurred
    if(!is.null(ret$error)) {
      print(ret$error)
    }
    #> <error/purrr_error_indexed>
    #> Error in `map2()`:
    #> ℹ In index: 1.
    #> ℹ With name: PROD.
    #> Caused by error in `map()`:
    #> ℹ In index: 1.
    #> Caused by error in `parse()`:
    #> ! 2:0: unexpected end of input
    #> 1: test <- function(){print('test')
    #>    ^
    #> ---
    #> Backtrace:
    #>      ▆
    #>   1. └─purrr (local) safely_rprofile(envsetup_config)
    #>   2.   ├─purrr:::capture_error(.f(...), otherwise, quiet)
    #>   3.   │ └─base::tryCatch(...)
    #>   4.   │   └─base (local) tryCatchList(expr, classes, parentenv, handlers)
    #>   5.   │     └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
    #>   6.   │       └─base (local) doTryCatch(return(expr), name, parentenv, handler)
    #>   7.   └─envsetup (local) .f(...)
    #>   8.     └─envsetup:::set_autos(config$autos, overwrite = overwrite)
    #>   9.       └─purrr::walk2(...)
    #>  10.         └─purrr::map2(.x, .y, .f, ..., .progress = .progress)
    #>  11.           └─purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
    #>  12.             ├─purrr:::with_indexed_errors(...)
    #>  13.             │ └─base::withCallingHandlers(...)
    #>  14.             ├─purrr:::call_with_cleanup(...)
    #>  15.             └─envsetup (local) .f(.x[[i]], .y[[i]], ...)
    #>  16.               └─envsetup:::attach_auto(.x, .y, overwrite = overwrite)
    #>  17.                 └─purrr::walk(collated_r_scripts, source_warn_conflicts, overwrite = overwrite)
    #>  18.                   └─purrr::map(.x, .f, ..., .progress = .progress)
    #>  19.                     └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
    #>  20.                       ├─purrr:::with_indexed_errors(...)
    #>  21.                       │ └─base::withCallingHandlers(...)
    #>  22.                       ├─purrr:::call_with_cleanup(...)
    #>  23.                       └─envsetup (local) .f(.x[[i]], ...)
    #>  24.                         └─base::sys.source(file, envir = new_env)
    #>  25.                           └─base::parse(n = -1, file = file, srcfile = NULL, keep.source = FALSE)