{-# LANGUAGE OverloadedStrings #-} module Main where import Control.Monad (void) import Data.Maybe (fromJust) import Data.Monoid ((<>)) import qualified Data.Text as T import qualified Graphics.Vty as V import qualified Skylighting.Core as S import System.Environment (getArgs, getProgName) import System.Exit (exitFailure) import Brick import Brick.Widgets.Center (hCenter) import Brick.Widgets.Border (borderWithLabel, hBorder) import Brick.Widgets.Skylighting (highlight, attrMappingsForStyle) haskellProgram :: T.Text haskellProgram = T.unlines [ "module Main where" , "" , "data FooBar = Foo | Bar deriving (Eq, Read, Show)" , "" , "main :: IO ()" , "main = do" , " let f x = x * x" , " return ()" ] pythonProgram :: T.Text pythonProgram = T.unlines [ "import os.path" , "" , "if __name__ == \"__main__\":" , " print('hello, world!')" ] bashProgram :: T.Text bashProgram = T.unlines [ "FOO=1" , "" , "function print_foo {" , " echo $FOO" , "}" , "" , "print_foo" ] ui :: [(T.Text, S.Syntax)] -> Int -> [Widget ()] ui programs styleIndex = [vBox $ help : hBorder : header : progs] where help = hCenter $ txt "q/esc:quit up/down:change theme" header = hCenter $ txt $ "Theme: " <> (fst $ styles !! styleIndex) progs = showProg <$> programs showProg (progSrc, syntax) = (borderWithLabel (txt $ S.sName syntax) $ highlight syntax progSrc) styles :: [(T.Text, S.Style)] styles = [ ("espresso", S.espresso) , ("kate", S.kate) , ("breezeDark", S.breezeDark) , ("pygments", S.pygments) , ("tango", S.tango) , ("haddock", S.haddock) , ("monochrome", S.monochrome) , ("zenburn", S.zenburn) ] handleEvent :: Int -> BrickEvent () e -> EventM () (Next Int) handleEvent i (VtyEvent (V.EvKey V.KUp [])) = continue $ (i + 1) `mod` length styles handleEvent i (VtyEvent (V.EvKey V.KDown [])) = continue $ (i - 1) `mod` length styles handleEvent i (VtyEvent (V.EvKey V.KEsc [])) = halt i handleEvent i (VtyEvent (V.EvKey (V.KChar 'q') [])) = halt i handleEvent i _ = continue i app :: [(T.Text, S.Syntax)] -> App Int e () app programs = App { appDraw = ui programs , appAttrMap = \i -> attrMap V.defAttr $ attrMappingsForStyle $ snd $ styles !! i , appHandleEvent = handleEvent , appChooseCursor = neverShowCursor , appStartEvent = return } usage :: IO () usage = do pn <- getProgName putStrLn $ pn <> " " main :: IO () main = do args <- getArgs path <- case args of [p] -> return p _ -> usage >> exitFailure syntaxMap <- do result <- S.loadSyntaxesFromDir path case result of Left e -> do putStrLn $ "Failed to load syntax map: " <> e exitFailure Right m -> return m let syntax = fromJust . S.syntaxByName syntaxMap programs = [ (haskellProgram, syntax "haskell") , (pythonProgram, syntax "python") , (bashProgram, syntax "bash") ] void $ defaultMain (app programs) 0