use crate::{resources::InlineImageProtocol, terminal::TerminalSize, ResourceUrlHandler};
use std::io::{Result, Write};
use tracing::{event, Level};
use url::Url;
pub fn is_terminology() -> bool {
std::env::var("TERMINOLOGY").is_ok_and(|value| value.trim() == "1")
}
#[derive(Debug, Copy, Clone)]
pub struct Terminology;
#[cfg(feature = "image-processing")]
fn get_image_dimensions(url: &Url) -> Option<(u32, u32)> {
if url.scheme() == "file" {
let path = url.to_file_path().ok()?;
event!(
Level::DEBUG,
"Inspecting image dimensions at {}",
path.display()
);
image::image_dimensions(&path)
.map_err(|error| {
event!(
Level::INFO,
"Failed to read image dimensions from {}: {}",
path.display(),
error
);
error
})
.ok()
} else {
None
}
}
#[cfg(not(feature = "image-processing"))]
fn get_image_dimensions(_url: &Url) -> Option<(u32, u32)> {
event!(
Level::DEBUG,
"Inspecting image dimensions not supported without image-processing feature"
);
None
}
impl InlineImageProtocol for Terminology {
fn write_inline_image(
&self,
writer: &mut dyn Write,
_resource_handler: &dyn ResourceUrlHandler,
url: &Url,
terminal_size: TerminalSize,
) -> Result<()> {
let columns = terminal_size.columns;
let lines = match get_image_dimensions(url) {
Some((w, h)) => ((h as f64) * (columns / 2) as f64 / (w as f64)) as usize,
None => terminal_size.rows as usize / 2,
};
let mut command = format!("\x1b}}ic#{};{};{}\x00", columns, lines, url.as_str());
for _ in 0..lines {
command.push_str("\x1b}ib\x00");
for _ in 0..columns {
command.push('#');
}
command.push_str("\x1b}ie\x00\n");
}
writer.write_all(command.as_bytes())?;
Ok(())
}
}