> module Test.HUnit.Terminal
> (
>   terminalAppearance
> )
> where
> import Data.Char (isPrint)
Simplifies the input string by interpreting '\r' and '\b' characters specially so that the result string has the same final (or "terminal", pun intended) appearance as would the input string when written to a terminal that overwrites character positions following carriage returns and backspaces. The helper function `ta` takes an accumulating `ShowS`-style function that holds "committed" lines of text, a (reversed) list of characters on the current line *before* the cursor, a (normal) list of characters on the current line *after* the cursor, and the remaining input.
> terminalAppearance :: String -> String
> terminalAppearance str = ta id "" "" str
>  where
>   ta f bs as ('\n':cs) = ta (\t -> f (reverse bs ++ as ++ '\n' : t)) "" "" cs
>   ta f bs as ('\r':cs) = ta f "" (reverse bs ++ as) cs
>   ta f (b:bs) as ('\b':cs) = ta f bs (b:as) cs
>   ta f ""     as ('\b':cs) = error "'\\b' at beginning of line"
>   ta f bs as (c:cs) | not (isPrint c) = error "invalid nonprinting character"
>                     | null as   = ta f (c:bs) ""        cs
>                     | otherwise = ta f (c:bs) (tail as) cs
>   ta f bs as "" = f (reverse bs ++ as)