new object $reads_lines: $utilities;

var $root inited = 1;
var $reads_lines line_buffer = 0;
var $reads_lines end_strings = 0;
var $reads_lines parser = 0;
var $reads_lines task = 0;

public method .tell() {
  arg @ignored;
};

public method .parse_line() {
  arg line;

  // If a parser is defined, don't try to command-match, just pass it through to the parser
  if (parser) {
    return .(parser)(line);
  } else {
    return (> pass(line) <);
  }
};

public method .read_lines() {
  arg @args;
  var prompt, ret;

  prompt = (| args[1] |) || "Receiving input.  Enter \".\" to finish or \"@abort\" to abort.";
  end_strings = [((| args[2] |) || "."), ((| args[3] |) || "@abort")];
  line_buffer = [];
  parser = '_read_line;
  task = task_id();
  
  if (prompt) {
    .tell(prompt);
  }

  // Now, suspend the task.  ._read_line will resume it when it's done
  catch any {
    (> suspend() <);
  } with {
    parser = 0;
    rethrow(error());
  }
  parser = 0;
  if (line_buffer == 0) {
    .tell("** Aborted **; Text thrown away.");
  }
  return line_buffer;
};

private method ._read_line() {
  arg line;
  var pos;

  if ((pos = (line in end_strings))) {
    if (pos > 1) {
      line_buffer = 0;
    }
    $scheduler.resume(task);
  } else {
    line_buffer += [line];
  }
};