    > 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)