#! /bin/bash
# Copyright (C) 2004, 2005 Stephen Bach
# This is the configurator for the program seer from the viewglob package.
#
# viewglob is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# viewglob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with viewglob; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

SCRIPT_NAME="${0##*/}"
export VG_DIR="/usr/lib/viewglob"

# Option defaults.
VG_CONFIG_FILE="$HOME/.viewglobrc"
VG_SHELL_MODE_DEFAULT=bash
VG_DISPLAY_DEFAULT="$VG_DIR/gviewglob"
VG_SHOW_MAX_DEFAULT=500
VG_SORT_STYLE_DEFAULT=ls
VG_DIR_ORDER_DEFAULT=descending
VG_FONT_SIZE_MODIFIER_DEFAULT=0

# We need extended globbing.
shopt -s extglob

vg_usage() {
	cat >&2 << EOF
usage: $SCRIPT_NAME [-d <display program>] [-f <config file>]
                   [-o <shell output file>] [-O <terminal output file]
                   [-p <name|inode>] [-s <ls|windows>] [-z <+/-#>] [-n <##>]
                   [-r <descending|ascending|ascending-pwd-first>]
                   [-b] [-t] [-m] [-w] [ -e <executable>]
-c, --shell-mode            Shell to use (bash or zsh).
-d, --display               Path to a display program to use instead of the
                            default.
-f, --config-file           Alternate config file.
-o, --shell-output          Output a transcript of the shell's output to the
                            given file.
-O, --term-output           Output a transcript of the terminal's input to given
                            file (i.e. the stuff you type into the shell).
-s, --sort-style            File sorting style.
-r, --dir-order             Order in which to list directories in the display.
-z, --font-size-modifier    Increase or decrease the size of text in the
                            display.
-n, --show-max              Maximum number of files to show per directory
                            (you can still force show if max is reached).
-b, --disable-icons         Don't show file/directory icons in display.
-t, --disable-star          Don't show the viewglob asterisk indicator in the
                            shell.
-m, --disable-smart-insert  Always insert escaped filenames.
-w, --show-hidden           Display hidden files by default.
-e, --executable            Alternate shell executable to run
                            (you probably don't need to use this).
-h, --help                  This usage.
-V, --version               Print the version.
EOF

	exit 0
}

vg_error() {
	echo "$SCRIPT_NAME: $1" >&2
	exit $2
}

vg_version() {
cat << EOF
viewglob 1.1.1
Released March 17, 2005
EOF
	exit 0
}

vg_test_shell_mode() {
	if [ "$1" != bash ] && [ "$1" != zsh ]
		then vg_error "Shell mode must be \"bash\" or \"zsh\"" 1
	fi
}

vg_test_executable() {
	if [ ! "$1" ]
		then vg_error "No executable specified" 1
	elif [ ! -x "$1" ]
		then vg_error "$1 is not present or not executable" 1
	fi
}

vg_test_display() {
	if [ ! "$1" ]
		then vg_error "No display program specified" 1
	elif [ ! -x "$1" ]
		then vg_error "$1 is not present or not executable" 1
	fi
}

vg_test_config_file() {
	if [ ! "$1" ]
		then vg_error "No config file specified" 1
	elif [ ! -e "$1" ]
		then vg_error "$1 does not exist" 1
	fi
}

vg_test_output_file() {
	if [ ! "$1" ]
		then vg_error "No output file specified" 1
	fi
}

vg_test_sort_style() {
	if [ "$1" != ls ] && [ "$1" != win ]
		then vg_error "Unknown sort style \"$1\"" 1
	fi
}

vg_test_dir_order() {
	if [ "$1" != descending ] && \
	   [ "$1" != ascending ] && \
	   [ "$1" != ascending-pwd-first ]
		then vg_error "Invalid directory ordering \"$1\"" 1
	fi
}

vg_test_show_max() {
	if [[ "$1" != *([0-9]) ]]
		then vg_error "Argument to show-max must be a real number" 1
	fi
}

vg_test_font_size_modifier() {
	if [[ "$1" != ?([-+])*([0-9]) ]]
		then vg_error "Invalid font size modifier" 1
	fi
}


if [[ -z "$DISPLAY" ]]
	then vg_error "Must be run from a graphical environment" 2
elif [[ "$VG_VIEWGLOB_ACTIVE" = yep ]]
	then vg_error "This shell is already being monitored" 2
fi

# The viewglob initialization script will pick up this variable from the
# environment.
export VG_ASTERISK=yep

# This is an excellent script to replace bash's getopts with one which allows
# long names.  I found it on Google Groups.  It's written by Grigoriy Strokin
# (grg@philol.msu.ru).  The script is also available in the bash package under
# examples/functions/getoptx.bash.
. $VG_DIR/getopt.sh

# Parse the options.
while getoptex "b; c: e: d: f: m; n: o: O: r: s: t; w; h; v; V; z: shell-mode: executable: display: config-file: shell-output: show-hidden; show-max: font-size-modifier: sort-style: dir-order: term-output: disable-star; disable-icons; disable-smart-insert; help; version;" "$@"
	do case "$OPTOPT" in

		b|disable-icons)
			VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -b"
			;;

		c|shell-mode)
			vg_test_shell_mode "$OPTARG"
			VG_SHELL_MODE="$OPTARG"
			;;

		e|executable)
			vg_test_executable "$OPTARG"
			VG_EXECUTABLE="$OPTARG"
			;;

		d|display)
			vg_test_display "$OPTARG"
			VG_DISPLAY="$OPTARG"
			;;

		f|config-file)
			vg_test_config_file "$OPTARG"
			VG_CONFIG_FILE="$OPTARG"
			;;

		m|disable-smart-insert)
			VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -m"
			;;

		o|shell-output)
			vg_test_output_file "$OPTARG"
			VG_SHELL_OUTPUT="$OPTARG"
			;;

		O|term-output)
			vg_test_output_file "$OPTARG"
			VG_TERM_OUTPUT="$OPTARG"
			;;

		s|sort-style)
			[ "$OPTARG" == windows ] && OPTARG=win
			vg_test_sort_style "$OPTARG"
			VG_SORT_STYLE=$OPTARG
			;;

		r|dir-order)
			vg_test_dir_order "$OPTARG"
			VG_DIR_ORDER=$OPTARG
			;;

		t|disable-star)
			VG_ASTERISK=nope
			;;

		z|font-size-modifier)
			vg_test_font_size_modifier "$OPTARG"
			VG_FONT_SIZE_MODIFIER=$OPTARG
			;;

		n|show-max)
			vg_test_show_max "$OPTARG"
			VG_SHOW_MAX=$OPTARG
			;;

		w|show-hidden)
			VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -w"
			;;
		
		h|help) vg_usage ;;

		v|V|version) vg_version ;;

		*) vg_error "invalid argument" 3 ;;
	esac
done
shift $((OPTIND - 1))

if [ "$OPTOPT" = \? ]
	# getopt.sh already emitted an error message.
	then exit 5
fi

# Parse the config file.  These options will not override the command line
# options.
if [ -r "$VG_CONFIG_FILE" ]; then
	while read opt arg; do
		case "$opt" in
			\#*)
				# Ignore comments.
				;;
			shell-mode)
				[[ -z "$VG_SHELL_MODE" ]] && vg_test_shell_mode "$arg" && \
					VG_SHELL_MODE="$arg"
				;;
			display)
				[[ -z "$VG_DISPLAY" ]] && vg_test_display "$arg" && \
					VG_DISPLAY="$arg"
				;;
			executable)
				[[ -z "$VG_EXECUTABLE" ]] && vg_test_executable "$arg" && \
					VG_EXECUTABLE="$arg"
				;;
			disable-icons)
				VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -b"
				;;
			disable-star)
				VG_ASTERISK=nope
				;;
			disable-smart-insert)
				VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -m"
				;;
			compare-mode)
				# Do nothing -- this is for compatibility with old config files.
				;;
			show-max)
				[[ -z "$VG_SHOW_MAX" ]] && vg_test_show_max "$arg" && \
					VG_SHOW_MAX=$arg
				;;
			font-size-modifier)
				[[ -z "$VG_FONT_SIZE_MODIFIER" ]] && \
					vg_test_font_size_modifier "$OPTARG" && \
					VG_FONT_SIZE_MODIFIER=$arg
				;;
			show-hidden)
				VG_DISPLAY_OPTS="${VG_DISPLAY_OPTS} -w"
				;;
			sort-style)
				[ "$arg" == windows ] && arg="win"
				[[ -z "$VG_SORT_STYLE" ]] && vg_test_sort_style "$arg" && \
					VG_SORT_STYLE=$arg
				;;
			dir-order)
				[[ -z "$VG_DIR_ORDER" ]] && vg_test_dir_order "$arg" && \
					VG_DIR_ORDER=$arg
				;;
			*)
				if [[ "$opt" ]]
					then vg_error "unknown option \"$opt\"" 3
				fi
				# Ignore empty lines.
				;;
		esac
	done < "$VG_CONFIG_FILE"
