|
|
@@ -1,51 +1,79 @@
|
|
|
+use std::iter;
|
|
|
+
|
|
|
use ansi_term::{ANSIString, Style};
|
|
|
|
|
|
use crate::fs::fields as f;
|
|
|
use crate::output::cell::{TextCell, DisplayWidth};
|
|
|
use crate::output::render::FiletypeColours;
|
|
|
|
|
|
+pub trait PermissionsPlusRender {
|
|
|
+ fn render<C: Colours+FiletypeColours>(&self, colours: &C) -> TextCell;
|
|
|
+}
|
|
|
|
|
|
-impl f::PermissionsPlus {
|
|
|
- pub fn render<C: Colours+FiletypeColours>(&self, colours: &C) -> TextCell {
|
|
|
- let mut chars = vec![ self.file_type.render(colours) ];
|
|
|
- chars.extend(self.permissions.render(colours, self.file_type.is_regular_file()));
|
|
|
-
|
|
|
- if self.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(),
|
|
|
+impl PermissionsPlusRender for Option<f::PermissionsPlus> {
|
|
|
+ fn render<C: Colours+FiletypeColours>(&self, colours: &C) -> TextCell {
|
|
|
+ match self {
|
|
|
+ Some(p) => {
|
|
|
+ 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(),
|
|
|
+ }
|
|
|
+ },
|
|
|
+ None => {
|
|
|
+ let chars: Vec<_> = iter::repeat(colours.dash().paint("-")).take(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 f::Permissions {
|
|
|
- pub fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>> {
|
|
|
-
|
|
|
- let bit = |bit, chr: &'static str, style: Style| {
|
|
|
- if bit { style.paint(chr) }
|
|
|
- else { colours.dash().paint("-") }
|
|
|
- };
|
|
|
-
|
|
|
- vec![
|
|
|
- bit(self.user_read, "r", colours.user_read()),
|
|
|
- bit(self.user_write, "w", colours.user_write()),
|
|
|
- self.user_execute_bit(colours, is_regular_file),
|
|
|
- bit(self.group_read, "r", colours.group_read()),
|
|
|
- bit(self.group_write, "w", colours.group_write()),
|
|
|
- self.group_execute_bit(colours),
|
|
|
- bit(self.other_read, "r", colours.other_read()),
|
|
|
- bit(self.other_write, "w", colours.other_write()),
|
|
|
- self.other_execute_bit(colours)
|
|
|
- ]
|
|
|
+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(colours.dash().paint("-")).take(9).collect()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
+impl f::Permissions {
|
|
|
fn user_execute_bit<C: Colours>(&self, colours: &C, is_regular_file: bool) -> ANSIString<'static> {
|
|
|
match (self.user_execute, self.setuid, is_regular_file) {
|
|
|
(false, false, _) => colours.dash().paint("-"),
|
|
|
@@ -103,7 +131,7 @@ pub trait Colours {
|
|
|
#[cfg(test)]
|
|
|
#[allow(unused_results)]
|
|
|
pub mod test {
|
|
|
- use super::Colours;
|
|
|
+ use super::{Colours, RenderPermissions};
|
|
|
use crate::output::cell::TextCellContents;
|
|
|
use crate::fs::fields as f;
|
|
|
|
|
|
@@ -133,11 +161,11 @@ pub mod test {
|
|
|
|
|
|
#[test]
|
|
|
fn negate() {
|
|
|
- let bits = f::Permissions {
|
|
|
+ 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("-"),
|
|
|
@@ -151,11 +179,11 @@ pub mod test {
|
|
|
|
|
|
#[test]
|
|
|
fn affirm() {
|
|
|
- let bits = f::Permissions {
|
|
|
+ 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"),
|
|
|
@@ -169,11 +197,11 @@ pub mod test {
|
|
|
|
|
|
#[test]
|
|
|
fn specials() {
|
|
|
- let bits = f::Permissions {
|
|
|
+ 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"),
|
|
|
@@ -187,11 +215,11 @@ pub mod test {
|
|
|
|
|
|
#[test]
|
|
|
fn extra_specials() {
|
|
|
- let bits = f::Permissions {
|
|
|
+ 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"),
|