aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--example-config.toml82
-rw-r--r--lib/Daffm/Action/Commands.hs62
-rw-r--r--lib/Daffm/Action/Keymap.hs2
-rw-r--r--lib/Daffm/Configuration.hs12
-rw-r--r--lib/Daffm/State.hs1
-rw-r--r--lib/Daffm/Types.hs8
-rw-r--r--notes.org3
7 files changed, 137 insertions, 33 deletions
diff --git a/example-config.toml b/example-config.toml
new file mode 100644
index 0000000..ccadfd8
--- /dev/null
+++ b/example-config.toml
@@ -0,0 +1,82 @@
+opener = """
+echo "%F" | while IFS= read file; do
+ case "$(file --mime-type "$file" -bL)" in
+ image/*) setsid -f sxiv "$file" >/dev/null 2>&1 ;;
+ video/*|image/gif) setsid -f mpv "$file" >/dev/null 2>&1 ;;
+ application/pdf) setsid -f zathura "$file" >/dev/null 2>&1 ;;
+ *) $EDITOR "$file" ;;
+ esac
+done;
+"""
+
+[keymap]
+md = "cmdline-set !mkdir -p "
+mf = "cmdline-set !touch "
+cl = ["cmdline-set !ln -s %f ", "selection-clear"]
+rn = ["!!clear; echo '%F' | vidir -v -", "selection-clear"]
+dd = "!clear; echo '%F'; rm -rfIv %f"
+sdd = "!clear; echo '%F'; sudo rm -rfIv %f"
+cc = ["!!clear; echo 'Duplicated %'; cp -r % %.dup", "selection-clear"]
+cp = ["!!cp -irv %s -t %d", "selection-clear"]
+mv = ["!!mv -iv %s -t %d", "selection-clear"]
+
+gdl = "cd ~/Downloads"
+gdc = "cd ~/Documents"
+gp = "cd ~/Pictures"
+gsc = "cd ~/Pictures/screenshots"
+gdp = "cd ~/dump"
+gmnt = "cd /run/media/imsohexy"
+gdv = "cd ~/dev/projects"
+
+# Clipboard
+yy = """shell
+relpath=$(realpath -s --relative-to="${DAFFM_PATH_RELATIVE_TO:-$PWD}" %)
+echo -n "$relpath" | xclip -selection clipboard
+"""
+YY = "!echo -n % | xclip -selection clipboard"
+yf = """shell
+xclip -selection clipboard -t $(file --mime-type % -bL) -i %
+"""
+
+# Mark directories
+"m1" = """eval echo "<daffm>map <space>1 cd %d" """
+"m2" = """eval echo "<daffm>map <space>2 cd %d" """
+"m3" = """eval echo "<daffm>map <space>3 cd %d" """
+"m4" = """eval echo "<daffm>map <space>4 cd %d" """
+
+# Alt openers
+"<space>du" = "!!dua ."
+"\\xz" = "!!unzip %f"
+"\\x7" = "!!7z x %f"
+"\\xt" = "!!tar xzf %f"
+"\\xr" = "!!unrar x %f"
+"\\wi" = "!!wine %"
+"<space>p" = ["!clear", "preview"]
+
+[commands]
+preview = """!!
+file="%args"
+if [ -z "$file" ]; then file=%; fi
+case "$file" in
+ *.bmp|*.jpg|*.jpeg|*.png|*.xpm|*.webp|*.gif) chafa -f kitty $file ;;
+ *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ac3|*.og[agx]|*.opus|*.flac)
+ mediainfo $file
+ ;;
+ *.avi|*.mp4|*.ogv|*.mkv|*.mpg|*.mpeg|*.m2v|*.mov|*.webm|*.mts|*.m4v)
+ mediainfo $file
+ ;;
+ *.pdf) pdftotext $file - | less ;;
+ *.docx) docx2txt $file - | less ;;
+ *.md|*.org) glow -s dark -p $file ;;
+ *.tgz|*.tar.gz) tar tzf $file ;;
+ *.tar.bz2|*.tbz2) tar tjf $file ;;
+ *.tar.bz2|*.tbz2) tar tjf $file ;;
+ *.tar.txz|*.txz) xz --list $file ;;
+ *.tar) tar tf $file ;;
+ *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l $file ;;
+ *.rar) unrar l $file ;;
+ *.7z) 7z l $file ;;
+ *.o) nm $file | less ;;
+ *) bat --color always $file || cat $file ;;
+esac
+"""
diff --git a/lib/Daffm/Action/Commands.hs b/lib/Daffm/Action/Commands.hs
index c77a9fc..5538eec 100644
--- a/lib/Daffm/Action/Commands.hs
+++ b/lib/Daffm/Action/Commands.hs
@@ -62,10 +62,10 @@ 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]
-readCommandLines' cmd = do
+readCommandLines :: Text.Text -> IO [Text.Text]
+readCommandLines cmd = do
Proc.withCreateProcess
(Proc.shell $ Text.unpack cmd)
{ Proc.delegate_ctlc = True,
@@ -77,47 +77,55 @@ readCommandLines' cmd = do
_ <- Proc.waitForProcess p
Text.lines <$> maybe (pure "") Text.hGetContents stdout
-processCommand :: Command -> AppEvent ()
-processCommand (CmdShell waitForKey cmd) = do
- cmdSubstitutions cmd >>= suspendAndRunShellCommand waitForKey
+argSubst :: Text.Text -> Text.Text -> Text.Text
+argSubst = Text.replace "%args"
+
+processCommand :: Command -> CustomArgs -> AppEvent ()
+processCommand (CmdShell waitForKey cmd) args = do
+ cmdSubstitutions (argSubst args cmd) >>= suspendAndRunShellCommand waitForKey
reloadDir
-processCommand (CmdCommandShell cmd) = do
- stdout <- cmdSubstitutions cmd >>= liftIO . readCommandLines'
+processCommand (CmdCommandShell cmd) args = do
+ stdout <- cmdSubstitutions (argSubst args cmd) >>= liftIO . readCommandLines
forM_ stdout runIfCmd
reloadDir
where
runIfCmd (Text.stripPrefix "<daffm>" -> Just cmd') =
- processCommand $ fromMaybe CmdNoop (parseCommand cmd')
+ processCommand (fromMaybe CmdNoop (parseCommand cmd')) args
runIfCmd _ = pure ()
-processCommand CmdQuit = M.halt
-processCommand (CmdSetCmdline txt) = enterCmdline >> cmdSubstitutions txt >>= setCmdlineText
-processCommand CmdEnterCmdline = enterCmdline
-processCommand CmdLeaveCmdline = leaveCmdline
-processCommand CmdOpenSelection = openSelectedFile
-processCommand (CmdChangeDir dir) = cmdSubstitutions dir >>= changeDir
-processCommand CmdReload = reloadDir
-processCommand CmdToggleSelection = toggleCurrentFileSelection
-processCommand CmdClearSelection = clearFileSelections
-processCommand CmdGoBack = goBackToParentDir
-processCommand (CmdChain chain) = forM_ chain processCommand
-processCommand (CmdSearch term) = setSearchTerm term >> applySearch >> nextSearchMatch
-processCommand (CmdSearchNext change) = updateSearchIndex (+ change) >> nextSearchMatch
-processCommand (CmdKeymapSet keys command) =
+processCommand CmdQuit _args = M.halt
+processCommand (CmdSetCmdline txt) args = enterCmdline >> cmdSubstitutions (argSubst args txt) >>= setCmdlineText
+processCommand CmdEnterCmdline _args = enterCmdline
+processCommand CmdLeaveCmdline _args = leaveCmdline
+processCommand CmdOpenSelection _args = openSelectedFile
+processCommand (CmdChangeDir dir) args = cmdSubstitutions (argSubst args dir) >>= changeDir
+processCommand CmdReload _args = reloadDir
+processCommand CmdToggleSelection _args = toggleCurrentFileSelection
+processCommand CmdClearSelection _args = clearFileSelections
+processCommand CmdGoBack _ = goBackToParentDir
+processCommand (CmdChain chain) args = forM_ chain (`processCommand` args)
+processCommand (CmdSearch term) _ = setSearchTerm term >> applySearch >> nextSearchMatch
+processCommand (CmdSearchNext change) _ = updateSearchIndex (+ change) >> nextSearchMatch
+processCommand (CmdKeymapSet keys command) _ =
modify $ \st -> st {stateKeyMap = Map.insert keys command $ stateKeyMap st}
-processCommand (CmdMove move) = moveCursor $ toUpdater move
+processCommand (CmdMove move) _ = moveCursor $ toUpdater move
where
toUpdater MoveToEnd = L.listMoveToEnd
toUpdater (MoveTo pos) = L.listMoveTo pos
- toUpdater (MoveUp inc) = L.listMoveBy $ - inc
+ toUpdater (MoveUp inc) = L.listMoveBy $ -inc
toUpdater (MoveDown inc) = L.listMoveBy inc
moveCursor :: (L.List FocusTarget FileInfo -> L.List FocusTarget FileInfo) -> AppEvent ()
moveCursor updater = do
files <- gets $ updater . stateFiles
modify $ \st -> st {stateFiles = files}
-processCommand CmdNoop = pure ()
+processCommand (CmdCustom cmd args) _ = do
+ myCmd <- gets $ Map.lookup cmd . stateCustomCommands
+ case myCmd of
+ Just command -> processCommand command args
+ Nothing -> pure ()
+processCommand CmdNoop _ = pure ()
evaluateCommand :: Text.Text -> AppEvent ()
evaluateCommand cmdtxt =
case parseCommand cmdtxt of
- Just cmd -> processCommand cmd
+ Just cmd -> processCommand cmd ""
Nothing -> pure ()
diff --git a/lib/Daffm/Action/Keymap.hs b/lib/Daffm/Action/Keymap.hs
index 4463446..c3079c9 100644
--- a/lib/Daffm/Action/Keymap.hs
+++ b/lib/Daffm/Action/Keymap.hs
@@ -11,7 +11,7 @@ processKeySequence = do
let match = matchKeySequence stateKeyMap stateKeySequence
case match of
MatchSuccess cmd -> do
- processCommand cmd
+ processCommand cmd ""
modify (\st -> st {stateKeySequence = []})
MatchPartial -> pure ()
MatchFailure -> do
diff --git a/lib/Daffm/Configuration.hs b/lib/Daffm/Configuration.hs
index 3b61d6e..ee8f88e 100644
--- a/lib/Daffm/Configuration.hs
+++ b/lib/Daffm/Configuration.hs
@@ -26,7 +26,7 @@ defaultConfiguration =
Configuration
{ configKeymap = defaultKeymaps,
configOpener = Nothing,
- configTheme = Map.empty,
+ configCommands = Map.empty,
configExtend = Nothing
}
@@ -102,7 +102,7 @@ configurationCodec =
<$> (keymapCodec "keymap" .= configKeymap)
<*> (openerCodec "opener" .= configOpener)
<*> (extendCodec "extend" .= configExtend)
- <*> pure Map.empty .= configTheme
+ <*> (commandsCodec "commands" .= configCommands)
where
openerCodec = Toml.dioptional . Toml.text
extendCodec = Toml.dioptional . Toml.text
@@ -118,3 +118,11 @@ keymapCodec = Toml.dimap (const Map.empty) toKeymap . keymapRawCodec
commandCodec k = cmdCodec k <|> cmdChainCodec k
cmdCodec = Toml.dimap (const "") toCmd . Toml.text
cmdChainCodec = Toml.dimap (const []) (CmdChain . map toCmd) . Toml.arrayOf Toml._Text
+
+commandsCodec :: Toml.Key -> Toml.TomlCodec (Map.Map Text.Text Command)
+commandsCodec = Toml.tableMap Toml._KeyText commandCodec
+ where
+ toCmd = fromMaybe CmdNoop . parseCommand
+ commandCodec k = cmdCodec k <|> cmdChainCodec k
+ cmdCodec = Toml.dimap (const "") toCmd . Toml.text
+ cmdChainCodec = Toml.dimap (const []) (CmdChain . map toCmd) . Toml.arrayOf Toml._Text
diff --git a/lib/Daffm/State.hs b/lib/Daffm/State.hs
index 6d7f6ea..040d244 100644
--- a/lib/Daffm/State.hs
+++ b/lib/Daffm/State.hs
@@ -39,6 +39,7 @@ mkEmptyAppState config =
stateKeySequence = [],
stateSearchTerm = Nothing,
stateSearchMatches = Vec.empty,
+ stateCustomCommands = configCommands config,
stateSearchIndex = 0
}
diff --git a/lib/Daffm/Types.hs b/lib/Daffm/Types.hs
index d9dd977..15c284b 100644
--- a/lib/Daffm/Types.hs
+++ b/lib/Daffm/Types.hs
@@ -40,6 +40,7 @@ data FocusTarget = FocusCmdline | FocusMain deriving (Show, Eq, Ord)
data AppState = AppState
{ stateCmdlineEditor :: CmdlineEditor,
stateCwd :: FilePathText,
+ stateCustomCommands :: Map.Map Text.Text Command,
stateFileSelections :: Set.Set FilePathText,
stateFiles :: L.List FocusTarget FileInfo,
stateFocusTarget :: FocusTarget,
@@ -53,6 +54,8 @@ data AppState = AppState
}
deriving (Show)
+type CustomArgs = Text.Text
+
type AppEvent = EventM FocusTarget AppState
type CmdlineEditor = Editor.Editor Text.Text FocusTarget
@@ -81,6 +84,7 @@ data Command
| CmdSearchNext Int
| CmdKeymapSet [Key] Command
| CmdMove MoveInc
+ | CmdCustom Text.Text CustomArgs
| CmdNoop
deriving (Show, Eq)
@@ -94,7 +98,7 @@ data Configuration = Configuration
{ configKeymap :: !Keymap,
configOpener :: !(Maybe Text.Text),
configExtend :: !(Maybe Text.Text),
- configTheme :: !(Map.Map Text.Text Text.Text)
+ configCommands :: !(Map.Map Text.Text Command)
}
deriving (Show)
@@ -103,7 +107,7 @@ instance Semigroup Configuration where
a
{ configKeymap = configKeymap a <> configKeymap b,
configOpener = configOpener a <|> configOpener b,
- configTheme = configTheme a <> configTheme b
+ configCommands = configCommands a <> configCommands b
}
data Args = Args
diff --git a/notes.org b/notes.org
index b9f2fb5..d1ff03e 100644
--- a/notes.org
+++ b/notes.org
@@ -1,9 +1,10 @@
- [X] commands: move cursor: move +1, move -1, move 5, move $, move 0
- [X] rename command-shell to evaluate
- [X] Allow recursive config extends (@A -> @B -> @C)
-- [ ] custom commands
+- [X] custom commands
- [X] fix problems with substitutions (maybe switch to env vars?)
- [ ] allow escaping % in commands
+- [ ] escape % in file paths while substituting
- [ ] allow updating selection list (:selection-add, :selection-delete)
- [ ] cmdline autocompletion
- [ ] handle permissions errors