mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-22 20:15:11 +00:00
Reverse what knows how to render a cell
This commit adds many traits, all named ‘Colours’, to the code. Each one asks for a colour needed to render a cell: the number of links asks for colours for the number and the multi-link-file special case; the file size asks for number, unit, punctuation, and device ID colours, or it can do a scale with its own colours, however it wants. This is a step towards LS_COLORS compatibility, believe it or not. If a text cell in a column doesn’t depend on Colours to render itself, then the source of the colours is open-ended. I am glad to have not needed any test changes here.
This commit is contained in:
parent
3405db1f4b
commit
9b24649d68
@ -1,6 +1,8 @@
|
||||
use ansi_term::Style;
|
||||
use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed};
|
||||
|
||||
use output::render;
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
pub struct Colours {
|
||||
@ -202,27 +204,93 @@ impl Colours {
|
||||
control_char: Red.normal(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_size(&self, size: u64) -> Style {
|
||||
if self.scale {
|
||||
if size < 1024 {
|
||||
self.size.scale_byte
|
||||
}
|
||||
else if size < 1024 * 1024 {
|
||||
self.size.scale_kilo
|
||||
}
|
||||
else if size < 1024 * 1024 * 1024 {
|
||||
self.size.scale_mega
|
||||
}
|
||||
else if size < 1024 * 1024 * 1024 * 1024 {
|
||||
self.size.scale_giga
|
||||
}
|
||||
else {
|
||||
self.size.scale_huge
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.size.numbers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl render::BlocksColours for Colours {
|
||||
fn block_count(&self) -> Style { self.blocks }
|
||||
fn no_blocks(&self) -> Style { self.punctuation }
|
||||
}
|
||||
|
||||
impl render::FiletypeColours for Colours {
|
||||
fn normal(&self) -> Style { self.filetypes.normal }
|
||||
fn directory(&self) -> Style { self.filetypes.directory }
|
||||
fn pipe(&self) -> Style { self.filetypes.pipe }
|
||||
fn symlink(&self) -> Style { self.filetypes.symlink }
|
||||
fn device(&self) -> Style { self.filetypes.device }
|
||||
fn socket(&self) -> Style { self.filetypes.socket }
|
||||
fn special(&self) -> Style { self.filetypes.special }
|
||||
}
|
||||
|
||||
impl render::GitColours for Colours {
|
||||
fn not_modified(&self) -> Style { self.punctuation }
|
||||
fn new(&self) -> Style { self.git.new }
|
||||
fn modified(&self) -> Style { self.git.modified }
|
||||
fn deleted(&self) -> Style { self.git.deleted }
|
||||
fn renamed(&self) -> Style { self.git.renamed }
|
||||
fn type_change(&self) -> Style { self.git.typechange }
|
||||
}
|
||||
|
||||
impl render::GroupColours for Colours {
|
||||
fn yours(&self) -> Style { self.users.group_yours }
|
||||
fn not_yours(&self) -> Style { self.users.group_not_yours }
|
||||
}
|
||||
|
||||
impl render::LinksColours for Colours {
|
||||
fn normal(&self) -> Style { self.links.normal }
|
||||
fn multi_link_file(&self) -> Style { self.links.multi_link_file }
|
||||
}
|
||||
|
||||
impl render::PermissionsColours for Colours {
|
||||
fn dash(&self) -> Style { self.punctuation }
|
||||
fn user_read(&self) -> Style { self.perms.user_read }
|
||||
fn user_write(&self) -> Style { self.perms.user_write }
|
||||
fn user_execute_file(&self) -> Style { self.perms.user_execute_file }
|
||||
fn user_execute_other(&self) -> Style { self.perms.user_execute_other }
|
||||
fn group_read(&self) -> Style { self.perms.group_read }
|
||||
fn group_write(&self) -> Style { self.perms.group_write }
|
||||
fn group_execute(&self) -> Style { self.perms.group_execute }
|
||||
fn other_read(&self) -> Style { self.perms.other_read }
|
||||
fn other_write(&self) -> Style { self.perms.other_write }
|
||||
fn other_execute(&self) -> Style { self.perms.other_execute }
|
||||
fn special_user_file(&self) -> Style { self.perms.special_user_file }
|
||||
fn special_other(&self) -> Style { self.perms.special_other }
|
||||
fn attribute(&self) -> Style { self.perms.attribute }
|
||||
}
|
||||
|
||||
impl render::SizeColours for Colours {
|
||||
fn size(&self, size: u64) -> Style {
|
||||
if self.scale {
|
||||
if size < 1024 {
|
||||
self.size.scale_byte
|
||||
}
|
||||
else if size < 1024 * 1024 {
|
||||
self.size.scale_kilo
|
||||
}
|
||||
else if size < 1024 * 1024 * 1024 {
|
||||
self.size.scale_mega
|
||||
}
|
||||
else if size < 1024 * 1024 * 1024 * 1024 {
|
||||
self.size.scale_giga
|
||||
}
|
||||
else {
|
||||
self.size.scale_huge
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.size.numbers
|
||||
}
|
||||
}
|
||||
|
||||
fn unit(&self) -> Style { self.size.unit }
|
||||
fn no_size(&self) -> Style { self.punctuation }
|
||||
fn major(&self) -> Style { self.size.major }
|
||||
fn comma(&self) -> Style { self.punctuation }
|
||||
fn minor(&self) -> Style { self.size.minor }
|
||||
}
|
||||
|
||||
impl render::UserColours for Colours {
|
||||
fn you(&self) -> Style { self.users.user_you }
|
||||
fn someone_else(&self) -> Style { self.users.user_someone_else }
|
||||
}
|
||||
|
||||
|
@ -1,44 +1,57 @@
|
||||
use ansi_term::Style;
|
||||
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
use fs::fields as f;
|
||||
|
||||
|
||||
impl f::Blocks {
|
||||
pub fn render(&self, colours: &Colours) -> TextCell {
|
||||
pub fn render<C: Colours>(&self, colours: &C) -> TextCell {
|
||||
match *self {
|
||||
f::Blocks::Some(ref blk) => TextCell::paint(colours.blocks, blk.to_string()),
|
||||
f::Blocks::None => TextCell::blank(colours.punctuation),
|
||||
f::Blocks::Some(ref blk) => TextCell::paint(colours.block_count(), blk.to_string()),
|
||||
f::Blocks::None => TextCell::blank(colours.no_blocks()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn block_count(&self) -> Style;
|
||||
fn no_blocks(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use ansi_term::Style;
|
||||
use ansi_term::Colour::*;
|
||||
|
||||
use super::Colours;
|
||||
use output::cell::TextCell;
|
||||
use fs::fields as f;
|
||||
|
||||
use ansi_term::Colour::*;
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn block_count(&self) -> Style { Red.blink() }
|
||||
fn no_blocks(&self) -> Style { Green.italic() }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn blocklessness() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Green.italic();
|
||||
|
||||
let blox = f::Blocks::None;
|
||||
let expected = TextCell::blank(Green.italic());
|
||||
assert_eq!(expected, blox.render(&colours).into());
|
||||
|
||||
assert_eq!(expected, blox.render(&TestColours).into());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn blockfulity() {
|
||||
let mut colours = Colours::default();
|
||||
colours.blocks = Red.blink();
|
||||
|
||||
let blox = f::Blocks::Some(3005);
|
||||
let expected = TextCell::paint_str(Red.blink(), "3005");
|
||||
assert_eq!(expected, blox.render(&colours).into());
|
||||
|
||||
assert_eq!(expected, blox.render(&TestColours).into());
|
||||
}
|
||||
}
|
||||
|
30
src/output/render/filetype.rs
Normal file
30
src/output/render/filetype.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use ansi_term::{ANSIString, Style};
|
||||
|
||||
use fs::fields as f;
|
||||
|
||||
|
||||
impl f::Type {
|
||||
pub fn render<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
match *self {
|
||||
f::Type::File => colours.normal().paint("."),
|
||||
f::Type::Directory => colours.directory().paint("d"),
|
||||
f::Type::Pipe => colours.pipe().paint("|"),
|
||||
f::Type::Link => colours.symlink().paint("l"),
|
||||
f::Type::CharDevice => colours.device().paint("c"),
|
||||
f::Type::BlockDevice => colours.device().paint("b"),
|
||||
f::Type::Socket => colours.socket().paint("s"),
|
||||
f::Type::Special => colours.special().paint("?"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn normal(&self) -> Style;
|
||||
fn directory(&self) -> Style;
|
||||
fn pipe(&self) -> Style;
|
||||
fn symlink(&self) -> Style;
|
||||
fn device(&self) -> Style;
|
||||
fn socket(&self) -> Style;
|
||||
fn special(&self) -> Style;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
use ansi_term::ANSIString;
|
||||
use ansi_term::{ANSIString, Style};
|
||||
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use output::colours::Colours;
|
||||
use fs::fields as f;
|
||||
|
||||
|
||||
@ -17,34 +16,55 @@ impl f::Git {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl f::GitStatus {
|
||||
fn render(&self, colours: &Colours) -> ANSIString<'static> {
|
||||
match *self {
|
||||
f::GitStatus::NotModified => colours.punctuation.paint("-"),
|
||||
f::GitStatus::New => colours.git.new.paint("N"),
|
||||
f::GitStatus::Modified => colours.git.modified.paint("M"),
|
||||
f::GitStatus::Deleted => colours.git.deleted.paint("D"),
|
||||
f::GitStatus::Renamed => colours.git.renamed.paint("R"),
|
||||
f::GitStatus::TypeChange => colours.git.typechange.paint("T"),
|
||||
f::GitStatus::NotModified => colours.not_modified().paint("-"),
|
||||
f::GitStatus::New => colours.new().paint("N"),
|
||||
f::GitStatus::Modified => colours.modified().paint("M"),
|
||||
f::GitStatus::Deleted => colours.deleted().paint("D"),
|
||||
f::GitStatus::Renamed => colours.renamed().paint("R"),
|
||||
f::GitStatus::TypeChange => colours.type_change().paint("T"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn not_modified(&self) -> Style;
|
||||
fn new(&self) -> Style;
|
||||
fn modified(&self) -> Style;
|
||||
fn deleted(&self) -> Style;
|
||||
fn renamed(&self) -> Style;
|
||||
fn type_change(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use super::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use fs::fields as f;
|
||||
|
||||
use ansi_term::Colour::*;
|
||||
use ansi_term::Style;
|
||||
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn not_modified(&self) -> Style { Fixed(90).normal() }
|
||||
fn new(&self) -> Style { Fixed(91).normal() }
|
||||
fn modified(&self) -> Style { Fixed(92).normal() }
|
||||
fn deleted(&self) -> Style { Fixed(93).normal() }
|
||||
fn renamed(&self) -> Style { Fixed(94).normal() }
|
||||
fn type_change(&self) -> Style { Fixed(95).normal() }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn git_blank() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(44).normal();
|
||||
|
||||
let stati = f::Git {
|
||||
staged: f::GitStatus::NotModified,
|
||||
unstaged: f::GitStatus::NotModified,
|
||||
@ -53,21 +73,17 @@ pub mod test {
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(2),
|
||||
contents: vec![
|
||||
Fixed(44).paint("-"),
|
||||
Fixed(44).paint("-"),
|
||||
Fixed(90).paint("-"),
|
||||
Fixed(90).paint("-"),
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&colours).into())
|
||||
assert_eq!(expected, stati.render(&TestColours).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn git_new_changed() {
|
||||
let mut colours = Colours::default();
|
||||
colours.git.new = Red.normal();
|
||||
colours.git.modified = Purple.normal();
|
||||
|
||||
let stati = f::Git {
|
||||
staged: f::GitStatus::New,
|
||||
unstaged: f::GitStatus::Modified,
|
||||
@ -76,11 +92,11 @@ pub mod test {
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(2),
|
||||
contents: vec![
|
||||
Red.paint("N"),
|
||||
Purple.paint("M"),
|
||||
Fixed(91).paint("N"),
|
||||
Fixed(92).paint("M"),
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&colours).into())
|
||||
assert_eq!(expected, stati.render(&TestColours).into())
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
use ansi_term::Style;
|
||||
use users::{Users, Groups};
|
||||
|
||||
use fs::fields as f;
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCell;
|
||||
|
||||
|
||||
impl f::Group {
|
||||
pub fn render<U: Users+Groups>(&self, colours: &Colours, users: &U) -> TextCell {
|
||||
pub fn render<C: Colours, U: Users+Groups>(&self, colours: &C, users: &U) -> TextCell {
|
||||
use users::os::unix::GroupExt;
|
||||
|
||||
let mut style = colours.users.group_not_yours;
|
||||
let mut style = colours.not_yours();
|
||||
|
||||
let group = match users.get_group_by_gid(self.0) {
|
||||
Some(g) => (*g).clone(),
|
||||
@ -20,7 +20,7 @@ impl f::Group {
|
||||
if let Some(current_user) = users.get_user_by_uid(current_uid) {
|
||||
if current_user.primary_group_id() == group.gid()
|
||||
|| group.members().contains(¤t_user.name().to_owned()) {
|
||||
style = colours.users.group_yours;
|
||||
style = colours.yours();
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,63 +29,66 @@ impl f::Group {
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn yours(&self) -> Style;
|
||||
fn not_yours(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use super::Colours;
|
||||
use fs::fields as f;
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
|
||||
use users::{User, Group};
|
||||
use users::mock::MockUsers;
|
||||
use users::os::unix::GroupExt;
|
||||
use ansi_term::Colour::*;
|
||||
use ansi_term::Style;
|
||||
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn yours(&self) -> Style { Fixed(80).normal() }
|
||||
fn not_yours(&self) -> Style { Fixed(81).normal() }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn named() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Fixed(101).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(1000);
|
||||
users.add_group(Group::new(100, "folk"));
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(101).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&TestColours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Fixed(87).normal();
|
||||
|
||||
let users = MockUsers::with_current_uid(1000);
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(87).normal(), "100");
|
||||
assert_eq!(expected, group.render(&colours, &users));
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), "100");
|
||||
assert_eq!(expected, group.render(&TestColours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn primary() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_yours = Fixed(64).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(2);
|
||||
users.add_user(User::new(2, "eve", 100));
|
||||
users.add_group(Group::new(100, "folk"));
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(64).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
let expected = TextCell::paint_str(Fixed(80).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&TestColours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secondary() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_yours = Fixed(31).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(2);
|
||||
users.add_user(User::new(2, "eve", 666));
|
||||
|
||||
@ -93,17 +96,14 @@ pub mod test {
|
||||
users.add_group(test_group);
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(31).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
let expected = TextCell::paint_str(Fixed(80).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&TestColours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overflow() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Blue.underline();
|
||||
|
||||
let group = f::Group(2_147_483_648);
|
||||
let expected = TextCell::paint_str(Blue.underline(), "2147483648");
|
||||
assert_eq!(expected, group.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
let expected = TextCell::paint_str(Fixed(81).normal(), "2147483648");
|
||||
assert_eq!(expected, group.render(&TestColours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
use ansi_term::Style;
|
||||
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
use fs::fields as f;
|
||||
|
||||
|
||||
impl f::Inode {
|
||||
pub fn render(&self, colours: &Colours) -> TextCell {
|
||||
TextCell::paint(colours.inode, self.0.to_string())
|
||||
pub fn render(&self, style: Style) -> TextCell {
|
||||
TextCell::paint(style, self.0.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCell;
|
||||
use fs::fields as f;
|
||||
|
||||
@ -21,11 +21,8 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn blocklessness() {
|
||||
let mut colours = Colours::default();
|
||||
colours.inode = Cyan.underline();
|
||||
|
||||
let io = f::Inode(1414213);
|
||||
let expected = TextCell::paint_str(Cyan.underline(), "1414213");
|
||||
assert_eq!(expected, io.render(&colours).into());
|
||||
assert_eq!(expected, io.render(Cyan.underline()).into());
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,47 @@
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
use fs::fields as f;
|
||||
use ansi_term::Style;
|
||||
use locale::Numeric as NumericLocale;
|
||||
|
||||
use locale;
|
||||
use output::cell::TextCell;
|
||||
use fs::fields as f;
|
||||
|
||||
|
||||
impl f::Links {
|
||||
pub fn render(&self, colours: &Colours, numeric: &locale::Numeric) -> TextCell {
|
||||
let style = if self.multiple { colours.links.multi_link_file }
|
||||
else { colours.links.normal };
|
||||
pub fn render<C: Colours>(&self, colours: &C, numeric: &NumericLocale) -> TextCell {
|
||||
let style = if self.multiple { colours.multi_link_file() }
|
||||
else { colours.normal() };
|
||||
|
||||
TextCell::paint(style, numeric.format_int(self.count))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn normal(&self) -> Style;
|
||||
fn multi_link_file(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use super::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use fs::fields as f;
|
||||
|
||||
use ansi_term::Colour::*;
|
||||
use ansi_term::Style;
|
||||
use locale;
|
||||
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn normal(&self) -> Style { Blue.normal() }
|
||||
fn multi_link_file(&self) -> Style { Blue.on(Red) }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn regular_file() {
|
||||
let mut colours = Colours::default();
|
||||
colours.links.normal = Blue.normal();
|
||||
|
||||
let stati = f::Links {
|
||||
count: 1,
|
||||
multiple: false,
|
||||
@ -40,14 +52,11 @@ pub mod test {
|
||||
contents: vec![ Blue.paint("1") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&TestColours, &locale::Numeric::english()).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regular_directory() {
|
||||
let mut colours = Colours::default();
|
||||
colours.links.normal = Blue.normal();
|
||||
|
||||
let stati = f::Links {
|
||||
count: 3005,
|
||||
multiple: false,
|
||||
@ -58,14 +67,11 @@ pub mod test {
|
||||
contents: vec![ Blue.paint("3,005") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&TestColours, &locale::Numeric::english()).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn popular_file() {
|
||||
let mut colours = Colours::default();
|
||||
colours.links.multi_link_file = Blue.on(Red);
|
||||
|
||||
let stati = f::Links {
|
||||
count: 3005,
|
||||
multiple: true,
|
||||
@ -76,6 +82,6 @@ pub mod test {
|
||||
contents: vec![ Blue.on(Red).paint("3,005") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&TestColours, &locale::Numeric::english()).into());
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,29 @@
|
||||
mod blocks;
|
||||
pub use self::blocks::Colours as BlocksColours;
|
||||
|
||||
mod filetype;
|
||||
pub use self::filetype::Colours as FiletypeColours;
|
||||
|
||||
mod git;
|
||||
pub use self::git::Colours as GitColours;
|
||||
|
||||
mod groups;
|
||||
pub use self::groups::Colours as GroupColours;
|
||||
|
||||
mod inode;
|
||||
// inode uses just one colour
|
||||
|
||||
mod links;
|
||||
pub use self::links::Colours as LinksColours;
|
||||
|
||||
mod permissions;
|
||||
pub use self::permissions::Colours as PermissionsColours;
|
||||
|
||||
mod size;
|
||||
pub use self::size::Colours as SizeColours;
|
||||
|
||||
mod times;
|
||||
// times does too
|
||||
|
||||
mod users;
|
||||
pub use self::users::Colours as UserColours;
|
||||
|
@ -1,16 +1,17 @@
|
||||
use fs::fields as f;
|
||||
use output::colours::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use ansi_term::{ANSIString, Style};
|
||||
|
||||
use fs::fields as f;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use output::render::FiletypeColours;
|
||||
|
||||
|
||||
impl f::PermissionsPlus {
|
||||
pub fn render(&self, colours: &Colours) -> TextCell {
|
||||
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.perms.attribute.paint("@"));
|
||||
chars.push(colours.attribute().paint("@"));
|
||||
}
|
||||
|
||||
// As these are all ASCII characters, we can guarantee that they’re
|
||||
@ -23,87 +24,115 @@ impl f::PermissionsPlus {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl f::Permissions {
|
||||
pub fn render(&self, colours: &Colours, is_regular_file: bool) -> Vec<ANSIString<'static>> {
|
||||
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.punctuation.paint("-") }
|
||||
if bit { style.paint(chr) } else { colours.dash().paint("-") }
|
||||
};
|
||||
|
||||
vec![
|
||||
bit(self.user_read, "r", colours.perms.user_read),
|
||||
bit(self.user_write, "w", colours.perms.user_write),
|
||||
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.perms.group_read),
|
||||
bit(self.group_write, "w", colours.perms.group_write),
|
||||
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.perms.other_read),
|
||||
bit(self.other_write, "w", colours.perms.other_write),
|
||||
bit(self.other_read, "r", colours.other_read()),
|
||||
bit(self.other_write, "w", colours.other_write()),
|
||||
self.other_execute_bit(colours)
|
||||
]
|
||||
}
|
||||
|
||||
fn user_execute_bit(&self, colours: &Colours, is_regular_file: bool) -> ANSIString<'static> {
|
||||
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.punctuation.paint("-"),
|
||||
(true, false, false) => colours.perms.user_execute_other.paint("x"),
|
||||
(true, false, true) => colours.perms.user_execute_file.paint("x"),
|
||||
(false, true, _) => colours.perms.special_other.paint("S"),
|
||||
(true, true, false) => colours.perms.special_other.paint("s"),
|
||||
(true, true, true) => colours.perms.special_user_file.paint("s"),
|
||||
(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(&self, colours: &Colours) -> ANSIString<'static> {
|
||||
fn group_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
match (self.group_execute, self.setgid) {
|
||||
(false, false) => colours.punctuation.paint("-"),
|
||||
(true, false) => colours.perms.group_execute.paint("x"),
|
||||
(false, true) => colours.perms.special_other.paint("S"),
|
||||
(true, true) => colours.perms.special_other.paint("s"),
|
||||
(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(&self, colours: &Colours) -> ANSIString<'static> {
|
||||
fn other_execute_bit<C: Colours>(&self, colours: &C) -> ANSIString<'static> {
|
||||
match (self.other_execute, self.sticky) {
|
||||
(false, false) => colours.punctuation.paint("-"),
|
||||
(true, false) => colours.perms.other_execute.paint("x"),
|
||||
(false, true) => colours.perms.special_other.paint("T"),
|
||||
(true, true) => colours.perms.special_other.paint("t"),
|
||||
(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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl f::Type {
|
||||
pub fn render(&self, colours: &Colours) -> ANSIString<'static> {
|
||||
match *self {
|
||||
f::Type::File => colours.filetypes.normal.paint("."),
|
||||
f::Type::Directory => colours.filetypes.directory.paint("d"),
|
||||
f::Type::Pipe => colours.filetypes.pipe.paint("|"),
|
||||
f::Type::Link => colours.filetypes.symlink.paint("l"),
|
||||
f::Type::CharDevice => colours.filetypes.device.paint("c"),
|
||||
f::Type::BlockDevice => colours.filetypes.device.paint("b"),
|
||||
f::Type::Socket => colours.filetypes.socket.paint("s"),
|
||||
f::Type::Special => colours.filetypes.special.paint("?"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use super::Colours;
|
||||
use output::cell::TextCellContents;
|
||||
use fs::fields as f;
|
||||
|
||||
use ansi_term::Colour::*;
|
||||
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() }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn negate() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
|
||||
let bits = f::Permissions {
|
||||
user_read: false, user_write: false, user_execute: false, setuid: false,
|
||||
group_read: false, group_write: false, group_execute: false, setgid: false,
|
||||
@ -116,25 +145,12 @@ pub mod test {
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(11).paint("-"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&colours, false).into())
|
||||
assert_eq!(expected, bits.render(&TestColours, false).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn affirm() {
|
||||
let mut colours = Colours::default();
|
||||
colours.perms.user_read = Fixed(101).normal();
|
||||
colours.perms.user_write = Fixed(102).normal();
|
||||
colours.perms.user_execute_file = Fixed(103).normal();
|
||||
|
||||
colours.perms.group_read = Fixed(104).normal();
|
||||
colours.perms.group_write = Fixed(105).normal();
|
||||
colours.perms.group_execute = Fixed(106).normal();
|
||||
|
||||
colours.perms.other_read = Fixed(107).normal();
|
||||
colours.perms.other_write = Fixed(108).normal();
|
||||
colours.perms.other_execute = Fixed(109).normal();
|
||||
|
||||
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,
|
||||
@ -147,17 +163,12 @@ pub mod test {
|
||||
Fixed(107).paint("r"), Fixed(108).paint("w"), Fixed(109).paint("x"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&colours, true).into())
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn specials() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
colours.perms.special_user_file = Fixed(77).normal();
|
||||
colours.perms.special_other = Fixed(88).normal();
|
||||
|
||||
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,
|
||||
@ -165,21 +176,17 @@ pub mod test {
|
||||
};
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(77).paint("s"),
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("s"),
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("t"),
|
||||
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(&colours, true).into())
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn extra_specials() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
colours.perms.special_other = Fixed(88).normal();
|
||||
|
||||
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,
|
||||
@ -187,11 +194,11 @@ pub mod test {
|
||||
};
|
||||
|
||||
let expected = TextCellContents::from(vec![
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("S"),
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("S"),
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("T"),
|
||||
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(&colours, true).into())
|
||||
assert_eq!(expected, bits.render(&TestColours, true).into())
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
use ansi_term::Style;
|
||||
use locale::Numeric as NumericLocale;
|
||||
|
||||
use fs::fields as f;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use output::colours::Colours;
|
||||
use output::table::SizeFormat;
|
||||
use locale;
|
||||
|
||||
|
||||
|
||||
impl f::Size {
|
||||
pub fn render(&self, colours: &Colours, size_format: SizeFormat, numerics: &locale::Numeric) -> TextCell {
|
||||
pub fn render<C: Colours>(&self, colours: &C, size_format: SizeFormat, numerics: &NumericLocale) -> TextCell {
|
||||
use number_prefix::{binary_prefix, decimal_prefix};
|
||||
use number_prefix::{Prefixed, Standalone, PrefixNames};
|
||||
|
||||
let size = match *self {
|
||||
f::Size::Some(s) => s,
|
||||
f::Size::None => return TextCell::blank(colours.punctuation),
|
||||
f::Size::None => return TextCell::blank(colours.no_size()),
|
||||
f::Size::DeviceIDs(ref ids) => return ids.render(colours),
|
||||
};
|
||||
|
||||
@ -21,12 +23,12 @@ impl f::Size {
|
||||
SizeFormat::BinaryBytes => binary_prefix(size as f64),
|
||||
SizeFormat::JustBytes => {
|
||||
let string = numerics.format_int(size);
|
||||
return TextCell::paint(colours.file_size(size), string);
|
||||
return TextCell::paint(colours.size(size), string);
|
||||
},
|
||||
};
|
||||
|
||||
let (prefix, n) = match result {
|
||||
Standalone(b) => return TextCell::paint(colours.file_size(b as u64), b.to_string()),
|
||||
Standalone(b) => return TextCell::paint(colours.size(b as u64), b.to_string()),
|
||||
Prefixed(p, n) => (p, n)
|
||||
};
|
||||
|
||||
@ -41,114 +43,121 @@ impl f::Size {
|
||||
TextCell {
|
||||
width: width,
|
||||
contents: vec![
|
||||
colours.file_size(size).paint(number),
|
||||
colours.size.unit.paint(symbol),
|
||||
colours.size(size).paint(number),
|
||||
colours.unit().paint(symbol),
|
||||
].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl f::DeviceIDs {
|
||||
fn render(&self, colours: &Colours) -> TextCell {
|
||||
fn render<C: Colours>(&self, colours: &C) -> TextCell {
|
||||
let major = self.major.to_string();
|
||||
let minor = self.minor.to_string();
|
||||
|
||||
TextCell {
|
||||
width: DisplayWidth::from(major.len() + 1 + minor.len()),
|
||||
contents: vec![
|
||||
colours.size.major.paint(major),
|
||||
colours.punctuation.paint(","),
|
||||
colours.size.minor.paint(minor),
|
||||
colours.major().paint(major),
|
||||
colours.comma().paint(","),
|
||||
colours.minor().paint(minor),
|
||||
].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn size(&self, size: u64) -> Style;
|
||||
fn unit(&self) -> Style;
|
||||
fn no_size(&self) -> Style;
|
||||
|
||||
fn major(&self) -> Style;
|
||||
fn comma(&self) -> Style;
|
||||
fn minor(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::colours::Colours;
|
||||
use super::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use output::table::SizeFormat;
|
||||
use fs::fields as f;
|
||||
|
||||
use locale;
|
||||
use locale::Numeric as NumericLocale;
|
||||
use ansi_term::Colour::*;
|
||||
use ansi_term::Style;
|
||||
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn size(&self, _size: u64) -> Style { Fixed(66).normal() }
|
||||
fn unit(&self) -> Style { Fixed(77).bold() }
|
||||
fn no_size(&self) -> Style { Black.italic() }
|
||||
|
||||
fn major(&self) -> Style { Blue.on(Red) }
|
||||
fn comma(&self) -> Style { Green.italic() }
|
||||
fn minor(&self) -> Style { Cyan.on(Yellow) }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn directory() {
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Green.italic();
|
||||
|
||||
let directory = f::Size::None;
|
||||
let expected = TextCell::blank(Green.italic());
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
let expected = TextCell::blank(Black.italic());
|
||||
assert_eq!(expected, directory.render(&TestColours, SizeFormat::JustBytes, &NumericLocale::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_decimal() {
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
colours.size.unit = Yellow.bold();
|
||||
|
||||
let directory = f::Size::Some(2_100_000);
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(4),
|
||||
contents: vec![
|
||||
Blue.on(Red).paint("2.1"),
|
||||
Yellow.bold().paint("M"),
|
||||
Fixed(66).paint("2.1"),
|
||||
Fixed(77).bold().paint("M"),
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::DecimalBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&TestColours, SizeFormat::DecimalBytes, &NumericLocale::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_binary() {
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
colours.size.unit = Yellow.bold();
|
||||
|
||||
let directory = f::Size::Some(1_048_576);
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(5),
|
||||
contents: vec![
|
||||
Blue.on(Red).paint("1.0"),
|
||||
Yellow.bold().paint("Mi"),
|
||||
Fixed(66).paint("1.0"),
|
||||
Fixed(77).bold().paint("Mi"),
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::BinaryBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&TestColours, SizeFormat::BinaryBytes, &NumericLocale::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_bytes() {
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
|
||||
let directory = f::Size::Some(1048576);
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(9),
|
||||
contents: vec![
|
||||
Blue.on(Red).paint("1,048,576"),
|
||||
Fixed(66).paint("1,048,576"),
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&TestColours, SizeFormat::JustBytes, &NumericLocale::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn device_ids() {
|
||||
let mut colours = Colours::default();
|
||||
colours.size.major = Blue.on(Red);
|
||||
colours.punctuation = Green.italic();
|
||||
colours.size.minor = Cyan.on(Yellow);
|
||||
|
||||
let directory = f::Size::DeviceIDs(f::DeviceIDs { major: 10, minor: 80 });
|
||||
let expected = TextCell {
|
||||
width: DisplayWidth::from(5),
|
||||
@ -159,6 +168,6 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&TestColours, SizeFormat::JustBytes, &NumericLocale::english()))
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,23 @@
|
||||
use datetime::TimeZone;
|
||||
use ansi_term::Style;
|
||||
|
||||
use fs::fields as f;
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
use output::time::TimeFormat;
|
||||
|
||||
|
||||
impl f::Time {
|
||||
pub fn render(self, colours: &Colours,
|
||||
tz: &Option<TimeZone>,
|
||||
style: &TimeFormat) -> TextCell {
|
||||
pub fn render(self, style: Style,
|
||||
tz: &Option<TimeZone>,
|
||||
format: &TimeFormat) -> TextCell {
|
||||
|
||||
if let Some(ref tz) = *tz {
|
||||
let datestamp = style.format_zoned(self, tz);
|
||||
TextCell::paint(colours.date, datestamp)
|
||||
let datestamp = format.format_zoned(self, tz);
|
||||
TextCell::paint(style, datestamp)
|
||||
}
|
||||
else {
|
||||
let datestamp = style.format_local(self);
|
||||
TextCell::paint(colours.date, datestamp)
|
||||
let datestamp = format.format_local(self);
|
||||
TextCell::paint(style, datestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,89 +1,92 @@
|
||||
use ansi_term::Style;
|
||||
use users::Users;
|
||||
|
||||
use fs::fields as f;
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCell;
|
||||
|
||||
|
||||
|
||||
impl f::User {
|
||||
pub fn render(&self, colours: &Colours, users: &Users) -> TextCell {
|
||||
pub fn render<C: Colours, U: Users>(&self, colours: &C, users: &U) -> TextCell {
|
||||
let user_name = match users.get_user_by_uid(self.0) {
|
||||
Some(user) => user.name().to_owned(),
|
||||
None => self.0.to_string(),
|
||||
};
|
||||
|
||||
let style = if users.get_current_uid() == self.0 { colours.users.user_you }
|
||||
else { colours.users.user_someone_else };
|
||||
let style = if users.get_current_uid() == self.0 { colours.you() }
|
||||
else { colours.someone_else() };
|
||||
TextCell::paint(style, user_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait Colours {
|
||||
fn you(&self) -> Style;
|
||||
fn someone_else(&self) -> Style;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use super::Colours;
|
||||
use fs::fields as f;
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
|
||||
use users::User;
|
||||
use users::mock::MockUsers;
|
||||
use ansi_term::Colour::*;
|
||||
use ansi_term::Style;
|
||||
|
||||
|
||||
struct TestColours;
|
||||
|
||||
impl Colours for TestColours {
|
||||
fn you(&self) -> Style { Red.bold() }
|
||||
fn someone_else(&self) -> Style { Blue.underline() }
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn named() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_you = Red.bold();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(1000);
|
||||
users.add_user(User::new(1000, "enoch", 100));
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Red.bold(), "enoch");
|
||||
assert_eq!(expected, user.render(&colours, &users))
|
||||
assert_eq!(expected, user.render(&TestColours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_you = Cyan.bold();
|
||||
|
||||
let users = MockUsers::with_current_uid(1000);
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Cyan.bold(), "1000");
|
||||
assert_eq!(expected, user.render(&colours, &users));
|
||||
let expected = TextCell::paint_str(Red.bold(), "1000");
|
||||
assert_eq!(expected, user.render(&TestColours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn different_named() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Green.bold();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(0);
|
||||
users.add_user(User::new(1000, "enoch", 100));
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Green.bold(), "enoch");
|
||||
assert_eq!(expected, user.render(&colours, &users));
|
||||
let expected = TextCell::paint_str(Blue.underline(), "enoch");
|
||||
assert_eq!(expected, user.render(&TestColours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn different_unnamed() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Red.normal();
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Red.normal(), "1000");
|
||||
assert_eq!(expected, user.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
let expected = TextCell::paint_str(Blue.underline(), "1000");
|
||||
assert_eq!(expected, user.render(&TestColours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overflow() {
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Blue.underline();
|
||||
|
||||
let user = f::User(2_147_483_648);
|
||||
let expected = TextCell::paint_str(Blue.underline(), "2147483648");
|
||||
assert_eq!(expected, user.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
assert_eq!(expected, user.render(&TestColours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
}
|
||||
|
@ -342,18 +342,18 @@ impl<'a, 'f> Table<'a> {
|
||||
use output::table::TimeType::*;
|
||||
|
||||
match *column {
|
||||
Column::Permissions => self.permissions_plus(file, xattrs).render(&self.colours),
|
||||
Column::FileSize => file.size().render(&self.colours, self.size_format, &self.env.numeric),
|
||||
Column::HardLinks => file.links().render(&self.colours, &self.env.numeric),
|
||||
Column::Inode => file.inode().render(&self.colours),
|
||||
Column::Blocks => file.blocks().render(&self.colours),
|
||||
Column::User => file.user().render(&self.colours, &*self.env.lock_users()),
|
||||
Column::Group => file.group().render(&self.colours, &*self.env.lock_users()),
|
||||
Column::GitStatus => file.git_status().render(&self.colours),
|
||||
Column::Permissions => self.permissions_plus(file, xattrs).render(self.colours),
|
||||
Column::FileSize => file.size().render(self.colours, self.size_format, &self.env.numeric),
|
||||
Column::HardLinks => file.links().render(self.colours, &self.env.numeric),
|
||||
Column::Inode => file.inode().render(self.colours.inode),
|
||||
Column::Blocks => file.blocks().render(self.colours),
|
||||
Column::User => file.user().render(self.colours, &*self.env.lock_users()),
|
||||
Column::Group => file.group().render(self.colours, &*self.env.lock_users()),
|
||||
Column::GitStatus => file.git_status().render(self.colours),
|
||||
|
||||
Column::Timestamp(Modified) => file.modified_time().render(&self.colours, &self.env.tz, &self.time_format),
|
||||
Column::Timestamp(Created) => file.created_time().render( &self.colours, &self.env.tz, &self.time_format),
|
||||
Column::Timestamp(Accessed) => file.accessed_time().render(&self.colours, &self.env.tz, &self.time_format),
|
||||
Column::Timestamp(Modified) => file.modified_time().render(self.colours.date, &self.env.tz, &self.time_format),
|
||||
Column::Timestamp(Created) => file.created_time() .render(self.colours.date, &self.env.tz, &self.time_format),
|
||||
Column::Timestamp(Accessed) => file.accessed_time().render(self.colours.date, &self.env.tz, &self.time_format),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user