我正在编写一个需要用户输入的小函数,该函数已经使用readline
函数进行了编码,但是想要消除用户在响应控制台中的提示后按下[enter]的需要。
我在SO上进行了广泛搜索,但没有找到解决方案,readline
文档没有提供任何潜在的解决方案。
timer <- function() {
require(tictoc) #load required package
experiment_no <- readline("Experiment number: ")
while(T){ #open infinite while loop
tic() #start timer
input_state=readline("State input: ") #allow for entry of state
if(input_state %in% 1:5){ #check if it's acceptable
elapsed=toc() #if it is then end timer and record data
write.table(cbind(experiment_no,input_state,elapsed$toc-elapsed$tic),'results.txt',col.names=F,row.names=F,quote=F,append=T)
}else if(input_state=='t'){ #if input is 't'
break #break out of while loop
}else if(input_state <1 | input_state > 5 & input_state!='t'){#if input is not and accepted state AND is not 't'
print('thats not an allowed state- please try another')
}
}
}
我希望用户能够在不按Enter的情况下将实验编号输入控制台。
答案 0 :(得分:1)
与 r2evans' 响应相反,此解决方案仅适用于 RStudio。它依赖于 rstudioapi 包捕获当前在控制台中的输入的能力。
dynamic_readline <- function() {
while (rstudioapi::isAvailable()) {
input <- rstudioapi::getConsoleEditorContext()$contents
if (input != "") {
rstudioapi::sendToConsole("", execute = FALSE)
return(input)
}
Sys.sleep(0.1)
}
readline()
}
while
循环每 0.1 秒检查一次控制台的内容,如果有任何输入,则返回输入。如果检测到某些内容,它会将 ""
发送到控制台以将其清除。如果 rstudioapi 不可用(即编辑器不是 Rstudio),该函数将回退到 readline()
。
睡眠时间可以根据您需要的响应时间进行调整,尽管在 R 控制台中您不会获得 60 Hz 的游戏体验。
您还可以通过使用 if
而不是 %in%
来调整 !=
语句以测试特定的有效输入而不是任何非空输入。 (类似于if (input %in% c("w", "a", "s", "d", "quit"))
)。这使得在已知输入长度超过一个字符的情况下使用此方法变得可行。
答案 1 :(得分:0)
编辑:预先,这在RStudio中也不起作用。由于我确信RStudio确实拦截并控制了很多R,尽管import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
class TestWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
companion object {
private const val TAG = "TestWorker"
}
override suspend fun doWork(): Result {
return coroutineScope {
val job = async {
someWork()
}
job.invokeOnCompletion { exception: Throwable? ->
when(exception) {
is CancellationException -> {
Log.e(TAG, "Cleanup on completion", exception)
// cleanup on cancellations
}
else -> {
// do something else.
}
}
}
job.await()
}
}
suspend fun someWork(): Result {
TODO()
}
}
可能有其他控制方法(例如C_menu
),但我认为RStudio正在拦截按键(从而强制 options
-使用)。因此,我建议这倾向于使用RStudio进行错误/功能请求。
如果您查看<enter>
的来源,您将在最后看到它的来源:
utils::menu
这表明repeat {
ind <- .Call(C_menu, as.character(choices))
if (ind <= nc)
return(ind)
cat(gettext("Enter an item from the menu, or 0 to exit\n"))
}
函数(未导出)可以(用于)执行您想要的操作。我不知道该功能的内部运作方式,因此有一些经验性的总结/观点:
C_menu
循环中的第一遍需要输入一个回车; repeat
之后,单位整数似乎少<enter>
,其他任何东西都支持任意长度,并且需要<enter>
<enter>
我推断repeat {
ret <- .Call(utils:::C_menu, letters)
if (ret == 0L) break
cat(" you entered ", ret, "\n")
}
# Selection: 345 # I typed "345<enter>"
# you entered 345
# Selection: 3 # just "3", no enter
# you entered 3
# Selection: 4
# you entered 4
# Selection: 5
# you entered 5
# Selection: # just enter
# you entered 27
# Selection: C # "C<enter>"
# you entered 27
# Selection: c # "c<enter>"
# you entered 3
# Selection: abc # "abc<enter>"
# you entered 27
# Selection: 0 # just "0", no enter, it quits
表示我输入的内容不是原始选项(27
)。
不确定您是否可以使此过程适应该问题,因为它似乎仅限于一位数字(一旦您超过了第一个条目)。我还没有找到它的来源,看看是否有一个带有其他参数的伴随函数。
注意: