#!/usr/bin/perl

# $Id: google,v 1.3 2003/02/22 08:42:15 sherzodr Exp $

#---------
# standard libraries
use strict;
use vars qw($VERSION);
use Getopt::Long;
use File::Spec;
use Pod::Usage;
use Text::Wrap;
use FindBin qw($RealBin);

#---------
# non-standard libraries. May need to be installed separately
for ( qw(Net::Google Config::Simple) ) {
  eval "require $_";
  if ( $@ ) {
    die "$0: '$_' doesn't seem to be installed\n";
  }
}

($VERSION) = '$Revision: 1.3 $' =~ m/Revision:\s*(\S+)/;

# parsing command line options
GetOptions(\my %options, "max-results=i", "lr=s", "key=s",
                         "safe-mode",  "starts-at=i", "snippet",
                         "wrap-at=i", "help", "man" );

if ( $options{help} ) {
  pod2usage(-verbose=>1, -exitval=>1, -output=>\*STDOUT);
}
if ( $options{man} ) {
  pod2usage(-verbose=>2, -exitval=>1, -output=>\*STDOUT);
}
unless ( @ARGV ) {
  pod2usage(-verbose=>0, -exitval=>1, -output=>\*STDERR);
}
unless ( defined $ENV{HOME} ) {
  die "$0: 'HOME' environmental variable is not defined\n";
}

#---------
# locating options file
my $options_file = locate_options_file();

#---------
# parsing the file
tie my %Config, "Config::Simple", $options_file;

#---------
# initializing missing options from the file, if possible
for ( qw(max-results lr safe-mode starts-at snippet key) ) {
  $options{$_} ||= $Config{'google.' . $_};
}
unless ( $options{key} ) {
  die "$0: couldn't find your key to google service\n";
}

#---------
# initializing Net::Google
my $service = new Net::Google( key=>$options{key} );
my $search = $service->search();

#----------
# defining query
$search->query(@ARGV);

#---------
# configuring search options
$search->max_results($options{'max-results'}) if $options{'max-results'};
$search->starts_at($options{'starts-at'})     if $options{'starts-at'};
$search->lr($options{lr})                     if $options{lr};
$search->safe(1)                              if $options{'safe-mode'};
$search->ie($options{ie})                     if $options{ie};
$search->oe($options{oe})                     if $options{oe};

# --------
# displaying the results
$Text::Wrap::columns = $options{'wrap-at'} || $Config{'client.wrap-at'} || 72;
my $i = $options{'starts-at'} || 0;
for my $doc ( @{$search->results()} ) {
  my $title = $doc->title();
  $title =~ s/<.*?>//g;
  printf("[%02d] %s\n<URL: %s>\n", ++$i, $title, $doc->URL());
  if ( $options{snippet} ) {
    my $snippet = $doc->snippet();
    $snippet =~ s/<[^>]+>//g;
    print wrap("", "", $snippet), "\n";
  }
  print "\n";
}


#---------
# shortcut for relatively long File::Spec->catfile()
sub catfile {
  return File::Spec->catfile(@_);
}

#---------
# shortcut for relatively long File::Sepc->curdir()
sub curdir {
  return File::Spec->curdir(@_);
}

#---------
# looks for options file
sub locate_options_file {

  my $file = undef;
  for ( catfile($ENV{HOME}, '.google'),
        catfile($ENV{HOME}, '.googlerc'),
        catfile(curdir(),   '.google'),
        catfile(curdir(),   '.googlerc'),
        catfile($RealBin,   '.google'),
        catfile($RealBin,   '.googlerc') ) {
    -e $_ and $file = $_, last;
  }
  unless ( $file ) {
    die "couldn't find option file\n";
  }
  return $file;
}


__END__

=head1 NAME

google - command-line Google interface

=head1 SYNOPSIS

  google [options] keyword(s)
  google [options] keyword(s) site:<URL>
  google [options] link:<URL>
  google [options] related:<URL>
  google [options] info:<URL>
  google --help


=head1 OPTIONS


Following options can be specified either in the command line, or
in google startup file found at ~/.googlerc

=over 4

=item B<--help>

displays the list of available options and exists

=item B<--max-results>

number of results returned in the result set

=item B<--starts-at>

where should the result set start

=item B<--safe-mode>

filter out offensive and adult content

=item B<--snippet>

display brief snippet of the resource

=item B<--lr>

language restrictions

=item B<--ie>

input encoding. Default is utf-8

=item B<--oe>

output encoding. Default is utf-8

=item B<--man>

display full manual of the client

=back

=head1 DESCRIPTION

B<google> is a command-line interface to Google Search. It uses Aaron Straup
Cope's L<Net::Google|Net::Google> library, which in turn, is an interface to Google's SOAP API.

To be able to use this tool, you first need to create an account with Google. It is free.
Visit http://www.google.com/apis/ for details. After creating your account successfully,
you will be provided with a key to use this tool.

=head1 INSTALLATION

  perl Makefile.PL
  make
  make install

The above set of commands will install the library to your B<sitebin> folder. It is
usually /usr/bin/ in some *nix machines. If you do not have write access to this folder,
you can alternatively install in your own ~/bin directory:

  perl Makefile.PL INSTALLSCRIPT=~/bin
  make
  make install

=head1 USING B<google>

Every time you use B<google> to search the Web, you should provide your key with "--key" option.
I know, it gets pretty tedious in no time. That's why we added support for default options file.

B<google> searches for a file called B<.google> or B<.googlerc> in your home directory. If
it can't find any, it looks for those files in your current directory as well as in the directory 
B<google> was installed in.

  [google]
  key=yourLongKeyGoesHere

You can find a more verbose option file in the B<google> distribution folder. Options
provided in the command line will override the ones set in the options file.

=head1 EXAMPLES

  google mod_perl

returns first 10 (unless you overrode it in your options file) results for keyword "mod_perl".

  google --max-results=5 --snippet mod_perl

similar to the first example, but returns first 5 results with snippets.

  google mod_perl site:apache.org

returns first 10 results for mod_perl from apache.org

  google info:perl.com

returns brief information about the resource

  google related:perl.com

returns related resources for perl.com

  google link:cpan.org

returns first 10 resources that have links to cpan.org.

=head1 TODO

Support for Google's spell checker, as well as Google cache

=head1 COPYRIGHT

Copyright (C) 2003 Sherzod B. Ruzmetov. B<google> is free software. You can modify
and/or redistribute it under GNU/Artistic license.

=head1 AUTHOR

Sherzod B. Ruzmetov E<lt>sherzodr@handalak.comE<gt>

=head1 BUGS

For bugs, feed backs and suggestions: E<lt>sherzodr@cpan.comE<gt>

=head1 SEE ALSO

http://www.google.com/apis,
L<Net::Google|Net::Google>,
L<Net::Google::Search|Net::Google::Search>

=cut

