diff --git a/bin/fqo b/bin/fqo index 2775836..1eca1ba 100644 --- a/bin/fqo +++ b/bin/fqo @@ -1,44 +1,64 @@ -#!/usr/bin/bash -# Fuzzy find a file and then check which package owns it +#!/usr/bin/python3 +"""Fuzzy-find a file and check which package owns it. -declare -r scriptname="fqo" +Dependencies +============ +* fzf +* mlocate +""" -printHelp() { -cat << helpinfo -${scriptname} - fuzzy find a file and then check which package owns it +import argparse +import subprocess -Usage: ${scriptname} [-h] [patterns] +# ========== Constants ========== +# Commands +PACMAN_CMD = '/usr/bin/pacman' +FZF_CMD = '/usr/bin/fzf' +FZF_OPTS = ['--read0', '--select-1', '--exit-0', '--print0'] +LOCATE_CMD = '/usr/bin/locate' +LOCATE_OPTS = ['--all', '--ignore-case', '--null'] +LOCALE = 'utf-8' -Options: - -h, --help print this help page -helpinfo -} -while true; do - case "${1}" in - "-h"|"--help") - printHelp - exit - ;; - --) - shift - break - ;; - -*) - printf '%s\n' "Unknown option: ${1}" >&2 - exit 1 - ;; - *) - break - ;; - esac -done +# ========== Functions ========== +def run_fzf(files): + """Run fzf on a stream of searched files for the user to select. -[[ ! -x '/usr/bin/locate' ]] && echo 'locate is not present' && exit 1 -[[ ! -x '/usr/bin/fzf' ]] && echo 'fzf is not present' && exit 1 -[[ -z "${*}" ]] && printf '%s\n' "No patterns entered" >&2 && exit 1 + :param files: stream of null-terminated files to read + :type files: bytes stream (stdout of a completed process) + :returns: selected file + :rtype: str + """ + selected_file = subprocess.run([FZF_CMD] + FZF_OPTS, + input=files, + stdout=subprocess.PIPE).stdout -file="$(locate --all --ignore-case --null -- "${@}" | fzf --exit-0 --select-1 --read0 --no-mouse)" -[[ ! "${file}" ]] && exit 1 + return selected_file.decode(LOCALE).strip('\x00') -pacman -Qo "${file}" + +def locate_files(patterns): + """Use a locate-based program to locate files, then pass to fzf. + + :param patterns: patterns to pass to locate + :type patterns: list + :returns: path of user-selected file + :rtype: bytes + """ + cmd = [LOCATE_CMD] + LOCATE_OPTS + cmd.extend(patterns) + + return subprocess.run(cmd, capture_output=True).stdout + + +# ========== Main Script ========== +parser = argparse.ArgumentParser() +parser.add_argument('patterns', + nargs='+', + help='file pattern to search for') + +args = parser.parse_args() + +files = locate_files(args.patterns) +selected_file = run_fzf(files) + +subprocess.run([PACMAN_CMD, '-Qo', selected_file]) diff --git a/misc/fqo.sh b/misc/fqo.sh new file mode 100644 index 0000000..2775836 --- /dev/null +++ b/misc/fqo.sh @@ -0,0 +1,44 @@ +#!/usr/bin/bash +# Fuzzy find a file and then check which package owns it + +declare -r scriptname="fqo" + +printHelp() { +cat << helpinfo +${scriptname} - fuzzy find a file and then check which package owns it + +Usage: ${scriptname} [-h] [patterns] + +Options: + -h, --help print this help page +helpinfo +} + +while true; do + case "${1}" in + "-h"|"--help") + printHelp + exit + ;; + --) + shift + break + ;; + -*) + printf '%s\n' "Unknown option: ${1}" >&2 + exit 1 + ;; + *) + break + ;; + esac +done + +[[ ! -x '/usr/bin/locate' ]] && echo 'locate is not present' && exit 1 +[[ ! -x '/usr/bin/fzf' ]] && echo 'fzf is not present' && exit 1 +[[ -z "${*}" ]] && printf '%s\n' "No patterns entered" >&2 && exit 1 + +file="$(locate --all --ignore-case --null -- "${@}" | fzf --exit-0 --select-1 --read0 --no-mouse)" +[[ ! "${file}" ]] && exit 1 + +pacman -Qo "${file}"