A library for iterating through the lines in a series of files. Very similar to the Python module of the same name.

It allows the programmer to automatically take filenames from the command line arguments (via input and input_state), as well as specify them as a vector directly (input_vec and input_vec_state). The files are opened as necessary, so any files that can't be opened only cause an error when reached in the iteration.

On the command line, stdin is represented by a filename of - (a single hyphen) and in the functions that take a vector directly (e.g. input_vec) it is represented by None. Note stdin is not reset once it has been finished, so attempting to iterate on [None, None] will only take input once unless io::stdin().seek(0, SeekSet) is called between.

The pathify function handles converting a list of file paths as strings to the appropriate format, including the (optional) conversion of "-" to stdin.

Basic

In many cases, one can use the input_* functions without having to handle any FileInput structs. E.g. a simple cat program

for input |line| {
    io::println(line)
}

or a program that numbers lines after concatenating two files

for input_vec_state(pathify([~"a.txt", ~"b.txt"])) |line, state| {
    io::println(fmt!("%u: %s", state.line_num,
                               line));
}

The two input_vec* functions take a vec of file names (where empty means read from stdin), the other two functions use the command line arguments.

Advanced

For more complicated uses (e.g. if one needs to pause iteration and resume it later), a FileInput instance can be constructed via the from_vec, from_vec_raw and from_args functions.

Once created, the each_line (from the std::io::ReaderUtil trait) and each_line_state methods allow one to iterate on the lines; the latter provides more information about the position within the iteration to the caller.

It is possible (and safe) to skip lines and files using the read_line and next_file methods. Also, FileInput implements std::io::Reader, and the state will be updated correctly while using any of those methods.

E.g. the following program reads until an empty line, pauses for user input, skips the current file and then numbers the remaining lines (where the numbers are from the start of each file, rather than the total line count).

let in = FileInput::from_vec(pathify([~"a.txt", ~"b.txt", ~"c.txt"],
                                         true));

for in.each_line |line| {
    if line.is_empty() {
        break
    }
    io::println(line);
}

io::println("Continue?");

if io::stdin().read_line() == ~"yes" {
    in.next_file(); // skip!

    for in.each_line_state |line, state| {
       io::println(fmt!("%u: %s", state.line_num_file,
                                  line))
    }
}

Struct FileInput

pub struct FileInput {
    priv fi: @mut FileInput_,
}

Struct FileInputState

pub struct FileInputState {
    current_path: Option<Path>,
    line_num: uint,
    line_num_file: uint,
}

A summary of the internal state of a FileInput object. line_num and line_num_file represent the number of lines read in total and in the current file respectively. current_path is None if the current file is stdin.

Implementation for FileInput

Method from_vec

fn from_vec(files: ~[Option<Path>]) -> FileInput

Create a FileInput object from a vec of files. An empty vec means lines are read from stdin (use from_vec_raw to stop this behaviour). Any occurence of None represents stdin.

Method from_vec_raw

fn from_vec_raw(files: ~[Option<Path>]) -> FileInput

Identical to from_vec, but an empty files vec stays empty. (None is stdin.)

Method from_args

fn from_args() -> FileInput

Create a FileInput object from the command line arguments. "-" represents stdin.

Method next_file

fn next_file(&self) -> bool

Skip to the next file in the queue. Can fail when opening a file.

Returns false if there is no more files, and true when it successfully opens the next file.

Method each_line_state

fn each_line_state(&self, f: &fn(&str, FileInputState) -> bool) -> bool

Apply f to each line successively, along with some state (line numbers and file names, see documentation for FileInputState). Otherwise identical to lines_each.

Method state

fn state(&self) -> FileInputState

Retrieve the current FileInputState information.

Implementation of io::Reader for FileInput

Method read_byte

fn read_byte(&self) -> int

Method read

fn read(&self, buf: &mut [u8], len: uint) -> uint

Method eof

fn eof(&self) -> bool

Method seek

fn seek(&self, offset: int, whence: io::SeekStyle)

Method tell

fn tell(&self) -> uint

Function input

fn input(f: &fn(&str) -> bool) -> bool

Iterate directly over the command line arguments (no arguments implies reading from stdin).

Fails when attempting to read from a file that can't be opened.

Function input_state

fn input_state(f: &fn(&str, FileInputState) -> bool) -> bool

Iterate directly over the command line arguments (no arguments implies reading from stdin) with the current state of the iteration provided at each call.

Fails when attempting to read from a file that can't be opened.

Function input_vec

fn input_vec(files: ~[Option<Path>], f: &fn(&str) -> bool) -> bool

Iterate over a vector of files (an empty vector implies just stdin).

Fails when attempting to read from a file that can't be opened.

Function input_vec_state

fn input_vec_state(files: ~[Option<Path>],
                   f: &fn(&str, FileInputState) -> bool) -> bool

Iterate over a vector of files (an empty vector implies just stdin) with the current state of the iteration provided at each call.

Fails when attempting to read from a file that can't be opened.

Function pathify

fn pathify(vec: &[~str], stdin_hyphen: bool) -> ~[Option<Path>]

Convert a list of strings to an appropriate form for a FileInput instance. stdin_hyphen controls whether - represents stdin or a literal -.