这是 OCaml 中的代码,用于在 Linux 终端中使用 Unix 模块和原始模式检测按键。
我唯一无法检测到的键是 ESC。可能还有其他键,但我的主要目标是检测 ESC 键。
该函数的代码如下:
(* Function to read a character and recognize special keys *)
let read_character () =
let in_chan = in_channel_of_descr stdin in
let c = input_char in_chan in
if c = '\027' then
let next1 = input_char in_chan in
let next2 = input_char in_chan in
match (next1, next2) with
| ('[', 'A') -> "Up Arrow"
| ('[', 'B') -> "Down Arrow"
| ('[', 'C') -> "Right Arrow"
| ('[', 'D') -> "Left Arrow"
| ('[', 'H') -> "Home"
| ('[', 'F') -> "End"
| ('[', '3') when input_char in_chan = '~' -> "Delete"
| ('[', '2') when input_char in_chan = '~' -> "Insert"
| ('[', '5') when input_char in_chan = '~' -> "Page Up"
| ('[', '6') when input_char in_chan = '~' -> "Page Down"
| _ -> "Ignore"
else
match c with
| '\n' -> "Enter" (* Handle Enter key *)
| '\127' -> "Backspace" (* Handle Backspace (DEL) *)
| _ -> String.make 1 c (* Return single character *)
请注意,C/curses 可以工作,但是初始化/完成速度非常慢并且会清除屏幕,因此它不是最佳选择。
这确实是一个挑战。AI 建议我使用 Lwt/Async,但这些都不起作用,因为我无法在 Arch Linux 中成功安装它们。
幸运的是,有一个非规范的超时模式可以实现这一点。完整的源代码如下:
Esc 键生成单个 ESC 字节(八进制 027),而其他特殊键生成以该字节开头的转义序列。
因此,没有完全可靠的方法来检测终端中的 Esc 按键。
一种可能性(可能最引人注目的是该
vi
系列所采用的)是在没有其他字节可用的情况下检查 ESC 字节。这种方法在实践中效果很好,尽管严格来说,在某些情况下,事件的时间安排可能会出错。这种方法的变体是在等待后续字节时允许一点额外的延迟。另一种可能性也经常出现在基于终端的应用程序中,即期望用户按两次 Esc 键。这很容易检测,无需启发式方法,但会导致用户体验不佳。