mirror of
https://github.com/eza-community/eza
synced 2024-10-04 15:09:49 +00:00
feat: add option --smart-group
This commit is contained in:
parent
a7718c84d7
commit
61284c80af
|
@ -40,23 +40,24 @@ const SORTS: Values = &[ "name", "Name", "size", "extension",
|
|||
"created", "inode", "type", "none" ];
|
||||
|
||||
// display options
|
||||
pub static BINARY: Arg = Arg { short: Some(b'b'), long: "binary", takes_value: TakesValue::Forbidden };
|
||||
pub static BYTES: Arg = Arg { short: Some(b'B'), long: "bytes", takes_value: TakesValue::Forbidden };
|
||||
pub static GROUP: Arg = Arg { short: Some(b'g'), long: "group", takes_value: TakesValue::Forbidden };
|
||||
pub static NUMERIC: Arg = Arg { short: Some(b'n'), long: "numeric", takes_value: TakesValue::Forbidden };
|
||||
pub static HEADER: Arg = Arg { short: Some(b'h'), long: "header", takes_value: TakesValue::Forbidden };
|
||||
pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Forbidden };
|
||||
pub static INODE: Arg = Arg { short: Some(b'i'), long: "inode", takes_value: TakesValue::Forbidden };
|
||||
pub static LINKS: Arg = Arg { short: Some(b'H'), long: "links", takes_value: TakesValue::Forbidden };
|
||||
pub static MODIFIED: Arg = Arg { short: Some(b'm'), long: "modified", takes_value: TakesValue::Forbidden };
|
||||
pub static CHANGED: Arg = Arg { short: None, long: "changed", takes_value: TakesValue::Forbidden };
|
||||
pub static BLOCKSIZE: Arg = Arg { short: Some(b'S'), long: "blocksize", takes_value: TakesValue::Forbidden };
|
||||
pub static TIME: Arg = Arg { short: Some(b't'), long: "time", takes_value: TakesValue::Necessary(Some(TIMES)) };
|
||||
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 MOUNTS: Arg = Arg { short: Some(b'M'), long: "mounts", takes_value: TakesValue::Forbidden };
|
||||
pub static BINARY: Arg = Arg { short: Some(b'b'), long: "binary", takes_value: TakesValue::Forbidden };
|
||||
pub static BYTES: Arg = Arg { short: Some(b'B'), long: "bytes", takes_value: TakesValue::Forbidden };
|
||||
pub static GROUP: Arg = Arg { short: Some(b'g'), long: "group", takes_value: TakesValue::Forbidden };
|
||||
pub static NUMERIC: Arg = Arg { short: Some(b'n'), long: "numeric", takes_value: TakesValue::Forbidden };
|
||||
pub static HEADER: Arg = Arg { short: Some(b'h'), long: "header", takes_value: TakesValue::Forbidden };
|
||||
pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Forbidden };
|
||||
pub static INODE: Arg = Arg { short: Some(b'i'), long: "inode", takes_value: TakesValue::Forbidden };
|
||||
pub static LINKS: Arg = Arg { short: Some(b'H'), long: "links", takes_value: TakesValue::Forbidden };
|
||||
pub static MODIFIED: Arg = Arg { short: Some(b'm'), long: "modified", takes_value: TakesValue::Forbidden };
|
||||
pub static CHANGED: Arg = Arg { short: None, long: "changed", takes_value: TakesValue::Forbidden };
|
||||
pub static BLOCKSIZE: Arg = Arg { short: Some(b'S'), long: "blocksize", takes_value: TakesValue::Forbidden };
|
||||
pub static TIME: Arg = Arg { short: Some(b't'), long: "time", takes_value: TakesValue::Necessary(Some(TIMES)) };
|
||||
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 MOUNTS: Arg = Arg { short: Some(b'M'), long: "mounts", takes_value: TakesValue::Forbidden };
|
||||
pub static SMART_GROUP: Arg = Arg { short: None, long: "smart-group", takes_value: TakesValue::Forbidden };
|
||||
const TIMES: Values = &["modified", "changed", "accessed", "created"];
|
||||
const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso", "relative"];
|
||||
|
||||
|
@ -87,7 +88,7 @@ pub static ALL_ARGS: Args = Args(&[
|
|||
|
||||
&BINARY, &BYTES, &GROUP, &NUMERIC, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
|
||||
&BLOCKSIZE, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, &HYPERLINK, &MOUNTS,
|
||||
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &NO_ICONS,
|
||||
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &NO_ICONS, &SMART_GROUP,
|
||||
|
||||
&GIT, &NO_GIT, &GIT_REPOS, &GIT_REPOS_NO_STAT,
|
||||
&EXTENDED, &OCTAL, &SECURITY_CONTEXT
|
||||
|
|
|
@ -27,6 +27,7 @@ DISPLAY OPTIONS
|
|||
--no-quotes don't quote file names with spaces
|
||||
--hyperlink display entries as hyperlinks
|
||||
-w, --width COLS set screen width in columns
|
||||
--smart-group only show group if it has a different name from owner
|
||||
|
||||
|
||||
FILTERING AND SORTING OPTIONS
|
||||
|
|
|
@ -3,7 +3,9 @@ use crate::options::parser::MatchedFlags;
|
|||
use crate::options::{flags, NumberSource, OptionsError, Vars};
|
||||
use crate::output::file_name::Options as FileStyle;
|
||||
use crate::output::grid_details::{self, RowThreshold};
|
||||
use crate::output::table::{Columns, Options as TableOptions, SizeFormat, TimeTypes, UserFormat};
|
||||
use crate::output::table::{
|
||||
Columns, GroupFormat, Options as TableOptions, SizeFormat, TimeTypes, UserFormat,
|
||||
};
|
||||
use crate::output::time::TimeFormat;
|
||||
use crate::output::{details, grid, Mode, TerminalWidth, View};
|
||||
|
||||
|
@ -231,11 +233,13 @@ impl TableOptions {
|
|||
let time_format = TimeFormat::deduce(matches, vars)?;
|
||||
let size_format = SizeFormat::deduce(matches)?;
|
||||
let user_format = UserFormat::deduce(matches)?;
|
||||
let group_format = GroupFormat::deduce(matches)?;
|
||||
let columns = Columns::deduce(matches, vars)?;
|
||||
Ok(Self {
|
||||
size_format,
|
||||
time_format,
|
||||
user_format,
|
||||
group_format,
|
||||
columns,
|
||||
})
|
||||
}
|
||||
|
@ -341,6 +345,13 @@ impl UserFormat {
|
|||
}
|
||||
}
|
||||
|
||||
impl GroupFormat {
|
||||
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
||||
let flag = matches.has(&flags::SMART_GROUP)?;
|
||||
Ok(if flag { Self::Smart } else { Self::Regular })
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeTypes {
|
||||
/// Determine which of a file’s time fields should be displayed for it
|
||||
/// based on the user’s options.
|
||||
|
|
|
@ -3,14 +3,15 @@ use uzers::{Groups, Users};
|
|||
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::TextCell;
|
||||
use crate::output::table::UserFormat;
|
||||
use crate::output::table::{GroupFormat, UserFormat};
|
||||
|
||||
pub trait Render {
|
||||
fn render<C: Colours, U: Users + Groups>(
|
||||
self,
|
||||
colours: &C,
|
||||
users: &U,
|
||||
format: UserFormat,
|
||||
user_format: UserFormat,
|
||||
group_format: GroupFormat,
|
||||
) -> TextCell;
|
||||
}
|
||||
|
||||
|
@ -19,7 +20,8 @@ impl Render for Option<f::Group> {
|
|||
self,
|
||||
colours: &C,
|
||||
users: &U,
|
||||
format: UserFormat,
|
||||
user_format: UserFormat,
|
||||
group_format: GroupFormat,
|
||||
) -> TextCell {
|
||||
use uzers::os::unix::GroupExt;
|
||||
|
||||
|
@ -46,11 +48,26 @@ impl Render for Option<f::Group> {
|
|||
style = colours.root_group();
|
||||
}
|
||||
|
||||
let group_name = match format {
|
||||
let mut group_name = match user_format {
|
||||
UserFormat::Name => group.name().to_string_lossy().into(),
|
||||
UserFormat::Numeric => group.gid().to_string(),
|
||||
};
|
||||
|
||||
group_name = match group_format {
|
||||
GroupFormat::Smart => {
|
||||
if let Some(current_user) = users.get_user_by_uid(current_uid) {
|
||||
if current_user.name() == group.name() {
|
||||
":".to_string()
|
||||
} else {
|
||||
group_name
|
||||
}
|
||||
} else {
|
||||
group_name
|
||||
}
|
||||
}
|
||||
GroupFormat::Regular => group_name,
|
||||
};
|
||||
|
||||
TextCell::paint(style, group_name)
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +85,7 @@ pub mod test {
|
|||
use super::{Colours, Render};
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::TextCell;
|
||||
use crate::output::table::UserFormat;
|
||||
use crate::output::table::{GroupFormat, UserFormat};
|
||||
|
||||
use ansiterm::Colour::*;
|
||||
use ansiterm::Style;
|
||||
|
@ -95,13 +112,18 @@ pub mod test {
|
|||
let expected = TextCell::paint_str(Fixed(81).normal(), "folk");
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Name)
|
||||
group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Regular)
|
||||
);
|
||||
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), "100");
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Numeric)
|
||||
group.render(
|
||||
&TestColours,
|
||||
&users,
|
||||
UserFormat::Numeric,
|
||||
GroupFormat::Regular
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -113,11 +135,16 @@ pub mod test {
|
|||
let expected = TextCell::paint_str(Fixed(81).normal(), "100");
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Name)
|
||||
group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Regular)
|
||||
);
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Numeric)
|
||||
group.render(
|
||||
&TestColours,
|
||||
&users,
|
||||
UserFormat::Numeric,
|
||||
GroupFormat::Regular
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -131,7 +158,7 @@ pub mod test {
|
|||
let expected = TextCell::paint_str(Fixed(80).normal(), "folk");
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Name)
|
||||
group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Regular)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -147,7 +174,7 @@ pub mod test {
|
|||
let expected = TextCell::paint_str(Fixed(80).normal(), "folk");
|
||||
assert_eq!(
|
||||
expected,
|
||||
group.render(&TestColours, &users, UserFormat::Name)
|
||||
group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Regular)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -160,8 +187,42 @@ pub mod test {
|
|||
group.render(
|
||||
&TestColours,
|
||||
&MockUsers::with_current_uid(0),
|
||||
UserFormat::Numeric
|
||||
UserFormat::Numeric,
|
||||
GroupFormat::Regular
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smart() {
|
||||
let mut users = MockUsers::with_current_uid(1000);
|
||||
users.add_user(User::new(1000, "user", 110));
|
||||
users.add_group(Group::new(100, "user"));
|
||||
users.add_group(Group::new(101, "http"));
|
||||
|
||||
let same_group = Some(f::Group(100));
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), ":");
|
||||
assert_eq!(
|
||||
expected,
|
||||
same_group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Smart)
|
||||
);
|
||||
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), ":");
|
||||
assert_eq!(
|
||||
expected,
|
||||
same_group.render(
|
||||
&TestColours,
|
||||
&users,
|
||||
UserFormat::Numeric,
|
||||
GroupFormat::Smart
|
||||
)
|
||||
);
|
||||
|
||||
let http_group = Some(f::Group(101));
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), "http");
|
||||
assert_eq!(
|
||||
expected,
|
||||
http_group.render(&TestColours, &users, UserFormat::Name, GroupFormat::Smart)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ pub struct Options {
|
|||
pub size_format: SizeFormat,
|
||||
pub time_format: TimeFormat,
|
||||
pub user_format: UserFormat,
|
||||
pub group_format: GroupFormat,
|
||||
pub columns: Columns,
|
||||
}
|
||||
|
||||
|
@ -239,6 +240,15 @@ pub enum UserFormat {
|
|||
Name,
|
||||
}
|
||||
|
||||
/// Formatting options for group only.
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
pub enum GroupFormat {
|
||||
/// Numeric or text value
|
||||
Regular,
|
||||
/// Show ":" if user-group value is the same
|
||||
Smart,
|
||||
}
|
||||
|
||||
impl Default for SizeFormat {
|
||||
fn default() -> Self {
|
||||
Self::DecimalBytes
|
||||
|
@ -355,6 +365,8 @@ pub struct Table<'a> {
|
|||
size_format: SizeFormat,
|
||||
#[cfg(unix)]
|
||||
user_format: UserFormat,
|
||||
#[cfg(unix)]
|
||||
group_format: GroupFormat,
|
||||
git: Option<&'a GitCache>,
|
||||
}
|
||||
|
||||
|
@ -379,6 +391,8 @@ impl<'a> Table<'a> {
|
|||
size_format: options.size_format,
|
||||
#[cfg(unix)]
|
||||
user_format: options.user_format,
|
||||
#[cfg(unix)]
|
||||
group_format: options.group_format,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,10 +471,12 @@ impl<'a> Table<'a> {
|
|||
.render(self.theme, &*self.env.lock_users(), self.user_format)
|
||||
}
|
||||
#[cfg(unix)]
|
||||
Column::Group => {
|
||||
file.group()
|
||||
.render(self.theme, &*self.env.lock_users(), self.user_format)
|
||||
}
|
||||
Column::Group => file.group().render(
|
||||
self.theme,
|
||||
&*self.env.lock_users(),
|
||||
self.user_format,
|
||||
self.group_format,
|
||||
),
|
||||
#[cfg(unix)]
|
||||
Column::SecurityContext => file.security_context().render(self.theme),
|
||||
Column::GitStatus => self.git_status(file).render(self.theme),
|
||||
|
|
Loading…
Reference in a new issue