summaryrefslogtreecommitdiff
path: root/dfm
diff options
context:
space:
mode:
authorunknown <“filip.rabiega@gmail.com”>2026-08-07 10:37:14 +0200
committerunknown <“filip.rabiega@gmail.com”>2026-08-07 10:37:14 +0200
commit9f9a57cf255c58fe44bb343b4a150a6a8f7fdc31 (patch)
tree16503e36498e5c4866d59b627e4b77a51a181017 /dfm
parent940118eba8178d177eec73ab100ceacdb2526715 (diff)
downloadchadscripts-9f9a57cf255c58fe44bb343b4a150a6a8f7fdc31.tar.gz
chadscripts-9f9a57cf255c58fe44bb343b4a150a6a8f7fdc31.tar.bz2
chadscripts-9f9a57cf255c58fe44bb343b4a150a6a8f7fdc31.zip
add dfm and linkhandlerHEADmaster
Diffstat (limited to 'dfm')
-rwxr-xr-xdfm324
1 files changed, 324 insertions, 0 deletions
diff --git a/dfm b/dfm
new file mode 100755
index 0000000..82d2f22
--- /dev/null
+++ b/dfm
@@ -0,0 +1,324 @@
+#!/bin/sh
+
+PROGRAM_NAME=$(basename $0) # This will be used in a few messages
+
+main() {
+ parse_opts "$@"
+ [ -z "$mode" ] && mode=open # The default mode
+
+ if [ -n "$copy" -a "$copy" != false -a "$cat" = true ]; then
+ prompt_copy_contents "$@"
+ elif [ "$open" = true ]; then
+ prompt_open "$@"
+ elif [ "$cat" = true ]; then
+ prompt_print_contents "$@"
+ elif [ "$print" = true ]; then
+ prompt_print "$@"
+ elif [ -n "$copy" -a "$copy" != false ]; then
+ prompt_copy "$@"
+ else
+ prompt_$mode "$@"
+ fi
+}
+
+prompt_base() {
+ [ -z "$length" ] && length=10
+
+ if [ "$case_sensitivity" = sensitive ]; then
+ backtrack() { sed 's|\(.*/'$sel'[^/]*\).*|\1|'; }
+ s=+i
+ else
+ backtrack() { perl -pe 's|(.*/'$sel'[^/]*).*|$1|i'; }
+ i=-i
+ fi
+
+ [ -z "$menu" ] && menu="dmenu"
+ if [ "$menu" = dmenu ]; then menu() { $menu $i -l $length -p "$@"; }
+ elif [ "$menu" = fzf ]; then menu() { $menu $s $i --header="$@"; }
+ else menu() { $menu; }; fi
+
+ if [ "$path" = "full" ]; then prompt() { p="$target"; }
+ else prompt() { p="$(printf '%s' "$target" | sed 's|^'"$HOME"'|~|')"; }; fi
+
+ # Only GNU `ls` supports `--group-directories-first`
+ if [ "$(ls --version | head -1 | cut -d " " -f 2-3)" = "(GNU coreutils)" ]
+ then
+ list() { ls --group-directories-first "$@"; }
+ else
+ list() {
+ (ls -l "$@" | grep "^d"
+ ls -l "$@" | grep -vE "^d|^total") | tr -s " " | cut -d " " -f 9-
+ }
+ fi
+
+ # Commonly used functions in DFM
+ truepath() { sh -c "realpath -s "$sel""; }
+ slash() { printf '%s' "$target/$sel" | rev | cut -b 1-2; }
+ check() { file -E "$@" | grep "(No such file or directory)$"; }
+ fullcmd() {
+ printf '%s\n' "$PWD" > "$cache_file"
+ printf '%s' "$target" | sed -e "s/'/'\\\\''/g;s/\(.*\)/'\1'/" | cmd
+ }
+
+ while true; do
+ p="$prompt" # Reset the prompt to have it update
+ [ -z "$p" ] && prompt # Make the prompt if it does not exist
+
+ # This is where the file manager actually first opens.
+ sel="$(printf '%s' "$(list "$target"; list -A "$target" | grep '^\.')" |
+ menu "$p")"
+
+ # Exit if the user presses Escape, Control-C, etc.
+ exit_code=$?
+ if [ "$exit_code" -ne 0 ]; then
+ printf '%s\n' "$target" > "$cache_file"
+ exit $exit_code
+ fi
+
+ if [ $(printf '%s' "$sel" | wc -l) -eq 0 ]; then
+ # If the input box is empty, go to the parent directory
+ if [ "$sel" = "" ]; then
+ newt="$(realpath -s "$target/..")"
+ # Relative directories
+ elif [ -e "$target/$sel" -a "$(slash)" != // ]; then
+ newt="$(realpath -s "$target/$sel")"
+ elif [ ! -e "$target/$sel" -a $(printf '%s' "$target" |
+ grep $i "$(sh -c "printf '%s' "$sel"")" | wc -l) -eq 1 ]
+ then
+ # Go to a lower directory using the input box
+ if [ ! -e "$(truepath)" ]; then
+ newt="$(printf '%s' "$target" | backtrack)"
+ # Go to certain directories like `~` `$HOME`, etc.
+ else
+ newt="$(truepath)"
+ fi
+ # Go to a directory when the input box begins with `/`
+ elif [ -e "$(truepath)" ] &&
+ [ ! -e "$target/$sel" -o "$(slash)" = "//" ]
+ then
+ newt="$(truepath)"
+ else
+ # This applies to wildcards
+ newt="$(realpath -s "$target/$sel")"
+ fi
+ else
+ newt="$sel"
+ fi
+
+ # If the current working directory is not empty
+ if [ $(ls | wc -l) -ge 1 ]; then
+ target="$newt"
+ if [ ! -d "$target" ]; then
+ # Check if the user used a wildcard
+ if [ $(printf '%s' "$target" | grep "*" | wc -l) -ge 1 -a\
+ $(check "$target" | wc -l) -eq 1 ]
+ then
+ IFS= # Needed to make wildcards work
+ ls "$PWD"/$sel 1> /dev/null 2>& 1
+ # Target is a file or directory
+ if [ $? -ne 0 ]; then
+ target="$PWD"
+ # Target is a wildcard
+ else
+ target=$(ls -d "$PWD"/$sel) fullcmd
+ exit 0
+ fi
+ # No such file or directory
+ elif [ $(printf '%s' "$target" | wc -l) -eq 0 -a\
+ $(check "$target" | wc -l) -eq 1 ]
+ then
+ target="$PWD"
+ # More than one selection
+ elif [ $(printf '%s' "$target" | wc -l) -gt 0 ]; then
+ target=$(printf '%s' "$target" | sed 's|^|'"$PWD"/'|')
+ fullcmd
+ exit
+ # Exactly one selection
+ else
+ fullcmd
+ exit
+ fi
+ # Target is a directory
+ else
+ PWD="$target"
+ fi
+ fi
+ done
+}
+
+prompt_print() {
+ cmd () { xargs ls -d; }
+ prompt_base "$@"
+}
+
+prompt_print_contents() {
+ cmd() { xargs cat; }
+ prompt_base "$@"
+}
+
+prompt_open() {
+ if [ -x "$(command -v sesame)" ]; then cmd() { xargs sesame; }
+ else cmd() { xargs xdg-open; }; fi
+ prompt_base "$@"
+}
+
+prompt_copy() {
+ cmd() { tr '\n' ' ' | xclip -r -i -selection $copy; }
+ prompt_base "$@"
+}
+
+prompt_copy_contents() {
+ if [ "$(file -b "$target" | cut -d " " -f2)" = "image" ]; then
+ cmd() { xargs xclip -i -selection $copy -t image/png; }
+ else
+ cmd() { xargs xclip -r -i -selection $copy; }
+ fi
+ prompt_base "$@"
+}
+
+help() {
+ printf "Usage:\t$0 [options] [target] [prompt]
+
+Options:
+
+Modes:
+-p|--print │ Print the output of the selection
+-o|--open │ Open the appropriate program for the selection (default)
+
+ --cat │ Concatenate the selections before using a mode
+-c|--copy=[CLIPBOARD] │ Copy the output of the selection
+ --no-copy │ Do not copy (always overrides \`--copy\`)
+ │
+-r|--restore │ Start from the previous path restored from the last run
+-s|--sensitive │ Use case-sensitive matching
+-i|--insensitive │ Use case-insensitive matching (default)
+-m|--menu=MENU │ Choose which menu program to use (default: dmenu)
+-l|--length=LENGTH │ Specify the length of dmenu (default: 10)
+ │
+-f|--full │ Use the full path for the prompt
+-a|--abbreviated │ Use the abbreviated path for the prompt (default)
+ │
+-h|--help │ Print this help message and exit
+"; }
+
+parse_opts() {
+ : "${config_dir:=${XDG_CONFIG_HOME:-$HOME/.config}/$PROGRAM_NAME}"
+ : "${config_file:=$config_dir/$PROGRAM_NAME.conf}"
+ [ -f "$config_file" ] && . "$config_file"
+
+ : "${cache_dir:=${XDG_CACHE_DIR:-$HOME/.cache}/$PROGRAM_NAME}"
+ : "${cache_file:=$cache_dir/path}"
+ # Create the cache file if it doesn't exist
+ if [ ! -f "$cache_file" ]; then
+ mkdir -p "$(dirname "$cache_file")" &&
+ touch "$cache_file"
+ fi
+
+ needs_arg() {
+ if [ -z "$OPTARG" ]; then
+ printf '%s\n' "No arg for --$OPT option" >&2
+ exit 2
+ fi
+ }
+
+ while getopts hpcosim:l:far-: OPT; do
+ # Support long options: https://stackoverflow.com/a/28466267/519360
+ if [ "$OPT" = "-" ]; then
+ OPT="${OPTARG%%=*}"
+ OPTARG="${OPTARG#$OPT}"
+ OPTARG="${OPTARG#=}"
+ fi
+ case "$OPT" in
+ h|help)
+ help
+ exit 0
+ ;;
+ p|print)
+ print=true
+ ;;
+ c|copy)
+ shift
+ [ $(printf '%s' "$OPT" | wc -c) -eq 1 ] && OPTARG="$1"
+ case "$OPTARG" in
+ primary|secondary|clipboard|buffer-cut)
+ copy="$OPTARG"
+ ;;
+ *)
+ copy=clipboard
+ ;;
+ esac
+ [ -n "$1" -a "$OPTARG" = "$1" -a "$copy" = "$OPTARG" ] && shift
+ ;;
+ no-copy)
+ copy=false
+ ;;
+ cat)
+ cat=true
+ ;;
+ o|open)
+ open=true
+ ;;
+ s|sensitive)
+ case_sensitivity="sensitive"
+ ;;
+ i|insensitive)
+ case_sensitivity="insensitive"
+ ;;
+ m|menu)
+ needs_arg
+ menu="$OPTARG"
+ ;;
+ l|length)
+ needs_arg
+ length=$OPTARG
+ ;;
+ f|full)
+ path="full"
+ ;;
+ a|abbreviated)
+ path="abbreviated"
+ ;;
+ r|restore)
+ restore=true
+ ;;
+ ??*)
+ printf '%s\n' "Illegal option --$OPT" >&2
+ exit 2
+ ;;
+ ?) # Error reported via `getopts`
+ exit 2
+ ;;
+ esac
+ done
+ shift $((OPTIND-1)) # Remove option arguments from the argument list
+
+ if [ -n "$1" ]; then
+ target="$1"
+ elif [ -z "$target" ]; then
+ if [ "$restore" = true -a -s "$cache_file" ]; then
+ target="$(cat "$cache_file")"
+ else
+ target="$PWD"
+ fi
+ fi
+
+ if [ -d "$target" ]; then
+ target="$(realpath -s "$target")"
+ PWD="$target"
+ else
+ # Zero out cache file.
+ [ "$restore" = true -a -s "$cache_file" ] && > "$cache_file"
+ printf '%s\n' "$PROGRAM_NAME: \`$target\` is not a directory." >&2
+ exit 2
+ fi
+
+ [ -n "$2" ] && prompt="$2"
+ # If the prompt is the same as the target, uset the prompt so that it can
+ # update. This is useful if you set a prompt in your configuration file but
+ # want to use the default prompt
+ if [ -n "$prompt" ] && [ "$(realpath -s "$prompt")" = "$target" ]; then
+ unset prompt
+ fi
+}
+
+main "$@"