Haskell 读取原始键盘输入

标签 haskell io terminal

我正在用 Haskell 编写一个终端模式程序。我将如何读取原始按键信息?

特别是,似乎有一些东西在 Haskell 之上提供了行编辑功能。如果我执行getLine,我似乎能够使用向上箭头来获取前一行,编辑文本,并且只有当我按 Enter 时,文本才会对 Haskell 应用程序本身可见。

我想要的是读取各个按键的能力,这样我就可以自己实现行编辑。

<小时/>

也许我的问题不清楚。基本上我想构建像 Vi 或 Emacs (或 Yi )这样的东西。我已经知道有终端绑定(bind)可以让我进行精美的控制台模式打印,因此输出侧不应该成为问题。我只是在寻找一种获取原始按键输入的方法,因此我可以执行以下操作:(例如)当用户按下字母 K 时将 K 添加到当前文本行,或者当用户按下字母 K 时将文件保存到磁盘按 Ctrl+S。

最佳答案

这可能是最简单的解决方案,类似于其他编程语言中的典型代码:

import System.IO (stdin, hReady)

getKey :: IO [Char]
getKey = reverse <$> getKey' ""
  where getKey' chars = do
          char <- getChar
          more <- hReady stdin
          (if more then getKey' else return) (char:chars)

它的工作原理是“一次”读取多个字符。允许例如 键,由三个字符 ['\ESC','[','A'] 组成,以区别于实际的 \ESC 字符输入。

使用示例:

import System.IO (stdin, hSetEcho, hSetBuffering, NoBuffering)
import Control.Monad (when)

-- Simple menu controller
main = do
  hSetBuffering stdin NoBuffering
  hSetEcho stdin False
  key <- getKey
  when (key /= "\ESC") $ do
    case key of
      "\ESC[A" -> putStr "↑"
      "\ESC[B" -> putStr "↓"
      "\ESC[C" -> putStr "→"
      "\ESC[D" -> putStr "←"
      "\n"     -> putStr "⎆"
      "\DEL"   -> putStr "⎋"
      _        -> return ()
    main

这有点 hackish,因为从理论上讲,用户可以在程序进入 hReady 之前输入更多按键。如果终端允许粘贴,就会发生这种情况。但实际上,对于交互式输入,这不是一个现实的场景。

有趣的事实:光标字符串可以通过 putStrd 来实际以编程方式移动光标。

关于Haskell 读取原始键盘输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23068218/

相关文章:

objective-c - 如何在 iOS/OS X 中将 HTML 转换为 Markdown?有什么方法可以在应用程序中使用 pandoc 吗?

haskell - 循环 StateT : Why this loop doesn't loop

r - 从 Linux 终端在 R 下将文件内容作为命令执行

linux - 如何使用 shell 脚本替换属性文件中的点

xcode - 将 Xcode 项目添加到 github 存储库?

haskell - 运算符 % 在 Haskell 中是什么意思?

haskell - 在 Haskell 中实现多态 λ-演算/系统 F 对的 Church 编码

c++ - 将( double )表写入二进制文件 IO C++

c - 如何将 txt 文件存储为两个字符串数组?

python - 在特定位置更新文本文件中的字符串