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 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)]
pub enum Adapter {
@ -108,7 +108,7 @@ impl Adapter {
if env_exists("DISPLAY") {
return Self::X11;
}
if std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok() {
if *WSL {
return Self::KittyOld;
}

View file

@ -20,7 +20,7 @@ use kitty::*;
use kitty_old::*;
use sixel::*;
use ueberzug::*;
use yazi_shared::{env_exists, RoCell};
use yazi_shared::{env_exists, in_wsl, RoCell};
pub use crate::image::*;
@ -32,10 +32,14 @@ static ESCAPE: RoCell<&'static str> = RoCell::new();
static START: RoCell<&'static str> = RoCell::new();
static CLOSE: RoCell<&'static str> = RoCell::new();
// WSL support
pub static WSL: RoCell<bool> = RoCell::new();
// Image state
static SHOWN: RoCell<arc_swap::ArcSwapOption<ratatui::layout::Rect>> = RoCell::new();
pub fn init() {
// Tmux support
TMUX.init(env_exists("TMUX") && env_exists("TMUX_PANE"));
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
START.init(if *TMUX { "\x1bPtmux;\x1b\x1b" } else { "\x1b" });
@ -50,6 +54,10 @@ pub fn init() {
.status();
}
// WSL support
WSL.init(in_wsl());
// Image state
SHOWN.with(<_>::default);
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, "\nWSL")?;
writeln!(
s,
" /proc/sys/fs/binfmt_misc/WSLInterop: {:?}",
std::fs::symlink_metadata("/proc/sys/fs/binfmt_misc/WSLInterop").is_ok()
)?;
writeln!(s, " WSL: {:?}", *yazi_adapter::WSL)?;
writeln!(s, "\nVariables")?;
writeln!(s, " SHELL : {:?}", env::var_os("SHELL"))?;

View file

@ -1,7 +1,7 @@
use std::{collections::{HashMap, HashSet}, time::Duration};
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 tokio::{fs, pin, sync::{mpsc::{self, UnboundedReceiver}, watch}};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
@ -27,20 +27,23 @@ impl Watcher {
let (out_tx, out_rx) = mpsc::unbounded_channel();
let out_tx_ = out_tx.clone();
let watcher = RecommendedWatcher::new(
move |res: Result<notify_fork::Event, notify_fork::Error>| {
let Ok(event) = res else { return };
if event.kind.is_access() {
return;
}
for path in event.paths {
out_tx_.send(Url::from(path)).ok();
}
},
Default::default(),
);
let handler = move |res: Result<notify_fork::Event, notify_fork::Error>| {
let Ok(event) = res else { return };
if event.kind.is_access() {
return;
}
for path in event.paths {
out_tx_.send(Url::from(path)).ok();
}
};
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));
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 {
let (mut to_unwatch, mut to_watch): (HashSet<_>, HashSet<_>) = {
let (new, old) = (&*rx.borrow_and_update(), &*WATCHED.read());

View file

@ -1,6 +1,18 @@
#[inline]
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]
pub fn in_ssh_connection() -> bool {
env_exists("SSH_CLIENT") || env_exists("SSH_TTY") || env_exists("SSH_CONNECTION")