Better referencing

This commit makes changes to the way variables are referenced:

• Make types Copy when possible
• Make methods take `self` instead of `&self` where possible (trivially_copy_pass_by_ref)
• Remove unnecessary borrowing (needless_ref)
• Remove unnecessary cloning (clone_on_copy)
• Remove `ref` from match arms where possible (new Rust match ergonomics)
This commit is contained in:
Benjamin Sago 2020-10-10 15:30:19 +01:00
parent 70a30ed683
commit f0c139ca68
27 changed files with 144 additions and 134 deletions

View File

@ -39,16 +39,16 @@ pub enum DirAction {
impl DirAction { impl DirAction {
/// Gets the recurse options, if this dir action has any. /// Gets the recurse options, if this dir action has any.
pub fn recurse_options(&self) -> Option<RecurseOptions> { pub fn recurse_options(self) -> Option<RecurseOptions> {
match *self { match self {
Self::Recurse(o) => Some(o), Self::Recurse(o) => Some(o),
_ => None, _ => None,
} }
} }
/// Whether to treat directories as regular files or not. /// Whether to treat directories as regular files or not.
pub fn treat_dirs_as_files(&self) -> bool { pub fn treat_dirs_as_files(self) -> bool {
match *self { match self {
Self::AsFile => true, Self::AsFile => true,
Self::Recurse(o) => o.tree, Self::Recurse(o) => o.tree,
_ => false, _ => false,
@ -73,7 +73,7 @@ pub struct RecurseOptions {
impl RecurseOptions { impl RecurseOptions {
/// Returns whether a directory of the given depth would be too deep. /// Returns whether a directory of the given depth would be too deep.
pub fn is_too_deep(&self, depth: usize) -> bool { pub fn is_too_deep(self, depth: usize) -> bool {
match self.max_depth { match self.max_depth {
None => false, None => false,
Some(d) => d <= depth Some(d) => d <= depth

View File

@ -43,19 +43,20 @@ pub type uid_t = u32;
/// regular file. (See the `filetype` module for those checks.) /// regular file. (See the `filetype` module for those checks.)
/// ///
/// Its ordering is used when sorting by type. /// Its ordering is used when sorting by type.
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub enum Type { pub enum Type {
Directory, File, Link, Pipe, Socket, CharDevice, BlockDevice, Special, Directory, File, Link, Pipe, Socket, CharDevice, BlockDevice, Special,
} }
impl Type { impl Type {
pub fn is_regular_file(&self) -> bool { pub fn is_regular_file(self) -> bool {
matches!(*self, Self::File) matches!(self, Self::File)
} }
} }
/// The files Unix permission bitfield, with one entry per bit. /// The files Unix permission bitfield, with one entry per bit.
#[derive(Copy, Clone)]
pub struct Permissions { pub struct Permissions {
pub user_read: bool, pub user_read: bool,
pub user_write: bool, pub user_write: bool,
@ -77,6 +78,7 @@ pub struct Permissions {
/// The three pieces of information that are displayed as a single column in /// The three pieces of information that are displayed as a single column in
/// the details view. These values are fused together to make the output a /// the details view. These values are fused together to make the output a
/// little more compressed. /// little more compressed.
#[derive(Copy, Clone)]
pub struct PermissionsPlus { pub struct PermissionsPlus {
pub file_type: Type, pub file_type: Type,
pub permissions: Permissions, pub permissions: Permissions,
@ -85,6 +87,7 @@ pub struct PermissionsPlus {
/// The permissions encoded as octal values /// The permissions encoded as octal values
#[derive(Copy, Clone)]
pub struct OctalPermissions { pub struct OctalPermissions {
pub permissions: Permissions, pub permissions: Permissions,
} }
@ -95,6 +98,7 @@ pub struct OctalPermissions {
/// multiple directories. However, its rare (but occasionally useful!) for a /// multiple directories. However, its rare (but occasionally useful!) for a
/// regular file to have a link count greater than 1, so we highlight the /// regular file to have a link count greater than 1, so we highlight the
/// block count specifically for this case. /// block count specifically for this case.
#[derive(Copy, Clone)]
pub struct Links { pub struct Links {
/// The actual link count. /// The actual link count.
@ -108,10 +112,12 @@ pub struct Links {
/// A files inode. Every directory entry on a Unix filesystem has an inode, /// A files inode. Every directory entry on a Unix filesystem has an inode,
/// including directories and links, so this is applicable to everything exa /// including directories and links, so this is applicable to everything exa
/// can deal with. /// can deal with.
#[derive(Copy, Clone)]
pub struct Inode(pub ino_t); pub struct Inode(pub ino_t);
/// The number of blocks that a file takes up on the filesystem, if any. /// The number of blocks that a file takes up on the filesystem, if any.
#[derive(Copy, Clone)]
pub enum Blocks { pub enum Blocks {
/// This file has the given number of blocks. /// This file has the given number of blocks.
@ -124,14 +130,17 @@ pub enum Blocks {
/// The ID of the user that owns a file. This will only ever be a number; /// The ID of the user that owns a file. This will only ever be a number;
/// looking up the username is done in the `display` module. /// looking up the username is done in the `display` module.
#[derive(Copy, Clone)]
pub struct User(pub uid_t); pub struct User(pub uid_t);
/// The ID of the group that a file belongs to. /// The ID of the group that a file belongs to.
#[derive(Copy, Clone)]
pub struct Group(pub gid_t); pub struct Group(pub gid_t);
/// A files size, in bytes. This is usually formatted by the `number_prefix` /// A files size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable. /// crate into something human-readable.
#[derive(Copy, Clone)]
pub enum Size { pub enum Size {
/// This file has a defined size. /// This file has a defined size.
@ -162,6 +171,7 @@ pub enum Size {
/// You can see what these device numbers mean: /// You can see what these device numbers mean:
/// - http://www.lanana.org/docs/device-list/ /// - http://www.lanana.org/docs/device-list/
/// - http://www.lanana.org/docs/device-list/devices-2.6+.txt /// - http://www.lanana.org/docs/device-list/devices-2.6+.txt
#[derive(Copy, Clone)]
pub struct DeviceIDs { pub struct DeviceIDs {
pub major: u8, pub major: u8,
pub minor: u8, pub minor: u8,
@ -179,7 +189,7 @@ pub struct Time {
/// A files status in a Git repository. Whether a file is in a repository or /// A files status in a Git repository. Whether a file is in a repository or
/// not is handled by the Git module, rather than having a “null” variant in /// not is handled by the Git module, rather than having a “null” variant in
/// this enum. /// this enum.
#[derive(PartialEq)] #[derive(PartialEq, Copy, Clone)]
pub enum GitStatus { pub enum GitStatus {
/// This file hasnt changed since the last commit. /// This file hasnt changed since the last commit.
@ -211,6 +221,7 @@ pub enum GitStatus {
/// A files complete Git status. Its possible to make changes to a file, add /// A files complete Git status. Its possible to make changes to a file, add
/// it to the staging area, then make *more* changes, so we need to list each /// it to the staging area, then make *more* changes, so we need to list each
/// files status for both of these. /// files status for both of these.
#[derive(Copy, Clone)]
pub struct Git { pub struct Git {
pub staged: GitStatus, pub staged: GitStatus,
pub unstaged: GitStatus, pub unstaged: GitStatus,

View File

@ -417,8 +417,8 @@ impl<'dir> File<'dir> {
/// ///
/// This will always return `false` if the file has no extension. /// This will always return `false` if the file has no extension.
pub fn extension_is_one_of(&self, choices: &[&str]) -> bool { pub fn extension_is_one_of(&self, choices: &[&str]) -> bool {
match self.ext { match &self.ext {
Some(ref ext) => choices.contains(&&ext[..]), Some(ext) => choices.contains(&&ext[..]),
None => false, None => false,
} }
} }
@ -463,10 +463,7 @@ impl<'dir> FileTarget<'dir> {
/// Whether this link doesnt lead to a file, for whatever reason. This /// Whether this link doesnt lead to a file, for whatever reason. This
/// gets used to determine how to highlight the link in grid views. /// gets used to determine how to highlight the link in grid views.
pub fn is_broken(&self) -> bool { pub fn is_broken(&self) -> bool {
match *self { matches!(self, Self::Broken(_) | Self::Err(_))
FileTarget::Ok(_) => false,
FileTarget::Broken(_) | FileTarget::Err(_) => true,
}
} }
} }

View File

@ -14,7 +14,7 @@ impl<'a> File<'a> {
/// don't want to always blindly highlight `*.js` as compiled. /// don't want to always blindly highlight `*.js` as compiled.
/// (See also `FileExtensions#is_compiled`) /// (See also `FileExtensions#is_compiled`)
pub fn get_source_files(&self) -> Vec<PathBuf> { pub fn get_source_files(&self) -> Vec<PathBuf> {
if let Some(ref ext) = self.ext { if let Some(ext) = &self.ext {
match &ext[..] { match &ext[..] {
"css" => vec![self.path.with_extension("sass"), self.path.with_extension("less")], // SASS, Less "css" => vec![self.path.with_extension("sass"), self.path.with_extension("less")], // SASS, Less
"js" => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")], // CoffeeScript, TypeScript "js" => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")], // CoffeeScript, TypeScript

View File

@ -228,7 +228,7 @@ impl<'args> Exa<'args> {
if !files.is_empty() { if !files.is_empty() {
let View { ref mode, ref colours, ref style } = self.options.view; let View { ref mode, ref colours, ref style } = self.options.view;
match *mode { match mode {
Mode::Lines(ref opts) => { Mode::Lines(ref opts) => {
let r = lines::Render { files, colours, style, opts }; let r = lines::Render { files, colours, style, opts };
r.render(&mut self.writer) r.render(&mut self.writer)

View File

@ -37,7 +37,7 @@ impl SortField {
// Get String because we cant match an OsStr // Get String because we cant match an OsStr
let word = match word.to_str() { let word = match word.to_str() {
Some(ref w) => *w, Some(w) => w,
None => return Err(Misfire::BadArgument(&flags::SORT, word.into())) None => return Err(Misfire::BadArgument(&flags::SORT, word.into()))
}; };

View File

@ -64,7 +64,7 @@ static OCTAL_HELP: &str = r##" --octal-permissions list each file's permissi
/// All the information needed to display the help text, which depends /// All the information needed to display the help text, which depends
/// on which features are enabled and whether the user only wants to /// on which features are enabled and whether the user only wants to
/// see one sections help. /// see one sections help.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Copy, Clone)]
pub struct HelpString { pub struct HelpString {
/// Only show the help for the long section, not all the help. /// Only show the help for the long section, not all the help.

View File

@ -55,8 +55,8 @@ impl Misfire {
/// The OS return code this misfire should signify. /// The OS return code this misfire should signify.
pub fn is_error(&self) -> bool { pub fn is_error(&self) -> bool {
match *self { match self {
Self::Help(_) => false, Self::Help(_) |
Self::Version(_) => false, Self::Version(_) => false,
_ => true, _ => true,
} }
@ -72,10 +72,9 @@ impl From<glob::PatternError> for Misfire {
impl fmt::Display for Misfire { impl fmt::Display for Misfire {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::options::parser::TakesValue; use crate::options::parser::TakesValue;
use self::Misfire::*;
match *self { match self {
BadArgument(ref arg, ref attempt) => { Self::BadArgument(arg, attempt) => {
if let TakesValue::Necessary(Some(values)) = arg.takes_value { if let TakesValue::Necessary(Some(values)) = arg.takes_value {
write!(f, "Option {} has no {:?} setting ({})", arg, attempt, Choices(values)) write!(f, "Option {} has no {:?} setting ({})", arg, attempt, Choices(values))
} }
@ -83,33 +82,31 @@ impl fmt::Display for Misfire {
write!(f, "Option {} has no {:?} setting", arg, attempt) write!(f, "Option {} has no {:?} setting", arg, attempt)
} }
}, },
InvalidOptions(ref e) => write!(f, "{}", e), Self::InvalidOptions(e) => write!(f, "{}", e),
Unsupported(ref e) => write!(f, "{}", e), Self::Unsupported(e) => write!(f, "{}", e),
Help(ref text) => write!(f, "{}", text), Self::Help(text) => write!(f, "{}", text),
Version(ref version) => write!(f, "{}", version), Self::Version(version) => write!(f, "{}", version),
Conflict(ref a, ref b) => write!(f, "Option {} conflicts with option {}", a, b), Self::Conflict(a, b) => write!(f, "Option {} conflicts with option {}", a, b),
Duplicate(ref a, ref b) => if a == b { write!(f, "Flag {} was given twice", a) } Self::Duplicate(a, b) if a == b => write!(f, "Flag {} was given twice", a),
else { write!(f, "Flag {} conflicts with flag {}", a, b) }, Self::Duplicate(a, b) => write!(f, "Flag {} conflicts with flag {}", a, b),
Useless(ref a, false, ref b) => write!(f, "Option {} is useless without option {}", a, b), Self::Useless(a, false, b) => write!(f, "Option {} is useless without option {}", a, b),
Useless(ref a, true, ref b) => write!(f, "Option {} is useless given option {}", a, b), Self::Useless(a, true, b) => write!(f, "Option {} is useless given option {}", a, b),
Useless2(ref a, ref b1, ref b2) => write!(f, "Option {} is useless without options {} or {}", a, b1, b2), Self::Useless2(a, b1, b2) => write!(f, "Option {} is useless without options {} or {}", a, b1, b2),
TreeAllAll => write!(f, "Option --tree is useless given --all --all"), Self::TreeAllAll => write!(f, "Option --tree is useless given --all --all"),
FailedParse(ref e) => write!(f, "Failed to parse number: {}", e), Self::FailedParse(ref e) => write!(f, "Failed to parse number: {}", e),
FailedGlobPattern(ref e) => write!(f, "Failed to parse glob pattern: {}", e), Self::FailedGlobPattern(ref e) => write!(f, "Failed to parse glob pattern: {}", e),
} }
} }
} }
impl fmt::Display for ParseError { impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ParseError::*; match self {
Self::NeedsValue { flag, values: None } => write!(f, "Flag {} needs a value", flag),
match *self { Self::NeedsValue { flag, values: Some(cs) } => write!(f, "Flag {} needs a value ({})", flag, Choices(cs)),
NeedsValue { ref flag, values: None } => write!(f, "Flag {} needs a value", flag), Self::ForbiddenValue { flag } => write!(f, "Flag {} cannot take a value", flag),
NeedsValue { ref flag, values: Some(cs) } => write!(f, "Flag {} needs a value ({})", flag, Choices(cs)), Self::UnknownShortArgument { attempt } => write!(f, "Unknown argument -{}", *attempt as char),
ForbiddenValue { ref flag } => write!(f, "Flag {} cannot take a value", flag), Self::UnknownArgument { attempt } => write!(f, "Unknown argument --{}", attempt.to_string_lossy()),
UnknownShortArgument { ref attempt } => write!(f, "Unknown argument -{}", *attempt as char),
UnknownArgument { ref attempt } => write!(f, "Unknown argument --{}", attempt.to_string_lossy()),
} }
} }
} }
@ -119,12 +116,16 @@ impl Misfire {
/// went wrong. /// went wrong.
pub fn suggestion(&self) -> Option<&'static str> { pub fn suggestion(&self) -> Option<&'static str> {
// ls -lt and ls -ltr are common combinations // ls -lt and ls -ltr are common combinations
match *self { match self {
Self::BadArgument(ref time, ref r) if *time == &flags::TIME && r == "r" => Self::BadArgument(time, r) if *time == &flags::TIME && r == "r" => {
Some("To sort oldest files last, try \"--sort oldest\", or just \"-sold\""), Some("To sort oldest files last, try \"--sort oldest\", or just \"-sold\"")
Self::InvalidOptions(ParseError::NeedsValue { ref flag, .. }) if *flag == Flag::Short(b't') => }
Some("To sort newest files last, try \"--sort newest\", or just \"-snew\""), Self::InvalidOptions(ParseError::NeedsValue { ref flag, .. }) if *flag == Flag::Short(b't') => {
_ => None Some("To sort newest files last, try \"--sort newest\", or just \"-snew\"")
}
_ => {
None
}
} }
} }
} }

View File

@ -52,7 +52,7 @@ pub type Values = &'static [&'static str];
/// A **flag** is either of the two argument types, because they have to /// A **flag** is either of the two argument types, because they have to
/// be in the same array together. /// be in the same array together.
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
pub enum Flag { pub enum Flag {
Short(ShortArg), Short(ShortArg),
Long(LongArg), Long(LongArg),
@ -60,17 +60,17 @@ pub enum Flag {
impl Flag { impl Flag {
pub fn matches(&self, arg: &Arg) -> bool { pub fn matches(&self, arg: &Arg) -> bool {
match *self { match self {
Self::Short(short) => arg.short == Some(short), Self::Short(short) => arg.short == Some(*short),
Self::Long(long) => arg.long == long, Self::Long(long) => arg.long == *long,
} }
} }
} }
impl fmt::Display for Flag { impl fmt::Display for Flag {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match self {
Self::Short(short) => write!(f, "-{}", short as char), Self::Short(short) => write!(f, "-{}", *short as char),
Self::Long(long) => write!(f, "--{}", long), Self::Long(long) => write!(f, "--{}", long),
} }
} }
@ -108,7 +108,7 @@ pub enum TakesValue {
/// An **argument** can be matched by one of the users input strings. /// An **argument** can be matched by one of the users input strings.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Copy, Clone)]
pub struct Arg { pub struct Arg {
/// The short argument that matches it, if any. /// The short argument that matches it, if any.
@ -372,7 +372,7 @@ impl<'a> MatchedFlags<'a> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if all.len() < 2 { Ok(all.first().map(|t| &t.0)) } if all.len() < 2 { Ok(all.first().map(|t| &t.0)) }
else { Err(Misfire::Duplicate(all[0].0.clone(), all[1].0.clone())) } else { Err(Misfire::Duplicate(all[0].0, all[1].0)) }
} }
else { else {
let any = self.flags.iter().rev() let any = self.flags.iter().rev()
@ -406,7 +406,7 @@ impl<'a> MatchedFlags<'a> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if those.len() < 2 { Ok(those.first().cloned().map(|t| t.1.unwrap())) } if those.len() < 2 { Ok(those.first().cloned().map(|t| t.1.unwrap())) }
else { Err(Misfire::Duplicate(those[0].0.clone(), those[1].0.clone())) } else { Err(Misfire::Duplicate(those[0].0, those[1].0)) }
} }
else { else {
let found = self.flags.iter().rev() let found = self.flags.iter().rev()

View File

@ -8,7 +8,7 @@ use crate::options::flags;
use crate::options::parser::MatchedFlags; use crate::options::parser::MatchedFlags;
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Copy, Clone)]
pub struct VersionString; pub struct VersionString;
// There were options here once, but there arent anymore! // There were options here once, but there arent anymore!

View File

@ -143,7 +143,7 @@ impl Mode {
/// The width of the terminal requested by the user. /// The width of the terminal requested by the user.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Copy, Clone)]
enum TerminalWidth { enum TerminalWidth {
/// The user requested this specific number of columns. /// The user requested this specific number of columns.
@ -178,8 +178,8 @@ impl TerminalWidth {
} }
} }
fn width(&self) -> Option<usize> { fn width(self) -> Option<usize> {
match *self { match self {
Self::Set(width) | Self::Set(width) |
Self::Terminal(width) => Some(width), Self::Terminal(width) => Some(width),
Self::Unset => None, Self::Unset => None,

View File

@ -162,7 +162,7 @@ impl<'a> Render<'a> {
(None, _) => {/* Keep Git how it is */}, (None, _) => {/* Keep Git how it is */},
} }
let mut table = Table::new(&table, git, &self.colours); let mut table = Table::new(table, git, self.colours);
if self.opts.header { if self.opts.header {
let header = table.header_row(); let header = table.header_row();
@ -248,7 +248,7 @@ impl<'a> Render<'a> {
} }
} }
let table_row = table.as_ref().map(|t| t.row_for_file(&file, !xattrs.is_empty())); let table_row = table.as_ref().map(|t| t.row_for_file(file, !xattrs.is_empty()));
if !self.opts.xattr { if !self.opts.xattr {
xattrs.clear(); xattrs.clear();
@ -266,7 +266,7 @@ impl<'a> Render<'a> {
}; };
let icon = if self.opts.icons { let icon = if self.opts.icons {
Some(painted_icon(&file, &self.style)) Some(painted_icon(file, self.style))
} else { None }; } else { None };
let egg = Egg { table_row, xattrs, errors, dir, file, icon }; let egg = Egg { table_row, xattrs, errors, dir, file, icon };
@ -283,7 +283,7 @@ impl<'a> Render<'a> {
let mut files = Vec::new(); let mut files = Vec::new();
let mut errors = egg.errors; let mut errors = egg.errors;
if let (Some(ref mut t), Some(ref row)) = (table.as_mut(), egg.table_row.as_ref()) { if let (Some(ref mut t), Some(row)) = (table.as_mut(), egg.table_row.as_ref()) {
t.add_widths(row); t.add_widths(row);
} }
@ -291,7 +291,7 @@ impl<'a> Render<'a> {
if let Some(icon) = egg.icon { if let Some(icon) = egg.icon {
name_cell.push(ANSIGenericString::from(icon), 2) name_cell.push(ANSIGenericString::from(icon), 2)
} }
name_cell.append(self.style.for_file(&egg.file, self.colours) name_cell.append(self.style.for_file(egg.file, self.colours)
.with_link_paths() .with_link_paths()
.paint() .paint()
.promote()); .promote());

View File

@ -133,8 +133,8 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
} }
if let (LinkStyle::FullLinkPaths, Some(target)) = (self.link_style, self.target.as_ref()) { if let (LinkStyle::FullLinkPaths, Some(target)) = (self.link_style, self.target.as_ref()) {
match *target { match target {
FileTarget::Ok(ref target) => { FileTarget::Ok(target) => {
bits.push(Style::default().paint(" ")); bits.push(Style::default().paint(" "));
bits.push(self.colours.normal_arrow().paint("->")); bits.push(self.colours.normal_arrow().paint("->"));
bits.push(Style::default().paint(" ")); bits.push(Style::default().paint(" "));
@ -159,7 +159,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
} }
}, },
FileTarget::Broken(ref broken_path) => { FileTarget::Broken(broken_path) => {
bits.push(Style::default().paint(" ")); bits.push(Style::default().paint(" "));
bits.push(self.colours.broken_symlink().paint("->")); bits.push(self.colours.broken_symlink().paint("->"));
bits.push(Style::default().paint(" ")); bits.push(Style::default().paint(" "));

View File

@ -41,7 +41,7 @@ impl<'a> Render<'a> {
grid.reserve(self.files.len()); grid.reserve(self.files.len());
for file in &self.files { for file in &self.files {
let icon = if self.opts.icons { Some(painted_icon(&file, &self.style)) } else { None }; let icon = if self.opts.icons { Some(painted_icon(file, self.style)) } else { None };
let filename = self.style.for_file(file, self.colours).paint(); let filename = self.style.for_file(file, self.colours).paint();
let width = if self.opts.icons { let width = if self.opts.icons {
DisplayWidth::from(2) + filename.width() DisplayWidth::from(2) + filename.width()
@ -64,7 +64,7 @@ impl<'a> Render<'a> {
// displays full link paths. // displays full link paths.
for file in &self.files { for file in &self.files {
if self.opts.icons { if self.opts.icons {
write!(w, "{}", painted_icon(&file, &self.style))?; write!(w, "{}", painted_icon(file, self.style))?;
} }
let name_cell = self.style.for_file(file, self.colours).paint(); let name_cell = self.style.for_file(file, self.colours).paint();
writeln!(w, "{}", name_cell.strings())?; writeln!(w, "{}", name_cell.strings())?;

View File

@ -112,7 +112,7 @@ impl<'a> Render<'a> {
style: self.style, style: self.style,
opts: self.details, opts: self.details,
recurse: None, recurse: None,
filter: &self.filter, filter: self.filter,
git_ignoring: self.git_ignoring, git_ignoring: self.git_ignoring,
} }
} }
@ -144,7 +144,7 @@ impl<'a> Render<'a> {
.map(|file| { .map(|file| {
if self.details.icons { if self.details.icons {
let mut icon_cell = TextCell::default(); let mut icon_cell = TextCell::default();
icon_cell.push(ANSIGenericString::from(painted_icon(&file, &self.style)), 2); icon_cell.push(ANSIGenericString::from(painted_icon(file, self.style)), 2);
let file_cell = self.style.for_file(file, self.colours).paint().promote(); let file_cell = self.style.for_file(file, self.colours).paint().promote();
icon_cell.append(file_cell); icon_cell.append(file_cell);
icon_cell icon_cell

View File

@ -8,6 +8,7 @@ pub trait FileIcon {
fn icon_file(&self, file: &File) -> Option<char>; fn icon_file(&self, file: &File) -> Option<char>;
} }
#[derive(Copy, Clone)]
pub enum Icons { pub enum Icons {
Audio, Audio,
Image, Image,
@ -15,8 +16,8 @@ pub enum Icons {
} }
impl Icons { impl Icons {
pub fn value(&self) -> char { pub fn value(self) -> char {
match *self { match self {
Self::Audio => '\u{f001}', Self::Audio => '\u{f001}',
Self::Image => '\u{f1c5}', Self::Image => '\u{f1c5}',
Self::Video => '\u{f03d}', Self::Video => '\u{f03d}',
@ -25,9 +26,9 @@ impl Icons {
} }
pub fn painted_icon(file: &File, style: &FileStyle) -> String { pub fn painted_icon(file: &File, style: &FileStyle) -> String {
let file_icon = icon(&file).to_string(); let file_icon = icon(file).to_string();
let painted = style.exts let painted = style.exts
.colour_file(&file) .colour_file(file)
.map_or(file_icon.to_string(), |c| { .map_or(file_icon.to_string(), |c| {
// Remove underline from icon // Remove underline from icon
if c.is_underline { if c.is_underline {

View File

@ -28,7 +28,7 @@ impl<'a> Render<'a> {
if self.opts.icons { if self.opts.icons {
// Create a TextCell for the icon then append the text to it // Create a TextCell for the icon then append the text to it
let mut cell = TextCell::default(); let mut cell = TextCell::default();
let icon = painted_icon(&file, self.style); let icon = painted_icon(file, self.style);
cell.push(ANSIGenericString::from(icon), 2); cell.push(ANSIGenericString::from(icon), 2);
cell.append(name_cell.promote()); cell.append(name_cell.promote());
writeln!(w, "{}", ANSIStrings(&cell))?; writeln!(w, "{}", ANSIStrings(&cell))?;

View File

@ -6,8 +6,8 @@ use crate::fs::fields as f;
impl f::Blocks { impl f::Blocks {
pub fn render<C: Colours>(&self, colours: &C) -> TextCell { pub fn render<C: Colours>(&self, colours: &C) -> TextCell {
match *self { match self {
Self::Some(ref blk) => TextCell::paint(colours.block_count(), blk.to_string()), Self::Some(blk) => TextCell::paint(colours.block_count(), blk.to_string()),
Self::None => TextCell::blank(colours.no_blocks()), Self::None => TextCell::blank(colours.no_blocks()),
} }
} }

View File

@ -4,8 +4,8 @@ use crate::fs::fields as f;
impl f::Type { impl f::Type {
pub fn render<C: Colours>(&self, colours: &C) -> ANSIString<'static> { pub fn render<C: Colours>(self, colours: &C) -> ANSIString<'static> {
match *self { match self {
Self::File => colours.normal().paint("."), Self::File => colours.normal().paint("."),
Self::Directory => colours.directory().paint("d"), Self::Directory => colours.directory().paint("d"),
Self::Pipe => colours.pipe().paint("|"), Self::Pipe => colours.pipe().paint("|"),

View File

@ -5,7 +5,7 @@ use crate::fs::fields as f;
impl f::Git { impl f::Git {
pub fn render(&self, colours: &dyn Colours) -> TextCell { pub fn render(self, colours: &dyn Colours) -> TextCell {
TextCell { TextCell {
width: DisplayWidth::from(2), width: DisplayWidth::from(2),
contents: vec![ contents: vec![
@ -18,8 +18,8 @@ impl f::Git {
impl f::GitStatus { impl f::GitStatus {
fn render(&self, colours: &dyn Colours) -> ANSIString<'static> { fn render(self, colours: &dyn Colours) -> ANSIString<'static> {
match *self { match self {
Self::NotModified => colours.not_modified().paint("-"), Self::NotModified => colours.not_modified().paint("-"),
Self::New => colours.new().paint("N"), Self::New => colours.new().paint("N"),
Self::Modified => colours.modified().paint("M"), Self::Modified => colours.modified().paint("M"),

View File

@ -6,7 +6,7 @@ use crate::output::cell::TextCell;
impl f::Group { impl f::Group {
pub fn render<C: Colours, U: Users+Groups>(&self, colours: &C, users: &U) -> TextCell { pub fn render<C: Colours, U: Users+Groups>(self, colours: &C, users: &U) -> TextCell {
use users::os::unix::GroupExt; use users::os::unix::GroupExt;
let mut style = colours.not_yours(); let mut style = colours.not_yours();

View File

@ -5,7 +5,7 @@ use crate::fs::fields as f;
impl f::Inode { impl f::Inode {
pub fn render(&self, style: Style) -> TextCell { pub fn render(self, style: Style) -> TextCell {
TextCell::paint(style, self.0.to_string()) TextCell::paint(style, self.0.to_string())
} }
} }

View File

@ -8,10 +8,10 @@ use crate::output::table::SizeFormat;
impl f::Size { impl f::Size {
pub fn render<C: Colours>(&self, colours: &C, size_format: SizeFormat, numerics: &NumericLocale) -> TextCell { pub fn render<C: Colours>(self, colours: &C, size_format: SizeFormat, numerics: &NumericLocale) -> TextCell {
use number_prefix::NumberPrefix; use number_prefix::NumberPrefix;
let size = match *self { let size = match self {
Self::Some(s) => s, Self::Some(s) => s,
Self::None => return TextCell::blank(colours.no_size()), Self::None => return TextCell::blank(colours.no_size()),
Self::DeviceIDs(ref ids) => return ids.render(colours), Self::DeviceIDs(ref ids) => return ids.render(colours),
@ -57,7 +57,7 @@ impl f::Size {
impl f::DeviceIDs { impl f::DeviceIDs {
fn render<C: Colours>(&self, colours: &C) -> TextCell { fn render<C: Colours>(self, colours: &C) -> TextCell {
let major = self.major.to_string(); let major = self.major.to_string();
let minor = self.minor.to_string(); let minor = self.minor.to_string();

View File

@ -7,7 +7,7 @@ use crate::output::cell::TextCell;
impl f::User { impl f::User {
pub fn render<C: Colours, U: Users>(&self, colours: &C, users: &U) -> TextCell { pub fn render<C: Colours, U: Users>(self, colours: &C, users: &U) -> TextCell {
let user_name = match users.get_user_by_uid(self.0) { let user_name = match users.get_user_by_uid(self.0) {
Some(user) => user.name().to_string_lossy().into(), Some(user) => user.name().to_string_lossy().into(),
None => self.0.to_string(), None => self.0.to_string(),

View File

@ -36,7 +36,7 @@ impl fmt::Debug for Options {
} }
/// Extra columns to display in the table. /// Extra columns to display in the table.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Copy, Clone)]
pub struct Columns { pub struct Columns {
/// At least one of these timestamps will be shown. /// At least one of these timestamps will be shown.
@ -118,7 +118,7 @@ impl Columns {
/// A table contains these. /// A table contains these.
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
pub enum Column { pub enum Column {
Permissions, Permissions,
FileSize, FileSize,
@ -142,8 +142,8 @@ pub enum Alignment {
impl Column { impl Column {
/// Get the alignment this column should use. /// Get the alignment this column should use.
pub fn alignment(&self) -> Alignment { pub fn alignment(self) -> Alignment {
match *self { match self {
Self::FileSize | Self::FileSize |
Self::HardLinks | Self::HardLinks |
Self::Inode | Self::Inode |
@ -155,8 +155,8 @@ impl Column {
/// Get the text that should be printed at the top, when the user elects /// Get the text that should be printed at the top, when the user elects
/// to have a header row printed. /// to have a header row printed.
pub fn header(&self) -> &'static str { pub fn header(self) -> &'static str {
match *self { match self {
Self::Permissions => "Permissions", Self::Permissions => "Permissions",
Self::FileSize => "Size", Self::FileSize => "Size",
Self::Timestamp(t) => t.header(), Self::Timestamp(t) => t.header(),
@ -342,7 +342,7 @@ impl<'a, 'f> Table<'a> {
pub fn row_for_file(&self, file: &File, xattrs: bool) -> Row { pub fn row_for_file(&self, file: &File, xattrs: bool) -> Row {
let cells = self.columns.iter() let cells = self.columns.iter()
.map(|c| self.display(file, c, xattrs)) .map(|c| self.display(file, *c, xattrs))
.collect(); .collect();
Row { cells } Row { cells }
@ -366,10 +366,10 @@ impl<'a, 'f> Table<'a> {
} }
} }
fn display(&self, file: &File, column: &Column, xattrs: bool) -> TextCell { fn display(&self, file: &File, column: Column, xattrs: bool) -> TextCell {
use crate::output::table::TimeType::*; use crate::output::table::TimeType::*;
match *column { match column {
Column::Permissions => self.permissions_plus(file, xattrs).render(self.colours), Column::Permissions => self.permissions_plus(file, xattrs).render(self.colours),
Column::FileSize => file.size().render(self.colours, self.size_format, &self.env.numeric), Column::FileSize => file.size().render(self.colours, self.size_format, &self.env.numeric),
Column::HardLinks => file.links().render(self.colours, &self.env.numeric), Column::HardLinks => file.links().render(self.colours, &self.env.numeric),
@ -380,10 +380,10 @@ impl<'a, 'f> Table<'a> {
Column::GitStatus => self.git_status(file).render(self.colours), Column::GitStatus => self.git_status(file).render(self.colours),
Column::Octal => self.octal_permissions(file).render(self.colours.octal), Column::Octal => self.octal_permissions(file).render(self.colours.octal),
Column::Timestamp(Modified) => file.modified_time().render(self.colours.date, &self.env.tz, &self.time_format), Column::Timestamp(Modified) => file.modified_time().render(self.colours.date, &self.env.tz, self.time_format),
Column::Timestamp(Changed) => file.changed_time() .render(self.colours.date, &self.env.tz, &self.time_format), Column::Timestamp(Changed) => file.changed_time() .render(self.colours.date, &self.env.tz, self.time_format),
Column::Timestamp(Created) => file.created_time() .render(self.colours.date, &self.env.tz, &self.time_format), Column::Timestamp(Created) => file.created_time() .render(self.colours.date, &self.env.tz, self.time_format),
Column::Timestamp(Accessed) => file.accessed_time().render(self.colours.date, &self.env.tz, &self.time_format), Column::Timestamp(Accessed) => file.accessed_time().render(self.colours.date, &self.env.tz, self.time_format),
} }
} }

View File

@ -51,18 +51,18 @@ pub enum TimeFormat {
impl TimeFormat { impl TimeFormat {
pub fn format_local(&self, time: SystemTime) -> String { pub fn format_local(&self, time: SystemTime) -> String {
match *self { match self {
Self::DefaultFormat(ref fmt) => fmt.format_local(time), Self::DefaultFormat(fmt) => fmt.format_local(time),
Self::ISOFormat(ref iso) => iso.format_local(time), Self::ISOFormat(iso) => iso.format_local(time),
Self::LongISO => long_local(time), Self::LongISO => long_local(time),
Self::FullISO => full_local(time), Self::FullISO => full_local(time),
} }
} }
pub fn format_zoned(&self, time: SystemTime, zone: &TimeZone) -> String { pub fn format_zoned(&self, time: SystemTime, zone: &TimeZone) -> String {
match *self { match self {
Self::DefaultFormat(ref fmt) => fmt.format_zoned(time, zone), Self::DefaultFormat(fmt) => fmt.format_zoned(time, zone),
Self::ISOFormat(ref iso) => iso.format_zoned(time, zone), Self::ISOFormat(iso) => iso.format_zoned(time, zone),
Self::LongISO => long_zoned(time, zone), Self::LongISO => long_zoned(time, zone),
Self::FullISO => full_zoned(time, zone), Self::FullISO => full_zoned(time, zone),
} }
@ -241,7 +241,7 @@ fn full_zoned(time: SystemTime, zone: &TimeZone) -> String {
#[derive(Debug, Clone)] #[derive(Debug, Copy, Clone)]
pub struct ISOFormat { pub struct ISOFormat {
/// The year of the current time. This gets used to determine which date /// The year of the current time. This gets used to determine which date
@ -257,12 +257,12 @@ impl ISOFormat {
} }
impl ISOFormat { impl ISOFormat {
fn is_recent(&self, date: LocalDateTime) -> bool { fn is_recent(self, date: LocalDateTime) -> bool {
date.year() == self.current_year date.year() == self.current_year
} }
#[allow(trivial_numeric_casts)] #[allow(trivial_numeric_casts)]
fn format_local(&self, time: SystemTime) -> String { fn format_local(self, time: SystemTime) -> String {
let date = LocalDateTime::at(systemtime_epoch(time)); let date = LocalDateTime::at(systemtime_epoch(time));
if self.is_recent(date) { if self.is_recent(date) {
@ -277,7 +277,7 @@ impl ISOFormat {
} }
#[allow(trivial_numeric_casts)] #[allow(trivial_numeric_casts)]
fn format_zoned(&self, time: SystemTime, zone: &TimeZone) -> String { fn format_zoned(self, time: SystemTime, zone: &TimeZone) -> String {
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time))); let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
if self.is_recent(date) { if self.is_recent(date) {

View File

@ -39,7 +39,7 @@
//! each directory) //! each directory)
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
pub enum TreePart { pub enum TreePart {
/// Rightmost column, *not* the last in the directory. /// Rightmost column, *not* the last in the directory.
@ -59,8 +59,8 @@ impl TreePart {
/// Turn this tree part into ASCII-licious box drawing characters! /// Turn this tree part into ASCII-licious box drawing characters!
/// (Warning: not actually ASCII) /// (Warning: not actually ASCII)
pub fn ascii_art(&self) -> &'static str { pub fn ascii_art(self) -> &'static str {
match *self { match self {
Self::Edge => "├──", Self::Edge => "├──",
Self::Line => "", Self::Line => "",
Self::Corner => "└──", Self::Corner => "└──",