mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: support local tmux image preview over SSH (#2229)
This commit is contained in:
parent
b4ca02f703
commit
245fb030df
14 changed files with 133 additions and 69 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -334,9 +334,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b"
|
checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -2276,9 +2276,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.135"
|
version = "1.0.136"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
|
checksum = "336a0c23cf42a38d9eaa7cd22c7040d04e1228a19a933890805ffd00a16437d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -2941,9 +2941,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vergen"
|
name = "vergen"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ ratatui = { version = "0.29.0", features = [ "unstable-rendered-line
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
serde = { version = "1.0.217", features = [ "derive" ] }
|
serde = { version = "1.0.217", features = [ "derive" ] }
|
||||||
serde_json = "1.0.135"
|
serde_json = "1.0.136"
|
||||||
shell-words = "1.1.0"
|
shell-words = "1.1.0"
|
||||||
tokio = { version = "1.43.0", features = [ "full" ] }
|
tokio = { version = "1.43.0", features = [ "full" ] }
|
||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.17"
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ impl Adapter {
|
||||||
protocols.retain(|p| *p == Self::Iip);
|
protocols.retain(|p| *p == Self::Iip);
|
||||||
if env_exists("ZELLIJ_SESSION_NAME") {
|
if env_exists("ZELLIJ_SESSION_NAME") {
|
||||||
protocols.retain(|p| *p == Self::Sixel);
|
protocols.retain(|p| *p == Self::Sixel);
|
||||||
} else if *TMUX != 0 {
|
} else if *TMUX {
|
||||||
protocols.retain(|p| *p != Self::KgpOld);
|
protocols.retain(|p| *p != Self::KgpOld);
|
||||||
}
|
}
|
||||||
if let Some(p) = protocols.first() {
|
if let Some(p) = protocols.first() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{io::{LineWriter, stderr}, time::Duration};
|
use std::{io::{LineWriter, Read, stderr}, time::Duration};
|
||||||
|
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
|
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
|
||||||
|
|
@ -84,7 +84,7 @@ impl Emulator {
|
||||||
|
|
||||||
// I really don't want to add this,
|
// I really don't want to add this,
|
||||||
// But tmux and ConPTY sometimes cause the cursor position to get out of sync.
|
// But tmux and ConPTY sometimes cause the cursor position to get out of sync.
|
||||||
if *TMUX != 0 || cfg!(windows) {
|
if *TMUX || cfg!(windows) {
|
||||||
execute!(buf, SavePosition, MoveTo(x, y), Show)?;
|
execute!(buf, SavePosition, MoveTo(x, y), Show)?;
|
||||||
execute!(buf, MoveTo(x, y), Show)?;
|
execute!(buf, MoveTo(x, y), Show)?;
|
||||||
execute!(buf, MoveTo(x, y), Show)?;
|
execute!(buf, MoveTo(x, y), Show)?;
|
||||||
|
|
@ -94,7 +94,7 @@ impl Emulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = cb(&mut buf);
|
let result = cb(&mut buf);
|
||||||
if *TMUX != 0 || cfg!(windows) {
|
if *TMUX || cfg!(windows) {
|
||||||
queue!(buf, Hide, RestorePosition)?;
|
queue!(buf, Hide, RestorePosition)?;
|
||||||
} else {
|
} else {
|
||||||
queue!(buf, RestorePosition)?;
|
queue!(buf, RestorePosition)?;
|
||||||
|
|
@ -124,10 +124,16 @@ impl Emulator {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
match timeout(Duration::from_secs(10), read).await {
|
match timeout(Duration::from_secs(5), read).await {
|
||||||
Err(e) => error!("read_until_da1 timed out: {buf:?}, error: {e:?}"),
|
|
||||||
Ok(Err(e)) => error!("read_until_da1 failed: {buf:?}, error: {e:?}"),
|
|
||||||
Ok(Ok(())) => debug!("read_until_da1: {buf:?}"),
|
Ok(Ok(())) => debug!("read_until_da1: {buf:?}"),
|
||||||
|
Err(e) => {
|
||||||
|
error!("read_until_da1 timed out: {buf:?}, error: {e:?}");
|
||||||
|
Self::error_to_user().ok();
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
error!("read_until_da1 failed: {buf:?}, error: {e:?}");
|
||||||
|
Self::error_to_user().ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String::from_utf8_lossy(&buf).into_owned()
|
String::from_utf8_lossy(&buf).into_owned()
|
||||||
}
|
}
|
||||||
|
|
@ -149,14 +155,45 @@ impl Emulator {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
match timeout(Duration::from_secs(10), read).await {
|
match timeout(Duration::from_secs(5), read).await {
|
||||||
Err(e) => error!("read_until_dsr timed out: {buf:?}, error: {e:?}"),
|
|
||||||
Ok(Err(e)) => error!("read_until_dsr failed: {buf:?}, error: {e:?}"),
|
|
||||||
Ok(Ok(())) => debug!("read_until_dsr: {buf:?}"),
|
Ok(Ok(())) => debug!("read_until_dsr: {buf:?}"),
|
||||||
|
Err(e) => {
|
||||||
|
error!("read_until_dsr timed out: {buf:?}, error: {e:?}");
|
||||||
|
Self::error_to_user().ok();
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
error!("read_until_dsr failed: {buf:?}, error: {e:?}");
|
||||||
|
Self::error_to_user().ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String::from_utf8_lossy(&buf).into_owned()
|
String::from_utf8_lossy(&buf).into_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn error_to_user() -> Result<()> {
|
||||||
|
use crossterm::style::{Attribute, Color, Print, ResetColor, SetAttributes, SetForegroundColor};
|
||||||
|
crossterm::execute!(
|
||||||
|
std::io::stderr(),
|
||||||
|
SetForegroundColor(Color::Red),
|
||||||
|
SetAttributes(Attribute::Bold.into()),
|
||||||
|
Print("\r\nTerminal response timeout: "),
|
||||||
|
ResetColor,
|
||||||
|
SetAttributes(Attribute::Reset.into()),
|
||||||
|
//
|
||||||
|
Print("The request sent by Yazi didn't receive a correct response.\r\n"),
|
||||||
|
Print(
|
||||||
|
"Please check your terminal environment as per: https://yazi-rs.github.io/docs/faq#trt\r\n"
|
||||||
|
),
|
||||||
|
//
|
||||||
|
SetAttributes(Attribute::Bold.into()),
|
||||||
|
SetAttributes(Attribute::Reverse.into()),
|
||||||
|
Print("Press any key to continue...\r\n"),
|
||||||
|
SetAttributes(Attribute::Reset.into()),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
std::io::stdin().read_exact(&mut [0])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn detect_base() -> Result<Self> {
|
fn detect_base() -> Result<Self> {
|
||||||
defer! { disable_raw_mode().ok(); }
|
defer! { disable_raw_mode().ok(); }
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub static ADAPTOR: RoCell<Adapter> = RoCell::new();
|
||||||
static SHOWN: SyncCell<Option<ratatui::layout::Rect>> = SyncCell::new(None);
|
static SHOWN: SyncCell<Option<ratatui::layout::Rect>> = SyncCell::new(None);
|
||||||
|
|
||||||
// Tmux support
|
// Tmux support
|
||||||
pub static TMUX: RoCell<u8> = RoCell::new();
|
pub static TMUX: RoCell<bool> = RoCell::new();
|
||||||
static ESCAPE: RoCell<&'static str> = RoCell::new();
|
static ESCAPE: RoCell<&'static str> = RoCell::new();
|
||||||
static START: RoCell<&'static str> = RoCell::new();
|
static START: RoCell<&'static str> = RoCell::new();
|
||||||
static CLOSE: RoCell<&'static str> = RoCell::new();
|
static CLOSE: RoCell<&'static str> = RoCell::new();
|
||||||
|
|
@ -39,9 +39,9 @@ pub fn init() -> anyhow::Result<()> {
|
||||||
pub fn init_default() {
|
pub fn init_default() {
|
||||||
// Tmux support
|
// Tmux support
|
||||||
TMUX.init(Mux::tmux_passthrough());
|
TMUX.init(Mux::tmux_passthrough());
|
||||||
ESCAPE.init(if *TMUX == 2 { "\x1b\x1b" } else { "\x1b" });
|
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
|
||||||
START.init(if *TMUX == 2 { "\x1bPtmux;\x1b\x1b" } else { "\x1b" });
|
START.init(if *TMUX { "\x1bPtmux;\x1b\x1b" } else { "\x1b" });
|
||||||
CLOSE.init(if *TMUX == 2 { "\x1b\\" } else { "" });
|
CLOSE.init(if *TMUX { "\x1b\\" } else { "" });
|
||||||
|
|
||||||
// WSL support
|
// WSL support
|
||||||
WSL.init(in_wsl());
|
WSL.init(in_wsl());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use yazi_shared::env_exists;
|
|
||||||
|
|
||||||
use crate::{CLOSE, ESCAPE, Emulator, NVIM, START, TMUX};
|
use crate::{CLOSE, ESCAPE, Emulator, NVIM, START, TMUX};
|
||||||
|
|
||||||
|
|
@ -8,7 +7,7 @@ pub struct Mux;
|
||||||
|
|
||||||
impl Mux {
|
impl Mux {
|
||||||
pub fn csi(s: &str) -> std::borrow::Cow<str> {
|
pub fn csi(s: &str) -> std::borrow::Cow<str> {
|
||||||
if *TMUX == 2 && !*NVIM {
|
if *TMUX && !*NVIM {
|
||||||
std::borrow::Cow::Owned(format!(
|
std::borrow::Cow::Owned(format!(
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
*START,
|
*START,
|
||||||
|
|
@ -20,9 +19,11 @@ impl Mux {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tmux_passthrough() -> u8 {
|
pub fn tmux_passthrough() -> bool {
|
||||||
if !env_exists("TMUX_PANE") || !env_exists("TMUX") {
|
if !std::env::var("TERM_PROGRAM").is_ok_and(|s| s == "tmux")
|
||||||
return 0;
|
&& !std::env::var("TERM").is_ok_and(|s| s.starts_with("tmux"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let child = std::process::Command::new("tmux")
|
let child = std::process::Command::new("tmux")
|
||||||
|
|
@ -33,23 +34,23 @@ impl Mux {
|
||||||
.spawn();
|
.spawn();
|
||||||
|
|
||||||
match child.and_then(|c| c.wait_with_output()) {
|
match child.and_then(|c| c.wait_with_output()) {
|
||||||
Ok(output) if output.status.success() => return 2,
|
Ok(o) if o.status.success() => {}
|
||||||
Ok(output) => {
|
Ok(o) => {
|
||||||
error!(
|
error!(
|
||||||
"Running `tmux set -p allow-passthrough on` failed: {:?}, {}",
|
"Running `tmux set -p allow-passthrough on` failed: {:?}, {}",
|
||||||
output.status,
|
o.status,
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&o.stderr)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(e) => {
|
||||||
error!("Failed to spawn `tmux set -p allow-passthrough on`: {err}");
|
error!("Failed to spawn `tmux set -p allow-passthrough on`: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tmux_drain() -> Result<()> {
|
pub fn tmux_drain() -> Result<()> {
|
||||||
if *TMUX == 2 && !*NVIM {
|
if *TMUX && !*NVIM {
|
||||||
crossterm::execute!(std::io::stderr(), crossterm::style::Print(Mux::csi("\x1b[5n")))?;
|
crossterm::execute!(std::io::stderr(), crossterm::style::Print(Mux::csi("\x1b[5n")))?;
|
||||||
_ = futures::executor::block_on(Emulator::read_until_dsr());
|
_ = futures::executor::block_on(Emulator::read_until_dsr());
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +74,7 @@ impl Mux {
|
||||||
|
|
||||||
pub(super) fn term_program() -> (Option<String>, Option<String>) {
|
pub(super) fn term_program() -> (Option<String>, Option<String>) {
|
||||||
let (mut term, mut program) = (None, None);
|
let (mut term, mut program) = (None, None);
|
||||||
if *TMUX == 0 {
|
if !*TMUX {
|
||||||
return (term, program);
|
return (term, program);
|
||||||
}
|
}
|
||||||
let Ok(output) = std::process::Command::new("tmux").arg("show-environment").output() else {
|
let Ok(output) = std::process::Command::new("tmux").arg("show-environment").output() else {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ impl Actions {
|
||||||
|
|
||||||
let emulator = yazi_adapter::Emulator::detect();
|
let emulator = yazi_adapter::Emulator::detect();
|
||||||
writeln!(s, "\nEmulator")?;
|
writeln!(s, "\nEmulator")?;
|
||||||
|
writeln!(s, " TERM : {:?}", env::var_os("TERM"))?;
|
||||||
|
writeln!(s, " TERM_PROGRAM : {:?}", env::var_os("TERM_PROGRAM"))?;
|
||||||
|
writeln!(s, " TERM_PROGRAM_VERSION: {:?}", env::var_os("TERM_PROGRAM_VERSION"))?;
|
||||||
writeln!(s, " Brand.from_env : {:?}", yazi_adapter::Brand::from_env())?;
|
writeln!(s, " Brand.from_env : {:?}", yazi_adapter::Brand::from_env())?;
|
||||||
writeln!(s, " Emulator.detect : {:?}", emulator)?;
|
writeln!(s, " Emulator.detect : {:?}", emulator)?;
|
||||||
writeln!(s, " Emulator.detect_full: {:?}", yazi_adapter::Emulator::detect_full())?;
|
writeln!(s, " Emulator.detect_full: {:?}", yazi_adapter::Emulator::detect_full())?;
|
||||||
|
|
@ -41,8 +44,8 @@ impl Actions {
|
||||||
writeln!(s, "\nWSL")?;
|
writeln!(s, "\nWSL")?;
|
||||||
writeln!(s, " WSL: {:?}", *yazi_adapter::WSL)?;
|
writeln!(s, " WSL: {:?}", *yazi_adapter::WSL)?;
|
||||||
|
|
||||||
writeln!(s, "\nNVIM")?;
|
writeln!(s, "\nNeovim")?;
|
||||||
writeln!(s, " NVIM : {:?}", *yazi_adapter::NVIM)?;
|
writeln!(s, " NVIM : {}", *yazi_adapter::NVIM)?;
|
||||||
writeln!(s, " Neovim version: {}", Self::process_output("nvim", "--version"))?;
|
writeln!(s, " Neovim version: {}", Self::process_output("nvim", "--version"))?;
|
||||||
|
|
||||||
writeln!(s, "\nVariables")?;
|
writeln!(s, "\nVariables")?;
|
||||||
|
|
@ -93,7 +96,7 @@ impl Actions {
|
||||||
writeln!(s, " chafa : {}", Self::process_output("chafa", "--version"))?;
|
writeln!(s, " chafa : {}", Self::process_output("chafa", "--version"))?;
|
||||||
writeln!(s, " zoxide : {}", Self::process_output("zoxide", "--version"))?;
|
writeln!(s, " zoxide : {}", Self::process_output("zoxide", "--version"))?;
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
writeln!(s, " 7z/7zz : {} / {}", Self::process_output("7z", "i"), Self::process_output("7zz", "i"))?;
|
writeln!(s, " 7zz/7z : {} / {}", Self::process_output("7zz", "i"), Self::process_output("7z", "i"))?;
|
||||||
writeln!(s, " jq : {}", Self::process_output("jq", "--version"))?;
|
writeln!(s, " jq : {}", Self::process_output("jq", "--version"))?;
|
||||||
|
|
||||||
writeln!(s, "\nClipboard")?;
|
writeln!(s, "\nClipboard")?;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use crossterm::style::{Color, Print, ResetColor, SetForegroundColor};
|
||||||
use tracing_appender::non_blocking::WorkerGuard;
|
use tracing_appender::non_blocking::WorkerGuard;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
use yazi_fs::Xdg;
|
use yazi_fs::Xdg;
|
||||||
|
|
@ -34,8 +35,11 @@ impl Logs {
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
_GUARD.init(guard);
|
_GUARD.init(guard);
|
||||||
eprintln!("Running with log level `{level}`, logs are written to {log_path:?}");
|
Ok(crossterm::execute!(
|
||||||
|
std::io::stderr(),
|
||||||
Ok(())
|
SetForegroundColor(Color::Yellow),
|
||||||
|
Print(format!("Running with log level `{level}`, logs are written to {log_path:?}\n")),
|
||||||
|
ResetColor
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{io::{self, BufWriter, Stderr, stderr}, ops::{Deref, DerefMut}, sync::atomic::{AtomicBool, AtomicU8, Ordering}};
|
use std::{io::{self, BufWriter, Stderr, stderr}, ops::{Deref, DerefMut}, sync::atomic::{AtomicBool, AtomicU8, Ordering}};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crossterm::{event::{DisableBracketedPaste, EnableBracketedPaste, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, style::Print, terminal::{EnterAlternateScreen, LeaveAlternateScreen, SetTitle, disable_raw_mode, enable_raw_mode}};
|
use crossterm::{event::{DisableBracketedPaste, EnableBracketedPaste, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, style::Print, terminal::{LeaveAlternateScreen, SetTitle, disable_raw_mode, enable_raw_mode}};
|
||||||
use cursor::RestoreCursor;
|
use cursor::RestoreCursor;
|
||||||
use ratatui::{CompletedFrame, Frame, Terminal, backend::CrosstermBackend, buffer::Buffer, layout::Rect};
|
use ratatui::{CompletedFrame, Frame, Terminal, backend::CrosstermBackend, buffer::Buffer, layout::Rect};
|
||||||
use yazi_adapter::{Emulator, Mux};
|
use yazi_adapter::{Emulator, Mux};
|
||||||
|
|
@ -26,17 +26,18 @@ impl Term {
|
||||||
};
|
};
|
||||||
|
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
if *yazi_adapter::TMUX != 0 {
|
if *yazi_adapter::TMUX {
|
||||||
yazi_adapter::Mux::tmux_passthrough();
|
yazi_adapter::Mux::tmux_passthrough();
|
||||||
}
|
}
|
||||||
|
|
||||||
execute!(
|
execute!(
|
||||||
BufWriter::new(stderr()),
|
BufWriter::new(stderr()),
|
||||||
|
screen::SetScreen(true),
|
||||||
Print(Mux::csi("\x1bP$q q\x1b\\")), // Request cursor shape (DECRQM)
|
Print(Mux::csi("\x1bP$q q\x1b\\")), // Request cursor shape (DECRQM)
|
||||||
Print(Mux::csi("\x1b[?12$p")), // Request cursor blink status (DECSET)
|
Print(Mux::csi("\x1b[?12$p")), // Request cursor blink status (DECSET)
|
||||||
Print("\x1b[?u"), // Request keyboard enhancement flags (CSI u)
|
Print("\x1b[?u"), // Request keyboard enhancement flags (CSI u)
|
||||||
Print(Mux::csi("\x1b[0c")), // Request device attributes
|
Print(Mux::csi("\x1b[0c")), // Request device attributes
|
||||||
EnterAlternateScreen,
|
screen::SetScreen(false),
|
||||||
EnableBracketedPaste,
|
EnableBracketedPaste,
|
||||||
mouse::SetMouse(true),
|
mouse::SetMouse(true),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -258,3 +259,24 @@ mod cursor {
|
||||||
fn execute_winapi(&self) -> std::io::Result<()> { Ok(()) }
|
fn execute_winapi(&self) -> std::io::Result<()> { Ok(()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod screen {
|
||||||
|
use crossterm::terminal::EnterAlternateScreen;
|
||||||
|
use yazi_adapter::TMUX;
|
||||||
|
|
||||||
|
pub struct SetScreen(pub bool);
|
||||||
|
|
||||||
|
impl crossterm::Command for SetScreen {
|
||||||
|
fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result {
|
||||||
|
if self.0 == *TMUX { Ok(()) } else { EnterAlternateScreen.write_ansi(f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn execute_winapi(&self) -> std::io::Result<()> {
|
||||||
|
if self.0 == *TMUX { Ok(()) } else { EnterAlternateScreen.execute_winapi() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn is_ansi_code_supported(&self) -> bool { EnterAlternateScreen.is_ansi_code_supported() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ function M:peek(job)
|
||||||
return require("empty").msg(
|
return require("empty").msg(
|
||||||
job,
|
job,
|
||||||
code == 2 and "File list in this archive is encrypted"
|
code == 2 and "File list in this archive is encrypted"
|
||||||
or "Failed to start both `7z` and `7zz`. Do you have 7-zip installed?"
|
or "Failed to start both `7zz` and `7z`. Do you have 7-zip installed?"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -55,15 +55,9 @@ function M.spawn_7z(args)
|
||||||
return child
|
return child
|
||||||
end
|
end
|
||||||
|
|
||||||
local child
|
local child = try("7zz") or try("7z")
|
||||||
if ya.target_os() == "macos" then
|
|
||||||
child = try("7zz") or try("7z")
|
|
||||||
else
|
|
||||||
child = try("7z") or try("7zz")
|
|
||||||
end
|
|
||||||
|
|
||||||
if not child then
|
if not child then
|
||||||
return ya.err("Failed to start both `7z` and `7zz`, error: " .. last_err)
|
return ya.err("Failed to start both `7zz` and `7z`, error: " .. last_err)
|
||||||
end
|
end
|
||||||
return child, last_err
|
return child, last_err
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ function M:try_with(from, pwd, to)
|
||||||
local archive = require("archive")
|
local archive = require("archive")
|
||||||
local child, err = archive.spawn_7z { "x", "-aou", "-sccUTF-8", "-p" .. pwd, "-o" .. tostring(tmp), tostring(from) }
|
local child, err = archive.spawn_7z { "x", "-aou", "-sccUTF-8", "-p" .. pwd, "-o" .. tostring(tmp), tostring(from) }
|
||||||
if not child then
|
if not child then
|
||||||
fail("Failed to start both `7z` and `7zz`, error: " .. err)
|
fail("Failed to start both `7zz` and `7z`, error: " .. err)
|
||||||
end
|
end
|
||||||
|
|
||||||
local output, err = child:wait_with_output()
|
local output, err = child:wait_with_output()
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ function M:preload(job)
|
||||||
"-font",
|
"-font",
|
||||||
tostring(job.file.url),
|
tostring(job.file.url),
|
||||||
"-pointsize",
|
"-pointsize",
|
||||||
"64",
|
64,
|
||||||
"xc:white",
|
"xc:white",
|
||||||
"-fill",
|
"-fill",
|
||||||
"black",
|
"black",
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,21 @@ function M:preload(job)
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, err = Command("magick"):args({
|
local status, err = Command("magick")
|
||||||
"-density",
|
:args({
|
||||||
"200",
|
"-density",
|
||||||
tostring(job.file.url),
|
200,
|
||||||
"-flatten",
|
tostring(job.file.url),
|
||||||
"-resize",
|
"-flatten",
|
||||||
string.format("%dx%d^", PREVIEW.max_width, PREVIEW.max_height),
|
"-resize",
|
||||||
"-quality",
|
string.format("%dx%d^", PREVIEW.max_width, PREVIEW.max_height),
|
||||||
PREVIEW.image_quality,
|
"-quality",
|
||||||
"-auto-orient",
|
PREVIEW.image_quality,
|
||||||
"JPG:" .. tostring(cache),
|
"-auto-orient",
|
||||||
}):status()
|
"JPG:" .. tostring(cache),
|
||||||
|
})
|
||||||
|
:env("MAGICK_THREAD_LIMIT", 1)
|
||||||
|
:status()
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
return status.success and 1 or 2
|
return status.success and 1 or 2
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,8 @@ local function entry()
|
||||||
:args({ "query", "-i", "--exclude" })
|
:args({ "query", "-i", "--exclude" })
|
||||||
:arg(st.cwd)
|
:arg(st.cwd)
|
||||||
:env("SHELL", "sh")
|
:env("SHELL", "sh")
|
||||||
:env("CLICOLOR", "1")
|
:env("CLICOLOR", 1)
|
||||||
:env("CLICOLOR_FORCE", "1")
|
:env("CLICOLOR_FORCE", 1)
|
||||||
:env("_ZO_FZF_OPTS", options())
|
:env("_ZO_FZF_OPTS", options())
|
||||||
:stdin(Command.INHERIT)
|
:stdin(Command.INHERIT)
|
||||||
:stdout(Command.PIPED)
|
:stdout(Command.PIPED)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue