mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-26 05:47:32 +00:00
Add --octal-permissions argument
Using --octal_permissions will insert another column before the existing permissions where permissions are encoded using octal values as requested in #316
This commit is contained in:
parent
78ba0b8973
commit
16046d57de
@ -87,6 +87,11 @@ pub struct PermissionsPlus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// The permissions encoded as octal values
|
||||||
|
pub struct OctalPermissions {
|
||||||
|
pub permissions: Permissions,
|
||||||
|
}
|
||||||
|
|
||||||
/// A file’s number of hard links on the filesystem.
|
/// A file’s number of hard links on the filesystem.
|
||||||
///
|
///
|
||||||
/// Under Unix, a file can exist on the filesystem only once but appear in
|
/// Under Unix, a file can exist on the filesystem only once but appear in
|
||||||
|
@ -60,8 +60,9 @@ pub static NO_USER: Arg = Arg { short: None, long: "no-user", takes_value: Takes
|
|||||||
pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: TakesValue::Forbidden };
|
pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: TakesValue::Forbidden };
|
||||||
|
|
||||||
// optional feature options
|
// optional feature options
|
||||||
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
|
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
|
||||||
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
|
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
|
||||||
|
pub static OCTAL: Arg = Arg { short: None, long: "octal-permissions", takes_value: TakesValue::Forbidden };
|
||||||
|
|
||||||
|
|
||||||
pub static ALL_ARGS: Args = Args(&[
|
pub static ALL_ARGS: Args = Args(&[
|
||||||
@ -77,5 +78,5 @@ pub static ALL_ARGS: Args = Args(&[
|
|||||||
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
|
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
|
||||||
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME,
|
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME,
|
||||||
|
|
||||||
&GIT, &EXTENDED,
|
&GIT, &EXTENDED, &OCTAL
|
||||||
]);
|
]);
|
||||||
|
@ -56,8 +56,9 @@ LONG VIEW OPTIONS
|
|||||||
--no-user suppress the user field
|
--no-user suppress the user field
|
||||||
--no-time suppress the time field"##;
|
--no-time suppress the time field"##;
|
||||||
|
|
||||||
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
|
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
|
||||||
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
|
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
|
||||||
|
static OCTAL_HELP: &str = r##" --octal-permissions list each file's permission in octal format"##;
|
||||||
|
|
||||||
|
|
||||||
/// All the information needed to display the help text, which depends
|
/// All the information needed to display the help text, which depends
|
||||||
@ -119,6 +120,8 @@ impl fmt::Display for HelpString {
|
|||||||
write!(f, "\n{}", EXTENDED_HELP)?;
|
write!(f, "\n{}", EXTENDED_HELP)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write!(f, "\n{}", OCTAL_HELP)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,12 +228,13 @@ impl Columns {
|
|||||||
let group = matches.has(&flags::GROUP)?;
|
let group = matches.has(&flags::GROUP)?;
|
||||||
let inode = matches.has(&flags::INODE)?;
|
let inode = matches.has(&flags::INODE)?;
|
||||||
let links = matches.has(&flags::LINKS)?;
|
let links = matches.has(&flags::LINKS)?;
|
||||||
|
let octal = matches.has(&flags::OCTAL)?;
|
||||||
|
|
||||||
let permissions = !matches.has(&flags::NO_PERMISSIONS)?;
|
let permissions = !matches.has(&flags::NO_PERMISSIONS)?;
|
||||||
let filesize = !matches.has(&flags::NO_FILESIZE)?;
|
let filesize = !matches.has(&flags::NO_FILESIZE)?;
|
||||||
let user = !matches.has(&flags::NO_USER)?;
|
let user = !matches.has(&flags::NO_USER)?;
|
||||||
|
|
||||||
Ok(Columns { time_types, git, blocks, group, inode, links, permissions, filesize, user })
|
Ok(Columns { time_types, git, octal, blocks, group, inode, links, permissions, filesize, user })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,3 +28,6 @@ pub use self::times::Render as TimeRender;
|
|||||||
|
|
||||||
mod users;
|
mod users;
|
||||||
pub use self::users::Colours as UserColours;
|
pub use self::users::Colours as UserColours;
|
||||||
|
|
||||||
|
mod octal;
|
||||||
|
// octal uses just one colour
|
||||||
|
116
src/output/render/octal.rs
Normal file
116
src/output/render/octal.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
use ansi_term::Style;
|
||||||
|
|
||||||
|
use crate::output::cell::TextCell;
|
||||||
|
use crate::fs::fields as f;
|
||||||
|
|
||||||
|
impl f::OctalPermissions {
|
||||||
|
fn bits_to_octal(r: bool, w: bool, x: bool) -> u8 {
|
||||||
|
(r as u8) * 4 + (w as u8) * 2 + (x as u8) * 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, style: Style) -> TextCell {
|
||||||
|
|
||||||
|
let perm = &self.permissions;
|
||||||
|
let octal_sticky = Self::bits_to_octal(perm.setuid, perm.setgid, perm.sticky);
|
||||||
|
let octal_owner = Self::bits_to_octal(perm.user_read, perm.user_write, perm.user_execute);
|
||||||
|
let octal_group = Self::bits_to_octal(perm.group_read, perm.group_write, perm.group_execute);
|
||||||
|
let octal_other = Self::bits_to_octal(perm.other_read, perm.other_write, perm.other_execute);
|
||||||
|
|
||||||
|
TextCell::paint(style, format!("{}{}{}{}", octal_sticky, octal_owner, octal_group, octal_other))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod test {
|
||||||
|
use crate::output::cell::TextCell;
|
||||||
|
use crate::fs::fields as f;
|
||||||
|
|
||||||
|
use ansi_term::Colour::*;
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normal_folder() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: true, setuid: false,
|
||||||
|
group_read: true, group_write: false, group_execute: true, setgid: false,
|
||||||
|
other_read: true, other_write: false, other_execute: true, sticky: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "0755");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normal_file() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: false, setuid: false,
|
||||||
|
group_read: true, group_write: false, group_execute: false, setgid: false,
|
||||||
|
other_read: true, other_write: false, other_execute: false, sticky: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "0644");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn secret_file() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: false, setuid: false,
|
||||||
|
group_read: false, group_write: false, group_execute: false, setgid: false,
|
||||||
|
other_read: false, other_write: false, other_execute: false, sticky: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "0600");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sticky1() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: true, setuid: true,
|
||||||
|
group_read: true, group_write: true, group_execute: true, setgid: false,
|
||||||
|
other_read: true, other_write: true, other_execute: true, sticky: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "4777");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sticky2() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: true, setuid: false,
|
||||||
|
group_read: true, group_write: true, group_execute: true, setgid: true,
|
||||||
|
other_read: true, other_write: true, other_execute: true, sticky: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "2777");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sticky3() {
|
||||||
|
let bits = f::Permissions {
|
||||||
|
user_read: true, user_write: true, user_execute: true, setuid: false,
|
||||||
|
group_read: true, group_write: true, group_execute: true, setgid: false,
|
||||||
|
other_read: true, other_write: true, other_execute: true, sticky: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let octal = f::OctalPermissions{ permissions: bits };
|
||||||
|
|
||||||
|
let expected = TextCell::paint_str(Purple.bold(), "1777");
|
||||||
|
assert_eq!(expected, octal.render(Purple.bold()).into());
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@ pub struct Columns {
|
|||||||
pub blocks: bool,
|
pub blocks: bool,
|
||||||
pub group: bool,
|
pub group: bool,
|
||||||
pub git: bool,
|
pub git: bool,
|
||||||
|
pub octal: bool,
|
||||||
|
|
||||||
// Defaults to true:
|
// Defaults to true:
|
||||||
pub permissions: bool,
|
pub permissions: bool,
|
||||||
@ -64,6 +65,10 @@ impl Columns {
|
|||||||
columns.push(Column::Inode);
|
columns.push(Column::Inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.octal {
|
||||||
|
columns.push(Column::Octal);
|
||||||
|
}
|
||||||
|
|
||||||
if self.permissions {
|
if self.permissions {
|
||||||
columns.push(Column::Permissions);
|
columns.push(Column::Permissions);
|
||||||
}
|
}
|
||||||
@ -125,6 +130,7 @@ pub enum Column {
|
|||||||
HardLinks,
|
HardLinks,
|
||||||
Inode,
|
Inode,
|
||||||
GitStatus,
|
GitStatus,
|
||||||
|
Octal,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Each column can pick its own **Alignment**. Usually, numbers are
|
/// Each column can pick its own **Alignment**. Usually, numbers are
|
||||||
@ -161,6 +167,7 @@ impl Column {
|
|||||||
Column::HardLinks => "Links",
|
Column::HardLinks => "Links",
|
||||||
Column::Inode => "inode",
|
Column::Inode => "inode",
|
||||||
Column::GitStatus => "Git",
|
Column::GitStatus => "Git",
|
||||||
|
Column::Octal => "Octal",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,6 +357,12 @@ impl<'a, 'f> Table<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn octal_permissions(&self, file: &File) -> f::OctalPermissions {
|
||||||
|
f::OctalPermissions {
|
||||||
|
permissions: file.permissions(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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::*;
|
||||||
|
|
||||||
@ -362,6 +375,7 @@ impl<'a, 'f> Table<'a> {
|
|||||||
Column::User => file.user().render(self.colours, &*self.env.lock_users()),
|
Column::User => file.user().render(self.colours, &*self.env.lock_users()),
|
||||||
Column::Group => file.group().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::GitStatus => self.git_status(file).render(self.colours),
|
||||||
|
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),
|
||||||
|
@ -23,6 +23,7 @@ pub struct Colours {
|
|||||||
pub inode: Style,
|
pub inode: Style,
|
||||||
pub blocks: Style,
|
pub blocks: Style,
|
||||||
pub header: Style,
|
pub header: Style,
|
||||||
|
pub octal: Style,
|
||||||
|
|
||||||
pub symlink_path: Style,
|
pub symlink_path: Style,
|
||||||
pub control_char: Style,
|
pub control_char: Style,
|
||||||
@ -174,6 +175,7 @@ impl Colours {
|
|||||||
date: Blue.normal(),
|
date: Blue.normal(),
|
||||||
inode: Purple.normal(),
|
inode: Purple.normal(),
|
||||||
blocks: Cyan.normal(),
|
blocks: Cyan.normal(),
|
||||||
|
octal: Purple.normal(),
|
||||||
header: Style::default().underline(),
|
header: Style::default().underline(),
|
||||||
|
|
||||||
symlink_path: Cyan.normal(),
|
symlink_path: Cyan.normal(),
|
||||||
|
Loading…
Reference in New Issue
Block a user