#!/usr/bin/env ruby

require 'sary'
require 'getopts'
 
include Sary

def print_usage
  $stderr.print <<HELP
Usage: searcher [options] <pattern> <file>
  -c,       only print a count of occurrences
  -i,       ignore case distinctions
  -l,       sort in lexicographical order
  -A NUM,   print NUM lines of trailing context
  -B NUM,   print NUM lines of leading context
  -C NUM,   print NUM lines of output context
  -s TAG,   print tagged region. set start tag to TAG 
  -e TAG,   print tagged region. set end tag to TAG
HELP
end

def grep_lines(filename, pattern)
  searcher = Searcher.new(filename)
  ret = if $OPT_i then
	  searcher.icase_search(pattern)
	else
	  searcher.search(pattern)
	end
  if ret
    if !$OPT_l
      searcher.sort_occurrences
    end

    separator = ""
    b = if $OPT_B then separator = "--\n"; $OPT_B.to_i else 0 end
    a = if $OPT_A then separator = "--\n"; $OPT_A.to_i else 0 end
    if $OPT_C.to_i != 0
      a = b = $OPT_C.to_i
      separator = "--\n"
    end

    sep = ""
    searcher.each_context_lines(b, a) {|text|
      print sep + text
      sep = separator
    }
  end
end

def count(filename, pattern)
  searcher = Searcher.new(filename)
  if searcher.search(pattern)
    print searcher.count_occurrences, "\n"
  else
    print "0\n"
  end
end

def grep_tagged_region(filename, pattern, stag, etag)
  searcher = Searcher.new(filename)
  if searcher.search(pattern)
    if !$OPT_l
      searcher.sort_occurrences
    end

    sep = ""
    searcher.each_tagged_region(stag, etag) {|text|
      print sep + text + "\n"
      sep = "--\n"
    }
  end
end

#---

unless getopts("cil", "A:", "B:", "s:", "e:", "C:0", "help")
  $stderr.puts("rsary: illegal option")
  print_usage
  exit(2)
end

if $OPT_help
  print_usage
  exit(2)
end

if ARGV.size < 2
  $stderr.puts("rsary: too few arguments")
  print_usage
  exit(2)
end

pattern = ARGV.shift
filename = ARGV.shift

if $OPT_c
  count(filename, pattern)
elsif $OPT_s and $OPT_e
  grep_tagged_region(filename, pattern, $OPT_s, $OPT_e)
else
  grep_lines(filename, pattern)
end

exit(0)
