fast image operations
Diffstat (limited to 'src/term.rs')
-rw-r--r--src/term.rs199
1 files changed, 0 insertions, 199 deletions
diff --git a/src/term.rs b/src/term.rs
deleted file mode 100644
index aeae9fb..0000000
--- a/src/term.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-//! terminal outputs
-//! produces output for any terminal supporting one of the
-//! ```text
-//! Kitty Graphics Protocol
-//! Iterm2 Inline Image Protocol
-//! Sixel Bitmap Graphics Format
-//! ```
-//! with a fallback for dumb terminals.
-//!
-//! the (second?) best way to debug your images.
-mod bloc;
-mod kitty;
-mod sixel;
-mod size;
-use crate::Image;
-pub use bloc::Bloc;
-pub use iterm2::Iterm2;
-pub use kitty::Kitty;
-pub use sixel::Sixel;
-use std::fmt::{Result, Write};
-
-mod seal {
- pub trait Sealed {}
-}
-use seal::Sealed;
-#[doc(hidden)]
-pub trait Basic: Sealed {}
-impl Sealed for [(); 1] {}
-impl Basic for [(); 1] {}
-impl Sealed for [(); 2] {}
-impl Basic for [(); 2] {}
-impl Sealed for [(); 3] {}
-impl Basic for [(); 3] {}
-impl Sealed for [(); 4] {}
-impl Basic for [(); 4] {}
-
-mod b64;
-mod iterm2;
-
-impl<'a, const N: usize> std::fmt::Display for Image<&'a [u8], N>
-where
- [(); N]: Basic,
-{
- /// Display an image in the terminal.
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result {
- Display(*self).write(f)
- }
-}
-
-/// Print an image in the terminal.
-///
-/// This is a wrapper for `print!("{}", term::Display(image))`
-pub fn print<T: AsRef<[u8]>, const N: usize>(i: Image<T, N>)
-where
- [(); N]: Basic,
- Display<Image<T, N>>: std::fmt::Display,
-{
- print!("{}", Display(i))
-}
-
-#[derive(Copy, Clone)]
-/// Display an image in the terminal.
-/// This type implements [`Display`](std::fmt::Display) and [`Debug`](std::fmt::Debug).
-pub struct Display<T>(pub T);
-
-impl<T> std::ops::Deref for Display<T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-
-impl<T: AsRef<[u8]>, const N: usize> std::fmt::Debug for Display<Image<T, N>>
-where
- [(); N]: Basic,
-{
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result {
- Display(self.as_ref()).write(f)
- }
-}
-
-impl<const N: usize> Display<Image<&[u8], N>>
-where
- [(); N]: Basic,
-{
- /// Write $TERM protocol encoded image data.
- pub fn write(self, f: &mut impl Write) -> Result {
- if let Ok(term) = std::env::var("TERM") {
- match &*term {
- "mlterm" | "yaft-256color" => return Sixel(self.0).write(f),
- x if x.contains("kitty") => return Kitty(self.0).write(f),
- _ => (),
- }
- }
- if let Ok(term_program) = std::env::var("TERM_PROGRAM") {
- match &*term_program {
- "MacTerm" => return Sixel(self.0).write(f),
- "iTerm" | "WezTerm" => return Iterm2(self.0).write(f),
- _ => (),
- }
- }
- if let Ok("iTerm") = std::env::var("LC_TERMINAL").as_deref() {
- return Iterm2(self.0).write(f);
- }
- #[cfg(unix)]
- return self
- .guess_harder(f)
- .unwrap_or_else(|| Bloc(self.0).write(f));
- #[cfg(not(unix))]
- return Bloc(*self).write(f);
- }
-
- #[cfg(unix)]
- // https://github.com/benjajaja/ratatui-image/blob/eeb2a1b26fbe360259f213d6d5eb5449c8ae1d6e/src/picker.rs#L226
- fn guess_harder(&self, to: &mut impl Write) -> Option<Result> {
- // contains a kitty gfx and sixel query, the `\x1b[c` is for sixels
- let buf = query(r"_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\")?;
- if buf.contains("_Gi=31;OK") {
- Some(Kitty(self.as_ref()).write(to))
- } else if buf.contains(";4;")
- || buf.contains("?4;")
- || buf.contains(";4c")
- || buf.contains("?4c")
- {
- Some(Sixel(self.as_ref()).write(to))
- } else {
- None
- }
- }
-}
-#[cfg(not(unix))]
-fn query(device_query_code: &'static str) -> Option<String> {
- None
-}
-#[cfg(unix)]
-// https://github.com/benjajaja/ratatui-image/blob/master/src/picker.rs#L226
-fn query(device_query_code: &'static str) -> Option<String> {
- extern crate libc;
- use std::mem::MaybeUninit;
- fn r(result: i32) -> Option<()> {
- (result != -1).then_some(())
- }
-
- let mut termios = MaybeUninit::<libc::termios>::uninit();
- // SAFETY: get termios of stdin
- r(unsafe { libc::tcgetattr(0, termios.as_mut_ptr()) })?;
- // SAFETY: gotten
- let termios = unsafe { termios.assume_init() };
-
- // SAFETY: turn off echo and canonical (requires enter before stdin reads) modes
- unsafe {
- libc::tcsetattr(
- 0,
- libc::TCSADRAIN,
- &libc::termios {
- c_lflag: termios.c_lflag & !libc::ICANON & !libc::ECHO,
- ..termios
- },
- )
- };
-
- let buf = try {
- // SAFETY: linux time out'd reading
- unsafe {
- println!("{device_query_code}");
- let mut buf = Vec::new();
- let mut tmp = [0; 1 << 5];
- loop {
- let mut x: libc::fd_set = std::mem::zeroed::<libc::fd_set>();
- libc::FD_SET(0, &mut x);
- match libc::select(
- 1,
- &mut x,
- 0 as _,
- 0 as _,
- &mut libc::timeval {
- tv_sec: 0,
- tv_usec: 5e5 as _,
- },
- ) {
- 0 => break,
- -1 => return None,
- _ => {}
- }
- match libc::read(libc::STDIN_FILENO, tmp.as_mut_ptr().cast(), tmp.len()) {
- 0 => continue,
- -1 => return None,
- n => buf.extend_from_slice(&tmp[..n as _]),
- }
- }
- String::from_utf8(buf).ok()?
- }
- };
-
- // SAFETY: reset attrs to what they were before we became nosy
- unsafe { libc::tcsetattr(0, libc::TCSADRAIN, &termios) };
- buf
-}