فهرست منبع

Merge branch 'master' into chesterliu/dev/win-support

Chester Liu 4 سال پیش
والد
کامیت
23a1c8a41f
16فایلهای تغییر یافته به همراه58 افزوده شده و 91 حذف شده
  1. 4 4
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 2 3
      src/fs/dir.rs
  4. 5 5
      src/fs/feature/xattr.rs
  5. 2 2
      src/fs/file.rs
  6. 7 47
      src/fs/filter.rs
  7. 1 0
      src/info/filetype.rs
  8. 10 6
      src/main.rs
  9. 1 1
      src/options/mod.rs
  10. 9 13
      src/options/view.rs
  11. 4 3
      src/output/details.rs
  12. 1 1
      src/output/escape.rs
  13. 4 1
      src/output/icons.rs
  14. 1 1
      src/output/mod.rs
  15. 1 0
      src/output/render/git.rs
  16. 5 3
      src/output/table.rs

+ 4 - 4
Cargo.lock

@@ -72,7 +72,7 @@ dependencies = [
  "number_prefix",
  "scoped_threadpool",
  "term_grid",
- "term_size",
+ "terminal_size",
  "unicode-width",
  "users",
  "zoneinfo_compiled",
@@ -285,10 +285,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "term_size"
-version = "0.3.2"
+name = "terminal_size"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
+checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
 dependencies = [
  "libc",
  "winapi",

+ 1 - 1
Cargo.toml

@@ -28,7 +28,7 @@ num_cpus = "1.10"
 number_prefix = "0.4"
 scoped_threadpool = "0.1"
 term_grid = "0.1"
-term_size = "0.3"
+terminal_size = "0.1.16"
 unicode-width = "0.1"
 zoneinfo_compiled = "0.5.1"
 

+ 2 - 3
src/fs/dir.rs

@@ -128,9 +128,8 @@ impl<'dir, 'ig> Files<'dir, 'ig> {
                 return Some(File::from_args(path.clone(), self.dir, filename)
                                  .map_err(|e| (path.clone(), e)))
             }
-            else {
-                return None
-            }
+
+            return None
         }
     }
 }

+ 5 - 5
src/fs/feature/xattr.rs

