blob: 64977aa1e869df1614be7d7405937788257e5afd (
plain) (
blame)
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
|
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 (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, callProcess)
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
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 "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
let editor' = Editor.applyEdit zipper editor
modify (\s -> s {stateCmdlineEditor = editor'})
|