2017-08-20 19:29:23 +00:00
|
|
|
|
use ansi_term::{ANSIString, Style};
|
|
|
|
|
|
2017-05-20 20:21:17 +00:00
|
|
|
|
use fs::fields as f;
|
|
|
|
|
use output::cell::{TextCell, DisplayWidth};
|
2017-08-20 19:29:23 +00:00
|
|
|
|
use output::render::FiletypeColours;
|
2017-05-20 20:21:17 +00:00
|
|
|
|
|
|
|
|
|
|
2017-05-21 09:48:27 +00:00
|
|
|
|
impl f::PermissionsPlus {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
pub fn render<C: Colours+FiletypeColours>(&self, colours: &C) -> TextCell {
|
2017-05-21 09:48:27 +00:00
|
|
|
|
let mut chars = vec![ self.file_type.render(colours) ];
|
2017-05-30 14:31:24 +00:00
|
|
|
|
chars.extend(self.permissions.render(colours, self.file_type.is_regular_file()));
|
2017-05-21 09:48:27 +00:00
|
|
|
|
|
|
|
|
|
if self.xattrs {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
chars.push(colours.attribute().paint("@"));
|
2017-05-21 09:48:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2017-05-21 09:51:42 +00:00
|
|
|
|
width: DisplayWidth::from(chars.len()),
|
2017-05-21 09:48:27 +00:00
|
|
|
|
contents: chars.into(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
|
|
|
|
|
|
2017-05-21 09:48:27 +00:00
|
|
|
|
impl f::Permissions {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
pub fn render<C: Colours>(&self, colours: &C, is_regular_file: bool) -> Vec<ANSIString<'static>> {
|
|
|
|
|
|
2017-05-21 09:48:27 +00:00
|
|
|
|
let bit = |bit, chr: &'static str, style: Style| {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
if bit { style.paint(chr) } else { colours.dash().paint("-") }
|
2017-05-21 09:48:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
vec![
|
2017-08-20 19:29:23 +00:00
|
|
|
|
bit(self.user_read, "r", colours.user_read()),
|
|
|
|
|
bit(self.user_write, "w", colours.user_write()),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
self.user_execute_bit(colours, is_regular_file),
|
2017-08-20 19:29:23 +00:00
|
|
|
|
bit(self.group_read, "r", colours.group_read()),
|
|
|
|
|
bit(self.group_write, "w", colours.group_write()),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
self.group_execute_bit(colours),
|
2017-08-20 19:29:23 +00:00
|
|
|
|
bit(self.other_read, "r", colours.other_read()),
|
|
|
|
|
bit(self.other_write, "w", colours.other_write()),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
self.other_execute_bit(colours)
|
2017-05-21 09:48:27 +00:00
|
|
|
|
]
|
|
|
|
|
}
|
2017-05-30 14:31:24 +00:00
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
fn user_execute_bit<C: Colours>(&self, colours: &C, is_regular_file: bool) -> ANSIString<'static> {
|
2017-05-30 14:31:24 +00:00
|
|
|
|
match (self.user_execute, self.setuid, is_regular_file) {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
(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"),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
fn group_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
2017-05-30 14:31:24 +00:00
|
|
|
|
match (self.group_execute, self.setgid) {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
(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"),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
fn other_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
2017-05-30 14:31:24 +00:00
|
|
|
|
match (self.other_execute, self.sticky) {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
(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"),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-20 20:21:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-20 20:49:00 +00:00
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
pub trait Colours {
|
|
|
|
|
fn dash(&self) -> Style;
|
|
|
|
|
|
|
|
|
|
fn user_read(&self) -> Style;
|
|
|
|
|
fn user_write(&self) -> Style;
|
|
|
|
|
fn user_execute_file(&self) -> Style;
|
|
|
|
|
fn user_execute_other(&self) -> Style;
|
|
|
|
|
|
|
|
|
|
fn group_read(&self) -> Style;
|
|
|
|
|
fn group_write(&self) -> Style;
|
|
|
|
|
fn group_execute(&self) -> Style;
|
|
|
|
|
|
|
|
|
|
fn other_read(&self) -> Style;
|
|
|
|
|
fn other_write(&self) -> Style;
|
|
|
|
|
fn other_execute(&self) -> Style;
|
|
|
|
|
|
|
|
|
|
fn special_user_file(&self) -> Style;
|
|
|
|
|
fn special_other(&self) -> Style;
|
|
|
|
|
|
|
|
|
|
fn attribute(&self) -> Style;
|
|
|
|
|
}
|
2017-05-20 20:49:00 +00:00
|
|
|
|
|
2017-05-20 20:21:17 +00:00
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
#[allow(unused_results)]
|
|
|
|
|
pub mod test {
|
2017-08-20 19:29:23 +00:00
|
|
|
|
use super::Colours;
|
2017-05-21 09:48:27 +00:00
|
|
|
|
use output::cell::TextCellContents;
|
2017-05-20 20:21:17 +00:00
|
|
|
|
use fs::fields as f;
|
|
|
|
|
|
|
|
|
|
use ansi_term::Colour::*;
|
2017-08-20 19:29:23 +00:00
|
|
|
|
use ansi_term::Style;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct TestColours;
|
|
|
|
|
|
|
|
|
|
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() }
|
|
|
|
|
}
|
2017-05-20 20:21:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
2017-05-21 09:48:27 +00:00
|
|
|
|
fn negate() {
|
|
|
|
|
let bits = f::Permissions {
|
2017-05-30 14:29:29 +00:00
|
|
|
|
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,
|
2017-05-21 09:48:27 +00:00
|
|
|
|
};
|
2017-05-20 20:21:17 +00:00
|
|
|
|
|
2017-05-21 09:48:27 +00:00
|
|
|
|
let expected = TextCellContents::from(vec![
|
2017-05-30 14:31:24 +00:00
|
|
|
|
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("-"),
|
2017-05-21 09:48:27 +00:00
|
|
|
|
]);
|
2017-05-20 20:21:17 +00:00
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
assert_eq!(expected, bits.render(&TestColours, false).into())
|
2017-05-20 20:21:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
2017-05-21 09:48:27 +00:00
|
|
|
|
fn affirm() {
|
|
|
|
|
let bits = f::Permissions {
|
2017-05-30 14:29:29 +00:00
|
|
|
|
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,
|
2017-05-21 09:48:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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"),
|
|
|
|
|
]);
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
assert_eq!(expected, bits.render(&TestColours, true).into())
|
2017-05-30 14:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn specials() {
|
|
|
|
|
let bits = 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![
|
2017-08-20 19:29:23 +00:00
|
|
|
|
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"),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
]);
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
assert_eq!(expected, bits.render(&TestColours, true).into())
|
2017-05-30 14:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn extra_specials() {
|
|
|
|
|
let bits = 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![
|
2017-08-20 19:29:23 +00:00
|
|
|
|
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"),
|
2017-05-30 14:31:24 +00:00
|
|
|
|
]);
|
|
|
|
|
|
2017-08-20 19:29:23 +00:00
|
|
|
|
assert_eq!(expected, bits.render(&TestColours, true).into())
|
2017-05-20 20:21:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|