在Windows中从Haskell输入UTF-8输入/输出 [英] UTF-8 input/output in from Haskell in Windows
问题描述
无论使用Prelude的getLine/putStrLn还是使用Data.Text.IO:
Simple code below does not work correctly in Windows terminal with UTF-8 characters, whether with getLine/putStrLn from Prelude or from Data.Text.IO:
main = forever $ getLine >>= putStrLn
在输入期间回显utf-8字符,然后打印?"代替utf-8字符;使用 chcp 65001
切换编码会使它们成为空格.
It echoes utf-8 characters during the input, then it prints "?"s in place of utf-8 characters; switching encoding with chcp 65001
makes them spaces.
我已经下载了新的终端并以此页面建议,但没有效果.
I've downloaded the new terminal and enabled utf-8 support as this page suggested, but it had no effect.
此解释似乎相关,但是提出的解决方案不起作用(代码也一样).
This explanation seems related, but the solution proposed there does not work (the code does the same).
显然python有一个类似问题
Apparently python has a similar issue
是否有适用于GHC 8.x的库/解决方法?
Is there any library/workaround that would work with GHC 8.x?
请帮助!
经过更多调查,问题同样出在输入过程中-如果不是我用putcodeLn而不是putStrLn来打印带有 mapM_(print.ord)s
的字符代码,则它们都是63而没有更改编码或 chcp 65001
之后为0.
after more investigation, the problem is during the input as well - if instead of putStrLn I print character codes with mapM_ (print . ord) s
they are all either 63 without changing encoding or 0 after chcp 65001
.
hSetEncoding stdin utf8
没有帮助
推荐答案
I've found the library that does it: https://hackage.haskell.org/package/terminal
它不包括getLine(仅包含键事件),但是实现起来很简单:
It does not include getLine (only key events), but it's simple enough to implement:
import Control.Monad.IO.Class (liftIO)
import System.Exit (exitSuccess)
import System.Terminal as C
getTermLine :: MonadTerminal m => m String
getTermLine = getChars ""
where
getChars s = awaitEvent >>= processKey s
processKey s = \case
Right (KeyEvent key ms) -> case key of
CharKey c
| ms == mempty || ms == shiftKey -> do
C.putChar c
flush -- works without flush in Windows, but not in Mac
getChars (c : s)
| otherwise -> getChars s
EnterKey -> do
putLn
flush
pure $ reverse s
BackspaceKey -> do
moveCursorBackward 1
eraseChars 1
flush
getChars $ if null s then s else tail s
_ -> getChars s
Left Interrupt -> liftIO exitSuccess
_ -> getChars s
这篇关于在Windows中从Haskell输入UTF-8输入/输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!