module Penny.Shield (
ScreenLines,
unScreenLines,
ScreenWidth,
unScreenWidth,
Output(IsTTY, NotTTY),
Runtime,
environment,
currentTime,
output,
screenLines,
screenWidth,
Term,
term,
runtime,
termFromEnv,
autoTerm)
where
import Control.Applicative ((<$>), (<*>))
import qualified Data.Time as T
import System.Environment (getEnvironment)
import System.IO (hIsTerminalDevice, stdout)
import qualified System.Console.Rainbow as C
import qualified Penny.Lincoln.Bits as B
data ScreenLines = ScreenLines { unScreenLines :: Int }
deriving Show
newtype ScreenWidth = ScreenWidth { unScreenWidth :: Int }
deriving Show
data Output = IsTTY | NotTTY deriving (Eq, Ord, Show)
newtype Term = Term { unTerm :: String } deriving Show
data Runtime = Runtime { environment :: [(String, String)]
, currentTime :: B.DateTime
, output :: Output }
runtime :: IO Runtime
runtime = Runtime
<$> getEnvironment
<*> (toDT <$> T.getZonedTime)
<*> findOutput
where
toDT t = case B.fromZonedTime t of
Nothing -> error "time conversion error"
Just ti -> ti
findOutput :: IO Output
findOutput = do
isTerm <- hIsTerminalDevice stdout
return $ if isTerm then IsTTY else NotTTY
screenLines :: Runtime -> Maybe ScreenLines
screenLines r =
(lookup "LINES" . environment $ r)
>>= safeRead
>>= return . ScreenLines
screenWidth :: Runtime -> Maybe ScreenWidth
screenWidth r =
(lookup "COLUMNS" . environment $ r)
>>= safeRead
>>= return . ScreenWidth
term :: Runtime -> Maybe Term
term r =
(lookup "TERM" . environment $ r)
>>= return . Term
safeRead :: (Read a) => String -> Maybe a
safeRead s = case reads s of
(a, []):[] -> Just a
_ -> Nothing
termFromEnv :: Runtime -> C.Term
termFromEnv rt = case term rt of
Just t -> C.TermName . unTerm $ t
Nothing -> C.Dumb
autoTerm :: Runtime -> C.Term
autoTerm rt = case output rt of
IsTTY -> termFromEnv rt
NotTTY -> C.Dumb