How to wait for a keypress in R?

103,565

Solution 1

As someone already wrote in a comment, you don't have to use the cat before readline(). Simply write:

readline(prompt="Press [enter] to continue")

If you don't want to assign it to a variable and don't want a return printed in the console, wrap the readline() in an invisible():

invisible(readline(prompt="Press [enter] to continue"))

Solution 2

Method 1

Waits until you press [enter] in the console:

cat ("Press [enter] to continue")
line <- readline()

Wrapping into a function:

readkey <- function()
{
    cat ("Press [enter] to continue")
    line <- readline()
}

This function is the best equivalent of Console.ReadKey() in C#.

Method 2

Pause until you type the [enter] keystroke on the keyboard. The disadvantage of this method is that if you type something that is not a number, it will display an error.

print ("Press [enter] to continue")
number <- scan(n=1)

Wrapping into a function:

readkey <- function()
{
    cat("[press [enter] to continue]")
    number <- scan(n=1)
}

Method 3

Imagine you want to wait for a keypress before plotting another point on a graph. In this case, we can use getGraphicsEvent() to wait for a keypress within a graph.

This sample program illustrates the concept:

readkeygraph <- function(prompt)
{
    getGraphicsEvent(prompt = prompt, 
                 onMouseDown = NULL, onMouseMove = NULL,
                 onMouseUp = NULL, onKeybd = onKeybd,
                 consolePrompt = "[click on graph then follow top prompt to continue]")
    Sys.sleep(0.01)
    return(keyPressed)
}

onKeybd <- function(key)
{
    keyPressed <<- key
}

xaxis=c(1:10) # Set up the x-axis.
yaxis=runif(10,min=0,max=1) # Set up the y-axis.
plot(xaxis,yaxis)

for (i in xaxis)
{
    # On each keypress, color the points on the graph in red, one by one.
    points(i,yaxis[i],col="red", pch=19)
    keyPressed = readkeygraph("[press any key to continue]")
}

Here you can see the graph, with half of its points colored, waiting for the next keystroke on the keyboard.

Compatibility: Tested under environments use either win.graph or X11. Works with Windows 7 x64 with Revolution R v6.1. Does not work under RStudio (as it doesn't use win.graph).

enter image description here

Solution 3

Here is a little function (using the tcltk package) that will open a small window and wait until you either click on the continue button or press any key (while the small window still has the focus), then it will let your script continue.

library(tcltk)

mywait <- function() {
    tt <- tktoplevel()
    tkpack( tkbutton(tt, text='Continue', command=function()tkdestroy(tt)),
        side='bottom')
    tkbind(tt,'<Key>', function()tkdestroy(tt) )

    tkwait.window(tt)
}

Just put mywait() in your script anywhere that you want the script to pause.

This works on any platform that supports tcltk (which I think is all the common ones), will respond to any key press (not just enter), and even works when the script is run in batch mode (but it still pauses in batch mode, so if you are not there to continue it it will wait forever). A timer could be added to make it continue after a set amount of time if not clicked or has a key pressed.

It does not return which key was pressed (but could be modified to do so).

Solution 4

R and Rscript both send '' to readline and scan in non-interactive mode (see ? readline). The solution is to force stdin using scan.

cat('Solution to everything? > ')
b <- scan("stdin", character(), n=1)

Example:

$ Rscript t.R 
Solution to everything? > 42
Read 1 item

Solution 5

The function keypress() from the package keypress reads a single key stroke instantly, without having to hit enter.

However, it only works in the Unix/OSX terminal or Windows command line. It does not work in Rstudio, the Windows R GUI, an emacs shell buffer etc.

Share:
103,565

Related videos on Youtube

Contango
Author by

Contango

Have been programming for over 22 years (since I was at elementary school). Experienced in C/C++, C#, Python, SQL, etc on both Linux and Windows. Currently working in finance / financial services in the Front Office of one of the larger market makers in Europe. Experienced in full stack development involving WPF, MVVM, DI, OMS, EMS, FIX, FAST, WCF, Tibco, Bloomberg API, etc. Have built systems running at discretionary trading timescales right down to high frequency trading (HFT) timescales, working on everything from the DAL to the user interface. Passionate about great software architecture, writing bug free, maintainable and performant code, and designing great user interfaces.

Updated on December 27, 2020

Comments

  • Contango
    Contango over 3 years

    I want to pause my R script until the user presses a key.

    How do I do this?

    • Michal aka Miki
      Michal aka Miki over 7 years
      Have you found any answer which you can accept?
  • Greg Snow
    Greg Snow over 11 years
    Method 1 could be shortened by using the prompt argument to readline. Method 2 would work with any input (not just numbers) if what="" were added to the call to scan. getGraphicsEvent only works on specific graphics devices on certain platforms (but if you are using one of those devices it works fine).
  • milia
    milia about 8 years
    It's awesome. But just a warning, it won't run on RStudio-Server webclient, for some reason(Error in structure(.External(.C_dotTclObjv, objv), class = "tclObj") : [tcl] invalid command name "toplevel". )
  • Greg Snow
    Greg Snow about 8 years
    @milia, that is correct. Code based on tcltk needs to run on the local machine and will not run on RStudio-Server.
  • Michal aka Miki
    Michal aka Miki over 7 years
    I think this is the best answer here.
  • Dorian Grv
    Dorian Grv over 7 years
    If you are using this function (Method 1) in a loop and want to stop the loop, include for example : if(line == "Q") stop()
  • Vorac
    Vorac over 6 years
    Awesome! This nearly solves my problem. Still it would be nice if the console wasn't waiting for text + Return, but rather reacted to the first keypress (as in "Press any key to continue").
  • LeMarque
    LeMarque over 6 years
    how about adding one more feature to it? press esc keep to exit loop ?
  • PascalIv
    PascalIv almost 6 years
    @nnn this does not work if I run a script in rstudio e.g. print("hi") readline("Press a key to continue") print("ho") Its probably because the session is not interactive. How to do this in a non-interactive session?
  • arielf
    arielf over 5 years
    +1 this is the only answer that actually works as desired for me. Inside Rscript: it pauses and only requires to hit Enter to continue.
  • blobbymatt
    blobbymatt about 5 years
    this broke R and i had to terminate the session
  • HoneyBuddha
    HoneyBuddha over 4 years
    in interactive mode, this breaks R and requires terminating the session. Please add warning on your entry, in which case, I will remove the downvote.
  • Matt Dzievit
    Matt Dzievit over 4 years
    Worked for me as expected on Windows!. The accepted solution (above) was skipped over and didn't pause. This one actually paused and waited for me to hit enter.