{-# LANGUAGE Safe #-} {-| Module : Data.Char.Control Description : Visualizing control characters. Maintainer : hapytexeu+gh@gmail.com Stability : experimental Portability : POSIX Unicode has a <https://www.unicode.org/charts/PDF/U2400.pdf block> named /Control Pictures/ that visualizes control characters such as NULL, SUB, LF, DEL, etc. This module aims to make it more convenient to convert the control characters to their visualization and vice versa. Only ASCII control characters and the space are supported. -} module Data.Char.Control ( -- * Conversion to control pictures controlPicture, controlPicture', convertToControlPictures -- * Conversion from control picturesa , fromControlPicture, fromControlPicture' -- * Check if a 'Char' is a control 'Char' , isAsciiControl, isControl, hasControlVisualization -- * Alternative characters , blankSymbol, openBox, newLine, alternativeDelete, alternativeSubstitute ) where import Data.Bits((.&.), (.|.)) import Data.Char(chr, ord, isControl) import Data.Maybe(fromMaybe) import Data.Text as T -- | Check if the given 'Char' is a control character in the ASCII range. isAsciiControl :: Char -- ^ The given 'Char' to check. -> Bool -- ^ 'True' if the given 'Char' is a control character in the ASCII range; otherwise 'False'. isAsciiControl :: Char -> Bool isAsciiControl Char c = Char c Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char '\x7f' Bool -> Bool -> Bool && Char -> Bool isControl Char c -- | Check if for the given 'Char' there is a visualization. hasControlVisualization :: Char -- ^ The given 'Char' to check. -> Bool -- ^ 'True' if the given control character can be visualized; 'False' otherwise. hasControlVisualization :: Char -> Bool hasControlVisualization Char ' ' = Bool True hasControlVisualization Char c = Char -> Bool isAsciiControl Char c -- | Another symbol used to denote a /space/ that works with @␢@. The 'controlPicture' function uses @␠@. blankSymbol :: Char -- ^ Another character for /space/. blankSymbol :: Char blankSymbol = Char '\x2422' -- | Another symbol used to denote a /space/ that works with @␣@. The 'controlPicture' function uses @␠@. openBox :: Char -- ^ Another character for /space/. openBox :: Char openBox = Char '\x2423' -- | Another symbol used to denote a /new line/ that works with @@. The control picture function uses @␊@. newLine :: Char -- ^ Another character for a /new line/. newLine :: Char newLine = Char '\x2424' -- | Another symbol used to denote a /delete/ character that works with @␥@. The control picture function uses @␡@. alternativeDelete :: Char -- ^ Another character for /delete/. alternativeDelete :: Char alternativeDelete = Char '\x2425' -- | Another symbol used to denote a /substitute/ character that works with @␦@. The control picture function uses @␚@. alternativeSubstitute :: Char -- ^ Another character for /substitute/. alternativeSubstitute :: Char alternativeSubstitute = Char '\x2426' -- | Convert the given control 'Char' to a 'Char' that visualizes that characters. -- This is sometimes done by diagonal lettering of the characters denoting the control -- character. If the given 'Char' is not a control character, 'Nothing' is returned. controlPicture :: Char -- ^ The given control 'Char' to convert. -> Maybe Char -- The corresponding 'Char' that visualizes the control 'Char' wrapped in a 'Just'; 'Nothing' if the given 'Char' is not a control character. controlPicture :: Char -> Maybe Char controlPicture Char c | Char c Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char ' ' = Char -> Maybe Char forall a. a -> Maybe a Just (Char -> Char controlPicture' Char c) | Bool otherwise = Maybe Char forall a. Maybe a Nothing -- | Convert the given control 'Char' to a 'Char' that visualizes that character. -- If the given 'Char' is not a control character, it is unspecified what happens. controlPicture' :: Char -- ^ The given control 'Char'. -> Char -- ^ The corresponding 'Char' that visualizes the control 'Char'. controlPicture' :: Char -> Char controlPicture' Char c | Char c Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char ' ' = Int -> Char chr (Int 0x2400 Int -> Int -> Int forall a. Bits a => a -> a -> a .|. Char -> Int ord Char c) | Bool otherwise = Char '\x2421' -- | Convert the given visualization of a control 'Char' to that control 'Char' wrapped -- in a 'Just'. If the given 'Char' is not a visualization of a control character, -- 'Nothing' is returned. fromControlPicture :: Char -- ^ The given /visualization/ of control 'Char'. -> Maybe Char -- ^ The corresponding control 'Char' wrapped in a 'Just' if the given character is the visualization of a control character; otherwise 'Nothing'. fromControlPicture :: Char -> Maybe Char fromControlPicture Char c | Char '\x2400' Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char c Bool -> Bool -> Bool && Char c Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char '\x2426' = Char -> Maybe Char forall a. a -> Maybe a Just (Char -> Char fromControlPicture' Char c) | Bool otherwise = Maybe Char forall a. Maybe a Nothing -- | Convert the given visualization of a control 'Char' to that control 'Char'. -- If the given 'Char' is not a visualization of a control character, -- it is unspecified what happens. fromControlPicture' :: Char -- ^ The given /visualization/ of control 'Char'. -> Char -- ^ The corresponding control 'Char'. fromControlPicture' :: Char -> Char fromControlPicture' Char '\x2421' = Char '\x7f' fromControlPicture' Char '\x2422' = Char ' ' fromControlPicture' Char '\x2423' = Char ' ' fromControlPicture' Char '\x2424' = Char '\x0a' fromControlPicture' Char '\x2425' = Char '\x7f' fromControlPicture' Char '\x2426' = Char '\x1a' fromControlPicture' Char c = Int -> Char chr (Int 0x7f Int -> Int -> Int forall a. Bits a => a -> a -> a .&. Char -> Int ord Char c) -- | Convert the given 'Text' to a 'Text' object where the control characters -- that have in Unicode a control picture block item. convertToControlPictures :: Text -- ^ The given 'Text' where we want to convert control characters to their control picture characters. -> Text -- ^ The corresponding 'Text' where the control characters are converted to their control picture characters. convertToControlPictures :: Text -> Text convertToControlPictures = (Char -> Char) -> Text -> Text T.map (Char -> Maybe Char -> Char forall a. a -> Maybe a -> a fromMaybe (Char -> Maybe Char -> Char) -> (Char -> Maybe Char) -> Char -> Char forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> Char -> Maybe Char controlPicture)