{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} module Main where import qualified Control.Exception as E #if !(MIN_VERSION_base(4,11,0)) import Data.Monoid #endif import qualified Graphics.Vty as V import Control.Monad.State (get) import qualified Data.Text as Text import qualified Brick.Main as M import qualified Brick.Widgets.List as L import Brick.AttrMap (AttrName, attrName) import Brick.Types ( Widget , BrickEvent(..) ) import Brick.Widgets.Center ( center , hCenter ) import Brick.Widgets.Border ( borderWithLabel ) import Brick.Widgets.Core ( vBox, (<=>), padTop , hLimit, vLimit, txt , withDefAttr, emptyWidget , Padding(..) ) import qualified Brick.Widgets.FileBrowser as FB import qualified Brick.AttrMap as A import Brick.Util (on, fg) import qualified Brick.Types as T data Name = FileBrowser1 deriving (Eq, Show, Ord) drawUI :: FB.FileBrowser Name -> [Widget Name] drawUI b = [center $ ui <=> help] where ui = hCenter $ vLimit 15 $ hLimit 50 $ borderWithLabel (txt "Choose a file") $ FB.renderFileBrowser True b help = padTop (Pad 1) $ vBox [ case FB.fileBrowserException b of Nothing -> emptyWidget Just e -> hCenter $ withDefAttr errorAttr $ txt $ Text.pack $ E.displayException e , hCenter $ txt "Up/Down: select" , hCenter $ txt "/: search, Ctrl-C or Esc: cancel search" , hCenter $ txt "Enter: change directory or select file" , hCenter $ txt "Esc: quit" ] appEvent :: BrickEvent Name e -> T.EventM Name (FB.FileBrowser Name) () appEvent (VtyEvent ev) = do b <- get case ev of V.EvKey V.KEsc [] | not (FB.fileBrowserIsSearching b) -> M.halt _ -> do FB.handleFileBrowserEvent ev -- If the browser has a selected file after handling the -- event (because the user pressed Enter), shut down. case ev of V.EvKey V.KEnter [] -> do b' <- get case FB.fileBrowserSelection b' of [] -> return () _ -> M.halt _ -> return () appEvent _ = return () errorAttr :: AttrName errorAttr = attrName "error" theMap :: A.AttrMap theMap = A.attrMap V.defAttr [ (L.listSelectedFocusedAttr, V.black `on` V.yellow) , (FB.fileBrowserCurrentDirectoryAttr, V.white `on` V.blue) , (FB.fileBrowserSelectionInfoAttr, V.white `on` V.blue) , (FB.fileBrowserDirectoryAttr, fg V.blue) , (FB.fileBrowserBlockDeviceAttr, fg V.magenta) , (FB.fileBrowserCharacterDeviceAttr, fg V.green) , (FB.fileBrowserNamedPipeAttr, fg V.yellow) , (FB.fileBrowserSymbolicLinkAttr, fg V.cyan) , (FB.fileBrowserUnixSocketAttr, fg V.red) , (FB.fileBrowserSelectedAttr, V.white `on` V.magenta) , (errorAttr, fg V.red) ] theApp :: M.App (FB.FileBrowser Name) e Name theApp = M.App { M.appDraw = drawUI , M.appChooseCursor = M.showFirstCursor , M.appHandleEvent = appEvent , M.appStartEvent = return () , M.appAttrMap = const theMap } main :: IO () main = do b <- M.defaultMain theApp =<< FB.newFileBrowser FB.selectNonDirectories FileBrowser1 Nothing putStrLn $ "Selected entry: " <> show (FB.fileBrowserSelection b)