From a9bb275250e1d2eb3d3e1b2855afee6a0c560903 Mon Sep 17 00:00:00 2001 From: Linden Krouse Date: Mon, 13 Jun 2016 23:14:36 -0400 Subject: [PATCH] Exa now recognizes pipes, devices, and sockets on unix systems. Fixes #112 --- src/fs/fields.rs | 2 +- src/fs/file.rs | 65 +++++++++++++++++++++++++++++++++++++++---- src/output/colours.rs | 6 ++++ src/output/details.rs | 5 +++- src/output/mod.rs | 6 +++- 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/fs/fields.rs b/src/fs/fields.rs index 53ef48f..b0635e7 100644 --- a/src/fs/fields.rs +++ b/src/fs/fields.rs @@ -41,7 +41,7 @@ pub type uid_t = u32; /// file’s contents. So “link” is a type, but “image” is just a type of /// regular file. (See the `filetype` module for those checks.) pub enum Type { - File, Directory, Pipe, Link, Special, + File, Directory, Pipe, Link, Socket, CharDevice, BlockDevice, Special, } impl Type { diff --git a/src/fs/file.rs b/src/fs/file.rs index 6725a04..fdecfc8 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -10,6 +10,8 @@ use std::path::{Path, PathBuf}; use fs::dir::Dir; use fs::fields as f; +#[cfg(any(target_os = "macos", target_os = "linux"))] +use std::os::unix::fs::FileTypeExt; /// Constant table copied from https://doc.rust-lang.org/src/std/sys/unix/ext/fs.rs.html#11-259 /// which is currently unstable and lacks vision for stabilization, @@ -145,12 +147,7 @@ impl<'dir> File<'dir> { /// Whether this file is a symlink on the filesystem. pub fn is_link(&self) -> bool { self.metadata.file_type().is_symlink() - } - - /// Whether this file is a named pipe on the filesystem. - pub fn is_pipe(&self) -> bool { - false // TODO: Still waiting on this one... - } + } /// Whether this file is a dotfile, based on its name. In Unix, file names /// beginning with a dot represent system or configuration files, and @@ -283,6 +280,15 @@ impl<'dir> File<'dir> { else if self.is_link() { f::Type::Link } + else if self.is_char_device() { + f::Type::CharDevice + } + else if self.is_block_device() { + f::Type::BlockDevice + } + else if self.is_socket() { + f::Type::Socket + } else { f::Type::Special } @@ -347,6 +353,53 @@ impl<'dir> File<'dir> { } } +#[cfg(any(target_os = "macos", target_os = "linux"))] +impl<'dir> File<'dir> { + /// Whether this file is a named pipe on the filesystem. + pub fn is_pipe(&self) -> bool { + self.metadata.file_type().is_fifo() + } + + /// Whether this file is a char device on the filesystem. + pub fn is_char_device(&self) -> bool { + self.metadata.file_type().is_char_device() + } + + /// Whether this file is a block device on the filesystem. + pub fn is_block_device(&self) -> bool { + self.metadata.file_type().is_block_device() + } + + /// Whether this file is a socket on the filesystem. + pub fn is_socket(&self) -> bool { + self.metadata.file_type().is_socket() + } +} + +#[cfg(not(any(target_os = "macos", target_os = "linux")))] +impl<'dir> File<'dir> { + /// Whether this file is a named pipe on the filesystem. + pub fn is_pipe(&self) -> bool { + false + } + + /// Whether this file is a char device on the filesystem. + pub fn is_char_device(&self) -> bool { + false + } + + /// Whether this file is a block device on the filesystem. + pub fn is_block_device(&self) -> bool { + false + } + + /// Whether this file is a socket on the filesystem. + pub fn is_socket(&self) -> bool { + false + } +} + + impl<'a> AsRef> for File<'a> { fn as_ref(&self) -> &File<'a> { &self diff --git a/src/output/colours.rs b/src/output/colours.rs index 97ccd87..5708032 100644 --- a/src/output/colours.rs +++ b/src/output/colours.rs @@ -27,6 +27,9 @@ pub struct FileTypes { pub normal: Style, pub directory: Style, pub symlink: Style, + pub pipe: Style, + pub device: Style, + pub socket: Style, pub special: Style, pub executable: Style, pub image: Style, @@ -99,6 +102,9 @@ impl Colours { normal: Style::default(), directory: Blue.bold(), symlink: Cyan.normal(), + pipe: Yellow.normal(), + device: Yellow.bold(), + socket: Red.bold(), special: Yellow.normal(), executable: Green.bold(), image: Fixed(133).normal(), diff --git a/src/output/details.rs b/src/output/details.rs index f6837c1..b30d2a3 100644 --- a/src/output/details.rs +++ b/src/output/details.rs @@ -515,8 +515,11 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> { let type_char = match file_type { f::Type::File => types.normal.paint("."), f::Type::Directory => types.directory.paint("d"), - f::Type::Pipe => types.special.paint("|"), + f::Type::Pipe => types.pipe.paint("|"), f::Type::Link => types.symlink.paint("l"), + f::Type::CharDevice => types.device.paint("c"), + f::Type::BlockDevice => types.device.paint("b"), + f::Type::Socket => types.socket.paint("s"), f::Type::Special => types.special.paint("?"), }; diff --git a/src/output/mod.rs b/src/output/mod.rs index f6aa294..d1f6137 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -84,7 +84,11 @@ pub fn file_colour(colours: &Colours, file: &File) -> Style { f if f.is_directory() => colours.filetypes.directory, f if f.is_executable_file() => colours.filetypes.executable, f if f.is_link() => colours.filetypes.symlink, - f if !f.is_file() => colours.filetypes.special, + f if f.is_pipe() => colours.filetypes.pipe, + f if f.is_char_device() + | f.is_block_device() => colours.filetypes.device, + f if f.is_socket() => colours.filetypes.socket, + f if !f.is_file() => colours.filetypes.special, f if f.is_immediate() => colours.filetypes.immediate, f if f.is_image() => colours.filetypes.image, f if f.is_video() => colours.filetypes.video,