aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Daffm/Action/Commands.hs9
-rw-r--r--lib/Daffm/State.hs28
-rw-r--r--lib/Daffm/Types.hs1
-rw-r--r--lib/Daffm/View.hs7
4 files changed, 36 insertions, 9 deletions
diff --git a/lib/Daffm/Action/Commands.hs b/lib/Daffm/Action/Commands.hs
index 5538eec..a963191 100644
--- a/lib/Daffm/Action/Commands.hs
+++ b/lib/Daffm/Action/Commands.hs
@@ -62,6 +62,7 @@ parseCommand cmd = mkCmd . splitCmdArgs $ trimStart cmd
("move", Text.stripPrefix "+" -> Just inc) -> Just . CmdMove . MoveDown . read $ Text.unpack inc
("move", Text.stripPrefix "-" -> Just inc) -> Just . CmdMove . MoveUp . read $ Text.unpack inc
("move", readMaybe . Text.unpack -> Just pos) -> Just . CmdMove . MoveTo $ pos
+ ("", _) -> Nothing
(cmd', args) -> Just $ CmdCustom cmd' args
readCommandLines :: Text.Text -> IO [Text.Text]
@@ -93,7 +94,8 @@ processCommand (CmdCommandShell cmd) args = do
processCommand (fromMaybe CmdNoop (parseCommand cmd')) args
runIfCmd _ = pure ()
processCommand CmdQuit _args = M.halt
-processCommand (CmdSetCmdline txt) args = enterCmdline >> cmdSubstitutions (argSubst args txt) >>= setCmdlineText
+processCommand (CmdSetCmdline txt) args =
+ enterCmdline >> cmdSubstitutions (argSubst args txt) >>= setCmdlineText
processCommand CmdEnterCmdline _args = enterCmdline
processCommand CmdLeaveCmdline _args = leaveCmdline
processCommand CmdOpenSelection _args = openSelectedFile
@@ -121,11 +123,12 @@ processCommand (CmdCustom cmd args) _ = do
myCmd <- gets $ Map.lookup cmd . stateCustomCommands
case myCmd of
Just command -> processCommand command args
- Nothing -> pure ()
+ Nothing -> modify (\st -> st { stateMessage = Just $ "Invalid command " <> cmd })
processCommand CmdNoop _ = pure ()
evaluateCommand :: Text.Text -> AppEvent ()
-evaluateCommand cmdtxt =
+evaluateCommand cmdtxt = do
+ modify (\st -> st { stateMessage = Nothing })
case parseCommand cmdtxt of
Just cmd -> processCommand cmd ""
Nothing -> pure ()
diff --git a/lib/Daffm/State.hs b/lib/Daffm/State.hs
index 040d244..902b6c6 100644
--- a/lib/Daffm/State.hs
+++ b/lib/Daffm/State.hs
@@ -17,7 +17,7 @@ import qualified Data.Set as Set
import qualified Data.Text as Text
import qualified Data.Text.Zipper.Generic as Zipper
import qualified Data.Vector as Vec
-import System.Directory (doesDirectoryExist, doesPathExist, getCurrentDirectory, getHomeDirectory, getSymbolicLinkTarget, listDirectory, makeAbsolute, setCurrentDirectory)
+import System.Directory (doesDirectoryExist, doesPathExist, getCurrentDirectory, getHomeDirectory, getPermissions, getSymbolicLinkTarget, listDirectory, makeAbsolute, readable, setCurrentDirectory)
import System.FilePath (joinPath, takeDirectory)
import System.PosixCompat (fileExist)
import qualified System.PosixCompat as Posix
@@ -29,6 +29,7 @@ mkEmptyAppState :: Configuration -> AppState
mkEmptyAppState config =
AppState
{ stateFiles = L.list FocusMain (Vec.fromList []) 1,
+ stateMessage = Nothing,
stateCmdlineEditor = mkEditor "",
stateFocusTarget = FocusMain,
stateListPositionHistory = Map.empty,
@@ -84,17 +85,34 @@ loadDirToState dir' appState@(AppState {stateCwd, stateListPositionHistory}) = d
if Posix.isDirectory stat
then (normalizedDir, Nothing)
else (textAsString takeDirectory normalizedDir, Just normalizedDir)
- doesDirectoryExist (Text.unpack dir) >>= \case
- True -> do
+ isReadable <- readable <$> getPermissions (Text.unpack dir)
+ if isReadable
+ then do
setCurrentDirectory $ Text.unpack dir
+ newState <- dirToAppState dir targetFilePath
+ doesPathExist (Text.unpack dir') >>= \case
+ True -> pure newState
+ _ -> pure newState {stateMessage = Just $ "No such file or directory: " <> dir'}
+ else do
+ let list = L.list FocusMain (Vec.fromList []) 1
+ pure $ (withNewDir dir list appState) {stateMessage = Just "Unable to read directory"}
+ where
+ withNewDir dir fileList st =
+ st
+ { stateCwd = dir,
+ stateFiles = fileList,
+ stateMessage = Nothing,
+ stateSearchIndex = 0,
+ stateSearchMatches = Vec.empty
+ }
+ dirToAppState dir targetFilePath = do
files <- listFilesInDir dir
let prevDirPos = findIndex ((== stateCwd) . filePath) files
let cachedPos = Map.lookup dir stateListPositionHistory
let targetFilePos = targetFilePath >>= \target -> findIndex ((== target) . filePath) files
let pos = fromMaybe 0 (targetFilePos <|> cachedPos <|> prevDirPos)
let list = L.listMoveTo pos $ L.list FocusMain (Vec.fromList files) 1
- pure $ appState {stateFiles = list, stateCwd = dir, stateSearchIndex = 0, stateSearchMatches = Vec.empty}
- False -> pure appState
+ pure $ withNewDir dir list appState
fileTypeFromStatus :: Posix.FileStatus -> FileType
fileTypeFromStatus s =
diff --git a/lib/Daffm/Types.hs b/lib/Daffm/Types.hs
index 15c284b..a26b0ef 100644
--- a/lib/Daffm/Types.hs
+++ b/lib/Daffm/Types.hs
@@ -43,6 +43,7 @@ data AppState = AppState
stateCustomCommands :: Map.Map Text.Text Command,
stateFileSelections :: Set.Set FilePathText,
stateFiles :: L.List FocusTarget FileInfo,
+ stateMessage :: Maybe Text.Text,
stateFocusTarget :: FocusTarget,
stateKeyMap :: Keymap,
stateKeySequence :: KeySequence,
diff --git a/lib/Daffm/View.hs b/lib/Daffm/View.hs
index da6a11b..0846f66 100644
--- a/lib/Daffm/View.hs
+++ b/lib/Daffm/View.hs
@@ -18,9 +18,10 @@ import Text.Printf (printf)
appView :: AppState -> [Widget FocusTarget]
appView appState@(AppState {stateFiles}) = [ui]
where
- ui = vBox [vLimit 1 header, box, vLimit 1 cmdline]
+ ui = vBox [vLimit 1 header, box, message, vLimit 1 cmdline]
header = headerView appState
cmdline = cmdlineView appState
+ message = messageView appState
box = L.renderListWithIndex (fileItemView appState) True stateFiles
hFixed :: Int -> Widget n -> Widget n
@@ -101,6 +102,10 @@ symTargetView _ Nothing = withAttr invalidLinkAttr $ txt "<none>"
symTargetView Nothing (Just target) = withAttr invalidLinkAttr $ txt target
symTargetView _ (Just target) = txt target
+messageView :: AppState -> Widget FocusTarget
+messageView (AppState {stateMessage = Just message}) = txt message
+messageView _ = emptyWidget
+
cmdlineView :: AppState -> Widget FocusTarget
cmdlineView (AppState {stateFocusTarget = FocusCmdline, stateCmdlineEditor}) =
txt ":" <+> renderEditor (txt . Text.unlines) True stateCmdlineEditor