diff options
Diffstat (limited to '')
| -rw-r--r-- | example-config.toml | 16 | ||||
| -rw-r--r-- | lib/Daffm/Action/Commands.hs | 9 | ||||
| -rw-r--r-- | lib/Daffm/State.hs | 28 | ||||
| -rw-r--r-- | lib/Daffm/Types.hs | 1 | ||||
| -rw-r--r-- | lib/Daffm/View.hs | 7 | ||||
| -rw-r--r-- | notes.org | 4 | ||||
| -rw-r--r-- | specs/Specs/FooSpec.hs | 3 |
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 @@ -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 |
