Created
December 4, 2018 09:49
-
-
Save willbasky/561e43a37c89984f352d07b8ebd95213 to your computer and use it in GitHub Desktop.
tui
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module Tui where | |
import Brick.AttrMap | |
import Brick.Main | |
import Brick.Types | |
import Brick.Util | |
import Brick.Widgets.Border | |
import Brick.Widgets.Core | |
import Control.Monad | |
import Control.Monad.IO.Class | |
import Cursor.Simple.List.NonEmpty | |
import Data.List.NonEmpty (NonEmpty (..)) | |
import Graphics.Vty.Attributes | |
import Graphics.Vty.Input.Events | |
import System.Directory | |
import System.Exit | |
import Data.List (sort) | |
import qualified Data.List.NonEmpty as NE | |
tui :: IO () | |
tui = do | |
initialState <- buildInitialState | |
endState <- defaultMain tuiApp initialState | |
print endState | |
data TuiState = TuiState | |
{ tuiStatePaths :: NonEmptyCursor POC | |
} | |
deriving (Show, Eq) | |
data POC = File FilePath | Directory FilePath | |
deriving (Show, Eq, Ord) | |
type ResourceName = String | |
tuiApp :: App TuiState e ResourceName | |
tuiApp = | |
App | |
{ appDraw = drawTui | |
, appChooseCursor = showFirstCursor | |
, appHandleEvent = handleTuiEvent | |
, appStartEvent = pure | |
, appAttrMap = const $ attrMap mempty [("selected", fg red), ("file", fg green), ("directory", fg blue)] | |
} | |
buildInitialState :: IO TuiState | |
buildInitialState = do | |
here <- getCurrentDirectory | |
contents <- getDirectoryContents here | |
contents' <- forM contents $ \fp -> do | |
e <- doesFileExist fp | |
pure $ if e then File fp else Directory fp | |
case NE.nonEmpty contents' of | |
Nothing -> die "There are no contents." | |
Just ne -> pure TuiState {tuiStatePaths = makeNonEmptyCursor ne} | |
drawTui :: TuiState -> [Widget ResourceName] | |
drawTui ts = let nec = tuiStatePaths ts in | |
[ border | |
$ vBox | |
$ concat | |
[ map (drawPath False) $ reverse $ nonEmptyCursorPrev nec | |
, [drawPath True $ nonEmptyCursorCurrent nec] | |
, map (drawPath False) $ nonEmptyCursorNext nec | |
] | |
] | |
drawPath :: Bool -> POC -> Widget n | |
drawPath b poc = (if b then forceAttr "selected" else id) $ case poc of | |
File fp -> withAttr "file" $ str fp | |
Directory fp -> withAttr "directory" $ str fp | |
handleTuiEvent :: TuiState -> BrickEvent n e -> EventM n (Next TuiState) | |
handleTuiEvent s e = | |
case e of | |
VtyEvent vtye -> | |
case vtye of | |
EvKey (KChar 'q') [] -> halt s | |
EvKey KDown [] -> do | |
let nec = tuiStatePaths s | |
case nonEmptyCursorSelectNext nec of | |
Nothing -> continue s | |
Just nec' -> continue $ s {tuiStatePaths = nec'} | |
EvKey KUp [] -> do | |
let nec = tuiStatePaths s | |
case nonEmptyCursorSelectPrev nec of | |
Nothing -> continue s | |
Just nec' -> continue $ s {tuiStatePaths = nec'} | |
EvKey KEnter [] -> do | |
let fp = nonEmptyCursorCurrent $ tuiStatePaths s | |
case fp of | |
File _ -> continue s | |
Directory fp -> do | |
liftIO $ setCurrentDirectory fp | |
s' <- liftIO buildInitialState | |
continue s' | |
_ -> continue s | |
_ -> continue s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment