|
|
@@ -11,12 +11,12 @@ use log::*;
|
|
|
|
|
|
use users::UsersCache;
|
|
|
|
|
|
-use crate::style::Colours;
|
|
|
+use crate::fs::{File, fields as f};
|
|
|
+use crate::fs::feature::git::GitCache;
|
|
|
use crate::output::cell::TextCell;
|
|
|
use crate::output::render::TimeRender;
|
|
|
use crate::output::time::TimeFormat;
|
|
|
-use crate::fs::{File, fields as f};
|
|
|
-use crate::fs::feature::git::GitCache;
|
|
|
+use crate::style::Colours;
|
|
|
|
|
|
|
|
|
/// Options for displaying a table.
|
|
|
@@ -108,7 +108,7 @@ impl Columns {
|
|
|
columns.push(Column::Timestamp(TimeType::Accessed));
|
|
|
}
|
|
|
|
|
|
- if cfg!(feature="git") && self.git && actually_enable_git {
|
|
|
+ if cfg!(feature = "git") && self.git && actually_enable_git {
|
|
|
columns.push(Column::GitStatus);
|
|
|
}
|
|
|
|
|
|
@@ -136,7 +136,8 @@ pub enum Column {
|
|
|
/// right-aligned, and text is left-aligned.
|
|
|
#[derive(Copy, Clone)]
|
|
|
pub enum Alignment {
|
|
|
- Left, Right,
|
|
|
+ Left,
|
|
|
+ Right,
|
|
|
}
|
|
|
|
|
|
impl Column {
|
|
|
@@ -144,12 +145,12 @@ impl Column {
|
|
|
/// Get the alignment this column should use.
|
|
|
pub fn alignment(self) -> Alignment {
|
|
|
match self {
|
|
|
- Self::FileSize |
|
|
|
- Self::HardLinks |
|
|
|
- Self::Inode |
|
|
|
- Self::Blocks |
|
|
|
- Self::GitStatus => Alignment::Right,
|
|
|
- _ => Alignment::Left,
|
|
|
+ Self::FileSize |
|
|
|
+ Self::HardLinks |
|
|
|
+ Self::Inode |
|
|
|
+ Self::Blocks |
|
|
|
+ Self::GitStatus => Alignment::Right,
|
|
|
+ _ => Alignment::Left,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -199,6 +200,7 @@ impl Default for SizeFormat {
|
|
|
/// across most (all?) operating systems.
|
|
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
|
pub enum TimeType {
|
|
|
+
|
|
|
/// The file’s modified time (`st_mtime`).
|
|
|
Modified,
|
|
|
|
|
|
@@ -229,7 +231,7 @@ impl TimeType {
|
|
|
/// Fields for which of a file’s time fields should be displayed in the
|
|
|
/// columns output.
|
|
|
///
|
|
|
-/// There should always be at least one of these--there's no way to disable
|
|
|
+/// There should always be at least one of these — there’s no way to disable
|
|
|
/// the time columns entirely (yet).
|
|
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
|
pub struct TimeTypes {
|
|
|
@@ -244,15 +246,18 @@ impl Default for TimeTypes {
|
|
|
/// By default, display just the ‘modified’ time. This is the most
|
|
|
/// common option, which is why it has this shorthand.
|
|
|
fn default() -> Self {
|
|
|
- Self { modified: true, changed: false, accessed: false, created: false }
|
|
|
+ Self {
|
|
|
+ modified: true,
|
|
|
+ changed: false,
|
|
|
+ accessed: false,
|
|
|
+ created: false,
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
/// The **environment** struct contains any data that could change between
|
|
|
-/// running instances of exa, depending on the user's computer's configuration.
|
|
|
+/// running instances of exa, depending on the user’s computer’s configuration.
|
|
|
///
|
|
|
/// Any environment field should be able to be mocked up for test runs.
|
|
|
pub struct Environment {
|
|
|
@@ -260,8 +265,8 @@ pub struct Environment {
|
|
|
/// Localisation rules for formatting numbers.
|
|
|
numeric: locale::Numeric,
|
|
|
|
|
|
- /// The computer's current time zone. This gets used to determine how to
|
|
|
- /// offset files' timestamps.
|
|
|
+ /// The computer’s current time zone. This gets used to determine how to
|
|
|
+ /// offset files’ timestamps.
|
|
|
tz: Option<TimeZone>,
|
|
|
|
|
|
/// Mapping cache of user IDs to usernames.
|
|
|
@@ -275,7 +280,9 @@ impl Environment {
|
|
|
|
|
|
pub fn load_all() -> Self {
|
|
|
let tz = match determine_time_zone() {
|
|
|
- Ok(t) => Some(t),
|
|
|
+ Ok(t) => {
|
|
|
+ Some(t)
|
|
|
+ }
|
|
|
Err(ref e) => {
|
|
|
println!("Unable to determine time zone: {}", e);
|
|
|
None
|
|
|
@@ -283,7 +290,7 @@ impl Environment {
|
|
|
};
|
|
|
|
|
|
let numeric = locale::Numeric::load_user_locale()
|
|
|
- .unwrap_or_else(|_| locale::Numeric::english());
|
|
|
+ .unwrap_or_else(|_| locale::Numeric::english());
|
|
|
|
|
|
let users = Mutex::new(UsersCache::new());
|
|
|
|
|
|
@@ -294,7 +301,8 @@ impl Environment {
|
|
|
fn determine_time_zone() -> TZResult<TimeZone> {
|
|
|
if let Ok(file) = env::var("TZ") {
|
|
|
TimeZone::from_file(format!("/usr/share/zoneinfo/{}", file))
|
|
|
- } else {
|
|
|
+ }
|
|
|
+ else {
|
|
|
TimeZone::from_file("/etc/localtime")
|
|
|
}
|
|
|
}
|
|
|
@@ -321,7 +329,10 @@ impl<'a, 'f> Table<'a> {
|
|
|
let widths = TableWidths::zero(columns.len());
|
|
|
|
|
|
Table {
|
|
|
- colours, widths, columns, git,
|
|
|
+ colours,
|
|
|
+ widths,
|
|
|
+ columns,
|
|
|
+ git,
|
|
|
env: &options.env,
|
|
|
time_format: &options.time_format,
|
|
|
size_format: options.size_format,
|
|
|
@@ -368,25 +379,52 @@ impl<'a, 'f> Table<'a> {
|
|
|
|
|
|
fn display(&self, file: &File, column: Column, xattrs: bool) -> TextCell {
|
|
|
match column {
|
|
|
- Column::Permissions => self.permissions_plus(file, xattrs).render(self.colours),
|
|
|
- Column::FileSize => file.size().render(self.colours, self.size_format, &self.env.numeric),
|
|
|
- Column::HardLinks => file.links().render(self.colours, &self.env.numeric),
|
|
|
- Column::Inode => file.inode().render(self.colours.inode),
|
|
|
- Column::Blocks => file.blocks().render(self.colours),
|
|
|
- Column::User => file.user().render(self.colours, &*self.env.lock_users()),
|
|
|
- Column::Group => file.group().render(self.colours, &*self.env.lock_users()),
|
|
|
- Column::GitStatus => self.git_status(file).render(self.colours),
|
|
|
- Column::Octal => self.octal_permissions(file).render(self.colours.octal),
|
|
|
-
|
|
|
- Column::Timestamp(TimeType::Modified) => file.modified_time().render(self.colours.date, &self.env.tz, self.time_format),
|
|
|
- Column::Timestamp(TimeType::Changed) => file.changed_time() .render(self.colours.date, &self.env.tz, self.time_format),
|
|
|
- Column::Timestamp(TimeType::Created) => file.created_time() .render(self.colours.date, &self.env.tz, self.time_format),
|
|
|
- Column::Timestamp(TimeType::Accessed) => file.accessed_time().render(self.colours.date, &self.env.tz, self.time_format),
|
|
|
+ Column::Permissions => {
|
|
|
+ self.permissions_plus(file, xattrs).render(self.colours)
|
|
|
+ }
|
|
|
+ Column::FileSize => {
|
|
|
+ file.size().render(self.colours, self.size_format, &self.env.numeric)
|
|
|
+ }
|
|
|
+ Column::HardLinks => {
|
|
|
+ file.links().render(self.colours, &self.env.numeric)
|
|
|
+ }
|
|
|
+ Column::Inode => {
|
|
|
+ file.inode().render(self.colours.inode)
|
|
|
+ }
|
|
|
+ Column::Blocks => {
|
|
|
+ file.blocks().render(self.colours)
|
|
|
+ }
|
|
|
+ Column::User => {
|
|
|
+ file.user().render(self.colours, &*self.env.lock_users())
|
|
|
+ }
|
|
|
+ Column::Group => {
|
|
|
+ file.group().render(self.colours, &*self.env.lock_users())
|
|
|
+ }
|
|
|
+ Column::GitStatus => {
|
|
|
+ self.git_status(file).render(self.colours)
|
|
|
+ }
|
|
|
+ Column::Octal => {
|
|
|
+ self.octal_permissions(file).render(self.colours.octal)
|
|
|
+ }
|
|
|
+
|
|
|
+ Column::Timestamp(TimeType::Modified) => {
|
|
|
+ file.modified_time().render(self.colours.date, &self.env.tz, self.time_format)
|
|
|
+ }
|
|
|
+ Column::Timestamp(TimeType::Changed) => {
|
|
|
+ file.changed_time().render(self.colours.date, &self.env.tz, self.time_format)
|
|
|
+ }
|
|
|
+ Column::Timestamp(TimeType::Created) => {
|
|
|
+ file.created_time().render(self.colours.date, &self.env.tz, self.time_format)
|
|
|
+ }
|
|
|
+ Column::Timestamp(TimeType::Accessed) => {
|
|
|
+ file.accessed_time().render(self.colours.date, &self.env.tz, self.time_format)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn git_status(&self, file: &File) -> f::Git {
|
|
|
debug!("Getting Git status for file {:?}", file.path);
|
|
|
+
|
|
|
self.git
|
|
|
.map(|g| g.get(&file.path, file.is_directory()))
|
|
|
.unwrap_or_default()
|
|
|
@@ -395,12 +433,22 @@ impl<'a, 'f> Table<'a> {
|
|
|
pub fn render(&self, row: Row) -> TextCell {
|
|
|
let mut cell = TextCell::default();
|
|
|
|
|
|
- for (n, (this_cell, width)) in row.cells.into_iter().zip(self.widths.iter()).enumerate() {
|
|
|
+ let iter = row.cells.into_iter()
|
|
|
+ .zip(self.widths.iter())
|
|
|
+ .enumerate();
|
|
|
+
|
|
|
+ for (n, (this_cell, width)) in iter {
|
|
|
let padding = width - *this_cell.width;
|
|
|
|
|
|
match self.columns[n].alignment() {
|
|
|
- Alignment::Left => { cell.append(this_cell); cell.add_spaces(padding); }
|
|
|
- Alignment::Right => { cell.add_spaces(padding); cell.append(this_cell); }
|
|
|
+ Alignment::Left => {
|
|
|
+ cell.append(this_cell);
|
|
|
+ cell.add_spaces(padding);
|
|
|
+ }
|
|
|
+ Alignment::Right => {
|
|
|
+ cell.add_spaces(padding);
|
|
|
+ cell.append(this_cell);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
cell.add_spaces(1);
|
|
|
@@ -411,7 +459,6 @@ impl<'a, 'f> Table<'a> {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
pub struct TableWidths(Vec<usize>);
|
|
|
|
|
|
impl Deref for TableWidths {
|
|
|
@@ -424,7 +471,7 @@ impl Deref for TableWidths {
|
|
|
|
|
|
impl TableWidths {
|
|
|
pub fn zero(count: usize) -> Self {
|
|
|
- Self(vec![ 0; count ])
|
|
|
+ Self(vec![0; count])
|
|
|
}
|
|
|
|
|
|
pub fn add_widths(&mut self, row: &Row) {
|