-- | Convert or strip control characters from input.
--
-- * Tab (HT) is replaced with 8 spaces.
-- * Other C0 codes (except CR and LF) and DEL are replaced with
--   <https://en.wikipedia.org/wiki/Control_Pictures Control Pictures>
-- * C1 and all other control characters are replaced with
--   REPLACEMENT CHARACTER U+FFFD
--
sanitiseText :: T.Text -> T.Text
sanitiseText = T.map substControl . T.replace "\t" "        "
  where
  substControl c
    | c == '\n' || c == '\r' = c  -- CR and LF are OK
    | c <= '\x1f' = chr (0x2400 + ord c)
    | c == '\DEL' = '\x2421'
    | isControl c = '\xfffd' -- REPLACEMENT CHARACTER
    | otherwise = c
sanitiseText :: T.Text -> T.Text
sanitiseText = T.map substControl . T.replace "\t" "        "
  where
  substControl c
    | c == '\n' || c == '\r' = c  -- CR and LF are OK
    | c <= '\x1f' = chr (0x2400 + ord c)
    | c == '\DEL' = '\x2421'
    | isControl c = '\xfffd' -- REPLACEMENT CHARACTER
    | otherwise = c
sanitiseText = T.map substControl . T.replace "\t" "        "
  where
  substControl c
    | c == '\n' || c == '\r' = c  -- CR and LF are OK
    | c <= '\x1f' = chr (0x2400 + ord c)
    | c == '\DEL' = '\x2421'
    | isControl c = '\xfffd' -- REPLACEMENT CHARACTER
    | otherwise = c