#!/usr/bin/env perl
use warnings;
use strict;
our $VERSION = '0.01';
my $word = shift;

# Specify like this because it's easier. We compute the reverse later (i.e.,
# it should be easier on the hacker than on the computer).
#
# Note: 'for' is a keyword for perlpod as well ('=for'), but is listed for
# perlsyn here, as that's more likely to be the intended meaning.
my %found_in = (
    perlop => [
        qw(lt gt le ge eq ne cmp not and or xor s m tr y
          q qq qr qx qw)
    ],
    perlsyn => [qw(if else elsif unless while until for foreach)],
    perlobj => [qw(isa ISA can VERSION)],
    perlsub => [qw(AUTOLOAD BEGIN CHECK INIT END DESTROY)],
    perltie => [
        qw(TIESCALAR TIEARRAY TIEHASH TIEHANDLE FETCH STORE UNTIE
          FETCHSIZE STORESIZE POP PUSH SHIFT UNSHIFT SPLICE DELETE EXISTS
          EXTEND CLEAR FIRSTKEY NEXTKEY WRITE PRINT PRINTF READ READLINE GETC
          CLOSE)
    ],
    perlvar => [
        qw(_ a b 0 1 2 3 4 5 6 7 8 9 ARG STDIN STDOUT STDERR ARGV
          ENV PREMATCH MATCH POSTMATCH LAST_PAREN_MATCH LAST_MATCH_END
          MULTILINE_MATCHING INPUT_LINE_NUMBER NR INPUT_RECORD_SEPARATOR RS
          OUTPUT_AUTOFLUSH OUTPUT_FIELD_SEPARATOR OFS OUTPUT_RECORD_SEPARATOR
          ORS LIST_SEPARATOR SUBSCRIPT_SEPARATOR SUBSEP OFMT FORMAT_PAGE_NUMBER
          FORMAT_LINES_PER_PAGE FORMAT_LINES_LEFT LAST_MATCH_START FORMAT_NAME
          FORMAT_TOP_NAME FORMAT_LINE_BREAK_CHARACTERS FORMAT_FORMFEED
          ACCUMULATOR CHILD_ERROR ENCODING OS_ERROR ERRNO EXTENDED_OS_ERROR
          EVAL_ERROR PROCESS_ID PID REAL_USER_ID UID EFFECTIVE_USER_ID EUID
          REAL_GROUP_ID GID EFFECTIVE_GROUP_ID EGID PROGRAM_NAME COMPILING
          DEBUGGING SYSTEM_FD_MAX INPLACE_EDIT OSNAME OPEN PERLDB
          LAST_REGEXP_CODE_RESULT EXCEPTIONS_BEING_CAUGHT BASETIME TAINT UNICODE
          PERL_VERSION WARNING WARNING_BITS EXECUTABLE_NAME ARGVOUT INC SIG
          __DIE__ __WARN__)
    ],
    perlpod => [
        qw(head1 head2 head3 head4 over item back cut pod begin
          end)
    ],
    perldata => [qw(__FILE__ __LINE__ __PACKAGE__)],

    # We could also list common functions and methods provided by some
    # commonly used modules, like:
    Error      => [qw(try catch with except otherwise finally record)],
    SelfLoader => [qw(__DATA__ __END__ DATA)],
    'Class::MethodMaker' => [
        qw(new new_with_init new_hash_init
          new_hash_with_init singleton new_with_args get_set static_get_set
          get_concat grouped_fields object object_list object_tie_list
          object_tie_hash forward boolean key_attrib key_with_create list
          static_list tie_list hash hash_of_lists tie_scalar tie_hash
          static_hash code method abstract copy deep_copy builtin_class)
    ],
    Storable     => [qw(freeze thaw)],
    Carp         => [qw(carp cluck croak confess shortmess longmess)],
    'Test::More' => [
        qw(plan use_ok require_ok ok is isnt like unlike cmp_ok
          is_deeply diag can_ok isa_ok pass fail eq_array eq_hash eq_set skip
          todo_skip builder SKIP: TODO:)
    ],
    'Getopt::Long' => [qw(GetOptions)],
    'File::Find'   => [qw(find finddepth)],
    'File::Path'   => [qw(mkpath rmtree)],
    'File::Spec'   => [
        qw(canonpath catdir catfile curdir devnull rootdir
          tmpdir updir no_upwards case_tolerant file_name_is_absolute path
          splitpath splitdir catpath abs2rel rel2abs)
    ],
    'File::Basename' => [
        qw(fileparse fileparse_set_fstype basename
          dirname)
    ],
    'File::Temp' => [
        qw(tempfile tempdir tmpnam tmpfile mkstemp mkstemps
          mkdtemp mktemp unlink0 safe_level)
    ],
    'File::Copy' => [qw(copy move cp mv rmscopy)],
);

while (my ($file, $words) = each %found_in) {
    $_ eq $word && run(perldoc => $file) for @$words;
}

# Is it a label (ends with ':')? Do this after %found_in, because there are
# special labels such as 'SKIP:' and 'TODO:' that map to Test::More
$word =~ /^\w+:$/       && run(perldoc => 'perlsyn');
$word =~ /^UNIVERSAL::/ && run(perldoc => 'perlobj');
$word =~ /^CORE::/      && run(perldoc => 'perlsub');

# try it as a module
try_module($word);

# if it contains '::', it's not a function - strip off the last bit and try
# that again as a module
$word =~ s/::(\w+)$// && try_module($word);

# otherwise, assume it's a function
run(qw(perldoc -f), $word);

# if we can require() it, we run perldoc for the module
sub try_module {
    my $module = shift;
    eval "use $module;";
    !$@ && run(perldoc => $module);
}

sub run {
    print "@_\n";
    exec @_;
}
__END__

=head1 NAME

Dist::Joseki - tools for the prolific module author

=head1 SYNOPSIS

None yet (see below).

=head1 DESCRIPTION

None yet. This is an early release; fully functional, but undocumented. The
next release will have more documentation.

=cut

