mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
d51962ce83
commit
0ac06e0bd8
9 changed files with 52 additions and 33 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2693,6 +2693,7 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
|||
name = "yazi-adaptor"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"base64 0.22.1",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
|||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||
|
||||
# External dependencies
|
||||
ansi-to-tui = "3.1.0"
|
||||
anyhow = "1.0.86"
|
||||
arc-swap = "1.7.1"
|
||||
base64 = "0.22.1"
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use std::{env, fmt::Display, path::Path, sync::Arc};
|
|||
use anyhow::Result;
|
||||
use ratatui::layout::Rect;
|
||||
use tracing::warn;
|
||||
use yazi_shared::{env_exists, term::Term};
|
||||
use yazi_shared::env_exists;
|
||||
|
||||
use super::{Iterm2, Kitty, KittyOld};
|
||||
use crate::{ueberzug::Ueberzug, Emulator, Sixel, SHOWN, TMUX};
|
||||
use crate::{Chafa, Emulator, Sixel, Ueberzug, SHOWN, TMUX};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Adaptor {
|
||||
|
|
@ -42,7 +42,8 @@ impl Adaptor {
|
|||
Self::KittyOld => KittyOld::image_show(path, max).await,
|
||||
Self::Iterm2 => Iterm2::image_show(path, max).await,
|
||||
Self::Sixel => Sixel::image_show(path, max).await,
|
||||
_ => Ueberzug::image_show(path, max).await,
|
||||
Self::X11 | Self::Wayland => Ueberzug::image_show(path, max).await,
|
||||
Self::Chafa => Chafa::image_show(path, max).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,9 +55,10 @@ impl Adaptor {
|
|||
match self {
|
||||
Self::Kitty => Kitty::image_erase(area),
|
||||
Self::Iterm2 => Iterm2::image_erase(area),
|
||||
Self::KittyOld => KittyOld::image_erase(),
|
||||
Self::KittyOld => KittyOld::image_erase(area),
|
||||
Self::Sixel => Sixel::image_erase(area),
|
||||
_ => Ueberzug::image_erase(area),
|
||||
Self::X11 | Self::Wayland => Ueberzug::image_erase(area),
|
||||
Self::Chafa => Chafa::image_erase(area),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
use std::{path::Path, process::Stdio};
|
||||
use std::{io::Write, path::Path, process::Stdio};
|
||||
|
||||
use ansi_to_tui::IntoText;
|
||||
use anyhow::{bail, Result};
|
||||
use imagesize::ImageSize;
|
||||
use ratatui::layout::Rect;
|
||||
use tokio::process::Command;
|
||||
use yazi_shared::term::Term;
|
||||
|
||||
use crate::Image;
|
||||
use crate::Adaptor;
|
||||
|
||||
pub(super) struct Chafa;
|
||||
|
||||
impl Chafa {
|
||||
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<(u32, u32)> {
|
||||
let p = path.to_owned();
|
||||
let ImageSize { width: w, height: h } =
|
||||
tokio::task::spawn_blocking(move || imagesize::size(p)).await??;
|
||||
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
let output = Command::new("chafa")
|
||||
.args([
|
||||
"-f",
|
||||
|
|
@ -29,7 +26,7 @@ impl Chafa {
|
|||
"off",
|
||||
"--view-size",
|
||||
])
|
||||
.arg(format!("{}x{}", rect.width, rect.height))
|
||||
.arg(format!("{}x{}", max.width, max.height))
|
||||
.arg(path)
|
||||
.stdin(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
|
|
@ -40,24 +37,40 @@ impl Chafa {
|
|||
|
||||
if !output.status.success() {
|
||||
bail!("chafa failed with status: {}", output.status);
|
||||
} else if output.stdout.is_empty() {
|
||||
bail!("chafa returned no output");
|
||||
}
|
||||
|
||||
// output.stdout
|
||||
let lines: Vec<_> = output.stdout.split(|&b| b == b'\n').collect();
|
||||
let Ok(Some(first)) = lines[0].into_text().map(|mut t| t.lines.pop()) else {
|
||||
bail!("failed to parse chafa output");
|
||||
};
|
||||
|
||||
let (max_w, max_h) = Image::max_pixel(rect);
|
||||
if w <= max_w as usize && h <= max_h as usize {
|
||||
return Ok((w as u32, h as u32));
|
||||
}
|
||||
let area = Rect {
|
||||
x: max.x,
|
||||
y: max.y,
|
||||
width: first.spans.into_iter().map(|s| s.content.chars().count() as u16).sum(),
|
||||
height: lines.len() as u16,
|
||||
};
|
||||
|
||||
let ratio = f64::min(max_w as f64 / w as f64, max_h as f64 / h as f64);
|
||||
Ok(((w as f64 * ratio).round() as u32, (h as f64 * ratio).round() as u32))
|
||||
Adaptor::shown_store(area);
|
||||
Term::move_lock((max.x, max.y), |stderr| {
|
||||
for (i, line) in lines.into_iter().enumerate() {
|
||||
stderr.write_all(line)?;
|
||||
Term::move_to(stderr, max.x, max.y + i as u16 + 1)?;
|
||||
}
|
||||
Ok(area)
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn image_erase(_: Rect) -> Result<()> {
|
||||
if let Some(tx) = &*DEMON {
|
||||
Ok(tx.send(None)?)
|
||||
} else {
|
||||
bail!("uninitialized ueberzugpp");
|
||||
}
|
||||
pub(super) fn image_erase(area: Rect) -> Result<()> {
|
||||
let s = " ".repeat(area.width as usize);
|
||||
Term::move_lock((0, 0), |stderr| {
|
||||
for y in area.top()..area.bottom() {
|
||||
Term::move_to(stderr, area.x, y)?;
|
||||
write!(stderr, "{s}")?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{io::Write, path::Path};
|
|||
|
||||
use anyhow::Result;
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use image::{DynamicImage, GenericImageView};
|
||||
use image::DynamicImage;
|
||||
use ratatui::layout::Rect;
|
||||
use yazi_shared::term::Term;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl KittyOld {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn image_erase() -> Result<()> {
|
||||
pub(super) fn image_erase(_: Rect) -> Result<()> {
|
||||
let mut stderr = LineWriter::new(stderr());
|
||||
write!(stderr, "{}_Gq=1,a=d,d=A{}\\{}", START, ESCAPE, CLOSE)?;
|
||||
stderr.flush()?;
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ mod sixel;
|
|||
mod ueberzug;
|
||||
|
||||
pub use adaptor::*;
|
||||
use chafa::*;
|
||||
pub use emulator::*;
|
||||
use iterm2::*;
|
||||
use kitty::*;
|
||||
use kitty_old::*;
|
||||
use sixel::*;
|
||||
use ueberzug::*;
|
||||
use yazi_shared::{env_exists, RoCell};
|
||||
|
||||
pub use crate::image::*;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ impl Ueberzug {
|
|||
tokio::task::spawn_blocking(move || imagesize::size(p)).await??;
|
||||
|
||||
let area = Image::pixel_area((w as u32, h as u32), max);
|
||||
tx.send(Some((path.to_owned(), max)))?;
|
||||
tx.send(Some((path.to_owned(), area)))?;
|
||||
|
||||
Adaptor::shown_store(area);
|
||||
Ok(area)
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ use mlua::{IntoLuaMulti, Lua, Table, Value};
|
|||
use yazi_adaptor::{Image, ADAPTOR};
|
||||
|
||||
use super::Utils;
|
||||
use crate::{elements::RectRef, url::UrlRef};
|
||||
use crate::{bindings::Cast, elements::{Rect, RectRef}, url::UrlRef};
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn image(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.raw_set(
|
||||
"image_show",
|
||||
lua.create_async_function(|lua, (url, rect): (UrlRef, RectRef)| async move {
|
||||
if let Ok(size) = ADAPTOR.image_show(&url, *rect).await {
|
||||
size.into_lua_multi(lua)
|
||||
if let Ok(area) = ADAPTOR.image_show(&url, *rect).await {
|
||||
Rect::cast(lua, area)?.into_lua_multi(lua)
|
||||
} else {
|
||||
Value::Nil.into_lua_multi(lua)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue