tilia-0.0.1.0: src/Tilia/Palette.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
-- | The color palette abstraction for printing to color-capable terminals.
module Tilia.Palette
( Palette (..),
paletteFor,
Color (..),
paint,
marker,
)
where
import Data.Maybe (isJust)
import Data.Text (Text)
import System.Environment (lookupEnv)
import System.IO (hIsTerminalDevice, stdout)
-- | Whether to color the output.
data Palette = Colors | Plain
deriving (Eq, Show)
-- | Color output when there is somebody there to see it.
paletteFor :: IO Palette
paletteFor = do
refused <- lookupEnv "NO_COLOR"
terminal <- hIsTerminalDevice stdout
pure $
if terminal && not (isJust refused)
then Colors
else Plain
-- | Different kinds of colors, classified semantically.
data Color
= -- | A diff's hunk headings and its asides.
Meta
| -- | A line a change removes.
Gone
| -- | A line a change adds.
New
| -- | A line a change leaves alone.
Unchanged
| -- | Something that went well.
Good
| -- | Something that did not, without being wrong.
Middling
| -- | Something wrong.
Bad
| -- | An operator.
Operator
| -- | Somewhere a message points at—a file, a module, the heading over a
-- file's diff.
Place
| -- | A heading over what follows it.
Header Color
deriving (Eq, Show)
-- | Color one piece of text, and only that piece.
paint :: Palette -> Color -> Text -> Text
paint Plain _ t = t
paint Colors color t = code color <> t <> "\ESC[0m"
where
code = \case
Meta -> "\ESC[36m"
Gone -> "\ESC[31m"
New -> "\ESC[32m"
Unchanged -> "\ESC[39m"
Good -> "\ESC[32m"
Middling -> "\ESC[33m"
Bad -> "\ESC[31m"
Operator -> "\ESC[36m"
Place -> "\ESC[1m"
Header i -> "\ESC[1m" <> code i
-- | A marker in brackets, as the summary lines wear one.
marker :: Palette -> Color -> Text -> Text
marker palette color mark = "[" <> paint palette color mark <> "]"