mirror of
https://github.com/eza-community/eza
synced 2024-07-21 01:55:44 +00:00
parent
51cdb54722
commit
3436171e9f
43
Cargo.lock
generated
43
Cargo.lock
generated
|
@ -94,6 +94,7 @@ dependencies = [
|
|||
"num_cpus",
|
||||
"number_prefix",
|
||||
"phf",
|
||||
"proc-mounts",
|
||||
"scoped_threadpool",
|
||||
"term_grid",
|
||||
"terminal_size",
|
||||
|
@ -288,6 +289,15 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "partition-identity"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa925f9becb532d758b0014b472c576869910929cf4c3f8054b386f19ab9e21"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
@ -351,6 +361,15 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-mounts"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d652f8435d0ab70bf4f3590a6a851d59604831a458086541b95238cc51ffcf2"
|
||||
dependencies = [
|
||||
"partition-identity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
|
@ -409,9 +428,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.29"
|
||||
version = "2.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -437,6 +456,26 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "timeago"
|
||||
version = "0.4.1"
|
||||
|
|
|
@ -67,6 +67,9 @@ default-features = false
|
|||
# See: https://github.com/eza-community/eza/pull/192
|
||||
features = ["vendored-libgit2"]
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
proc-mounts = "0.3"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
uzers = "0.11.2"
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ By deliberately making some decisions differently, eza attempts to be a more fea
|
|||
|
||||
- Fixes [“The Grid Bug”](https://github.com/eza-community/eza/issues/66#issuecomment-1656758327) introduced in exa 2021.
|
||||
- Hyperlink support.
|
||||
- Mount point details.
|
||||
- Selinux context output.
|
||||
- Git repo status output.
|
||||
- Human readable relative dates.
|
||||
|
@ -170,6 +171,7 @@ These options are available when running with `--long` (`-l`):
|
|||
- **-H**, **--links**: list each file’s number of hard links
|
||||
- **-i**, **--inode**: list each file’s inode number
|
||||
- **-m**, **--modified**: use the modified timestamp field
|
||||
- **-M**, **--mounts**: Show mount details (Linux only).
|
||||
- **-S**, **--blocksize**: show size of allocated file system blocks
|
||||
- **-t**, **--time=(field)**: which timestamp field to use
|
||||
- **-u**, **--accessed**: use the accessed timestamp field
|
||||
|
|
|
@ -89,6 +89,7 @@ complete -c eza -s o -l octal-permissions -d "List each file's permission in oct
|
|||
complete -c eza -l no-filesize -d "Suppress the filesize field"
|
||||
complete -c eza -l no-user -d "Suppress the user field"
|
||||
complete -c eza -l no-time -d "Suppress the time field"
|
||||
complete -c eza -s M -l mounts -d "Show mount details"
|
||||
|
||||
# Optional extras
|
||||
complete -c eza -l git -d "List each file's Git status, if tracked"
|
||||
|
|
|
@ -60,6 +60,7 @@ __eza() {
|
|||
--git-repos-no-status"[List each git-repos branch name (much faster)]" \
|
||||
{-@,--extended}"[List each file's extended attributes and sizes]" \
|
||||
{-Z,--context}"[List each file's security context]" \
|
||||
{-M,--mounts}"[Show mount details (long mode only)]" \
|
||||
'*:filename:_files'
|
||||
}
|
||||
|
||||
|
|
|
@ -149,6 +149,9 @@ These options are available when running with `--long` (`-l`):
|
|||
`-m`, `--modified`
|
||||
: Use the modified timestamp field.
|
||||
|
||||
`-M`, `--mounts`
|
||||
: Show mount details (Linux only)
|
||||
|
||||
`-n`, `--numeric`
|
||||
: List numeric user and group IDs.
|
||||
|
||||
|
|
|
@ -220,6 +220,9 @@ LIST OF CODES
|
|||
`bO`
|
||||
: the overlay style for broken symlink paths
|
||||
|
||||
`mp`
|
||||
: a mount point
|
||||
|
||||
Values in `EXA_COLORS` override those given in `LS_COLORS`, so you don’t need to re-write an existing `LS_COLORS` variable with proprietary extensions.
|
||||
|
||||
|
||||
|
|
|
@ -12,11 +12,14 @@ use std::time::{Duration, UNIX_EPOCH};
|
|||
|
||||
use log::*;
|
||||
|
||||
use crate::ALL_MOUNTS;
|
||||
use crate::fs::dir::Dir;
|
||||
use crate::fs::feature::xattr;
|
||||
use crate::fs::feature::xattr::{FileAttributes, Attribute};
|
||||
use crate::fs::fields as f;
|
||||
|
||||
use super::mounts::MountedFs;
|
||||
|
||||
|
||||
/// A **File** is a wrapper around one of Rust’s `PathBuf` values, along with
|
||||
/// associated data about the file.
|
||||
|
@ -79,7 +82,9 @@ pub struct File<'dir> {
|
|||
pub deref_links: bool,
|
||||
/// The extended attributes of this file.
|
||||
pub extended_attributes: Vec<Attribute>,
|
||||
}
|
||||
|
||||
/// The absolute value of this path, used to look up mount points.
|
||||
pub absolute_path: PathBuf,}
|
||||
|
||||
impl<'dir> File<'dir> {
|
||||
pub fn from_args<PD, FN>(path: PathBuf, parent_dir: PD, filename: FN, deref_links: bool) -> io::Result<File<'dir>>
|
||||
|
@ -94,8 +99,9 @@ impl<'dir> File<'dir> {
|
|||
let metadata = std::fs::symlink_metadata(&path)?;
|
||||
let is_all_all = false;
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path)?;
|
||||
|
||||
Ok(File { name, ext, path, metadata, parent_dir, is_all_all, deref_links, extended_attributes })
|
||||
Ok(File { name, ext, path, metadata, parent_dir, is_all_all, deref_links, extended_attributes, absolute_path })
|
||||
}
|
||||
|
||||
pub fn new_aa_current(parent_dir: &'dir Dir) -> io::Result<File<'dir>> {
|
||||
|
@ -107,8 +113,9 @@ impl<'dir> File<'dir> {
|
|||
let is_all_all = true;
|
||||
let parent_dir = Some(parent_dir);
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path)?;
|
||||
|
||||
Ok(File { path, parent_dir, metadata, ext, name: ".".into(), is_all_all, deref_links: false, extended_attributes })
|
||||
Ok(File { path, parent_dir, metadata, ext, name: ".".into(), is_all_all, deref_links: false, extended_attributes, absolute_path })
|
||||
}
|
||||
|
||||
pub fn new_aa_parent(path: PathBuf, parent_dir: &'dir Dir) -> io::Result<File<'dir>> {
|
||||
|
@ -119,8 +126,9 @@ impl<'dir> File<'dir> {
|
|||
let is_all_all = true;
|
||||
let parent_dir = Some(parent_dir);
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path)?;
|
||||
|
||||
Ok(File { path, parent_dir, metadata, ext, name: "..".into(), is_all_all, deref_links: false, extended_attributes })
|
||||
Ok(File { path, parent_dir, metadata, ext, name: "..".into(), is_all_all, deref_links: false, extended_attributes, absolute_path })
|
||||
}
|
||||
|
||||
/// A file’s name is derived from its string. This needs to handle directories
|
||||
|
@ -243,6 +251,21 @@ impl<'dir> File<'dir> {
|
|||
self.metadata.file_type().is_socket()
|
||||
}
|
||||
|
||||
/// Whether this file is a mount point
|
||||
pub fn is_mount_point(&self) -> bool {
|
||||
if cfg!(target_os = "linux") && self.is_directory() {
|
||||
return ALL_MOUNTS.contains_key(&self.absolute_path);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// The filesystem device and type for a mount point
|
||||
pub fn mount_point_info(&self) -> Option<&MountedFs> {
|
||||
if cfg!(target_os = "linux") {
|
||||
return ALL_MOUNTS.get(&self.absolute_path);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Re-prefixes the path pointed to by this file, if it’s a symlink, to
|
||||
/// make it an absolute path that can be accessed from whichever
|
||||
|
@ -293,7 +316,17 @@ impl<'dir> File<'dir> {
|
|||
let ext = File::ext(&path);
|
||||
let name = File::filename(&path);
|
||||
let extended_attributes = File::gather_extended_attributes(&absolute_path);
|
||||
let file = File { parent_dir: None, path, ext, metadata, name, is_all_all: false, deref_links: self.deref_links, extended_attributes };
|
||||
let file = File {
|
||||
parent_dir: None,
|
||||
path,
|
||||
ext,
|
||||
metadata,
|
||||
name,
|
||||
is_all_all: false,
|
||||
deref_links: self.deref_links,
|
||||
extended_attributes,
|
||||
absolute_path
|
||||
};
|
||||
FileTarget::Ok(Box::new(file))
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
|
@ -8,3 +8,4 @@ pub mod dir_action;
|
|||
pub mod feature;
|
||||
pub mod fields;
|
||||
pub mod filter;
|
||||
pub mod mounts;
|
6
src/fs/mounts.rs
Normal file
6
src/fs/mounts.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
/// Details of a mounted filesystem.
|
||||
pub struct MountedFs {
|
||||
pub dest: String,
|
||||
pub fstype: String,
|
||||
pub source: String,
|
||||
}
|
29
src/main.rs
29
src/main.rs
|
@ -22,6 +22,7 @@
|
|||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(clippy::wildcard_imports)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::io::{self, Write, ErrorKind};
|
||||
|
@ -31,6 +32,13 @@ use ansi_term::{ANSIStrings, Style};
|
|||
|
||||
use log::*;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use proc_mounts::MountList;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use crate::fs::mounts::MountedFs;
|
||||
use crate::fs::{Dir, File};
|
||||
use crate::fs::feature::git::GitCache;
|
||||
use crate::fs::filter::GitIgnore;
|
||||
|
@ -45,6 +53,27 @@ mod options;
|
|||
mod output;
|
||||
mod theme;
|
||||
|
||||
lazy_static! {
|
||||
static ref ALL_MOUNTS: HashMap<PathBuf, MountedFs> = {
|
||||
#[cfg(target_os = "linux")]
|
||||
match MountList::new() {
|
||||
Ok(mount_list) => {
|
||||
let mut m = HashMap::new();
|
||||
mount_list.0.iter().for_each(|mount| {
|
||||
m.insert(mount.dest.clone(), MountedFs {
|
||||
dest: mount.dest.to_string_lossy().into_owned(),
|
||||
fstype: mount.fstype.clone(),
|
||||
source: mount.source.to_string_lossy().into(),
|
||||
});
|
||||
});
|
||||
m
|
||||
}
|
||||
Err(_) => HashMap::new()
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
HashMap::new()
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use std::process::exit;
|
||||
|
|
|
@ -54,7 +54,8 @@ pub static TIME: Arg = Arg { short: Some(b't'), long: "time", takes_
|
|||
pub static ACCESSED: Arg = Arg { short: Some(b'u'), long: "accessed", takes_value: TakesValue::Forbidden };
|
||||
pub static CREATED: Arg = Arg { short: Some(b'U'), long: "created", takes_value: TakesValue::Forbidden };
|
||||
pub static TIME_STYLE: Arg = Arg { short: None, long: "time-style", takes_value: TakesValue::Necessary(Some(TIME_STYLES)) };
|
||||
pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Forbidden};
|
||||
pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Forbidden };
|
||||
pub static MOUNTS: Arg = Arg { short: Some(b'M'), long: "mounts", takes_value: TakesValue::Forbidden };
|
||||
const TIMES: Values = &["modified", "changed", "accessed", "created"];
|
||||
const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso", "relative"];
|
||||
|
||||
|
@ -85,7 +86,7 @@ pub static ALL_ARGS: Args = Args(&[
|
|||
&IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS,
|
||||
|
||||
&BINARY, &BYTES, &GROUP, &NUMERIC, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
|
||||
&BLOCKSIZE, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, &HYPERLINK,
|
||||
&BLOCKSIZE, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, &HYPERLINK, &MOUNTS,
|
||||
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &NO_ICONS,
|
||||
|
||||
&GIT, &NO_GIT, &GIT_REPOS, &GIT_REPOS_NO_STAT,
|
||||
|
|
|
@ -53,6 +53,7 @@ LONG VIEW OPTIONS
|
|||
-H, --links list each file's number of hard links
|
||||
-i, --inode list each file's inode number
|
||||
-m, --modified use the modified timestamp field
|
||||
-M, --mounts show mount details (Linux only)
|
||||
-n, --numeric list numeric user and group IDs
|
||||
-S, --blocksize show size of allocated file system blocks
|
||||
-t, --time FIELD which timestamp field to list (modified, accessed, created)
|
||||
|
|
|
@ -82,7 +82,8 @@ impl Mode {
|
|||
// user about flags that won’t have any effect.
|
||||
if matches.is_strict() {
|
||||
for option in &[ &flags::BINARY, &flags::BYTES, &flags::INODE, &flags::LINKS,
|
||||
&flags::HEADER, &flags::BLOCKSIZE, &flags::TIME, &flags::GROUP, &flags::NUMERIC ] {
|
||||
&flags::HEADER, &flags::BLOCKSIZE, &flags::TIME, &flags::GROUP, &flags::NUMERIC,
|
||||
&flags::MOUNTS ] {
|
||||
if matches.has(option)? {
|
||||
return Err(OptionsError::Useless(option, false, &flags::LONG));
|
||||
}
|
||||
|
@ -119,6 +120,7 @@ impl details::Options {
|
|||
header: false,
|
||||
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
||||
secattr: xattr::ENABLED && matches.has(&flags::SECURITY_CONTEXT)?,
|
||||
mounts: matches.has(&flags::MOUNTS)?,
|
||||
};
|
||||
|
||||
Ok(details)
|
||||
|
@ -139,6 +141,7 @@ impl details::Options {
|
|||
header: matches.has(&flags::HEADER)?,
|
||||
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
||||
secattr: xattr::ENABLED && matches.has(&flags::SECURITY_CONTEXT)?,
|
||||
mounts: matches.has(&flags::MOUNTS)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ use crate::theme::Theme;
|
|||
///
|
||||
/// Almost all the heavy lifting is done in a Table object, which handles the
|
||||
/// columns for each row.
|
||||
#[allow(clippy::struct_excessive_bools)] /// This clearly isn't a state machine
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Options {
|
||||
|
||||
|
@ -109,6 +110,9 @@ pub struct Options {
|
|||
|
||||
/// Whether to show each file's security attribute.
|
||||
pub secattr: bool,
|
||||
|
||||
/// Whether to show a directory's mounted filesystem details
|
||||
pub mounts: bool,
|
||||
}
|
||||
|
||||
|
||||
|
@ -288,6 +292,7 @@ impl<'a> Render<'a> {
|
|||
|
||||
let file_name = self.file_style.for_file(egg.file, self.theme)
|
||||
.with_link_paths()
|
||||
.with_mount_details(self.opts.mounts)
|
||||
.paint()
|
||||
.promote();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
|
||||
use ansi_term::{ANSIString, Style};
|
||||
|
||||
use crate::fs::mounts::MountedFs;
|
||||
use crate::fs::{File, FileTarget};
|
||||
use crate::output::cell::TextCellContents;
|
||||
use crate::output::escape;
|
||||
|
@ -35,7 +36,9 @@ impl Options {
|
|||
link_style: LinkStyle::JustFilenames,
|
||||
options: self,
|
||||
target: if file.is_link() { Some(file.link_target()) }
|
||||
else { None }
|
||||
else { None },
|
||||
mount_style: MountStyle::JustDirectoryNames,
|
||||
mounted_fs: file.mount_point_info(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +77,18 @@ impl Default for Classify {
|
|||
}
|
||||
}
|
||||
|
||||
/// When displaying a directory name, there needs to be some way to handle
|
||||
/// mount details, depending on how long the resulting Cell can be.
|
||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||
enum MountStyle {
|
||||
|
||||
/// Just display the directory names.
|
||||
JustDirectoryNames,
|
||||
|
||||
/// Display mount points as directories and include information about
|
||||
/// the filesystem that's mounted there.
|
||||
MountInfo,
|
||||
}
|
||||
|
||||
/// Whether and how to show icons.
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
|
@ -112,6 +127,12 @@ pub struct FileName<'a, 'dir, C> {
|
|||
link_style: LinkStyle,
|
||||
|
||||
pub options: Options,
|
||||
|
||||
/// The filesystem details for a mounted filesystem.
|
||||
mounted_fs: Option<&'a MountedFs>,
|
||||
|
||||
/// How to handle displaying a mounted filesystem.
|
||||
mount_style: MountStyle,
|
||||
}
|
||||
|
||||
impl<'a, 'dir, C> FileName<'a, 'dir, C> {
|
||||
|
@ -122,6 +143,17 @@ impl<'a, 'dir, C> FileName<'a, 'dir, C> {
|
|||
self.link_style = LinkStyle::FullLinkPaths;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the flag on this file name to display mounted filesystem
|
||||
///details.
|
||||
pub fn with_mount_details(mut self, enable: bool) -> Self {
|
||||
self.mount_style = if enable {
|
||||
MountStyle::MountInfo
|
||||
} else {
|
||||
MountStyle::JustDirectoryNames
|
||||
};
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
||||
|
@ -190,6 +222,8 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
|||
target: None,
|
||||
link_style: LinkStyle::FullLinkPaths,
|
||||
options: target_options,
|
||||
mounted_fs: None,
|
||||
mount_style: MountStyle::JustDirectoryNames,
|
||||
};
|
||||
|
||||
for bit in target_name.escaped_file_name() {
|
||||
|
@ -228,6 +262,15 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
|||
}
|
||||
}
|
||||
|
||||
if let (MountStyle::MountInfo, Some(mount_details)) = (self.mount_style, self.mounted_fs.as_ref()) {
|
||||
// This is a filesystem mounted on the directory, output its details
|
||||
bits.push(Style::default().paint(" ["));
|
||||
bits.push(Style::default().paint(mount_details.source.clone()));
|
||||
bits.push(Style::default().paint(" ("));
|
||||
bits.push(Style::default().paint(mount_details.fstype.clone()));
|
||||
bits.push(Style::default().paint(")]"));
|
||||
}
|
||||
|
||||
bits.into()
|
||||
}
|
||||
|
||||
|
@ -372,6 +415,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
|||
}
|
||||
|
||||
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(),
|
||||
|
@ -424,6 +468,9 @@ pub trait Colours: FiletypeColours {
|
|||
/// The style to paint a file that has its executable bit set.
|
||||
fn executable_file(&self) -> Style;
|
||||
|
||||
/// The style to paint a directory that has a filesystem mounted on it.
|
||||
fn mount_point(&self) -> Style;
|
||||
|
||||
fn colour_file(&self, file: &File<'_>) -> Style;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use ansi_term::ANSIStrings;
|
|||
use crate::fs::File;
|
||||
use crate::fs::filter::FileFilter;
|
||||
use crate::output::cell::TextCellContents;
|
||||
use crate::output::file_name::{Options as FileStyle};
|
||||
use crate::output::file_name::Options as FileStyle;
|
||||
use crate::theme::Theme;
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ impl<'a> Render<'a> {
|
|||
self.file_style
|
||||
.for_file(file, self.theme)
|
||||
.with_link_paths()
|
||||
.with_mount_details(false)
|
||||
.paint()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ impl UiStyles {
|
|||
socket: Red.bold(),
|
||||
special: Yellow.normal(),
|
||||
executable: Green.bold(),
|
||||
mount_point: Blue.bold().underline(),
|
||||
},
|
||||
|
||||
perms: Permissions {
|
||||
|
|
|
@ -327,6 +327,7 @@ impl FileNameColours for Theme {
|
|||
fn control_char(&self) -> Style { self.ui.control_char }
|
||||
fn symlink_path(&self) -> Style { self.ui.symlink_path }
|
||||
fn executable_file(&self) -> Style { self.ui.filekinds.executable }
|
||||
fn mount_point(&self) -> Style { self.ui.filekinds.mount_point }
|
||||
|
||||
fn colour_file(&self, file: &File<'_>) -> Style {
|
||||
self.exts.colour_file(file).unwrap_or(self.ui.filekinds.normal)
|
||||
|
@ -534,6 +535,8 @@ mod customs_test {
|
|||
test!(exa_cc: ls "", exa "cc=38;5;134" => colours c -> { c.control_char = Fixed(134).normal(); });
|
||||
test!(exa_bo: ls "", exa "bO=4" => colours c -> { c.broken_path_overlay = Style::default().underline(); });
|
||||
|
||||
test!(exa_mp: ls "", exa "mp=1;34;4" => colours c -> { c.filekinds.mount_point = Blue.bold().underline(); });
|
||||
|
||||
// All the while, LS_COLORS treats them as filenames:
|
||||
test!(ls_uu: ls "uu=38;5;117", exa "" => exts [ ("uu", Fixed(117).normal()) ]);
|
||||
test!(ls_un: ls "un=38;5;118", exa "" => exts [ ("un", Fixed(118).normal()) ]);
|
||||
|
|
|
@ -39,6 +39,7 @@ pub struct FileKinds {
|
|||
pub socket: Style,
|
||||
pub special: Style,
|
||||
pub executable: Style,
|
||||
pub mount_point: Style,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
|
@ -210,6 +211,8 @@ impl UiStyles {
|
|||
"cc" => self.control_char = pair.to_style(),
|
||||
"bO" => self.broken_path_overlay = pair.to_style(),
|
||||
|
||||
"mp" => self.filekinds.mount_point = pair.to_style(),
|
||||
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue