if (word(2 $loadinfo()) != [pf]) { load -pf $word(1 $loadinfo()); return; };

#
# Help replacement written by howl 2003
#
package help;
load addset;

addset help_path str;
set help_path $irclib()/help/;

addset help_window bool;
set help_window off;

addset help_prompt bool;
set help_prompt off;

addset help_pager bool;
set help_pager on;

alias h {help.help $*;};
alias help {help.help $*;};

# help.isdir is stolen more or less from nsx's tabkey script. Thanks nsx!
alias help.isdir (dir) {
	return ${(left(1 $word(2 $stat("$dir"))) & 4)? 1 : 0};
};

alias help.help {
	^local pager,prompt,dir,file,fp,dp,size,win,line,list,name,match,width,pad;
	^local tmp,tmp1,tmp2,tmp3,tmp4,tmp5,var,taken,varlist,unset,clear,padlen;
	^local more,break,nohelp,myinput,oldinput,noparse,helppath,path,root;
	^local nocheck,helpwin,last,realroot,window;
	
	push varlist dir dp file fp line match name pad pager path prompt realroot;
	push varlist win window;

	@ path = getset(help_path);
	@ window = getset(help_window) == [on] ? 1 : 0;
	@ prompt = getset(help_prompt) == [on] ? 1 : 0;
	@ pager = getset(help_pager) == [on] ? 1 : 0;

	@ noparse = nohelp = nocheck = 0;
	
	@ list = [$*];
	push list *;
	while (tmp = shift(list)) {
		if (!noparse && tmp =~ [-*]) {
			switch ($tmp) {
				(-var) (-v) {
					@ var = shift(list);
					@ tmp = aliasctl(assign pmatch help.cache.${var}.*));
					while (tmp2 = shift(tmp)) { 
						^eval @ $after(3 . $tmp2) = $tmp2;
					}
					@ nocheck = 1;
				}
				(-break) {
					@ close($fp);
					@ fp = dp = file = dir = [];
				}
				(-newhelp) {
					^local realroot,name,line,match,root,file,dir,dp,fp;
					^local nocheck 0;
				}
				(-kill) {
					@ tmp = shift(list);
					if (tmp != [] && tmp != [*] && numwords($aliasctl(assign pmatch help.cache.${tmp}.*)) == 0) {
						xecho -say -b -c -- HELP: No such cache: $tmp;
						return;
					};
					if (tmp == [*]) {
						fe ($aliasctl(assign pmatch help.cache.*.fp)) tmp2 {
							@ tmp2 = aliasctl(assign get $tmp2);
							if (tmp2 != -1 && tmp2 != []) {
								@ tmp3 = close($tmp2);
							};
						};
						fe ($aliasctl(assign pmatch help.cache.*.win)) tmp2 {
							if (aliasctl(assign get ${tmp2}dow) == 1) {
								@ tmp2 = aliasctl(assign get $tmp2);
								if (0 < tmp2 && windowctl(GET $tmp2 REFNUM) != []) {
									^window $tmp2 kill;
								};
							};
						};
						fe ($aliasctl(assign pmatch help.cache.*.*)) tmp2 {
							^assign -$tmp2;
						};

					} else {
						@ tmp2 = aliasctl(assign get help.cache.${tmp}.fd);
						if (tmp2 != -1 && tmp2 != []) {
							@ tmp3 = close($tmp2);
						};
						@ tmp2 = aliasctl(assign get help.cache.${tmp}.win);
						if (0 < tmp2 && windowctl(GET $tmp2 REFNUM) != [] && aliasctl(assign get help.cache.${tmp}.window) == 1) {
							^window $tmp2 kill;
						};
						fe ($aliasctl(assign pmatch help.cache.${tmp}.*)) tmp2 {
							^assign -$tmp2;
						};
					};
					xecho -say -b -c -- HELP: Cleared cache for $tmp;
					return;
				}
				(-path) { @ path = shift(list); }
				(-pager) { @ pager = 1; }
				(-nopager) { @ pager = 0; }
				(-prompt) { @ prompt = 1; }
				(-noprompt) { @ prompt = 0; }
				(-window) { @ window = 1; }
				(-nowindow) { @ window = 0; }
				(-help) {
					xecho -b -c -say -- HELP supports the following switches;
					xecho -b -c -say -- -path *         Override HELP_PATH;
					xecho -b -c -say -- -[no]pager      Override HELP_PAGER;
					xecho -b -c -say -- -[no]prompt     Override HELP_PROMPT;
					xecho -b -c -say -- -[no]window     Override HELP_WINDOW;
					xecho -b -c -say -- Usage: /help <switches> [--] <help topic>;
					return;
				}
				(--) { @ noparse = 1; }
			};
			continue;
		};
		@ noparse = 1;
		if (nocheck) break;
		if (@path == 0 && @root == 0) {
			xecho -say -b -c -- No HELP_PATH set.;
			return;
		};
		if (tmp == [?]) {
			@ tmp = [*];
		};
		if (@root == 0) {
			while (tmp2 = shift(path)) {
				if (fexist($tmp2/$tmp) == 1) {
					@ root = tmp2;
					@ realroot = tmp2;
				} elif (0 < numwords($globi($tmp2/$tmp*))) {
					@ root = tmp2;
					@ realroot = tmp2;
				} else {
					@ break = 1;
					@ nohelp = 1;
					xecho -w ${win == [] ? 0 : win} -b -- No help available on $tmp: Use ? for list of topics.;
					break;
				};
			};
			if (@root == 0) {
				break;
			};
		};
		if (fexist($root/$tmp) == 1) {
			@ tmp2 = [$root/$tmp];
		} elif (numwords($globi($root/$tmp*)) == 1) {
			@ tmp2 = globi($root/$tmp*);
		} elif (numwords($globi($root/$tmp*)) == 0) {
			@ break = 1;
			@ nohelp = 1;
			xecho -w ${win == [] ? 0 : win} -b -- No help available on $tmp: Use ? for list of topics.;
			break;
		} else {
			# More than one match, dispatch and we're done.
			@ match = [${tmp == [*] ? [] : tmp}*];
			echo $tmp;
			@ dir = [$root];
			@ break = 1;
			break;
		};
		@ last = after(${count(/ $root)+1} / $tmp2);
		if (last =~ [*/]) 
			@ last = before(-1 / $last);
		@ name #= (@name > 0 ? [ ] : []) ## last;
		if (!help.isdir($tmp2)) {
			@ file = tmp2;
			@ dir = [];
			@ break = 1;
			@ match = [];
			break;
		} else {
			@ root = [$tmp2];
			@ dir = [];
		};
	};
	if (break != 1 && nocheck != 1) {
		@ dir = root;
		@ match = [*];
	};
	if (dir != []) {
		@ tmp = split(/ $rest($strlen($realroot) $dir));
	} else {
		@ tmp = split(/ $rest($strlen($realroot) $file));
		@ tmp = revw($restw(1 $revw($tmp)));
	};
	@ myinput = tmp;
	@ line = more = nohelp = 0;
	@ pad = (pad == [] ? [ ] : pad);

	if (var == []) {
		@ var = 0;
		until (help[cache][$var][taken] != 1) 
			@ var++;
		@ help[cache][$var][taken] = 1;
	} elif (help[cache][$var][taken] != 1) {
		@ help[cache][$var][taken] = 1;
	};

	if (clear == 1) {
		xecho -say -b -- HELP: Cleared cache;
		fe ($aliasctl(assign pmatch help.cache.*.fp)) fp {
			@ tmp = close($fp);
			# echo close\($fp\) returned $tmp;
		};
		fe ($aliasctl(assign pmatch help.cache.*.*)) tmp {
			^assign -$tmp;
		};
		return;
	};
	if (unset == 1 && var != []) {
		^help.help -kill $var;
	};
	if (!nohelp) {
		if (window && win == []) {
			window new;
			@ win = winnum(0);
		};
		@ size = (size == [] ? winsize($win) : size);
		@ width = (width == [] ? word(0 $geom($win)) -1 : width);
		
		if (file == [] && dir != [] && fexist($dir/$last) == 1 && match == [*]) {
			@ file = [$dir/$last];
		};
		if (dp == [] && file != [] && fexist($file) == 1 && !help.isdir($file)) {
			if (fp == []) {
				@ fp = open("$file" R);
				if (match(*.gz $name)) {
					@ tmp = [$G Help on $before(-1 . $name)];
				} else {
					@ tmp = [$G Help on $name];
				};
				@ line += numlines($width $tmp);
				xecho -w $win -- $tmp;
			};
			if (fp != []) {
				while (!eof($fp) && (pager == 0 || line < size)) {
					@ tmp = read($fp);
					if (tmp =~ [#*] || tmp =~ [!*]) 
						continue;
					^stack push set indent;
					^set indent off;
					@ line += numlines($width $tmp);
					if (!eof($fp)) {
						xecho -w $win -- $tmp;
					};
					^stack pop set indent;
				};
				if (eof($fp)) {
					@ close($fp);
					@ fp = [];
					if (dir != []) {
						@ line++;
						xecho -w $win --;
					};
				};
			};
		};
		if (fp == [] && dir != []) {
			if (dp == []) 
				xecho -b -w $win -- ${name ? [$name choices] : [Choices]} \($match\);
			@ tmp = stripcrap(ALL $globi("$dir/$match"));
			@ tmp1 = strlen($dir/);
			@ tmp2 = maxlen($tmp) - strlen($dir/);
			@ tmp3 = [];
			@ padlen = strlen(ALL $pad);

			while (tmp4 = shift(tmp)) {
				if (tmp4 =~ [*/CVS/] || (dp != [] && dp != tmp4)) 
					continue;
				@ dp = [];
				@ tmp5 = pad($tmp2 " " $rest($tmp1 $tmp4));
				if (tmp3 == []) {
					@ tmp3 = tmp5;
				} elif ((strlen($tmp3) + padlen + tmp2) <= width) {
					@ tmp3 #= pad ## tmp5;
				} else {
					@ line++;
					if (pager == 0 || line < size) {
						xecho -w $win -- $tmp3 ;
						@ tmp3 = tmp5;
					} else {
						@ dp = tmp4;
						@ more = 1;
						break;
					};
				};
			};
			if (more != 1) {
				if (tmp3 != []) {
					@ line++;
					xecho -w $win -- $tmp3;
					@ tmp = dp = [];
				} elif (numwords($tmp) == 0) {
					@ dp = [];
				};
			};
		};
	};
	while (tmp = shift(varlist)) {
		^eval @ help[cache][$var][$tmp] = $tmp;
	};
	if (nohelp == 0 && (fp != [] && !eof($fp)) || more == 1) {
		help.more $var;
	};
	if (fp == [] && dp == []) {
		if (prompt) {
			help.prompt $var $encode(Help?) $encode(-. $unsplit(" " $myinput)) .;
		} else {
			^help.help -kill $var;
		};
	};
};

alias help.more (var, key) {
	if (@key != 1) {
		^eval input_char "*** Hit any key for more. Q to quit, A for all, and F to finish ***" \{ help.more $var \$* \};
		return;
	};
	if (key == [q]) {
		^help.help -var $var -break;
	} elif (key == [a]) {
		^help.help -var $var -nopager;
	} elif (key == [f]) {
		^help.help -var $var -noprompt -nopager;
	} else {
		^help.help -var $var;
	};
};

alias help.prompt (var, prompt, old, ...) {
	^local tmp,input;
	@ old = after(- $decode($old));
	@ prompt = decode($prompt);
	@ tmp = unsplit(" " $afterw(. $old) $prompt);
	if ([$0] == [.]) {
		^eval input "$tmp " help.prompt $var $encode($prompt) $encode(-$unsplit(" " $old)) \\\$*;
		return;
	};
	if ([$0] == []) {
		@ old = revw($restw(1 $revw($old)));
		if (numwords($old) == 0) {
			^help.help -kill $var;
			return;
		};
		@ tmp = unsplit(" " $afterw(. $old) $prompt);
		^eval input "$tmp " help.prompt $var $encode($prompt) $encode(-$unsplit(" " $old)) \\\$*;
	} else {
		help.help -var $var -newhelp $unsplit(" " $afterw(. $old) $*);
	};
};

# howl (2003)
