2015-05-09 09:09:40 +03:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2015-05-11 17:55:48 +03:00
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
2015-05-09 09:09:40 +03:00
|
|
|
module Main where
|
|
|
|
|
2015-05-11 17:55:48 +03:00
|
|
|
import Control.Lens
|
2015-06-25 22:58:32 +03:00
|
|
|
import Control.Monad (void)
|
2015-05-17 19:22:08 +03:00
|
|
|
import Data.Monoid
|
2015-05-26 04:07:20 +03:00
|
|
|
import Graphics.Vty hiding (translate)
|
2015-06-16 06:26:29 +03:00
|
|
|
import qualified Data.Text as T
|
2015-05-09 09:09:40 +03:00
|
|
|
|
2015-05-18 04:41:38 +03:00
|
|
|
import Brick.Main
|
2015-07-08 03:00:42 +03:00
|
|
|
import Brick.Types
|
2015-06-25 06:54:32 +03:00
|
|
|
import Brick.Widgets.Core
|
2015-06-25 06:58:34 +03:00
|
|
|
import Brick.Widgets.Center
|
|
|
|
import Brick.Widgets.Border
|
|
|
|
import Brick.Widgets.Border.Style
|
|
|
|
import Brick.Widgets.Edit
|
|
|
|
import Brick.Widgets.List
|
2015-05-18 04:41:38 +03:00
|
|
|
import Brick.Util
|
2015-06-15 02:14:35 +03:00
|
|
|
import Brick.AttrMap
|
2015-06-16 06:26:29 +03:00
|
|
|
import Brick.Markup
|
|
|
|
import Data.Text.Markup
|
2015-05-09 10:18:29 +03:00
|
|
|
|
2015-06-21 23:47:47 +03:00
|
|
|
styles :: [(T.Text, BorderStyle)]
|
2015-05-19 06:59:58 +03:00
|
|
|
styles =
|
2015-05-19 07:01:59 +03:00
|
|
|
[ ("ascii", ascii)
|
|
|
|
, ("uni", unicode)
|
|
|
|
, ("uni-bold", unicodeBold)
|
|
|
|
, ("uni-rounded", unicodeRounded)
|
2015-05-19 06:59:58 +03:00
|
|
|
]
|
|
|
|
|
2015-05-09 10:45:46 +03:00
|
|
|
data St =
|
2015-05-11 17:55:48 +03:00
|
|
|
St { _stEditor :: Editor
|
2015-05-19 00:14:13 +03:00
|
|
|
, _stList :: List Int
|
2015-05-19 06:59:58 +03:00
|
|
|
, _stBorderStyle :: Int
|
2015-05-19 07:58:16 +03:00
|
|
|
, _stTrans :: Location
|
2015-05-09 10:45:46 +03:00
|
|
|
}
|
2015-05-09 10:18:29 +03:00
|
|
|
|
2015-05-11 17:55:48 +03:00
|
|
|
makeLenses ''St
|
|
|
|
|
2015-06-15 02:14:35 +03:00
|
|
|
keywordAttr :: AttrName
|
|
|
|
keywordAttr = "app" <> "keyword"
|
|
|
|
|
2015-06-16 06:26:29 +03:00
|
|
|
editHighlightedKw1Attr :: AttrName
|
|
|
|
editHighlightedKw1Attr = editAttr <> "kw1"
|
|
|
|
|
|
|
|
editHighlightedKw2Attr :: AttrName
|
|
|
|
editHighlightedKw2Attr = editAttr <> "kw2"
|
|
|
|
|
2015-06-25 06:34:35 +03:00
|
|
|
kw :: Widget -> Widget
|
2015-06-29 08:08:54 +03:00
|
|
|
kw = withAttr keywordAttr
|
2015-05-19 07:18:51 +03:00
|
|
|
|
2015-06-16 06:26:29 +03:00
|
|
|
highlightWord :: (Eq a) => String -> a -> Markup a -> Markup a
|
|
|
|
highlightWord w att mk = assignAttrs 0 chunks mk
|
|
|
|
where
|
|
|
|
wordLen = length w
|
|
|
|
s = toText mk
|
|
|
|
chunks = T.splitOn (T.pack w) s
|
|
|
|
|
|
|
|
assignAttrs _ [] m = m
|
|
|
|
assignAttrs _ [_] m = m
|
|
|
|
assignAttrs pos (t:ts) m = markupSet (pos + T.length t, wordLen) att $ assignAttrs (pos + T.length t + wordLen) ts m
|
|
|
|
|
|
|
|
applyMarkup :: String -> Markup AttrName
|
|
|
|
applyMarkup s =
|
|
|
|
highlightWord "foo" editHighlightedKw1Attr $
|
|
|
|
highlightWord "bar" editHighlightedKw2Attr $
|
|
|
|
(T.pack s) @? editAttr
|
|
|
|
|
2015-06-25 06:34:35 +03:00
|
|
|
drawEditString :: String -> Widget
|
2015-06-16 06:26:29 +03:00
|
|
|
drawEditString = markup . applyMarkup
|
|
|
|
|
2015-06-25 06:34:35 +03:00
|
|
|
drawUI :: St -> [Widget]
|
2015-06-08 05:40:49 +03:00
|
|
|
drawUI st = [withBorderStyle bs a]
|
2015-05-10 00:28:37 +03:00
|
|
|
where
|
2015-05-19 07:07:55 +03:00
|
|
|
(bsName, bs) = styles !! (st^.stBorderStyle)
|
2015-06-21 23:56:27 +03:00
|
|
|
box = borderWithLabel (txt bsName) $
|
2015-06-08 04:37:36 +03:00
|
|
|
(hLimit 25 (
|
2015-06-28 21:02:18 +03:00
|
|
|
(renderEditor $ st^.stEditor)
|
2015-06-08 06:51:56 +03:00
|
|
|
<=> hBorder
|
|
|
|
<=> (vLimit 10 $ renderList (st^.stList))
|
2015-06-08 04:37:36 +03:00
|
|
|
))
|
2015-06-08 06:37:32 +03:00
|
|
|
a = translateBy (st^.stTrans) $ vCenter $
|
2015-06-08 04:37:36 +03:00
|
|
|
(hCenter box)
|
2015-06-28 01:25:19 +03:00
|
|
|
<=> " "
|
2015-06-08 06:37:32 +03:00
|
|
|
<=> (hCenter (kw "Enter" <+> " adds a list item"))
|
|
|
|
<=> (hCenter (kw "+" <+> " changes border styles"))
|
|
|
|
<=> (hCenter (kw "Arrow keys" <+> " navigates the list"))
|
|
|
|
<=> (hCenter (kw "Ctrl-Arrow keys" <+> " move the interface"))
|
2015-05-09 09:09:40 +03:00
|
|
|
|
2015-07-01 23:05:28 +03:00
|
|
|
appEvent :: St -> Event -> EventM (Next St)
|
|
|
|
appEvent st e =
|
2015-05-09 09:09:40 +03:00
|
|
|
case e of
|
2015-05-19 07:09:59 +03:00
|
|
|
EvKey (KChar '+') [] ->
|
2015-06-25 22:58:32 +03:00
|
|
|
continue $ st & stBorderStyle %~ ((`mod` (length styles)) . (+ 1))
|
2015-05-19 06:59:58 +03:00
|
|
|
|
2015-06-25 22:58:32 +03:00
|
|
|
EvKey KEsc [] -> halt st
|
2015-05-18 18:38:30 +03:00
|
|
|
|
2015-06-28 21:57:38 +03:00
|
|
|
EvKey (KChar 'r') [MCtrl] -> suspendAndResume $ do
|
2015-06-25 22:58:32 +03:00
|
|
|
putStrLn "Suspended. Press any key..."
|
|
|
|
void getChar
|
|
|
|
return st
|
|
|
|
|
2015-06-28 21:35:28 +03:00
|
|
|
EvKey KUp [MCtrl] -> continue $ st & stTrans.row %~ subtract 1
|
|
|
|
EvKey KDown [MCtrl] -> continue $ st & stTrans.row %~ (+ 1)
|
|
|
|
|
|
|
|
EvKey KLeft [MCtrl] -> continue $ st & stTrans.column %~ (subtract 1)
|
|
|
|
EvKey KRight [MCtrl] -> continue $ st & stTrans.column %~ (+ 1)
|
2015-05-19 07:58:16 +03:00
|
|
|
|
2015-05-17 19:53:00 +03:00
|
|
|
EvKey KEnter [] ->
|
2015-06-28 21:57:38 +03:00
|
|
|
let el = length $ st^.stList.listElementsL
|
2015-06-25 22:58:32 +03:00
|
|
|
in continue $ st & stList %~ (listMoveBy 1 . listInsert el el)
|
2015-05-18 18:38:30 +03:00
|
|
|
|
2015-06-25 22:58:32 +03:00
|
|
|
ev -> continue $ st & stEditor %~ (handleEvent ev)
|
|
|
|
& stList %~ (handleEvent ev)
|
2015-05-09 10:45:46 +03:00
|
|
|
|
|
|
|
initialState :: St
|
|
|
|
initialState =
|
2015-06-28 21:02:18 +03:00
|
|
|
St { _stEditor = editor (Name "edit") drawEditString ""
|
2015-06-08 04:52:04 +03:00
|
|
|
, _stList = list (Name "list") listDrawElem []
|
2015-05-19 06:59:58 +03:00
|
|
|
, _stBorderStyle = 0
|
2015-05-19 07:58:16 +03:00
|
|
|
, _stTrans = Location (0, 0)
|
2015-05-09 19:14:56 +03:00
|
|
|
}
|
|
|
|
|
2015-06-25 06:34:35 +03:00
|
|
|
listDrawElem :: Bool -> Int -> Widget
|
2015-05-17 19:44:18 +03:00
|
|
|
listDrawElem sel i =
|
2015-06-15 02:14:35 +03:00
|
|
|
let selStr s = if sel then "<" <> s <> ">" else s
|
2015-07-08 03:05:24 +03:00
|
|
|
in hCenterWith (Just ' ') $ vBox $ (flip map) [1..i+1] $ \j ->
|
2015-06-28 02:34:45 +03:00
|
|
|
str $ "Item " <> (selStr $ show i) <> " L" <> show j
|
2015-06-15 02:14:35 +03:00
|
|
|
|
|
|
|
theAttrMap :: AttrMap
|
|
|
|
theAttrMap = attrMap defAttr
|
2015-06-16 06:26:29 +03:00
|
|
|
[ (listSelectedAttr, white `on` blue)
|
|
|
|
, (editAttr, white `on` blue)
|
|
|
|
, (editHighlightedKw1Attr, fg magenta)
|
|
|
|
, (editHighlightedKw2Attr, fg cyan)
|
|
|
|
, (keywordAttr, fg blue)
|
|
|
|
, (borderAttr, fg blue)
|
|
|
|
, (hBorderLabelAttr, fg cyan)
|
2015-06-15 02:14:35 +03:00
|
|
|
]
|
2015-05-17 19:22:08 +03:00
|
|
|
|
2015-05-11 01:51:08 +03:00
|
|
|
theApp :: App St Event
|
2015-05-11 00:56:58 +03:00
|
|
|
theApp =
|
2015-06-26 09:22:22 +03:00
|
|
|
App { appDraw = drawUI
|
2015-05-11 01:42:59 +03:00
|
|
|
, appChooseCursor = showFirstCursor
|
2015-07-01 05:15:29 +03:00
|
|
|
, appStartEvent = return
|
2015-05-17 19:41:17 +03:00
|
|
|
, appHandleEvent = appEvent
|
2015-06-15 02:14:35 +03:00
|
|
|
, appAttrMap = const theAttrMap
|
2015-06-26 09:42:52 +03:00
|
|
|
, appMakeVtyEvent = id
|
2015-05-09 19:24:59 +03:00
|
|
|
}
|
|
|
|
|
2015-05-09 09:09:40 +03:00
|
|
|
main :: IO ()
|
2015-06-25 07:26:44 +03:00
|
|
|
main = do
|
|
|
|
st <- defaultMain theApp initialState
|
2015-06-28 21:57:38 +03:00
|
|
|
putStrLn $ "You entered: " <> (st^.stEditor.editContentsL)
|