use lla_plugin_interface::DecoratedEntry;
use std::collections::HashMap;
type FieldFormatter = dyn Fn(&DecoratedEntry) -> Option<String>;
pub trait EntryFormatter {
fn format_field(&self, entry: &DecoratedEntry, format: &str) -> Option<String>;
}
pub struct FieldFormatterBuilder {
formatters: HashMap<String, Box<FieldFormatter>>,
}
impl FieldFormatterBuilder {
pub fn new() -> Self {
Self {
formatters: HashMap::new(),
}
}
pub fn add_formatter<F>(mut self, format: &str, formatter: F) -> Self
where
F: Fn(&DecoratedEntry) -> Option<String> + 'static,
{
self.formatters
.insert(format.to_string(), Box::new(formatter));
self
}
pub fn build(self) -> CustomFieldFormatter {
CustomFieldFormatter {
formatters: self.formatters,
}
}
}
pub struct CustomFieldFormatter {
formatters: HashMap<String, Box<FieldFormatter>>,
}
impl EntryFormatter for CustomFieldFormatter {
fn format_field(&self, entry: &DecoratedEntry, format: &str) -> Option<String> {
self.formatters.get(format).and_then(|f| f(entry))
}
}
impl Default for FieldFormatterBuilder {
fn default() -> Self {
Self::new()
}
}
pub fn format_permissions(permissions: u32) -> String {
let mut result = String::with_capacity(10);
result.push(if permissions & 0o040000 != 0 {
'd'
} else {
'-'
});
result.push(if permissions & 0o400 != 0 { 'r' } else { '-' });
result.push(if permissions & 0o200 != 0 { 'w' } else { '-' });
result.push(if permissions & 0o100 != 0 { 'x' } else { '-' });
result.push(if permissions & 0o040 != 0 { 'r' } else { '-' });
result.push(if permissions & 0o020 != 0 { 'w' } else { '-' });
result.push(if permissions & 0o010 != 0 { 'x' } else { '-' });
result.push(if permissions & 0o004 != 0 { 'r' } else { '-' });
result.push(if permissions & 0o002 != 0 { 'w' } else { '-' });
result.push(if permissions & 0o001 != 0 { 'x' } else { '-' });
result
}
pub fn format_file_type(entry: &DecoratedEntry) -> String {
if entry.metadata.is_dir {
"Directory".to_string()
} else if entry.metadata.is_symlink {
"Symlink".to_string()
} else if entry.metadata.is_file {
match entry.path.extension() {
Some(ext) => ext.to_string_lossy().to_uppercase(),
None => "File".to_string(),
}
} else {
"Unknown".to_string()
}
}
pub fn format_ownership(uid: u32, gid: u32) -> String {
use users::{get_group_by_gid, get_user_by_uid};
let user = get_user_by_uid(uid)
.map(|u| u.name().to_string_lossy().into_owned())
.unwrap_or_else(|| uid.to_string());
let group = get_group_by_gid(gid)
.map(|g| g.name().to_string_lossy().into_owned())
.unwrap_or_else(|| gid.to_string());
format!("{}:{}", user, group)
}