Allure-0.4.2: src/Display/Vty.hs
module Display.Vty
(displayId, startup, shutdown, display, nextEvent, Session) where
import Graphics.Vty
import qualified Data.List as L
import qualified Data.ByteString.Char8 as BS
import Area
import Loc
import qualified Keys as K (Key(..))
import qualified Color
displayId :: String
displayId = "vty"
type Session = Vty
startup :: (Session -> IO ()) -> IO ()
startup k = mkVty >>= k
display :: Area -> Session -> (Loc -> (Color.Attr, Char)) -> String -> String
-> IO ()
display (x0, y0, x1, y1) vty f msg status =
let img = (foldr (<->) empty_image .
L.map (foldr (<|>) empty_image .
L.map (\ (x, y) -> let (a, c) = f (toLoc (x1 + 1) (x, y))
in char (setAttr a) c)))
[ [ (x, y) | x <- [x0..x1] ] | y <- [y0..y1] ]
in update vty (pic_for_image
(utf8_bytestring (setAttr Color.defaultAttr)
(BS.pack (toWidth (x1 - x0 + 1) msg)) <->
img <->
utf8_bytestring (setAttr Color.defaultAttr)
(BS.pack (toWidth (x1 - x0 + 1) status))))
toWidth :: Int -> String -> String
toWidth n x = take n (x ++ repeat ' ')
keyTranslate :: Event -> K.Key
keyTranslate e =
case e of
EvKey KEsc [] -> K.Esc
EvKey KEnter [] -> K.Return
EvKey (KASCII '\t') [] -> K.Tab
EvKey KUp [] -> K.Up
EvKey KDown [] -> K.Down
EvKey KLeft [] -> K.Left
EvKey KRight [] -> K.Right
EvKey KHome [] -> K.Home
EvKey KPageUp [] -> K.PgUp
EvKey KEnd [] -> K.End
EvKey KPageDown [] -> K.PgDn
EvKey KBegin [] -> K.Begin
-- No KP_ keys in vty; see https://github.com/coreyoconnor/vty/issues/8
-- For now, movement keys are more important than hero selection:
EvKey (KASCII c) []
| c `elem` ['1'..'9'] -> K.KP c
| otherwise -> K.Char c
_ -> K.Unknown (show e)
nextEvent :: Session -> IO K.Key
nextEvent session =
do
e <- next_event session
return (keyTranslate e)
-- A hack to get bright colors via the bold attribute. Depending on terminal
-- settings this is needed or not and the characters really get bold or not.
-- HSCurses does this by default, but in Vty you have to request the hack.
hack :: Color.Color -> Attr -> Attr
hack c a = if Color.isBright c then with_style a bold else a
setAttr :: (Color.Color, Color.Color) -> Attr
setAttr (fg, bg) =
-- This optimization breaks display for white background terminals:
-- if (fg, bg) == Color.defaultAttr
-- then def_attr
-- else
hack fg $ hack bg $
def_attr { attr_fore_color = SetTo (aToc fg),
attr_back_color = SetTo (aToc bg) }
aToc :: Color.Color -> Color
aToc Color.Black = black
aToc Color.Red = red
aToc Color.Green = green
aToc Color.Yellow = yellow
aToc Color.Blue = blue
aToc Color.Magenta = magenta
aToc Color.Cyan = cyan
aToc Color.White = white
aToc Color.BrBlack = bright_black
aToc Color.BrRed = bright_red
aToc Color.BrGreen = bright_green
aToc Color.BrYellow = bright_yellow
aToc Color.BrBlue = bright_blue
aToc Color.BrMagenta = bright_magenta
aToc Color.BrCyan = bright_cyan
aToc Color.BrWhite = bright_white