mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
79 lines
1.8 KiB
Rust
79 lines
1.8 KiB
Rust
use std::{io::Write, path::PathBuf, process::Stdio};
|
|
|
|
use ansi_to_tui::IntoText;
|
|
use anyhow::{Result, anyhow, bail};
|
|
use crossterm::{cursor::MoveTo, queue};
|
|
use ratatui::layout::Rect;
|
|
use tokio::process::Command;
|
|
use yazi_emulator::Emulator;
|
|
|
|
use crate::Adapter;
|
|
|
|
pub(crate) struct Chafa;
|
|
|
|
impl Chafa {
|
|
pub(crate) async fn image_show(path: PathBuf, max: Rect) -> Result<Rect> {
|
|
let child = Command::new("chafa")
|
|
.args([
|
|
"-f",
|
|
"symbols",
|
|
"--relative",
|
|
"off",
|
|
"--polite",
|
|
"on",
|
|
"--passthrough",
|
|
"none",
|
|
"--animate",
|
|
"off",
|
|
"--view-size",
|
|
])
|
|
.arg(format!("{}x{}", max.width, max.height))
|
|
.arg(path)
|
|
.stdin(Stdio::null())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::null())
|
|
.kill_on_drop(true)
|
|
.spawn()
|
|
.map_err(|e| anyhow!("failed to spawn chafa: {e}"))?;
|
|
|
|
let output = child.wait_with_output().await?;
|
|
if !output.status.success() {
|
|
bail!("chafa failed with status: {}", output.status);
|
|
} else if output.stdout.is_empty() {
|
|
bail!("chafa returned no output");
|
|
}
|
|
|
|
let lines: Vec<_> = output.stdout.split(|&b| b == b'\n').collect();
|
|
let Ok(Some(first)) = lines[0].to_text().map(|mut t| t.lines.pop()) else {
|
|
bail!("failed to parse chafa output");
|
|
};
|
|
|
|
let area = Rect {
|
|
x: max.x,
|
|
y: max.y,
|
|
width: first.width() as u16,
|
|
height: lines.len() as u16,
|
|
};
|
|
|
|
Adapter::Chafa.image_hide()?;
|
|
Adapter::shown_store(area);
|
|
Emulator::move_lock((max.x, max.y), |w| {
|
|
for (i, line) in lines.into_iter().enumerate() {
|
|
w.write_all(line)?;
|
|
queue!(w, MoveTo(max.x, max.y + i as u16 + 1))?;
|
|
}
|
|
Ok(area)
|
|
})
|
|
}
|
|
|
|
pub(crate) fn image_erase(area: Rect) -> Result<()> {
|
|
let s = " ".repeat(area.width as usize);
|
|
Emulator::move_lock((0, 0), |w| {
|
|
for y in area.top()..area.bottom() {
|
|
queue!(w, MoveTo(area.x, y))?;
|
|
write!(w, "{s}")?;
|
|
}
|
|
Ok(())
|
|
})
|
|
}
|
|
}
|