Make Readline Wait for Input in R

Make readline wait for input in R

If you want to do this in interactive mode then you already have answers but not for use with Rscript. For that instance you need to send messages to the console with cat:

If this test file is named 'prompt.r' and is in the directory where you are working in a system console session:

cat("a string please: ");
a <- readLines("stdin",n=1);
cat("You entered")
str(a);
cat( "\n" )

Then you can run it from the command line as

$ Rscript prompt.r

If you want an all-purpose script then this would run your script under interactive conditions and my script for non-interactive ones:

if (interactive() ){raw <- 
readline("TRUE or FALSE -- this is a validation run: ")

if (raw == "F" | raw == "FALSE" | raw == "False"){
validation <- F
} else{
validation <- T
}
rm(raw) } else{
# non-interactive
cat("a string please: ");
a <- readLines("stdin",n=1);
cat("You entered")
str(a);
cat( "\n" )}

How to wait for a keypress in R?

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"))

R Language - Waiting for user input with scan or readline

This is how I use readLInes:

FUN <- function(x) {

if (missing(x)) {
message("Uhh you forgot to eneter x...\nPlease enter it now.")
x <- readLines(n = 1)
}
x
}

FUN()

Or maybe something along these lines:

FUN2 <- function() {

message("How many fruits will you buy")
x <- readLines(n = 1)

message("Good you want to buy %s fruits.\n Enter them now.")
y <- readLines(n = x)
paste(y, collapse = ", ")
}

FUN2()

EDIT: With your approach in Rgui...

FUN3 <- function(n=2) {
keywords <- scan(what=character(), nlines=n)
paste(keywords, collapse=",")
}

## > FUN3 <- function(n=2) {
## + keywords <- scan(what=character(), nlines=n)
## + paste(keywords, collapse=",")
## + }
## > FUN3()
## 1: apple
## 2: chicken
## Read 2 items
## [1] "apple,chicken"

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

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.

R: how do I prompt the user for input from the console?

Readline does wait for the user's input. But the problem is that, in your case, when you run all of your code at once, R will treat 'n2<-readline(prompt="Enter skip 2: " )' as the user's input (it indeed is) to the first readline. This is the root of the problem.

So basically you have two choices to deal with your problem, the first is to find some specific package in R that halts R execution process when prompting; the second one is to stick to the R base, but only use readline in the ending block of your file. In your case, you can use a little trick like this:

{
n1<-readline(prompt="Enter skip 1: " )
n2<-readline(prompt="Enter skip 2: " )
n1<-as.integer(n1)
n2<-as.integer(n2)
}

The rationale behind this trick is this: when R read the thing between { and }, it will treat all of the things in between as a whole command, this is the ending block of the code, so it behaves like what you want. R will not feed part of this command to another part of the command, thus prevents the problem you met.

You can develop similar tricks yourself, like putting the readline in a function:

foo <- function(){
n1<-readline(prompt="Enter skip 1: " )
n2<-readline(prompt="Enter skip 2: " )
n1<-as.integer(n1)
n2<-as.integer(n2)
c(n1, n2)
}

foo()

In this case, the whole foo function will act as the ending block of your code, and all things work as you want. Hope this helps.



Related Topics



Leave a reply



Submit