diff --git a/Cargo.lock b/Cargo.lock index 6896c43..8fa1906 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,7 +99,7 @@ dependencies = [ "term_grid 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "users 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "users 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "zoneinfo_compiled 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -404,7 +404,7 @@ dependencies = [ [[package]] name = "users" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -522,7 +522,7 @@ dependencies = [ "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" -"checksum users 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a098d836637f965bbe0df8f744088318c43b685ffd46b676ed21036b7c94bae6" +"checksum users 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "caa2760fcc10a6ae2c2a35d41c5d69827e4663f0d3889ecfb4d60b343f4139df" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/src/bin/main.rs b/src/bin/main.rs index ffb40a8..7b28d30 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -19,7 +19,7 @@ fn main() { match e.kind() { ErrorKind::BrokenPipe => exit(exits::SUCCESS), _ => { - writeln!(stderr(), "{}", e).unwrap(); + eprintln!("{}", e); exit(exits::RUNTIME_ERROR); }, }; @@ -39,7 +39,7 @@ fn main() { }, Err(ref e) => { - writeln!(stdout(), "{}", e).unwrap(); + println!("{}", e); exit(exits::SUCCESS); }, }; diff --git a/src/exa.rs b/src/exa.rs index 26a0ae0..851e521 100644 --- a/src/exa.rs +++ b/src/exa.rs @@ -83,7 +83,7 @@ impl Vars for LiveVars { /// listed before they’re actually listed, if the options demand it. fn git_options(options: &Options, args: &[&OsStr]) -> Option { if options.should_scan_for_git() { - Some(args.iter().map(|os| PathBuf::from(os)).collect()) + Some(args.iter().map(PathBuf::from).collect()) } else { None @@ -166,7 +166,7 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> { first = false; } else { - write!(self.writer, "\n")?; + writeln!(self.writer)?; } if !is_only_dir { diff --git a/src/fs/dir.rs b/src/fs/dir.rs index 9414c59..74480c5 100644 --- a/src/fs/dir.rs +++ b/src/fs/dir.rs @@ -52,7 +52,7 @@ impl Dir { dir: self, dotfiles: dots.shows_dotfiles(), dots: dots.dots(), - ignore: ignore, + ignore, } } @@ -103,7 +103,7 @@ impl<'dir, 'ig> Files<'dir, 'ig> { loop { if let Some(path) = self.inner.next() { let filename = File::filename(path); - if !self.dotfiles && filename.starts_with(".") { continue } + if !self.dotfiles && filename.starts_with('.') { continue } if let Some(i) = self.ignore { if i.is_ignored(path) { continue } @@ -180,8 +180,8 @@ impl Default for DotFilter { impl DotFilter { /// Whether this filter should show dotfiles in a listing. - fn shows_dotfiles(&self) -> bool { - match *self { + fn shows_dotfiles(self) -> bool { + match self { DotFilter::JustFiles => false, DotFilter::Dotfiles => true, DotFilter::DotfilesAndDots => true, @@ -189,8 +189,8 @@ impl DotFilter { } /// Whether this filter should add dot directories to a listing. - fn dots(&self) -> Dots { - match *self { + fn dots(self) -> Dots { + match self { DotFilter::JustFiles => Dots::FilesNext, DotFilter::Dotfiles => Dots::FilesNext, DotFilter::DotfilesAndDots => Dots::DotNext, diff --git a/src/fs/feature/git.rs b/src/fs/feature/git.rs index 9cc1b7f..d0d5bce 100644 --- a/src/fs/feature/git.rs +++ b/src/fs/feature/git.rs @@ -134,7 +134,7 @@ impl GitRepo { debug!("Querying Git repo {:?} for the first time", &self.workdir); let repo = replace(&mut *contents, Processing).inner_repo(); - let statuses = repo_to_statuses(repo, &self.workdir); + let statuses = repo_to_statuses(&repo, &self.workdir); let result = statuses.status(index, prefix_lookup); let _processing = replace(&mut *contents, After { statuses }); result @@ -194,7 +194,7 @@ impl GitContents { /// mapping of files to their Git status. /// We will have already used the working directory at this point, so it gets /// passed in rather than deriving it from the `Repository` again. -fn repo_to_statuses(repo: git2::Repository, workdir: &Path) -> Git { +fn repo_to_statuses(repo: &git2::Repository, workdir: &Path) -> Git { let mut statuses = Vec::new(); info!("Getting Git statuses for repo with workdir {:?}", workdir); diff --git a/src/fs/feature/ignore.rs b/src/fs/feature/ignore.rs index 40eb71c..cec1a9b 100644 --- a/src/fs/feature/ignore.rs +++ b/src/fs/feature/ignore.rs @@ -72,7 +72,7 @@ fn file_lines_to_patterns<'a, I>(iter: I) -> IgnorePatterns where I: Iterator { let iter = iter.filter(|el| !el.is_empty()); - let iter = iter.filter(|el| !el.starts_with("#")); + let iter = iter.filter(|el| !el.starts_with('#')); // TODO: Figure out if this should trim whitespace or not diff --git a/src/fs/feature/xattr.rs b/src/fs/feature/xattr.rs index 0e33455..93bab1d 100644 --- a/src/fs/feature/xattr.rs +++ b/src/fs/feature/xattr.rs @@ -203,7 +203,7 @@ mod lister { impl Lister { pub fn new(follow_symlinks: FollowSymlinks) -> Lister { - Lister { follow_symlinks: follow_symlinks } + Lister { follow_symlinks } } pub fn translate_attribute_name(&self, input: &[u8]) -> String { diff --git a/src/fs/file.rs b/src/fs/file.rs index f6eeb1e..4196419 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -95,13 +95,7 @@ impl<'dir> File<'dir> { /// against a pre-compiled list of extensions which are known to only exist /// within ASCII, so it’s alright. fn ext(path: &Path) -> Option { - #[allow(unused)] - use std::ascii::AsciiExt; - - let name = match path.file_name() { - Some(f) => f.to_string_lossy().to_string(), - None => return None, - }; + let name = path.file_name().map(|f| f.to_string_lossy().to_string())?; name.rfind('.').map(|p| name[p+1..].to_ascii_lowercase()) } @@ -225,7 +219,7 @@ impl<'dir> File<'dir> { Ok(metadata) => { let ext = File::ext(&path); let name = File::filename(&path); - FileTarget::Ok(File { parent_dir: None, path, ext, metadata, name }) + FileTarget::Ok(Box::new(File { parent_dir: None, path, ext, metadata, name })) } Err(e) => { error!("Error following link {:?}: {:#?}", &path, e); @@ -245,7 +239,7 @@ impl<'dir> File<'dir> { let count = self.metadata.nlink(); f::Links { - count: count, + count, multiple: self.is_file() && count > 1, } } @@ -410,7 +404,7 @@ impl<'a> AsRef> for File<'a> { pub enum FileTarget<'dir> { /// The symlink pointed at a file that exists. - Ok(File<'dir>), + Ok(Box>), /// The symlink pointed at a file that does not exist. Holds the path /// where the file would be, if it existed. diff --git a/src/fs/filter.rs b/src/fs/filter.rs index 768efe8..3b7cd4d 100644 --- a/src/fs/filter.rs +++ b/src/fs/filter.rs @@ -234,10 +234,10 @@ impl SortField { /// into groups between letters and numbers, and then sorts those blocks /// together, so `file10` will sort after `file9`, instead of before it /// because of the `1`. - pub fn compare_files(&self, a: &File, b: &File) -> Ordering { + pub fn compare_files(self, a: &File, b: &File) -> Ordering { use self::SortCase::{ABCabc, AaBbCc}; - match *self { + match self { SortField::Unsorted => Ordering::Equal, SortField::Name(ABCabc) => natord::compare(&a.name, &b.name), @@ -277,7 +277,7 @@ impl SortField { } fn strip_dot(n: &str) -> &str { - if n.starts_with(".") { + if n.starts_with('.') { &n[1..] } else { n diff --git a/src/options/help.rs b/src/options/help.rs index 388f062..fb65294 100644 --- a/src/options/help.rs +++ b/src/options/help.rs @@ -96,7 +96,7 @@ impl fmt::Display for HelpString { /// Format this help options into an actual string of help /// text to be displayed to the user. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "Usage:\n exa [options] [files...]\n")?; + writeln!(f, "Usage:\n exa [options] [files...]")?; if !self.only_long { write!(f, "{}", OPTIONS)?; diff --git a/src/options/misfire.rs b/src/options/misfire.rs index 5cc0ba3..da9174a 100644 --- a/src/options/misfire.rs +++ b/src/options/misfire.rs @@ -117,19 +117,13 @@ impl Misfire { /// went wrong. pub fn suggestion(&self) -> Option<&'static str> { // ‘ls -lt’ and ‘ls -ltr’ are common combinations - if let Misfire::BadArgument(ref time, ref r) = *self { - if *time == &flags::TIME && r == "r" { - return Some("To sort oldest files last, try \"--sort oldest\", or just \"-sold\""); - } + match *self { + Misfire::BadArgument(ref time, ref r) if *time == &flags::TIME && r == "r" => + Some("To sort oldest files last, try \"--sort oldest\", or just \"-sold\""), + Misfire::InvalidOptions(ParseError::NeedsValue { ref flag, .. }) if *flag == Flag::Short(b't') => + Some("To sort newest files last, try \"--sort newest\", or just \"-snew\""), + _ => None } - - if let Misfire::InvalidOptions(ParseError::NeedsValue { ref flag, values: _ }) = *self { - if *flag == Flag::Short(b't') { - return Some("To sort newest files last, try \"--sort newest\", or just \"-snew\""); - } - } - - None } } diff --git a/src/options/parser.rs b/src/options/parser.rs index f84f15e..bba731e 100644 --- a/src/options/parser.rs +++ b/src/options/parser.rs @@ -452,7 +452,7 @@ fn split_on_equals(input: &OsStr) -> Option<(&OsStr, &OsStr)> { let (before, after) = input.as_bytes().split_at(index); // The after string contains the = that we need to remove. - if before.len() >= 1 && after.len() >= 2 { + if !before.is_empty() && after.len() >= 2 { return Some((OsStr::from_bytes(before), OsStr::from_bytes(&after[1..]))) } diff --git a/src/options/view.rs b/src/options/view.rs index 563e8fc..d627acd 100644 --- a/src/options/view.rs +++ b/src/options/view.rs @@ -72,23 +72,20 @@ impl Mode { Ok(Mode::Grid(grid)) } } + // If the terminal width couldn’t be matched for some reason, such + // as the program’s stdout being connected to a file, then + // fallback to the lines view. + else if matches.has(&flags::TREE)? { + let details = details::Options { + table: None, + header: false, + xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?, + }; + + Ok(Mode::Details(details)) + } else { - // If the terminal width couldn’t be matched for some reason, such - // as the program’s stdout being connected to a file, then - // fallback to the lines view. - - if matches.has(&flags::TREE)? { - let details = details::Options { - table: None, - header: false, - xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?, - }; - - Ok(Mode::Details(details)) - } - else { - Ok(Mode::Lines) - } + Ok(Mode::Lines) } }; @@ -260,16 +257,16 @@ impl TimeFormat { use options::vars; match vars.get(vars::TIME_STYLE) { Some(ref t) if !t.is_empty() => t.clone(), - _ => return Ok(TimeFormat::DefaultFormat(DefaultFormat::new())) + _ => return Ok(TimeFormat::DefaultFormat(DefaultFormat::default())) } }, }; if &word == "default" { - Ok(TimeFormat::DefaultFormat(DefaultFormat::new())) + Ok(TimeFormat::DefaultFormat(DefaultFormat::default())) } else if &word == "iso" { - Ok(TimeFormat::ISOFormat(ISOFormat::new())) + Ok(TimeFormat::ISOFormat(ISOFormat::default())) } else if &word == "long-iso" { Ok(TimeFormat::LongISO) diff --git a/src/output/cell.rs b/src/output/cell.rs index ef06b6e..3833606 100644 --- a/src/output/cell.rs +++ b/src/output/cell.rs @@ -44,7 +44,7 @@ impl TextCell { TextCell { contents: vec![ style.paint(text) ].into(), - width: width, + width, } } @@ -56,7 +56,7 @@ impl TextCell { TextCell { contents: vec![ style.paint(text) ].into(), - width: width, + width, } } diff --git a/src/output/details.rs b/src/output/details.rs index 3a81a76..557f784 100644 --- a/src/output/details.rs +++ b/src/output/details.rs @@ -184,7 +184,7 @@ impl<'a> Render<'a> { /// Adds files to the table, possibly recursively. This is easily /// parallelisable, and uses a pool of threads. - fn add_files_to_table<'dir, 'ig>(&self, pool: &mut Pool, table: &mut Option>, rows: &mut Vec, src: &Vec>, ignore: Option<&'ig IgnoreCache>, depth: TreeDepth) { + fn add_files_to_table<'dir, 'ig>(&self, pool: &mut Pool, table: &mut Option>, rows: &mut Vec, src: &[File<'dir>], ignore: Option<&'ig IgnoreCache>, depth: TreeDepth) { use std::sync::{Arc, Mutex}; use fs::feature::xattr; @@ -294,7 +294,7 @@ impl<'a> Render<'a> { if !files.is_empty() { for xattr in egg.xattrs { - rows.push(self.render_xattr(xattr, TreeParams::new(depth.deeper(), false))); + rows.push(self.render_xattr(&xattr, TreeParams::new(depth.deeper(), false))); } for (error, path) in errors { @@ -308,7 +308,7 @@ impl<'a> Render<'a> { let count = egg.xattrs.len(); for (index, xattr) in egg.xattrs.into_iter().enumerate() { - rows.push(self.render_xattr(xattr, TreeParams::new(depth.deeper(), errors.is_empty() && index == count - 1))); + rows.push(self.render_xattr(&xattr, TreeParams::new(depth.deeper(), errors.is_empty() && index == count - 1))); } let count = errors.len(); @@ -340,7 +340,7 @@ impl<'a> Render<'a> { Row { cells: None, name, tree } } - fn render_xattr(&self, xattr: Attribute, tree: TreeParams) -> Row { + fn render_xattr(&self, xattr: &Attribute, tree: TreeParams) -> Row { let name = TextCell::paint(self.colours.perms.attribute, format!("{} (len {})", xattr.name, xattr.size)); Row { cells: None, name, tree } } @@ -353,7 +353,7 @@ impl<'a> Render<'a> { TableIter { tree_trunk: TreeTrunk::default(), total_width: table.widths().total(), - table: table, + table, inner: rows.into_iter(), tree_style: self.colours.punctuation, } diff --git a/src/output/grid.rs b/src/output/grid.rs index 00ff14a..c07e7aa 100644 --- a/src/output/grid.rs +++ b/src/output/grid.rs @@ -37,7 +37,7 @@ impl<'a> Render<'a> { grid.reserve(self.files.len()); - for file in self.files.iter() { + for file in &self.files { let filename = self.style.for_file(file, self.colours).paint(); let width = filename.width(); @@ -54,7 +54,7 @@ impl<'a> Render<'a> { // File names too long for a grid - drop down to just listing them! // This isn’t *quite* the same as the lines view, which also // displays full link paths. - for file in self.files.iter() { + for file in &self.files { let name_cell = self.style.for_file(file, self.colours).paint(); writeln!(w, "{}", name_cell.strings())?; } diff --git a/src/output/grid_details.rs b/src/output/grid_details.rs index 2327c43..408dc9e 100644 --- a/src/output/grid_details.rs +++ b/src/output/grid_details.rs @@ -87,7 +87,7 @@ impl<'a> Render<'a> { /// *n* files into each column’s table, not all of them. pub fn details(&self) -> DetailsRender<'a> { DetailsRender { - dir: self.dir.clone(), + dir: self.dir, files: Vec::new(), colours: self.colours, style: self.style, @@ -170,7 +170,7 @@ impl<'a> Render<'a> { None } - fn make_table<'t>(&'a self, options: &'a TableOptions, mut git: Option<&'a GitCache>, drender: &DetailsRender) -> (Table<'a>, Vec) { + fn make_table(&'a self, options: &'a TableOptions, mut git: Option<&'a GitCache>, drender: &DetailsRender) -> (Table<'a>, Vec) { match (git, self.dir) { (Some(g), Some(d)) => if !g.has_anything_for(&d.path) { git = None }, (Some(g), None) => if !self.files.iter().any(|f| g.has_anything_for(&f.path)) { git = None }, @@ -226,7 +226,7 @@ impl<'a> Render<'a> { else { grid::Direction::TopToBottom }; let mut grid = grid::Grid::new(grid::GridOptions { - direction: direction, + direction, filling: grid::Filling::Spaces(4), }); diff --git a/src/output/render/size.rs b/src/output/render/size.rs index ea80f98..25b2007 100644 --- a/src/output/render/size.rs +++ b/src/output/render/size.rs @@ -41,7 +41,7 @@ impl f::Size { let width = DisplayWidth::from(number.len() + symbol.len()); TextCell { - width: width, + width, contents: vec![ colours.size(size).paint(number), colours.unit().paint(symbol), diff --git a/src/output/table.rs b/src/output/table.rs index fd22a8b..2f3e6d7 100644 --- a/src/output/table.rs +++ b/src/output/table.rs @@ -189,8 +189,8 @@ pub enum TimeType { impl TimeType { /// Returns the text to use for a column’s heading in the columns output. - pub fn header(&self) -> &'static str { - match *self { + pub fn header(self) -> &'static str { + match self { TimeType::Accessed => "Date Accessed", TimeType::Modified => "Date Modified", TimeType::Created => "Date Created", @@ -324,7 +324,7 @@ impl<'a, 'f> Table<'a> { f::PermissionsPlus { file_type: file.type_char(), permissions: file.permissions(), - xattrs: xattrs, + xattrs, } } @@ -379,7 +379,7 @@ pub struct TableWidths(Vec); impl Deref for TableWidths { type Target = [usize]; - fn deref<'a>(&'a self) -> &'a Self::Target { + fn deref(&self) -> &Self::Target { &self.0 } } diff --git a/src/output/time.rs b/src/output/time.rs index 4439e97..a635e0d 100644 --- a/src/output/time.rs +++ b/src/output/time.rs @@ -88,8 +88,8 @@ pub struct DefaultFormat { pub date_and_year: DateFormat<'static>, } -impl DefaultFormat { - pub fn new() -> DefaultFormat { +impl Default for DefaultFormat { + fn default() -> DefaultFormat { use unicode_width::UnicodeWidthStr; let locale = locale::Time::load_user_locale() @@ -120,7 +120,9 @@ impl DefaultFormat { DefaultFormat { current_year, locale, date_and_time, date_and_year } } +} +impl DefaultFormat { fn is_recent(&self, date: LocalDateTime) -> bool { date.year() == self.current_year } @@ -199,12 +201,14 @@ pub struct ISOFormat { pub current_year: i64, } -impl ISOFormat { - pub fn new() -> Self { +impl Default for ISOFormat { + fn default() -> ISOFormat { let current_year = LocalDateTime::now().year(); ISOFormat { current_year } } +} +impl ISOFormat { fn is_recent(&self, date: LocalDateTime) -> bool { date.year() == self.current_year } diff --git a/src/style/colours.rs b/src/style/colours.rs index 59b6d19..d218635 100644 --- a/src/style/colours.rs +++ b/src/style/colours.rs @@ -111,7 +111,7 @@ impl Colours { pub fn colourful(scale: bool) -> Colours { Colours { colourful: true, - scale: scale, + scale, filekinds: FileKinds { normal: Style::default(), diff --git a/src/style/lsc.rs b/src/style/lsc.rs index b3abba3..9bd8478 100644 --- a/src/style/lsc.rs +++ b/src/style/lsc.rs @@ -26,8 +26,8 @@ pub struct LSColors<'var>(pub &'var str); impl<'var> LSColors<'var> { pub fn each_pair(&mut self, mut callback: C) where C: FnMut(Pair<'var>) -> () { - for next in self.0.split(":") { - let bits = next.split("=") + for next in self.0.split(':') { + let bits = next.split('=') .take(3) .collect::>(); @@ -48,7 +48,7 @@ fn parse_into_high_colour<'a, I>(iter: &mut Peekable) -> Option where I: Iterator { match iter.peek() { Some(&"5") => { - let _5 = iter.next(); + let _ = iter.next(); if let Some(byte) = iter.next() { if let Ok(num) = byte.parse() { return Some(Fixed(num)); @@ -56,7 +56,7 @@ where I: Iterator { } } Some(&"2") => { - let _2 = iter.next(); + let _ = iter.next(); if let Some(hexes) = iter.next() { // Some terminals support R:G:B instead of R;G;B // but this clashes with splitting on ':' in each_pair above. @@ -79,14 +79,13 @@ where I: Iterator { } _ => {}, } - None } impl<'var> Pair<'var> { pub fn to_style(&self) -> Style { let mut style = Style::default(); - let mut iter = self.value.split(";").peekable(); + let mut iter = self.value.split(';').peekable(); while let Some(num) = iter.next() { match num.trim_left_matches('0') {