diff --git a/src/fs/file.rs b/src/fs/file.rs index bd181de8b..02a9a6048 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -8,6 +8,10 @@ #[cfg(unix)] use std::collections::HashMap; +#[cfg(windows)] +use std::collections::HashSet; +#[cfg(windows)] +use std::env; use std::fs::FileType; use std::io; #[cfg(unix)] @@ -331,16 +335,35 @@ impl<'dir> File<'dir> { /// Whether this file is both a regular file *and* executable for the /// current user. An executable file has a different purpose from an /// executable directory, so they should be highlighted differently. - #[cfg(unix)] pub fn is_executable_file(&self) -> bool { - let bit = modes::USER_EXECUTE; - if !self.is_file() { - return false; + #[cfg(unix)] + { + let bit = modes::USER_EXECUTE; + if !self.is_file() { + return false; + } + let Ok(md) = self.metadata() else { + return false; + }; + (md.permissions().mode() & bit) == bit + } + #[cfg(windows)] + { + let Some(ext) = self.ext.as_ref() else { + return false; + }; + + static PATHEXT: OnceLock> = OnceLock::new(); + PATHEXT + .get_or_init(|| { + env::var("PATHEXT") + .unwrap_or_default() + .split(';') + .map(|s| s[1..].to_string()) + .collect::>() + }) + .contains(&ext.to_uppercase()) } - let Ok(md) = self.metadata() else { - return false; - }; - (md.permissions().mode() & bit) == bit } /// Whether this file is a symlink on the filesystem. diff --git a/src/output/file_name.rs b/src/output/file_name.rs index ae232a3d9..b7758df40 100644 --- a/src/output/file_name.rs +++ b/src/output/file_name.rs @@ -489,7 +489,6 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { return match self.file { f if f.is_mount_point() => self.colours.mount_point(), f if f.is_directory() => self.colours.directory(), - #[cfg(unix)] f if f.is_executable_file() => self.colours.executable_file(), f if f.is_link() => self.colours.symlink(), #[cfg(unix)]