diff --git a/docs/en/src/column-renderer.md b/docs/en/src/column-renderer.md index 3d14f19..19d4f77 100644 --- a/docs/en/src/column-renderer.md +++ b/docs/en/src/column-renderer.md @@ -36,6 +36,8 @@ The special argument contains the following fields - [permissions][15] - [created][34] - [last_modified][35] +- [uid][36] +- [gid][37] - [canonical][16] - [symlink][17] - [index][18] @@ -141,6 +143,18 @@ Type: nullable integer Last modification time in nanosecond since UNIX epoch. +### uid + +Type: integer + +User ID of the file owner. + +### gid + +Type: integer + +Group ID of the file owner. + ### canonical Type: nullable [Resolved Node Metadata][31] @@ -256,6 +270,8 @@ It contains the following fields. - [human_size][14] - [created][34] - [last_modified][35] +- [uid][36] +- [gid][37] ## Example: Customizing Table Renderer @@ -315,3 +331,5 @@ xplr.config.general.table.col_widths = { [33]: node-type.md#meta [34]: #created [35]: #last_modified +[36]: #uid +[37]: #gid diff --git a/src/node.rs b/src/node.rs index 84ef96c..befc9ac 100644 --- a/src/node.rs +++ b/src/node.rs @@ -2,6 +2,7 @@ use crate::permissions::Permissions; use humansize::{file_size_opts as options, FileSize}; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; +use std::os::unix::prelude::MetadataExt; use std::path::{Path, PathBuf}; use std::time::UNIX_EPOCH; @@ -33,6 +34,8 @@ pub struct ResolvedNode { pub human_size: String, pub created: Option, pub last_modified: Option, + pub uid: u32, + pub gid: u32, } impl ResolvedNode { @@ -42,25 +45,27 @@ impl ResolvedNode { .map(|e| e.to_string_lossy().to_string()) .unwrap_or_default(); - let (is_dir, is_file, is_readonly, size, created, last_modified) = path - .metadata() - .map(|m| { - ( - m.is_dir(), - m.is_file(), - m.permissions().readonly(), - m.len(), - m.created() - .ok() - .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) - .map(|d| d.as_nanos()), - m.modified() - .ok() - .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) - .map(|d| d.as_nanos()), - ) - }) - .unwrap_or((false, false, false, 0, None, None)); + let (is_dir, is_file, is_readonly, size, created, last_modified, uid, gid) = + path.metadata() + .map(|m| { + ( + m.is_dir(), + m.is_file(), + m.permissions().readonly(), + m.len(), + m.created() + .ok() + .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) + .map(|d| d.as_nanos()), + m.modified() + .ok() + .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) + .map(|d| d.as_nanos()), + m.uid(), + m.gid(), + ) + }) + .unwrap_or((false, false, false, 0, None, None, 0, 0)); let mime_essence = mime_essence(&path, is_dir); let human_size = to_human_size(size); @@ -76,6 +81,8 @@ impl ResolvedNode { human_size, created, last_modified, + uid, + gid, } } } @@ -97,6 +104,8 @@ pub struct Node { pub permissions: Permissions, pub created: Option, pub last_modified: Option, + pub uid: u32, + pub gid: u32, pub canonical: Option, pub symlink: Option, @@ -130,6 +139,8 @@ impl Node { permissions, created, last_modified, + uid, + gid, ) = path .symlink_metadata() .map(|m| { @@ -148,6 +159,8 @@ impl Node { .ok() .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) .map(|d| d.as_nanos()), + m.uid(), + m.gid(), ) }) .unwrap_or_else(|_| { @@ -160,6 +173,8 @@ impl Node { Permissions::default(), None, None, + 0, + 0, ) }); @@ -182,6 +197,8 @@ impl Node { permissions, created, last_modified, + uid, + gid, canonical: maybe_canonical_meta.clone(), symlink: if is_symlink { maybe_canonical_meta diff --git a/src/ui.rs b/src/ui.rs index 2f8cd57..5bfdcfd 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -410,6 +410,8 @@ pub struct NodeUiMetadata { pub symlink: Option, pub created: Option, pub last_modified: Option, + pub uid: u32, + pub gid: u32, // Extra pub index: usize, @@ -458,6 +460,8 @@ impl NodeUiMetadata { symlink: node.symlink.to_owned().map(ResolvedNode::into), created: node.created, last_modified: node.last_modified, + uid: node.uid, + gid: node.gid, index, relative_index, is_before_focus,