mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
7488cb0eee
commit
3219297ffd
12 changed files with 198 additions and 86 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
|
@ -961,9 +961,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.7.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
|
checksum = "67827e6ea8ee8a7c4a72227ef4fc08957040acffdb5f122733b24fa12daff41b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md5"
|
name = "md5"
|
||||||
|
|
@ -1425,7 +1425,7 @@ checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata 0.3.3",
|
"regex-automata 0.3.4",
|
||||||
"regex-syntax 0.7.4",
|
"regex-syntax 0.7.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1440,9 +1440,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -1502,18 +1502,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.176"
|
version = "1.0.178"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76dc28c9523c5d70816e393136b86d48909cfb27cecaa902d338c19ed47164dc"
|
checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.176"
|
version = "1.0.178"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4e7b8c5dc823e3b90651ff1d3808419cd14e5ad76de04feaf37da114e7a306f"
|
checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ sort_reverse = true
|
||||||
show_hidden = false
|
show_hidden = false
|
||||||
|
|
||||||
[preview]
|
[preview]
|
||||||
adaptor = "kitty"
|
|
||||||
tab_size = 2
|
tab_size = 2
|
||||||
max_width = 600
|
max_width = 600
|
||||||
max_height = 900
|
max_height = 900
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug"],"version":"0.2","language":"en"}
|
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp"],"language":"en","version":"0.2"}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,55 @@
|
||||||
use anyhow::bail;
|
use std::env;
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[serde(try_from = "String")]
|
|
||||||
pub enum PreviewAdaptor {
|
pub enum PreviewAdaptor {
|
||||||
Kitty,
|
Kitty,
|
||||||
Ueberzug,
|
Iterm2,
|
||||||
|
|
||||||
|
// Supported by Überzug++
|
||||||
|
X11,
|
||||||
|
Wayland,
|
||||||
|
Sixel,
|
||||||
|
Chafa,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<String> for PreviewAdaptor {
|
impl Default for PreviewAdaptor {
|
||||||
type Error = anyhow::Error;
|
fn default() -> Self {
|
||||||
|
match env::var("TERM").unwrap_or_default().as_str() {
|
||||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
"wezterm" => return Self::Kitty,
|
||||||
Ok(match value.to_lowercase().as_str() {
|
"xterm-kitty" => return Self::Kitty,
|
||||||
"kitty" => Self::Kitty,
|
"iterm2" => return Self::Iterm2,
|
||||||
"ueberzug" => Self::Ueberzug,
|
"foot" => return Self::Sixel,
|
||||||
_ => bail!("invalid preview adaptor: {}", value),
|
_ => {}
|
||||||
})
|
}
|
||||||
|
match env::var("XDG_SESSION_TYPE").unwrap_or_default().as_str() {
|
||||||
|
"x11" => return Self::X11,
|
||||||
|
"wayland" => return Self::Wayland,
|
||||||
|
_ => Self::Chafa,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for PreviewAdaptor {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
PreviewAdaptor::Kitty => "kitty",
|
||||||
|
PreviewAdaptor::Iterm2 => "iterm2",
|
||||||
|
PreviewAdaptor::X11 => "x11",
|
||||||
|
PreviewAdaptor::Wayland => "wayland",
|
||||||
|
PreviewAdaptor::Sixel => "sixel",
|
||||||
|
PreviewAdaptor::Chafa => "chafa",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PreviewAdaptor {
|
||||||
|
#[inline]
|
||||||
|
pub fn needs_ueberzug(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
PreviewAdaptor::Kitty => false,
|
||||||
|
PreviewAdaptor::Iterm2 => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use crate::config::MERGED_YAZI;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Preview {
|
pub struct Preview {
|
||||||
|
#[serde(skip)]
|
||||||
pub adaptor: PreviewAdaptor,
|
pub adaptor: PreviewAdaptor,
|
||||||
pub tab_size: u32,
|
pub tab_size: u32,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use super::{kitty::Kitty, ueberzug::Ueberzug};
|
use super::{iterm2::Iterm2, kitty::Kitty, ueberzug::Ueberzug};
|
||||||
use crate::config::{preview::PreviewAdaptor, PREVIEW};
|
use crate::config::{preview::PreviewAdaptor, PREVIEW};
|
||||||
|
|
||||||
pub struct Adaptor {
|
pub struct Adaptor {
|
||||||
|
|
@ -15,7 +15,7 @@ impl Adaptor {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut adaptor = Self { ueberzug: None };
|
let mut adaptor = Self { ueberzug: None };
|
||||||
|
|
||||||
if PREVIEW.adaptor == PreviewAdaptor::Ueberzug {
|
if PREVIEW.adaptor.needs_ueberzug() {
|
||||||
adaptor.ueberzug = Ueberzug::init().ok();
|
adaptor.ueberzug = Ueberzug::init().ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +25,8 @@ impl Adaptor {
|
||||||
pub async fn image_show(&self, path: &Path, rect: Rect) -> Result<()> {
|
pub async fn image_show(&self, path: &Path, rect: Rect) -> Result<()> {
|
||||||
match PREVIEW.adaptor {
|
match PREVIEW.adaptor {
|
||||||
PreviewAdaptor::Kitty => Kitty::image_show(path, rect).await,
|
PreviewAdaptor::Kitty => Kitty::image_show(path, rect).await,
|
||||||
PreviewAdaptor::Ueberzug => {
|
PreviewAdaptor::Iterm2 => Iterm2::image_show(path, rect).await,
|
||||||
|
_ => {
|
||||||
if let Some(tx) = &self.ueberzug {
|
if let Some(tx) = &self.ueberzug {
|
||||||
tx.send(Some((path.to_path_buf(), rect))).ok();
|
tx.send(Some((path.to_path_buf(), rect))).ok();
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +38,8 @@ impl Adaptor {
|
||||||
pub fn image_hide(&self) {
|
pub fn image_hide(&self) {
|
||||||
match PREVIEW.adaptor {
|
match PREVIEW.adaptor {
|
||||||
PreviewAdaptor::Kitty => Kitty::image_hide(),
|
PreviewAdaptor::Kitty => Kitty::image_hide(),
|
||||||
PreviewAdaptor::Ueberzug => {
|
PreviewAdaptor::Iterm2 => {}
|
||||||
|
_ => {
|
||||||
if let Some(tx) = &self.ueberzug {
|
if let Some(tx) = &self.ueberzug {
|
||||||
tx.send(None).ok();
|
tx.send(None).ok();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/core/adaptor/image.rs
Normal file
31
src/core/adaptor/image.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use image::{imageops::FilterType, DynamicImage};
|
||||||
|
use tokio::fs;
|
||||||
|
|
||||||
|
use crate::{config::PREVIEW, misc::tty_ratio};
|
||||||
|
|
||||||
|
pub(super) struct Image;
|
||||||
|
|
||||||
|
impl Image {
|
||||||
|
pub(super) async fn resize(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
|
||||||
|
let (w, h) = {
|
||||||
|
let r = tty_ratio();
|
||||||
|
let (w, h) = ((size.0 as f64 * r.0) as u32, (size.1 as f64 * r.1) as u32);
|
||||||
|
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = fs::read(path).await?;
|
||||||
|
let img = tokio::task::spawn_blocking(move || -> Result<DynamicImage> {
|
||||||
|
let img = image::load_from_memory(&img)?;
|
||||||
|
Ok(if img.width() > w || img.height() > h {
|
||||||
|
img.resize(w, h, FilterType::Triangle)
|
||||||
|
} else {
|
||||||
|
img
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(img.await??)
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/core/adaptor/iterm2.rs
Normal file
50
src/core/adaptor/iterm2.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
use std::{io::Write, path::Path};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use base64::{engine::general_purpose, Engine};
|
||||||
|
use image::DynamicImage;
|
||||||
|
use ratatui::prelude::Rect;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
use super::image::Image;
|
||||||
|
use crate::ui::Term;
|
||||||
|
|
||||||
|
pub(super) struct Iterm2;
|
||||||
|
|
||||||
|
impl Iterm2 {
|
||||||
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
|
let img = Image::resize(path, (rect.width, rect.height)).await?;
|
||||||
|
let b = Self::encode(img).await?;
|
||||||
|
|
||||||
|
Term::move_to(rect.x, rect.y).ok();
|
||||||
|
tokio::io::stdout().write_all(&b).await.ok();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn encode(img: DynamicImage) -> Result<Vec<u8>> {
|
||||||
|
fn output(raw: Vec<u8>, size: (u32, u32)) -> Result<Vec<u8>> {
|
||||||
|
let mut buf = Vec::with_capacity(raw.len() * 4 / 3 + 4 + 200);
|
||||||
|
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"\x1b]1337;File=inline=1;size={};width={}px;height={}px:",
|
||||||
|
raw.len(),
|
||||||
|
size.0,
|
||||||
|
size.1,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let len = buf.len();
|
||||||
|
let written = general_purpose::STANDARD.encode_slice(raw, &mut buf[len..])?;
|
||||||
|
buf.truncate(len + written);
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = (img.width(), img.height());
|
||||||
|
tokio::task::spawn_blocking(move || match img {
|
||||||
|
DynamicImage::ImageRgb8(v) => output(v.into_raw(), size),
|
||||||
|
DynamicImage::ImageRgba8(v) => output(v.into_raw(), size),
|
||||||
|
v => output(v.to_rgb8().into_raw(), size),
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,32 +2,19 @@ use std::{io::Write, path::Path};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use image::{imageops::FilterType, DynamicImage};
|
use image::DynamicImage;
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
use tokio::{fs, io::AsyncWriteExt};
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use crate::{config::PREVIEW, misc::tty_ratio, ui::Term};
|
use super::image::Image;
|
||||||
|
use crate::ui::Term;
|
||||||
|
|
||||||
pub struct Kitty;
|
pub(super) struct Kitty;
|
||||||
|
|
||||||
impl Kitty {
|
impl Kitty {
|
||||||
pub async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
let (w, h) = {
|
let img = Image::resize(path, (rect.width, rect.height)).await?;
|
||||||
let r = tty_ratio();
|
let b = Self::encode(img).await?;
|
||||||
let (w, h) = ((rect.width as f64 * r.0) as u32, (rect.height as f64 * r.1) as u32);
|
|
||||||
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
|
|
||||||
};
|
|
||||||
|
|
||||||
let img = fs::read(path).await?;
|
|
||||||
let b = tokio::task::spawn_blocking(move || -> Result<Vec<u8>> {
|
|
||||||
let img = image::load_from_memory(&img)?;
|
|
||||||
Self::encode(if img.width() > w || img.height() > h {
|
|
||||||
img.resize(w, h, FilterType::Triangle)
|
|
||||||
} else {
|
|
||||||
img
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
Term::move_to(rect.x, rect.y).ok();
|
Term::move_to(rect.x, rect.y).ok();
|
||||||
tokio::io::stdout().write_all(&b).await.ok();
|
tokio::io::stdout().write_all(&b).await.ok();
|
||||||
|
|
@ -35,9 +22,9 @@ impl Kitty {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn image_hide() { std::io::stdout().write_all(b"\x1b\\\x1b_Ga=d\x1b\\").ok(); }
|
pub(super) fn image_hide() { std::io::stdout().write_all(b"\x1b\\\x1b_Ga=d\x1b\\").ok(); }
|
||||||
|
|
||||||
fn encode(img: DynamicImage) -> Result<Vec<u8>> {
|
async fn encode(img: DynamicImage) -> Result<Vec<u8>> {
|
||||||
fn output(raw: Vec<u8>, format: u8, size: (u32, u32)) -> Result<Vec<u8>> {
|
fn output(raw: Vec<u8>, format: u8, size: (u32, u32)) -> Result<Vec<u8>> {
|
||||||
let b64 = general_purpose::STANDARD.encode(raw).chars().collect::<Vec<_>>();
|
let b64 = general_purpose::STANDARD.encode(raw).chars().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
@ -67,10 +54,11 @@ impl Kitty {
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = (img.width(), img.height());
|
let size = (img.width(), img.height());
|
||||||
match img {
|
tokio::task::spawn_blocking(move || match img {
|
||||||
DynamicImage::ImageRgb8(v) => output(v.into_raw(), 24, size),
|
DynamicImage::ImageRgb8(v) => output(v.into_raw(), 24, size),
|
||||||
DynamicImage::ImageRgba8(v) => output(v.into_raw(), 32, size),
|
DynamicImage::ImageRgba8(v) => output(v.into_raw(), 32, size),
|
||||||
v => output(v.to_rgb8().into_raw(), 24, size),
|
v => output(v.to_rgb8().into_raw(), 24, size),
|
||||||
}
|
})
|
||||||
|
.await?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
mod adaptor;
|
mod adaptor;
|
||||||
|
mod image;
|
||||||
|
mod iterm2;
|
||||||
mod kitty;
|
mod kitty;
|
||||||
mod ueberzug;
|
mod ueberzug;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,29 @@
|
||||||
use std::{path::PathBuf, process::Stdio};
|
use std::{path::PathBuf, process::Stdio};
|
||||||
|
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::Result;
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
use tokio::{io::AsyncWriteExt, process::{Child, Command}, select, sync::mpsc::{self, UnboundedSender}};
|
use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}};
|
||||||
|
|
||||||
pub struct Ueberzug;
|
use crate::config::PREVIEW;
|
||||||
|
|
||||||
|
pub(super) struct Ueberzug;
|
||||||
|
|
||||||
impl Ueberzug {
|
impl Ueberzug {
|
||||||
pub fn init() -> Result<UnboundedSender<Option<(PathBuf, Rect)>>> {
|
pub(super) fn init() -> Result<UnboundedSender<Option<(PathBuf, Rect)>>> {
|
||||||
let mut child = Some(Self::create_demon()?);
|
let mut child = Self::create_demon().ok();
|
||||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
while let Some(img) = rx.recv().await {
|
||||||
if let Some(c) = &mut child {
|
let exit = child.as_mut().and_then(|c| c.try_wait().ok());
|
||||||
select! {
|
if exit != Some(None) {
|
||||||
_ = c.wait() => child = None,
|
child = None;
|
||||||
data = rx.recv() => {
|
}
|
||||||
if let Some(img) = data {
|
if child.is_none() {
|
||||||
Self::send_command(c, img).await.ok();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else if let Some(img) = rx.recv().await {
|
|
||||||
child = Self::create_demon().ok();
|
child = Self::create_demon().ok();
|
||||||
if let Some(c) = &mut child {
|
}
|
||||||
Self::send_command(c, img).await.ok();
|
if let Some(c) = &mut child {
|
||||||
}
|
Self::send_command(c, img).await.ok();
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -41,21 +34,31 @@ impl Ueberzug {
|
||||||
fn create_demon() -> Result<Child> {
|
fn create_demon() -> Result<Child> {
|
||||||
Ok(
|
Ok(
|
||||||
Command::new("ueberzug")
|
Command::new("ueberzug")
|
||||||
.args(["layer", "-s", "--use-escape-codes"])
|
.args(["layer", "-so", &PREVIEW.adaptor.to_string()])
|
||||||
.kill_on_drop(true)
|
.kill_on_drop(true)
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
// .stdout(Stdio::piped())
|
.stderr(Stdio::null())
|
||||||
.stderr(Stdio::null())
|
.spawn()?,
|
||||||
.spawn()?,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_command(child: &mut Child, img: Option<(PathBuf, Rect)>) -> Result<()> {
|
async fn send_command(child: &mut Child, img: Option<(PathBuf, Rect)>) -> Result<()> {
|
||||||
let stdin = child.stdin.as_mut().unwrap();
|
let stdin = child.stdin.as_mut().unwrap();
|
||||||
if let Some((path, rect)) = img {
|
if let Some((path, rect)) = img {
|
||||||
stdin.write_all(br#"{"action":"add","identifier":"preview","max_height":0,"max_width":0,"path":"/Users/ika/Downloads/photo_2023-06-28 07.23.33.jpeg","x":0,"y":0}\n"#).await?;
|
let cmd = format!(
|
||||||
|
r#"{{"action":"add","identifier":"yazi","x":{},"y":{},"max_width":{},"max_height":{},"path":"{}"}}{}"#,
|
||||||
|
rect.x,
|
||||||
|
rect.y,
|
||||||
|
rect.width,
|
||||||
|
rect.height,
|
||||||
|
path.to_string_lossy(),
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
stdin.write_all(cmd.as_bytes()).await?;
|
||||||
} else {
|
} else {
|
||||||
stdin.write_all(br#"{"action":"remove","identifier":"preview"}\n"#).await?;
|
stdin
|
||||||
|
.write_all(format!(r#"{{"action":"remove","identifier":"yazi"}}{}"#, "\n").as_bytes())
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use ansi_to_tui::IntoText;
|
use ansi_to_tui::IntoText;
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Paragraph, Widget}};
|
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Clear, Paragraph, Widget}};
|
||||||
|
|
||||||
use super::Folder;
|
use super::Folder;
|
||||||
use crate::{core::manager::PreviewData, ui::Ctx};
|
use crate::{core::manager::PreviewData, ui::Ctx};
|
||||||
|
|
@ -14,6 +14,8 @@ impl<'a> Preview<'a> {
|
||||||
|
|
||||||
impl<'a> Widget for Preview<'a> {
|
impl<'a> Widget for Preview<'a> {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Clear.render(Rect { x: area.x, y: area.y, width: area.width + 1, height: area.height }, buf);
|
||||||
|
|
||||||
// TODO: image
|
// TODO: image
|
||||||
// if self.cx.input.visible || self.cx.select.visible || self.cx.tasks.visible {
|
// if self.cx.input.visible || self.cx.select.visible || self.cx.tasks.visible {
|
||||||
// }
|
// }
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue