【发布时间】:2016-12-08 01:26:54
【问题描述】:
我正在尝试制作一个从 ByteStrings 过滤 ANSI 转义码的导管。我想出了一个函数,将 ByteString 转换为 Word8 的流,进行过滤,最后再转换回 ByteStream 流。
当我在 GHCi 中使用它时,它似乎工作正常:
> runConduit $ yield "hello\27[23;1m world" .| ansiFilter .| printC
"hello world"
当我在我的应用程序中使用它时,包含ansiFilter 的管道似乎没有通过任何东西。这是完整的来源:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Conduit
import Control.Concurrent.Async
import Control.Concurrent.STM
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Conduit.TQueue
import Data.Word8 (Word8)
import qualified Data.Word8 as Word8
main :: IO ()
main = do
queue <- atomically $ newTBQueue 25
let qSource = sourceTBQueue queue
atomically $ writeTBQueue queue ("hello" :: ByteString)
race_
(putInputIntoQueue queue)
(doConversionAndPrint qSource)
putInputIntoQueue q =
runConduit
$ stdinC
.| iterMC (atomically . writeTBQueue q)
.| sinkNull
doConversionAndPrint src =
runConduit
$ src
.| ansiFilter
.| stdoutC
ansiFilter :: MonadIO m => ConduitM ByteString ByteString m ()
ansiFilter = toWord8 .| ansiFilter' .| toByteString
where
ansiFilter' = awaitForever $ \first -> do
msecond <- peekC
case (first, msecond) of
(0x1b, Just 0x5b) -> do
dropWhileC (not . Word8.isLetter)
dropC 1
_ -> yield first
toWord8 = concatC
toByteString :: Monad m => ConduitM Word8 ByteString m ()
toByteString =
(mapC BS.singleton .| foldC) >>= yield
这个程序应该回显stdin的过滤内容,但没有回显。
但是,如果我在 doConversionAndPrint 中注释掉 ansiFilter,回显确实有效,这让我觉得 ansiFilter 函数是错误的。
任何帮助将不胜感激!
【问题讨论】:
-
请将您正在使用的导入添加到代码中,以便我们可以更直接地运行它。
-
toByteString不是将整个Word8s 流变成一个严格的字节串吗?如果是这样,ansiFilter似乎永远不会完成。 -
例如,如果我只写
toByteString = mapC BS.singleton它是有效率的,虽然标准输入和标准输出的干扰有点难以理解。 -
@duplode 我编辑了我的问题以包含导入。对此感到抱歉。