diff options
| author | Dylan Araps <dylan.araps@gmail.com> | 2026-02-28 21:52:26 +0200 |
|---|---|---|
| committer | Dylan Araps <dylan.araps@gmail.com> | 2026-02-28 21:52:26 +0200 |
| commit | 67a1c24a8661fdcbc48f72f7b65521772065d305 (patch) | |
| tree | 33c1fbfe2452c23773de046b1127f4920aa5a49f | |
| parent | 4fb29c95c61256f78e4b501a3c550b4c92a92a4e (diff) | |
dfm: add ranger style bulk rename
Also the ability to embed scripts within dfm.
| -rw-r--r-- | README.txt | 6 | ||||
| -rwxr-xr-x | bin/embed | 32 | ||||
| -rw-r--r-- | config_cmd.h.in | 33 | ||||
| -rw-r--r-- | config_key.h.in | 1 | ||||
| -rwxr-xr-x | script/bulk-rename | 47 | ||||
| -rwxr-xr-x | script/opener_ext (renamed from example/opener_ext) | 0 | ||||
| -rwxr-xr-x | script/opener_mime (renamed from example/opener_mime) | 0 |
7 files changed, 115 insertions, 4 deletions
@@ -26,7 +26,7 @@ Initial Announcement: https://dylan.gr/1772192922 * UTF8 support (minus grapheme clusters and other unruly things) * Multiple view modes (name, size, permissions, mtime, ...) * Multiple sort modes (name, extension, size, mtime, reverse, ...) -* No temporary file usage +* Ranger-style bulk rename * Incremental as-you-type search * Bookmarks * Vim-like keybindings @@ -161,7 +161,7 @@ environment, default values are derived from the config.h.in file. bind act_cd_bookmark_[0-9] to the keys of your choosing) - DFM_OPENER (Opener script to use when opening files. This could be - xdg-open or a custom script (see the examples/ directory)) + xdg-open or a custom script (see the script/ directory)) - DFM_TRASH (Program to use when trashing files) @@ -228,7 +228,7 @@ All is the sum of the other view modes and gives an idea of what is shown: -rwxr-xr-x 16m 4.0K .git/ -rwxr-xr-x 2h 4.0K bin/ --rwxr-xr-x 4d 4.0K example/ +-rwxr-xr-x 4d 4.0K script/ -rwxr-xr-x 32m 4.0K lib/ -rwxr-xr-x 16h 4.0K platform/ -rw-r--r-- 16m 0B .config_macro.h diff --git a/bin/embed b/bin/embed new file mode 100755 index 0000000..5efe6d8 --- /dev/null +++ b/bin/embed @@ -0,0 +1,32 @@ +#!/bin/sed -f +# +# Convert input to 32bit hex encoded utf8. +# +# Copyright (c) 2026 Dylan Araps +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +/^[[:space:]]*#/d +s/\\/\\\\/g +s/"/\\"/g +s/$/\\n/ +s/^/"/ +s/$/"/ + diff --git a/config_cmd.h.in b/config_cmd.h.in index 5891957..3802760 100644 --- a/config_cmd.h.in +++ b/config_cmd.h.in @@ -25,7 +25,31 @@ // CMD_FILE_CURSOR = Ignore marks and add the name under the cursor to input. // CMD_EXEC_MARK = Skip interactive prompt only if marks exist.. // CMD_EXEC_ROOT = Skip interactive prompt even if root. -// +!! +## Shell cript can be embedded within dfm by using the embed command. +## The script will be run in $SHELL as the argument following '-c'. +## +## FM_CMD(cmd_bulk_rename, +## .prompt = CUT_NULL, +## .left = CUT($(embed script/bulk-rename)), +## .enter = fm_cmd_run_sh, +## .config = CMD_MARK_DIR | CMD_MUT | CMD_EXEC, +## ) +## +## Another useful example is embedding your opener script. +## +## FM_CMD(cmd_opener, +## .prompt = CUT_NULL, +## .left = CUT($(embed script/opener_ext)), +## .enter = fm_cmd_run_sh, +## .config = CMD_MARK_DIR | CMD_EXEC, +## ) +## +## Shell can also be typed directly but its cumbersone to add \\n to the end of +## each line and escape backslashes and double quotes. +## +## .left = CUT("echo \\"$@\\"\\n"), +!! // If the FM_CMD system is too limiting you can define your own functions and // bind them to keys. The same function signature is used in navigation and // input modes. @@ -154,3 +178,10 @@ FM_CMD(cmd_trash, .config = CMD_MARK_DIR | CMD_MUT | CMD_EXEC_MARK, ) +FM_CMD(cmd_bulk_rename, + .prompt = CUT_NULL, + .left = CUT($(embed script/bulk-rename)), + .enter = fm_cmd_run_sh, + .config = CMD_MARK_DIR | CMD_MUT | CMD_EXEC, +) + diff --git a/config_key.h.in b/config_key.h.in index fde7239..cfb4253 100644 --- a/config_key.h.in +++ b/config_key.h.in @@ -92,6 +92,7 @@ static inline void (*fm_key(u32 cp))(struct fm *) case 'z': return act_alt_buffer; case 'p': return cmd_chmod; case 'P': return cmd_chown; + case 'B': return cmd_bulk_rename; case '~': return act_cd_home; case 'Y': return cmd_copy_clipboard; diff --git a/script/bulk-rename b/script/bulk-rename new file mode 100755 index 0000000..3bd6c85 --- /dev/null +++ b/script/bulk-rename @@ -0,0 +1,47 @@ +#!/bin/sh -eu +# +# Interactive bulk file rename using $EDITOR. +# +# Copyright (c) 2026 Dylan Araps +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +case $# in 0) exit; esac +f=${TMPDIR:=/tmp}/.dfm-brn-$$-$# +e() { rm -f "$f" || :; exit "$1"; } +( + printf '%s\n' "$@" > "$f" && + "${EDITOR:=vi}" "$f" && + exec 3<"$f" && + for _ do + IFS= read -r l <&3 + set -- "$@" "mv -f -- '$1' '${l:?line mismatch in rename file}'" + shift + done && { + read -r l <&3 && { + echo "$0: 39: line mismatch in rename file" >&2 + return 1 + } + printf '%s\n' '# This file will be executed when the editor is closed.' \ + '# Clear the file to abort.' "$@" + } > "$f" && + "$EDITOR" "$f" && . "$f" && e 0 +) || e 1 + diff --git a/example/opener_ext b/script/opener_ext index ce1699a..ce1699a 100755 --- a/example/opener_ext +++ b/script/opener_ext diff --git a/example/opener_mime b/script/opener_mime index 2f7bd52..2f7bd52 100755 --- a/example/opener_mime +++ b/script/opener_mime |