Como esperar por um pressionamento de tecla no R?

139

Quero pausar meu script R até que o usuário pressione uma tecla.

Como eu faço isso?

Contango
fonte
Você encontrou alguma resposta que possa aceitar?
Léo Léopold Hertz,

Respostas:

127

Como alguém já escreveu em um comentário, você não precisa usar o gato antes readline(). Escreva simplesmente:

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

Se você não deseja atribuí-lo a uma variável e não deseja um retorno impresso no console, envolva o readline()em invisible():

invisible(readline(prompt="Press [enter] to continue"))
nnn
fonte
Eu acho que esta é a melhor resposta aqui.
Léo Léopold Hertz #
1
Que tal adicionar mais um recurso a ele? press esc keep to exit loop?
I_m_LeMarque
4
@nnn isso não funciona se eu executar um script no rstudio, por exemplo, print ("oi") readline ("Pressione uma tecla para continuar") print ("ho") Provavelmente porque a sessão não é interativa. Como fazer isso em uma sessão não interativa?
PascalIv
79

Método 1

Aguarde até você pressionar [enter] no console:

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

Agrupando em uma função:

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

Essa função é o melhor equivalente Console.ReadKey()em C #.

Método 2

Faça uma pausa até você digitar a tecla [enter] no teclado. A desvantagem desse método é que, se você digitar algo que não é um número, ele exibirá um erro.

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

Agrupando em uma função:

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

Método 3

Imagine que você deseja aguardar um pressionamento de tecla antes de traçar outro ponto em um gráfico. Nesse caso, podemos usar getGraphicsEvent () para aguardar um pressionamento de tecla em um gráfico.

Este programa de exemplo ilustra o conceito:

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

Aqui você pode ver o gráfico, com metade de seus pontos coloridos, aguardando o próximo pressionamento de tecla no teclado.

Compatibilidade: Testado em ambientes, use win.graph ou X11 . Funciona com o Windows 7 x64 com o Revolution R v6.1. Não funciona no RStudio (pois não usa win.graph).

insira a descrição da imagem aqui

Gravitas
fonte
6
Método 1 poderia ser encurtado usando o promptargumento para readline. O método 2 funcionaria com qualquer entrada (não apenas números) se what=""fosse adicionado à chamada scan. getGraphicsEventfunciona apenas em dispositivos gráficos específicos em determinadas plataformas (mas se você estiver usando um desses dispositivos, ele funcionará bem).
Greg Neve
2
Se você estiver usando esta função (Método 1) em um loop e quiser interromper o loop, inclua, por exemplo:if(line == "Q") stop()
Dorian Grv 17/17/17 / 13h
18

Aqui está uma pequena função (usando o pacote tcltk) que abrirá uma pequena janela e espere até você clicar no botão continuar ou pressionar qualquer tecla (enquanto a pequena janela ainda estiver focada), e assim o script continuará.

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

Basta colocar mywait()seu script em qualquer lugar que você queira que o script seja pausado.

Isso funciona em qualquer plataforma que suporte tcltk (que eu acho que é comum), responde a qualquer pressionamento de tecla (não apenas entre) e até funciona quando o script é executado no modo em lote (mas ainda pausa no modo em lote) , portanto, se você não estiver lá para continuar, esperará para sempre). Um temporizador pode ser adicionado para continuar após um determinado período de tempo, se não clicar ou pressionar uma tecla.

Não retorna qual tecla foi pressionada (mas pode ser modificada para isso).

Greg Snow
fonte
É incrivel. Mas apenas um aviso, ele não será executado em webclient rstudio-Server, por algum motivo ( Error in structure(.External(.C_dotTclObjv, objv), class = "tclObj") : [tcl] invalid command name "toplevel". )
milia
2
@milia, isso está correto. O código baseado no tcltk precisa ser executado na máquina local e não será executado no RStudio-Server.
Greg Neve
14

R e Rscript enviam ''para a linha de leitura e digitalizam no modo não interativo (consulte ? readline). A solução é forçar o stdinuso da digitalização.

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

Exemplo:

$ Rscript t.R 
Solution to everything? > 42
Read 1 item
Simon A. Eugster
fonte
2
Impressionante! Isso quase resolve o meu problema . Ainda assim, seria bom se o console não estivesse esperando texto + Return, mas reagisse ao primeiro pressionamento de tecla (como em "Pressione qualquer tecla para continuar").
Vorac
3

Esta resposta é semelhante à de Simon , mas não requer entrada extra além de uma nova linha.

cat("Press Enter to continue...")
invisible(scan("stdin", character(), nlines = 1, quiet = TRUE))

Usando em nlines=1vez de n=1, o usuário pode simplesmente pressionar enter para continuar o Rscript.

Dennis YL
fonte
+1 é a única resposta que realmente funciona como desejado para mim. Interior Rscript: faz uma pausa e só é necessário pressionar Enterpara continuar.
Arielf # 10/18
2
Isto quebrou R e eu tive que encerrar a sessão
blobbymatt
1
no modo interativo, isso quebra R e requer o encerramento da sessão. Por favor, adicione um aviso à sua entrada. Nesse caso, removerei o voto negativo.
HoneyBuddha
Trabalhou para mim como esperado no Windows !. A solução aceita (acima) foi ignorada e não parou. Este realmente parou e esperou que eu aperte enter.
Matt D
0

Uma maneira de fazer isso (meio que você precisa pressionar um botão em vez de uma tecla, mas perto o suficiente) é usar brilhante:

library(shiny)

ui     <- fluidPage(actionButton("button", "Press the button"))
server <- function(input, output) {observeEvent(input$button, {stopApp()})}

runApp(shinyApp(ui = ui, server = server))

print("He waited for you to press the button in order to print this")

Para minha experiência, isso tem uma característica única: mesmo que você tenha executado um script com código escrito seguindo a runAppfunção, ele não será executado até você pressionar o botão no aplicativo (botão que interrompe o uso interno dos aplicativos stopApp).

Sébastien Wouters
fonte