如何在Haskell中使用readline在任何按键上删除终端中的一行?

时间:2015-02-21 12:12:45

标签: haskell readline

我正在使用Haskell bindingsreadline库来阅读用户的输入。

我想要实现的是提供一个预填充值,只需点击返回键即可提交,但如果用户开始输入,我想自动删除预填充文本。 (这样用户就不必关心擦除预填充值。)

我认为可以使用rl_getc_function挂钩来完成。但是,Haskell绑定不会公开此函数。

有什么方法可以达到预期的行为吗?

1 个答案:

答案 0 :(得分:0)

最后我找到了一种方法,但这并不好,感觉有点像黑客。

它的工作原理是将所有键重新绑定到首先删除该行的自定义函数,然后重置所有这些处理程序以实际再次插入该字符。为了不失去触发按键,它被推回输入。

main :: IO ()
main = do
    -- create a copy of current keymap
    keymap <- getKeymap >>= copyKeymap
    -- bind (hopefully all) regular keys to a helper function
    forM_ (map toEnum [32..256]) $ \key ->
        bindKey key $ \ _ _ -> do
            -- delete all text on line
            getEnd >>= deleteText 0
            -- set cursor to start of line
            setPoint 0
            redisplay
            -- reset keymap to the original one
            setKeymap keymap
            -- push pressed key back to input
            setPendingInput key
            return 0
    setStartupHook (Just $ insertText "prefilled text")
    readline "prompt> "

这个主要的痛点是确定要重新绑定的键。我使用了一种科学的反复试验方法:下限就是空间(任何不到的东西都是不可打印的,可能有一些特殊的功能,我不想搞砸它)。上限设置为256 - 任何更多的结果导致段错误,使用较少的数字使该函数无法处理某些unicode输入。

即使使用此范围,如果用户开始在CJK中输入内容,它也可能无效。如果用户使用dead key键入内容,它肯定无法正常工作。