Mat*_*hid 17 io terminal haskell
我正在Haskell中编写一个终端模式程序.我如何阅读原始按键信息?
特别是,似乎有一些东西在Haskell之上提供行编辑工具.如果我这样做getLine
,我似乎能够使用向上箭头来获取前一行,编辑文本,并且只有当我按Enter键时,文本才会对Haskell应用程序本身可见.
我所追求的是能够阅读单个按键,因此我可以自己实现行编辑.
也许我的问题不清楚.基本上我想构建类似Vi或Emacs(或Yi)的东西.我已经知道有终端绑定可以让我进行花哨的控制台模式打印,所以输出端不应该是一个问题.我只是想找到一种获取原始按键输入的方法,所以我可以做一些事情,比如(例如)当用户按下字母K时将K添加到当前文本行,或者当用户将文件保存到磁盘时按Ctrl + S.
Evi*_*ine 10
这可能是最简单的解决方案,类似于其他编程语言中的典型代码:
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)
Run Code Online (Sandbox Code Playgroud)
它的工作原理是"一次"读取多个字符.允许例如?
,由三个字符组成的键['\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
Run Code Online (Sandbox Code Playgroud)
这有点hackish,因为理论上,用户可以在程序到达之前输入更多的键hReady
.如果终端允许粘贴,可能会发生这种情况.但实际上,对于交互式输入,这不是一个现实的场景.
有趣的事实:光标字符串可以putStr
用来实际以编程方式移动光标.
听起来你想要readline支持.有几个软件包可以做到这一点,但haskeline可能是最容易使用最支持的平台.
import Control.Monad.Trans
import System.Console.Haskeline
type Repl a = InputT IO a
process :: String -> IO ()
process = putStrLn
repl :: Repl ()
repl = do
minput <- getInputLine "> "
case minput of
Nothing -> outputStrLn "Goodbye."
Just input -> (liftIO $ process input) >> repl
main :: IO ()
main = runInputT defaultSettings repl
Run Code Online (Sandbox Code Playgroud)
未完成:
经过几个小时的网上冲浪,我可以报告以下内容:
readline
有一个巨大的界面,几乎没有任何文档.从函数名称和类型签名中你可以猜出这些东西的作用......但它远非微不足道.无论如何,这个库似乎提供了一个高级编辑界面 - 这是我试图自己实现的东西.我需要更低级别的东西.
在浏览源代码之后haskeline
,似乎它有一个巨大的纠结低级代码,单独用于Win32和POSIX.如果是一个简单的方法做控制台I/O,这个库不能证明它.代码看起来如此紧密集成,并且非常具体haskeline
,我怀疑我可以重用它们.但也许通过阅读它我可以学到足够的东西来写自己的东西?
易是......吓坏了.Cabal文件列出了> 150个暴露的模块.(!!)但是,它下面显示的是使用名为vty
POSIX 的软件包.(我想知道Yi如何在Windows上运行?)vty
看起来它可能对我没有进一步修改直接有用.(但同样,不在Windows上.)
unix
有...基本没什么有趣的.它有一堆东西可以在终端上设置东西,但绝对没有什么可以从终端读取.(除了可以检查回声是否打开等等.没有关于按键的信息.)
unix-compat
完全没有兴趣.
一种选择是使用ncurses。一个简单的例子:
import Control.Monad
import UI.NCurses
main :: IO ()
main = runCurses $ do
w <- defaultWindow
forever $ do
e <- getEvent w Nothing
updateWindow w $ do
moveCursor 0 0
drawString (show e)
render
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4448 次 |
最近记录: |