|
|
@@ -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());
|
|
|
- }
|
|
|
-}
|