Get the last top-level command as a character string

Is there a way to get the last top-level command stored in a character string without saving the history to a file and reading it just to capture the last command? I have a code for this

lastcmd <- function(){ tmp <- tempfile() savehistory(tmp) # If we call this function then that call will # be the last line in the history so we want the one # before that tail(readLines(tmp), 2)[1] } 

and this is not so bad, but I was wondering if there is a way to get the history as characters without first writing to the file.

+8
r
source share
2 answers

This is a good use case for callback tasks. Basically, you can register a callback that will store the last top-level expression in a variable, which you can later get.

 .lastcall <- NULL # create an empty variable to store into # register your callback addTaskCallback(function(expr,value,ok,visible) { assign(".lastcall", as.character(substitute(expr))[2], .GlobalEnv) TRUE}, name='storelast') # storelast # 1 # check the callback on a bunch of things 2+2 # [1] 4 .lastcall # [1] "2 + 2" 1:4 # [1] 1 2 3 4 .lastcall # [1] "1:4" matrix(1:4, nrow=2) # [,1] [,2] # [1,] 1 3 # [2,] 2 4 .lastcall # [1] "matrix(1:4, nrow = 2)" a <- 2; b <- 3 .lastcall # [1] "b <- 3" # cleanup everything; check that everything is cleaned up removeTaskCallback('storelast') # [1] TRUE 2+2 # [1] 4 .lastcall # confirm 2+2 was not stored as .lastcall # [1] ".lastcall" rm(.lastcall) .lastcall # Error: object '.lastcall' not found 

You can also write a callback function so that it simply adds the last call to the vector (or list or the like), so that you build a complete history of commands:

 .lastcall <- character() # create an empty variable to store into # register your callback addTaskCallback(function(expr,value,ok,visible) { assign(".lastcall", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv) TRUE}, name='storelast') # storelast # 1 # check the callback on a bunch of things 2+2 # [1] 4 .lastcall # [1] "addTaskCallback(function(expr, value, ok, visible) {\n assign(\".lastcall\", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv)\n TRUE\n}, name = \"storelast\")" # [2] "2 + 2" 1:4 # [1] 1 2 3 4 .lastcall # [1] "addTaskCallback(function(expr, value, ok, visible) {\n assign(\".lastcall\", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv)\n TRUE\n}, name = \"storelast\")" # [2] "2 + 2" # [3] ".lastcall" # [4] "1:4" matrix(1:4, nrow=2) # [,1] [,2] # [1,] 1 3 # [2,] 2 4 .lastcall # [1] "addTaskCallback(function(expr, value, ok, visible) {\n assign(\".lastcall\", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv)\n TRUE\n}, name = \"storelast\")" # [2] "2 + 2" # [3] ".lastcall" # [4] "1:4" # [5] ".lastcall" # [6] "matrix(1:4, nrow = 2)" a <- 2; b <- 3 .lastcall # [1] "addTaskCallback(function(expr, value, ok, visible) {\n assign(\".lastcall\", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv)\n TRUE\n}, name = \"storelast\")" # [2] "2 + 2" # [3] ".lastcall" # [4] "1:4" # [5] ".lastcall" # [6] "matrix(1:4, nrow = 2)" # [7] ".lastcall" # [8] "a <- 2" # [9] "b <- 3" # cleanup everything; check that everything is cleaned up removeTaskCallback('storelast') # [1] TRUE 2+2 # [1] 4 .lastcall # confirm 2+2 was not added to .lastcall # [1] "addTaskCallback(function(expr, value, ok, visible) {\n assign(\".lastcall\", append(.lastcall, as.character(substitute(expr))[2]), .GlobalEnv)\n TRUE\n}, name = \"storelast\")" # [2] "2 + 2" # [3] ".lastcall" # [4] "1:4" # [5] ".lastcall" # [6] "matrix(1:4, nrow = 2)" # [7] ".lastcall" # [8] "a <- 2" # [9] "b <- 3" # [10] ".lastcall" rm(.lastcall) .lastcall # Error: object '.lastcall' not found 

Remember that when you call back a task, it is important that you clean yourself after removeTaskCallback (or you can write a callback function to remove it after some condition is met, see the example ?addTaskCallback ). otherwise .lastcall will linger in your environment forever and be constantly updated without need.

+12
source share
 lastcmd <- function(){ tmp<-tempfile() savehistory(tmp) readLines(tmp)[length(readLines(tmp))-1] } 

Do you think it’s better?

-one
source share

All Articles