I am trying to make a Conduit that filters ANSI escape codes from ByteStrings. I came up with a function that converts a ByteString to a Word8 stream, performs filtering, and converts back to a ByteStream at the end.
It seems to work fine when I use it in GHCi:
> runConduit $ yield "hello\27[23;1m world" .| ansiFilter .| printC "hello world"
When I use it in my application, cables containing ansiFilter do not seem to miss anything. Here is the complete source:
{-# 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
This program should track the filtered contents of stdin , but nothing returns.
However, if I comment on ansiFilter in doConversionAndPrint , an echo, it does work that makes the ansiFilter function ansiFilter .
Any help would be greatly appreciated!
source share