Ich versuche, ein Conduit zu erstellen, das ANSI-Escape-Codes von ByteStrings filtert. Ich habe eine Funktion entwickelt, die den ByteString in einen Stream von Word8 konvertiert, filtert und am Ende wieder in einen Stream von ByteStream konvertiert.Filtern von ANSI-Escape-Sequenzen von einem ByteString mit Conduit
Es scheint gut zu funktionieren, wenn ich es in GHCi verwenden:
> runConduit $ yield "hello\27[23;1m world" .| ansiFilter .| printC
"hello world"
Als ich es in meiner Anwendung verwenden, Leitungen, die ansiFilter
enthalten scheinen nicht durch irgendetwas zu passieren. Hier ist die vollständige Quelle:
{-# 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
Dieses Programm soll die gefilterten Inhalte stdin
Echo zurück, aber nichts wird wieder wiederholt.
Allerdings, wenn ich die ansiFilter
in doConversionAndPrint
kommentieren, funktioniert Echo, was mich die ansiFilter
Funktion falsch macht.
Jede Hilfe würde sehr geschätzt werden!
Bitte fügen Sie die Importe Sie den Code verwenden, damit wir es ohne weiteres ausgeführt werden kann. – duplode
Ist 'toByteString' nicht der ganze Stream von' Word8' in einen einzigen string Bytestring? Wenn dem so ist, scheint 'ansiFilter' niemals fertig zu werden. – Michael
Zum Beispiel wenn ich nur 'toByteString = mapC BS.singleton' schreibe, ist es produktiv, obwohl die Interferenz von stdin und stdout ein wenig schwer zu folgen ist. – Michael