@@ -246,7 +246,7 @@ mod lister {
 
             unsafe {
                 listxattr(
-                    c_path.as_ptr() as *const _,
+                    c_path.as_ptr().cast(),
                     ptr::null_mut(),
                     0,
                 )
@@ -261,8 +261,8 @@ mod lister {
 
             unsafe {
                 listxattr(
-                    c_path.as_ptr() as *const _,
-                    buf.as_mut_ptr() as *mut c_char,
+                    c_path.as_ptr().cast(),
+                    buf.as_mut_ptr().cast::<i8>(),
                     bufsize as size_t,
                 )
             }
@@ -276,8 +276,8 @@ mod lister {
 
             unsafe {
                 getxattr(
-                    c_path.as_ptr() as *const _,
-                    buf.as_ptr() as *const c_char,
+                    c_path.as_ptr().cast(),
+                    buf.as_ptr().cast::<i8>(),
                     ptr::null_mut(),
                     0,
                 )

+ 2 - 2
src/fs/file.rs

@@ -81,11 +81,11 @@ impl<'dir> File<'dir> {
         let metadata   = std::fs::symlink_metadata(&path)?;
         let is_all_all = false;
 
-        Ok(File { path, parent_dir, metadata, ext, name, is_all_all })
+        Ok(File { name, ext, path, metadata, parent_dir, is_all_all })
     }
 
     pub fn new_aa_current(parent_dir: &'dir Dir) -> io::Result<File<'dir>> {
-        let path       = parent_dir.path.to_path_buf();
+        let path       = parent_dir.path.clone();
         let ext        = File::ext(&path);
 
         debug!("Statting file {:?}", &path);

+ 7 - 47
src/fs/filter.rs

@@ -4,7 +4,6 @@ use std::cmp::Ordering;
 use std::iter::FromIterator;
 #[cfg(unix)]
 use std::os::unix::fs::MetadataExt;
-use std::path::Path;
 
 use crate::fs::DotFilter;
 use crate::fs::File;
@@ -51,31 +50,8 @@ pub struct FileFilter {
     ///
     /// This came about more or less by a complete historical accident,
     /// when the original `ls` tried to hide `.` and `..`:
-    /// https://plus.google.com/+RobPikeTheHuman/posts/R58WgWwN9jp
     ///
-    ///   When one typed ls, however, these files appeared, so either Ken or
-    ///   Dennis added a simple test to the program. It was in assembler then,
-    ///   but the code in question was equivalent to something like this:
-    ///      if (name[0] == '.') continue;
-    ///   This statement was a little shorter than what it should have been,
-    ///   which is:
-    ///      if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
-    ///   but hey, it was easy.
-    ///
-    ///   Two things resulted.
-    ///
-    ///   First, a bad precedent was set. A lot of other lazy programmers
-    ///   introduced bugs by making the same simplification. Actual files
-    ///   beginning with periods are often skipped when they should be counted.
-    ///
-    ///   Second, and much worse, the idea of a "hidden" or "dot" file was
-    ///   created. As a consequence, more lazy programmers started dropping
-    ///   files into everyone's home directory. I don't have all that much
-    ///   stuff installed on the machine I'm using to type this, but my home
-    ///   directory has about a hundred dot files and I don't even know what
-    ///   most of them are or whether they're still needed. Every file name
-    ///   evaluation that goes through my home directory is slowed down by
-    ///   this accumulated sludge.
+    /// [Linux History: How Dot Files Became Hidden Files](https://linux-audit.com/linux-history-how-dot-files-became-hidden-files/)
     pub dot_filter: DotFilter,
 
     /// Glob patterns to ignore. Any file name that matches *any* of these
@@ -83,9 +59,6 @@ pub struct FileFilter {
     pub ignore_patterns: IgnorePatterns,
 
     /// Whether to ignore Git-ignored patterns.
-    /// This is implemented completely separately from the actual Git
-    /// repository scanning — a `.gitignore` file will still be scanned even
-    /// if there’s no `.git` folder present.
     pub git_ignore: GitIgnore,
 }
 
@@ -287,8 +260,10 @@ impl SortField {
     }
 
     fn strip_dot(n: &str) -> &str {
-        if n.starts_with('.') { &n[1..] }
-                         else { n }
+        match n.strip_prefix('.') {
+            Some(s) => s,
+            None    => n,
+        }
     }
 }
 
@@ -348,35 +323,20 @@ impl IgnorePatterns {
     fn is_ignored(&self, file: &str) -> bool {
         self.patterns.iter().any(|p| p.matches(file))
     }
-
-    /// Test whether the given file should be hidden from the results.
-    pub fn is_ignored_path(&self, file: &Path) -> bool {
-        self.patterns.iter().any(|p| p.matches_path(file))
-    }
-
-    // TODO(ogham): The fact that `is_ignored_path` is pub while `is_ignored`
-    // isn’t probably means it’s in the wrong place
 }
 
 
-/// Whether to ignore or display files that are mentioned in `.gitignore` files.
+/// Whether to ignore or display files that Git would ignore.
 #[derive(PartialEq, Debug, Copy, Clone)]
 pub enum GitIgnore {
 
-    /// Ignore files that Git would ignore. This means doing a check for a
-    /// `.gitignore` file, possibly recursively up the filesystem tree.
+    /// Ignore files that Git would ignore.
     CheckAndIgnore,
 
     /// Display files, even if Git would ignore them.
     Off,
 }
 
-// This is not fully baked yet. The `ignore` crate lists a lot more files that
-// we aren’t checking:
-//
-// > By default, all ignore files found are respected. This includes .ignore,
-// > .gitignore, .git/info/exclude and even your global gitignore globs,
-// > usually found in $XDG_CONFIG_HOME/git/ignore.
 
 
 #[cfg(test)]

+ 1 - 0
src/info/filetype.rs

@@ -19,6 +19,7 @@ impl FileExtensions {
     /// An “immediate” file is something that can be run or activated somehow
     /// in order to kick off the build of a project. It’s usually only present
     /// in directories full of source code.
+    #[allow(clippy::case_sensitive_file_extension_comparisons)]
     fn is_immediate(&self, file: &File<'_>) -> bool {
         file.name.to_lowercase().starts_with("readme") ||
         file.name.ends_with(".ninja") ||

+ 10 - 6
src/main.rs

@@ -7,18 +7,19 @@
 #![warn(unused)]
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::cast_precision_loss)]
+#![allow(clippy::cast_possible_truncation)]
+#![allow(clippy::cast_possible_wrap)]
+#![allow(clippy::cast_sign_loss)]
 #![allow(clippy::enum_glob_use)]
-#![allow(clippy::find_map)]
 #![allow(clippy::map_unwrap_or)]
 #![allow(clippy::match_same_arms)]
-#![allow(clippy::missing_const_for_fn)]
-#![allow(clippy::missing_errors_doc)]
 #![allow(clippy::module_name_repetitions)]
-#![allow(clippy::must_use_candidate)]
 #![allow(clippy::non_ascii_literal)]
 #![allow(clippy::option_if_let_else)]
 #![allow(clippy::too_many_lines)]
 #![allow(clippy::unused_self)]
+#![allow(clippy::upper_case_acronyms)]
 #![allow(clippy::wildcard_imports)]
 
 use std::env;
@@ -160,6 +161,9 @@ fn git_options(options: &Options, args: &[&OsStr]) -> Option<GitCache> {
 }
 
 impl<'args> Exa<'args> {
+    /// # Errors
+    ///
+    /// Will return `Err` if printing to stderr fails.
     pub fn run(mut self) -> io::Result<i32> {
         debug!("Running with options: {:#?}", self.options);
 
@@ -287,7 +291,7 @@ impl<'args> Exa<'args> {
 
                 let git_ignoring = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
                 let git = self.git.as_ref();
-                let r = details::Render { dir, files, theme, file_style, opts, filter, recurse, git_ignoring, git };
+                let r = details::Render { dir, files, theme, file_style, opts, recurse, filter, git_ignoring, git };
                 r.render(&mut self.writer)
             }
 
@@ -311,7 +315,7 @@ impl<'args> Exa<'args> {
                 let git_ignoring = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
 
                 let git = self.git.as_ref();
-                let r = details::Render { dir, files, theme, file_style, opts, filter, recurse, git_ignoring, git };
+                let r = details::Render { dir, files, theme, file_style, opts, recurse, filter, git_ignoring, git };
                 r.render(&mut self.writer)
             }
         }

+ 1 - 1
src/options/mod.rs

@@ -178,7 +178,7 @@ impl Options {
     fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
         if cfg!(not(feature = "git")) &&
                 matches.has_where_any(|f| f.matches(&flags::GIT) || f.matches(&flags::GIT_IGNORE)).is_some() {
-            return Err(OptionsError::Unsupported(format!(
+            return Err(OptionsError::Unsupported(String::from(
                 "Options --git and --git-ignore can't be used because `git` feature was disabled in this build of exa"
             )));
         }

+ 9 - 13
src/options/view.rs

@@ -32,13 +32,10 @@ impl Mode {
         let flag = matches.has_where_any(|f| f.matches(&flags::LONG) || f.matches(&flags::ONE_LINE)
                                           || f.matches(&flags::GRID) || f.matches(&flags::TREE));
 
-        let flag = match flag {
-            Some(f) => f,
-            None => {
-                Self::strict_check_long_flags(matches)?;
-                let grid = grid::Options::deduce(matches)?;
-                return Ok(Self::Grid(grid));
-            }
+        let flag = if let Some(f) = flag { f } else {
+            Self::strict_check_long_flags(matches)?;
+            let grid = grid::Options::deduce(matches)?;
+            return Ok(Self::Grid(grid));
         };
 
         if flag.matches(&flags::LONG)
@@ -57,10 +54,9 @@ impl Mode {
                 let grid_details = grid_details::Options { grid, details, row_threshold };
                 return Ok(Self::GridDetails(grid_details));
             }
-            else {
-                // the --tree case is handled by the DirAction parser later
-                return Ok(Self::Details(details));
-            }
+
+            // the --tree case is handled by the DirAction parser later
+            return Ok(Self::Details(details));
         }
 
         Self::strict_check_long_flags(matches)?;
@@ -195,7 +191,7 @@ impl TableOptions {
         let size_format = SizeFormat::deduce(matches)?;
         let user_format = UserFormat::deduce(matches)?;
         let columns = Columns::deduce(matches)?;
-        Ok(Self { time_format, size_format, columns , user_format})
+        Ok(Self { size_format, time_format, user_format, columns })
     }
 }
 
@@ -215,7 +211,7 @@ impl Columns {
         let filesize =    ! matches.has(&flags::NO_FILESIZE)?;
         let user =        ! matches.has(&flags::NO_USER)?;
 
-        Ok(Self { time_types, git, octal, blocks, group, inode, links, permissions, filesize, user })
+        Ok(Self { time_types, inode, links, blocks, group, git, octal, permissions, filesize, user })
     }
 }
 

+ 4 - 3
src/output/details.rs

@@ -350,9 +350,10 @@ impl<'a> Render<'a> {
     fn render_error(&self, error: &io::Error, tree: TreeParams, path: Option<PathBuf>) -> Row {
         use crate::output::file_name::Colours;
 
-        let error_message = match path {
-            Some(path) => format!("<{}: {}>", path.display(), error),
-            None       => format!("<{}>", error),
+        let error_message = if let Some(path) = path {
+            format!("<{}: {}>", path.display(), error)
+        } else {
+            format!("<{}>", error)
         };
 
         // TODO: broken_symlink() doesn’t quite seem like the right name for

+ 1 - 1
src/output/escape.rs

@@ -1,7 +1,7 @@
 use ansi_term::{ANSIString, Style};
 
 
-pub fn escape<'a>(string: String, bits: &mut Vec<ANSIString<'a>>, good: Style, bad: Style) {
+pub fn escape(string: String, bits: &mut Vec<ANSIString<'_>>, good: Style, bad: Style) {
     if string.chars().all(|c| c >= 0x20 as char && c != 0x7f as char) {
         bits.push(good.paint(string));
         return;

+ 4 - 1
src/output/icons.rs

@@ -37,7 +37,7 @@ impl Icons {
 /// - If neither is set, just use the default style.
 /// - Attributes such as bold or underline should not be used to paint the
 ///   icon, as they can make it look weird.
-pub fn iconify_style<'a>(style: Style) -> Style {
+pub fn iconify_style(style: Style) -> Style {
     style.background.or(style.foreground)
          .map(Style::from)
          .unwrap_or_default()
@@ -170,6 +170,9 @@ pub fn icon_for_file(file: &File<'_>) -> char {
             "flac"          => '\u{f001}', // 
             "flv"           => '\u{f03d}', // 
             "font"          => '\u{f031}', // 
+            "fs"            => '\u{e7a7}', // 
+            "fsi"           => '\u{e7a7}', // 
+            "fsx"           => '\u{e7a7}', // 
             "gdoc"          => '\u{f1c2}', // 
             "gem"           => '\u{e21e}', // 
             "gemfile"       => '\u{e21e}', // 

+ 1 - 1
src/output/mod.rs

@@ -55,7 +55,7 @@ impl TerminalWidth {
 
         match self {
             Self::Set(width)  => Some(width),
-            Self::Automatic   => term_size::dimensions_stdout().map(|t| t.0),
+            Self::Automatic   => terminal_size::terminal_size().map(|(w, _)| w.0.into()),
         }
     }
 }

+ 1 - 0
src/output/render/git.rs

@@ -35,6 +35,7 @@ impl f::GitStatus {
 
 pub trait Colours {
     fn not_modified(&self) -> Style;
+    #[allow(clippy::new_ret_no_self)]
     fn new(&self) -> Style;
     fn modified(&self) -> Style;
     fn deleted(&self) -> Style;

+ 5 - 3
src/output/table.rs

@@ -30,6 +30,7 @@ pub struct Options {
 }
 
 /// Extra columns to display in the table.
+#[allow(clippy::struct_excessive_bools)]
 #[derive(PartialEq, Debug, Copy, Clone)]
 pub struct Columns {
 
@@ -199,6 +200,7 @@ impl Column {
 
 
 /// Formatting options for file sizes.
+#[allow(clippy::pub_enum_variant_names)]
 #[derive(PartialEq, Debug, Copy, Clone)]
 pub enum SizeFormat {
 
@@ -332,7 +334,7 @@ impl Environment {
         #[cfg(unix)]
         let users = Mutex::new(UsersCache::new());
 
-        Self { tz, numeric, #[cfg(unix)] users }
+        Self { numeric, tz, #[cfg(unix)] users }
     }
 }
 
@@ -340,11 +342,11 @@ impl Environment {
 fn determine_time_zone() -> TZResult<TimeZone> {
     if let Ok(file) = env::var("TZ") {
         TimeZone::from_file({
-            if file.starts_with("/") {
+            if file.starts_with('/') {
                 file
             } else {
                 format!("/usr/share/zoneinfo/{}", {
-                    if file.starts_with(":") {
+                    if file.starts_with(':') {
                         file.replacen(":", "", 1)
                     } else {
                         file