mirror of
https://github.com/eza-community/eza.git
synced 2026-10-12 02:13:29 +00:00
chore: replace #[allow(unused)] by #[cfg(unix)] when appropriate
Biggest change is splitting platform-specific code from permissions.rs (similarly to flags.rs in the same directory).
This commit is contained in:
+10
-7
@@ -21,18 +21,19 @@
|
||||
#![allow(clippy::struct_excessive_bools)]
|
||||
|
||||
/// The type of a file’s group ID.
|
||||
#[cfg(unix)]
|
||||
pub type gid_t = u32;
|
||||
|
||||
/// The type of a file’s inode.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
pub type ino_t = u64;
|
||||
|
||||
/// The type of a file’s number of links.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
pub type nlink_t = u64;
|
||||
|
||||
/// The type of a file’s user ID.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
pub type uid_t = u32;
|
||||
|
||||
/// The type of user file flags
|
||||
@@ -68,6 +69,7 @@ impl Type {
|
||||
/// The file’s Unix permission bitfield, with one entry per bit.
|
||||
#[derive(Copy, Clone)]
|
||||
#[rustfmt::skip]
|
||||
#[cfg(unix)]
|
||||
pub struct Permissions {
|
||||
pub user_read: bool,
|
||||
pub user_write: bool,
|
||||
@@ -116,6 +118,7 @@ pub struct PermissionsPlus {
|
||||
|
||||
/// The permissions encoded as octal values
|
||||
#[derive(Copy, Clone)]
|
||||
#[cfg(unix)]
|
||||
pub struct OctalPermissions {
|
||||
pub permissions: Permissions,
|
||||
}
|
||||
@@ -126,7 +129,7 @@ pub struct OctalPermissions {
|
||||
/// multiple directories. However, it’s rare (but occasionally useful!) for a
|
||||
/// regular file to have a link count greater than 1, so we highlight the
|
||||
/// block count specifically for this case.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Links {
|
||||
/// The actual link count.
|
||||
@@ -139,7 +142,7 @@ pub struct Links {
|
||||
/// A file’s inode. Every directory entry on a Unix filesystem has an inode,
|
||||
/// including directories and links, so this is applicable to everything exa
|
||||
/// can deal with.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Inode(pub ino_t);
|
||||
|
||||
@@ -156,12 +159,12 @@ pub enum Blocksize {
|
||||
|
||||
/// The ID of the user that owns a file. This will only ever be a number;
|
||||
/// looking up the username is done in the `display` module.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct User(pub uid_t);
|
||||
|
||||
/// The ID of the group that a file belongs to.
|
||||
#[allow(unused)]
|
||||
#[cfg(unix)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Group(pub gid_t);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ pub struct MountedFs {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||
pub enum Error {
|
||||
#[cfg(target_os = "macos")]
|
||||
GetFSStatError(i32),
|
||||
@@ -35,18 +35,18 @@ pub enum Error {
|
||||
IOError(std::io::Error),
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// Allow unreachable_patterns for windows build
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
#[cfg(target_os = "macos")]
|
||||
Error::GetFSStatError(err) => write!(f, "getfsstat failed: {err}"),
|
||||
#[cfg(target_os = "linux")]
|
||||
Error::IOError(err) => write!(f, "failed to read /proc/mounts: {err}"),
|
||||
_ => write!(f, "Unknown error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ pub use self::links::Colours as LinksColours;
|
||||
|
||||
mod permissions;
|
||||
pub use self::permissions::{Colours as PermissionsColours, PermissionsPlusRender};
|
||||
#[cfg(unix)]
|
||||
mod permissions_unix;
|
||||
#[cfg(windows)]
|
||||
mod permissions_windows;
|
||||
|
||||
mod size;
|
||||
pub use self::size::Colours as SizeColours;
|
||||
@@ -45,6 +49,7 @@ pub use self::users::Colours as UserColours;
|
||||
#[cfg(unix)]
|
||||
pub use self::users::Render as UserRender;
|
||||
|
||||
#[cfg(unix)]
|
||||
mod octal;
|
||||
#[cfg(unix)]
|
||||
pub use self::octal::Render as OctalPermissionsRender;
|
||||
|
||||
@@ -9,7 +9,6 @@ use nu_ansi_term::Style;
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::TextCell;
|
||||
|
||||
#[allow(unused)]
|
||||
pub trait Render {
|
||||
fn render(&self, style: Style) -> TextCell;
|
||||
}
|
||||
|
||||
@@ -4,167 +4,16 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024 Christina Sørensen, eza contributors
|
||||
// SPDX-FileCopyrightText: 2014 Benjamin Sago
|
||||
// SPDX-License-Identifier: MIT
|
||||
use std::iter;
|
||||
|
||||
use nu_ansi_term::{AnsiString as ANSIString, Style};
|
||||
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::{DisplayWidth, TextCell};
|
||||
use crate::output::cell::TextCell;
|
||||
use crate::output::render::FiletypeColours;
|
||||
|
||||
use nu_ansi_term::Style;
|
||||
|
||||
pub trait PermissionsPlusRender {
|
||||
fn render<C: Colours + FiletypeColours>(&self, colours: &C) -> TextCell;
|
||||
}
|
||||
|
||||
impl PermissionsPlusRender for Option<f::PermissionsPlus> {
|
||||
#[cfg(unix)]
|
||||
fn render<C: Colours + FiletypeColours>(&self, colours: &C) -> TextCell {
|
||||
if let Some(p) = self {
|
||||
let mut chars = vec![p.file_type.render(colours)];
|
||||
let permissions = p.permissions;
|
||||
chars.extend(Some(permissions).render(colours, p.file_type.is_regular_file()));
|
||||
|
||||
if p.xattrs {
|
||||
chars.push(colours.attribute().paint("@"));
|
||||
}
|
||||
|
||||
// As these are all ASCII characters, we can guarantee that they’re
|
||||
// all going to be one character wide, and don’t need to compute the
|
||||
// cell’s display width.
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
} else {
|
||||
let chars: Vec<_> = iter::repeat_n(colours.dash().paint("-"), 10).collect();
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn render<C: Colours + FiletypeColours>(&self, colours: &C) -> TextCell {
|
||||
match self {
|
||||
Some(p) => {
|
||||
let mut chars = vec![p.attributes.render_type(colours)];
|
||||
chars.extend(p.attributes.render(colours));
|
||||
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
}
|
||||
None => TextCell {
|
||||
width: DisplayWidth::from(0),
|
||||
contents: vec![].into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub trait RenderPermissions {
|
||||
fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>>;
|
||||
}
|
||||
|
||||
impl RenderPermissions for Option<f::Permissions> {
|
||||
fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>> {
|
||||
match self {
|
||||
Some(p) => {
|
||||
let bit = |bit, chr: &'static str, style: Style| {
|
||||
if bit {
|
||||
style.paint(chr)
|
||||
} else {
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
};
|
||||
|
||||
vec![
|
||||
bit(p.user_read, "r", colours.user_read()),
|
||||
bit(p.user_write, "w", colours.user_write()),
|
||||
p.user_execute_bit(colours, is_regular_file),
|
||||
bit(p.group_read, "r", colours.group_read()),
|
||||
bit(p.group_write, "w", colours.group_write()),
|
||||
p.group_execute_bit(colours),
|
||||
bit(p.other_read, "r", colours.other_read()),
|
||||
bit(p.other_write, "w", colours.other_write()),
|
||||
p.other_execute_bit(colours),
|
||||
]
|
||||
}
|
||||
None => iter::repeat_n(colours.dash().paint("-"), 9).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl f::Permissions {
|
||||
fn user_execute_bit<C: Colours>(
|
||||
&self,
|
||||
colours: &C,
|
||||
is_regular_file: bool,
|
||||
) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.user_execute, self.setuid, is_regular_file) {
|
||||
(false, false, _) => colours.dash().paint("-"),
|
||||
(true, false, false) => colours.user_execute_other().paint("x"),
|
||||
(true, false, true) => colours.user_execute_file().paint("x"),
|
||||
(false, true, _) => colours.special_other().paint("S"),
|
||||
(true, true, false) => colours.special_other().paint("s"),
|
||||
(true, true, true) => colours.special_user_file().paint("s"),
|
||||
};
|
||||
}
|
||||
|
||||
fn group_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.group_execute, self.setgid) {
|
||||
(false, false) => colours.dash().paint("-"),
|
||||
(true, false) => colours.group_execute().paint("x"),
|
||||
(false, true) => colours.special_other().paint("S"),
|
||||
(true, true) => colours.special_other().paint("s"),
|
||||
};
|
||||
}
|
||||
|
||||
fn other_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.other_execute, self.sticky) {
|
||||
(false, false) => colours.dash().paint("-"),
|
||||
(true, false) => colours.other_execute().paint("x"),
|
||||
(false, true) => colours.special_other().paint("T"),
|
||||
(true, true) => colours.special_other().paint("t"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl f::Attributes {
|
||||
pub fn render<C: Colours + FiletypeColours>(self, colours: &C) -> Vec<ANSIString<'static>> {
|
||||
let bit = |bit, chr: &'static str, style: Style| {
|
||||
if bit {
|
||||
style.paint(chr)
|
||||
} else {
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
};
|
||||
|
||||
vec![
|
||||
bit(self.archive, "a", colours.normal()),
|
||||
bit(self.readonly, "r", colours.user_read()),
|
||||
bit(self.hidden, "h", colours.special_user_file()),
|
||||
bit(self.system, "s", colours.special_other()),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn render_type<C: Colours + FiletypeColours>(self, colours: &C) -> ANSIString<'static> {
|
||||
if self.reparse_point {
|
||||
return colours.pipe().paint("l");
|
||||
} else if self.directory {
|
||||
return colours.directory().paint("d");
|
||||
}
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Colours {
|
||||
fn dash(&self) -> Style;
|
||||
|
||||
@@ -186,162 +35,3 @@ pub trait Colours {
|
||||
|
||||
fn attribute(&self) -> Style;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use super::{Colours, RenderPermissions};
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::TextCellContents;
|
||||
|
||||
use nu_ansi_term::Color::*;
|
||||
use nu_ansi_term::Style;
|
||||
|
||||
struct TestColours;
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl Colours for TestColours {
|
||||
fn dash(&self) -> Style { Fixed(11).normal() }
|
||||
fn user_read(&self) -> Style { Fixed(101).normal() }
|
||||
fn user_write(&self) -> Style { Fixed(102).normal() }
|
||||
fn user_execute_file(&self) -> Style { Fixed(103).normal() }
|
||||
fn user_execute_other(&self) -> Style { Fixed(113).normal() }
|
||||
fn group_read(&self) -> Style { Fixed(104).normal() }
|
||||
fn group_write(&self) -> Style { Fixed(105).normal() }
|
||||
fn group_execute(&self) -> Style { Fixed(106).normal() }
|
||||
fn other_read(&self) -> Style { Fixed(107).normal() }
|
||||
fn other_write(&self) -> Style { Fixed(108).normal() }
|
||||
fn other_execute(&self) -> Style { Fixed(109).normal() }
|
||||
fn special_user_file(&self) -> Style { Fixed(110).normal() }
|
||||
fn special_other(&self) -> Style { Fixed(111).normal() }
|
||||
fn attribute(&self) -> Style { Fixed(112).normal() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negate() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
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 expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, false).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn affirm() {
|
||||
let bits = Some(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: false,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(101).paint("r"),
|
||||
Fixed(102).paint("w"),
|
||||
Fixed(103).paint("x"),
|
||||
Fixed(104).paint("r"),
|
||||
Fixed(105).paint("w"),
|
||||
Fixed(106).paint("x"),
|
||||
Fixed(107).paint("r"),
|
||||
Fixed(108).paint("w"),
|
||||
Fixed(109).paint("x"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn specials() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
user_execute: true,
|
||||
setuid: true,
|
||||
group_read: false,
|
||||
group_write: false,
|
||||
group_execute: true,
|
||||
setgid: true,
|
||||
other_read: false,
|
||||
other_write: false,
|
||||
other_execute: true,
|
||||
sticky: true,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(110).paint("s"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("s"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("t"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_specials() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
user_execute: false,
|
||||
setuid: true,
|
||||
group_read: false,
|
||||
group_write: false,
|
||||
group_execute: false,
|
||||
setgid: true,
|
||||
other_read: false,
|
||||
other_write: false,
|
||||
other_execute: false,
|
||||
sticky: true,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("S"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("S"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("T"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
// SPDX-FileCopyrightText: 2024 Christina Sørensen
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2023-2024 Christina Sørensen, eza contributors
|
||||
// SPDX-FileCopyrightText: 2014 Benjamin Sago
|
||||
// SPDX-License-Identifier: MIT
|
||||
use std::iter;
|
||||
|
||||
use super::{PermissionsColours as Colours, PermissionsPlusRender};
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::{DisplayWidth, TextCell};
|
||||
use crate::output::render::FiletypeColours;
|
||||
|
||||
use nu_ansi_term::{AnsiString as ANSIString, Style};
|
||||
|
||||
impl PermissionsPlusRender for Option<f::PermissionsPlus> {
|
||||
fn render<C: Colours + FiletypeColours>(&self, colours: &C) -> TextCell {
|
||||
if let Some(p) = self {
|
||||
let mut chars = vec![p.file_type.render(colours)];
|
||||
let permissions = p.permissions;
|
||||
chars.extend(Some(permissions).render(colours, p.file_type.is_regular_file()));
|
||||
|
||||
if p.xattrs {
|
||||
chars.push(colours.attribute().paint("@"));
|
||||
}
|
||||
|
||||
// As these are all ASCII characters, we can guarantee that they’re
|
||||
// all going to be one character wide, and don’t need to compute the
|
||||
// cell’s display width.
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
} else {
|
||||
let chars: Vec<_> = iter::repeat_n(colours.dash().paint("-"), 10).collect();
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RenderPermissions {
|
||||
fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>>;
|
||||
}
|
||||
|
||||
impl RenderPermissions for Option<f::Permissions> {
|
||||
fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>> {
|
||||
match self {
|
||||
Some(p) => {
|
||||
let bit = |bit, chr: &'static str, style: Style| {
|
||||
if bit {
|
||||
style.paint(chr)
|
||||
} else {
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
};
|
||||
|
||||
vec![
|
||||
bit(p.user_read, "r", colours.user_read()),
|
||||
bit(p.user_write, "w", colours.user_write()),
|
||||
p.user_execute_bit(colours, is_regular_file),
|
||||
bit(p.group_read, "r", colours.group_read()),
|
||||
bit(p.group_write, "w", colours.group_write()),
|
||||
p.group_execute_bit(colours),
|
||||
bit(p.other_read, "r", colours.other_read()),
|
||||
bit(p.other_write, "w", colours.other_write()),
|
||||
p.other_execute_bit(colours),
|
||||
]
|
||||
}
|
||||
None => std::iter::repeat_n(colours.dash().paint("-"), 9).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl f::Permissions {
|
||||
fn user_execute_bit<C: Colours>(
|
||||
&self,
|
||||
colours: &C,
|
||||
is_regular_file: bool,
|
||||
) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.user_execute, self.setuid, is_regular_file) {
|
||||
(false, false, _) => colours.dash().paint("-"),
|
||||
(true, false, false) => colours.user_execute_other().paint("x"),
|
||||
(true, false, true) => colours.user_execute_file().paint("x"),
|
||||
(false, true, _) => colours.special_other().paint("S"),
|
||||
(true, true, false) => colours.special_other().paint("s"),
|
||||
(true, true, true) => colours.special_user_file().paint("s"),
|
||||
};
|
||||
}
|
||||
|
||||
fn group_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.group_execute, self.setgid) {
|
||||
(false, false) => colours.dash().paint("-"),
|
||||
(true, false) => colours.group_execute().paint("x"),
|
||||
(false, true) => colours.special_other().paint("S"),
|
||||
(true, true) => colours.special_other().paint("s"),
|
||||
};
|
||||
}
|
||||
|
||||
fn other_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
#[rustfmt::skip]
|
||||
return match (self.other_execute, self.sticky) {
|
||||
(false, false) => colours.dash().paint("-"),
|
||||
(true, false) => colours.other_execute().paint("x"),
|
||||
(false, true) => colours.special_other().paint("T"),
|
||||
(true, true) => colours.special_other().paint("t"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use nu_ansi_term::Color::*;
|
||||
use nu_ansi_term::Style;
|
||||
|
||||
use super::*;
|
||||
use crate::output::cell::TextCellContents;
|
||||
|
||||
struct TestColours;
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl Colours for TestColours {
|
||||
fn dash(&self) -> Style { Fixed(11).normal() }
|
||||
fn user_read(&self) -> Style { Fixed(101).normal() }
|
||||
fn user_write(&self) -> Style { Fixed(102).normal() }
|
||||
fn user_execute_file(&self) -> Style { Fixed(103).normal() }
|
||||
fn user_execute_other(&self) -> Style { Fixed(113).normal() }
|
||||
fn group_read(&self) -> Style { Fixed(104).normal() }
|
||||
fn group_write(&self) -> Style { Fixed(105).normal() }
|
||||
fn group_execute(&self) -> Style { Fixed(106).normal() }
|
||||
fn other_read(&self) -> Style { Fixed(107).normal() }
|
||||
fn other_write(&self) -> Style { Fixed(108).normal() }
|
||||
fn other_execute(&self) -> Style { Fixed(109).normal() }
|
||||
fn special_user_file(&self) -> Style { Fixed(110).normal() }
|
||||
fn special_other(&self) -> Style { Fixed(111).normal() }
|
||||
fn attribute(&self) -> Style { Fixed(112).normal() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn negate() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
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 expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, false).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn affirm() {
|
||||
let bits = Some(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: false,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(101).paint("r"),
|
||||
Fixed(102).paint("w"),
|
||||
Fixed(103).paint("x"),
|
||||
Fixed(104).paint("r"),
|
||||
Fixed(105).paint("w"),
|
||||
Fixed(106).paint("x"),
|
||||
Fixed(107).paint("r"),
|
||||
Fixed(108).paint("w"),
|
||||
Fixed(109).paint("x"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn specials() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
user_execute: true,
|
||||
setuid: true,
|
||||
group_read: false,
|
||||
group_write: false,
|
||||
group_execute: true,
|
||||
setgid: true,
|
||||
other_read: false,
|
||||
other_write: false,
|
||||
other_execute: true,
|
||||
sticky: true,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(110).paint("s"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("s"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("t"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_specials() {
|
||||
let bits = Some(f::Permissions {
|
||||
user_read: false,
|
||||
user_write: false,
|
||||
user_execute: false,
|
||||
setuid: true,
|
||||
group_read: false,
|
||||
group_write: false,
|
||||
group_execute: false,
|
||||
setgid: true,
|
||||
other_read: false,
|
||||
other_write: false,
|
||||
other_execute: false,
|
||||
sticky: true,
|
||||
});
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("S"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("S"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(11).paint("-"),
|
||||
Fixed(111).paint("T"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// SPDX-FileCopyrightText: 2024 Christina Sørensen
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2023-2024 Christina Sørensen, eza contributors
|
||||
// SPDX-FileCopyrightText: 2014 Benjamin Sago
|
||||
// SPDX-License-Identifier: MIT
|
||||
use crate::fs::fields as f;
|
||||
use crate::output::cell::{DisplayWidth, TextCell};
|
||||
use crate::output::render::FiletypeColours;
|
||||
|
||||
use super::{PermissionsColours as Colours, PermissionsPlusRender};
|
||||
|
||||
use nu_ansi_term::{AnsiString as ANSIString, Style};
|
||||
|
||||
impl PermissionsPlusRender for Option<f::PermissionsPlus> {
|
||||
fn render<C: Colours + FiletypeColours>(&self, colours: &C) -> TextCell {
|
||||
match self {
|
||||
Some(p) => {
|
||||
let mut chars = vec![p.attributes.render_type(colours)];
|
||||
chars.extend(p.attributes.render(colours));
|
||||
|
||||
TextCell {
|
||||
width: DisplayWidth::from(chars.len()),
|
||||
contents: chars.into(),
|
||||
}
|
||||
}
|
||||
None => TextCell {
|
||||
width: DisplayWidth::from(0),
|
||||
contents: vec![].into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl f::Attributes {
|
||||
pub fn render<C: Colours + FiletypeColours>(self, colours: &C) -> Vec<ANSIString<'static>> {
|
||||
let bit = |bit, chr: &'static str, style: Style| {
|
||||
if bit {
|
||||
style.paint(chr)
|
||||
} else {
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
};
|
||||
|
||||
vec![
|
||||
bit(self.archive, "a", colours.normal()),
|
||||
bit(self.readonly, "r", colours.user_read()),
|
||||
bit(self.hidden, "h", colours.special_user_file()),
|
||||
bit(self.system, "s", colours.special_other()),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn render_type<C: Colours + FiletypeColours>(self, colours: &C) -> ANSIString<'static> {
|
||||
if self.reparse_point {
|
||||
return colours.pipe().paint("l");
|
||||
} else if self.directory {
|
||||
return colours.directory().paint("d");
|
||||
}
|
||||
colours.dash().paint("-")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user