aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/Daffm.hs4
-rw-r--r--lib/Daffm/Action/Cmdline.hs37
-rw-r--r--lib/Daffm/Action/Core.hs22
-rw-r--r--lib/Daffm/State.hs12
4 files changed, 48 insertions, 27 deletions
diff --git a/lib/Daffm.hs b/lib/Daffm.hs
index ffae42b..afdba11 100644
--- a/lib/Daffm.hs
+++ b/lib/Daffm.hs
@@ -1,9 +1,9 @@
-module Daffm (app, loadDirInAppState, mkEmptyAppState) where
+module Daffm (app, loadDirToState, mkEmptyAppState) where
import qualified Brick.Main as M
import Daffm.Attrs (appAttrMap)
import Daffm.Event (appEvent)
-import Daffm.State (loadDirInAppState, mkEmptyAppState)
+import Daffm.State (loadDirToState, mkEmptyAppState)
import Daffm.Types (AppState (..), FocusTarget)
import Daffm.View (appView)
diff --git a/lib/Daffm/Action/Cmdline.hs b/lib/Daffm/Action/Cmdline.hs
index bf1f3f1..64977aa 100644
--- a/lib/Daffm/Action/Cmdline.hs
+++ b/lib/Daffm/Action/Cmdline.hs
@@ -3,16 +3,17 @@ 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 (unless, 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.Set as Set
import qualified Data.Text as Text
import qualified Data.Text.Zipper as Z
import qualified Data.Text.Zipper as Zipper
-import System.Process (callCommand)
+import System.Process (callCommand, callProcess)
leaveCmdline :: AppEvent ()
leaveCmdline = clearCmdline >> modify (\st -> st {stateFocusTarget = FocusMain})
@@ -27,16 +28,6 @@ setCmdlineText text =
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)
@@ -56,8 +47,30 @@ evaluateCommand ('!' : cmd) = do
cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd)
suspendAndResume' $ callCommand cmd'
reloadDir
+evaluateCommand "delete" = do
+ (AppState {stateFileSelections, stateFiles}) <- get
+ let files =
+ if Set.null stateFileSelections
+ then maybe [] ((: []) . filePath . snd) $ L.listSelectedElement stateFiles
+ else Set.elems stateFileSelections
+ unless (null files) $ do
+ suspendAndResume' $ callProcess "rm" ("-rfi" : files)
+ reloadDir
evaluateCommand _cmd = pure ()
+cmdSubstitutions :: Text.Text -> AppEvent Text.Text
+cmdSubstitutions cmd = do
+ (AppState {stateFiles, stateCwd, stateFileSelections}) <- get
+ let file = maybe "" (filePath . snd) . L.listSelectedElement $ stateFiles
+ let escape = (\s -> "'" <> s <> "'") . Text.replace "'" "\\'"
+ let selections = Text.unwords . map (escape . Text.pack) $ Set.elems stateFileSelections
+ -- TODO: Escaping %
+ let subst =
+ Text.replace "%" (Text.pack file)
+ . Text.replace "%d" (Text.pack stateCwd)
+ . Text.replace "%s" selections
+ pure . subst $ cmd
+
applyCmdlineEdit :: (Zipper.TextZipper String -> Zipper.TextZipper String) -> AppEvent ()
applyCmdlineEdit zipper = do
editor <- gets stateCmdlineEditor
diff --git a/lib/Daffm/Action/Core.hs b/lib/Daffm/Action/Core.hs
index 9fed688..d18bda9 100644
--- a/lib/Daffm/Action/Core.hs
+++ b/lib/Daffm/Action/Core.hs
@@ -1,12 +1,13 @@
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Use for_" #-}
+{-# HLINT ignore "Use <=<" #-}
module Daffm.Action.Core where
import Brick (suspendAndResume')
import qualified Brick.Widgets.List as L
import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, modify, put)
-import Daffm.State (loadDirInAppState, toggleFileSelection)
+import Daffm.State
import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FileType (..))
import qualified Data.Set as Set
import System.Directory (getHomeDirectory)
@@ -16,32 +17,34 @@ import System.Process (callProcess)
modifyM :: (MonadState s m) => (s -> m s) -> m ()
modifyM f = get >>= f >>= put
+loadDir :: FilePath -> FilePath -> AppEvent ()
+loadDir dir parentDir = do
+ modifyM (liftIO . (>>= filterInvalidSelections) . loadDirToState dir parentDir)
+
reloadDir :: AppEvent ()
reloadDir = do
AppState {stateCwd, stateParentDir} <- get
- modifyM (liftIO . loadDirInAppState stateCwd stateParentDir)
+ loadDir stateCwd stateParentDir
goBackToParentDir :: AppEvent ()
goBackToParentDir = do
dir <- gets stateParentDir
- modifyM (liftIO . loadDirInAppState dir (takeDirectory dir))
+ loadDir dir (takeDirectory dir)
goHome :: AppEvent ()
goHome = do
dir <- liftIO getHomeDirectory
- modifyM (liftIO . loadDirInAppState dir (takeDirectory dir))
+ loadDir dir (takeDirectory dir)
openSelectedFile :: AppEvent ()
openSelectedFile = do
- fileM <- currentFile
- case fileM of
+ currentFile >>= \case
Just file -> openFile file
Nothing -> pure ()
openFile :: FileInfo -> AppEvent ()
openFile (FileInfo {filePath, fileType = Directory}) = do
- (AppState {stateCwd}) <- get
- modifyM (liftIO . loadDirInAppState filePath stateCwd)
+ gets stateCwd >>= loadDir filePath
openFile (FileInfo {filePath, fileType}) = do
suspendAndResume' $ do
putStrLn $ "Opening " <> show fileType <> ": " <> filePath
@@ -53,8 +56,7 @@ currentFile = do
toggleCurrentFileSelection :: AppEvent ()
toggleCurrentFileSelection = do
- fileM <- currentFile
- case fileM of
+ currentFile >>= \case
Just file -> modify $ toggleFileSelection (filePath file)
Nothing -> pure ()
moveCurrent 1
diff --git a/lib/Daffm/State.hs b/lib/Daffm/State.hs
index ead5209..d35dccf 100644
--- a/lib/Daffm/State.hs
+++ b/lib/Daffm/State.hs
@@ -3,7 +3,7 @@ module Daffm.State where
import qualified Brick.Widgets.Edit as Editor
import qualified Brick.Widgets.List as L
import Control.Applicative ((<|>))
-import Control.Monad (forM)
+import Control.Monad (filterM, forM)
import Daffm.Types (AppState (..), FileInfo (..), FileType (..), FocusTarget (..))
import Data.Char (toLower)
import Data.List (findIndex, sortBy)
@@ -13,6 +13,7 @@ import qualified Data.Set as Set
import qualified Data.Text.Zipper.Generic as Zipper
import qualified Data.Vector as Vec
import System.Directory (listDirectory, makeAbsolute, setCurrentDirectory)
+import System.PosixCompat (fileExist)
import qualified System.PosixCompat as Posix
mkEditor :: (Zipper.GenericTextZipper a) => a -> Editor.Editor a FocusTarget
@@ -37,8 +38,8 @@ toggleSetItem val set =
toggleFileSelection :: FilePath -> AppState -> AppState
toggleFileSelection path st = st {stateFileSelections = toggleSetItem path $ stateFileSelections st}
-loadDirInAppState :: FilePath -> FilePath -> AppState -> IO AppState
-loadDirInAppState dir parentDir appState@(AppState {stateCwd, stateListPositionCache}) = do
+loadDirToState :: FilePath -> FilePath -> AppState -> IO AppState
+loadDirToState dir parentDir appState@(AppState {stateCwd, stateListPositionCache}) = do
setCurrentDirectory dir
files <- listFilesInDir dir
let prevDirPosM = findIndex ((== stateCwd) . filePath) files
@@ -97,3 +98,8 @@ cacheDirPosition appState@(AppState {stateListPositionCache, stateCwd, stateFile
}
where
pos = fromMaybe 0 $ L.listSelected stateFiles
+
+filterInvalidSelections :: AppState -> IO AppState
+filterInvalidSelections st = do
+ selections <- filterM fileExist . Set.elems $ stateFileSelections st
+ pure $ st {stateFileSelections = Set.fromList selections}