mirror of
https://github.com/sxyazi/yazi.git
synced 2024-11-24 09:53:12 +03:00
feat: add --debug
flag to print debug information (#794)
This commit is contained in:
parent
9396d8760c
commit
b10f2de16d
23
.github/ISSUE_TEMPLATE/bug.yml
vendored
23
.github/ISSUE_TEMPLATE/bug.yml
vendored
@ -12,21 +12,14 @@ body:
|
|||||||
- Linux Wayland
|
- Linux Wayland
|
||||||
- macOS
|
- macOS
|
||||||
- Windows
|
- Windows
|
||||||
|
- Windows WSL
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: terminal
|
id: terminal
|
||||||
attributes:
|
attributes:
|
||||||
label: What terminal are you running Yazi in?
|
label: What terminal are you running Yazi in?
|
||||||
placeholder: "ex: Kitty v0.30.1"
|
placeholder: "ex: kitty v0.32.2"
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Yazi version
|
|
||||||
description: Please do a `yazi -V` and paste the output here.
|
|
||||||
placeholder: "ex: yazi 0.1.5 (3867c29 2023-11-25)"
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
@ -38,6 +31,18 @@ body:
|
|||||||
- Not tried, and I'll explain why below
|
- Not tried, and I'll explain why below
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: debug
|
||||||
|
attributes:
|
||||||
|
label: "`yazi --debug` output"
|
||||||
|
description: Please do a `yazi --debug` and paste the output here.
|
||||||
|
value: |
|
||||||
|
<!-- Paste the output between the backticks below: -->
|
||||||
|
```sh
|
||||||
|
|
||||||
|
```
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2716,6 +2716,7 @@ dependencies = [
|
|||||||
"clap_complete_nushell",
|
"clap_complete_nushell",
|
||||||
"serde",
|
"serde",
|
||||||
"vergen",
|
"vergen",
|
||||||
|
"yazi-adaptor",
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use std::{env, fmt::Display, io::{Read, Write}, path::Path, sync::Arc};
|
use std::{env, fmt::Display, path::Path, sync::Arc};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use yazi_shared::{env_exists, term::Term};
|
use yazi_shared::{env_exists, term::Term};
|
||||||
|
|
||||||
use super::{Iterm2, Kitty, KittyOld};
|
use super::{Iterm2, Kitty, KittyOld};
|
||||||
use crate::{ueberzug::Ueberzug, Sixel, SHOWN, TMUX};
|
use crate::{ueberzug::Ueberzug, Emulator, Sixel, SHOWN, TMUX};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum Adaptor {
|
pub enum Adaptor {
|
||||||
@ -22,82 +21,73 @@ pub enum Adaptor {
|
|||||||
Chafa,
|
Chafa,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
impl Display for Adaptor {
|
||||||
enum Emulator {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
Unknown(Vec<Adaptor>),
|
match self {
|
||||||
Kitty,
|
Self::Kitty => write!(f, "kitty"),
|
||||||
Konsole,
|
Self::KittyOld => write!(f, "kitty"),
|
||||||
Iterm2,
|
Self::Iterm2 => write!(f, "iterm2"),
|
||||||
WezTerm,
|
Self::Sixel => write!(f, "sixel"),
|
||||||
Foot,
|
Self::X11 => write!(f, "x11"),
|
||||||
Ghostty,
|
Self::Wayland => write!(f, "wayland"),
|
||||||
BlackBox,
|
Self::Chafa => write!(f, "chafa"),
|
||||||
VSCode,
|
}
|
||||||
Tabby,
|
}
|
||||||
Hyper,
|
|
||||||
Mintty,
|
|
||||||
Neovim,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Adaptor {
|
impl Adaptor {
|
||||||
fn emulator() -> Emulator {
|
pub async fn image_show(self, path: &Path, rect: Rect) -> Result<(u32, u32)> {
|
||||||
if env_exists("NVIM_LOG_FILE") && env_exists("NVIM") {
|
match self {
|
||||||
return Emulator::Neovim;
|
Self::Kitty => Kitty::image_show(path, rect).await,
|
||||||
|
Self::KittyOld => KittyOld::image_show(path, rect).await,
|
||||||
|
Self::Iterm2 => Iterm2::image_show(path, rect).await,
|
||||||
|
Self::Sixel => Sixel::image_show(path, rect).await,
|
||||||
|
_ => Ueberzug::image_show(path, rect).await,
|
||||||
}
|
}
|
||||||
|
|
||||||
let vars = [
|
|
||||||
("KITTY_WINDOW_ID", Emulator::Kitty),
|
|
||||||
("KONSOLE_VERSION", Emulator::Konsole),
|
|
||||||
("ITERM_SESSION_ID", Emulator::Iterm2),
|
|
||||||
("WEZTERM_EXECUTABLE", Emulator::WezTerm),
|
|
||||||
("GHOSTTY_RESOURCES_DIR", Emulator::Ghostty),
|
|
||||||
("VSCODE_INJECTION", Emulator::VSCode),
|
|
||||||
("TABBY_CONFIG_DIRECTORY", Emulator::Tabby),
|
|
||||||
];
|
|
||||||
match vars.into_iter().find(|v| env_exists(v.0)) {
|
|
||||||
Some(var) => return var.1,
|
|
||||||
None => warn!("[Adaptor] No special environment variables detected"),
|
|
||||||
}
|
|
||||||
|
|
||||||
let (term, program) = Self::via_env();
|
|
||||||
match program.as_str() {
|
|
||||||
"iTerm.app" => return Emulator::Iterm2,
|
|
||||||
"WezTerm" => return Emulator::WezTerm,
|
|
||||||
"ghostty" => return Emulator::Ghostty,
|
|
||||||
"BlackBox" => return Emulator::BlackBox,
|
|
||||||
"vscode" => return Emulator::VSCode,
|
|
||||||
"Tabby" => return Emulator::Tabby,
|
|
||||||
"Hyper" => return Emulator::Hyper,
|
|
||||||
"mintty" => return Emulator::Mintty,
|
|
||||||
_ => warn!("[Adaptor] Unknown TERM_PROGRAM: {program}"),
|
|
||||||
}
|
|
||||||
match term.as_str() {
|
|
||||||
"xterm-kitty" => return Emulator::Kitty,
|
|
||||||
"foot" => return Emulator::Foot,
|
|
||||||
"foot-extra" => return Emulator::Foot,
|
|
||||||
"xterm-ghostty" => return Emulator::Ghostty,
|
|
||||||
_ => warn!("[Adaptor] Unknown TERM: {term}"),
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::via_csi().unwrap_or(Emulator::Unknown(vec![]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn detect() -> Self {
|
pub fn image_hide(self) -> Result<()> {
|
||||||
let mut protocols = match Self::emulator() {
|
if let Some(rect) = SHOWN.swap(None) { self.image_erase(*rect) } else { Ok(()) }
|
||||||
Emulator::Unknown(adapters) => adapters,
|
}
|
||||||
Emulator::Kitty => vec![Self::Kitty],
|
|
||||||
Emulator::Konsole => vec![Self::KittyOld, Self::Iterm2, Self::Sixel],
|
pub fn image_erase(self, rect: Rect) -> Result<()> {
|
||||||
Emulator::Iterm2 => vec![Self::Iterm2, Self::Sixel],
|
match self {
|
||||||
Emulator::WezTerm => vec![Self::Iterm2, Self::Sixel],
|
Self::Kitty => Kitty::image_erase(rect),
|
||||||
Emulator::Foot => vec![Self::Sixel],
|
Self::Iterm2 => Iterm2::image_erase(rect),
|
||||||
Emulator::Ghostty => vec![Self::KittyOld],
|
Self::KittyOld => KittyOld::image_erase(),
|
||||||
Emulator::BlackBox => vec![Self::Sixel],
|
Self::Sixel => Sixel::image_erase(rect),
|
||||||
Emulator::VSCode => vec![Self::Iterm2, Self::Sixel],
|
_ => Ueberzug::image_erase(rect),
|
||||||
Emulator::Tabby => vec![Self::Iterm2, Self::Sixel],
|
}
|
||||||
Emulator::Hyper => vec![Self::Iterm2, Self::Sixel],
|
}
|
||||||
Emulator::Mintty => vec![Self::Iterm2],
|
|
||||||
Emulator::Neovim => vec![],
|
#[inline]
|
||||||
};
|
pub fn shown_load(self) -> Option<Rect> { SHOWN.load_full().map(|r| *r) }
|
||||||
|
|
||||||
|
pub(super) fn start(self) { Ueberzug::start(self); }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn shown_store(rect: Rect, size: (u32, u32)) {
|
||||||
|
SHOWN.store(Some(Arc::new(
|
||||||
|
Term::ratio()
|
||||||
|
.map(|(r1, r2)| Rect {
|
||||||
|
x: rect.x,
|
||||||
|
y: rect.y,
|
||||||
|
width: (size.0 as f64 / r1).ceil() as u16,
|
||||||
|
height: (size.1 as f64 / r2).ceil() as u16,
|
||||||
|
})
|
||||||
|
.unwrap_or(rect),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn needs_ueberzug(self) -> bool {
|
||||||
|
!matches!(self, Self::Kitty | Self::KittyOld | Self::Iterm2 | Self::Sixel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Adaptor {
|
||||||
|
pub fn matches() -> Self {
|
||||||
|
let mut protocols = Emulator::detect().adapters();
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
protocols.retain(|p| *p == Self::Iterm2);
|
protocols.retain(|p| *p == Self::Iterm2);
|
||||||
@ -129,134 +119,4 @@ impl Adaptor {
|
|||||||
warn!("[Adaptor] Falling back to chafa");
|
warn!("[Adaptor] Falling back to chafa");
|
||||||
Self::Chafa
|
Self::Chafa
|
||||||
}
|
}
|
||||||
|
|
||||||
fn via_env() -> (String, String) {
|
|
||||||
fn tmux_env(name: &str) -> Result<String> {
|
|
||||||
let output = std::process::Command::new("tmux").args(["show-environment", name]).output()?;
|
|
||||||
|
|
||||||
String::from_utf8(output.stdout)?
|
|
||||||
.trim()
|
|
||||||
.strip_prefix(&format!("{name}="))
|
|
||||||
.map_or_else(|| Err(anyhow!("")), |s| Ok(s.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut term = env::var("TERM").unwrap_or_default();
|
|
||||||
let mut program = 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn via_csi() -> Result<Emulator> {
|
|
||||||
enable_raw_mode()?;
|
|
||||||
std::io::stdout().write_all(b"\x1b[>q\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\\x1b[c")?;
|
|
||||||
std::io::stdout().flush()?;
|
|
||||||
|
|
||||||
let mut stdin = std::io::stdin().lock();
|
|
||||||
let mut buf = String::with_capacity(200);
|
|
||||||
loop {
|
|
||||||
let mut c = [0; 1];
|
|
||||||
if stdin.read(&mut c)? == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if c[0] == b'c' && buf.contains("\x1b[?") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf.push(c[0] as char);
|
|
||||||
}
|
|
||||||
|
|
||||||
disable_raw_mode().ok();
|
|
||||||
let names = [
|
|
||||||
("kitty", Emulator::Kitty),
|
|
||||||
("Konsole", Emulator::Konsole),
|
|
||||||
("iTerm2", Emulator::Iterm2),
|
|
||||||
("WezTerm", Emulator::WezTerm),
|
|
||||||
("foot", Emulator::Foot),
|
|
||||||
("ghostty", Emulator::Ghostty),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (name, emulator) in names.iter() {
|
|
||||||
if buf.contains(name) {
|
|
||||||
return Ok(emulator.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut adapters = Vec::with_capacity(2);
|
|
||||||
if buf.contains("\x1b_Gi=31;OK") {
|
|
||||||
adapters.push(Adaptor::KittyOld);
|
|
||||||
}
|
|
||||||
if ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| buf.contains(s)) {
|
|
||||||
adapters.push(Adaptor::Sixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Emulator::Unknown(adapters))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Adaptor {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Kitty => write!(f, "kitty"),
|
|
||||||
Self::KittyOld => write!(f, "kitty"),
|
|
||||||
Self::Iterm2 => write!(f, "iterm2"),
|
|
||||||
Self::Sixel => write!(f, "sixel"),
|
|
||||||
Self::X11 => write!(f, "x11"),
|
|
||||||
Self::Wayland => write!(f, "wayland"),
|
|
||||||
Self::Chafa => write!(f, "chafa"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Adaptor {
|
|
||||||
pub(super) fn start(self) { Ueberzug::start(self); }
|
|
||||||
|
|
||||||
pub async fn image_show(self, path: &Path, rect: Rect) -> Result<(u32, u32)> {
|
|
||||||
match self {
|
|
||||||
Self::Kitty => Kitty::image_show(path, rect).await,
|
|
||||||
Self::KittyOld => KittyOld::image_show(path, rect).await,
|
|
||||||
Self::Iterm2 => Iterm2::image_show(path, rect).await,
|
|
||||||
Self::Sixel => Sixel::image_show(path, rect).await,
|
|
||||||
_ => Ueberzug::image_show(path, rect).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn image_hide(self) -> Result<()> {
|
|
||||||
if let Some(rect) = SHOWN.swap(None) { self.image_erase(*rect) } else { Ok(()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn image_erase(self, rect: Rect) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
Self::Kitty => Kitty::image_erase(rect),
|
|
||||||
Self::Iterm2 => Iterm2::image_erase(rect),
|
|
||||||
Self::KittyOld => KittyOld::image_erase(),
|
|
||||||
Self::Sixel => Sixel::image_erase(rect),
|
|
||||||
_ => Ueberzug::image_erase(rect),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn shown_load(self) -> Option<Rect> { SHOWN.load_full().map(|r| *r) }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super) fn shown_store(rect: Rect, size: (u32, u32)) {
|
|
||||||
SHOWN.store(Some(Arc::new(
|
|
||||||
Term::ratio()
|
|
||||||
.map(|(r1, r2)| Rect {
|
|
||||||
x: rect.x,
|
|
||||||
y: rect.y,
|
|
||||||
width: (size.0 as f64 / r1).ceil() as u16,
|
|
||||||
height: (size.1 as f64 / r2).ceil() as u16,
|
|
||||||
})
|
|
||||||
.unwrap_or(rect),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super) fn needs_ueberzug(self) -> bool {
|
|
||||||
!matches!(self, Self::Kitty | Self::KittyOld | Self::Iterm2 | Self::Sixel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
155
yazi-adaptor/src/emulator.rs
Normal file
155
yazi-adaptor/src/emulator.rs
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
use std::{env, io::{Read, Write}};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
|
use tracing::warn;
|
||||||
|
use yazi_shared::env_exists;
|
||||||
|
|
||||||
|
use crate::{Adaptor, TMUX};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Emulator {
|
||||||
|
Unknown(Vec<Adaptor>),
|
||||||
|
Kitty,
|
||||||
|
Konsole,
|
||||||
|
Iterm2,
|
||||||
|
WezTerm,
|
||||||
|
Foot,
|
||||||
|
Ghostty,
|
||||||
|
BlackBox,
|
||||||
|
VSCode,
|
||||||
|
Tabby,
|
||||||
|
Hyper,
|
||||||
|
Mintty,
|
||||||
|
Neovim,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emulator {
|
||||||
|
pub fn adapters(self) -> Vec<Adaptor> {
|
||||||
|
match self {
|
||||||
|
Self::Unknown(adapters) => adapters,
|
||||||
|
Self::Kitty => vec![Adaptor::Kitty],
|
||||||
|
Self::Konsole => vec![Adaptor::KittyOld, Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::Iterm2 => vec![Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::WezTerm => vec![Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::Foot => vec![Adaptor::Sixel],
|
||||||
|
Self::Ghostty => vec![Adaptor::KittyOld],
|
||||||
|
Self::BlackBox => vec![Adaptor::Sixel],
|
||||||
|
Self::VSCode => vec![Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::Tabby => vec![Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::Hyper => vec![Adaptor::Iterm2, Adaptor::Sixel],
|
||||||
|
Self::Mintty => vec![Adaptor::Iterm2],
|
||||||
|
Self::Neovim => vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emulator {
|
||||||
|
pub fn detect() -> Self {
|
||||||
|
if env_exists("NVIM_LOG_FILE") && env_exists("NVIM") {
|
||||||
|
return Self::Neovim;
|
||||||
|
}
|
||||||
|
|
||||||
|
let vars = [
|
||||||
|
("KITTY_WINDOW_ID", Self::Kitty),
|
||||||
|
("KONSOLE_VERSION", Self::Konsole),
|
||||||
|
("ITERM_SESSION_ID", Self::Iterm2),
|
||||||
|
("WEZTERM_EXECUTABLE", Self::WezTerm),
|
||||||
|
("GHOSTTY_RESOURCES_DIR", Self::Ghostty),
|
||||||
|
("VSCODE_INJECTION", Self::VSCode),
|
||||||
|
("TABBY_CONFIG_DIRECTORY", Self::Tabby),
|
||||||
|
];
|
||||||
|
match vars.into_iter().find(|v| env_exists(v.0)) {
|
||||||
|
Some(var) => return var.1,
|
||||||
|
None => warn!("[Adaptor] No special environment variables detected"),
|
||||||
|
}
|
||||||
|
|
||||||
|
let (term, program) = Self::via_env();
|
||||||
|
match program.as_str() {
|
||||||
|
"iTerm.app" => return Self::Iterm2,
|
||||||
|
"WezTerm" => return Self::WezTerm,
|
||||||
|
"ghostty" => return Self::Ghostty,
|
||||||
|
"BlackBox" => return Self::BlackBox,
|
||||||
|
"vscode" => return Self::VSCode,
|
||||||
|
"Tabby" => return Self::Tabby,
|
||||||
|
"Hyper" => return Self::Hyper,
|
||||||
|
"mintty" => return Self::Mintty,
|
||||||
|
_ => warn!("[Adaptor] Unknown TERM_PROGRAM: {program}"),
|
||||||
|
}
|
||||||
|
match term.as_str() {
|
||||||
|
"xterm-kitty" => return Self::Kitty,
|
||||||
|
"foot" => return Self::Foot,
|
||||||
|
"foot-extra" => return Self::Foot,
|
||||||
|
"xterm-ghostty" => return Self::Ghostty,
|
||||||
|
_ => warn!("[Adaptor] Unknown TERM: {term}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::via_csi().unwrap_or(Self::Unknown(vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn via_env() -> (String, String) {
|
||||||
|
fn tmux_env(name: &str) -> Result<String> {
|
||||||
|
let output = std::process::Command::new("tmux").args(["show-environment", name]).output()?;
|
||||||
|
|
||||||
|
String::from_utf8(output.stdout)?
|
||||||
|
.trim()
|
||||||
|
.strip_prefix(&format!("{name}="))
|
||||||
|
.map_or_else(|| Err(anyhow!("")), |s| Ok(s.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut term = env::var("TERM").unwrap_or_default();
|
||||||
|
let mut program = 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn via_csi() -> Result<Self> {
|
||||||
|
enable_raw_mode()?;
|
||||||
|
std::io::stdout().write_all(b"\x1b[>q\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\\x1b[c")?;
|
||||||
|
std::io::stdout().flush()?;
|
||||||
|
|
||||||
|
let mut stdin = std::io::stdin().lock();
|
||||||
|
let mut buf = String::with_capacity(200);
|
||||||
|
loop {
|
||||||
|
let mut c = [0; 1];
|
||||||
|
if stdin.read(&mut c)? == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if c[0] == b'c' && buf.contains("\x1b[?") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf.push(c[0] as char);
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_raw_mode().ok();
|
||||||
|
let names = [
|
||||||
|
("kitty", Self::Kitty),
|
||||||
|
("Konsole", Self::Konsole),
|
||||||
|
("iTerm2", Self::Iterm2),
|
||||||
|
("WezTerm", Self::WezTerm),
|
||||||
|
("foot", Self::Foot),
|
||||||
|
("ghostty", Self::Ghostty),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (name, emulator) in names.iter() {
|
||||||
|
if buf.contains(name) {
|
||||||
|
return Ok(emulator.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut adapters = Vec::with_capacity(2);
|
||||||
|
if buf.contains("\x1b_Gi=31;OK") {
|
||||||
|
adapters.push(Adaptor::KittyOld);
|
||||||
|
}
|
||||||
|
if ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| buf.contains(s)) {
|
||||||
|
adapters.push(Adaptor::Sixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self::Unknown(adapters))
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#![allow(clippy::unit_arg)]
|
#![allow(clippy::unit_arg)]
|
||||||
|
|
||||||
mod adaptor;
|
mod adaptor;
|
||||||
|
mod emulator;
|
||||||
mod image;
|
mod image;
|
||||||
mod iterm2;
|
mod iterm2;
|
||||||
mod kitty;
|
mod kitty;
|
||||||
@ -8,7 +9,8 @@ mod kitty_old;
|
|||||||
mod sixel;
|
mod sixel;
|
||||||
mod ueberzug;
|
mod ueberzug;
|
||||||
|
|
||||||
use adaptor::*;
|
pub use adaptor::*;
|
||||||
|
pub use emulator::*;
|
||||||
use iterm2::*;
|
use iterm2::*;
|
||||||
use kitty::*;
|
use kitty::*;
|
||||||
use kitty_old::*;
|
use kitty_old::*;
|
||||||
@ -20,7 +22,7 @@ pub use crate::image::*;
|
|||||||
pub static ADAPTOR: RoCell<Adaptor> = RoCell::new();
|
pub static ADAPTOR: RoCell<Adaptor> = RoCell::new();
|
||||||
|
|
||||||
// Tmux support
|
// Tmux support
|
||||||
static TMUX: RoCell<bool> = 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();
|
||||||
@ -36,7 +38,7 @@ pub fn init() {
|
|||||||
|
|
||||||
SHOWN.with(Default::default);
|
SHOWN.with(Default::default);
|
||||||
|
|
||||||
ADAPTOR.init(Adaptor::detect());
|
ADAPTOR.init(Adaptor::matches());
|
||||||
ADAPTOR.start();
|
ADAPTOR.start();
|
||||||
|
|
||||||
if *TMUX {
|
if *TMUX {
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::{bail, Result};
|
|||||||
use imagesize::ImageSize;
|
use imagesize::ImageSize;
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}};
|
use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}};
|
||||||
use tracing::debug;
|
use tracing::{debug, warn};
|
||||||
use yazi_config::PREVIEW;
|
use yazi_config::PREVIEW;
|
||||||
use yazi_shared::RoCell;
|
use yazi_shared::RoCell;
|
||||||
|
|
||||||
@ -71,14 +71,17 @@ impl Ueberzug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_demon(adaptor: Adaptor) -> Result<Child> {
|
fn create_demon(adaptor: Adaptor) -> Result<Child> {
|
||||||
Ok(
|
let result = Command::new("ueberzug")
|
||||||
Command::new("ueberzug")
|
.args(["layer", "-so", &adaptor.to_string()])
|
||||||
.args(["layer", "-so", &adaptor.to_string()])
|
.kill_on_drop(true)
|
||||||
.kill_on_drop(true)
|
.stdin(Stdio::piped())
|
||||||
.stdin(Stdio::piped())
|
.stderr(Stdio::null())
|
||||||
.stderr(Stdio::null())
|
.spawn();
|
||||||
.spawn()?,
|
|
||||||
)
|
if let Err(ref e) = result {
|
||||||
|
warn!("ueberzug spawning failed: {}", e);
|
||||||
|
}
|
||||||
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_rect(mut rect: Rect) -> Rect {
|
fn adjust_rect(mut rect: Rect) -> Rect {
|
||||||
|
@ -9,8 +9,9 @@ homepage = "https://yazi-rs.github.io"
|
|||||||
repository = "https://github.com/sxyazi/yazi"
|
repository = "https://github.com/sxyazi/yazi"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
yazi-config = { path = "../yazi-config", version = "0.2.4" }
|
yazi-adaptor = { path = "../yazi-adaptor", version = "0.2.4" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
yazi-config = { path = "../yazi-config", version = "0.2.4" }
|
||||||
|
yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
clap = { version = "^4", features = [ "derive" ] }
|
clap = { version = "^4", features = [ "derive" ] }
|
||||||
|
@ -20,6 +20,10 @@ pub struct Args {
|
|||||||
#[arg(long, action)]
|
#[arg(long, action)]
|
||||||
pub clear_cache: bool,
|
pub clear_cache: bool,
|
||||||
|
|
||||||
|
/// Print debug information
|
||||||
|
#[arg(long, action)]
|
||||||
|
pub debug: bool,
|
||||||
|
|
||||||
/// Print version
|
/// Print version
|
||||||
#[arg(short = 'V', long)]
|
#[arg(short = 'V', long)]
|
||||||
pub version: bool,
|
pub version: bool,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{ffi::OsString, path::{Path, PathBuf}, process};
|
use std::{env, ffi::OsString, path::{Path, PathBuf}, process};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -32,6 +32,63 @@ impl Boot {
|
|||||||
|
|
||||||
(parent.unwrap().to_owned(), Some(entry.file_name().unwrap().to_owned()))
|
(parent.unwrap().to_owned(), Some(entry.file_name().unwrap().to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn action_version() {
|
||||||
|
println!(
|
||||||
|
"yazi {} ({} {})",
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
env!("VERGEN_GIT_SHA"),
|
||||||
|
env!("VERGEN_BUILD_DATE")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn action_debug() {
|
||||||
|
print!("Yazi\n ");
|
||||||
|
Self::action_version();
|
||||||
|
|
||||||
|
println!("\nEnvironment");
|
||||||
|
println!(
|
||||||
|
" OS: {}-{} ({})",
|
||||||
|
std::env::consts::OS,
|
||||||
|
std::env::consts::ARCH,
|
||||||
|
std::env::consts::FAMILY
|
||||||
|
);
|
||||||
|
println!(" Debug: {}", cfg!(debug_assertions));
|
||||||
|
|
||||||
|
println!("\nEmulator");
|
||||||
|
println!(" Emulator.via_env: {:?}", yazi_adaptor::Emulator::via_env());
|
||||||
|
println!(" Emulator.via_csi: {:?}", yazi_adaptor::Emulator::via_csi());
|
||||||
|
println!(" Emulator.detect: {:?}", yazi_adaptor::Emulator::detect());
|
||||||
|
|
||||||
|
println!("\nAdaptor");
|
||||||
|
println!(" Adaptor.matches: {:?}", yazi_adaptor::Adaptor::matches());
|
||||||
|
|
||||||
|
println!("\ntmux");
|
||||||
|
println!(" TMUX: {:?}", *yazi_adaptor::TMUX);
|
||||||
|
|
||||||
|
println!("\nZellij");
|
||||||
|
println!(" ZELLIJ_SESSION_NAME: {:?}", env::var_os("ZELLIJ_SESSION_NAME"));
|
||||||
|
|
||||||
|
println!("\nDesktop");
|
||||||
|
println!(" XDG_SESSION_TYPE: {:?}", env::var_os("XDG_SESSION_TYPE"));
|
||||||
|
println!(" WAYLAND_DISPLAY: {:?}", env::var_os("WAYLAND_DISPLAY"));
|
||||||
|
println!(" DISPLAY: {:?}", env::var_os("DISPLAY"));
|
||||||
|
|
||||||
|
println!("\nUeberzug");
|
||||||
|
println!(" Version: {:?}", std::process::Command::new("ueberzug").arg("--version").output());
|
||||||
|
|
||||||
|
println!("\nWSL");
|
||||||
|
println!(
|
||||||
|
" /proc/sys/fs/binfmt_misc/WSLInterop: {:?}",
|
||||||
|
std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok()
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("\n\n--------------------------------------------------");
|
||||||
|
println!(
|
||||||
|
"When reporting a bug, please also upload the `yazi.log` log file - only upload the most recent content by time."
|
||||||
|
);
|
||||||
|
println!("You can find it in the {:?} directory.", Xdg::state_dir());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Boot {
|
impl Default for Boot {
|
||||||
@ -58,13 +115,13 @@ impl Default for Args {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let args = Self::parse();
|
let args = Self::parse();
|
||||||
|
|
||||||
|
if args.debug {
|
||||||
|
Boot::action_debug();
|
||||||
|
process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if args.version {
|
if args.version {
|
||||||
println!(
|
Boot::action_version();
|
||||||
"yazi {} ({} {})",
|
|
||||||
env!("CARGO_PKG_VERSION"),
|
|
||||||
env!("VERGEN_GIT_SHA"),
|
|
||||||
env!("VERGEN_BUILD_DATE")
|
|
||||||
);
|
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user