diff --git a/examples/buffer.rs b/examples/buffer.rs
index 839689d4..eefdb249 100644
--- a/examples/buffer.rs
+++ b/examples/buffer.rs
@@ -1,4 +1,6 @@
-use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input};
+use bat::{
+    assets::HighlightingAssets, config::Config, controller::Controller, output::OutputHandle, Input,
+};
 
 fn main() {
     let mut buffer = String::new();
@@ -10,7 +12,10 @@ fn main() {
     let controller = Controller::new(&config, &assets);
     let input = Input::from_file(file!());
     controller
-        .run(vec![input.into()], Some(&mut buffer))
+        .run(
+            vec![input.into()],
+            Some(OutputHandle::FmtWrite(&mut buffer)),
+        )
         .unwrap();
 
     println!("{buffer}");
diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs
index d339ba94..946ce5b1 100644
--- a/src/bin/bat/app.rs
+++ b/src/bin/bat/app.rs
@@ -124,7 +124,10 @@ impl App {
                 // If we have -pp as an option when in auto mode, the pager should be disabled.
                 if extra_plain || self.matches.get_flag("no-paging") {
                     PagingMode::Never
-                } else if inputs.iter().any(Input::is_stdin) {
+                } else if inputs.iter().any(Input::is_stdin)
+                    // ignore stdin when --list-themes is used because in that case no input will be read anyways
+                    && !self.matches.get_flag("list-themes")
+                {
                     // If we are reading from stdin, only enable paging if we write to an
                     // interactive terminal and if we do not *read* from an interactive
                     // terminal.
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index 70443b2f..4496032b 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -16,6 +16,7 @@ use std::io::{BufReader, Write};
 use std::path::Path;
 use std::process;
 
+use bat::output::{OutputHandle, OutputType};
 use bat::theme::DetectColorScheme;
 use nu_ansi_term::Color::Green;
 use nu_ansi_term::Style;
@@ -205,8 +206,9 @@ pub fn list_themes(
     config.language = Some("Rust");
     config.style_components = StyleComponents(style);
 
-    let stdout = io::stdout();
-    let mut stdout = stdout.lock();
+    let mut output_type =
+        OutputType::from_mode(config.paging_mode, config.wrapping_mode, config.pager)?;
+    let mut writer = output_type.handle()?;
 
     let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
     for theme in assets.themes() {
@@ -221,26 +223,29 @@ pub fn list_themes(
         };
         if config.colored_output {
             writeln!(
-                stdout,
+                writer,
                 "Theme: {}{}\n",
                 Style::new().bold().paint(theme.to_string()),
                 default_theme_info
             )?;
             config.theme = theme.to_string();
             Controller::new(&config, &assets)
-                .run(vec![theme_preview_file()], None)
+                .run(
+                    vec![theme_preview_file()],
+                    Some(OutputHandle::IoWrite(&mut writer)),
+                )
                 .ok();
-            writeln!(stdout)?;
+            writeln!(writer)?;
         } else if config.loop_through {
-            writeln!(stdout, "{theme}")?;
+            writeln!(writer, "{theme}")?;
         } else {
-            writeln!(stdout, "{theme}{default_theme_info}")?;
+            writeln!(writer, "{theme}{default_theme_info}")?;
         }
     }
 
     if config.colored_output {
         writeln!(
-            stdout,
+            writer,
             "Further themes can be installed to '{}', \
             and are added to the cache with `bat cache --build`. \
             For more information, see:\n\n  \
diff --git a/src/controller.rs b/src/controller.rs
index 422b381e..c8961b91 100644
--- a/src/controller.rs
+++ b/src/controller.rs
@@ -11,10 +11,10 @@ use crate::lessopen::LessOpenPreprocessor;
 #[cfg(feature = "git")]
 use crate::line_range::LineRange;
 use crate::line_range::{LineRanges, RangeCheckResult};
-use crate::output::OutputType;
+use crate::output::{OutputHandle, OutputType};
 #[cfg(feature = "paging")]
 use crate::paging::PagingMode;
-use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter};
+use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
 
 use clircle::{Clircle, Identifier};
 
@@ -35,18 +35,14 @@ impl Controller<'_> {
         }
     }
 
-    pub fn run(
-        &self,
-        inputs: Vec<Input>,
-        output_buffer: Option<&mut dyn std::fmt::Write>,
-    ) -> Result<bool> {
-        self.run_with_error_handler(inputs, output_buffer, default_error_handler)
+    pub fn run(&self, inputs: Vec<Input>, output_handle: Option<OutputHandle<'_>>) -> Result<bool> {
+        self.run_with_error_handler(inputs, output_handle, default_error_handler)
     }
 
     pub fn run_with_error_handler(
         &self,
         inputs: Vec<Input>,
-        output_buffer: Option<&mut dyn std::fmt::Write>,
+        output_handle: Option<OutputHandle<'_>>,
         mut handle_error: impl FnMut(&Error, &mut dyn Write),
     ) -> Result<bool> {
         let mut output_type;
@@ -88,8 +84,9 @@ impl Controller<'_> {
             clircle::Identifier::stdout()
         };
 
-        let mut writer = match output_buffer {
-            Some(buf) => OutputHandle::FmtWrite(buf),
+        let mut writer = match output_handle {
+            Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w),
+            Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w),
             None => OutputHandle::IoWrite(output_type.handle()?),
         };
         let mut no_errors: bool = true;
diff --git a/src/lib.rs b/src/lib.rs
index 502427a7..4c60f10e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,7 @@ mod less;
 mod lessopen;
 pub mod line_range;
 pub(crate) mod nonprintable_notation;
-mod output;
+pub mod output;
 #[cfg(feature = "paging")]
 mod pager;
 #[cfg(feature = "paging")]
diff --git a/src/output.rs b/src/output.rs
index dc75d6e7..bb9a45d5 100644
--- a/src/output.rs
+++ b/src/output.rs
@@ -1,3 +1,4 @@
+use std::fmt;
 use std::io::{self, Write};
 #[cfg(feature = "paging")]
 use std::process::Child;
@@ -162,3 +163,17 @@ impl Drop for OutputType {
         }
     }
 }
+
+pub enum OutputHandle<'a> {
+    IoWrite(&'a mut dyn io::Write),
+    FmtWrite(&'a mut dyn fmt::Write),
+}
+
+impl OutputHandle<'_> {
+    pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
+        match self {
+            Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into),
+            Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into),
+        }
+    }
+}
diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs
index a70ac021..4979bab5 100644
--- a/src/pretty_printer.rs
+++ b/src/pretty_printer.rs
@@ -10,6 +10,7 @@ use crate::{
     error::Result,
     input,
     line_range::{HighlightedLineRanges, LineRange, LineRanges},
+    output::OutputHandle,
     style::StyleComponent,
     StripAnsiMode, SyntaxMapping, WrappingMode,
 };
