#!/usr/bin/perl

# usConstitutionSearch:
# This script allows you to search the text of the US constitution
# (as provided by http://www.usconstitution.net/const.txt)
# for a search term (can be a regular expression if you like).
# It expects at least one command-line argument specifying the search term.
# It shows the matching lines with a few lines of context before and after.
# You can specify how many lines of context are shown via the (optional)
# second command-line argument (an integer). By default, 2 lines of context
# are shown.
# Examples of use:
# usConstitutionSearch religion
# usConstitutionSearch amendment 5
# usConstitutionSearch people 0
#
# Cameron Hayne (macdev@hayne.net)  April 2011

use strict;
use warnings;
use LWP::Simple;

die "usage: $0 searchTerm [numContextLines]\n" unless @ARGV >= 1;
my $searchTerm = shift @ARGV;
my $numContextLines = (@ARGV ? shift @ARGV : 2);

# get the text of the document:
my $url = "http://www.usconstitution.net/const.txt";
my $contents = get($url) or die "Failed to download from $url: $!";
my @lines = split(/\r?\n/, $contents);
my $numLines = scalar(@lines);
my $start = "We the People";
my $startLineNum = -1;

# find the matching lines:
my %lineNums;
for (my $i = 0; $i < $numLines; $i++)
{
    $_ = $lines[$i];
    if ($startLineNum < 0)
    {
        if (/^\s*$start/oi)
        {
            $startLineNum = $i;
        }
        else
        {
            next; # skip lines before the start
        }
    }

    if (/$searchTerm/oi)
    {
        $lineNums{$i} = 1;
    }
}

# fill in context lines:
for my $lineNum (keys(%lineNums))
{
    for (my $i = 1; $i <= $numContextLines; $i++)
    {
        $lineNums{$lineNum - $i} = 1 if ($lineNum - $i) >= $startLineNum;
        $lineNums{$lineNum + $i} = 1 if ($lineNum + $i) < $numLines;
    }
}

# show the matching lines (with context)
for my $lineNum (sort {$a <=> $b} keys %lineNums)
{
    print "$lines[$lineNum]\n";
    print "--------------------------\n" unless $lineNums{$lineNum + 1};
}

