#!/usr/bin/env bash # Both standalone script and qutebrowser userscript that opens a rofi menu with # all files from the download directory and opens the selected file. It works # both as a userscript and a standalone script that is called from outside of # qutebrowser. # # Suggested keybinding (for "show downloads"): # spawn --userscript ~/.config/qutebrowser/open_download # sd # # Requirements: # - rofi (in a recent version) # - xdg-open and xdg-mime # - You should configure qutebrowser to download files to a single directory # - It comes in handy if you enable downloads.remove_finished. If you want to # see the recent downloads, just press "sd". # # Thorsten Wißmann, 2015 (thorsten` on freenode) # Any feedback is welcome! set -e # open a file from the download directory using rofi DOWNLOAD_DIR=${DOWNLOAD_DIR:-$QUTE_DOWNLOAD_DIR} DOWNLOAD_DIR=${DOWNLOAD_DIR:-$HOME/Downloads} # the name of the rofi command ROFI_CMD=${ROFI_CMD:-rofi} ROFI_ARGS=${ROFI_ARGS:-} msg() { local cmd="$1" shift local msg="$*" if [ -z "$QUTE_FIFO" ] ; then echo "$cmd: $msg" >&2 else echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO" fi } die() { msg error "$*" if [ -n "$QUTE_FIFO" ] ; then # when run as a userscript, the above error message already informs the # user about the failure, and no additional "userscript exited with status # 1" is needed. exit 0; else exit 1; fi } if ! [ -d "$DOWNLOAD_DIR" ] ; then die "Download directory »$DOWNLOAD_DIR« not found!" fi if ! command -v "${ROFI_CMD}" > /dev/null ; then die "Rofi command »${ROFI_CMD}« not found in PATH!" fi rofi_default_args=( -monitor -2 # place above window -location 6 # aligned at the bottom -i -no-custom -format i # make rofi return the index -l 10 -p 'Open download' -dmenu ) crop-first-column() { local maxlength=${1:-40} local expression='s|^\([^\t]\{0,'"$maxlength"'\}\)[^\t]*\t|\1\t|' sed "$expression" } ls-files() { # add the slash at the end of the download dir enforces to follow the # symlink, if the DOWNLOAD_DIR itself is a symlink # shellcheck disable=SC2010 ls -Q --quoting-style escape -h -o -1 -A -t "${DOWNLOAD_DIR}/" \ | grep '^[-]' \ | cut -d' ' -f3- \ | sed 's,^\(.*[^\]\) \(.*\)$,\2\t\1,' \ | sed 's,\\\(.\),\1,g' } mapfile -t entries < <(ls-files) # we need to manually check that there are items, because rofi doesn't show up # if there are no items and -no-custom is passed to rofi. if [ "${#entries[@]}" -eq 0 ] ; then die "Download directory »${DOWNLOAD_DIR}« empty" fi line=$(printf '%s\n' "${entries[@]}" \ | crop-first-column 55 \ | column -s $'\t' -t \ | $ROFI_CMD "${rofi_default_args[@]}" "$ROFI_ARGS") || true if [ -z "$line" ]; then exit 0 fi file="${entries[$line]}" file="${file%%$'\t'*}" path="$DOWNLOAD_DIR/$file" filetype=$(xdg-mime query filetype "$path") application=$(xdg-mime query default "$filetype") if [ -z "$application" ] ; then die "Do not know how to open »$file« of type $filetype" fi msg info "Opening »$file« (of type $filetype) with ${application%.desktop}" xdg-open "$path" &