mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-14 22:22:26 +00:00
Implementation
This commit is contained in:
parent
48b5adf929
commit
92d4e96622
15 changed files with 386 additions and 117 deletions
|
@ -68,8 +68,8 @@ pub struct Cli {
|
||||||
#[arg(short, long, conflicts_with_all = ["depth", "recursive"])]
|
#[arg(short, long, conflicts_with_all = ["depth", "recursive"])]
|
||||||
pub directory_only: bool,
|
pub directory_only: bool,
|
||||||
|
|
||||||
/// How to display permissions [default: rwx]
|
/// How to display permissions [default: rwx for non-windows, attributes for windows]
|
||||||
#[arg(long, value_name = "MODE", value_parser = ["rwx", "octal", "disable"])]
|
#[arg(long, value_name = "MODE", value_parser = ["rwx", "octal", "attributes", "disable"])]
|
||||||
pub permission: Option<String>,
|
pub permission: Option<String>,
|
||||||
|
|
||||||
/// How to display size [default: default]
|
/// How to display size [default: default]
|
||||||
|
|
17
src/color.rs
17
src/color.rs
|
@ -38,6 +38,12 @@ pub enum Elem {
|
||||||
Acl,
|
Acl,
|
||||||
Context,
|
Context,
|
||||||
|
|
||||||
|
/// Attributes
|
||||||
|
Archive,
|
||||||
|
AttributeRead,
|
||||||
|
Hidden,
|
||||||
|
System,
|
||||||
|
|
||||||
/// Last Time Modified
|
/// Last Time Modified
|
||||||
DayOld,
|
DayOld,
|
||||||
HourOld,
|
HourOld,
|
||||||
|
@ -112,6 +118,11 @@ impl Elem {
|
||||||
Elem::Acl => theme.permission.acl,
|
Elem::Acl => theme.permission.acl,
|
||||||
Elem::Context => theme.permission.context,
|
Elem::Context => theme.permission.context,
|
||||||
|
|
||||||
|
Elem::Archive => theme.attributes.archive,
|
||||||
|
Elem::AttributeRead => theme.attributes.read,
|
||||||
|
Elem::Hidden => theme.attributes.hidden,
|
||||||
|
Elem::System => theme.attributes.system,
|
||||||
|
|
||||||
Elem::DayOld => theme.date.day_old,
|
Elem::DayOld => theme.date.day_old,
|
||||||
Elem::HourOld => theme.date.hour_old,
|
Elem::HourOld => theme.date.hour_old,
|
||||||
Elem::Older => theme.date.older,
|
Elem::Older => theme.date.older,
|
||||||
|
@ -399,6 +410,12 @@ mod elem {
|
||||||
acl: Color::DarkCyan,
|
acl: Color::DarkCyan,
|
||||||
context: Color::Cyan,
|
context: Color::Cyan,
|
||||||
},
|
},
|
||||||
|
attributes: color::Attributes {
|
||||||
|
read: Color::Green,
|
||||||
|
archive: Color::Yellow,
|
||||||
|
hidden: Color::Red,
|
||||||
|
system: Color::Magenta,
|
||||||
|
},
|
||||||
file_type: color::FileType {
|
file_type: color::FileType {
|
||||||
file: color::File {
|
file: color::File {
|
||||||
exec_uid: Color::AnsiValue(40), // Green3
|
exec_uid: Color::AnsiValue(40), // Green3
|
||||||
|
|
|
@ -299,8 +299,8 @@ size: default
|
||||||
|
|
||||||
# == Permission ==
|
# == Permission ==
|
||||||
# Specify the format of the permission column.
|
# Specify the format of the permission column.
|
||||||
# Possible value: rwx, octal
|
# Possible value: rwx, octal, attributes, disable
|
||||||
permission: rwx
|
# permission: rwx
|
||||||
|
|
||||||
# == Sorting ==
|
# == Sorting ==
|
||||||
sorting:
|
sorting:
|
||||||
|
@ -363,7 +363,6 @@ mod tests {
|
||||||
use crate::flags::color::{ColorOption, ThemeOption};
|
use crate::flags::color::{ColorOption, ThemeOption};
|
||||||
use crate::flags::icons::{IconOption, IconTheme};
|
use crate::flags::icons::{IconOption, IconTheme};
|
||||||
use crate::flags::layout::Layout;
|
use crate::flags::layout::Layout;
|
||||||
use crate::flags::permission::PermissionFlag;
|
|
||||||
use crate::flags::size::SizeFlag;
|
use crate::flags::size::SizeFlag;
|
||||||
use crate::flags::sorting::{DirGrouping, SortColumn};
|
use crate::flags::sorting::{DirGrouping, SortColumn};
|
||||||
use crate::flags::HyperlinkOption;
|
use crate::flags::HyperlinkOption;
|
||||||
|
@ -402,7 +401,7 @@ mod tests {
|
||||||
depth: None,
|
depth: None,
|
||||||
}),
|
}),
|
||||||
size: Some(SizeFlag::Default),
|
size: Some(SizeFlag::Default),
|
||||||
permission: Some(PermissionFlag::Rwx),
|
permission: None,
|
||||||
sorting: Some(config_file::Sorting {
|
sorting: Some(config_file::Sorting {
|
||||||
column: Some(SortColumn::Name),
|
column: Some(SortColumn::Name),
|
||||||
reverse: Some(false),
|
reverse: Some(false),
|
||||||
|
|
10
src/core.rs
10
src/core.rs
|
@ -1,8 +1,7 @@
|
||||||
use crate::color::Colors;
|
use crate::color::Colors;
|
||||||
use crate::display;
|
use crate::display;
|
||||||
use crate::flags::{
|
use crate::flags::{
|
||||||
ColorOption, Display, Flags, HyperlinkOption, Layout, Literal, PermissionFlag, SortOrder,
|
ColorOption, Display, Flags, HyperlinkOption, Layout, Literal, SortOrder, ThemeOption,
|
||||||
ThemeOption,
|
|
||||||
};
|
};
|
||||||
use crate::git::GitCache;
|
use crate::git::GitCache;
|
||||||
use crate::icon::Icons;
|
use crate::icon::Icons;
|
||||||
|
@ -106,11 +105,8 @@ impl Core {
|
||||||
};
|
};
|
||||||
|
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let mut meta = match Meta::from_path(
|
let mut meta =
|
||||||
&path,
|
match Meta::from_path(&path, self.flags.dereference.0, self.flags.permission) {
|
||||||
self.flags.dereference.0,
|
|
||||||
self.flags.permission == PermissionFlag::Disable,
|
|
||||||
) {
|
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
print_error!("{}: {}.", path.display(), err);
|
print_error!("{}: {}.", path.display(), err);
|
||||||
|
|
|
@ -347,8 +347,10 @@ fn get_output(
|
||||||
Block::Permission => {
|
Block::Permission => {
|
||||||
block_vec.extend([
|
block_vec.extend([
|
||||||
meta.file_type.render(colors),
|
meta.file_type.render(colors),
|
||||||
match meta.permissions {
|
match &meta.permissions_or_attributes {
|
||||||
Some(permissions) => permissions.render(colors, flags),
|
Some(permissions_or_attributes) => {
|
||||||
|
permissions_or_attributes.render(colors, flags)
|
||||||
|
}
|
||||||
None => colorize_missing("?????????"),
|
None => colorize_missing("?????????"),
|
||||||
},
|
},
|
||||||
match &meta.access_control {
|
match &meta.access_control {
|
||||||
|
@ -491,7 +493,7 @@ mod tests {
|
||||||
use crate::app::Cli;
|
use crate::app::Cli;
|
||||||
use crate::color;
|
use crate::color;
|
||||||
use crate::color::Colors;
|
use crate::color::Colors;
|
||||||
use crate::flags::{HyperlinkOption, IconOption, IconTheme as FlagTheme};
|
use crate::flags::{HyperlinkOption, IconOption, IconTheme as FlagTheme, PermissionFlag};
|
||||||
use crate::icon::Icons;
|
use crate::icon::Icons;
|
||||||
use crate::meta::{FileType, Name};
|
use crate::meta::{FileType, Name};
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
@ -686,7 +688,7 @@ mod tests {
|
||||||
dir.child("one.d").create_dir_all().unwrap();
|
dir.child("one.d").create_dir_all().unwrap();
|
||||||
dir.child("one.d/two").touch().unwrap();
|
dir.child("one.d/two").touch().unwrap();
|
||||||
dir.child("one.d/.hidden").touch().unwrap();
|
dir.child("one.d/.hidden").touch().unwrap();
|
||||||
let mut metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let mut metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(42, &flags, None)
|
.recurse_into(42, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -719,7 +721,7 @@ mod tests {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
dir.child("dir").create_dir_all().unwrap();
|
dir.child("dir").create_dir_all().unwrap();
|
||||||
dir.child("dir/file").touch().unwrap();
|
dir.child("dir/file").touch().unwrap();
|
||||||
let metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(42, &flags, None)
|
.recurse_into(42, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -760,7 +762,7 @@ mod tests {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
dir.child("dir").create_dir_all().unwrap();
|
dir.child("dir").create_dir_all().unwrap();
|
||||||
dir.child("dir/file").touch().unwrap();
|
dir.child("dir/file").touch().unwrap();
|
||||||
let metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(42, &flags, None)
|
.recurse_into(42, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -800,7 +802,7 @@ mod tests {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
dir.child("one.d").create_dir_all().unwrap();
|
dir.child("one.d").create_dir_all().unwrap();
|
||||||
dir.child("one.d/two").touch().unwrap();
|
dir.child("one.d/two").touch().unwrap();
|
||||||
let metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(42, &flags, None)
|
.recurse_into(42, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -831,7 +833,7 @@ mod tests {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
dir.child("testdir").create_dir_all().unwrap();
|
dir.child("testdir").create_dir_all().unwrap();
|
||||||
dir.child("test").touch().unwrap();
|
dir.child("test").touch().unwrap();
|
||||||
let metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(1, &flags, None)
|
.recurse_into(1, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -865,7 +867,7 @@ mod tests {
|
||||||
|
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
dir.child("testdir").create_dir_all().unwrap();
|
dir.child("testdir").create_dir_all().unwrap();
|
||||||
let metas = Meta::from_path(Path::new(dir.path()), false, false)
|
let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recurse_into(1, &flags, None)
|
.recurse_into(1, &flags, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -895,11 +897,11 @@ mod tests {
|
||||||
|
|
||||||
let file_path = tmp_dir.path().join("file");
|
let file_path = tmp_dir.path().join("file");
|
||||||
std::fs::File::create(&file_path).expect("failed to create the file");
|
std::fs::File::create(&file_path).expect("failed to create the file");
|
||||||
let file = Meta::from_path(&file_path, false, false).unwrap();
|
let file = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let dir_path = tmp_dir.path().join("dir");
|
let dir_path = tmp_dir.path().join("dir");
|
||||||
std::fs::create_dir(&dir_path).expect("failed to create the dir");
|
std::fs::create_dir(&dir_path).expect("failed to create the dir");
|
||||||
let dir = Meta::from_path(&dir_path, false, false).unwrap();
|
let dir = Meta::from_path(&dir_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
display_folder_path(&dir),
|
display_folder_path(&dir),
|
||||||
|
@ -945,15 +947,15 @@ mod tests {
|
||||||
|
|
||||||
let file_path = tmp_dir.path().join("file");
|
let file_path = tmp_dir.path().join("file");
|
||||||
std::fs::File::create(&file_path).expect("failed to create the file");
|
std::fs::File::create(&file_path).expect("failed to create the file");
|
||||||
let file = Meta::from_path(&file_path, false, false).unwrap();
|
let file = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let dir_path = tmp_dir.path().join("dir");
|
let dir_path = tmp_dir.path().join("dir");
|
||||||
std::fs::create_dir(&dir_path).expect("failed to create the dir");
|
std::fs::create_dir(&dir_path).expect("failed to create the dir");
|
||||||
let dir = Meta::from_path(&dir_path, false, false).unwrap();
|
let dir = Meta::from_path(&dir_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let link_path = tmp_dir.path().join("link");
|
let link_path = tmp_dir.path().join("link");
|
||||||
std::os::unix::fs::symlink("dir", &link_path).unwrap();
|
std::os::unix::fs::symlink("dir", &link_path).unwrap();
|
||||||
let link = Meta::from_path(&link_path, false, false).unwrap();
|
let link = Meta::from_path(&link_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let grid_flags = Flags {
|
let grid_flags = Flags {
|
||||||
layout: Layout::Grid,
|
layout: Layout::Grid,
|
||||||
|
|
|
@ -13,10 +13,13 @@ use serde::Deserialize;
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum PermissionFlag {
|
pub enum PermissionFlag {
|
||||||
/// The variant to show file permissions in rwx format
|
/// The variant to show file permissions in rwx format
|
||||||
#[default]
|
#[cfg_attr(not(target_os = "windows"), default)]
|
||||||
Rwx,
|
Rwx,
|
||||||
/// The variant to show file permissions in octal format
|
/// The variant to show file permissions in octal format
|
||||||
Octal,
|
Octal,
|
||||||
|
/// (windows only): Attributes from powershell's `Get-ChildItem`
|
||||||
|
#[cfg_attr(target_os = "windows", default)]
|
||||||
|
Attributes,
|
||||||
/// Disable the display of owner and permissions, may be used to speed up in Windows
|
/// Disable the display of owner and permissions, may be used to speed up in Windows
|
||||||
Disable,
|
Disable,
|
||||||
}
|
}
|
||||||
|
@ -26,6 +29,7 @@ impl PermissionFlag {
|
||||||
match value {
|
match value {
|
||||||
"rwx" => Self::Rwx,
|
"rwx" => Self::Rwx,
|
||||||
"octal" => Self::Octal,
|
"octal" => Self::Octal,
|
||||||
|
"attributes" => Self::Attributes,
|
||||||
"disable" => Self::Disable,
|
"disable" => Self::Disable,
|
||||||
// Invalid value should be handled by `clap` when building an `Cli`
|
// Invalid value should be handled by `clap` when building an `Cli`
|
||||||
other => unreachable!("Invalid value '{other}' for 'permission'"),
|
other => unreachable!("Invalid value '{other}' for 'permission'"),
|
||||||
|
@ -75,7 +79,12 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default() {
|
fn test_default() {
|
||||||
assert_eq!(PermissionFlag::Rwx, PermissionFlag::default());
|
let expected = if cfg!(target_os = "windows") {
|
||||||
|
PermissionFlag::Attributes
|
||||||
|
} else {
|
||||||
|
PermissionFlag::Rwx
|
||||||
|
};
|
||||||
|
assert_eq!(expected, PermissionFlag::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -99,6 +108,16 @@ mod test {
|
||||||
assert_eq!(Some(PermissionFlag::Octal), PermissionFlag::from_cli(&cli));
|
assert_eq!(Some(PermissionFlag::Octal), PermissionFlag::from_cli(&cli));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_cli_attributes() {
|
||||||
|
let argv = ["lsd", "--permission", "attributes"];
|
||||||
|
let cli = Cli::try_parse_from(argv).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Some(PermissionFlag::Attributes),
|
||||||
|
PermissionFlag::from_cli(&cli)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_cli_permissions_disable() {
|
fn test_from_cli_permissions_disable() {
|
||||||
let argv = ["lsd", "--permission", "disable"];
|
let argv = ["lsd", "--permission", "disable"];
|
||||||
|
|
24
src/icon.rs
24
src/icon.rs
|
@ -75,7 +75,7 @@ impl Icons {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{IconTheme, Icons};
|
use super::{IconTheme, Icons};
|
||||||
use crate::flags::{IconOption, IconTheme as FlagTheme};
|
use crate::flags::{IconOption, IconTheme as FlagTheme, PermissionFlag};
|
||||||
use crate::meta::Meta;
|
use crate::meta::Meta;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
@ -85,7 +85,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icons = Icons::new(true, IconOption::Never, FlagTheme::Fancy, " ".to_string());
|
let icons = Icons::new(true, IconOption::Never, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon = icons.get(&meta.name);
|
let icon = icons.get(&meta.name);
|
||||||
|
@ -97,7 +97,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icons = Icons::new(false, IconOption::Never, FlagTheme::Fancy, " ".to_string());
|
let icons = Icons::new(false, IconOption::Never, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon = icons.get(&meta.name);
|
let icon = icons.get(&meta.name);
|
||||||
|
@ -110,7 +110,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icons = Icons::new(false, IconOption::Auto, FlagTheme::Fancy, " ".to_string());
|
let icons = Icons::new(false, IconOption::Auto, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon = icons.get(&meta.name);
|
let icon = icons.get(&meta.name);
|
||||||
|
@ -122,7 +122,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icons = Icons::new(true, IconOption::Auto, FlagTheme::Fancy, " ".to_string());
|
let icons = Icons::new(true, IconOption::Auto, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon = icons.get(&meta.name);
|
let icon = icons.get(&meta.name);
|
||||||
|
@ -135,7 +135,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file");
|
let file_path = tmp_dir.path().join("file");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(true, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
let icon = Icons::new(true, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon_str = icon.get(&meta.name);
|
let icon_str = icon.get(&meta.name);
|
||||||
|
@ -148,7 +148,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file");
|
let file_path = tmp_dir.path().join("file");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon_str = icon.get(&meta.name);
|
let icon_str = icon.get(&meta.name);
|
||||||
|
@ -161,7 +161,7 @@ mod test {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path().join("file");
|
let file_path = tmp_dir.path().join("file");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(
|
let icon = Icons::new(
|
||||||
false,
|
false,
|
||||||
|
@ -178,7 +178,7 @@ mod test {
|
||||||
fn get_icon_default_directory() {
|
fn get_icon_default_directory() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path();
|
let file_path = tmp_dir.path();
|
||||||
let meta = Meta::from_path(file_path, false, false).unwrap();
|
let meta = Meta::from_path(file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon_str = icon.get(&meta.name);
|
let icon_str = icon.get(&meta.name);
|
||||||
|
@ -190,7 +190,7 @@ mod test {
|
||||||
fn get_icon_default_directory_unicode() {
|
fn get_icon_default_directory_unicode() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
let file_path = tmp_dir.path();
|
let file_path = tmp_dir.path();
|
||||||
let meta = Meta::from_path(file_path, false, false).unwrap();
|
let meta = Meta::from_path(file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(
|
let icon = Icons::new(
|
||||||
false,
|
false,
|
||||||
|
@ -210,7 +210,7 @@ mod test {
|
||||||
for (file_name, file_icon) in &IconTheme::get_default_icons_by_name() {
|
for (file_name, file_icon) in &IconTheme::get_default_icons_by_name() {
|
||||||
let file_path = tmp_dir.path().join(file_name);
|
let file_path = tmp_dir.path().join(file_name);
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon_str = icon.get(&meta.name);
|
let icon_str = icon.get(&meta.name);
|
||||||
|
@ -226,7 +226,7 @@ mod test {
|
||||||
for (ext, file_icon) in &IconTheme::get_default_icons_by_extension() {
|
for (ext, file_icon) in &IconTheme::get_default_icons_by_extension() {
|
||||||
let file_path = tmp_dir.path().join(format!("file.{ext}"));
|
let file_path = tmp_dir.path().join(format!("file.{ext}"));
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
let icon = Icons::new(false, IconOption::Always, FlagTheme::Fancy, " ".to_string());
|
||||||
let icon_str = icon.get(&meta.name);
|
let icon_str = icon.get(&meta.name);
|
||||||
|
|
|
@ -110,6 +110,10 @@ mod test {
|
||||||
use super::FileType;
|
use super::FileType;
|
||||||
use crate::color::{Colors, ThemeOption};
|
use crate::color::{Colors, ThemeOption};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
use crate::flags::PermissionFlag;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use crate::meta::permissions_or_attributes::PermissionsOrAttributes;
|
||||||
|
#[cfg(unix)]
|
||||||
use crate::meta::Permissions;
|
use crate::meta::Permissions;
|
||||||
use crossterm::style::{Color, Stylize};
|
use crossterm::style::{Color, Stylize};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -144,14 +148,19 @@ mod test {
|
||||||
fn test_dir_type() {
|
fn test_dir_type() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let meta = crate::meta::Meta::from_path(tmp_dir.path(), false, false)
|
let meta = crate::meta::Meta::from_path(tmp_dir.path(), false, PermissionFlag::Rwx)
|
||||||
.expect("failed to get tempdir path");
|
.expect("failed to get tempdir path");
|
||||||
let metadata = tmp_dir.path().metadata().expect("failed to get metas");
|
let metadata = tmp_dir.path().metadata().expect("failed to get metas");
|
||||||
|
|
||||||
let colors = Colors::new(ThemeOption::NoLscolors);
|
let colors = Colors::new(ThemeOption::NoLscolors);
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let file_type = FileType::new(&metadata, None, &meta.permissions.unwrap());
|
let file_type = match meta.permissions_or_attributes {
|
||||||
|
Some(PermissionsOrAttributes::Permissions(permissions)) => {
|
||||||
|
FileType::new(&metadata, None, &permissions)
|
||||||
|
}
|
||||||
|
_ => panic!("unexpected"),
|
||||||
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let file_type = FileType::new(&metadata, None, tmp_dir.path());
|
let file_type = FileType::new(&metadata, None, tmp_dir.path());
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,10 @@ mod locale;
|
||||||
pub mod name;
|
pub mod name;
|
||||||
mod owner;
|
mod owner;
|
||||||
mod permissions;
|
mod permissions;
|
||||||
|
mod permissions_or_attributes;
|
||||||
mod size;
|
mod size;
|
||||||
mod symlink;
|
mod symlink;
|
||||||
|
mod windows_attributes;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod windows_utils;
|
mod windows_utils;
|
||||||
|
@ -25,6 +27,7 @@ pub use self::links::Links;
|
||||||
pub use self::name::Name;
|
pub use self::name::Name;
|
||||||
pub use self::owner::Owner;
|
pub use self::owner::Owner;
|
||||||
pub use self::permissions::Permissions;
|
pub use self::permissions::Permissions;
|
||||||
|
use self::permissions_or_attributes::PermissionsOrAttributes;
|
||||||
pub use self::size::Size;
|
pub use self::size::Size;
|
||||||
pub use self::symlink::SymLink;
|
pub use self::symlink::SymLink;
|
||||||
|
|
||||||
|
@ -35,11 +38,13 @@ use crate::git::GitCache;
|
||||||
use std::io::{self, Error, ErrorKind};
|
use std::io::{self, Error, ErrorKind};
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use self::windows_attributes::get_attributes;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Meta {
|
pub struct Meta {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub permissions: Option<Permissions>,
|
pub permissions_or_attributes: Option<PermissionsOrAttributes>,
|
||||||
pub date: Option<Date>,
|
pub date: Option<Date>,
|
||||||
pub owner: Option<Owner>,
|
pub owner: Option<Owner>,
|
||||||
pub file_type: FileType,
|
pub file_type: FileType,
|
||||||
|
@ -97,7 +102,7 @@ impl Meta {
|
||||||
let mut parent_meta = Self::from_path(
|
let mut parent_meta = Self::from_path(
|
||||||
&self.path.join(Component::ParentDir),
|
&self.path.join(Component::ParentDir),
|
||||||
flags.dereference.0,
|
flags.dereference.0,
|
||||||
flags.permission == PermissionFlag::Disable,
|
flags.permission,
|
||||||
)?;
|
)?;
|
||||||
parent_meta.name.name = "..".to_owned();
|
parent_meta.name.name = "..".to_owned();
|
||||||
|
|
||||||
|
@ -141,11 +146,8 @@ impl Meta {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut entry_meta = match Self::from_path(
|
let mut entry_meta = match Self::from_path(&path, flags.dereference.0, flags.permission)
|
||||||
&path,
|
{
|
||||||
flags.dereference.0,
|
|
||||||
flags.permission == PermissionFlag::Disable,
|
|
||||||
) {
|
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
print_error!("{}: {}.", path.display(), err);
|
print_error!("{}: {}.", path.display(), err);
|
||||||
|
@ -250,7 +252,11 @@ impl Meta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_path(path: &Path, dereference: bool, disable_permission: bool) -> io::Result<Self> {
|
pub fn from_path(
|
||||||
|
path: &Path,
|
||||||
|
dereference: bool,
|
||||||
|
permission_flag: PermissionFlag,
|
||||||
|
) -> io::Result<Self> {
|
||||||
let mut metadata = path.symlink_metadata()?;
|
let mut metadata = path.symlink_metadata()?;
|
||||||
let mut symlink_meta = None;
|
let mut symlink_meta = None;
|
||||||
let mut broken_link = false;
|
let mut broken_link = false;
|
||||||
|
@ -275,21 +281,30 @@ impl Meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let (owner, permissions) = if disable_permission {
|
let (owner, permissions) = match permission_flag {
|
||||||
(None, None)
|
PermissionFlag::Disable => (None, None),
|
||||||
} else {
|
_ => (
|
||||||
(
|
|
||||||
Some(Owner::from(&metadata)),
|
Some(Owner::from(&metadata)),
|
||||||
Some(Permissions::from(&metadata)),
|
Some(Permissions::from(&metadata)),
|
||||||
)
|
),
|
||||||
};
|
};
|
||||||
|
#[cfg(unix)]
|
||||||
|
let permissions_or_attributes = permissions.map(PermissionsOrAttributes::Permissions);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let (owner, permissions) = if disable_permission {
|
let (owner, permissions_or_attributes) = match permission_flag {
|
||||||
(None, None)
|
PermissionFlag::Disable => (None, None),
|
||||||
} else {
|
PermissionFlag::Attributes => (
|
||||||
match windows_utils::get_file_data(path) {
|
None,
|
||||||
Ok((owner, permissions)) => (Some(owner), Some(permissions)),
|
Some(PermissionsOrAttributes::WindowsAttributes(get_attributes(
|
||||||
|
&metadata,
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
_ => match windows_utils::get_file_data(path) {
|
||||||
|
Ok((owner, permissions)) => (
|
||||||
|
Some(owner),
|
||||||
|
Some(PermissionsOrAttributes::Permissions(permissions)),
|
||||||
|
),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"lsd: {}: {}(Hint: Consider using `--permission disabled`.)",
|
"lsd: {}: {}(Hint: Consider using `--permission disabled`.)",
|
||||||
|
@ -298,7 +313,7 @@ impl Meta {
|
||||||
);
|
);
|
||||||
(None, None)
|
(None, None)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
|
@ -313,7 +328,8 @@ impl Meta {
|
||||||
|
|
||||||
let name = Name::new(path, file_type);
|
let name = Name::new(path, file_type);
|
||||||
|
|
||||||
let (inode, links, size, date, owner, permissions, access_control) = match broken_link {
|
let (inode, links, size, date, owner, permissions_or_attributes, access_control) =
|
||||||
|
match broken_link {
|
||||||
true => (None, None, None, None, None, None, None),
|
true => (None, None, None, None, None, None, None),
|
||||||
false => (
|
false => (
|
||||||
Some(INode::from(&metadata)),
|
Some(INode::from(&metadata)),
|
||||||
|
@ -321,7 +337,7 @@ impl Meta {
|
||||||
Some(Size::from(&metadata)),
|
Some(Size::from(&metadata)),
|
||||||
Some(Date::from(&metadata)),
|
Some(Date::from(&metadata)),
|
||||||
Some(owner),
|
Some(owner),
|
||||||
Some(permissions),
|
Some(permissions_or_attributes),
|
||||||
Some(AccessControl::for_path(path)),
|
Some(AccessControl::for_path(path)),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
@ -335,7 +351,7 @@ impl Meta {
|
||||||
date,
|
date,
|
||||||
indicator: Indicator::from(file_type),
|
indicator: Indicator::from(file_type),
|
||||||
owner: owner.unwrap_or_default(),
|
owner: owner.unwrap_or_default(),
|
||||||
permissions: permissions.unwrap_or_default(),
|
permissions_or_attributes: permissions_or_attributes.unwrap_or_default(),
|
||||||
name,
|
name,
|
||||||
file_type,
|
file_type,
|
||||||
content: None,
|
content: None,
|
||||||
|
@ -347,6 +363,8 @@ impl Meta {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::flags::PermissionFlag;
|
||||||
|
|
||||||
use super::Meta;
|
use super::Meta;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
@ -355,15 +373,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_path_path() {
|
fn test_from_path_path() {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
let meta = Meta::from_path(dir.path(), false, false).unwrap();
|
let meta = Meta::from_path(dir.path(), false, PermissionFlag::Rwx).unwrap();
|
||||||
assert_eq!(meta.path, dir.path())
|
assert_eq!(meta.path, dir.path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_path_disable_permission() {
|
fn test_from_path_disable_permission() {
|
||||||
let dir = assert_fs::TempDir::new().unwrap();
|
let dir = assert_fs::TempDir::new().unwrap();
|
||||||
let meta = Meta::from_path(dir.path(), false, true).unwrap();
|
let meta = Meta::from_path(dir.path(), false, PermissionFlag::Disable).unwrap();
|
||||||
assert!(meta.permissions.is_none());
|
assert!(meta.permissions_or_attributes.is_none());
|
||||||
assert!(meta.owner.is_none());
|
assert!(meta.owner.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +391,8 @@ mod tests {
|
||||||
|
|
||||||
let path_a = tmp_dir.path().join("aaa.aa");
|
let path_a = tmp_dir.path().join("aaa.aa");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_b = tmp_dir.path().join("bbb.bb");
|
let path_b = tmp_dir.path().join("bbb.bb");
|
||||||
let path_c = tmp_dir.path().join("ccc.cc");
|
let path_c = tmp_dir.path().join("ccc.cc");
|
||||||
|
@ -388,7 +407,8 @@ mod tests {
|
||||||
std::os::windows::fs::symlink_file(path_c, &path_b)
|
std::os::windows::fs::symlink_file(path_c, &path_b)
|
||||||
.expect("failed to create broken symlink");
|
.expect("failed to create broken symlink");
|
||||||
|
|
||||||
let meta_b = Meta::from_path(&path_b, true, false).expect("failed to get meta");
|
let meta_b =
|
||||||
|
Meta::from_path(&path_b, true, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
meta_a.inode.is_some()
|
meta_a.inode.is_some()
|
||||||
|
@ -396,7 +416,7 @@ mod tests {
|
||||||
&& meta_a.size.is_some()
|
&& meta_a.size.is_some()
|
||||||
&& meta_a.date.is_some()
|
&& meta_a.date.is_some()
|
||||||
&& meta_a.owner.is_some()
|
&& meta_a.owner.is_some()
|
||||||
&& meta_a.permissions.is_some()
|
&& meta_a.permissions_or_attributes.is_some()
|
||||||
&& meta_a.access_control.is_some()
|
&& meta_a.access_control.is_some()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -406,7 +426,7 @@ mod tests {
|
||||||
&& meta_b.size.is_none()
|
&& meta_b.size.is_none()
|
||||||
&& meta_b.date.is_none()
|
&& meta_b.date.is_none()
|
||||||
&& meta_b.owner.is_none()
|
&& meta_b.owner.is_none()
|
||||||
&& meta_b.permissions.is_none()
|
&& meta_b.permissions_or_attributes.is_none()
|
||||||
&& meta_b.access_control.is_none()
|
&& meta_b.access_control.is_none()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,7 @@ mod test {
|
||||||
use super::DisplayOption;
|
use super::DisplayOption;
|
||||||
use super::Name;
|
use super::Name;
|
||||||
use crate::color::{self, Colors};
|
use crate::color::{self, Colors};
|
||||||
|
use crate::flags::PermissionFlag;
|
||||||
use crate::flags::{HyperlinkOption, IconOption, IconTheme as FlagTheme};
|
use crate::flags::{HyperlinkOption, IconOption, IconTheme as FlagTheme};
|
||||||
use crate::icon::Icons;
|
use crate::icon::Icons;
|
||||||
use crate::meta::FileType;
|
use crate::meta::FileType;
|
||||||
|
@ -274,7 +275,7 @@ mod test {
|
||||||
// Create the directory
|
// Create the directory
|
||||||
let dir_path = tmp_dir.path().join("directory");
|
let dir_path = tmp_dir.path().join("directory");
|
||||||
fs::create_dir(&dir_path).expect("failed to create the dir");
|
fs::create_dir(&dir_path).expect("failed to create the dir");
|
||||||
let meta = Meta::from_path(&dir_path, false, false).unwrap();
|
let meta = Meta::from_path(&dir_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let colors = Colors::new(color::ThemeOption::NoLscolors);
|
let colors = Colors::new(color::ThemeOption::NoLscolors);
|
||||||
|
|
||||||
|
@ -398,7 +399,7 @@ mod test {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let colors = Colors::new(color::ThemeOption::NoColor);
|
let colors = Colors::new(color::ThemeOption::NoColor);
|
||||||
|
|
||||||
|
@ -424,7 +425,7 @@ mod test {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let file_path = tmp_dir.path().join("file.txt");
|
let file_path = tmp_dir.path().join("file.txt");
|
||||||
File::create(&file_path).expect("failed to create file");
|
File::create(&file_path).expect("failed to create file");
|
||||||
let meta = Meta::from_path(&file_path, false, false).unwrap();
|
let meta = Meta::from_path(&file_path, false, PermissionFlag::Rwx).unwrap();
|
||||||
|
|
||||||
let colors = Colors::new(color::ThemeOption::NoColor);
|
let colors = Colors::new(color::ThemeOption::NoColor);
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,8 @@ impl Permissions {
|
||||||
|
|
||||||
colors.colorize(octals, &Elem::Octal).to_string()
|
colors.colorize(octals, &Elem::Octal).to_string()
|
||||||
}
|
}
|
||||||
|
// technically this should be an error, hmm
|
||||||
|
PermissionFlag::Attributes => colors.colorize('-', &Elem::NoAccess).to_string(),
|
||||||
PermissionFlag::Disable => colors.colorize('-', &Elem::NoAccess).to_string(),
|
PermissionFlag::Disable => colors.colorize('-', &Elem::NoAccess).to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
27
src/meta/permissions_or_attributes.rs
Normal file
27
src/meta/permissions_or_attributes.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#[cfg(windows)]
|
||||||
|
use super::windows_attributes::WindowsAttributes;
|
||||||
|
use crate::{
|
||||||
|
color::{ColoredString, Colors},
|
||||||
|
flags::Flags,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Permissions;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum PermissionsOrAttributes {
|
||||||
|
Permissions(Permissions),
|
||||||
|
#[cfg(windows)]
|
||||||
|
WindowsAttributes(WindowsAttributes),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PermissionsOrAttributes {
|
||||||
|
pub fn render(&self, colors: &Colors, flags: &Flags) -> ColoredString {
|
||||||
|
match self {
|
||||||
|
PermissionsOrAttributes::Permissions(permissions) => permissions.render(colors, flags),
|
||||||
|
#[cfg(windows)]
|
||||||
|
PermissionsOrAttributes::WindowsAttributes(attributes) => {
|
||||||
|
attributes.render(colors, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
src/meta/windows_attributes.rs
Normal file
126
src/meta/windows_attributes.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#[cfg(windows)]
|
||||||
|
use crate::{
|
||||||
|
color::{ColoredString, Colors, Elem},
|
||||||
|
flags::Flags,
|
||||||
|
};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::os::windows::fs::MetadataExt;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct WindowsAttributes {
|
||||||
|
pub archive: bool,
|
||||||
|
pub readonly: bool,
|
||||||
|
pub hidden: bool,
|
||||||
|
pub system: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn get_attributes(metadata: &std::fs::Metadata) -> WindowsAttributes {
|
||||||
|
use windows::Win32::Storage::FileSystem::{
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM, FILE_FLAGS_AND_ATTRIBUTES,
|
||||||
|
};
|
||||||
|
|
||||||
|
let bits = metadata.file_attributes();
|
||||||
|
let has_bit = |bit: FILE_FLAGS_AND_ATTRIBUTES| bits & bit.0 == bit.0;
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
|
||||||
|
WindowsAttributes {
|
||||||
|
archive: has_bit(FILE_ATTRIBUTE_ARCHIVE),
|
||||||
|
readonly: has_bit(FILE_ATTRIBUTE_READONLY),
|
||||||
|
hidden: has_bit(FILE_ATTRIBUTE_HIDDEN),
|
||||||
|
system: has_bit(FILE_ATTRIBUTE_SYSTEM),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl WindowsAttributes {
|
||||||
|
pub fn render(&self, colors: &Colors, _flags: &Flags) -> ColoredString {
|
||||||
|
let res = [
|
||||||
|
match self.archive {
|
||||||
|
true => colors.colorize("a", &Elem::Archive),
|
||||||
|
false => colors.colorize('-', &Elem::NoAccess),
|
||||||
|
},
|
||||||
|
match self.readonly {
|
||||||
|
true => colors.colorize("r", &Elem::AttributeRead),
|
||||||
|
false => colors.colorize('-', &Elem::NoAccess),
|
||||||
|
},
|
||||||
|
match self.hidden {
|
||||||
|
true => colors.colorize("h", &Elem::Hidden),
|
||||||
|
false => colors.colorize('-', &Elem::NoAccess),
|
||||||
|
},
|
||||||
|
match self.system {
|
||||||
|
true => colors.colorize("s", &Elem::System),
|
||||||
|
false => colors.colorize('-', &Elem::NoAccess),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.fold(String::with_capacity(4), |mut acc, x| {
|
||||||
|
acc.push_str(&x.to_string());
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
ColoredString::new(Colors::default_style(), res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
color::{Colors, ThemeOption},
|
||||||
|
flags::Flags,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::get_attributes;
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn archived_file() {
|
||||||
|
let attribute_string = create_and_process_file_with_attributes("archived_file.txt", "+A");
|
||||||
|
assert_eq!("a---", attribute_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn readonly_file() {
|
||||||
|
let attribute_string = create_and_process_file_with_attributes("readonly_file.txt", "+R");
|
||||||
|
assert_eq!("ar--", attribute_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn hidden_file() {
|
||||||
|
let attribute_string = create_and_process_file_with_attributes("hidden_file.txt", "+H");
|
||||||
|
assert_eq!("a-h-", attribute_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn system_file() {
|
||||||
|
let attribute_string = create_and_process_file_with_attributes("system_file.txt", "+S");
|
||||||
|
assert_eq!("a--s", attribute_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_and_process_file_with_attributes(name: &str, attrs: &str) -> String {
|
||||||
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
let path = tmp_dir.path().join(name);
|
||||||
|
let mut file = fs::File::create(path.clone()).unwrap();
|
||||||
|
writeln!(file, "Test content").unwrap();
|
||||||
|
Command::new("attrib")
|
||||||
|
.arg(attrs)
|
||||||
|
.arg(&path)
|
||||||
|
.output()
|
||||||
|
.expect("able to set attributes");
|
||||||
|
let metadata = file.metadata().expect("able to get metadata");
|
||||||
|
|
||||||
|
let colors = Colors::new(ThemeOption::NoColor);
|
||||||
|
|
||||||
|
let attributes = get_attributes(&metadata);
|
||||||
|
attributes
|
||||||
|
.render(&colors, &Flags::default())
|
||||||
|
.content()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
74
src/sort.rs
74
src/sort.rs
|
@ -80,7 +80,7 @@ fn by_git_status(a: &Meta, b: &Meta) -> Ordering {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::flags::Flags;
|
use crate::flags::{Flags, PermissionFlag};
|
||||||
use std::fs::{create_dir, File};
|
use std::fs::{create_dir, File};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -93,12 +93,14 @@ mod tests {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_a = tmp_dir.path().join("zzz");
|
let path_a = tmp_dir.path().join("zzz");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create a dir;
|
// Create a dir;
|
||||||
let path_z = tmp_dir.path().join("aaa");
|
let path_z = tmp_dir.path().join("aaa");
|
||||||
create_dir(&path_z).expect("failed to create dir");
|
create_dir(&path_z).expect("failed to create dir");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.dir_grouping = DirGrouping::First;
|
flags.sorting.dir_grouping = DirGrouping::First;
|
||||||
|
@ -121,12 +123,14 @@ mod tests {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_a = tmp_dir.path().join("zzz");
|
let path_a = tmp_dir.path().join("zzz");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create a dir;
|
// Create a dir;
|
||||||
let path_z = tmp_dir.path().join("aaa");
|
let path_z = tmp_dir.path().join("aaa");
|
||||||
create_dir(&path_z).expect("failed to create dir");
|
create_dir(&path_z).expect("failed to create dir");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.dir_grouping = DirGrouping::Last;
|
flags.sorting.dir_grouping = DirGrouping::Last;
|
||||||
|
@ -147,12 +151,14 @@ mod tests {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_a = tmp_dir.path().join("aaa");
|
let path_a = tmp_dir.path().join("aaa");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create a dir;
|
// Create a dir;
|
||||||
let path_z = tmp_dir.path().join("zzz");
|
let path_z = tmp_dir.path().join("zzz");
|
||||||
create_dir(&path_z).expect("failed to create dir");
|
create_dir(&path_z).expect("failed to create dir");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.dir_grouping = DirGrouping::None;
|
flags.sorting.dir_grouping = DirGrouping::None;
|
||||||
|
@ -175,12 +181,14 @@ mod tests {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_a = tmp_dir.path().join("zzz");
|
let path_a = tmp_dir.path().join("zzz");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create a dir;
|
// Create a dir;
|
||||||
let path_z = tmp_dir.path().join("aaa");
|
let path_z = tmp_dir.path().join("aaa");
|
||||||
create_dir(&path_z).expect("failed to create dir");
|
create_dir(&path_z).expect("failed to create dir");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.dir_grouping = DirGrouping::None;
|
flags.sorting.dir_grouping = DirGrouping::None;
|
||||||
|
@ -203,7 +211,8 @@ mod tests {
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_a = tmp_dir.path().join("aaa");
|
let path_a = tmp_dir.path().join("aaa");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
let path_z = tmp_dir.path().join("zzz");
|
let path_z = tmp_dir.path().join("zzz");
|
||||||
|
@ -229,7 +238,8 @@ mod tests {
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
assert!(success, "failed to change file timestamp");
|
assert!(success, "failed to change file timestamp");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.column = SortColumn::Time;
|
flags.sorting.column = SortColumn::Time;
|
||||||
|
@ -251,22 +261,26 @@ mod tests {
|
||||||
// Create the file with rs extension;
|
// Create the file with rs extension;
|
||||||
let path_a = tmp_dir.path().join("aaa.rs");
|
let path_a = tmp_dir.path().join("aaa.rs");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create the file with rs extension;
|
// Create the file with rs extension;
|
||||||
let path_z = tmp_dir.path().join("zzz.rs");
|
let path_z = tmp_dir.path().join("zzz.rs");
|
||||||
File::create(&path_z).expect("failed to create file");
|
File::create(&path_z).expect("failed to create file");
|
||||||
let meta_z = Meta::from_path(&path_z, false, false).expect("failed to get meta");
|
let meta_z =
|
||||||
|
Meta::from_path(&path_z, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create the file with js extension;
|
// Create the file with js extension;
|
||||||
let path_j = tmp_dir.path().join("zzz.js");
|
let path_j = tmp_dir.path().join("zzz.js");
|
||||||
File::create(&path_j).expect("failed to create file");
|
File::create(&path_j).expect("failed to create file");
|
||||||
let meta_j = Meta::from_path(&path_j, false, false).expect("failed to get meta");
|
let meta_j =
|
||||||
|
Meta::from_path(&path_j, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
// Create the file with txt extension;
|
// Create the file with txt extension;
|
||||||
let path_t = tmp_dir.path().join("zzz.txt");
|
let path_t = tmp_dir.path().join("zzz.txt");
|
||||||
File::create(&path_t).expect("failed to create file");
|
File::create(&path_t).expect("failed to create file");
|
||||||
let meta_t = Meta::from_path(&path_t, false, false).expect("failed to get meta");
|
let meta_t =
|
||||||
|
Meta::from_path(&path_t, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.column = SortColumn::Extension;
|
flags.sorting.column = SortColumn::Extension;
|
||||||
|
@ -288,15 +302,18 @@ mod tests {
|
||||||
|
|
||||||
let path_a = tmp_dir.path().join("2");
|
let path_a = tmp_dir.path().join("2");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_b = tmp_dir.path().join("11");
|
let path_b = tmp_dir.path().join("11");
|
||||||
File::create(&path_b).expect("failed to create file");
|
File::create(&path_b).expect("failed to create file");
|
||||||
let meta_b = Meta::from_path(&path_b, false, false).expect("failed to get meta");
|
let meta_b =
|
||||||
|
Meta::from_path(&path_b, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_c = tmp_dir.path().join("12");
|
let path_c = tmp_dir.path().join("12");
|
||||||
File::create(&path_c).expect("failed to create file");
|
File::create(&path_c).expect("failed to create file");
|
||||||
let meta_c = Meta::from_path(&path_c, false, false).expect("failed to get meta");
|
let meta_c =
|
||||||
|
Meta::from_path(&path_c, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.column = SortColumn::Version;
|
flags.sorting.column = SortColumn::Version;
|
||||||
|
@ -314,19 +331,23 @@ mod tests {
|
||||||
|
|
||||||
let path_a = tmp_dir.path().join("aaa.aa");
|
let path_a = tmp_dir.path().join("aaa.aa");
|
||||||
File::create(&path_a).expect("failed to create file");
|
File::create(&path_a).expect("failed to create file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_b = tmp_dir.path().join("aaa");
|
let path_b = tmp_dir.path().join("aaa");
|
||||||
create_dir(&path_b).expect("failed to create dir");
|
create_dir(&path_b).expect("failed to create dir");
|
||||||
let meta_b = Meta::from_path(&path_b, false, false).expect("failed to get meta");
|
let meta_b =
|
||||||
|
Meta::from_path(&path_b, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_c = tmp_dir.path().join("zzz.zz");
|
let path_c = tmp_dir.path().join("zzz.zz");
|
||||||
File::create(&path_c).expect("failed to create file");
|
File::create(&path_c).expect("failed to create file");
|
||||||
let meta_c = Meta::from_path(&path_c, false, false).expect("failed to get meta");
|
let meta_c =
|
||||||
|
Meta::from_path(&path_c, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_d = tmp_dir.path().join("zzz");
|
let path_d = tmp_dir.path().join("zzz");
|
||||||
create_dir(&path_d).expect("failed to create dir");
|
create_dir(&path_d).expect("failed to create dir");
|
||||||
let meta_d = Meta::from_path(&path_d, false, false).expect("failed to get meta");
|
let meta_d =
|
||||||
|
Meta::from_path(&path_d, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let mut flags = Flags::default();
|
let mut flags = Flags::default();
|
||||||
flags.sorting.column = SortColumn::None;
|
flags.sorting.column = SortColumn::None;
|
||||||
|
@ -359,14 +380,16 @@ mod tests {
|
||||||
.expect("failed to create file")
|
.expect("failed to create file")
|
||||||
.write_all(b"1, 2, 3")
|
.write_all(b"1, 2, 3")
|
||||||
.expect("failed to write to file");
|
.expect("failed to write to file");
|
||||||
let meta_a = Meta::from_path(&path_a, false, false).expect("failed to get meta");
|
let meta_a =
|
||||||
|
Meta::from_path(&path_a, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_b = tmp_dir.path().join("bbb.bb");
|
let path_b = tmp_dir.path().join("bbb.bb");
|
||||||
File::create(&path_b)
|
File::create(&path_b)
|
||||||
.expect("failed to create file")
|
.expect("failed to create file")
|
||||||
.write_all(b"1, 2, 3, 4, 5, 6, 7, 8, 9, 10")
|
.write_all(b"1, 2, 3, 4, 5, 6, 7, 8, 9, 10")
|
||||||
.expect("failed to write file");
|
.expect("failed to write file");
|
||||||
let meta_b = Meta::from_path(&path_b, false, false).expect("failed to get meta");
|
let meta_b =
|
||||||
|
Meta::from_path(&path_b, false, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
let path_c = tmp_dir.path().join("ccc.cc");
|
let path_c = tmp_dir.path().join("ccc.cc");
|
||||||
let path_d = tmp_dir.path().join("ddd.dd");
|
let path_d = tmp_dir.path().join("ddd.dd");
|
||||||
|
@ -381,7 +404,8 @@ mod tests {
|
||||||
std::os::windows::fs::symlink_file(path_d, &path_c)
|
std::os::windows::fs::symlink_file(path_d, &path_c)
|
||||||
.expect("failed to create broken symlink");
|
.expect("failed to create broken symlink");
|
||||||
|
|
||||||
let meta_c = Meta::from_path(&path_c, true, false).expect("failed to get meta");
|
let meta_c =
|
||||||
|
Meta::from_path(&path_c, true, PermissionFlag::Rwx).expect("failed to get meta");
|
||||||
|
|
||||||
assert_eq!(by_size(&meta_a, &meta_a), Ordering::Equal);
|
assert_eq!(by_size(&meta_a, &meta_a), Ordering::Equal);
|
||||||
assert_eq!(by_size(&meta_a, &meta_b), Ordering::Greater);
|
assert_eq!(by_size(&meta_a, &meta_b), Ordering::Greater);
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub struct ColorTheme {
|
||||||
#[serde(deserialize_with = "deserialize_color")]
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
pub group: Color,
|
pub group: Color,
|
||||||
pub permission: Permission,
|
pub permission: Permission,
|
||||||
|
pub attributes: Attributes,
|
||||||
pub date: Date,
|
pub date: Date,
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
pub inode: INode,
|
pub inode: INode,
|
||||||
|
@ -124,6 +125,21 @@ pub struct Permission {
|
||||||
pub context: Color,
|
pub context: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Attributes {
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
pub archive: Color,
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
pub read: Color,
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
pub hidden: Color,
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
pub system: Color,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
|
@ -274,6 +290,16 @@ impl Default for Permission {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Default for Attributes {
|
||||||
|
fn default() -> Self {
|
||||||
|
Attributes {
|
||||||
|
archive: Color::DarkGreen,
|
||||||
|
read: Color::DarkYellow,
|
||||||
|
hidden: Color::AnsiValue(13), // Pink,
|
||||||
|
system: Color::AnsiValue(13), // Pink,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Default for FileType {
|
impl Default for FileType {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FileType {
|
FileType {
|
||||||
|
@ -381,6 +407,7 @@ impl ColorTheme {
|
||||||
user: Color::AnsiValue(230), // Cornsilk1
|
user: Color::AnsiValue(230), // Cornsilk1
|
||||||
group: Color::AnsiValue(187), // LightYellow3
|
group: Color::AnsiValue(187), // LightYellow3
|
||||||
permission: Permission::default(),
|
permission: Permission::default(),
|
||||||
|
attributes: Attributes::default(),
|
||||||
file_type: FileType::default(),
|
file_type: FileType::default(),
|
||||||
date: Date::default(),
|
date: Date::default(),
|
||||||
size: Size::default(),
|
size: Size::default(),
|
||||||
|
|
Loading…
Reference in a new issue