#!/usr/bin/env bash

# places-pipemenu - an openbox places pipe menu
# Copyright (C) 2010~2016  John Crawley <john@bunsenlabs.org>
# Copyright (C) 2017~2018  Nathaniel Maia <natemaia10@gmail.com>
#
# forked by manjaro <fhatmanjaroorg>
#
# <menu id="places" label="Places" execute="/START_PATH/to/manjaro-places-pipemenu ~/" />
# or, if you want the "recent files" menu incorporated at the top, use:
# <menu id="places" label="Places" execute="/START_PATH/to/manjaro-places-pipemenu --recent ~/" />
# make sure you have manjaro-recent-files-pipemenu, and enter its START_PATH below.

readonly RECENT_FILES_BIN="/usr/bin/manjaro-recent-files-pipemenu"
readonly XEDITOR="/usr/bin/xed"

if hash pcmanfm &>/dev/null; then
    readonly FILEMANAGER=pcmanfm
else
    readonly FILEMANAGER=thunar
fi

if hash xdg-open &>dev/null; then
    readonly OPEN_CMD=xdg-open
else
    readonly OPEN_CMD=exo-open
fi
readonly SHOW_DOTFILES=".config .local .vim .vimrc .Xresources .Xmodmap .bashrc .zshrc .xinitrc .gtkrc-2.0.mine .xprofile .xsessionrc"
readonly HELP='
manjaro-places-pipemenu is an Openbox Pipe Menu for showing a directory tree
It should normally be called from an openbox menu.

Usage:
    manjaro-places-pipemenu [options] [directory tree root]

Options:
    -h,--help           show this message
    --recent            incorporate a "recent files" submenu
    --open <filepath>   open a file with configured default application
                        (in this case the script will not output a menu)

    If a directory tree root is not specified, $HOME will be used.

Configuration:
    Do not change the script directly - it will be overwritten on updates.
    Copy the script to ~/.local/bin and edit there for per-user changes.

Editable variables and functions, at the top of the file:
    RECENT_FILES_BIN    START_PATH to a script outputting an openbox pipemenu
    FILEMANAGER         command to open folders - any file manager
    OPEN_CMD            default command to open files
    XEDITOR             command to open text files
    open_file()         open files, using commands above, or alternatives
    SHOW_DOTFILES      list of dotfiles to display (they are hidden by default)

    By default, this script will display directories separately, before files.
    To change this behaviour, see NOTE1, NOTE2 and NOTE3 near end of file.
'

open_file() {
    if hash "$OPEN_CMD" &>/dev/null; then
        exec "$OPEN_CMD" "$1"
    elif hash $XEDITOR &>/dev/null; then
        exec "$XEDITOR" "$1"
    elif hash $TERMINAL &>/dev/null; then
        ($TERMINAL -e "$EDITOR $1") &>/dev/null &
    else
        echo "$0 : failed to open $2" ; exit 1
    fi
}

case $1 in
    -h|--help) echo "$HELP" ; exit 0 ;;
    --open) open_file "$2" ;;
    --recent)
        shift
        output='<openbox_pipe_menu>'
        if [[ -x $RECENT_FILES_BIN ]]; then
            output="$output
  <separator label=\"Recently opened...\"/>
  <menu execute=\"$RECENT_FILES_BIN\" id=\"recent\" label=\"files\"/>"
        else
            echo "$0 : cannot find executable script $RECENT_FILES_BIN" >&2
        fi
        ;;
    *) output='<openbox_pipe_menu>'
esac

START_PATH=${1:-$HOME}
START_PATH=${START_PATH%/}

[[ -d $START_PATH ]] || { echo "$0 : $START_PATH is not a directory" >&2 ; exit 1 ; }

# only escape if string needs it
case $START_PATH in
    *\&*|*\<*|*\>*|*\"*|*\'*) pathe=$(sed "s/\&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;s/\"/\&quot;/g;s/'/\&apos;/g;" <<<"$START_PATH") ;;
    *)                        pathe=$START_PATH
esac
case $pathe in
    *\&apos\;*) pathe_apos=$(sed 's/\&apos;/\&apos;\&quot;\&apos;\&quot;\&apos;/g;' <<<"$pathe") ;;
    *)          pathe_apos=$pathe
esac

output="$output
  <separator label=\"$pathe\"/>
  <item label=\"Browse here...\">
    <action name=\"Execute\">
      <command>&apos;$FILEMANAGER&apos; &apos;$pathe_apos&apos;</command>
    </action>
  </item>
  <separator/>"

[[ "$START_PATH" == "$HOME" ]] && DOTFILES="$SHOW_DOTFILES"

for i in $START_PATH/* $DOTFILES; do

    [[ ! -e $i ]] && continue
    shortname=${i##*/}

    case $shortname in
        *\&*|*\<*|*\>*|*\"*|*\'*) shortnamee=$(sed "s/\&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;s/\"/\&quot;/g;s/'/\&apos;/g;" <<<"$shortname") ;;
        *)                        shortnamee=$shortname
    esac
    case $shortnamee in
        *\&apos\;*) shortnamee_apos=$(sed 's/\&apos;/\&apos;\&quot;\&apos;\&quot;\&apos;/g;' <<<"$shortnamee") ;;
        *)          shortnamee_apos=$shortnamee
    esac
    case $shortnamee in
        *_*) shortnamee_label=$(sed 's/_/__/g;' <<<"$shortnamee") ;;
        *)   shortnamee_label=$shortnamee
    esac

    # NOTE1: If you want directories and files listed together
    # change directories_menu="$directories_menu to: files_menu="$files_menu
    if [[ -d $i ]]; then
        directories_menu="$directories_menu
  <menu id=\"$pathe_apos/$shortnamee_apos\" label=\"$shortnamee_label\" execute=\"&apos;$0&apos; &apos;$pathe_apos/$shortnamee_apos&apos;\"/>"
    else
        files_menu="$files_menu
  <item label=\"$shortnamee_label\">
    <action name=\"Execute\">
      <command>&apos;$0&apos; --open &apos;${pathe_apos}/${shortnamee_apos}&apos;</command>
    </action>
  </item>"
    fi
done

# NOTE2: uncomment these 2 lines if you want "Folders" label
output="$output
<separator label=\"Folders\"/>"
[ -n "$directories_menu" ] && { output="${output}${directories_menu}"; }

# NOTE3: uncomment these 2 lines if you want "Files" label
output="$output
<separator label=\"Files\"/>"
[ -n "$files_menu" ] && { output="${output}${files_menu}"; }

output="${output}
</openbox_pipe_menu>
"

printf '%s' "$output"

exit 0
