Introduction

This is a short tutorial for fun on how to customise your R profile, which shows in the console every time you load R. You should end up with a console that looks something like this:

Part 1, install packages

Before you start you will need to install the following packages:

  • usethis - helper functions for package development

  • praise - fun package to give user praise

  • lubridate - package for working with dates

  • purrr - package for doing iteration

  • cli - tools for building attractive command line interfaces (https://github.com/r-lib/cli)

install.packages(c("usethis", "praise", 
                   "lubridate", "purrr",
                   "cli"))

Once they are installed you can move to part 2.

Part 2, access your r profile

In order to change your rprofile, you will first need to get access to it. This is where the usethis package comes in, which has the very helpful function edit_r_profile().

Run the code chunk below to open up your r profile.

# run to open your r profile
usethis::edit_r_profile()

Great, your .Rprofile should now be loaded so we can move to part 3.

Part 3, add code to your profile

The below code chunk contains the code to make your rprofile a bit more exciting! To use it, copy and paste the code into .Rprofile. Save it, then restart R. When loaded look at your console and you’ll see the new console take effect!

if(interactive()) {
  
  # set up welcome
  name <- 'Andrew'
  hour <- format(Sys.time(), format = '%H') |> as.numeric() |> as.character()
  
  morning <- 0:11
  afternoon <- 12:16
  evening <- c(17:23)
  
  day_hrs <- rep(
    x = c('Morning', 'Afternoon', 'Evening'), 
    times = c(length(morning), length(afternoon), length(evening))
  )
  
  names(day_hrs) <- as.character(0:23)
  
  # clear screen
  cat("\014") 
  cli::cli_text("")
  # call r version
  cli::cli_text(R.version$version.string) 
  cli::cli_text("")
  
  # customise the prompt
  prompt::set_prompt(function(...){
    branch <- (purrr::safely(gert::git_branch))()
    if(is.null(branch$result)) return("> ")
    return(paste0("[", branch$result, "] > "))
  })
  
  # usethis options
  options(usethis.protocol = "ssh")
  options(usethis.full_name = "Andrew Peter Moles")
  
  # bias against scientific notation
  options(scipen = 4)
  
  # speed up package install with Ncpus (parallel installation)
  options(Ncpus = 6)
  
  # increase install packages timeout 
  options(timeout=300)
  
  # R compile speed up - https://twitter.com/grant_mcdermott/status/1493400952878952448
  options(collapse_mask = "manip")
  
  # hey, welcome to r
  cli::cli_text(
    cli::col_yellow(paste0(
      'Good ', day_hrs[hour], ', ', name, '!'
    ))
  )
  cli::cli_text(
    cli::col_br_magenta(paste0(
      paste0("Welcome to R and RStudio! ", 
             intToUtf8(127758), intToUtf8(129429), intToUtf8(129430), 
             intToUtf8(127794), intToUtf8(128029))
    ))
  )
  cli::cli_text("")
  # been using and learning r for x days
  cli::cli_alert_success(
    paste0(
      "Using and learning R for ",
      lubridate::today() - lubridate::dmy("1 may 16"),
      " days ", intToUtf8(129504), intToUtf8(128187)
    )
  )
  # give yourself some praise
  cli::cli_alert_success(praise::praise("${exclamation}! You are doing a ${adjective} job, keep up the ${adjective} work!"))
  cli::cli_alert_success(praise::praise("${exclamation}! I've been ${adverb} ${creating} R materials since 2018, how ${adjective}"))
  cli::cli_text("")
  
  cli::cli_rule(center = '#rstats')
  
  # emoji references:
  # list of emoji
  # https://unicode.org/emoji/charts/full-emoji-list.html
  # add code to search to find html entity
  # https://www.compart.com/en/unicode 
  
  # Hadley quote to finish
  cli::cli_blockquote(
    quote = paste0(
      'R is not a language driven by the purity of its philosophy; ', 
      'R is a language designed to get shit done.'
    ), 
    
    citation = '@hadleywickham, rstudioconf2022.'
  )
}

Part 4, edit the script to suit you

Using the script, change parts of it to suit you. You can change when you first started learning R, edit the welcome message or more!

To help you, below are some details on what is happening in the script:

The first section clears the console screen so you have a blank slate to work with.

The second section adds the prompt to tell you how long you’ve been learning R for: it uses a combination of paste0 and lubridate. To change this to when you started learning R, change the date from 1 may 16 to whenever your first R experience was. You can add other achievements (or failures using cli::cli_alert_warning()) here too, like when you graduated or learned to drive.

The third section tells you what git branch you are in. This is very helpful if you are using git with R. If you are not using git you will just get the default console setting.

The next section uses paste and praise to add welcome messages. If you want to find out more about the praise package, check out it’s github repo.

You will notice within paste we have a function with a six digit code: intToUtf8(129429). We are taking a html entity code and converting it, which provides us with an emoji. How do we get this? First, you need to use this list of emojis to find the emoji you want and copy the code. For example, the code U+1F995 is for a sauropod. We then search for that code in a unicode converter, pasting the code in the search menu. You should get a page up with the emoji and other information; you’ll want the html entity part, which for the sauropod is 129429. You only need the digits. Take them and add them to the intToUtf8() function and you’ll get your emoji!

The final section adds options. I’ve added Ncpus = 6, this effects the install.packages function, and using Ncpus = 6 means it will use 6 cores rather than the default 2 cores; this means it will install packages much faster!

That’s it! Enjoy editing and making a welcoming rprofile.

LS0tCnRpdGxlOiAiQ2hhbmdpbmcgeW91ciAuUnByb2ZpbGUgdHV0b3JpYWwiCmF1dGhvcjoKICAgLSBuYW1lOiBBbmRyZXcgTW9sZXMKICAgICBhZmZpbGlhdGlvbjogTGVhcm5pbmcgRGV2ZWxvcGVyLCBEaWdpdGFsIFNraWxscyBMYWIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6IAogICAgdGhlbWU6IHJlYWRhYmxlCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICBrZWVwX21kOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKIyBJbnRyb2R1Y3Rpb24KClRoaXMgaXMgYSBzaG9ydCB0dXRvcmlhbCBmb3IgZnVuIG9uIGhvdyB0byBjdXN0b21pc2UgeW91ciBSIHByb2ZpbGUsIHdoaWNoIHNob3dzIGluIHRoZSBjb25zb2xlIGV2ZXJ5IHRpbWUgeW91IGxvYWQgUi4gWW91IHNob3VsZCBlbmQgdXAgd2l0aCBhIGNvbnNvbGUgdGhhdCBsb29rcyBzb21ldGhpbmcgbGlrZSB0aGlzOgoKIVtdKHJwcm9maWxlLnBuZyl7d2lkdGg9IjYwMyJ9CgojIFBhcnQgMSwgaW5zdGFsbCBwYWNrYWdlcwoKQmVmb3JlIHlvdSBzdGFydCB5b3Ugd2lsbCBuZWVkIHRvIGluc3RhbGwgdGhlIGZvbGxvd2luZyBwYWNrYWdlczoKCi0gICB1c2V0aGlzIC0gaGVscGVyIGZ1bmN0aW9ucyBmb3IgcGFja2FnZSBkZXZlbG9wbWVudAoKLSAgIHByYWlzZSAtIGZ1biBwYWNrYWdlIHRvIGdpdmUgdXNlciBwcmFpc2UKCi0gICBsdWJyaWRhdGUgLSBwYWNrYWdlIGZvciB3b3JraW5nIHdpdGggZGF0ZXMKCi0gICBwdXJyciAtIHBhY2thZ2UgZm9yIGRvaW5nIGl0ZXJhdGlvbgoKLSAgIGNsaSAtIHRvb2xzIGZvciBidWlsZGluZyBhdHRyYWN0aXZlIGNvbW1hbmQgbGluZSBpbnRlcmZhY2VzICg8aHR0cHM6Ly9naXRodWIuY29tL3ItbGliL2NsaT4pCgpgYGB7ciBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKGMoInVzZXRoaXMiLCAicHJhaXNlIiwgCiAgICAgICAgICAgICAgICAgICAibHVicmlkYXRlIiwgInB1cnJyIiwKICAgICAgICAgICAgICAgICAgICJjbGkiKSkKYGBgCgpPbmNlIHRoZXkgYXJlIGluc3RhbGxlZCB5b3UgY2FuIG1vdmUgdG8gcGFydCAyLgoKIyBQYXJ0IDIsIGFjY2VzcyB5b3VyIHIgcHJvZmlsZQoKSW4gb3JkZXIgdG8gY2hhbmdlIHlvdXIgcnByb2ZpbGUsIHlvdSB3aWxsIGZpcnN0IG5lZWQgdG8gZ2V0IGFjY2VzcyB0byBpdC4gVGhpcyBpcyB3aGVyZSB0aGUgdXNldGhpcyBwYWNrYWdlIGNvbWVzIGluLCB3aGljaCBoYXMgdGhlIHZlcnkgaGVscGZ1bCBmdW5jdGlvbiBgZWRpdF9yX3Byb2ZpbGUoKWAuCgpSdW4gdGhlIGNvZGUgY2h1bmsgYmVsb3cgdG8gb3BlbiB1cCB5b3VyIHIgcHJvZmlsZS4KCmBgYHtyIGV2YWw9RkFMU0V9CiMgcnVuIHRvIG9wZW4geW91ciByIHByb2ZpbGUKdXNldGhpczo6ZWRpdF9yX3Byb2ZpbGUoKQpgYGAKCkdyZWF0LCB5b3VyIC5ScHJvZmlsZSBzaG91bGQgbm93IGJlIGxvYWRlZCBzbyB3ZSBjYW4gbW92ZSB0byBwYXJ0IDMuCgojIFBhcnQgMywgYWRkIGNvZGUgdG8geW91ciBwcm9maWxlCgpUaGUgYmVsb3cgY29kZSBjaHVuayBjb250YWlucyB0aGUgY29kZSB0byBtYWtlIHlvdXIgcnByb2ZpbGUgYSBiaXQgbW9yZSBleGNpdGluZyEgVG8gdXNlIGl0LCBjb3B5IGFuZCBwYXN0ZSB0aGUgY29kZSBpbnRvIC5ScHJvZmlsZS4gU2F2ZSBpdCwgdGhlbiByZXN0YXJ0IFIuIFdoZW4gbG9hZGVkIGxvb2sgYXQgeW91ciBjb25zb2xlIGFuZCB5b3UnbGwgc2VlIHRoZSBuZXcgY29uc29sZSB0YWtlIGVmZmVjdCEKCmBgYHtyIGV2YWw9RkFMU0V9CmlmKGludGVyYWN0aXZlKCkpIHsKICAKICAjIHNldCB1cCB3ZWxjb21lCiAgbmFtZSA8LSAnQW5kcmV3JwogIGhvdXIgPC0gZm9ybWF0KFN5cy50aW1lKCksIGZvcm1hdCA9ICclSCcpIHw+IGFzLm51bWVyaWMoKSB8PiBhcy5jaGFyYWN0ZXIoKQogIAogIG1vcm5pbmcgPC0gMDoxMQogIGFmdGVybm9vbiA8LSAxMjoxNgogIGV2ZW5pbmcgPC0gYygxNzoyMykKICAKICBkYXlfaHJzIDwtIHJlcCgKICAgIHggPSBjKCdNb3JuaW5nJywgJ0FmdGVybm9vbicsICdFdmVuaW5nJyksIAogICAgdGltZXMgPSBjKGxlbmd0aChtb3JuaW5nKSwgbGVuZ3RoKGFmdGVybm9vbiksIGxlbmd0aChldmVuaW5nKSkKICApCiAgCiAgbmFtZXMoZGF5X2hycykgPC0gYXMuY2hhcmFjdGVyKDA6MjMpCiAgCiAgIyBjbGVhciBzY3JlZW4KICBjYXQoIlwwMTQiKSAKICBjbGk6OmNsaV90ZXh0KCIiKQogICMgY2FsbCByIHZlcnNpb24KICBjbGk6OmNsaV90ZXh0KFIudmVyc2lvbiR2ZXJzaW9uLnN0cmluZykgCiAgY2xpOjpjbGlfdGV4dCgiIikKICAKICAjIGN1c3RvbWlzZSB0aGUgcHJvbXB0CiAgcHJvbXB0OjpzZXRfcHJvbXB0KGZ1bmN0aW9uKC4uLil7CiAgICBicmFuY2ggPC0gKHB1cnJyOjpzYWZlbHkoZ2VydDo6Z2l0X2JyYW5jaCkpKCkKICAgIGlmKGlzLm51bGwoYnJhbmNoJHJlc3VsdCkpIHJldHVybigiPiAiKQogICAgcmV0dXJuKHBhc3RlMCgiWyIsIGJyYW5jaCRyZXN1bHQsICJdID4gIikpCiAgfSkKICAKICAjIHVzZXRoaXMgb3B0aW9ucwogIG9wdGlvbnModXNldGhpcy5wcm90b2NvbCA9ICJzc2giKQogIG9wdGlvbnModXNldGhpcy5mdWxsX25hbWUgPSAiQW5kcmV3IFBldGVyIE1vbGVzIikKICAKICAjIGJpYXMgYWdhaW5zdCBzY2llbnRpZmljIG5vdGF0aW9uCiAgb3B0aW9ucyhzY2lwZW4gPSA0KQogIAogICMgc3BlZWQgdXAgcGFja2FnZSBpbnN0YWxsIHdpdGggTmNwdXMgKHBhcmFsbGVsIGluc3RhbGxhdGlvbikKICBvcHRpb25zKE5jcHVzID0gNikKICAKICAjIGluY3JlYXNlIGluc3RhbGwgcGFja2FnZXMgdGltZW91dCAKICBvcHRpb25zKHRpbWVvdXQ9MzAwKQogIAogICMgUiBjb21waWxlIHNwZWVkIHVwIC0gaHR0cHM6Ly90d2l0dGVyLmNvbS9ncmFudF9tY2Rlcm1vdHQvc3RhdHVzLzE0OTM0MDA5NTI4Nzg5NTI0NDgKICBvcHRpb25zKGNvbGxhcHNlX21hc2sgPSAibWFuaXAiKQogIAogICMgaGV5LCB3ZWxjb21lIHRvIHIKICBjbGk6OmNsaV90ZXh0KAogICAgY2xpOjpjb2xfeWVsbG93KHBhc3RlMCgKICAgICAgJ0dvb2QgJywgZGF5X2hyc1tob3VyXSwgJywgJywgbmFtZSwgJyEnCiAgICApKQogICkKICBjbGk6OmNsaV90ZXh0KAogICAgY2xpOjpjb2xfYnJfbWFnZW50YShwYXN0ZTAoCiAgICAgIHBhc3RlMCgiV2VsY29tZSB0byBSIGFuZCBSU3R1ZGlvISAiLCAKICAgICAgICAgICAgIGludFRvVXRmOCgxMjc3NTgpLCBpbnRUb1V0ZjgoMTI5NDI5KSwgaW50VG9VdGY4KDEyOTQzMCksIAogICAgICAgICAgICAgaW50VG9VdGY4KDEyNzc5NCksIGludFRvVXRmOCgxMjgwMjkpKQogICAgKSkKICApCiAgY2xpOjpjbGlfdGV4dCgiIikKICAjIGJlZW4gdXNpbmcgYW5kIGxlYXJuaW5nIHIgZm9yIHggZGF5cwogIGNsaTo6Y2xpX2FsZXJ0X3N1Y2Nlc3MoCiAgICBwYXN0ZTAoCiAgICAgICJVc2luZyBhbmQgbGVhcm5pbmcgUiBmb3IgIiwKICAgICAgbHVicmlkYXRlOjp0b2RheSgpIC0gbHVicmlkYXRlOjpkbXkoIjEgbWF5IDE2IiksCiAgICAgICIgZGF5cyAiLCBpbnRUb1V0ZjgoMTI5NTA0KSwgaW50VG9VdGY4KDEyODE4NykKICAgICkKICApCiAgIyBnaXZlIHlvdXJzZWxmIHNvbWUgcHJhaXNlCiAgY2xpOjpjbGlfYWxlcnRfc3VjY2VzcyhwcmFpc2U6OnByYWlzZSgiJHtleGNsYW1hdGlvbn0hIFlvdSBhcmUgZG9pbmcgYSAke2FkamVjdGl2ZX0gam9iLCBrZWVwIHVwIHRoZSAke2FkamVjdGl2ZX0gd29yayEiKSkKICBjbGk6OmNsaV9hbGVydF9zdWNjZXNzKHByYWlzZTo6cHJhaXNlKCIke2V4Y2xhbWF0aW9ufSEgSSd2ZSBiZWVuICR7YWR2ZXJifSAke2NyZWF0aW5nfSBSIG1hdGVyaWFscyBzaW5jZSAyMDE4LCBob3cgJHthZGplY3RpdmV9IikpCiAgY2xpOjpjbGlfdGV4dCgiIikKICAKICBjbGk6OmNsaV9ydWxlKGNlbnRlciA9ICcjcnN0YXRzJykKICAKICAjIGVtb2ppIHJlZmVyZW5jZXM6CiAgIyBsaXN0IG9mIGVtb2ppCiAgIyBodHRwczovL3VuaWNvZGUub3JnL2Vtb2ppL2NoYXJ0cy9mdWxsLWVtb2ppLWxpc3QuaHRtbAogICMgYWRkIGNvZGUgdG8gc2VhcmNoIHRvIGZpbmQgaHRtbCBlbnRpdHkKICAjIGh0dHBzOi8vd3d3LmNvbXBhcnQuY29tL2VuL3VuaWNvZGUgCiAgCiAgIyBIYWRsZXkgcXVvdGUgdG8gZmluaXNoCiAgY2xpOjpjbGlfYmxvY2txdW90ZSgKICAgIHF1b3RlID0gcGFzdGUwKAogICAgICAnUiBpcyBub3QgYSBsYW5ndWFnZSBkcml2ZW4gYnkgdGhlIHB1cml0eSBvZiBpdHMgcGhpbG9zb3BoeTsgJywgCiAgICAgICdSIGlzIGEgbGFuZ3VhZ2UgZGVzaWduZWQgdG8gZ2V0IHNoaXQgZG9uZS4nCiAgICApLCAKICAgIAogICAgY2l0YXRpb24gPSAnQGhhZGxleXdpY2toYW0sIHJzdHVkaW9jb25mMjAyMi4nCiAgKQp9CmBgYAoKIyBQYXJ0IDQsIGVkaXQgdGhlIHNjcmlwdCB0byBzdWl0IHlvdQoKVXNpbmcgdGhlIHNjcmlwdCwgY2hhbmdlIHBhcnRzIG9mIGl0IHRvIHN1aXQgeW91LiBZb3UgY2FuIGNoYW5nZSB3aGVuIHlvdSBmaXJzdCBzdGFydGVkIGxlYXJuaW5nIFIsIGVkaXQgdGhlIHdlbGNvbWUgbWVzc2FnZSBvciBtb3JlIQoKKipUbyBoZWxwIHlvdSwgYmVsb3cgYXJlIHNvbWUgZGV0YWlscyBvbiB3aGF0IGlzIGhhcHBlbmluZyBpbiB0aGUgc2NyaXB0OioqCgpUaGUgZmlyc3Qgc2VjdGlvbiBjbGVhcnMgdGhlIGNvbnNvbGUgc2NyZWVuIHNvIHlvdSBoYXZlIGEgYmxhbmsgc2xhdGUgdG8gd29yayB3aXRoLgoKVGhlIHNlY29uZCBzZWN0aW9uIGFkZHMgdGhlIHByb21wdCB0byB0ZWxsIHlvdSBob3cgbG9uZyB5b3UndmUgYmVlbiBsZWFybmluZyBSIGZvcjogaXQgdXNlcyBhIGNvbWJpbmF0aW9uIG9mIHBhc3RlMCBhbmQgbHVicmlkYXRlLiBUbyBjaGFuZ2UgdGhpcyB0byB3aGVuIHlvdSBzdGFydGVkIGxlYXJuaW5nIFIsIGNoYW5nZSB0aGUgZGF0ZSBmcm9tIDEgbWF5IDE2IHRvIHdoZW5ldmVyIHlvdXIgZmlyc3QgUiBleHBlcmllbmNlIHdhcy4gWW91IGNhbiBhZGQgb3RoZXIgYWNoaWV2ZW1lbnRzIChvciBmYWlsdXJlcyB1c2luZyBgY2xpOjpjbGlfYWxlcnRfd2FybmluZygpYCkgaGVyZSB0b28sIGxpa2Ugd2hlbiB5b3UgZ3JhZHVhdGVkIG9yIGxlYXJuZWQgdG8gZHJpdmUuCgpUaGUgdGhpcmQgc2VjdGlvbiB0ZWxscyB5b3Ugd2hhdCBnaXQgYnJhbmNoIHlvdSBhcmUgaW4uIFRoaXMgaXMgdmVyeSBoZWxwZnVsIGlmIHlvdSBhcmUgdXNpbmcgZ2l0IHdpdGggUi4gSWYgeW91IGFyZSBub3QgdXNpbmcgZ2l0IHlvdSB3aWxsIGp1c3QgZ2V0IHRoZSBkZWZhdWx0IGNvbnNvbGUgc2V0dGluZy4KClRoZSBuZXh0IHNlY3Rpb24gdXNlcyBwYXN0ZSBhbmQgcHJhaXNlIHRvIGFkZCB3ZWxjb21lIG1lc3NhZ2VzLiBJZiB5b3Ugd2FudCB0byBmaW5kIG91dCBtb3JlIGFib3V0IHRoZSBwcmFpc2UgcGFja2FnZSwgY2hlY2sgb3V0IGl0J3MgW2dpdGh1YiByZXBvXShodHRwczovL2dpdGh1Yi5jb20vcmxhZGllcy9wcmFpc2UpLgoKWW91IHdpbGwgbm90aWNlIHdpdGhpbiBwYXN0ZSB3ZSBoYXZlIGEgZnVuY3Rpb24gd2l0aCBhIHNpeCBkaWdpdCBjb2RlOiBgaW50VG9VdGY4KDEyOTQyOSlgLiBXZSBhcmUgdGFraW5nIGEgaHRtbCBlbnRpdHkgY29kZSBhbmQgY29udmVydGluZyBpdCwgd2hpY2ggcHJvdmlkZXMgdXMgd2l0aCBhbiBlbW9qaS4gSG93IGRvIHdlIGdldCB0aGlzPyBGaXJzdCwgeW91IG5lZWQgdG8gdXNlIHRoaXMgW2xpc3Qgb2YgZW1vamlzXShodHRwczovL3VuaWNvZGUub3JnL2Vtb2ppL2NoYXJ0cy9mdWxsLWVtb2ppLWxpc3QuaHRtbCkgdG8gZmluZCB0aGUgZW1vamkgeW91IHdhbnQgYW5kIGNvcHkgdGhlIGNvZGUuIEZvciBleGFtcGxlLCB0aGUgY29kZSBgVSsxRjk5NWAgaXMgZm9yIGEgc2F1cm9wb2QuIFdlIHRoZW4gc2VhcmNoIGZvciB0aGF0IGNvZGUgaW4gYSBbdW5pY29kZSBjb252ZXJ0ZXJdKGh0dHBzOi8vd3d3LmNvbXBhcnQuY29tL2VuL3VuaWNvZGUpLCBwYXN0aW5nIHRoZSBjb2RlIGluIHRoZSBzZWFyY2ggbWVudS4gWW91IHNob3VsZCBnZXQgYSBwYWdlIHVwIHdpdGggdGhlIGVtb2ppIGFuZCBvdGhlciBpbmZvcm1hdGlvbjsgeW91J2xsIHdhbnQgdGhlICoqKmh0bWwgZW50aXR5KioqIHBhcnQsIHdoaWNoIGZvciB0aGUgc2F1cm9wb2QgaXMgYDEyOTQyOWAuIFlvdSBvbmx5IG5lZWQgdGhlIGRpZ2l0cy4gVGFrZSB0aGVtIGFuZCBhZGQgdGhlbSB0byB0aGUgYGludFRvVXRmOCgpYCBmdW5jdGlvbiBhbmQgeW91J2xsIGdldCB5b3VyIGVtb2ppIQoKVGhlIGZpbmFsIHNlY3Rpb24gYWRkcyBvcHRpb25zLiBJJ3ZlIGFkZGVkIGBOY3B1cyA9IDZgLCB0aGlzIGVmZmVjdHMgdGhlIGBpbnN0YWxsLnBhY2thZ2VzYCBmdW5jdGlvbiwgYW5kIHVzaW5nIGBOY3B1cyA9IDZgIG1lYW5zIGl0IHdpbGwgdXNlIDYgY29yZXMgcmF0aGVyIHRoYW4gdGhlIGRlZmF1bHQgMiBjb3JlczsgdGhpcyBtZWFucyBpdCB3aWxsIGluc3RhbGwgcGFja2FnZXMgbXVjaCBmYXN0ZXIhCgpUaGF0J3MgaXQhIEVuam95IGVkaXRpbmcgYW5kIG1ha2luZyBhIHdlbGNvbWluZyBycHJvZmlsZS4K