fi


# Set default values for unused variables.
# (VG_SHELL_OUTPUT and VG_TERM_OUTPUT have no defaults).
[[ -z "$VG_SHELL_MODE" ]] && VG_SHELL_MODE="$VG_SHELL_MODE_DEFAULT"
[[ -z "$VG_EXECUTABLE" ]] && VG_EXECUTABLE="$VG_SHELL_MODE"
[[ -z "$VG_DISPLAY" ]] && VG_DISPLAY="$VG_DISPLAY_DEFAULT"
[[ -z "$VG_SHOW_MAX" ]] && VG_SHOW_MAX="$VG_SHOW_MAX_DEFAULT"
[[ -z "$VG_SORT_STYLE" ]] && VG_SORT_STYLE="$VG_SORT_STYLE_DEFAULT"
[[ -z "$VG_DIR_ORDER" ]] && VG_DIR_ORDER="$VG_DIR_ORDER_DEFAULT"
[[ -z "$VG_FONT_SIZE_MODIFIER" ]] && VG_FONT_SIZE_MODIFIER="$VG_FONT_SIZE_MODIFIER_DEFAULT"

if [[ "$VG_SHELL_MODE" = bash ]]; then
	# The bash initialization requires a file.
	VG_SHELL_INIT="$VG_DIR/init-viewglob.bashrc"
else
	# The zsh initialization just requires a directory.
	VG_SHELL_INIT="$VG_DIR"
fi

# The glob-expand flags are not reprocessed by seer.
VG_EXPAND_COMMAND="$VG_DIR/glob-expand"
if [[ "$VG_DIR_ORDER" = descending ]]
	then VG_EXPAND_COMMAND="$VG_EXPAND_COMMAND -d"
elif [[ "$VG_DIR_ORDER" = ascending ]]
	then VG_EXPAND_COMMAND="$VG_EXPAND_COMMAND -a"
elif [[ "$VG_DIR_ORDER" = ascending-pwd-first ]]
	then VG_EXPAND_COMMAND="$VG_EXPAND_COMMAND -p"
fi
VG_EXPAND_COMMAND="$VG_EXPAND_COMMAND --"

# Exec seer.
exec "$VG_DIR"/seer -c "$VG_SHELL_MODE" -e "$VG_EXECUTABLE"     \
                    -f "$VG_CONFIG_FILE"                        \
                    -o "$VG_SHELL_OUTPUT" -O "$VG_TERM_OUTPUT"  \
                    -d "$VG_DISPLAY" $VG_DISPLAY_OPTS           \
                    -n "$VG_SHOW_MAX" -s "$VG_SORT_STYLE"       \
                    -z "$VG_FONT_SIZE_MODIFIER"                 \
                    -i "$VG_SHELL_INIT"                         \
                    -x "$VG_EXPAND_COMMAND"

