diff options
| -rw-r--r-- | daffm.cabal | 1 | ||||
| -rw-r--r-- | lib/Daffm/Event.hs | 43 | ||||
| -rw-r--r-- | lib/Daffm/State.hs | 2 | ||||
| -rw-r--r-- | notes.org | 11 |
4 files changed, 49 insertions, 8 deletions
diff --git a/daffm.cabal b/daffm.cabal index 75a49fe..781e01a 100644 --- a/daffm.cabal +++ b/daffm.cabal @@ -34,6 +34,7 @@ common common-config unix-compat <= 0.7.4.1, mtl == 2.3.1, containers <= 0.8, + text-zipper <= 0.13, temporary, text, vector, diff --git a/lib/Daffm/Event.hs b/lib/Daffm/Event.hs index f14ebd8..b9e7398 100644 --- a/lib/Daffm/Event.hs +++ b/lib/Daffm/Event.hs @@ -8,10 +8,15 @@ import qualified Brick.Widgets.List as L import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, modify, put) import Daffm.State (cacheDirPosition, loadDirInAppState) import Daffm.Types (AppState (..), FileInfo (..), FileType (..), FocusTarget (FocusCmdline, FocusMain)) +import Data.Char (isSpace) +import Data.List (dropWhileEnd) +import Data.Maybe (fromMaybe) +import qualified Data.Text as Text +import qualified Data.Text.Zipper as Z import Data.Vector ((!?)) import qualified Graphics.Vty as V import System.FilePath (takeDirectory) -import System.Process (callProcess) +import System.Process (callCommand, callProcess) type AppEvent = T.EventM FocusTarget AppState @@ -22,17 +27,24 @@ appEvent :: T.BrickEvent FocusTarget e -> AppEvent () appEvent brickevent@(T.VtyEvent event) = do focusTarget <- gets stateFocusTarget case (focusTarget, event) of - (FocusCmdline, V.EvKey V.KEsc []) -> modify (\st -> st {stateFocusTarget = FocusMain}) - (FocusMain, V.EvKey (V.KChar ':') []) -> modify (\st -> st {stateFocusTarget = FocusCmdline}) - (FocusMain, V.EvKey (V.KChar 'q') []) -> M.halt (FocusMain, V.EvKey (V.KChar 'l') []) -> openSelectedFile (FocusMain, V.EvKey (V.KChar 'h') []) -> goBackToParentDir (FocusMain, V.EvKey V.KEnter []) -> openSelectedFile (FocusMain, V.EvKey V.KBS []) -> goBackToParentDir + (FocusMain, V.EvKey (V.KChar ':') []) -> modify (\st -> st {stateFocusTarget = FocusCmdline}) + (FocusMain, V.EvKey (V.KChar 'q') []) -> M.halt + (FocusMain, V.EvKey (V.KChar 'r') [V.MCtrl]) -> reloadDir (FocusMain, _) -> do files <- gets stateFiles newFiles <- T.nestEventM' files (L.handleListEventVi L.handleListEvent event) modify (\appState -> appState {stateFiles = newFiles}) + (FocusCmdline, V.EvKey V.KEsc []) -> modify (\st -> st {stateFocusTarget = FocusMain}) + (FocusCmdline, V.EvKey V.KEnter []) -> do + gets (trimCmd . Editor.getEditContents . stateCmdlineEditor) >>= evaluateCommand + clearEditor + modify (\st -> st {stateFocusTarget = FocusMain}) + where + trimCmd = dropWhile isSpace . dropWhileEnd isSpace . unlines (FocusCmdline, _) -> do editor <- gets stateCmdlineEditor newEditor <- T.nestEventM' editor (Editor.handleEditorEvent brickevent) @@ -40,6 +52,29 @@ appEvent brickevent@(T.VtyEvent event) = do modify cacheDirPosition appEvent _ = pure () +cmdSubstitutions :: Text.Text -> AppEvent Text.Text +cmdSubstitutions cmd = do + file <- gets (maybe "" (filePath . snd) . L.listSelectedElement . stateFiles) + pure $ Text.replace "%" (Text.pack file) cmd + +evaluateCommand :: String -> AppEvent () +evaluateCommand ('!' : cmd) = do + cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd) + suspendAndResume' $ callCommand cmd' + reloadDir +evaluateCommand cmd = pure () + +clearEditor :: AppEvent () +clearEditor = do + editor <- gets stateCmdlineEditor + let editor' = Editor.applyEdit Z.clearZipper editor + modify (\s -> s {stateCmdlineEditor = editor'}) + +reloadDir :: AppEvent () +reloadDir = do + AppState {stateParentDir, stateCwd} <- get + modifyM (liftIO . loadDirInAppState stateCwd stateParentDir) + openSelectedFile :: AppEvent () openSelectedFile = do AppState {stateFiles, stateCwd} <- get diff --git a/lib/Daffm/State.hs b/lib/Daffm/State.hs index cfa9aeb..13fb613 100644 --- a/lib/Daffm/State.hs +++ b/lib/Daffm/State.hs @@ -17,7 +17,7 @@ mkEmptyAppState :: AppState mkEmptyAppState = AppState { stateFiles = L.list FocusMain (Vec.fromList []) 1, - stateCmdlineEditor = Editor.editor FocusCmdline Nothing "", + stateCmdlineEditor = Editor.editor FocusCmdline (Just 1) "", stateFocusTarget = FocusMain, stateListPositionCache = Map.empty, stateCwd = "", @@ -1,18 +1,23 @@ ** Current - [X] Preserve cursor position per dir while navigating -- [ ] Cmdline must be single line +- [X] Cmdline must be single line +- [X] Reload - [ ] Commands -- [ ] Run shell command -- [ ] Command substitutions (%:filehighlighted %d:cwd %s:selections) +- [X] Run shell command +- [X] Command substitution % +- [ ] Command substitution %d:cwd - [ ] Show file permissions ** Later - [ ] handle on open (for external integrations) - [ ] Cmdline history - [ ] bind command: define keybindings - [ ] select multiple files +- [ ] Command substitution %s:selections +- [ ] cd into dir symlinks - [ ] copy/paste across instances - user-land solution (write selections to file and read from second instance) - socket - [ ] support multikey bindings? - [ ] configuration file (toml?) - [ ] watch for changes +- [ ] cmdline tab completion |
