diff options
Diffstat (limited to 'lib/Daffm/Action/Core.hs')
| -rw-r--r-- | lib/Daffm/Action/Core.hs | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/lib/Daffm/Action/Core.hs b/lib/Daffm/Action/Core.hs index fef6b36..f80e41a 100644 --- a/lib/Daffm/Action/Core.hs +++ b/lib/Daffm/Action/Core.hs @@ -6,14 +6,17 @@ module Daffm.Action.Core where import Brick (suspendAndResume') 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 import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FilePathText, FileType (..)) +import Data.Maybe (fromMaybe) import qualified Data.Set as Set import qualified Data.Text as Text import System.Directory (getHomeDirectory) +import qualified System.Exit as Proc import System.FilePath (takeDirectory) -import System.Process (callProcess) +import qualified System.Process as Proc modifyM :: (MonadState s m) => (s -> m s) -> m () modifyM f = get >>= f >>= put @@ -33,8 +36,7 @@ goBackToParentDir = do loadDir dir changeDir :: FilePathText -> AppEvent () -changeDir dir = do - loadDir dir +changeDir = loadDir goHome :: AppEvent () goHome = do @@ -43,15 +45,47 @@ goHome = do openSelectedFile :: AppEvent () openSelectedFile = do currentFile >>= \case - Just file -> openFile file + Just (FileInfo {filePath, fileType = Directory}) -> loadDir filePath + Just _ -> do + opener <- gets (fromMaybe "echo '%F' | xargs -i xdg-open {}" . stateOpenerScript) + cmdSubstitutions opener >>= suspendAndRunShellCommand False Nothing -> pure () -openFile :: FileInfo -> AppEvent () -openFile (FileInfo {filePath, fileType = Directory}) = loadDir filePath -openFile (FileInfo {filePath, fileType}) = do +shellCommand :: String -> IO Proc.ExitCode +shellCommand cmd = do + Proc.withCreateProcess + (Proc.shell cmd) {Proc.delegate_ctlc = True} + $ \_ _ _ p -> Proc.waitForProcess p + +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 = Set.elems stateFileSelections + let selectionsOrCurrent = if Set.null stateFileSelections then [file] else selections + let subst = + Text.replace "%" file + . Text.replace "%d" stateCwd + . Text.replace "%s" (Text.unwords $ map escape selections) + . Text.replace "%S" (Text.dropWhileEnd (== '\n') $ Text.unlines selections) + . Text.replace "%f" (Text.unwords $ map escape selectionsOrCurrent) + . Text.replace "%F" (Text.dropWhileEnd (== '\n') $ Text.unlines selectionsOrCurrent) + pure . subst $ cmd + +-- Suspend tui and run shell command +-- When waitForKey is true, it will prompt for a key press on success +-- When exit code is non-zero, it will print it and prompt for key press regardless of waitForKey +suspendAndRunShellCommand :: Bool -> Text.Text -> AppEvent () +suspendAndRunShellCommand waitForKey cmd = do suspendAndResume' $ do - putStrLn $ "Opening " <> show fileType <> ": " <> Text.unpack filePath - callProcess "nvim" [Text.unpack filePath] + exitCode <- shellCommand $ Text.unpack cmd + case exitCode of + Proc.ExitFailure code -> do + putStrLn $ "Process exited with " <> show code + putStrLn "Press any key to continue" >> void getChar + _ | waitForKey -> putStrLn "Press any key to continue" >> void getChar + _ -> pure () currentFile :: AppEvent (Maybe FileInfo) currentFile = do |
