diff options
Diffstat (limited to 'lib/Daffm/Action')
| -rw-r--r-- | lib/Daffm/Action/Cmdline.hs | 65 | ||||
| -rw-r--r-- | lib/Daffm/Action/Core.hs | 45 |
2 files changed, 110 insertions, 0 deletions
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 () |
