mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
6ff64cd33a
commit
435d910751
20 changed files with 404 additions and 216 deletions
|
|
@ -1 +1 @@
|
||||||
{"language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","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","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","Sysinfo","ffprobe","vframes"],"version":"0.2"}
|
{"version":"0.2","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","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","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","Sysinfo","ffprobe","vframes","luma"],"language":"en"}
|
||||||
|
|
@ -5,7 +5,7 @@ use ratatui::layout::Rect;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use yazi_shared::env_exists;
|
use yazi_shared::env_exists;
|
||||||
|
|
||||||
use crate::{Emulator, SHOWN, TMUX, WSL, drivers};
|
use crate::{Brand, Emulator, SHOWN, TMUX, WSL, drivers};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum Adapter {
|
pub enum Adapter {
|
||||||
|
|
@ -80,15 +80,14 @@ impl Adapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Adapter {
|
impl Adapter {
|
||||||
pub fn matches() -> Self {
|
pub fn matches(emulator: Emulator) -> Self {
|
||||||
let emulator = Emulator::detect();
|
if matches!(emulator.kind.left(), Some(Brand::Microsoft)) {
|
||||||
if matches!(emulator, Emulator::Microsoft) {
|
|
||||||
return Self::Sixel;
|
return Self::Sixel;
|
||||||
} else if *WSL && matches!(emulator, Emulator::WezTerm) {
|
} else if *WSL && matches!(emulator.kind.left(), Some(Brand::WezTerm)) {
|
||||||
return Self::KgpOld;
|
return Self::KgpOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut protocols = emulator.adapters();
|
let mut protocols = emulator.adapters().to_owned();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
protocols.retain(|p| *p == Self::Iip);
|
protocols.retain(|p| *p == Self::Iip);
|
||||||
if env_exists("ZELLIJ_SESSION_NAME") {
|
if env_exists("ZELLIJ_SESSION_NAME") {
|
||||||
|
|
|
||||||
119
yazi-adapter/src/brand.rs
Normal file
119
yazi-adapter/src/brand.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
use tracing::warn;
|
||||||
|
use yazi_shared::env_exists;
|
||||||
|
|
||||||
|
use crate::Mux;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Brand {
|
||||||
|
Kitty,
|
||||||
|
Konsole,
|
||||||
|
Iterm2,
|
||||||
|
WezTerm,
|
||||||
|
Foot,
|
||||||
|
Ghostty,
|
||||||
|
Microsoft,
|
||||||
|
Rio,
|
||||||
|
BlackBox,
|
||||||
|
VSCode,
|
||||||
|
Tabby,
|
||||||
|
Hyper,
|
||||||
|
Mintty,
|
||||||
|
Neovim,
|
||||||
|
Apple,
|
||||||
|
Urxvt,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Brand {
|
||||||
|
pub fn from_env() -> Option<Self> {
|
||||||
|
use Brand as B;
|
||||||
|
|
||||||
|
if env_exists("NVIM_LOG_FILE") && env_exists("NVIM") {
|
||||||
|
return Some(Self::Neovim);
|
||||||
|
}
|
||||||
|
|
||||||
|
let vars = [
|
||||||
|
("KITTY_WINDOW_ID", B::Kitty),
|
||||||
|
("KONSOLE_VERSION", B::Konsole),
|
||||||
|
("ITERM_SESSION_ID", B::Iterm2),
|
||||||
|
("WEZTERM_EXECUTABLE", B::WezTerm),
|
||||||
|
("GHOSTTY_RESOURCES_DIR", B::Ghostty),
|
||||||
|
("WT_Session", B::Microsoft),
|
||||||
|
("VSCODE_INJECTION", B::VSCode),
|
||||||
|
("TABBY_CONFIG_DIRECTORY", B::Tabby),
|
||||||
|
];
|
||||||
|
match vars.into_iter().find(|&(s, _)| env_exists(s)) {
|
||||||
|
Some((_, brand)) => return Some(brand),
|
||||||
|
None => warn!("[Adapter] No special environment variables detected"),
|
||||||
|
}
|
||||||
|
|
||||||
|
let (term, program) = B::env();
|
||||||
|
match program.as_str() {
|
||||||
|
"iTerm.app" => return Some(B::Iterm2),
|
||||||
|
"WezTerm" => return Some(B::WezTerm),
|
||||||
|
"ghostty" => return Some(B::Ghostty),
|
||||||
|
"rio" => return Some(B::Rio),
|
||||||
|
"BlackBox" => return Some(B::BlackBox),
|
||||||
|
"vscode" => return Some(B::VSCode),
|
||||||
|
"Tabby" => return Some(B::Tabby),
|
||||||
|
"Hyper" => return Some(B::Hyper),
|
||||||
|
"mintty" => return Some(B::Mintty),
|
||||||
|
"Apple_Terminal" => return Some(B::Apple),
|
||||||
|
_ => warn!("[Adapter] Unknown TERM_PROGRAM: {program}"),
|
||||||
|
}
|
||||||
|
match term.as_str() {
|
||||||
|
"xterm-kitty" => return Some(B::Kitty),
|
||||||
|
"foot" => return Some(B::Foot),
|
||||||
|
"foot-extra" => return Some(B::Foot),
|
||||||
|
"xterm-ghostty" => return Some(B::Ghostty),
|
||||||
|
"rio" => return Some(B::Rio),
|
||||||
|
"rxvt-unicode-256color" => return Some(B::Urxvt),
|
||||||
|
_ => warn!("[Adapter] Unknown TERM: {term}"),
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn from_csi(resp: &str) -> Option<Self> {
|
||||||
|
let names = [
|
||||||
|
("kitty", Self::Kitty),
|
||||||
|
("Konsole", Self::Konsole),
|
||||||
|
("iTerm2", Self::Iterm2),
|
||||||
|
("WezTerm", Self::WezTerm),
|
||||||
|
("foot", Self::Foot),
|
||||||
|
("ghostty", Self::Ghostty),
|
||||||
|
];
|
||||||
|
names.into_iter().find(|&(n, _)| resp.contains(n)).map(|(_, b)| b)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn adapters(self) -> &'static [crate::Adapter] {
|
||||||
|
use Brand as B;
|
||||||
|
|
||||||
|
use crate::Adapter as A;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
B::Kitty => &[A::Kgp],
|
||||||
|
B::Konsole => &[A::KgpOld],
|
||||||
|
B::Iterm2 => &[A::Iip, A::Sixel],
|
||||||
|
B::WezTerm => &[A::Iip, A::Sixel],
|
||||||
|
B::Foot => &[A::Sixel],
|
||||||
|
B::Ghostty => &[A::Kgp],
|
||||||
|
B::Microsoft => &[A::Sixel],
|
||||||
|
B::Rio => &[A::Iip, A::Sixel],
|
||||||
|
B::BlackBox => &[A::Sixel],
|
||||||
|
B::VSCode => &[A::Iip, A::Sixel],
|
||||||
|
B::Tabby => &[A::Iip, A::Sixel],
|
||||||
|
B::Hyper => &[A::Iip, A::Sixel],
|
||||||
|
B::Mintty => &[A::Iip],
|
||||||
|
B::Neovim => &[],
|
||||||
|
B::Apple => &[],
|
||||||
|
B::Urxvt => &[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env() -> (String, String) {
|
||||||
|
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()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,150 +4,61 @@ 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}};
|
||||||
use scopeguard::defer;
|
use scopeguard::defer;
|
||||||
use tokio::{io::{AsyncReadExt, BufReader}, time::timeout};
|
use tokio::{io::{AsyncReadExt, BufReader}, time::timeout};
|
||||||
use tracing::{error, warn};
|
use tracing::{debug, error, warn};
|
||||||
use yazi_shared::env_exists;
|
use yazi_shared::Either;
|
||||||
|
|
||||||
use crate::{Adapter, Mux, TMUX};
|
use crate::{Adapter, Brand, Mux, TMUX, Unknown};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Emulator {
|
pub struct Emulator {
|
||||||
Unknown(Vec<Adapter>),
|
pub kind: Either<Brand, Unknown>,
|
||||||
Kitty,
|
pub light: bool,
|
||||||
Konsole,
|
|
||||||
Iterm2,
|
|
||||||
WezTerm,
|
|
||||||
Foot,
|
|
||||||
Ghostty,
|
|
||||||
Microsoft,
|
|
||||||
Rio,
|
|
||||||
BlackBox,
|
|
||||||
VSCode,
|
|
||||||
Tabby,
|
|
||||||
Hyper,
|
|
||||||
Mintty,
|
|
||||||
Neovim,
|
|
||||||
Apple,
|
|
||||||
Urxvt,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emulator {
|
impl Default for Emulator {
|
||||||
pub fn adapters(self) -> Vec<Adapter> {
|
fn default() -> Self { Self { kind: Either::Right(Unknown::default()), light: false } }
|
||||||
match self {
|
|
||||||
Self::Unknown(adapters) => adapters,
|
|
||||||
Self::Kitty => vec![Adapter::Kgp],
|
|
||||||
Self::Konsole => vec![Adapter::KgpOld],
|
|
||||||
Self::Iterm2 => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::WezTerm => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::Foot => vec![Adapter::Sixel],
|
|
||||||
Self::Ghostty => vec![Adapter::Kgp],
|
|
||||||
Self::Microsoft => vec![Adapter::Sixel],
|
|
||||||
Self::Rio => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::BlackBox => vec![Adapter::Sixel],
|
|
||||||
Self::VSCode => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::Tabby => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::Hyper => vec![Adapter::Iip, Adapter::Sixel],
|
|
||||||
Self::Mintty => vec![Adapter::Iip],
|
|
||||||
Self::Neovim => vec![],
|
|
||||||
Self::Apple => vec![],
|
|
||||||
Self::Urxvt => vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emulator {
|
impl Emulator {
|
||||||
pub fn detect() -> Self {
|
pub fn detect() -> Self {
|
||||||
if env_exists("NVIM_LOG_FILE") && env_exists("NVIM") {
|
if let Some(brand) = Brand::from_env() {
|
||||||
return Self::Neovim;
|
Self { kind: Either::Left(brand), light: Self::detect_base().unwrap_or_default().light }
|
||||||
|
} else {
|
||||||
|
Self::detect_full().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
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),
|
|
||||||
("WT_Session", Self::Microsoft),
|
|
||||||
("VSCODE_INJECTION", Self::VSCode),
|
|
||||||
("TABBY_CONFIG_DIRECTORY", Self::Tabby),
|
|
||||||
];
|
|
||||||
match vars.into_iter().find(|(env, _)| env_exists(env)) {
|
|
||||||
Some((_, emulator)) => return emulator,
|
|
||||||
None => warn!("[Adapter] 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,
|
|
||||||
"rio" => return Self::Rio,
|
|
||||||
"BlackBox" => return Self::BlackBox,
|
|
||||||
"vscode" => return Self::VSCode,
|
|
||||||
"Tabby" => return Self::Tabby,
|
|
||||||
"Hyper" => return Self::Hyper,
|
|
||||||
"mintty" => return Self::Mintty,
|
|
||||||
"Apple_Terminal" => return Self::Apple,
|
|
||||||
_ => warn!("[Adapter] 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,
|
|
||||||
"rio" => return Self::Rio,
|
|
||||||
"rxvt-unicode-256color" => return Self::Urxvt,
|
|
||||||
_ => warn!("[Adapter] Unknown TERM: {term}"),
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::via_csi().unwrap_or(Self::Unknown(vec![]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn via_env() -> (String, String) {
|
pub fn detect_full() -> Result<Self> {
|
||||||
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> {
|
|
||||||
defer! { disable_raw_mode().ok(); }
|
defer! { disable_raw_mode().ok(); }
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
|
|
||||||
execute!(
|
execute!(
|
||||||
LineWriter::new(stderr()),
|
LineWriter::new(stderr()),
|
||||||
SavePosition,
|
SavePosition,
|
||||||
Print(Mux::csi("\x1b[>q")), // Request terminal version
|
|
||||||
Print(Mux::csi("\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\")), // Detect KGP
|
Print(Mux::csi("\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\")), // Detect KGP
|
||||||
Print(Mux::csi("\x1b[c")), // Request device attributes
|
Print(Mux::csi("\x1b[>q")), // Request terminal version
|
||||||
|
Print(Mux::csi("\x1b[c")), // Request device attributes
|
||||||
RestorePosition
|
RestorePosition
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let resp = futures::executor::block_on(Self::read_until_da1());
|
let resp = futures::executor::block_on(Self::read_until_da1());
|
||||||
let names = [
|
let kind = if let Some(brand) = Brand::from_csi(&resp) {
|
||||||
("kitty", Self::Kitty),
|
Either::Left(brand)
|
||||||
("Konsole", Self::Konsole),
|
} else {
|
||||||
("iTerm2", Self::Iterm2),
|
Either::Right(Unknown {
|
||||||
("WezTerm", Self::WezTerm),
|
kgp: resp.contains("\x1b_Gi=31;OK"),
|
||||||
("foot", Self::Foot),
|
sixel: ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| resp.contains(s)),
|
||||||
("ghostty", Self::Ghostty),
|
})
|
||||||
];
|
};
|
||||||
|
|
||||||
for (name, emulator) in names.iter() {
|
Ok(Self { kind, light: Self::light_bg(&resp).unwrap_or_default() })
|
||||||
if resp.contains(name) {
|
}
|
||||||
return Ok(emulator.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut adapters = Vec::with_capacity(2);
|
pub fn adapters(self) -> &'static [Adapter] {
|
||||||
if resp.contains("\x1b_Gi=31;OK") {
|
match self.kind {
|
||||||
adapters.push(Adapter::KgpOld);
|
Either::Left(brand) => brand.adapters(),
|
||||||
|
Either::Right(unknown) => unknown.adapters(),
|
||||||
}
|
}
|
||||||
if ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| resp.contains(s)) {
|
|
||||||
adapters.push(Adapter::Sixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self::Unknown(adapters))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_lock<F, T>((x, y): (u16, u16), cb: F) -> Result<T>
|
pub fn move_lock<F, T>((x, y): (u16, u16), cb: F) -> Result<T>
|
||||||
|
|
@ -209,4 +120,35 @@ impl Emulator {
|
||||||
}
|
}
|
||||||
String::from_utf8_lossy(&buf).into_owned()
|
String::from_utf8_lossy(&buf).into_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn detect_base() -> Result<Self> {
|
||||||
|
defer! { disable_raw_mode().ok(); }
|
||||||
|
enable_raw_mode()?;
|
||||||
|
|
||||||
|
execute!(
|
||||||
|
LineWriter::new(stderr()),
|
||||||
|
Print(Mux::csi("\x1b]11;?\x07")), // Request background color
|
||||||
|
Print(Mux::csi("\x1b[c")), // Request device attributes
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let resp = futures::executor::block_on(Self::read_until_da1());
|
||||||
|
Ok(Self { light: Self::light_bg(&resp).unwrap_or_default(), ..Default::default() })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn light_bg(resp: &str) -> Result<bool> {
|
||||||
|
match resp.split_once("]11;rgb:") {
|
||||||
|
Some((_, s)) if s.len() >= 14 => {
|
||||||
|
let r = u8::from_str_radix(&s[0..2], 16)? as f32;
|
||||||
|
let g = u8::from_str_radix(&s[5..7], 16)? as f32;
|
||||||
|
let b = u8::from_str_radix(&s[10..12], 16)? as f32;
|
||||||
|
let luma = r * 0.2627 / 256.0 + g * 0.6780 / 256.0 + b * 0.0593 / 256.0;
|
||||||
|
debug!("Detected background color: {} (luma = {luma:.2})", &s[..14]);
|
||||||
|
Ok(luma > 0.6)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("Failed to detect background color: {resp:?}");
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,16 @@
|
||||||
|
|
||||||
yazi_macro::mod_pub!(drivers);
|
yazi_macro::mod_pub!(drivers);
|
||||||
|
|
||||||
yazi_macro::mod_flat!(adapter dimension emulator image info mux);
|
yazi_macro::mod_flat!(adapter brand dimension emulator image info mux unknown);
|
||||||
|
|
||||||
use yazi_shared::{RoCell, SyncCell, env_exists, in_wsl};
|
use yazi_shared::{RoCell, SyncCell, env_exists, in_wsl};
|
||||||
|
|
||||||
|
pub static EMULATOR: RoCell<Emulator> = RoCell::new();
|
||||||
pub static ADAPTOR: RoCell<Adapter> = RoCell::new();
|
pub static ADAPTOR: RoCell<Adapter> = RoCell::new();
|
||||||
|
|
||||||
|
// Image state
|
||||||
|
static SHOWN: SyncCell<Option<ratatui::layout::Rect>> = SyncCell::new(None);
|
||||||
|
|
||||||
// Tmux support
|
// Tmux support
|
||||||
pub 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();
|
||||||
|
|
@ -16,10 +21,7 @@ static CLOSE: RoCell<&'static str> = RoCell::new();
|
||||||
// WSL support
|
// WSL support
|
||||||
pub static WSL: RoCell<bool> = RoCell::new();
|
pub static WSL: RoCell<bool> = RoCell::new();
|
||||||
|
|
||||||
// Image state
|
pub fn init() -> anyhow::Result<()> {
|
||||||
static SHOWN: SyncCell<Option<ratatui::layout::Rect>> = SyncCell::new(None);
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
// Tmux support
|
// Tmux support
|
||||||
TMUX.init(env_exists("TMUX_PANE") && env_exists("TMUX"));
|
TMUX.init(env_exists("TMUX_PANE") && env_exists("TMUX"));
|
||||||
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
|
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
|
||||||
|
|
@ -38,6 +40,11 @@ pub fn init() {
|
||||||
// WSL support
|
// WSL support
|
||||||
WSL.init(in_wsl());
|
WSL.init(in_wsl());
|
||||||
|
|
||||||
ADAPTOR.init(Adapter::matches());
|
EMULATOR.init(Emulator::detect());
|
||||||
|
yazi_config::init_flavor(EMULATOR.light)?;
|
||||||
|
|
||||||
|
ADAPTOR.init(Adapter::matches(*EMULATOR));
|
||||||
ADAPTOR.start();
|
ADAPTOR.start();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
yazi-adapter/src/unknown.rs
Normal file
20
yazi-adapter/src/unknown.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
use crate::Adapter;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct Unknown {
|
||||||
|
pub kgp: bool,
|
||||||
|
pub sixel: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Unknown {
|
||||||
|
pub(super) fn adapters(self) -> &'static [Adapter] {
|
||||||
|
use Adapter as A;
|
||||||
|
|
||||||
|
match (self.kgp, self.sixel) {
|
||||||
|
(true, true) => &[A::Kgp, A::Sixel],
|
||||||
|
(true, false) => &[A::Kgp],
|
||||||
|
(false, true) => &[A::Sixel],
|
||||||
|
(false, false) => &[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,13 +17,14 @@ impl Actions {
|
||||||
writeln!(s, "\nYa")?;
|
writeln!(s, "\nYa")?;
|
||||||
writeln!(s, " Version: {}", Self::process_output("ya", "--version"))?;
|
writeln!(s, " Version: {}", Self::process_output("ya", "--version"))?;
|
||||||
|
|
||||||
|
let emulator = yazi_adapter::Emulator::detect();
|
||||||
writeln!(s, "\nEmulator")?;
|
writeln!(s, "\nEmulator")?;
|
||||||
writeln!(s, " Emulator.via_env: {:?}", yazi_adapter::Emulator::via_env())?;
|
writeln!(s, " Brand.from_env : {:?}", yazi_adapter::Brand::from_env())?;
|
||||||
writeln!(s, " Emulator.via_csi: {:?}", yazi_adapter::Emulator::via_csi())?;
|
writeln!(s, " Emulator.detect : {:?}", emulator)?;
|
||||||
writeln!(s, " Emulator.detect : {:?}", yazi_adapter::Emulator::detect())?;
|
writeln!(s, " Emulator.detect_full: {:?}", yazi_adapter::Emulator::detect_full())?;
|
||||||
|
|
||||||
writeln!(s, "\nAdapter")?;
|
writeln!(s, "\nAdapter")?;
|
||||||
writeln!(s, " Adapter.matches: {:?}", yazi_adapter::Adapter::matches())?;
|
writeln!(s, " Adapter.matches: {:?}", yazi_adapter::Adapter::matches(emulator))?;
|
||||||
|
|
||||||
writeln!(s, "\nDesktop")?;
|
writeln!(s, "\nDesktop")?;
|
||||||
writeln!(s, " XDG_SESSION_TYPE : {:?}", env::var_os("XDG_SESSION_TYPE"))?;
|
writeln!(s, " XDG_SESSION_TYPE : {:?}", env::var_os("XDG_SESSION_TYPE"))?;
|
||||||
|
|
|
||||||
|
|
@ -214,16 +214,3 @@ rules = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# : }}}
|
# : }}}
|
||||||
|
|
||||||
|
|
||||||
# : Icons {{{
|
|
||||||
|
|
||||||
[icon]
|
|
||||||
|
|
||||||
globs = []
|
|
||||||
dirs = []
|
|
||||||
files = []
|
|
||||||
exts = []
|
|
||||||
conds = []
|
|
||||||
|
|
||||||
# : }}}
|
|
||||||
|
|
|
||||||
|
|
@ -24,22 +24,7 @@ pub static LAYOUT: SyncCell<Layout> = SyncCell::new(Layout::default());
|
||||||
|
|
||||||
pub fn init() -> anyhow::Result<()> {
|
pub fn init() -> anyhow::Result<()> {
|
||||||
if let Err(e) = try_init(true) {
|
if let Err(e) = try_init(true) {
|
||||||
eprintln!("{e}");
|
wait_for_key(e)?;
|
||||||
if let Some(src) = e.source() {
|
|
||||||
eprintln!("\nCaused by:\n{src}");
|
|
||||||
}
|
|
||||||
|
|
||||||
use crossterm::style::{Attribute, Print, SetAttributes};
|
|
||||||
crossterm::execute!(
|
|
||||||
std::io::stderr(),
|
|
||||||
SetAttributes(Attribute::Reverse.into()),
|
|
||||||
SetAttributes(Attribute::Bold.into()),
|
|
||||||
Print("Press <Enter> to continue with preset settings..."),
|
|
||||||
SetAttributes(Attribute::Reset.into()),
|
|
||||||
Print("\n"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
std::io::stdin().read_line(&mut String::new())?;
|
|
||||||
try_init(false)?;
|
try_init(false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,13 +63,29 @@ Please change `create_title = "Create:"` to `create_title = ["Create:", "Create
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init_flavor(light: bool) -> anyhow::Result<()> {
|
||||||
|
let mut flavor_toml = Preset::flavor(light, true);
|
||||||
|
if let Err(e) = flavor_toml {
|
||||||
|
wait_for_key(e)?;
|
||||||
|
flavor_toml = Preset::flavor(light, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut theme: theme::Theme = <_>::from_str(&flavor_toml.unwrap())?;
|
||||||
|
theme.manager.syntect_theme = theme
|
||||||
|
.flavor
|
||||||
|
.syntect_path(light)
|
||||||
|
.unwrap_or_else(|| yazi_shared::fs::expand_path(&theme.manager.syntect_theme));
|
||||||
|
|
||||||
|
THEME.init(theme);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn try_init(merge: bool) -> anyhow::Result<()> {
|
fn try_init(merge: bool) -> anyhow::Result<()> {
|
||||||
let (yazi_toml, keymap_toml, theme_toml) = if merge {
|
let (yazi_toml, keymap_toml) = if merge {
|
||||||
let p = Xdg::config_dir();
|
let p = Xdg::config_dir();
|
||||||
(Preset::yazi(&p)?, Preset::keymap(&p)?, Preset::theme(&p)?)
|
(Preset::yazi(&p)?, Preset::keymap(&p)?)
|
||||||
} else {
|
} else {
|
||||||
use yazi_macro::config_preset as preset;
|
(yazi_macro::config_preset!("yazi"), yazi_macro::config_preset!("keymap"))
|
||||||
(preset!("yazi"), preset!("keymap"), preset!("theme"))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let keymap = <_>::from_str(&keymap_toml)?;
|
let keymap = <_>::from_str(&keymap_toml)?;
|
||||||
|
|
@ -93,7 +94,6 @@ fn try_init(merge: bool) -> anyhow::Result<()> {
|
||||||
let plugin = <_>::from_str(&yazi_toml)?;
|
let plugin = <_>::from_str(&yazi_toml)?;
|
||||||
let preview = <_>::from_str(&yazi_toml)?;
|
let preview = <_>::from_str(&yazi_toml)?;
|
||||||
let tasks = <_>::from_str(&yazi_toml)?;
|
let tasks = <_>::from_str(&yazi_toml)?;
|
||||||
let theme = <_>::from_str(&theme_toml)?;
|
|
||||||
let input = <_>::from_str(&yazi_toml)?;
|
let input = <_>::from_str(&yazi_toml)?;
|
||||||
let confirm = <_>::from_str(&yazi_toml)?;
|
let confirm = <_>::from_str(&yazi_toml)?;
|
||||||
let pick = <_>::from_str(&yazi_toml)?;
|
let pick = <_>::from_str(&yazi_toml)?;
|
||||||
|
|
@ -105,7 +105,6 @@ fn try_init(merge: bool) -> anyhow::Result<()> {
|
||||||
PLUGIN.init(plugin);
|
PLUGIN.init(plugin);
|
||||||
PREVIEW.init(preview);
|
PREVIEW.init(preview);
|
||||||
TASKS.init(tasks);
|
TASKS.init(tasks);
|
||||||
THEME.init(theme);
|
|
||||||
INPUT.init(input);
|
INPUT.init(input);
|
||||||
CONFIRM.init(confirm);
|
CONFIRM.init(confirm);
|
||||||
PICK.init(pick);
|
PICK.init(pick);
|
||||||
|
|
@ -113,3 +112,23 @@ fn try_init(merge: bool) -> anyhow::Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wait_for_key(e: anyhow::Error) -> anyhow::Result<()> {
|
||||||
|
eprintln!("{e}");
|
||||||
|
if let Some(src) = e.source() {
|
||||||
|
eprintln!("\nCaused by:\n{src}");
|
||||||
|
}
|
||||||
|
|
||||||
|
use crossterm::style::{Attribute, Print, SetAttributes};
|
||||||
|
crossterm::execute!(
|
||||||
|
std::io::stderr(),
|
||||||
|
SetAttributes(Attribute::Reverse.into()),
|
||||||
|
SetAttributes(Attribute::Bold.into()),
|
||||||
|
Print("Press <Enter> to continue with preset settings..."),
|
||||||
|
SetAttributes(Attribute::Reset.into()),
|
||||||
|
Print("\n"),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
std::io::stdin().read_line(&mut String::new())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{borrow::Cow, path::{Path, PathBuf}};
|
use std::{borrow::Cow, path::{Path, PathBuf}, str::FromStr};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use toml::{Table, Value};
|
use toml::{Table, Value};
|
||||||
use yazi_macro::config_preset as preset;
|
use yazi_shared::Xdg;
|
||||||
|
|
||||||
use crate::theme::Flavor;
|
use crate::theme::Flavor;
|
||||||
|
|
||||||
|
|
@ -10,26 +10,26 @@ pub(crate) struct Preset;
|
||||||
|
|
||||||
impl Preset {
|
impl Preset {
|
||||||
pub(crate) fn yazi(p: &Path) -> Result<Cow<'static, str>> {
|
pub(crate) fn yazi(p: &Path) -> Result<Cow<'static, str>> {
|
||||||
Self::merge_path(p.join("yazi.toml"), preset!("yazi"))
|
Self::merge_path(p.join("yazi.toml"), yazi_macro::config_preset!("yazi"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn keymap(p: &Path) -> Result<Cow<'static, str>> {
|
pub(crate) fn keymap(p: &Path) -> Result<Cow<'static, str>> {
|
||||||
Self::merge_path(p.join("keymap.toml"), preset!("keymap"))
|
Self::merge_path(p.join("keymap.toml"), yazi_macro::config_preset!("keymap"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn theme(p: &Path) -> Result<Cow<'static, str>> {
|
pub(crate) fn flavor(light: bool, merge: bool) -> Result<Cow<'static, str>> {
|
||||||
let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else {
|
let theme = if merge {
|
||||||
return Ok(preset!("theme"));
|
std::fs::read_to_string(Xdg::config_dir().join("theme.toml")).unwrap_or_default()
|
||||||
};
|
} else {
|
||||||
let Some(use_) = Flavor::parse_use(&user) else {
|
Default::default()
|
||||||
return Self::merge_str(&user, &preset!("theme"));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let p = p.join(format!("flavors/{use_}.yazi/flavor.toml"));
|
let flavor = Flavor::from_str(&theme)?;
|
||||||
let flavor =
|
|
||||||
std::fs::read_to_string(&p).with_context(|| format!("failed to load flavor {p:?}"))?;
|
|
||||||
|
|
||||||
Self::merge_str(&user, &Self::merge_str(&flavor, &preset!("theme"))?)
|
let preset =
|
||||||
|
if light { yazi_macro::theme_preset!("light") } else { yazi_macro::theme_preset!("dark") };
|
||||||
|
|
||||||
|
Self::merge_str(&theme, &Self::merge_str(&flavor.read(light)?, &preset)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,50 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use std::{borrow::Cow, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
use anyhow::{Context, Result};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yazi_shared::Xdg;
|
||||||
|
|
||||||
|
#[derive(Default, Deserialize, Serialize)]
|
||||||
pub struct Flavor {
|
pub struct Flavor {
|
||||||
#[serde(rename = "use")]
|
#[serde(default)]
|
||||||
pub use_: String,
|
pub dark: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub light: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Flavor {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Outer {
|
||||||
|
#[serde(default)]
|
||||||
|
flavor: Flavor,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(
|
||||||
|
toml::from_str::<Outer>(s)
|
||||||
|
.context("Failed to parse the [flavor] section in your theme.toml")?
|
||||||
|
.flavor,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flavor {
|
impl Flavor {
|
||||||
pub fn parse_use(s: &str) -> Option<String> {
|
pub(crate) fn read(&self, light: bool) -> Result<Cow<'static, str>> {
|
||||||
#[derive(Deserialize)]
|
Ok(match if light { self.light.as_str() } else { self.dark.as_str() } {
|
||||||
struct Outer {
|
"" => Cow::Borrowed(""),
|
||||||
flavor: Inner,
|
name => {
|
||||||
}
|
let p = Xdg::config_dir().join(format!("flavors/{name}.yazi/flavor.toml"));
|
||||||
#[derive(Deserialize)]
|
std::fs::read_to_string(&p).with_context(|| format!("Failed to load flavor {p:?}"))?.into()
|
||||||
struct Inner {
|
}
|
||||||
#[serde(rename = "use")]
|
})
|
||||||
pub use_: String,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
toml::from_str::<Outer>(s).ok().map(|o| o.flavor.use_).filter(|s| !s.is_empty())
|
pub(crate) fn syntect_path(&self, light: bool) -> Option<PathBuf> {
|
||||||
|
match if light { self.light.as_str() } else { self.dark.as_str() } {
|
||||||
|
"" => None,
|
||||||
|
name => Some(Xdg::config_dir().join(format!("flavors/{name}.yazi/tmtheme.xml"))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{path::PathBuf, str::FromStr};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
use yazi_shared::{Xdg, fs::expand_path, theme::Style};
|
use yazi_shared::theme::Style;
|
||||||
|
|
||||||
use super::{Filetype, Flavor, Icons};
|
use super::{Filetype, Flavor, Icons};
|
||||||
|
|
||||||
|
|
@ -32,17 +32,10 @@ impl FromStr for Theme {
|
||||||
type Err = anyhow::Error;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut theme: Self = toml::from_str(s).context("Failed to parse your yazi.toml")?;
|
let theme: Self = toml::from_str(s).context("Failed to parse your theme.toml")?;
|
||||||
theme.manager.validate()?;
|
theme.manager.validate()?;
|
||||||
theme.which.validate()?;
|
theme.which.validate()?;
|
||||||
|
|
||||||
if theme.flavor.use_.is_empty() {
|
|
||||||
theme.manager.syntect_theme = expand_path(&theme.manager.syntect_theme);
|
|
||||||
} else {
|
|
||||||
theme.manager.syntect_theme =
|
|
||||||
Xdg::config_dir().join(format!("flavors/{}.yazi/tmtheme.xml", theme.flavor.use_));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(theme)
|
Ok(theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ impl FromStr for Which {
|
||||||
which: Which,
|
which: Which,
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer = toml::from_str::<Outer>(s)
|
let outer: Outer =
|
||||||
.context("Failed to parse the [which] section in your yazi.toml")?;
|
toml::from_str(s).context("Failed to parse the [which] section in your yazi.toml")?;
|
||||||
|
|
||||||
Ok(outer.which)
|
Ok(outer.which)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
yazi_config::init()?;
|
yazi_config::init()?;
|
||||||
|
|
||||||
yazi_adapter::init();
|
yazi_adapter::init()?;
|
||||||
|
|
||||||
yazi_boot::init();
|
yazi_boot::init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ macro_rules! config_preset {
|
||||||
($name:literal) => {{
|
($name:literal) => {{
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
std::borrow::Cow::Owned(
|
std::borrow::Cow::from(
|
||||||
std::fs::read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/preset/", $name, ".toml"))
|
std::fs::read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/preset/", $name, ".toml"))
|
||||||
.expect(concat!("Failed to read 'yazi-config/preset/", $name, ".toml'")),
|
.expect(concat!("Failed to read 'yazi-config/preset/", $name, ".toml'")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
{
|
{
|
||||||
std::borrow::Cow::Borrowed(include_str!(concat!(
|
std::borrow::Cow::from(include_str!(concat!(
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
"/preset/",
|
"/preset/",
|
||||||
$name,
|
$name,
|
||||||
|
|
@ -37,3 +37,28 @@ macro_rules! plugin_preset {
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! theme_preset {
|
||||||
|
($name:literal) => {{
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
let append = std::fs::read_to_string(concat!(
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
"/preset/theme+",
|
||||||
|
$name,
|
||||||
|
".toml"
|
||||||
|
))
|
||||||
|
.expect(concat!("Failed to read 'yazi-config/preset/theme+", $name, ".toml'"));
|
||||||
|
std::borrow::Cow::from(format!("{}\n{append}", &$crate::config_preset!("theme")))
|
||||||
|
}
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
|
std::borrow::Cow::from(concat!(
|
||||||
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/preset/theme.toml")),
|
||||||
|
"\n",
|
||||||
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/preset/theme+", $name, ".toml"))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ impl Loader {
|
||||||
|
|
||||||
let p = BOOT.plugin_dir.join(format!("{name}.yazi/init.lua"));
|
let p = BOOT.plugin_dir.join(format!("{name}.yazi/init.lua"));
|
||||||
let chunk =
|
let chunk =
|
||||||
fs::read(&p).await.with_context(|| format!("failed to load plugin from {p:?}"))?.into();
|
fs::read(&p).await.with_context(|| format!("Failed to load plugin from {p:?}"))?.into();
|
||||||
|
|
||||||
self.cache.write().insert(name.to_owned(), chunk);
|
self.cache.write().insert(name.to_owned(), chunk);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
49
yazi-shared/src/either.rs
Normal file
49
yazi-shared/src/either.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Either<L, R> {
|
||||||
|
Left(L),
|
||||||
|
Right(R),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, R> Either<L, R> {
|
||||||
|
pub fn left(&self) -> Option<&L> {
|
||||||
|
match self {
|
||||||
|
Either::Left(l) => Some(l),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(&self) -> Option<&R> {
|
||||||
|
match self {
|
||||||
|
Either::Right(r) => Some(r),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left_mut(&mut self) -> Option<&mut L> {
|
||||||
|
match self {
|
||||||
|
Either::Left(l) => Some(l),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right_mut(&mut self) -> Option<&mut R> {
|
||||||
|
match self {
|
||||||
|
Either::Right(r) => Some(r),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_left(self) -> Option<L> {
|
||||||
|
match self {
|
||||||
|
Either::Left(l) => Some(l),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_right(self) -> Option<R> {
|
||||||
|
match self {
|
||||||
|
Either::Right(r) => Some(r),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
yazi_macro::mod_pub!(errors event fs shell theme translit);
|
yazi_macro::mod_pub!(errors event fs shell theme translit);
|
||||||
|
|
||||||
yazi_macro::mod_flat!(chars condition debounce env id layer natsort number os rand ro_cell sync_cell terminal throttle time xdg);
|
yazi_macro::mod_flat!(chars condition debounce either env id layer natsort number os rand ro_cell sync_cell terminal throttle time xdg);
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue