在Windows中从Haskell输入UTF-8输入/输出 [英] UTF-8 input/output in from Haskell in Windows

查看:42
本文介绍了在Windows中从Haskell输入UTF-8输入/输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无论使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