1#!/usr/local/bin/bash
2
3# herbstcommander.sh - launch herbstluftwm-commands via dmenu
4# Written by Florian Bruhin <me@the-compiler.org>
5
6# To customize dmenu-colors, create a file named "herbstcommander" in your
7# herbstluftwm config-directory, with something like this in it:
8#
9# dmenu_command=(dmenu -i -b -nb '#313131' -nf '#686868' -sb '#454545' -sf '#898989')
10#
11# You can also directly pass dmenu-arguments to this script instead, as long
12# as dmenu_command is undefined.
13
14config_1="$XDG_CONFIG_HOME/herbstluftwm/herbstcommander"
15config_2="$HOME/.config/herbstluftwm/herbstcommander"
16[[ -f "$config_1" ]] && source "$config_1"
17[[ -f "$config_2" ]] && source "$config_2"
18
19dm() {
20    if [[ "${dmenu_command[@]}" ]]; then
21        "${dmenu_command[@]}" "$@"
22    else
23        dmenu -i "$@"
24    fi
25}
26
27hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;}
28prompt=${prompt:-herbstluft: }
29display_reply=${display_reply:-true}
30
31cmd=( "$@" )
32forceexec=0
33
34while :; do
35    dmenu_args=""
36    if [[ "$forceexec" != 1 ]]; then
37        completion=$(hc complete "${#cmd[@]}" "${cmd[@]}")
38        if [[ "$?" = 7 ]] ; then
39            forceexec=1
40        fi
41    fi
42    if [[ "$forceexec" == 1 ]]; then
43        echo "Executing ${cmd[@]}"
44        reply=$(hc "${cmd[@]}")
45        status=$?
46        if [[ "$display_reply" && "$reply" ]]; then
47            dm -p "${cmd[*]}" <<< "$reply" >/dev/null
48        fi
49        exit $status
50    else
51        case "${cmd[*]}" in
52            raise|jumpto|bring)
53                IFS=$'\t' read -ra tags <<< "$(hc tag_status)"
54                i=1
55                completion=$(
56                    wmctrl -l | while read line; do
57                        IFS=' ' read -ra fields <<< "$line"
58                        id=${fields[0]}
59                        tag=${tags[ ${fields[1]} ]}
60                        class=$(xprop -notype -id $id WM_CLASS |
61                            sed 's/.*\?= *//; s/"\(.*\?\)", *"\(.*\?\)".*/\1,\2/')
62                        title=${fields[@]:3}
63                        printf "%-3s %s %-3s [%s] %s\n" "$i)" "$id" "$tag" "$class" "$title"
64                        i=$((i+1))
65                    done
66                )
67
68                dmenu_args="-l 10"
69                ;;
70        esac
71        next=$(dm $dmenu_args -p "${prompt}${cmd[*]}" <<< "$completion")
72        (( $? != 0 )) && exit 125 # dmenu was killed
73        if [[ -z "$next" ]]; then
74            forceexec=1 # empty reply instead of completion
75        else
76            case "${cmd[*]}" in
77                raise|jumpto|bring)
78                    # add the WINID only (second field)
79                    IFS=' ' read -ra fields <<< "$next"
80                    cmd+=( ${fields[1]} )
81                    ;;
82                *)
83                    cmd+=( $next )
84                    ;;
85            esac
86        fi
87    fi
88done
89