/* Do not remove the headers from this file! see /USAGE for more info. */

//  Grep - Locate files containing a particular regular expression.
//  Created by Rust, Jul 10, 1995

//:COMMAND
//USAGE grep [-inv] <target> <files>
//
//Locates and displays lines matching specified pattern within specified files.
//
//Flags :
//-i for case insensitive comparison
//-n to display line numbers
//-v to invert slection - ie display lines NOT matching.

inherit CMD;
inherit M_REGEX;
inherit M_GLOB;

private void
stdin_grep(string pattern, mapping flags, string stdin)
{
  string array lines;
  int	bits = 0;
  int	i;

  if(!stdin)
  {
    out("Too few arguments.\nUsage: grep -inv string file(s)\n");
    return;
  }

  if(flags["i"])
    pattern = insensitive_pattern(pattern);
  if(flags["n"])
    bits |= 1;
  if(flags["v"])
    bits |= 2;

  pattern = translate(pattern);
  lines = regexp(explode(stdin, "\n"),pattern, bits);
  if(!sizeof(lines))
  {
    out("No matches.\n");
  } else {
    if(flags["n"])
    {
      for(i = 0;i<sizeof(lines);i++)
        outf(" %d  %s\n", lines[i+1], lines[i++]);
    } else {
        map(map(lines,(:$1+"\n":)), (: out :));
    }
  }
}

private void
main(mixed argv, mapping flags, string stdin)
{
  string file;
  string this_output;
  string pattern;

  pattern = replace_string(argv[0], "/", "\\/");
  if(!argv[1])
  {
    stdin_grep(pattern, flags, stdin);
    return;
  }
  if(flags["v"])
  {
    map(argv[1], (:stdin_grep($(pattern), $(flags), read_file($1)):));
    return;
  }

  argv[1] = decompose(map(argv[1], (:is_directory($1) ?
      glob($1 + ($1[<1] == '/' ? "*" : "/*")): $1:)));

  if(flags["i"])
    pattern = insensitive_pattern(pattern);
  pattern = translate(pattern);
  foreach(file in argv[1])
  {
    if(file_size(file) < 1)
      continue;
    if(file_size(file) > MAX_FILE_SIZE)
    {
      outf("Ignoring file %s - too large!\n", file);
      continue;
    }
    ed_start(file);
    if(flags["n"])
      ed_cmd("n");
    if (catch(this_output = ed_cmd("1,$g/"+pattern+"/p")))
    {
      printf("Warning: %s was too large for LPC to grep.\n", file);
      continue;
    }
    if(this_output && strlen(this_output))
      outf("[%s]:\n%s\n\n", file, this_output);
    ed_cmd("q");
  }
  if(!strlen(get_output()))
    out("No matches found.\n");
}