I recently tried hacking some custom "commands" into the R REPL. I thought the method was fun and interesting enough to be worth sharing.
In other language REPLs/interactive prompts, there are often a couple of special commands. Some of the more common ones are exit
(to exit the session) and clear
(to clear the buffer).
I often find myself instinctively attempting to use these in R. Of course, they do not exist in R. To terminate the R session, one can use quit(...)
or q(...)
, but this requires typing brackets, as well as a "no"
if you want to avoid that annoying "save workspace?" prompt.
Rather than put up with a couple of extra key presses, I decided to do something about it. I came up with a workaround (ab)using the P in REPL (Read-Eval-Print-Loop) and R's S3 methods:
exit <- structure(list(), class = "exit_command")
print.exit_command <- function(...) {
cat(glue::glue("Bye! {emo::ji('wave')}\n\n"))
q("no")
}
This creates a new object named exit
, that terminates the current R session when print(exit)
is called:
As I mentioned at the beginning, I don't just want to exit the session like this, I also want to be able to clear the buffer at will. To do this, we can do something similar to our exit
"command":
clear <- structure(list(), class = "clear_command")
print.clear_command <- function(...) {
# Clear console in both R and RStudio:
# From: https://stackoverflow.com/questions/14260340/function-to-clear-the-console-in-r-and-rstudio
purrr::walk(c("\f", "\033[2J", "\033[0;0H"), cat)
}
Here, I've placed it in my .Rprofile
, so it's loaded automatically when the R session is started:
It's starting to get a little tedious typing this out each time to add a command. I think we can generalise it a little bit:
create_command <- function(name, fn) {
class_name <- paste0("command_", name)
obj <- structure(list(), class = class_name)
assign(name, obj, env = parent.env(environment()))
assign(paste0("print.", class_name), fn, env = parent.env(environment()))
}
create_command("exit", function(...) q("no"))
create_command("clear", function(...) purrr::walk(c("\f", "\033[2J", "\033[0;0H"), cat))
Now we can easily add special R commands to our heart's content!
Of course, whether we should be adding all these commands is perhaps a different question...
NB for a saner way to get rid of the annoying "Save workspace data?" prompt R gives, I added the following to my .bash_profile
:
alias R="$(/usr/bin/which R) --no-save --no-restore-data"
alias r="$(/usr/bin/which r) --no-save --no-restore-data"