From f4f17803c6c5b413ef6b43308cb6e0cfcb68224e Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Thu, 28 May 2026 23:23:18 +0300 Subject: fix: prefer osc52 clipboard writes in wsl refs #333 --- src/selection.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/selection.rs b/src/selection.rs index 35e44c1d..b2e37c3e 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -243,14 +243,51 @@ fn osc52_sequence(bytes: &[u8]) -> String { format!("\x1b]52;c;{encoded}\x07") } -fn should_prefer_osc52_for_env(ssh_connection: Option<&OsStr>, ssh_tty: Option<&OsStr>) -> bool { - ssh_connection.is_some() || ssh_tty.is_some() +fn contains_wsl_marker(value: &str) -> bool { + let lower = value.to_ascii_lowercase(); + lower.contains("microsoft") || lower.contains("wsl2") || lower.contains("-wsl") +} + +fn is_wsl_for_env( + os_release: Option<&str>, + proc_version: Option<&str>, + wsl_distro_name: Option<&OsStr>, + wsl_interop: Option<&OsStr>, + runtime_marker_exists: bool, +) -> bool { + wsl_distro_name.is_some() + || wsl_interop.is_some() + || os_release.is_some_and(contains_wsl_marker) + || proc_version.is_some_and(contains_wsl_marker) + || runtime_marker_exists +} + +fn is_wsl() -> bool { + let os_release = std::fs::read_to_string("/proc/sys/kernel/osrelease").ok(); + let proc_version = std::fs::read_to_string("/proc/version").ok(); + is_wsl_for_env( + os_release.as_deref(), + proc_version.as_deref(), + std::env::var_os("WSL_DISTRO_NAME").as_deref(), + std::env::var_os("WSL_INTEROP").as_deref(), + std::path::Path::new("/run/WSL").exists() + || std::path::Path::new("/proc/sys/fs/binfmt_misc/WSLInterop").exists(), + ) +} + +fn should_prefer_osc52_for_env( + ssh_connection: Option<&OsStr>, + ssh_tty: Option<&OsStr>, + wsl: bool, +) -> bool { + ssh_connection.is_some() || ssh_tty.is_some() || wsl } fn should_prefer_osc52() -> bool { should_prefer_osc52_for_env( std::env::var_os("SSH_CONNECTION").as_deref(), std::env::var_os("SSH_TTY").as_deref(), + is_wsl(), ) } @@ -291,13 +328,74 @@ mod tests { fn ssh_sessions_prefer_osc52() { assert!(should_prefer_osc52_for_env( Some(OsStr::new("1 2 3 4")), - None + None, + false )); assert!(should_prefer_osc52_for_env( None, - Some(OsStr::new("/dev/ttys001")) + Some(OsStr::new("/dev/ttys001")), + false )); - assert!(!should_prefer_osc52_for_env(None, None)); + assert!(!should_prefer_osc52_for_env(None, None, false)); + } + + #[test] + fn wsl_sessions_prefer_osc52() { + assert!(should_prefer_osc52_for_env(None, None, true)); + } + + #[test] + fn wsl_detection_uses_env_vars() { + assert!(is_wsl_for_env( + None, + None, + Some(OsStr::new("Ubuntu")), + None, + false + )); + assert!(is_wsl_for_env( + None, + None, + None, + Some(OsStr::new("/run/WSL/123_interop")), + false + )); + } + + #[test] + fn wsl_detection_uses_kernel_markers() { + assert!(is_wsl_for_env( + Some("5.15.167.4-microsoft-standard-WSL2"), + None, + None, + None, + false + )); + assert!(is_wsl_for_env( + None, + Some("Linux version 5.15.167.4-microsoft-standard-WSL2"), + None, + None, + false + )); + } + + #[test] + fn wsl_detection_ignores_non_wsl_kernel_strings() { + assert!(!contains_wsl_marker("notwsl-kernel")); + assert!(!is_wsl_for_env( + Some("6.8.0-31-generic"), + Some("Linux version 6.8.0-31-generic"), + None, + None, + false + )); + } + + #[test] + fn wsl_detection_uses_wsl_runtime_markers() { + assert!(is_wsl_for_env(None, None, None, None, true)); + assert!(!is_wsl_for_env(None, None, None, None, false)); } #[test] -- cgit v1.2.3