aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example-config.toml16
-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
-rw-r--r--notes.org4
-rw-r--r--specs/Specs/FooSpec.hs3
7 files changed, 51 insertions, 17 deletions
diff --git a/example-config.toml b/example-config.toml
index ccadfd8..2947c73 100644
--- a/example-config.toml
+++ b/example-config.toml
@@ -50,13 +50,13 @@ xclip -selection clipboard -t $(file --mime-type % -bL) -i %
"\\x7" = "!!7z x %f"
"\\xt" = "!!tar xzf %f"
"\\xr" = "!!unrar x %f"
-"\\wi" = "!!wine %"
-"<space>p" = ["!clear", "preview"]
+"<space>p" = "preview"
[commands]
-preview = """!!
-file="%args"
+preview = """shell!
+file='%args'
if [ -z "$file" ]; then file=%; fi
+clear;
case "$file" in
*.bmp|*.jpg|*.jpeg|*.png|*.xpm|*.webp|*.gif) chafa -f kitty $file ;;
*.wav|*.mp3|*.flac|*.m4a|*.wma|*.ac3|*.og[agx]|*.opus|*.flac)
@@ -77,6 +77,12 @@ case "$file" in
*.rar) unrar l $file ;;
*.7z) 7z l $file ;;
*.o) nm $file | less ;;
- *) bat --color always $file || cat $file ;;
+ *)
+ if isutf8 -q "$file"; then
+ bat --color always $file || cat $file
+ else
+ mediainfo "$file"
+ fi
+ ;;
esac
"""
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
diff --git a/notes.org b/notes.org
index d1ff03e..a45483d 100644
--- a/notes.org
+++ b/notes.org
@@ -3,14 +3,14 @@
- [X] Allow recursive config extends (@A -> @B -> @C)
- [X] custom commands
- [X] fix problems with substitutions (maybe switch to env vars?)
+- [X] handle permissions errors
- [ ] allow escaping % in commands
- [ ] escape % in file paths while substituting
- [ ] allow updating selection list (:selection-add, :selection-delete)
- [ ] cmdline autocompletion
-- [ ] handle permissions errors
- [ ] Use ls for file listing respecting ansi colors?
- [ ] Generalize cd/opener/back?
-- [ ] Show error messages (invalid commands/shell errors)
+- [X] Show error messages (invalid commands/shell errors)
** Later
- [ ] cross instance selections? (just override keys?)
- [ ] Show last cmd in cmdline
diff --git a/specs/Specs/FooSpec.hs b/specs/Specs/FooSpec.hs
index 24545f9..d79ce9e 100644
--- a/specs/Specs/FooSpec.hs
+++ b/specs/Specs/FooSpec.hs
@@ -52,7 +52,8 @@ test = do
describe "parseCommand" $ do
context "when given an invalid command" $ do
it "returns Nothing" $ do
- parseCommand "aklsdjijm" `shouldBe` Nothing
+ parseCommand "foobar arg1 arg2" `shouldBe` Just (CmdCustom "foobar" "arg1 arg2")
+
context "when empty command" $ do
it "returns Nothing" $ do
parseCommand "" `shouldBe` Nothing