#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Term::ANSIColor qw(BOLD ON_YELLOW RED GREEN MAGENTA CYAN YELLOW RESET); use URI::Escape 'uri_escape'; use HTML::Entities 'decode_entities'; use LWP::UserAgent; use XML::LibXML; use constant { URL_BASE => 'http://www.google.com/codesearch/feeds/search', TIMEOUT => 3, DEFAULT_START_INDEX => 1, DEFAULT_MAX_RESULT => 5, DEFAULT_MAX_MATCH => 3, }; sub color { our $color; return $color ? $_[0] : ""; } sub cleanup_content { my ($str, $keyword) = @_; $str =~ s/^
]+)?>|<\/pre\s*>//g;
decode_entities($str);
my $hilighted = color(BOLD)
. color(ON_YELLOW)
. color(RED)
. $keyword
. color(color(RESET))
;
$str =~ s/$keyword<\/b>/$hilighted/ig;
return $str;
}
my (%opt);
Getopt::Long::GetOptions(
'lang=s' => \$opt{'lang'},
"start=i" => \$opt{'start-index'},
"num=i" => \$opt{'max-results'},
"match=i" => \$opt{'max-match'},
"nocolor" => \$opt{'nocolor'},
);
$opt{'start-index'} ||= DEFAULT_START_INDEX;
$opt{'max-results'} ||= DEFAULT_MAX_RESULT;
$opt{'max-match'} ||= DEFAULT_MAX_MATCH;
our $color = defined $opt{'nocolor'} ? 0 : 1;
my $keyword = $ARGV[0];
if (!$keyword) {
die "specify keyword!";
}
my ($query);
{ # create query string
my $lang = (defined $opt{'lang'} && $opt{'lang'}
? ' lang:' . $opt{'lang'} : '');
my $option = join '&', map { sprintf("%s=%s", $_, $opt{$_}) }
qw/start-index max-results/;
$query = sprintf("%s?q=%s&%s", URL_BASE
, uri_escape($keyword . $lang), $option);
}
{ # get and parse search results from Google.
my $ua = new LWP::UserAgent();
$ua->timeout(TIMEOUT);
my $res = $ua->get($query);
if (!$res->is_success()) {
die "search failed. request URI=[$query]";
}
# parse response XML
my ($xmldoc);
eval { $xmldoc = XML::LibXML->new()->parse_string($res->content()); };
if ($@ || !defined $xmldoc) {
die "parse failed. request uri=[$query] [$@]";
}
my @entry_nodes = $xmldoc->findnodes('//*[local-name()="entry"]');
my $match_count = (scalar @entry_nodes);
if (0 == $match_count) {
print "result is empty.\n";
exit;
}
# print lines
foreach my $entry_node (@entry_nodes) {
my $title = $entry_node->findvalue(
'*[local-name()="title"]/text()');
my $updated = $entry_node->findvalue(
'*[local-name()="updated"]/text()');
my $alt_href = $entry_node->findvalue(
'*[local-name()="link"]/@href');
print color(GREEN) . color(BOLD) . "$title" . color(RESET)
. color(GREEN) . ' - ' . $updated . color(RESET) . "\n"
. color(CYAN) . "$alt_href" . color(RESET) . "\n"
;
my @match = $entry_node->findnodes('*[local-name()="match"]');
my $print_count = 0;
MATCH_LOOP:
foreach my $match (@match) {
last MATCH_LOOP if ++$print_count > $opt{'max-match'};
my $content = $match->textContent() || "";
my $line = $match->find('@lineNumber');
print color(MAGENTA) . "line $line" . color(RESET) . "\n"
. cleanup_content($content, $keyword) . "\n\n"
;
}
}
}
__END__
=head1 NAME
google_code_search.pl - search google_code_search with keywords
=head1 SYNOPSIS
google_code_search.pl ap_table_do
google_code_search.pl --lang=perl --num=3 --start=10 uri_escape
=head1 DESCRIPTION
this is the command line script to search Google Code Search.
=head1 OPTIONS
=over 4
=item --lang=
language name (perl, python, lisp...)
=item --start=
start point of search results
=item --num=
=item --match=
=item -nocolor
not use ANSI colors
=back
=head1 AUTHOR
bonar
=cut