cat/
cat.rs

1//! You can open files as part of parsing process too, might not be the best idea though
2//! because depending on a context `bpaf` might need to evaluate some parsers multiple times.
3//!
4//! Main motivation for this example is that you can open a file as part of the argument parsing
5//! and give a reader directly to user. In practice to replicate `cat`'s behavior you'd accept
6//! multiple files with `many` and open them one by one in your code.
7
8use bpaf::*;
9use std::{
10    ffi::OsString,
11    fs::File,
12    io::{stdin, BufRead, BufReader, Read},
13};
14
15fn main() {
16    let file = positional::<OsString>("FILE")
17        .help("File name to concatenate, with no FILE or when FILE is -, read standard input")
18        .optional()
19        .parse::<_, Box<dyn Read>, std::io::Error>(|path| {
20            Ok(if let Some(path) = path {
21                if path == "-" {
22                    Box::new(stdin())
23                } else {
24                    Box::new(File::open(path)?)
25                }
26            } else {
27                Box::new(stdin())
28            })
29        })
30        .to_options()
31        .descr("Concatenate a file to standard output")
32        .run();
33
34    let reader = BufReader::new(file);
35
36    for line in reader.lines() {
37        println!("{}", line.unwrap());
38    }
39}