-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtext-grep.rs
49 lines (43 loc) · 1.54 KB
/
text-grep.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//! A simple grep-like program using `kommand` and `InputTextStream`.
//! Unlike regular grep, this grep supports URLs and gzip. Perg!
use clap::{ambient_authority, TryFromOsArg};
use nameless::{InputTextStream, OutputTextStream};
use regex::Regex;
use std::io::{self, BufRead, BufReader, Write};
/// # Arguments
///
/// * `pattern` - The regex to search for
/// * `inputs` - Input sources, stdin if none
#[kommand::main]
fn main(pattern: Regex, mut inputs: Vec<InputTextStream>) -> anyhow::Result<()> {
let mut output = OutputTextStream::try_from_os_str_arg("-".as_ref(), ambient_authority())?;
if inputs.is_empty() {
inputs.push(InputTextStream::try_from_os_str_arg(
"-".as_ref(),
ambient_authority(),
)?);
}
let print_inputs = inputs.len() > 1;
'inputs: for input in inputs {
let pseudonym = input.pseudonym();
let reader = BufReader::new(input);
for line in reader.lines() {
let line = line?;
if pattern.is_match(&line) {
if let Err(e) = (|| -> io::Result<()> {
if print_inputs {
output.write_pseudonym(&pseudonym)?;
write!(output, ":")?;
}
writeln!(output, "{}", line)
})() {
match e.kind() {
io::ErrorKind::BrokenPipe => break 'inputs,
_ => return Err(e.into()),
}
}
}
}
}
Ok(())
}