首页 > 解决方案 > 如何读取功能键等?

问题描述

这个问题是以下问题的续集:如何防止输入被刷新到输出中?

使用这个程序,我观察到功能键(和其他一些)是多个字符的组合:

'\ESC' -- F1 pressed
'O'
'P'
'\ESC' -- Insert pressed
'['
'2'
'~'
'\ESC' -- Alt+v pressed
'v'

所以我想读这样的钥匙。这是我的尝试:

import Control.Monad
import System.IO

main :: IO ()
main = forever $ do
    hSetEcho stdin False
    c <- getChar
    cs <- getRemaining
    putStrLn $ case c:cs of
        "\ESCOP" -> "\\F1"
        "\ESCOQ" -> "\\F2"
        "\ESCOR" -> "\\F3"
        "\ESCOS" -> "\\F4"
        "\ESC[15~" -> "\\F5"
        "\ESC[17~" -> "\\F6"
        "\ESC[18~" -> "\\F7"
        "\ESC[19~" -> "\\F8"
        "\ESC[20~" -> "\\F9"
        "\ESC[24~" -> "\\F12"
        "\ESC[2~" -> "\\Insert"
        "\ESC[3~" -> "\\Delete"
        "\ESC[H" -> "\\Home"
        "\ESC[F" -> "\\End"
        "\ESC[5~" -> "\\PageUp"
        "\ESC[6~" -> "\\PageDown"
        "\ESC[A" -> "\\↑"
        "\ESC[D" -> "\\←"
        "\ESC[B" -> "\\↓"
        "\ESC[C" -> "\\→"
        "\ESC[E" -> "\\NumPad5"
        '\ESC':_ -> "\\Alt" ++ cs
        _        -> c:cs
  where
    getRemaining = do
        c <- hReady stdin >>= \r -> if r then pure <$> getChar else return ""
        if null c
            then return ""
            else (c ++) <$> getRemaining

关键思想是调用getChar直到输入缓冲区变空。

但是为什么这失败了并且不接受任何输入?

编辑:我期待这样的事情:

a -- A pressed
A -- Shift+A pressed
\F1 -- F1 pressed
\Insert -- Insert pressed
\Alte -- Alt+E pressed

但我没有看到任何输出。如果我不这样做hSetEcho stdin False,唯一的输出就是回声。

编辑2:我试过:

getRemaining = do
    c <- isEOF >>= \r -> if r then return "" else pure <$> getChar
    case c of
        "" -> return ""
        _  -> (c ++) <$> getRemaining

但问题仍然存在。

标签: haskellinputiokeyboard

解决方案


推荐阅读