Wait for a user input for 5 seconds and use a default value otherwise
Asked Answered
D

3

6

I would like to give the user an opportunity to enter an input, and use a default value if they do not enter anything after 5 seconds.

Here's for the input part:

input <- readline(prompt="Do something? (y/n): ")

Is there a way to do it in R?

Drava answered 9/1, 2019 at 14:42 Comment(5)
?Sys.sleep maybe?Stancil
Humm, the way I understand it, Sys.sleep can make R wait, but it will not force R to stop waiting and carry on the execution if nobody answers..Drava
This may be hard, "Furthermore, it is not possible to interrupt/break out of a "readline" prompt (e.g. readline() and readLines()) using timeouts; the timeout exception will not be thrown until after the user completes the prompt (i.e. after pressing ENTER)." You will have to be creative..rdocumentation.org/packages/R.utils/versions/2.7.0/topics/…Literatim
Not sure if you want to keep this text based, but this can be done with tcltk2 using tclAfterAlarice
It looks to me that @Literatim is right, and even tcltk2::tclAfter is like Sys.sleep and only allows to delay the execution of a function, not to force R to carry on the execution of a function after waiting a few seconds.Drava
A
2

Here is how I accomplish a window prompt allowing the user to select the number of threads to start in a cluster. It uses a default value and then it will proceed after the OK button is pressed or 5 seconds pass.

library(tcltk2)

clusterCount = 1

tklist <- list()
tklist <- within(tklist, {
  # define processor input window
  win1 <- tktoplevel()
  rb1 <- tk2radiobutton(win1)
  rb2 <- tk2radiobutton(win1)
  rb3 <- tk2radiobutton(win1)
  rb4 <- tk2radiobutton(win1)
  rbCluster <- tclVar(clusterCount)
  tkconfigure(rb1, text = "one",  variable = rbCluster, value = 1L)
  tkconfigure(rb2, text = "two",  variable = rbCluster, value = 2L)
  tkconfigure(rb3, text = "three", variable = rbCluster, value = 3L)
  tkconfigure(rb4, text = "four", variable = rbCluster, value = 4L)
  onOK <- function() {
    clusterCount <<- as.integer(tclvalue(rbCluster))
    tkdestroy(win1)
  }
  butOK <- tk2button(win1, text = "OK", width = -8, command = onOK)

  # geometry manager
  tkgrid(tk2label(win1, text = "how many cores?"), padx = 10, pady = c(15, 5))
  tkgrid(rb1, padx = 10, pady = c(0, 5))
  tkgrid(rb2, padx = 10, pady = c(0, 15))
  tkgrid(rb3, padx = 10, pady = c(0, 15))
  tkgrid(rb4, padx = 10, pady = c(0, 15))
  tkgrid(butOK, padx = 10, pady = c(5, 15))
  tclAfter(5000, function() tkdestroy(win1)) # delay for prompt and then close window to proceed
  tkfocus(win1)
  tkwait.window(win1)
})

After the window closes then clusterCount will either remain the default 1 or can be changed to 2, 3, or 4.

Alarice answered 10/1, 2019 at 14:51 Comment(0)
B
1

If you have a newer version of R then you can try withTimeout function from the utils package, to wrap the readline function.

There is a difficult to use function in base R called setTimeLimit.

My buggy attempt at a solution follows This worked in RGui, but it also seemed to reliably crash R-studio

timed_readline <- function(prompt = '',default,timeout = 10)
{
    inner <- function(timeout)    # wrapped in internal function to stop error being displayed
    {
        setTimeLimit(elapsed=timeout,transient=TRUE)
        a <- readline('')
        setTimeLimit(transient=TRUE)
        return(a)
    }

    cat(prompt)
    b <- default
    try({b <- inner(timeout)},silent=TRUE) 
    return(b)
}

As such I can't recommend this code but it might inspire you to something workable

Berck answered 9/1, 2019 at 23:56 Comment(1)
thanks for taking the time Aaron, much appreciated. this approach seems to works fine with any other function, but not with readline() unfortunately.Drava
F
-1

I can't find the way to skip that interaction in console. Anyway I'm leaving a function concerning time where, if you push enter out of time in order to skip the promt, you will get a predefined value. I hope it is a way to save that console interaction.

#set time in seconds to get an answer from prompt 
#some interaction in console is needed, sorry

Q <- function (x) {
    t0 <- Sys.time() 
    input <- readline(prompt="Do something? (y/n): ")
    tf <- Sys.time()-t0

    if (tf > x){
        input <- "your predefined answer"
    }

    print (tf) #remove if you like
    return (input)
}

Q(5)
Felicitous answered 9/1, 2019 at 15:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.