用stdin识别箭头键

Jac*_*ack 11 c terminal stdin ocaml input

是否有可能采用跨平台方式处理C或OCaml程序中的退格键和箭头键?

实际上,OCaml解决方案将受到赞赏,但许多标准的unix函数直接包装到相应的API调用,因此移植C解决方案应该没有问题.

我要实现的是捕获箭头键以覆盖它在shell中的行为(通过重新排序最后一行或类似这样的操作).我认为这件事落在实际程序之前并且它不是由代码本身处理的,所以我不知道它是否可能.

该程序在Linux,OS X和Windows(在cygwin上)编译,所以我想在所有平台上进行编译.

Nik*_*chi 9

我最近做了一些非常相似的事情(尽管我的代码只是Linux).您必须将stdin设置为非规范模式才能读取箭头键.这应该适用于OS X和Linux,并且可能适用于Cygwin,尽管我不能肯定.

open Unix
let terminfo = tcgetattr stdin in
  let newterminfo = {terminfo with c_icanon = false; c_vmin = 0; c_vtime = 0} in
    at_exit (fun _ -> tcsetattr stdin TCSAFLUSH terminfo); (* reset stdin when you quit*)
    tcsetattr stdin TCSAFLUSH newterminfo;
Run Code Online (Sandbox Code Playgroud)

当规范模式关闭时,您不需要等待换行符才能从标准输入读取.c_vmin表示返回前要读取的最小字符数(您可能希望一次只能读取一个字符),c_vtime是最大读取等待时间(以0.1s为单位).

您可能还希望设置c_echo为false,以便按下箭头键打印到终端(但是您必须手动打印其他所有内容.

大多数终端使用ANSI转义序列表示箭头按键.如果您在cat没有参数的情况下运行并开始按箭头键,则可以看到使用的转义序列.他们通常是

up - "\033[A"
down - "\033[B"
left - "\033[D"
right - "\033[C"
Run Code Online (Sandbox Code Playgroud)

其中'\ 033'是ascii值 esc


Ign*_*ams 5

使用ncurses提取箭头键功能的序列,然后在读取stdin时查找它们.使用像libedit或readline这样的东西可能更容易,并让它处理密钥处理.