如何实时处理键盘读入


#1

问题分为如下两部分:

  1. 请问如何实现 读入 键盘输入的一个字符 (不加空格)及返回的函数?
    比较接近的是下面这个例子,但输入字符后必须要输空格
function F(a=parse(Char,readline()))
       @show a
       end
  1. 如何实时调用该函数,希望函数在规定时间给一个返回值或者返回timeout。
    已有的尝试是
julia> timedwait(F(),1,0.1)

但无输入超过 1 s 后,啥都没返回。

版本为 Julia 1.3


#2

Windows-specific:

julia> Char(ccall(:_getch,Cchar,()))
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

但是如果你要实时的话就只能用Windows API了。


#3

谢啦!我目前在用 Linux ,搞个Windows去试一下


#4

新年快乐:joy:


#5

Linux也有类似的键盘输入API或者lib,Google一下吧。Julia自身没有这样的东西


#6

发现 Linux 中这个命令可以直接满足上述两个需求,怎么接入 Julia 我再去查查文档

read -n 1 -t 1

#7

大概思路是这样子,但是需要再加一些修改来做成你想要的功能,可能这里应该用进程而不是线程

function keyboard_input()
    println("Y/n")
    task = @async read(stdin, Char)
    timedwait(()->task.state == :done, 1.0) == :ok && fetch(task)
end

#8

开一个协程去run它,或者用readCmd重载试试?


#9

感谢两位,找到解决方案了! 资料来源是中文文档的环境变量->外部应用
使用 Cmd 重载后的 read 命令即可,

julia>input=Cmd(`read -n 1 -t 2`, ignorestatus=false, detach=false);
julia>out=Base.repl_cmd(input,1)

则可读入键盘输入的单个字符,若超出 2s,返回 nothing , 即可后续处理。

keyboard_input () 直接用的话好像还是需要输入终止符,也就是说其 read 函数无法满足需求。但是可以用

input=Cmd(`read -n 1 `, ignorestatus=false, detach=false);

将时间管理通过 timedwait 完成,这样也是一个有趣的解决方案。

完成功能过程中的坑和疑问:

  1. Base.repl_cmd(input,1) 第二个参数介绍是个 output,但没看懂out在哪里.

  2. 重载以后感觉直接用 run(input)也应该能解析,但实际上报错如下。

ERROR: IOError: could not spawn `read -n 1 -t 1`: no such file or directory (ENOENT)
Stacktrace:
 [1] _spawn_primitive(::String, ::Cmd, ::Array{Any,1}) at ./process.jl:99
 [2] #554 at ./process.jl:112 [inlined]
 [3] setup_stdios(::Base.var"#554#555"{Cmd}, ::Array{Any,1}) at ./process.jl:196
 [4] _spawn at ./process.jl:111 [inlined]
 [5] #run#565(::Bool, ::typeof(run), ::Cmd) at ./process.jl:439
 [6] run(::Cmd) at ./process.jl:438
 [7] top-level scope at REPL[62]:1

当时觉得是环境没配对(所以找到了资料,也算运气不错),但

input=Cmd(`ls`, ignorestatus=false, detach=false);
run(input)

则可以正常运行。