#!/usr/bin/perl
# Filename:	manwhich
# Author:	David Ljung Madison <DaveSource.com>
# See License:	http://MarginalHacks.com/License
# Description:	A sloppy joe meal.  No wait, that's "Manwich."
# Description:	Which for man pages, based on $MANPATH, and possibly $MANSECT
use strict;

##################################################
# Setup the variables
##################################################
my $PROGNAME = $0;
$PROGNAME =~ s|.*/||;

# Obey the $MANSECT variable ('man man' :)
my $MANSECT = $ENV{MANSECT};

##################################################
# Usage
##################################################
sub usage {
  foreach my $msg (@_) { print STDERR "ERROR:  $msg\n"; }
  print STDERR "\n";
  print STDERR "Usage:\t$PROGNAME <cmd...>\n";
  print STDERR "\t'which' for man pages.\n";
  print STDERR "\n";
  print STDERR "\tUses \$MANPATH (and optionally \$MANSECT)\n";
  print STDERR "\t-S <sections>	Override \$MANSECT value\n";
  print STDERR "\n";
  print STDERR "\tcmd can be a regexp, if desired\n";
  print STDERR "\n";
  print STDERR "\tSee 'man man' for info on man pages\n";
  print STDERR "\n";
  exit -1;
}

sub parse_args {
  my @files;
  while (my $arg=shift(@ARGV)) {
    if ($arg =~ /^-h$/) { usage(); }
    if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; }
    if ($arg =~ /^-S$/) { $MANSECT = shift(@ARGV); next; }
    if ($arg =~ /^-/) { usage("Unknown option: $arg"); }
    push(@files,$arg);
  }
  usage("No man pages defined") unless @files;

  # Turn MANSECT into an regexp
  if ($MANSECT) {
    $MANSECT =~ s/:/|/g;
    $MANSECT = "($MANSECT)";
  }

  @files;
}

sub debug {
  return unless $MAIN::DEBUG;
  foreach my $msg (@_) { print STDERR "[$PROGNAME] $msg\n"; }
}

##################################################
# Main code
##################################################
sub manpage {
  my ($man,@cmds) =@_;
  # Use $MANSECT (allows env var specification of sections to search)
  return grep($man =~ /^$_\.$MANSECT(.gz|.tgz|.bz)?$/, @cmds) if ($MANSECT);
  # Sections are:  .man, .man.gz, .1, .1.gz, .1n, .1x, etc....
  return grep($man =~ /^$_\.(\d+[lnbx]?|man)(.gz|.tgz|.bz)?$/, @cmds);
}

sub check_dir {
  my ($dir,@cmds) = @_;

  opendir(DIR,$dir) || die("[$PROGNAME] Couldn't read directory [$dir]\n");
  my @man = grep(!/^\.{1,2}$/ && manpage($_,@cmds), readdir(DIR));
  #my @man = grep(!/^\.{1,2}$/ && /\..*\D[^x]$/ && !/\.\d+$/, readdir(DIR));
  closedir(DIR);

  return undef unless @man;

  foreach ( @man ) { print "$dir/$_\n"; }
  1;
}

sub check_man {
  my ($dir,@cmds) = @_;

  # In case it's wrongly placed in this directory
  check_dir($dir,@cmds);

  # Now check the subdirectories
  opendir(DIR,$dir) || die("[$PROGNAME] Couldn't read directory [$dir]\n");
  my @dirs = grep(!/^\.{1,2}$/ && -d "$dir/$_", readdir(DIR));
  closedir(DIR);

  map { check_dir("$dir/$_",@cmds); } @dirs;
}

sub find_man {
  my (@cmds) = @_;
  map { check_man($_,@cmds); } split(':',$ENV{MANPATH});
}

sub main {
  my (@cmds) = parse_args;
  my @found = find_man(@cmds);
  die("[$PROGNAME] Man page not found\n") unless grep($_, @found);
}
main();
