ByteStringsからANSIエスケープコードをフィルタリングするコンジットを作成しようとしています。 ByteStringをWord8のストリームに変換し、フィルタリングし、最後にByteStreamのストリームに変換する関数を思いついた。コンジット付きByteStringからANSIエスケープシーケンスをフィルタリングする
私が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
のフィルタ処理内容をエコーバックすることになっているが、何もエコーバックなかっます。
ansiFilter
をdoConversionAndPrint
にコメントアウトすると、エコーが働いてansiFilter
機能が間違ってしまう事があります。
ご協力いただければ幸いです!
、コードに使用している輸入品を追加してください。 – duplode
'toByteString'は' Word8'のストリーム全体を単一の厳密なバイトコードに変換していませんか?もしそうなら、 'ansiFilter'は決して終わらないはずです。 – Michael
たとえば、 'toByteString = mapC BS.singleton'と書くと、stdinとstdoutの干渉は少し遅れますが、生産的です。 – Michael