fix: fallback to PollWatcher on WSL (#1574)

This commit is contained in:
三咲雅 · Misaki Masa 2024-08-31 01:33:28 +08:00 committed by GitHub
parent 69e7c8ff0d
commit a0a2331b3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 42 additions and 23 deletions

View file

@ -6,7 +6,7 @@ use tracing::warn;
use yazi_shared::env_exists; use yazi_shared::env_exists;
use super::{Iterm2, Kitty, KittyOld}; use super::{Iterm2, Kitty, KittyOld};
use crate::{Chafa, Emulator, Sixel, Ueberzug, SHOWN, TMUX}; use crate::{Chafa, Emulator, Sixel, Ueberzug, SHOWN, TMUX, WSL};
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Adapter { pub enum Adapter {
@ -108,7 +108,7 @@ impl Adapter {
if env_exists("DISPLAY") { if env_exists("DISPLAY") {
return Self::X11; return Self::X11;
} }
if std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok() { if *WSL {
return Self::KittyOld; return Self::KittyOld;
} }

View file

@ -20,7 +20,7 @@ use kitty::*;
use kitty_old::*; use kitty_old::*;
use sixel::*; use sixel::*;
use ueberzug::*; use ueberzug::*;
use yazi_shared::{env_exists, RoCell}; use yazi_shared::{env_exists, in_wsl, RoCell};
pub use crate::image::*; pub use crate::image::*;
@ -32,10 +32,14 @@ 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();
// WSL support
pub static WSL: RoCell<bool> = RoCell::new();
// Image state // Image state
static SHOWN: RoCell<arc_swap::ArcSwapOption<ratatui::layout::Rect>> = RoCell::new(); static SHOWN: RoCell<arc_swap::ArcSwapOption<ratatui::layout::Rect>> = RoCell::new();
pub fn init() { pub fn init() {
// Tmux support
TMUX.init(env_exists("TMUX") && env_exists("TMUX_PANE")); TMUX.init(env_exists("TMUX") && env_exists("TMUX_PANE"));
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" }); ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
START.init(if *TMUX { "\x1bPtmux;\x1b\x1b" } else { "\x1b" }); START.init(if *TMUX { "\x1bPtmux;\x1b\x1b" } else { "\x1b" });
@ -50,6 +54,10 @@ pub fn init() {
.status(); .status();
} }
// WSL support
WSL.init(in_wsl());
// Image state
SHOWN.with(<_>::default); SHOWN.with(<_>::default);
ADAPTOR.init(Adapter::matches()); ADAPTOR.init(Adapter::matches());

View file

@ -39,11 +39,7 @@ impl Actions {
writeln!(s, " shared.in_ssh_connection: {:?}", yazi_shared::in_ssh_connection())?; writeln!(s, " shared.in_ssh_connection: {:?}", yazi_shared::in_ssh_connection())?;
writeln!(s, "\nWSL")?; writeln!(s, "\nWSL")?;
writeln!( writeln!(s, " WSL: {:?}", *yazi_adapter::WSL)?;
s,
" /proc/sys/fs/binfmt_misc/WSLInterop: {:?}",
std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok()
)?;
writeln!(s, "\nVariables")?; writeln!(s, "\nVariables")?;
writeln!(s, " SHELL : {:?}", env::var_os("SHELL"))?; writeln!(s, " SHELL : {:?}", env::var_os("SHELL"))?;

View file

@ -1,7 +1,7 @@
use std::{collections::{HashMap, HashSet}, time::Duration}; use std::{collections::{HashMap, HashSet}, time::Duration};
use anyhow::Result; use anyhow::Result;
use notify_fork::{RecommendedWatcher, RecursiveMode, Watcher as _Watcher}; use notify_fork::{PollWatcher, RecommendedWatcher, RecursiveMode, Watcher as _Watcher};
use parking_lot::RwLock; use parking_lot::RwLock;
use tokio::{fs, pin, sync::{mpsc::{self, UnboundedReceiver}, watch}}; use tokio::{fs, pin, sync::{mpsc::{self, UnboundedReceiver}, watch}};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
@ -27,20 +27,23 @@ impl Watcher {
let (out_tx, out_rx) = mpsc::unbounded_channel(); let (out_tx, out_rx) = mpsc::unbounded_channel();
let out_tx_ = out_tx.clone(); let out_tx_ = out_tx.clone();
let watcher = RecommendedWatcher::new( let handler = move |res: Result<notify_fork::Event, notify_fork::Error>| {
move |res: Result<notify_fork::Event, notify_fork::Error>| { let Ok(event) = res else { return };
let Ok(event) = res else { return }; if event.kind.is_access() {
if event.kind.is_access() { return;
return; }
} for path in event.paths {
for path in event.paths { out_tx_.send(Url::from(path)).ok();
out_tx_.send(Url::from(path)).ok(); }
} };
},
Default::default(), let config = notify_fork::Config::default().with_poll_interval(Duration::from_millis(500));
); if *yazi_adapter::WSL {
tokio::spawn(Self::fan_in(in_rx, PollWatcher::new(handler, config).unwrap()));
} else {
tokio::spawn(Self::fan_in(in_rx, RecommendedWatcher::new(handler, config).unwrap()));
}
tokio::spawn(Self::fan_in(in_rx, watcher.unwrap()));
tokio::spawn(Self::fan_out(out_rx)); tokio::spawn(Self::fan_out(out_rx));
Self { in_tx, out_tx } Self { in_tx, out_tx }
} }
@ -76,7 +79,7 @@ impl Watcher {
}); });
} }
async fn fan_in(mut rx: watch::Receiver<HashSet<Url>>, mut watcher: RecommendedWatcher) { async fn fan_in(mut rx: watch::Receiver<HashSet<Url>>, mut watcher: impl notify_fork::Watcher) {
loop { loop {
let (mut to_unwatch, mut to_watch): (HashSet<_>, HashSet<_>) = { let (mut to_unwatch, mut to_watch): (HashSet<_>, HashSet<_>) = {
let (new, old) = (&*rx.borrow_and_update(), &*WATCHED.read()); let (new, old) = (&*rx.borrow_and_update(), &*WATCHED.read());

View file

@ -1,6 +1,18 @@
#[inline] #[inline]
pub fn env_exists(name: &str) -> bool { std::env::var_os(name).is_some_and(|s| !s.is_empty()) } pub fn env_exists(name: &str) -> bool { std::env::var_os(name).is_some_and(|s| !s.is_empty()) }
#[inline]
pub fn in_wsl() -> bool {
#[cfg(target_os = "linux")]
{
std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok()
}
#[cfg(not(target_os = "linux"))]
{
false
}
}
#[inline] #[inline]
pub fn in_ssh_connection() -> bool { pub fn in_ssh_connection() -> bool {
env_exists("SSH_CLIENT") || env_exists("SSH_TTY") || env_exists("SSH_CONNECTION") env_exists("SSH_CLIENT") || env_exists("SSH_TTY") || env_exists("SSH_CONNECTION")