regex_minigrep 1.0.0

A basic grep function
Documentation
extern crate regex;

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path;

/// Configuration from arguments
struct Config {
    target: path::PathBuf,
    regex: regex::Regex,
}

/// Create a new `Config` if arguments are valid
impl Config {
    fn new(args: Vec<String>) -> Result<Config, Box<Error>> {
        let config = Config {
            target: path::PathBuf::from(&args[1]),
            regex: regex::Regex::new(&args[2])?,
        };
        if !config.target.is_file() {
            return Err(From::from("Path does not lead to a file"));
        }
        Ok(config)
    }
}

/// From an argument vector it returns a formatted string with the search results
///
/// # Example
///
/// ```
/// // Input test.txt contains:
/// // This function will never return and will immediately
/// // terminate the current process. The exit code is passed
/// //
/// // This Note that because this function never returns, and that
/// // it terminates the process, no destructors on the current
///
/// let args = !["/path/", "target_file.txt", "This"];
///
/// match regex_minigrep::grep(args) {
///     Err(e) => {
///         println!("Error while running MiniGrep: {}", e);
///         process::exit(1);
///     }
///     Ok(content) => print!("{}", content),
/// }
///
/// // Output to the terminal will be:
/// // This function will never return and will immediately
/// // This Note that because this function never returns, and that
/// ```

pub fn grep(args: Vec<String>) -> Result<String, Box<Error>> {
    if args.len() < 3 {
        print_help();
        println!("{:?}", args);
        Err(From::from("Invalid length of arguments"))
    } else if args.len() > 3 {
        print_help();
        println!("{:?}", args);
        Err(From::from("Invalid length of arguments"))
    } else {
        let config: Config = Config::new(args)?;
        let contents = read_file(&config.target)?;
        let contents = contents.split("\n");
        let mut result: String = String::from("");
        for s in contents {
            let mut pushed = false;
            for cap in config.regex.captures_iter(&s) {
                if cap.len() > 0 && !pushed {
                    result.push_str(s);
                    pushed = true;
                }
            }
            if pushed {
                result.push_str("\n");
            }
        }
        result.pop();
        Ok(result)
    }
}

/// Read from the path defined in the `Config`
fn read_file(target: &path::PathBuf) -> Result<String, Box<Error>> {
    let mut file: File = File::open(target).expect("File not found");
    let mut contents: String = String::new();

    file.read_to_string(&mut contents).expect("Cannot read file");
    Ok(contents)
}

/// Prints the help message to the command line
fn print_help() {
    let help_message = &(String::from(
        "\n    ============  MiniGrep v") + env!("CARGO_PKG_VERSION") +
        "  ============    \n\n" +
        "    Arguments:\n" +
        "        target - The target file to be searched\n" +
        "        regex  - The regular expression to search by (default: .)\n" +
        //"        --output - Search results output to file (default: output.txt)\n" +
        "        --help   - Display this message\n");
    println!("{}", help_message);
}