view bin/dmenu_filesel @ 13:f73e67cd0b71

filesel: support spaces and optional regex filter
author David Demelier <markand@malikania.fr>
date Wed, 08 Nov 2017 10:12:22 +0100
parents f004b506c789
children ea81d5b2c72e
line wrap: on
line source

#!/bin/sh
#
# dmenu_filesel -- prompt for a file or directory
#
# Copyright (c) 2016-2017 David Demelier <markand@malikania.fr>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

TOOL="filesel"
TOP=$(dirname "$(readlink -f "$0")")

dmt_filesel_usage()
{
    echo "usage: dmenu_filesel [-t file|directory]" 1>&2;
    exit 1
}

dmt_filesel_list()
{
	list="/tmp/dmenutools-$(id -u).filesel_list.txt"
	result="/tmp/dmenutools-$(id -u).filesel_result.txt"

    # Allow '.' only if traget must be directory.
    if [ "${ftype}" = "directory" ]; then
		echo "." > ${result}
    fi

	echo ".." >> ${result}

	# Avoid basename error in case of empty directories.
    if [ -n "$(ls -A "${root}")" ]; then
		find "${root}" -mindepth 1 -maxdepth 1 > ${list}

		# Update the result list.
		cat ${list} | while read n; do
			keep=1

			# Check for optional pattern
			if [ -f "$n" ] && [ -n "${pattern}" ] && ! (echo $n | egrep -q "${pattern}"); then
				keep=0
			fi

			if [ ${keep} -eq 1 ]; then
				echo $(basename "$n") >> ${result}
			fi
		done
    fi

	cat ${result} | sort
	rm -f ${result} ${list}
}

ftype="file"
lines="16"

while getopts "il:t:p:" opt; do
    case ${opt} in
    l)
        lines=${OPTARG}
        ;;
	p)
		pattern="${OPTARG}"
		;;
    t)
        if [ "${OPTARG}" = "f" ] || [ "${OPTARG}" = "file" ]; then
            ftype="file"
        elif [ "${OPTARG}" = "d" ] || [ "${OPTARG}" = "directory" ]; then
            ftype="directory"
        fi
        ;;
    *)
        dmt_filesel_usage
        # NOTREACHED
    esac
done

shift $((OPTIND - 1))

# Start from here.
if [ $# -ge 1 ]; then
    root="${1}/"
else
    root="/"
fi

while [ -z "${selection}" ]; do
    entry="$(dmt_filesel_list | dmenu -p "${root}" -l ${lines})"

    # Abort on empty selection.
    if [ -z "${entry}" ]; then
        exit 1
    fi

    if [ "${entry}" = ".." ]; then
        parent="$(dirname "${root}")"

        if [ "${parent}" = "/" ]; then
            root="/"
        else
            root="${parent}/"
        fi

        continue;
    fi

    # If directory, goes deeper.
    path="${root}${entry}"

    if [ -d "${path}" ]; then
        if [ -r "${path}" ]; then
            root="${path}/"
        else
            continue
        fi
    else
        selection="${path}"
    fi
done

echo "${selection}"