diff --git a/src/cli.rs b/src/cli.rs index ab092db..dbbcd6f 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -19,6 +19,10 @@ pub(crate) struct Options { /// Recursively replace files pub recursive: bool, + #[structopt(short = "b", long = "buffered-mode")] + /// Buffered mode. Doesn't support multiline matching + pub buffered: bool, + #[structopt(short = "n")] /// Limit the number of replacements pub replacements: Option, diff --git a/src/input.rs b/src/input.rs index 9751a6d..3a41edd 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,9 +1,11 @@ use crate::{Replacer, Result}; +use std::io::{BufRead, Write}; use std::{fs::File, io::prelude::*, path::PathBuf}; #[derive(Debug)] pub(crate) enum Source { Stdin, + StdinBuffered, Files(Vec), } @@ -54,6 +56,35 @@ impl App { Ok(()) } + (Source::StdinBuffered, _) => { + let stdin = std::io::stdin(); + let stdout = std::io::stdout(); + let mut handle = stdout.lock(); + + let mut buffer = String::new(); + + loop { + let bytes_read = stdin + .lock() + .read_line(&mut buffer) + .expect("Error reading from standard input"); + if bytes_read == 0 { + break; + } + let output = if is_tty { + self.replacer.replace_preview(buffer.as_bytes()) + } else { + self.replacer.replace(buffer.as_bytes()) + }; + handle + .write_all(output.as_ref()) + .expect("Error writing to standard output"); + handle.flush().expect("Error flushing output"); + buffer.clear(); + } + + Ok(()) + } (Source::Files(paths), false) => { use rayon::prelude::*; diff --git a/src/main.rs b/src/main.rs index 436904a..8b2beaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,8 @@ fn main() -> Result<()> { Source::recursive()? } else if options.files.len() > 0 { Source::Files(options.files) + } else if options.buffered { + Source::StdinBuffered } else { Source::Stdin };