From fcd59ace3a41e97328079d95c052a0570733f75c Mon Sep 17 00:00:00 2001 From: Vladyslav Tronko Date: Tue, 14 Mar 2023 19:39:57 +0200 Subject: [PATCH] Fix chmln#100: allow line-buffered input --- src/cli.rs | 4 ++++ src/input.rs | 31 +++++++++++++++++++++++++++++++ src/main.rs | 2 ++ 3 files changed, 37 insertions(+) diff --git a/src/cli.rs b/src/cli.rs index ab092db..2636f03 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 = "l", long = "line-buffered-mode")] + /// Buffered mode. Doesn't support multiline matching + pub line_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..762b395 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, + StdinLineBuffered, Files(Vec), } @@ -54,6 +56,35 @@ impl App { Ok(()) } + (Source::StdinLineBuffered, _) => { + 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..ea6638b 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.line_buffered { + Source::StdinLineBuffered } else { Source::Stdin };