sysutils: grep for stdin
This commit is contained in:
parent
aefa7a93fa
commit
de98ae1082
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, stdout, Seek, Write},
|
io::{self, stdout, Seek, Stdin, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::ExitCode,
|
process::ExitCode,
|
||||||
};
|
};
|
||||||
@ -29,6 +29,22 @@ struct FileInput {
|
|||||||
position: usize,
|
position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StdinInput {
|
||||||
|
stdin: Stdin,
|
||||||
|
buffer: String,
|
||||||
|
eof: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdinInput {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
stdin: io::stdin(),
|
||||||
|
buffer: String::new(),
|
||||||
|
eof: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FileInput {
|
impl FileInput {
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||||
let mut file = File::open(path)?;
|
let mut file = File::open(path)?;
|
||||||
@ -39,6 +55,22 @@ impl FileInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Input for StdinInput {
|
||||||
|
fn next_line(&mut self) -> io::Result<Option<&[u8]>> {
|
||||||
|
if self.eof {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.buffer.clear();
|
||||||
|
if self.stdin.read_line(&mut self.buffer)? == 0 {
|
||||||
|
self.eof = true;
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(self.buffer.trim_end_matches('\n').as_bytes()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Input for FileInput {
|
impl Input for FileInput {
|
||||||
fn next_line(&mut self) -> io::Result<Option<&[u8]>> {
|
fn next_line(&mut self) -> io::Result<Option<&[u8]>> {
|
||||||
if self.position >= self.mmap.len() {
|
if self.position >= self.mmap.len() {
|
||||||
@ -57,7 +89,7 @@ impl Input for FileInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_on<I: Input>(input: &mut I, regex: &Regex) -> io::Result<bool> {
|
fn run_on<I: Input>(input: &mut I, regex: &Regex) -> Result<bool, Error> {
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
loop {
|
loop {
|
||||||
let Some(line) = input.next_line()? else {
|
let Some(line) = input.next_line()? else {
|
||||||
@ -76,14 +108,18 @@ fn run_on<I: Input>(input: &mut I, regex: &Regex) -> io::Result<bool> {
|
|||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
expression: String,
|
expression: String,
|
||||||
filename: PathBuf,
|
filename: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(args: &Args) -> Result<bool, Error> {
|
fn run(args: &Args) -> Result<bool, Error> {
|
||||||
let regex = Regex::new(&args.expression)?;
|
let regex = Regex::new(&args.expression)?;
|
||||||
let mut input = FileInput::open(&args.filename)?;
|
if let Some(filename) = args.filename.as_deref() {
|
||||||
let any = run_on(&mut input, ®ex)?;
|
let mut input = FileInput::open(filename)?;
|
||||||
Ok(any)
|
run_on(&mut input, ®ex)
|
||||||
|
} else {
|
||||||
|
let mut input = StdinInput::new();
|
||||||
|
run_on(&mut input, ®ex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user