{-# LANGUAGE Safe #-}
module System.Console.ANSI
(
module System.Console.ANSI.Types
, cursorUp
, cursorDown
, cursorForward
, cursorBackward
, hCursorUp
, hCursorDown
, hCursorForward
, hCursorBackward
, cursorUpCode
, cursorDownCode
, cursorForwardCode
, cursorBackwardCode
, cursorUpLine
, cursorDownLine
, hCursorUpLine
, hCursorDownLine
, cursorUpLineCode
, cursorDownLineCode
, setCursorColumn
, setCursorPosition
, hSetCursorColumn
, hSetCursorPosition
, setCursorColumnCode
, setCursorPositionCode
, saveCursor
, restoreCursor
, reportCursorPosition
, hSaveCursor
, hRestoreCursor
, hReportCursorPosition
, saveCursorCode
, restoreCursorCode
, reportCursorPositionCode
, clearFromCursorToScreenEnd
, clearFromCursorToScreenBeginning
, clearScreen
, clearFromCursorToLineEnd
, clearFromCursorToLineBeginning
, clearLine
, hClearFromCursorToScreenEnd
, hClearFromCursorToScreenBeginning
, hClearScreen
, hClearFromCursorToLineEnd
, hClearFromCursorToLineBeginning
, hClearLine
, clearFromCursorToScreenEndCode
, clearFromCursorToScreenBeginningCode
, clearScreenCode
, clearFromCursorToLineEndCode
, clearFromCursorToLineBeginningCode
, clearLineCode
, scrollPageUp
, scrollPageDown
, hScrollPageUp
, hScrollPageDown
, scrollPageUpCode
, scrollPageDownCode
, useAlternateScreenBuffer
, useNormalScreenBuffer
, hUseAlternateScreenBuffer
, hUseNormalScreenBuffer
, useAlternateScreenBufferCode
, useNormalScreenBufferCode
, reportLayerColor
, hReportLayerColor
, reportLayerColorCode
, setSGR
, hSetSGR
, setSGRCode
, hideCursor
, showCursor
, hHideCursor
, hShowCursor
, hideCursorCode
, showCursorCode
, hyperlink
, hyperlinkWithId
, hyperlinkWithParams
, hHyperlink
, hHyperlinkWithId
, hHyperlinkWithParams
, hyperlinkCode
, hyperlinkWithIdCode
, hyperlinkWithParamsCode
, setTitle
, hSetTitle
, setTitleCode
, hSupportsANSI
, hNowSupportsANSI
, hSupportsANSIColor
, getCursorPosition
, hGetCursorPosition
, getReportedCursorPosition
, cursorPosition
, getTerminalSize
, hGetTerminalSize
, getLayerColor
, hGetLayerColor
, getReportedLayerColor
, layerColor
, hSupportsANSIWithoutEmulation
) where
import Control.Exception.Base ( bracket )
import Control.Monad ( when, void )
import Data.Char ( digitToInt, isDigit, isHexDigit )
import Data.Colour.SRGB ( RGB (..) )
import Data.Word ( Word16 )
import System.Environment ( getEnvironment )
import System.IO
( BufferMode (..), Handle, hFlush, hGetBuffering, hGetEcho, hPutStr
, hReady, hSetBuffering, hSetEcho, stdin, stdout
)
import Text.ParserCombinators.ReadP
( ReadP, (<++), char, many1, readP_to_S, satisfy, string )
import System.Console.ANSI.Codes
import qualified System.Console.ANSI.Internal as Internal
import System.Console.ANSI.Types
hCursorUp, hCursorDown, hCursorForward, hCursorBackward ::
Handle
-> Int
-> IO ()
hCursorUp :: Handle -> Int -> IO ()
hCursorUp Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorUpCode Int
n
hCursorDown :: Handle -> Int -> IO ()
hCursorDown Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorDownCode Int
n
hCursorForward :: Handle -> Int -> IO ()
hCursorForward Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorForwardCode Int
n
hCursorBackward :: Handle -> Int -> IO ()
hCursorBackward Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorBackwardCode Int
n
cursorUp, cursorDown, cursorForward, cursorBackward ::
Int
-> IO ()
cursorUp :: Int -> IO ()
cursorUp = Handle -> Int -> IO ()
hCursorUp Handle
stdout
cursorDown :: Int -> IO ()
cursorDown = Handle -> Int -> IO ()
hCursorDown Handle
stdout
cursorForward :: Int -> IO ()
cursorForward = Handle -> Int -> IO ()
hCursorForward Handle
stdout
cursorBackward :: Int -> IO ()
cursorBackward = Handle -> Int -> IO ()
hCursorBackward Handle
stdout
hCursorDownLine, hCursorUpLine ::
Handle
-> Int
-> IO ()
hCursorDownLine :: Handle -> Int -> IO ()
hCursorDownLine Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorDownLineCode Int
n
hCursorUpLine :: Handle -> Int -> IO ()
hCursorUpLine Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
cursorUpLineCode Int
n
cursorDownLine, cursorUpLine ::
Int
-> IO ()
cursorDownLine :: Int -> IO ()
cursorDownLine = Handle -> Int -> IO ()
hCursorDownLine Handle
stdout
cursorUpLine :: Int -> IO ()
cursorUpLine = Handle -> Int -> IO ()
hCursorUpLine Handle
stdout
hSetCursorColumn ::
Handle
-> Int
-> IO ()
hSetCursorColumn :: Handle -> Int -> IO ()
hSetCursorColumn Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
setCursorColumnCode Int
n
setCursorColumn ::
Int
-> IO ()
setCursorColumn :: Int -> IO ()
setCursorColumn = Handle -> Int -> IO ()
hSetCursorColumn Handle
stdout
hSetCursorPosition ::
Handle
-> Int
-> Int
-> IO ()
hSetCursorPosition :: Handle -> Int -> Int -> IO ()
hSetCursorPosition Handle
h Int
n Int
m = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> Int -> String
setCursorPositionCode Int
n Int
m
setCursorPosition ::
Int
-> Int
-> IO ()
setCursorPosition :: Int -> Int -> IO ()
setCursorPosition = Handle -> Int -> Int -> IO ()
hSetCursorPosition Handle
stdout
hSaveCursor, hRestoreCursor, hReportCursorPosition :: Handle -> IO ()
hSaveCursor :: Handle -> IO ()
hSaveCursor Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
saveCursorCode
hRestoreCursor :: Handle -> IO ()
hRestoreCursor Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
restoreCursorCode
hReportCursorPosition :: Handle -> IO ()
hReportCursorPosition Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
reportCursorPositionCode
saveCursor :: IO ()
saveCursor :: IO ()
saveCursor = Handle -> IO ()
hSaveCursor Handle
stdout
restoreCursor :: IO ()
restoreCursor :: IO ()
restoreCursor = Handle -> IO ()
hRestoreCursor Handle
stdout
reportCursorPosition :: IO ()
reportCursorPosition :: IO ()
reportCursorPosition = Handle -> IO ()
hReportCursorPosition Handle
stdout
hHideCursor, hShowCursor :: Handle -> IO ()
hHideCursor :: Handle -> IO ()
hHideCursor Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
hideCursorCode
hShowCursor :: Handle -> IO ()
hShowCursor Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
showCursorCode
hideCursor, showCursor :: IO ()
hideCursor :: IO ()
hideCursor = Handle -> IO ()
hHideCursor Handle
stdout
showCursor :: IO ()
showCursor = Handle -> IO ()
hShowCursor Handle
stdout
hUseAlternateScreenBuffer :: Handle -> IO ()
hUseAlternateScreenBuffer :: Handle -> IO ()
hUseAlternateScreenBuffer Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
useAlternateScreenBufferCode
hUseNormalScreenBuffer :: Handle -> IO ()
hUseNormalScreenBuffer :: Handle -> IO ()
hUseNormalScreenBuffer Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
useNormalScreenBufferCode
useAlternateScreenBuffer :: IO ()
useAlternateScreenBuffer :: IO ()
useAlternateScreenBuffer = Handle -> IO ()
hUseAlternateScreenBuffer Handle
stdout
useNormalScreenBuffer :: IO ()
useNormalScreenBuffer :: IO ()
useNormalScreenBuffer = Handle -> IO ()
hUseNormalScreenBuffer Handle
stdout
hHyperlinkWithParams::
Handle
-> [(String, String)]
-> String
-> String
-> IO ()
hHyperlinkWithParams :: Handle -> [(String, String)] -> String -> String -> IO ()
hHyperlinkWithParams Handle
h [(String, String)]
params String
uri String
link =
Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [(String, String)] -> String -> String -> String
hyperlinkWithParamsCode [(String, String)]
params String
uri String
link
hyperlinkWithParams ::
[(String, String)]
-> String
-> String
-> IO ()
hyperlinkWithParams :: [(String, String)] -> String -> String -> IO ()
hyperlinkWithParams = Handle -> [(String, String)] -> String -> String -> IO ()
hHyperlinkWithParams Handle
stdout
hHyperlink ::
Handle
-> String
-> String
-> IO ()
hHyperlink :: Handle -> String -> String -> IO ()
hHyperlink Handle
h = Handle -> [(String, String)] -> String -> String -> IO ()
hHyperlinkWithParams Handle
h []
hyperlink ::
String
-> String
-> IO ()
hyperlink :: String -> String -> IO ()
hyperlink = Handle -> String -> String -> IO ()
hHyperlink Handle
stdout
hHyperlinkWithId ::
Handle
-> String
-> String
-> String
-> IO ()
hHyperlinkWithId :: Handle -> String -> String -> String -> IO ()
hHyperlinkWithId Handle
h String
linkId = Handle -> [(String, String)] -> String -> String -> IO ()
hHyperlinkWithParams Handle
h [(String
"id", String
linkId)]
hyperlinkWithId ::
String
-> String
-> String
-> IO ()
hyperlinkWithId :: String -> String -> String -> IO ()
hyperlinkWithId = Handle -> String -> String -> String -> IO ()
hHyperlinkWithId Handle
stdout
hSetTitle ::
Handle
-> String
-> IO ()
hSetTitle :: Handle -> String -> IO ()
hSetTitle Handle
h String
title = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> String
setTitleCode String
title
setTitle :: String
-> IO ()
setTitle :: String -> IO ()
setTitle = Handle -> String -> IO ()
hSetTitle Handle
stdout
hSupportsANSI :: Handle -> IO Bool
hSupportsANSI :: Handle -> IO Bool
hSupportsANSI = Handle -> IO Bool
Internal.hSupportsANSI
hNowSupportsANSI :: Handle -> IO Bool
hNowSupportsANSI :: Handle -> IO Bool
hNowSupportsANSI = Handle -> IO Bool
Internal.hNowSupportsANSI
hSupportsANSIColor :: Handle -> IO Bool
hSupportsANSIColor :: Handle -> IO Bool
hSupportsANSIColor Handle
h = Bool -> Bool -> Bool
(||) (Bool -> Bool -> Bool) -> IO Bool -> IO (Bool -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Handle -> IO Bool
hSupportsANSI Handle
h IO (Bool -> Bool) -> IO Bool -> IO Bool
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO Bool
isEmacsTerm
where
isEmacsTerm :: IO Bool
isEmacsTerm = (\[(String, String)]
env -> [(String, String)] -> Bool
forall {b}. [(String, b)] -> Bool
insideEmacs [(String, String)]
env Bool -> Bool -> Bool
&& [(String, String)] -> Bool
isDumb [(String, String)]
env) ([(String, String)] -> Bool) -> IO [(String, String)] -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(String, String)]
getEnvironment
insideEmacs :: [(String, b)] -> Bool
insideEmacs = ((String, b) -> Bool) -> [(String, b)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\(String
k, b
_) -> String
k String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"INSIDE_EMACS")
isDumb :: [(String, String)] -> Bool
isDumb [(String, String)]
env = String -> Maybe String
forall a. a -> Maybe a
Just String
"dumb" Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"TERM" [(String, String)]
env
{-# DEPRECATED hSupportsANSIWithoutEmulation "See Haddock documentation and hNowSupportsANSI." #-}
hSupportsANSIWithoutEmulation :: Handle -> IO (Maybe Bool)
hSupportsANSIWithoutEmulation :: Handle -> IO (Maybe Bool)
hSupportsANSIWithoutEmulation Handle
h = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> IO Bool -> IO (Maybe Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Handle -> IO Bool
hNowSupportsANSI Handle
h
cursorPosition :: ReadP (Int, Int)
cursorPosition :: ReadP (Int, Int)
cursorPosition = do
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
'\ESC'
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
'['
String
row <- ReadP String
decimal
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
';'
String
col <- ReadP String
decimal
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
'R'
(Int, Int) -> ReadP (Int, Int)
forall a. a -> ReadP a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Int
forall a. Read a => String -> a
read String
row, String -> Int
forall a. Read a => String -> a
read String
col)
where
digit :: ReadP Char
digit = (Char -> Bool) -> ReadP Char
satisfy Char -> Bool
isDigit
decimal :: ReadP String
decimal = ReadP Char -> ReadP String
forall a. ReadP a -> ReadP [a]
many1 ReadP Char
digit
getReportedCursorPosition :: IO String
getReportedCursorPosition :: IO String
getReportedCursorPosition = IO String
Internal.getReportedCursorPosition
getCursorPosition :: IO (Maybe (Int, Int))
getCursorPosition :: IO (Maybe (Int, Int))
getCursorPosition = Handle -> IO (Maybe (Int, Int))
hGetCursorPosition Handle
stdout
hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
hGetCursorPosition Handle
h = ((Int, Int) -> (Int, Int)) -> Maybe (Int, Int) -> Maybe (Int, Int)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, Int) -> (Int, Int)
forall {a} {b}. (Num a, Num b) => (a, b) -> (a, b)
to0base (Maybe (Int, Int) -> Maybe (Int, Int))
-> IO (Maybe (Int, Int)) -> IO (Maybe (Int, Int))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Maybe (Int, Int))
getCursorPosition'
where
to0base :: (a, b) -> (a, b)
to0base (a
row, b
col) = (a
row a -> a -> a
forall a. Num a => a -> a -> a
- a
1, b
col b -> b -> b
forall a. Num a => a -> a -> a
- b
1)
getCursorPosition' :: IO (Maybe (Int, Int))
getCursorPosition' = do
String
input <- IO BufferMode
-> (BufferMode -> IO ()) -> (BufferMode -> IO String) -> IO String
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Handle -> IO BufferMode
hGetBuffering Handle
stdin) (Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdin) ((BufferMode -> IO String) -> IO String)
-> (BufferMode -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \BufferMode
_ -> do
Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdin BufferMode
NoBuffering
IO Bool -> (Bool -> IO ()) -> (Bool -> IO String) -> IO String
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Handle -> IO Bool
hGetEcho Handle
stdin) (Handle -> Bool -> IO ()
hSetEcho Handle
stdin) ((Bool -> IO String) -> IO String)
-> (Bool -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \Bool
_ -> do
Handle -> Bool -> IO ()
hSetEcho Handle
stdin Bool
False
IO ()
clearStdin
Handle -> IO ()
hReportCursorPosition Handle
h
Handle -> IO ()
hFlush Handle
h
IO String
getReportedCursorPosition
case ReadP (Int, Int) -> ReadS (Int, Int)
forall a. ReadP a -> ReadS a
readP_to_S ReadP (Int, Int)
cursorPosition String
input of
[] -> Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Int, Int)
forall a. Maybe a
Nothing
[((Int
row, Int
col),String
_)] -> Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (Int, Int) -> IO (Maybe (Int, Int)))
-> Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
row, Int
col)
(((Int, Int), String)
_:[((Int, Int), String)]
_) -> Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Int, Int)
forall a. Maybe a
Nothing
clearStdin :: IO ()
clearStdin = do
Bool
isReady <- Handle -> IO Bool
hReady Handle
stdin
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isReady (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Char
_ <-IO Char
getChar
IO ()
clearStdin
reportLayerColor :: ConsoleLayer -> IO ()
reportLayerColor :: ConsoleLayer -> IO ()
reportLayerColor = Handle -> ConsoleLayer -> IO ()
hReportLayerColor Handle
stdout
hReportLayerColor :: Handle -> ConsoleLayer -> IO ()
hReportLayerColor :: Handle -> ConsoleLayer -> IO ()
hReportLayerColor Handle
h ConsoleLayer
layer = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ ConsoleLayer -> String
reportLayerColorCode ConsoleLayer
layer
getReportedLayerColor :: ConsoleLayer -> IO String
getReportedLayerColor :: ConsoleLayer -> IO String
getReportedLayerColor = ConsoleLayer -> IO String
Internal.getReportedLayerColor
getLayerColor :: ConsoleLayer -> IO (Maybe(RGB Word16))
getLayerColor :: ConsoleLayer -> IO (Maybe (RGB Word16))
getLayerColor = Handle -> ConsoleLayer -> IO (Maybe (RGB Word16))
hGetLayerColor Handle
stdout
hGetLayerColor :: Handle -> ConsoleLayer -> IO (Maybe (RGB Word16))
hGetLayerColor :: Handle -> ConsoleLayer -> IO (Maybe (RGB Word16))
hGetLayerColor Handle
h ConsoleLayer
layer = do
String
input <- IO BufferMode
-> (BufferMode -> IO ()) -> (BufferMode -> IO String) -> IO String
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Handle -> IO BufferMode
hGetBuffering Handle
stdin) (Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdin) ((BufferMode -> IO String) -> IO String)
-> (BufferMode -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \BufferMode
_ -> do
Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdin BufferMode
NoBuffering
IO Bool -> (Bool -> IO ()) -> (Bool -> IO String) -> IO String
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Handle -> IO Bool
hGetEcho Handle
stdin) (Handle -> Bool -> IO ()
hSetEcho Handle
stdin) ((Bool -> IO String) -> IO String)
-> (Bool -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \Bool
_ -> do
Handle -> Bool -> IO ()
hSetEcho Handle
stdin Bool
False
IO ()
clearStdin
Handle -> ConsoleLayer -> IO ()
hReportLayerColor Handle
h ConsoleLayer
layer
Handle -> IO ()
hFlush Handle
h
ConsoleLayer -> IO String
getReportedLayerColor ConsoleLayer
layer
case ReadP (RGB Word16) -> ReadS (RGB Word16)
forall a. ReadP a -> ReadS a
readP_to_S (ConsoleLayer -> ReadP (RGB Word16)
layerColor ConsoleLayer
layer) String
input of
[] -> Maybe (RGB Word16) -> IO (Maybe (RGB Word16))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (RGB Word16)
forall a. Maybe a
Nothing
[(RGB Word16
col, String
_)] -> Maybe (RGB Word16) -> IO (Maybe (RGB Word16))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (RGB Word16) -> IO (Maybe (RGB Word16)))
-> Maybe (RGB Word16) -> IO (Maybe (RGB Word16))
forall a b. (a -> b) -> a -> b
$ RGB Word16 -> Maybe (RGB Word16)
forall a. a -> Maybe a
Just RGB Word16
col
((RGB Word16, String)
_:[(RGB Word16, String)]
_) -> Maybe (RGB Word16) -> IO (Maybe (RGB Word16))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (RGB Word16)
forall a. Maybe a
Nothing
where
clearStdin :: IO ()
clearStdin = do
Bool
isReady <- Handle -> IO Bool
hReady Handle
stdin
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isReady (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Char
_ <-IO Char
getChar
IO ()
clearStdin
layerColor :: ConsoleLayer -> ReadP (RGB Word16)
layerColor :: ConsoleLayer -> ReadP (RGB Word16)
layerColor ConsoleLayer
layer = do
ReadP String -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP String -> ReadP ()) -> ReadP String -> ReadP ()
forall a b. (a -> b) -> a -> b
$ String -> ReadP String
string String
"\ESC]"
ReadP String -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP String -> ReadP ()) -> ReadP String -> ReadP ()
forall a b. (a -> b) -> a -> b
$ String -> ReadP String
string (String -> ReadP String) -> String -> ReadP String
forall a b. (a -> b) -> a -> b
$ case ConsoleLayer
layer of
ConsoleLayer
Foreground -> String
"10"
ConsoleLayer
Background -> String
"11"
ReadP String -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP String -> ReadP ()) -> ReadP String -> ReadP ()
forall a b. (a -> b) -> a -> b
$ String -> ReadP String
string String
";rgb:"
String
redHex <- ReadP String
hexadecimal
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
'/'
String
greenHex <- ReadP String
hexadecimal
ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
'/'
String
blueHex <- ReadP String
hexadecimal
ReadP String -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP String -> ReadP ()) -> ReadP String -> ReadP ()
forall a b. (a -> b) -> a -> b
$ String -> ReadP String
string String
"\BEL" ReadP String -> ReadP String -> ReadP String
forall a. ReadP a -> ReadP a -> ReadP a
<++ String -> ReadP String
string String
"\ESC\\"
let lenRed :: Int
lenRed = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
redHex
lenGreen :: Int
lenGreen = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
greenHex
lenBlue :: Int
lenBlue = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
blueHex
if Int
lenRed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
lenGreen Bool -> Bool -> Bool
&& Int
lenGreen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
lenBlue
then
if Int
lenRed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| Int
lenRed Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
4
then String -> ReadP (RGB Word16)
forall a. String -> ReadP a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Color format not recognised"
else
let m :: Int
m = Int
16 Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lenRed)
r :: Word16
r = Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
* String -> Int
hexToInt String
redHex
g :: Word16
g = Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
* String -> Int
hexToInt String
greenHex
b :: Word16
b = Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
* String -> Int
hexToInt String
blueHex
in RGB Word16 -> ReadP (RGB Word16)
forall a. a -> ReadP a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RGB Word16 -> ReadP (RGB Word16))
-> RGB Word16 -> ReadP (RGB Word16)
forall a b. (a -> b) -> a -> b
$ Word16 -> Word16 -> Word16 -> RGB Word16
forall a. a -> a -> a -> RGB a
RGB Word16
r Word16
g Word16
b
else String -> ReadP (RGB Word16)
forall a. String -> ReadP a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Color format not recognised"
where
hexDigit :: ReadP Char
hexDigit = (Char -> Bool) -> ReadP Char
satisfy Char -> Bool
isHexDigit
hexadecimal :: ReadP String
hexadecimal = ReadP Char -> ReadP String
forall a. ReadP a -> ReadP [a]
many1 ReadP Char
hexDigit
hexToInt :: String -> Int
hexToInt String
hex = (Int -> Int -> Int) -> Int -> [Int] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Int
d Int
a -> Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
16 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
a) Int
0 ((Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt String
hex)
getTerminalSize :: IO (Maybe (Int, Int))
getTerminalSize :: IO (Maybe (Int, Int))
getTerminalSize = Handle -> IO (Maybe (Int, Int))
hGetTerminalSize Handle
stdout
hGetTerminalSize :: Handle -> IO (Maybe (Int, Int))
hGetTerminalSize :: Handle -> IO (Maybe (Int, Int))
hGetTerminalSize Handle
h = do
Handle -> IO ()
hSaveCursor Handle
h
Handle -> Int -> Int -> IO ()
hSetCursorPosition Handle
h Int
9999 Int
9999
Maybe (Int, Int)
mPos <- Handle -> IO (Maybe (Int, Int))
hGetCursorPosition Handle
h
Handle -> IO ()
hRestoreCursor Handle
h
Handle -> IO ()
hFlush Handle
h
Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (Int, Int) -> IO (Maybe (Int, Int)))
-> Maybe (Int, Int) -> IO (Maybe (Int, Int))
forall a b. (a -> b) -> a -> b
$ ((Int, Int) -> (Int, Int)) -> Maybe (Int, Int) -> Maybe (Int, Int)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Int
r, Int
c) -> (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) Maybe (Int, Int)
mPos
hSetSGR ::
Handle
-> [SGR]
-> IO ()
hSetSGR :: Handle -> [SGR] -> IO ()
hSetSGR Handle
h [SGR]
sgrs = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [SGR] -> String
setSGRCode [SGR]
sgrs
setSGR ::
[SGR]
-> IO ()
setSGR :: [SGR] -> IO ()
setSGR = Handle -> [SGR] -> IO ()
hSetSGR Handle
stdout
hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen ::
Handle
-> IO ()
hClearFromCursorToScreenEnd :: Handle -> IO ()
hClearFromCursorToScreenEnd Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
clearFromCursorToScreenEndCode
hClearFromCursorToScreenBeginning :: Handle -> IO ()
hClearFromCursorToScreenBeginning Handle
h
= Handle -> String -> IO ()
hPutStr Handle
h String
clearFromCursorToScreenBeginningCode
hClearScreen :: Handle -> IO ()
hClearScreen Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
clearScreenCode
clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen :: IO ()
clearFromCursorToScreenEnd :: IO ()
clearFromCursorToScreenEnd = Handle -> IO ()
hClearFromCursorToScreenEnd Handle
stdout
clearFromCursorToScreenBeginning :: IO ()
clearFromCursorToScreenBeginning = Handle -> IO ()
hClearFromCursorToScreenBeginning Handle
stdout
clearScreen :: IO ()
clearScreen = Handle -> IO ()
hClearScreen Handle
stdout
hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine ::
Handle
-> IO ()
hClearFromCursorToLineEnd :: Handle -> IO ()
hClearFromCursorToLineEnd Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
clearFromCursorToLineEndCode
hClearFromCursorToLineBeginning :: Handle -> IO ()
hClearFromCursorToLineBeginning Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
clearFromCursorToLineBeginningCode
hClearLine :: Handle -> IO ()
hClearLine Handle
h = Handle -> String -> IO ()
hPutStr Handle
h String
clearLineCode
clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine :: IO ()
clearFromCursorToLineEnd :: IO ()
clearFromCursorToLineEnd = Handle -> IO ()
hClearFromCursorToLineEnd Handle
stdout
clearFromCursorToLineBeginning :: IO ()
clearFromCursorToLineBeginning = Handle -> IO ()
hClearFromCursorToLineBeginning Handle
stdout
clearLine :: IO ()
clearLine = Handle -> IO ()
hClearLine Handle
stdout
hScrollPageUp, hScrollPageDown ::
Handle
-> Int
-> IO ()
hScrollPageUp :: Handle -> Int -> IO ()
hScrollPageUp Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
scrollPageUpCode Int
n
hScrollPageDown :: Handle -> Int -> IO ()
hScrollPageDown Handle
h Int
n = Handle -> String -> IO ()
hPutStr Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> String
scrollPageDownCode Int
n
scrollPageUp, scrollPageDown ::
Int
-> IO ()
scrollPageUp :: Int -> IO ()
scrollPageUp = Handle -> Int -> IO ()
hScrollPageUp Handle
stdout
scrollPageDown :: Int -> IO ()
scrollPageDown = Handle -> Int -> IO ()
hScrollPageDown Handle
stdout