#!/usr/bin/env bash MUTDROP_PATH=/tmp/tdrop_"$USER" # shellcheck disable=SC2174 mkdir -p "$MUTDROP_PATH" -m 700 print_help() { echo " usage: tdrop [options] [program options ...] or 'current' or one of 'auto_show'/'auto_hide'/'toggle_auto_hide' or 'hide_all' options: -h height specify a height for a newly created term (default: 45%) -w width specify a width for a newly created term (default: 100%) -x pos specify x offset for a newly created term (default: 0) -y pos specify y offset for a newly created term (default: 1, see man) -s name name for tmux/tmuxinator/tmuxifier session (supported terminal required) -n num num or extra text; only needed if for the purpose of using multiple dropdowns of same program -c cmd provide a pre-create command -C cmd provide a post-create command -l cmd provide a command to float the window before it is mapped -L cmd provide a command to float the window after it is mapped -p cmd provide a pre-map command -P cmd provide a post-map command -u cmd provide a pre-unmap command -U cmd provide a post-unmap command -d XxY give decoration/border size to accurately restore window position; only applicable with auto_show -S cmd can be used to fix saved geometry with auto_hide; see manpage -i cmd provide a command to detect whether the current window is a floating window; on applicable with auto_hide -f flags specify flags/options to be used when creating the term or window (e.g. -f '--title mytitle'; default: none). NOTE: This flag is deprecated. Specify flags after the program name instead. This flag may be removed in the future. Caution: if there is a tmux session specified (with -s), the option to execute a program (usually -e for terminal programs) is implicitly added by tdrop -a automatically detect window manager and set relevant options (e.g. this makes specifying -l/-L, -d, and -i uneccessary for supported WMs) (default: false) -m for use with multiple monitors and only with dropdowns (i.e. not for auto_show or auto_hide); convert percentages used for width or height to values relative to the size of the current monitor and force resizing of the dropdown when the monitor changes (default: false) -t use mouse pointer location for detecting which monitor is the current one --wm set the window manager name to mimic another window manager (for use with -a) --class name manually specify the class of the window (can be obtained with xprop) --name name set a new name for the dropdown window --clear clear saved window id; useful after accidentally make a window a dropdown (e.g. '$ tdrop --clear current') --no-cancel don't cancel auto-showing (default is to prevent this when manually toggling a window after it is auto-hidden) --timeout set the timeout (in seconds) that tdrop will wait for a window to appear before giving up in case the program fails to start (default: 10) --help print help See man page for more details. " } error() { echo >&2 "$@" | tee -a "$MUTDROP_PATH"/log exit 1 } # * Default Options and Option Parsing # xdotool can take percentages; cannot take decimal percentages though width="100%" height="45%" xoff=0 yoff=2 session_name= num= pre_create= post_create= pre_float= post_float= pre_map= post_map= pre_unmap= post_unmap= dec_fix= # NOTE: # pekwm, xfwm4, sawfish, openbox need subtract_when_same to be true # for awesome, fluxbox, blackbox, mutter, fvwm, and metacity, the value # does not matter # set in decoration_settings subtract_when_same= is_floating= program_flags=() clearwid=false cancel_auto_show=true auto_detect_wm=false monitor_aware=false pointer_monitor_detection=false wm= user_set_wm=false class= name= timeout=10 while getopts :h:w:x:y:s:n:c:C:l:L:p:P:u:U:d:S:i:f:-:amt opt do case $opt in h) height=$OPTARG;; w) width=$OPTARG;; x) xoff=$OPTARG;; y) yoff=$OPTARG;; s) session_name=$OPTARG;; n) num=$OPTARG;; c) pre_create=$OPTARG;; C) post_create=$OPTARG;; l) pre_float=$OPTARG;; L) post_float=$OPTARG;; p) pre_map=$OPTARG;; P) post_map=$OPTARG;; u) pre_unmap=$OPTARG;; U) post_unmap=$OPTARG;; d) dec_fix=$OPTARG;; S) subtract_when_same=false;; i) is_floating=$OPTARG;; f) eval "program_flags=($OPTARG)";; a) auto_detect_wm=true;; m) monitor_aware=true;; t) pointer_monitor_detection=true;; -) if [[ $OPTARG =~ ^(auto-detect-wm|monitor-aware|pointer-monitor-detection|clear|no-cancel|help)$ ]] || \ [[ $OPTARG == *=* ]]; then OPTION=${OPTARG%%=*} OPTARG=${OPTARG#*=} else OPTION=$OPTARG # shellcheck disable=SC2124 OPTARG=${@:$OPTIND:1} ((OPTIND++)) fi case $OPTION in height) height=$OPTARG;; width) width=$OPTARG;; x-offset) xoff=$OPTARG;; y-offset) yoff=$OPTARG;; session) session_name=$OPTARG;; number) num=$OPTARG;; pre-create-hook) pre_create=$OPTARG;; post-create-hook) post_create=$OPTARG;; pre-map-float-command) pre_float=$OPTARG;; post-map-float-command) post_float=$OPTARG;; pre-map-hook) pre_map=$OPTARG;; post-map-hook) post_map=$OPTARG;; pre-unmap-hook) pre_unmap=$OPTARG;; post-unmap-hook) post_unmap=$OPTARG;; decoration-fix) dec_fix=$OPTARG;; no-subtract-when-same) subtract_when_same=false;; is-floating) is_floating=$OPTARG;; program-flags) eval "program_flags=($OPTARG)";; auto-detect-wm) auto_detect_wm=true;; monitor-aware) monitor_aware=true;; pointer-monitor-detection) pointer_monitor_detection=true;; wm) wm=$OPTARG user_set_wm=true;; class) class=$OPTARG;; name) name=$OPTARG;; clear) clearwid=true;; no-cancel) cancel_auto_show=false;; timeout) timeout=$OPTARG;; help) print_help;; *) error "Unknown option --$OPTION." \ "Use --help to see available flags.";; esac;; *) error "Unknown option -$OPTARG." \ "Use --help to see available flags.";; esac done shift "$((OPTIND-1))" program=$1 if [[ ${#program_flags[@]} -eq 0 ]]; then program_flags=("${@:2}") fi if [[ -z $program ]]; then error "Program to run is required as a positional argument." \ "For help use -h or --help or see the manpage." fi # check that the program is in PATH if [[ ! $program =~ ^(current|auto_hide|auto_show|toggle_auto_hide|hide_all)$ ]] && \ ! type "$program" &> /dev/null; then error "The program should be in PATH." fi # validate options that require number values if [[ ! $height$width$xoff$yoff =~ ^[0-9%-]*$ ]]; then error "The -h, -w, -x, and -y values must be numbers (or percentages)." fi if [[ -n $dec_fix ]] && [[ ! $dec_fix =~ ^-?[0-9]+x-?[0-9]+$ ]]; then error "The decoration fix value must have form 'num'x'num'." \ "The numbers can be negative or zero." fi # non-user-settable global vars wid= # * Multiple Monitor Automatic Re-Sizing percent_of_total() { # percent total # gawk "BEGIN {printf(\"%.0f\", 0.01*${1%\%}*$2)}" echo $((${1%\%} * ${2} / 100)) } # acts on globals convert_geometry_to_pixels() { total_width=$1 total_height=$2 local minus_width minus_height minus_xoff minus_yoff if [[ $width =~ %$ ]]; then width=$(percent_of_total "$width" "$total_width") elif [[ $width =~ ^- ]]; then minus_width=${width#-} width=$((total_width-minus_width)) fi if [[ $height =~ %$ ]]; then height=$(percent_of_total "$height" "$total_height") elif [[ $height =~ ^- ]]; then minus_height=${height#-} height=$((total_height-minus_height)) fi if [[ $xoff =~ %$ ]]; then xoff=$(percent_of_total "$xoff" "$total_width") elif [[ $xoff =~ ^- ]]; then minus_xoff=${xoff#-} xoff=$((total_width-minus_xoff)) fi if [[ $yoff =~ %$ ]]; then yoff=$(percent_of_total "$yoff" "$total_height") elif [[ $yoff =~ ^- ]]; then minus_yoff=${yoff#-} yoff=$((total_height-minus_yoff)) fi } # meant to set non-local variables split_geometry() { # monitor_geo=$1 # x_begin=$(echo "$monitor_geo" | gawk -F '+' '{print $2}') x_begin=${monitor_geo#*+} x_begin=${x_begin%+*} # y_begin=$(echo "$monitor_geo" | gawk -F '+' '{print $3}') y_begin=${monitor_geo##*+} # x_width=$(echo "$monitor_geo" | gawk -F 'x' '{print $1}') x_width=${monitor_geo%x*} # y_height=$(echo "$monitor_geo" | gawk -F 'x|+' '{print $2}') y_height=${monitor_geo#*x} y_height=${y_height%%+*} } update_geometry_settings_for_monitor() { # 1. Correctly interpret width/height percentages when there exist multiple # monitors so an initially created dropdown is the correct size (xdotool # would create a dropdown the width of all screens for 100% width) # 2. Force resize the dropdown to the correct percentage of the current # monitor IF the monitor has changed since the last time the dropdown # was used # it is conceivable that a user may want to use -m but not -a, so # get the wm from within this function local current_monitor if [[ $wm == bspwm ]]; then current_monitor=$(bspc query --names --monitors --monitor) elif [[ $wm == i3 ]]; then # TODO use jq if installed # I'd rather not make jq a dependency current_monitor=$(i3-msg -t get_workspaces | sed 's/{"num"/\n/g' | \ gawk -F ',' '/focused":true/ {sub(".*output",""); gsub("[:\"]",""); print $1}') fi local monitor_geo x_begin y_begin x_width y_height if [[ -n $current_monitor ]]; then monitor_geo=$(xrandr --current | \ gawk "/^$current_monitor/ {gsub(\"primary \",\"\"); print \$3}") split_geometry "$monitor_geo" else local current_x current_y monitors_info x_end y_end if ! $pointer_monitor_detection; then # determine current monitor using active window local wid wininfo wid=$(xdotool getactivewindow) if [[ -z $wid ]]; then # will try again after remapping or creating the dropdown return 1 fi wininfo=$(xwininfo -id "$wid") current_x=$(echo "$wininfo" | gawk '/Absolute.*X/ {print $4}') current_y=$(echo "$wininfo" | gawk '/Absolute.*Y/ {print $4}') else # shellcheck disable=SC2034 local X Y SCREEN WINDOW # determine current monitor using pointer location eval "$(xdotool getmouselocation --shell)" current_x=X current_y=Y fi monitors_info=$(xrandr --current | gawk '/ connected/ {gsub("primary ",""); print}') while read -r monitor; do monitor_geo=$(echo "$monitor" | gawk '{print $3}') if [[ $monitor_geo =~ ^[0-9]+x[0-9]+\+[0-9]+\+[0-9]+$ ]]; then split_geometry "$monitor_geo" x_end=$((x_begin+x_width)) y_end=$((y_begin+y_height)) if [[ $current_x -ge $x_begin ]] && [[ $current_x -lt $x_end ]] && \ [[ $current_y -ge $y_begin ]] && [[ $current_y -lt $y_end ]]; then # current_monitor=$(echo "$monitor" | gawk '{print $1}') current_monitor=${monitor%% *} break fi fi done <<< "$monitors_info" fi # convert w/h/x/y percentages/negatives to pixels convert_geometry_to_pixels "$x_width" "$y_height" # update x and y offsets, so that will appear on correct screen # (required for some WMs apparently, but not for others) ((xoff+=x_begin)) ((yoff+=y_begin)) } map_and_reset_geometry() { xdotool windowmap "$wid" windowmove "$wid" "$xoff" "$yoff" \ windowsize "$wid" "$width" "$height" 2> /dev/null } # * WM Detection and Hooks set_wm() { if ! $user_set_wm && $auto_detect_wm; then local id id=$(xprop -root -notype _NET_SUPPORTING_WM_CHECK) id=${id##* } # xfwm4 and fvwm at least will give two names (hence piping into head) wm=$(xprop -notype -id "$id" _NET_WM_NAME | head -n 1) wm=${wm##* } wm=${wm//\"/} fi } decoration_settings() { if [[ -z $subtract_when_same ]]; then if $auto_detect_wm \ && [[ $wm =~ ^(Mutter|GNOME Shell|bspwm|i3|GoomwW)$ ]]; then subtract_when_same=false else subtract_when_same=true fi fi if [[ -z $dec_fix ]] && $auto_detect_wm; then # settings for stacking/floating wms where can't get right position # easily from xwininfo; take borders into account if [[ $wm == Blackbox ]]; then dec_fix="1x22" elif [[ $wm =~ ^(Mutter|GNOME Shell)$ ]]; then dec_fix="-10x-8" elif [[ $wm =~ ^(Mutter \(Muffin\))$ ]]; then dec_fix="-9x-8" fi fi } set_class() { if [[ -z $class ]]; then if [[ $program =~ ^emacsclient ]]; then class=emacs elif [[ $program =~ ^google-chrome ]]; then class=google-chrome elif [[ $program == st ]]; then class=st-256color elif [[ $program == gnome-terminal ]]; then class=Gnome-terminal elif [[ $program =~ ^urxvt.* ]]; then class=urxvt elif [[ $program == xiatec ]]; then class=xiate elif [[ $program == alacritty ]]; then class=Alacritty elif [[ $program == current ]]; then class=$(cat "$MUTDROP_PATH"/current"$num"_class 2> /dev/null) else class=$program fi fi } is_floating() { if [[ -n $is_floating ]]; then eval "$is_floating $1" elif $auto_detect_wm; then if [[ $wm == i3 ]]; then # TODO make sure this returns 1 on failure i3-msg -t get_tree | gawk 'gsub(/{"id"/, "\n{\"id\"")' | \ gawk '/focused":true.*floating":"user_on/ {print $1}' elif [[ $wm == bspwm ]]; then bspc query -T -n | grep '"state":"floating"' else return 0 fi else return 0 fi } pre_float() { if [[ $wm == bspwm ]]; then # newest (using "instance" names) if [[ $class =~ [A-Z] ]]; then bspc rule -a "$class" -o state=floating else bspc rule -a \*:"$class" -o state=floating fi fi } post_float() { if [[ $wm == awesome ]]; then echo 'local awful = require("awful") ; awful.client.floating.set(c, true)' | \ awesome-client elif [[ $wm == i3 ]]; then i3-msg "[id=$wid] floating enable" > /dev/null elif [[ $wm == herbstluftwm ]]; then herbstclient fullscreen on fi } pre_create() { if [[ -n $pre_create ]]; then eval "$pre_create" fi } post_create() { if [[ -n $post_create ]]; then eval "$post_create" fi } pre_map() { float=${1:-true} if [[ $float != false ]]; then if [[ -n $pre_float ]]; then eval "$pre_float" elif $auto_detect_wm; then pre_float fi fi if [[ -n $pre_map ]]; then eval "$pre_map" fi } map_and_post_map() { # always reset geometry map_and_reset_geometry float=${1:-true} if [[ $float != false ]]; then if [[ -n $post_float ]]; then eval "$post_float" elif $auto_detect_wm; then post_float fi fi # need to set geometry again if wasn't previously floating map_and_reset_geometry if [[ -n $post_map ]]; then eval "$post_map" fi } pre_unmap() { if [[ -n $pre_unmap ]]; then eval "$pre_unmap" fi } post_unmap() { if [[ -n $post_unmap ]]; then eval "$post_unmap" fi } unmap() { hide=$1 pre_unmap xdotool windowunmap "$wid" if [[ -z $hide ]]; then if [[ $wm == herbstluftwm ]]; then # TODO should only happen if wasn't previously fullscreen herbstclient fullscreen off fi fi post_unmap } # Old notes: # floating WMs that may move a window after remapping it # pekwm|Fluxbox|Blackbox|xfwm4|Metacity|FVWM|Sawfish|GoomwW|Mutter|GNOME Shell|Mutter \(Muffin\)|KWin|Metacity \(Marco\)|[Cc]ompiz|bspwm # floating WMs that may both move and resize a window after remapping it # Openbox # * General Helper Functions get_class_name() { local class class=$(xprop -id "$1" WM_CLASS 2> /dev/null) class=${class##* } class=${class//\"/} echo "$class" } get_visibility() { xwininfo -id "$1" 2> /dev/null | gawk '/Map State/ {print $3}' } maybe_cancel_auto_show() { if $cancel_auto_show && \ [[ $1 == $(cat "$MUTDROP_PATH"/auto_hidden/wid 2> /dev/null) ]]; then # shellcheck disable=SC2188 > "$MUTDROP_PATH"/auto_hidden/wid fi } program_start() { local program_command tmux_command wid program_command=("$program") if [[ $program == alacritty ]]; then # prevent alacritty from resizing the terminal to 80x24 program_command+=(-d 0 0) fi program_command+=("${program_flags[@]}") if [[ -n $session_name ]]; then session_name=$(printf "%q" "$session_name") tmux_command="tmux attach-session -dt $session_name || \ tmuxifier load-session $session_name || \ tmuxinator start $session_name || \ tmux new-session -s $session_name" # note: st will work with or without the -e flag (like kitty) # note: regular console works with or without quotes, but trinity's # konsole only works without quotes if [[ $program =~ ^(urxvt|alacritty|xiatec|st|lxterminal|qterminal|cool-retro-term|lilyterm|konsole$) ]]; then program_command+=(-e bash -c "$tmux_command") elif [[ $program == kitty ]]; then program_command+=(bash -c "$tmux_command") else program_command+=(-e "\"bash -c $tmux_command\"") fi fi wid=$(xtoolwait -wid "${program_command[@]}") if [[ -n $name ]]; then xdotool set_window --name "$name" "$wid" fi echo "$wid" > "$MUTDROP_PATH/$program$num" echo -n "$wid" } current_create() { # turns active window into a dropdown local wid wid=$(xdotool getactivewindow) echo "$wid" > "$MUTDROP_PATH"/current"$num" get_class_name "$wid" > "$MUTDROP_PATH"/current"$num"_class if [[ -n $name ]]; then xdotool set_window --name "$name" "$wid" fi echo -n "$wid" } wid_toggle() { # used for -m option; at first tdrop assumes that there is a focused window # on the current desktop; if there isn't (and the WM doesn't have some way # to query the current monitor), this will be set to false, and tdrop will # have to find out the current monitor info after opening the dropdown # (currently, using xwininfo to find the position of a window is the only # WM-independent way I know to find out what the current monitor is) local focused_window_exists focused_window_exists=true # deal with percentages/negatives when no -m if ! $monitor_aware; then local total_geo total_width total_height total_geo=$(xwininfo -root | gawk '/geometry/ {gsub("+*",""); print $2}') # total_width=$(echo "$total_geo" | gawk -F 'x' '{print $1}') total_width=${total_geo%x*} # total_height=$(echo "$total_geo" | gawk -F 'x' '{print $2}') total_height=${total_geo#*x} convert_geometry_to_pixels "$total_width" "$total_height" fi # get saved window id if already created local exists visibility # cat to silence error wid=$(cat "$MUTDROP_PATH/$program$num" 2> /dev/null) exists=true if [[ -n $wid ]]; then visibility=$(get_visibility "$wid") # sometimes xwininfo will still report a window as existing hence xprop check if [[ -z $visibility ]] || ! xprop -id "$wid" &> /dev/null; then # window no longer exists exists=false # shellcheck disable=SC2188 > "$MUTDROP_PATH/$program$num" fi else exists=false fi if $exists; then if [[ $visibility =~ ^(IsUnMapped|IsUnviewable)$ ]]; then # visibility will be IsUnMapped on most WMs if the dropdown is open # on another desktop; may also be IsUnviewable xdotool set_desktop_for_window "$wid" "$(xdotool get_desktop)" if [[ $(get_visibility "$wid") == IsUnMapped ]]; then pre_map else xdotool windowactivate "$wid" fi # update here if possible so this doesn't cause a delay # between the window being remapped and resized if $monitor_aware; then update_geometry_settings_for_monitor || \ focused_window_exists=false fi map_and_post_map # cancel auto-show for a window when manually remapping it maybe_cancel_auto_show "$wid" if ! $focused_window_exists; then # need to use dropdown as active window to get monitor info update_geometry_settings_for_monitor # always resize/move; if monitor hasn't changed then it won't be # necessary, but it won't cause problems either map_and_reset_geometry fi else unmap fi else # necessary to deal with negative width or height # if creating on an empty desktop and can't determine the monitor, # must set temporary values for negative width and/or height local original_width original_height if $monitor_aware && ! update_geometry_settings_for_monitor; then focused_window_exists=false if [[ $width =~ ^- ]]; then original_width=$width width=100% fi if [[ $height =~ ^- ]]; then original_height=$height height=100% fi fi # make it pre_create if [[ $program == current ]]; then wid=$(current_create) unmap else pre_map wid=$(program_start) map_and_post_map # update window dimensions if necessary if ! $focused_window_exists; then width=${original_width:-$width} height=${original_height:-$height} update_geometry_settings_for_monitor map_and_reset_geometry fi fi post_create fi } # * Helper Functions for Auto Hiding/Showing get_geometry() { # so that won't float a tiled window later when showing if is_floating "$1" &> /dev/null; then local wininfo x y rel_x rel_y width height wininfo=$(xwininfo -id "$1") x=$(echo "$wininfo" | gawk '/Absolute.*X/ {print $4}') y=$(echo "$wininfo" | gawk '/Absolute.*Y/ {print $4}') rel_x=$(echo "$wininfo" | gawk '/Relative.*X/ {print $4}') rel_y=$(echo "$wininfo" | gawk '/Relative.*Y/ {print $4}') if [[ $subtract_when_same != false ]]; then # behaviour works for most WMs (at least floating ones) x=$((x-rel_x)) y=$((y-rel_y)) else # don't subtract when abs and rel values are the same # necessary for WMs like bspwm and i3 if [[ $x -ne $rel_x ]]; then x=$((x-rel_x)) fi if [[ $y -ne $rel_y ]]; then y=$((y-rel_y)) fi fi width=$(xwininfo -id "$(xdotool getactivewindow)" | \ gawk '/Width/ {print $2}') height=$(xwininfo -id "$(xdotool getactivewindow)" | \ gawk '/Height/ {print $2}') echo -n -e "xoff=$x\nyoff=$y\nwidth=$width\nheight=$height" else # window is not floating; don't bother saving geometry echo -n "false" fi } # set global xoff, yoff, width, and height based on stored values restore_geometry() { local x_fix y_fix eval "$(< "$MUTDROP_PATH"/auto_hidden/geometry)" if [[ -n $dec_fix ]]; then x_fix=$(echo "$dec_fix" | gawk -F "x" '{print $1}') y_fix=$(echo "$dec_fix" | gawk -F "x" '{print $2}') xoff=$((xoff-x_fix)) yoff=$((yoff-y_fix)) fi } toggle_auto_hide() { local no_hide no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null) mkdir -p "$MUTDROP_PATH"/auto_hidden if [[ -z $no_hide ]]; then echo "true" > "$MUTDROP_PATH"/auto_hidden/no_hide else # shellcheck disable=SC2188 > "$MUTDROP_PATH"/auto_hidden/no_hide fi } # * Auto Hiding/Showing auto_hide() { local no_hide no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null) if [[ -z $no_hide ]]; then wid=$(xdotool getactivewindow) mkdir -p "$MUTDROP_PATH"/auto_hidden echo "$wid" > "$MUTDROP_PATH"/auto_hidden/wid get_class_name "$wid" > "$MUTDROP_PATH"/auto_hidden/class get_geometry "$wid" > "$MUTDROP_PATH"/auto_hidden/geometry unmap hide fi } auto_show() { local no_hide no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null) if [[ -z $no_hide ]]; then local was_floating wid=$(< "$MUTDROP_PATH"/auto_hidden/wid) class=$(< "$MUTDROP_PATH"/auto_hidden/class) was_floating=$(< "$MUTDROP_PATH"/auto_hidden/geometry) restore_geometry "$wid" pre_map "$was_floating" map_and_post_map "$was_floating" fi } # * Hide All hide_all() { shopt -s nullglob dotglob local dropdowns dropdowns=("$MUTDROP_PATH"/*) for dropdown in "${dropdowns[@]}"; do # cat to silence errors wid=$(cat "$dropdown" 2> /dev/null) unmap "$wid" 2> /dev/null done shopt -u nullglob dotglob } # * Main # ** Setup set_wm decoration_settings set_class # ** Primary Action if $clearwid; then # shellcheck disable=SC2188 > "$MUTDROP_PATH/$program$num" elif [[ $program == toggle_auto_hide ]]; then toggle_auto_hide elif [[ $program == auto_hide ]]; then auto_hide elif [[ $program == auto_show ]]; then auto_show elif [[ $program == hide_all ]]; then hide_all else wid_toggle fi # vim is dumb # vim: set ft=sh noet: