feat: yazi --debug supports detecting whether tmux is built with --enable-sixel (#1762)

This commit is contained in:
三咲雅 · Misaki Masa 2024-10-11 19:39:47 +08:00 committed by GitHub
parent 2014aee646
commit c84917c5e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 83 additions and 40 deletions

View file

@ -7,7 +7,7 @@ use tokio::{io::{AsyncReadExt, BufReader}, time::timeout};
use tracing::{error, warn};
use yazi_shared::env_exists;
use crate::{Adapter, TMUX, tcsi};
use crate::{Adapter, Mux, TMUX};
#[derive(Clone, Debug)]
pub enum Emulator {
@ -103,24 +103,11 @@ impl Emulator {
}
pub fn via_env() -> (String, String) {
fn tmux_env(name: &str) -> Option<String> {
String::from_utf8_lossy(
&std::process::Command::new("tmux").args(["show-environment", name]).output().ok()?.stdout,
)
.trim()
.strip_prefix(&format!("{name}="))
.map(ToOwned::to_owned)
}
let mut term = std::env::var("TERM").unwrap_or_default();
let mut program = std::env::var("TERM_PROGRAM").unwrap_or_default();
if *TMUX {
term = tmux_env("TERM").unwrap_or(term);
program = tmux_env("TERM_PROGRAM").unwrap_or(program);
}
(term, program)
let (term, program) = Mux::term_program();
(
term.unwrap_or(std::env::var("TERM").unwrap_or_default()),
program.unwrap_or(std::env::var("TERM_PROGRAM").unwrap_or_default()),
)
}
pub fn via_csi() -> Result<Self> {
@ -130,7 +117,7 @@ impl Emulator {
execute!(
LineWriter::new(stderr()),
SavePosition,
Print(tcsi("\x1b[>q\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\\x1b[c")),
Print(Mux::csi("\x1b[>q\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\\x1b[c")),
RestorePosition
)?;

View file

@ -8,6 +8,7 @@ mod iip;
mod image;
mod kgp;
mod kgp_old;
mod mux;
mod sixel;
mod ueberzug;
@ -18,6 +19,7 @@ pub use emulator::*;
use iip::*;
use kgp::*;
use kgp_old::*;
pub use mux::*;
use sixel::*;
use ueberzug::*;
use yazi_shared::{RoCell, env_exists, in_wsl};
@ -63,16 +65,3 @@ pub fn init() {
ADAPTOR.init(Adapter::matches());
ADAPTOR.start();
}
pub fn tcsi(s: &str) -> std::borrow::Cow<str> {
if *TMUX {
std::borrow::Cow::Owned(format!(
"{}{}{}",
*START,
s.trim_start_matches('\x1b').replace('\x1b', *ESCAPE),
*CLOSE
))
} else {
std::borrow::Cow::Borrowed(s)
}
}

56
yazi-adapter/src/mux.rs Normal file
View file

@ -0,0 +1,56 @@
use crate::{CLOSE, ESCAPE, START, TMUX};
pub struct Mux;
impl Mux {
pub fn csi(s: &str) -> std::borrow::Cow<str> {
if *TMUX {
std::borrow::Cow::Owned(format!(
"{}{}{}",
*START,
s.trim_start_matches('\x1b').replace('\x1b', *ESCAPE),
*CLOSE
))
} else {
std::borrow::Cow::Borrowed(s)
}
}
pub fn tmux_sixel_flag() -> &'static str {
let stdout = std::process::Command::new("tmux")
.args(["-LwU0dju1is5", "-f/dev/null", "start", ";", "display", "-p", "#{sixel_support}"])
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_default();
match stdout.trim() {
"1" => "Supported",
"0" => "Unsupported",
_ => "Unknown",
}
}
pub(super) fn term_program() -> (Option<String>, Option<String>) {
let (mut term, mut program) = (None, None);
if !*TMUX {
return (term, program);
}
let Ok(output) = std::process::Command::new("tmux").arg("show-environment").output() else {
return (term, program);
};
for line in String::from_utf8_lossy(&output.stdout).lines() {
if let Some((k, v)) = line.trim().split_once('=') {
match k {
"TERM" => term = Some(v.to_owned()),
"TERM_PROGRAM" => program = Some(v.to_owned()),
_ => continue,
}
}
if term.is_some() && program.is_some() {
break;
}
}
(term, program)
}
}

View file

@ -1,6 +1,7 @@
use std::{env, ffi::OsStr, fmt::Write};
use regex::Regex;
use yazi_adapter::Mux;
use yazi_shared::Xdg;
use super::Actions;
@ -51,14 +52,24 @@ impl Actions {
writeln!(s, "\nText Opener")?;
writeln!(
s,
" default: {:?}",
" default : {:?}",
yazi_config::OPEN.openers("f75a.txt", "text/plain").and_then(|a| a.first().cloned())
)?;
writeln!(s, " block : {:?}", yazi_config::OPEN.block_opener("bulk.txt", "text/plain"))?;
writeln!(
s,
" block-create: {:?}",
yazi_config::OPEN.block_opener("bulk-create.txt", "text/plain")
)?;
writeln!(
s,
" block-rename: {:?}",
yazi_config::OPEN.block_opener("bulk-rename.txt", "text/plain")
)?;
writeln!(s, "\nMultiplexers")?;
writeln!(s, " TMUX : {:?}", *yazi_adapter::TMUX)?;
writeln!(s, " tmux version : {}", Self::process_output("tmux", "-V"))?;
writeln!(s, " tmux build flags : enable-sixel={}", Mux::tmux_sixel_flag())?;
writeln!(s, " ZELLIJ_SESSION_NAME: {:?}", env::var_os("ZELLIJ_SESSION_NAME"))?;
writeln!(s, " Zellij version : {}", Self::process_output("zellij", "--version"))?;

View file

@ -12,7 +12,7 @@ use crate::manager::Manager;
impl Manager {
pub(super) fn bulk_rename(&self) {
let Some(opener) = OPEN.block_opener("bulk.txt", "text/plain") else {
let Some(opener) = OPEN.block_opener("bulk-rename.txt", "text/plain") else {
return AppProxy::notify_warn("Bulk rename", "No text opener found");
};

View file

@ -4,7 +4,7 @@ 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 cursor::RestoreCursor;
use ratatui::{CompletedFrame, Frame, Terminal, backend::CrosstermBackend, buffer::Buffer, layout::Rect};
use yazi_adapter::{Emulator, tcsi};
use yazi_adapter::{Emulator, Mux};
use yazi_config::{INPUT, MANAGER};
static CSI_U: AtomicBool = AtomicBool::new(false);
@ -28,9 +28,9 @@ impl Term {
enable_raw_mode()?;
execute!(
BufWriter::new(stderr()),
Print(tcsi("\x1b[?12$p")), // Request cursor blink status (DECSET)
Print(tcsi("\x1bP$q q\x1b\\")), // Request cursor shape (DECRQM)
Print(tcsi("\x1b[?u\x1b[c")), // Request keyboard enhancement flags (CSI u)
Print(Mux::csi("\x1b[?12$p")), // Request cursor blink status (DECSET)
Print(Mux::csi("\x1bP$q q\x1b\\")), // Request cursor shape (DECRQM)
Print(Mux::csi("\x1b[?u\x1b[c")), // Request keyboard enhancement flags (CSI u)
EnterAlternateScreen,
EnableBracketedPaste,
mouse::SetMouse(true),