#!/usr/bin/perl 
#===============================================================================
#
#         FILE:  opt_sum.pl
#
#        USAGE:  ./opt_sum.pl 
#
#  DESCRIPTION:  This is just a little prototype script that will show the options 
#  for a command and turn them into a fish script that will create a completions file.  It will
#  also give a bit of context from the man page to assiste you put in descriptions for the completion
#  options.
#
#      OPTIONS:  ---
# REQUIREMENTS:  ---
#         BUGS:  ---
#        NOTES:  ---
#       AUTHOR:  Ben Staniford (BTS), <ben@staniford.net>
#      COMPANY:  IBM UK
#      VERSION:  1.0
#      CREATED:  21/04/06 11:14:35 BST
#     REVISION:  ---
#===============================================================================


#---------------------------------------------------------------------------
#  Globals
#---------------------------------------------------------------------------
$MAN_PATH = "/usr/share/man/";   # Hack right now, should search through global man path
$DEBUG = 0;
#---------------------------------------------------------------------------
#  Main functions
#---------------------------------------------------------------------------

if (@ARGV < 1) {
	print "Usage: opt_sum <man_page>\n";
	exit 1;
}
my $manpage = $ARGV[0];
my $outfile = "$manpage"."_complete.fish";
open FISHSCRIPT, ">$outfile"; 

main($manpage);

sub main {
	my($manpage)	= @_;

	my $man_file = find_manpage($manpage);

	my %l_options = parse_loptions($man_file);

	print "Long Options List:\n";
	foreach $opt (sort { $b <=> $a } keys %l_options) {
		if (length($opt) == 2) {       # Short option
			print FISHSCRIPT "\n\n# Context for $opt (from man page)\n ".$l_options{$opt};
			print FISHSCRIPT "complete -c $manpage -s $opt -a \"\"";
		} else {
			print FISHSCRIPT "\n\n# Context for $opt (from man page)\n ".$l_options{$opt};
			print FISHSCRIPT "complete -c $manpage -l $opt -a \"\"";
		}
    }

	print "Finished, outputed $outfile\n";
	return ;
}	# ----------  end of subroutine main  ----------


sub find_manpage {
	my ($manpage)	= @_;
	my $man_file;

	#Not the best way to find the man page, but it'll do for now
	for (`find $MAN_PATH`) {
		chomp;
		if (/^.*\/$manpage\..*\.gz/) {
			$man_file = $_;
			last;   #Just find the first one at the moment, for prototype purposes
		}
	}

	if ($man_file eq "") {
		die("Can't find that man page");
	}

	return $man_file;
}	# ----------  end of subroutine find_manpage  ----------

sub parse_loptions {
	my	($man_file)	= @_;
	my %l_options;
	open (MAN_IN, "gzip -dc $man_file |");
	my %l_options;
	my $context;   #Save 5 lines of context after each option we find
	@content = <MAN_IN>;
	$line_count = 0;

	for (@content) {
		chomp;

		my @opts=();

		#Lines that start with a . are groff commands, ignore
		if (/^\./) { $line_count++; next;}

		#Parsing rules for long options
		if (
			/(\\-\\-\w+)(\\-\w+)(\\-\w+)/ ||         # --three-word-option
			/(\\-\\-\w+)(\\-\w+)/         ||         # --two-worder
			/(\\-\\-\w+)/        	                 # --oneworder 
		) 
		{ 
			$a = $b = $c = "";
			$a = $1; $b = $2; $c = $3;
			$a=~s/\\//g; $b=~s/\\//g  ; $c =~s/\\//g;
			push @opts, $a.$b.$c;
		}

		#Parsing rules for short options
		if (/^(\-\w{1})/) { push @opts, $1;}
		if (/\W(\-\w{1})/) { push @opts, $1;}

		#Columated output for debug purposes
		if ($DEBUG == 1) {
			printf "|%-90s|%-15s|%-15s|%-15s|\n", $_, $opts[0], $opts[1], $opts[2];
		}

		if (@opts > 0) {     #If we found any options on this line
			$context="";
			for ($i=0;$i<8;$i++) {
				$context .= $content[$i + $line_count];
			}
			$a = grofify_chunk($context);
			$a =~ s/$opts[0]/$opts[0] /;
			if ($a eq "") { $a = $context; }
			for (@opts) { 
				$l_options{$_} = $a; 
			}
		}

		$line_count++;
	}
	return %l_options;
}	# ----------  end of subroutine parse_loptions  ----------	


sub grofify_chunk {
	my	($chunk) = @_;
	open (GROF, "| groff -a > /tmp/groffed 2>/dev/null");
	print GROF $chunk;
	close GROF;
	open (GROF, "/tmp/groffed");
	$chunk = "";
	while (<GROF>) {
		chomp;
		s/\<-\>/-/g;
		s/\<.*\>//g;
		if ($_ ne "") {
			$chunk .= "# $_\n";
		}
	}
	unlink "/tmp/groffed";
	return $chunk;
}	# ----------  end of subroutine grofify_chunk  ----------
