@@ -1,4 +1,4 @@
1−use std::io::{self, Write};
1+use std::io::{self, BufRead, Read, Write};
3use crate::assets::HighlightingAssets;
3use crate::assets::HighlightingAssets;
4use crate::config::{Config, VisibleLines};
4use crate::config::{Config, VisibleLines};
@@ -14,7 +14,20 @@ use crate::output::OutputType;
14use crate::paging::PagingMode;
14use crate::paging::PagingMode;
15use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
15use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
17−use clircle::Clircle;
17+use clircle::{Clircle, Identifier};
20+impl Read for DummyStdin {
21+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
25+impl BufRead for DummyStdin {
26+ fn fill_buf(&mut self) -> io::Result<&[u8]> {
29+ fn consume(&mut self, _amt: usize) {}
19pub struct Controller<'a> {
32pub struct Controller<'a> {
20 config: &'a Config<'a>,
33 config: &'a Config<'a>,
@@ -87,72 +100,82 @@ impl<'b> Controller<'b> {
89 for (index, input) in inputs.into_iter().enumerate() {
102 for (index, input) in inputs.into_iter().enumerate() {
90− match input.open(io::stdin().lock(), stdout_identifier.as_ref()) {
103+ let identifier = stdout_identifier.as_ref();
104+ let is_first = index == 0;
105+ let result = if input.is_stdin() {
106+ self.print_input(input, writer, io::stdin().lock(), identifier, is_first)
108+ // Use dummy stdin since stdin is actually not used (#1902)
109+ self.print_input(input, writer, DummyStdin, identifier, is_first)
91− Err(error) => {
111+ if let Err(error) = result {
92− print_error(&error, writer);
112+ print_error(&error, writer);
93− no_errors = false;
113+ no_errors = false;
95− Ok(mut opened_input) => {
96− #[cfg(feature = "git")]
97− let line_changes = if self.config.visible_lines.diff_mode()
98− || (!self.config.loop_through && self.config.style_components.changes())
100− match opened_input.kind {
101− crate::input::OpenedInputKind::OrdinaryFile(ref path) => {
102− let diff = get_git_diff(path);
104− // Skip files without Git modifications
105− if self.config.visible_lines.diff_mode()
108− .map(|changes| changes.is_empty())
116− _ if self.config.visible_lines.diff_mode() => {
117− // Skip non-file inputs in diff mode
126− let mut printer: Box<dyn Printer> = if self.config.loop_through {
117+ Ok(no_errors)
127− Box::new(SimplePrinter::new(self.config))
118+ }
129− Box::new(InteractivePrinter::new(
120+ fn print_input<'a, R: BufRead>(
130− self.config,
121+ &self,
131− self.assets,
122+ input: Input,
132− &mut opened_input,
123+ writer: &mut dyn Write,
133− #[cfg(feature = "git")]
124+ stdin: R,
134− &line_changes,
125+ stdout_identifier: Option<&Identifier>,
135− )?)
126+ is_first: bool,
136− };
127+ ) -> Result<()> {
137−
128+ let mut opened_input = input.open(stdin, stdout_identifier)?;
138− let result = self.print_file(
129+ #[cfg(feature = "git")]
139− &mut *printer,
130+ let line_changes = if self.config.visible_lines.diff_mode()
140− writer,
131+ || (!self.config.loop_through && self.config.style_components.changes())
141− &mut opened_input,
132+ {
142− index != 0,
133+ match opened_input.kind {
143− #[cfg(feature = "git")]
134+ crate::input::OpenedInputKind::OrdinaryFile(ref path) => {
144− &line_changes,
135+ let diff = get_git_diff(path);
146−
137+ // Skip files without Git modifications
147− if let Err(error) = result {
138+ if self.config.visible_lines.diff_mode()
148− print_error(&error, writer);
139+ && diff
149− no_errors = false;
140+ .as_ref()
141+ .map(|changes| changes.is_empty())
149+ _ if self.config.visible_lines.diff_mode() => {
150+ // Skip non-file inputs in diff mode
155− Ok(no_errors)
159+ let mut printer: Box<dyn Printer> = if self.config.loop_through {
160+ Box::new(SimplePrinter::new(self.config))
162+ Box::new(InteractivePrinter::new(
166+ #[cfg(feature = "git")]
176+ #[cfg(feature = "git")]
158 fn print_file(
181 fn print_file(