diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-10-03 15:48:49 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-10-03 15:55:29 +0530 |
| commit | a3d5295ee745ab851c28d0a53147cbad65a7805f (patch) | |
| tree | f1771baa2748700e3045e00344d53a5782bd48c0 | |
| parent | dd048c390f8762e7701572c4e319f22df06aeb75 (diff) | |
| download | daffm-a3d5295ee745ab851c28d0a53147cbad65a7805f.tar.gz daffm-a3d5295ee745ab851c28d0a53147cbad65a7805f.zip | |
Refactor event module with actions
| -rw-r--r-- | daffm.cabal | 2 | ||||
| -rw-r--r-- | lib/Daffm/Action/Cmdline.hs | 65 | ||||
| -rw-r--r-- | lib/Daffm/Action/Core.hs | 45 | ||||
| -rw-r--r-- | lib/Daffm/Event.hs | 98 | ||||
| -rw-r--r-- | lib/Daffm/View.hs | 18 |
5 files changed, 127 insertions, 101 deletions
diff --git a/daffm.cabal b/daffm.cabal index 781e01a..c125b10 100644 --- a/daffm.cabal +++ b/daffm.cabal @@ -63,6 +63,8 @@ library lib-daffm Daffm.Attrs Daffm.Event Daffm.State + Daffm.Action.Core + Daffm.Action.Cmdline test-suite specs import: common-config, warnings diff --git a/lib/Daffm/Action/Cmdline.hs b/lib/Daffm/Action/Cmdline.hs new file mode 100644 index 0000000..bf1f3f1 --- /dev/null +++ b/lib/Daffm/Action/Cmdline.hs @@ -0,0 +1,65 @@ +module Daffm.Action.Cmdline where + +import Brick (suspendAndResume') +import qualified Brick.Widgets.Edit as Editor +import qualified Brick.Widgets.List as L +import Control.Monad (void) +import Control.Monad.State (get, gets, modify) +import Daffm.Action.Core (reloadDir) +import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FocusTarget (..)) +import Data.Char (isSpace) +import Data.List (dropWhileEnd) +import qualified Data.Text as Text +import qualified Data.Text.Zipper as Z +import qualified Data.Text.Zipper as Zipper +import System.Process (callCommand) + +leaveCmdline :: AppEvent () +leaveCmdline = clearCmdline >> modify (\st -> st {stateFocusTarget = FocusMain}) + +enterCmdline :: AppEvent () +enterCmdline = modify (\st -> st {stateFocusTarget = FocusCmdline}) + +setCmdlineText :: String -> AppEvent () +setCmdlineText text = + applyCmdlineEdit (const $ Z.stringZipper [text] (Just 1)) + +clearCmdline :: AppEvent () +clearCmdline = applyCmdlineEdit Z.clearZipper + +cmdSubstitutions :: Text.Text -> AppEvent Text.Text +cmdSubstitutions cmd = do + (AppState {stateFiles, stateCwd}) <- get + let file = maybe "" (filePath . snd) . L.listSelectedElement $ stateFiles + -- TODO: Escaping % + let subst = + Text.replace "%" (Text.pack file) + . Text.replace "%d" (Text.pack stateCwd) + pure . subst $ cmd + +runCmdline :: AppEvent () +runCmdline = do + cmd <- gets (trimCmd . Editor.getEditContents . stateCmdlineEditor) + evaluateCommand cmd + leaveCmdline + where + trimCmd = dropWhile isSpace . dropWhileEnd isSpace . unlines + +evaluateCommand :: String -> AppEvent () +evaluateCommand ('!' : '!' : cmd) = do + cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd) + suspendAndResume' $ do + callCommand cmd' + putStrLn "Press any key to continue" >> void getChar + reloadDir +evaluateCommand ('!' : cmd) = do + cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd) + suspendAndResume' $ callCommand cmd' + reloadDir +evaluateCommand _cmd = pure () + +applyCmdlineEdit :: (Zipper.TextZipper String -> Zipper.TextZipper String) -> AppEvent () +applyCmdlineEdit zipper = do + editor <- gets stateCmdlineEditor + let editor' = Editor.applyEdit zipper editor + modify (\s -> s {stateCmdlineEditor = editor'}) diff --git a/lib/Daffm/Action/Core.hs b/lib/Daffm/Action/Core.hs new file mode 100644 index 0000000..48792c4 --- /dev/null +++ b/lib/Daffm/Action/Core.hs @@ -0,0 +1,45 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} + +{-# HLINT ignore "Use for_" #-} +module Daffm.Action.Core where + +import Brick (suspendAndResume') +import qualified Brick.Widgets.List as L +import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, put) +import Daffm.State (loadDirInAppState) +import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FileType (..)) +import Data.Vector ((!?)) +import System.FilePath (takeDirectory) +import System.Process (callProcess) + +modifyM :: (MonadState s m) => (s -> m s) -> m () +modifyM f = get >>= f >>= put + +reloadDir :: AppEvent () +reloadDir = do + AppState {stateCwd, stateParentDir} <- get + modifyM (liftIO . loadDirInAppState stateCwd stateParentDir) + +goBackToParentDir :: AppEvent () +goBackToParentDir = do + dir <- gets stateParentDir + modifyM (liftIO . loadDirInAppState dir (takeDirectory dir)) + +openSelectedFile :: AppEvent () +openSelectedFile = do + appState <- get + let indexM = L.listSelected $ stateFiles appState + let files = L.listElements $ stateFiles appState + case indexM >>= (files !?) of + Just file -> openFile appState file + Nothing -> pure () + pure () + +openFile :: AppState -> FileInfo -> AppEvent () +openFile appState (FileInfo {filePath, fileType = Directory}) = do + modifyM (liftIO . loadDirInAppState filePath (stateCwd appState)) +openFile _appState (FileInfo {filePath, fileType}) = do + suspendAndResume' $ do + putStrLn $ "Opening " <> show fileType <> ": " <> filePath + callProcess "nvim" [filePath] + pure () diff --git a/lib/Daffm/Event.hs b/lib/Daffm/Event.hs index 2bcebab..8eaf960 100644 --- a/lib/Daffm/Event.hs +++ b/lib/Daffm/Event.hs @@ -1,26 +1,15 @@ 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 (void) -import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, modify, put) -import Daffm.State (cacheDirPosition, loadDirInAppState) -import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FileType (..), FocusTarget (..)) -import Data.Char (isSpace) -import Data.List (dropWhileEnd) -import qualified Data.Text as Text -import qualified Data.Text.Zipper as Z -import qualified Data.Text.Zipper as Zipper -import Data.Vector ((!?)) +import Control.Monad.State (gets, modify) +import Daffm.Action.Cmdline (enterCmdline, evaluateCommand, leaveCmdline, runCmdline, setCmdlineText) +import Daffm.Action.Core (goBackToParentDir, openSelectedFile, reloadDir) +import Daffm.State (cacheDirPosition) +import Daffm.Types (AppEvent, AppState (..), FocusTarget (..)) import qualified Graphics.Vty as V -import System.FilePath (takeDirectory) -import System.Process (callCommand, callProcess) - -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 @@ -48,80 +37,3 @@ appEvent brickevent@(T.VtyEvent event) = do modify (\appState -> appState {stateCmdlineEditor = newEditor}) modify cacheDirPosition appEvent _ = pure () - -leaveCmdline :: AppEvent () -leaveCmdline = clearCmdline >> modify (\st -> st {stateFocusTarget = FocusMain}) - -enterCmdline :: AppEvent () -enterCmdline = modify (\st -> st {stateFocusTarget = FocusCmdline}) - -setCmdlineText :: String -> AppEvent () -setCmdlineText text = - applyCmdlineEdit (const $ Z.stringZipper [text] (Just 1)) - -clearCmdline :: AppEvent () -clearCmdline = applyCmdlineEdit Z.clearZipper - -cmdSubstitutions :: Text.Text -> AppEvent Text.Text -cmdSubstitutions cmd = do - (AppState {stateFiles, stateCwd}) <- get - let file = maybe "" (filePath . snd) . L.listSelectedElement $ stateFiles - -- TODO: Escaping % - let subst = - Text.replace "%" (Text.pack file) - . Text.replace "%d" (Text.pack stateCwd) - pure . subst $ cmd - -runCmdline :: AppEvent () -runCmdline = do - cmd <- gets (trimCmd . Editor.getEditContents . stateCmdlineEditor) - evaluateCommand cmd - leaveCmdline - where - trimCmd = dropWhile isSpace . dropWhileEnd isSpace . unlines - -evaluateCommand :: String -> AppEvent () -evaluateCommand ('!' : '!' : cmd) = do - cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd) - suspendAndResume' $ do - callCommand cmd' - putStrLn "Press any key to continue" - void getChar - reloadDir -evaluateCommand ('!' : cmd) = do - cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd) - suspendAndResume' $ callCommand cmd' - reloadDir -evaluateCommand _cmd = pure () - -reloadDir :: AppEvent () -reloadDir = do - AppState {stateParentDir, stateCwd} <- get - modifyM (liftIO . loadDirInAppState stateCwd stateParentDir) - -applyCmdlineEdit :: (Zipper.TextZipper String -> Zipper.TextZipper String) -> AppEvent () -applyCmdlineEdit zipper = do - editor <- gets stateCmdlineEditor - let editor' = Editor.applyEdit zipper editor - modify (\s -> s {stateCmdlineEditor = editor'}) - -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)) diff --git a/lib/Daffm/View.hs b/lib/Daffm/View.hs index 443d017..906fe26 100644 --- a/lib/Daffm/View.hs +++ b/lib/Daffm/View.hs @@ -38,14 +38,16 @@ fileItemView sel fileInfo@(FileInfo {fileSize, fileType, fileMode}) = fileSizeView = str . prettyFileSize . fromIntegral fileTypeView = str . showFileType fileModeView = str . showFileMode - showFileType Directory = "dir" - showFileType SymbolicLink = "link" - showFileType UnixSocket = "sock" - showFileType NamedPipe = "pipe" - showFileType CharacterDevice = "cdev" - showFileType BlockDevice = "bdev" - showFileType RegularFile = "file" - showFileType UnknownFileType = "?" + +showFileType :: FileType -> String +showFileType Directory = "dir" +showFileType SymbolicLink = "link" +showFileType UnixSocket = "sock" +showFileType NamedPipe = "pipe" +showFileType CharacterDevice = "cdev" +showFileType BlockDevice = "bdev" +showFileType RegularFile = "file" +showFileType UnknownFileType = "?" showFileMode :: FileMode -> String showFileMode mode = permchars |
