1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
module Daffm.Event where
import Brick (suspendAndResume')
import qualified Brick.Main as M
import qualified Brick.Types as T
import qualified Brick.Widgets.Edit as Editor
import qualified Brick.Widgets.List as L
import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, modify, put)
import Daffm.State (cacheDirPosition, loadDirInAppState)
import Daffm.Types (AppState (..), FileInfo (..), FileType (..), FocusTarget (FocusCmdline, FocusMain))
import Data.Char (isSpace)
import Data.List (dropWhileEnd)
import Data.Maybe (fromMaybe)
import qualified Data.Text as Text
import qualified Data.Text.Zipper as Z
import Data.Vector ((!?))
import qualified Graphics.Vty as V
import System.FilePath (takeDirectory)
import System.Process (callCommand, callProcess)
type AppEvent = T.EventM FocusTarget AppState
modifyM :: (MonadState s m) => (s -> m s) -> m ()
modifyM f = get >>= f >>= put
appEvent :: T.BrickEvent FocusTarget e -> AppEvent ()
appEvent brickevent@(T.VtyEvent event) = do
focusTarget <- gets stateFocusTarget
case (focusTarget, event) of
(FocusMain, V.EvKey (V.KChar 'l') []) -> openSelectedFile
(FocusMain, V.EvKey (V.KChar 'h') []) -> goBackToParentDir
(FocusMain, V.EvKey V.KEnter []) -> openSelectedFile
(FocusMain, V.EvKey V.KBS []) -> goBackToParentDir
(FocusMain, V.EvKey (V.KChar ':') []) -> modify (\st -> st {stateFocusTarget = FocusCmdline})
(FocusMain, V.EvKey (V.KChar 'q') []) -> M.halt
(FocusMain, V.EvKey (V.KChar 'r') [V.MCtrl]) -> reloadDir
(FocusMain, _) -> do
files <- gets stateFiles
newFiles <- T.nestEventM' files (L.handleListEventVi L.handleListEvent event)
modify (\appState -> appState {stateFiles = newFiles})
(FocusCmdline, V.EvKey V.KEsc []) -> modify (\st -> st {stateFocusTarget = FocusMain})
(FocusCmdline, V.EvKey V.KEnter []) -> do
gets (trimCmd . Editor.getEditContents . stateCmdlineEditor) >>= evaluateCommand
clearEditor
modify (\st -> st {stateFocusTarget = FocusMain})
where
trimCmd = dropWhile isSpace . dropWhileEnd isSpace . unlines
(FocusCmdline, _) -> do
editor <- gets stateCmdlineEditor
newEditor <- T.nestEventM' editor (Editor.handleEditorEvent brickevent)
modify (\appState -> appState {stateCmdlineEditor = newEditor})
modify cacheDirPosition
appEvent _ = pure ()
cmdSubstitutions :: Text.Text -> AppEvent Text.Text
cmdSubstitutions cmd = do
file <- gets (maybe "" (filePath . snd) . L.listSelectedElement . stateFiles)
pure $ Text.replace "%" (Text.pack file) cmd
evaluateCommand :: String -> AppEvent ()
evaluateCommand ('!' : cmd) = do
cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd)
suspendAndResume' $ callCommand cmd'
reloadDir
evaluateCommand cmd = pure ()
clearEditor :: AppEvent ()
clearEditor = do
editor <- gets stateCmdlineEditor
let editor' = Editor.applyEdit Z.clearZipper editor
modify (\s -> s {stateCmdlineEditor = editor'})
reloadDir :: AppEvent ()
reloadDir = do
AppState {stateParentDir, stateCwd} <- get
modifyM (liftIO . loadDirInAppState stateCwd stateParentDir)
openSelectedFile :: AppEvent ()
openSelectedFile = do
AppState {stateFiles, stateCwd} <- get
let indexM = L.listSelected stateFiles
let files = L.listElements stateFiles
case indexM >>= (files !?) of
Just (FileInfo {filePath, fileType = Directory}) ->
modifyM (liftIO . loadDirInAppState filePath stateCwd)
Just (FileInfo {filePath, fileType}) -> do
suspendAndResume' $ do
putStrLn $ "Opening " <> show fileType <> ": " <> filePath
callProcess "nvim" [filePath]
pure ()
Nothing -> pure ()
pure ()
goBackToParentDir :: AppEvent ()
goBackToParentDir = do
dir <- gets stateParentDir
modifyM (liftIO . loadDirInAppState dir (takeDirectory dir))
|