@@ -325,7 +326,10 @@ impl<'a> PrettyPrinter<'a> {
 
         // If writer is provided, pass it to the controller, otherwise pass None
         if let Some(mut w) = writer {
-            controller.run(inputs.into_iter().map(|i| i.into()).collect(), Some(&mut w))
+            controller.run(
+                inputs.into_iter().map(|i| i.into()).collect(),
+                Some(OutputHandle::FmtWrite(&mut w)),
+            )
         } else {
             controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
         }
diff --git a/src/printer.rs b/src/printer.rs
index 2c364bd7..c62be3f6 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -1,5 +1,3 @@
-use std::fmt;
-use std::io;
 use std::vec::Vec;
 
 use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
@@ -29,6 +27,7 @@ use crate::diff::LineChanges;
 use crate::error::*;
 use crate::input::OpenedInput;
 use crate::line_range::RangeCheckResult;
+use crate::output::OutputHandle;
 use crate::preprocessor::strip_ansi;
 use crate::preprocessor::{expand_tabs, replace_nonprintable};
 use crate::style::StyleComponent;
@@ -68,20 +67,6 @@ const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting:
     font_style: FontStyle::empty(),
 };
 
-pub enum OutputHandle<'a> {
-    IoWrite(&'a mut dyn io::Write),
-    FmtWrite(&'a mut dyn fmt::Write),
-}
-
-impl OutputHandle<'_> {
-    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
-        match self {
-            Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into),
-            Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into),
-        }
-    }
-}
-
 pub(crate) trait Printer {
     fn print_header(
         &mut self,