Skip to content

Commit

Permalink
[chronicler] show user and group
Browse files Browse the repository at this point in the history
  • Loading branch information
aslpavel committed Apr 6, 2024
1 parent 712ad87 commit a0c179d
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 28 deletions.
3 changes: 2 additions & 1 deletion chronicler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "chronicler"
build = "build.rs"
version = "0.3.2"
version = "0.3.3"
edition = "2021"

[dependencies]
Expand All @@ -21,6 +21,7 @@ time = { version = "^0.3", features = ["macros"] }
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1.10", features = ["fs"] }
unix_mode = "^0.1"
uzers = "^0.11"
tracing = "^0.1"
tracing-appender = "^0.2"
tracing-subscriber = "^0.3"
47 changes: 44 additions & 3 deletions chronicler/src/history.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::navigator::{NavigatorContext, FAILED_ICON, FOLDER_ICON};
use crate::{
navigator::{NavigatorContext, FAILED_ICON, FOLDER_ICON},
utils::Table,
};

use super::DATE_FORMAT;
use anyhow::{Context, Error};
Expand Down Expand Up @@ -115,12 +118,50 @@ impl Haystack for HistoryEntry {
})()
.expect("in memory write failed");

let view = Container::new(text.take())
let left_face = Face::default()
// .with_fg(Some(theme.accent))
// .with_bg(Some(theme.accent.with_alpha(0.05)))
.with_attrs(FaceAttrs::BOLD);
let mut table = Table::new(10, Some(left_face), None);
table.push(
Text::new().push_str("Status", None).take(),
Text::new().push_fmt(format_args!("{}", self.status)).take(),
);
if let Some(date) = self
.start_dt()
.ok()
.and_then(|date| date.format(&DATE_FORMAT).ok())
{
table.push(
Text::new().push_str("Date", None).take(),
Text::new().push_str(date.as_str(), None).take(),
)
}
table.push(
Text::new().push_str("Duration", None).take(),
Text::new()
.push_fmt(format_args!("{:.3}s", self.end_ts - self.start_ts))
.take(),
);
table.push(
Text::new().push_str("User", None).take(),
Text::new().push_str(&self.user, None).take(),
);
table.push(
Text::new().push_str("Hostname", None).take(),
Text::new().push_str(&self.hostname, None).take(),
);
table.push(
Text::new().push_str("Directory", None).take(),
Text::new().push_str(&self.cwd, None).take(),
);

let view = Container::new(table)
.with_horizontal(Align::Expand)
.with_vertical(Align::Expand)
.with_color(theme.list_selected.bg.unwrap_or(theme.bg))
.boxed();
Some(HaystackPreview::new(view, Some(0.6)))
Some(HaystackPreview::new(view, Some(0.7)))
}
}

Expand Down
2 changes: 1 addition & 1 deletion chronicler/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const HISTORY_DB: &str = "chronicler/history.db";
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

const DATE_FORMAT: &[FormatItem<'_>] =
format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]");
format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");

#[tokio::main]
async fn main() -> Result<(), Error> {
Expand Down
33 changes: 32 additions & 1 deletion chronicler/src/navigator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ use std::{
io::Write,
os::unix::prelude::OsStrExt,
path::{Path, PathBuf},
sync::Arc,
sync::{Arc, RwLock},
};
use sweep::{
common::LockExt,
surf_n_term::{Glyph, Key},
Haystack, HaystackPreview, Positions, Sweep, SweepEvent, SweepOptions,
};
Expand All @@ -29,6 +30,34 @@ pub enum NavigatorItem {
pub struct NavigatorContext {
pub cwd: Arc<str>,
pub home_dir: Arc<str>,
users_cache: Arc<RwLock<HashMap<u32, Option<uzers::User>>>>,
groups_cache: Arc<RwLock<HashMap<u32, Option<uzers::Group>>>>,
}

impl NavigatorContext {
pub fn get_group_by_gid(&self, gid: u32) -> Option<uzers::Group> {
match self.groups_cache.with(|groups| groups.get(&gid).cloned()) {
Some(group) => group,
None => {
let group = uzers::get_group_by_gid(gid);
self.groups_cache
.with_mut(|groups| groups.insert(gid, group.clone()));
group
}
}
}

pub fn get_user_by_uid(&self, uid: u32) -> Option<uzers::User> {
match self.users_cache.with(|users| users.get(&uid).cloned()) {
Some(user) => user,
None => {
let user = uzers::get_user_by_uid(uid);
self.users_cache
.with_mut(|users| users.insert(uid, user.clone()));
user
}
}
}
}

impl NavigatorItem {
Expand Down Expand Up @@ -120,6 +149,8 @@ impl Navigator {
home_dir: dirs::home_dir()
.map_or_else(String::new, |path| path.to_string_lossy().into_owned())
.into(),
users_cache: Default::default(),
groups_cache: Default::default(),
};
let sweep = Sweep::new(ctx, options)?;
sweep.scorer_by_name(Some("substr".to_owned())).await?;
Expand Down
48 changes: 48 additions & 0 deletions chronicler/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ use std::{
pin::Pin,
task::{Context, Poll},
};
use sweep::surf_n_term::{
view::{Align, Container, Flex, IntoView},
Face,
};
use tokio::task::JoinHandle;

#[derive(Debug)]
Expand Down Expand Up @@ -36,3 +40,47 @@ impl<T> Deref for AbortJoinHandle<T> {
&self.handle
}
}

pub(crate) struct Table<'a> {
left_width: usize,
left_face: Option<Face>,
right_face: Option<Face>,
view: Flex<'a>,
}

impl<'a> Table<'a> {
pub(crate) fn new(
left_width: usize,
left_face: Option<Face>,
right_face: Option<Face>,
) -> Self {
Self {
left_width,
left_face,
right_face,
view: Flex::column(),
}
}

pub(crate) fn push(&mut self, left: impl IntoView + 'a, right: impl IntoView + 'a) {
let row = Flex::row()
.add_child_ext(
Container::new(left)
.with_width(self.left_width)
.with_horizontal(Align::Expand),
None,
self.left_face,
Align::Start,
)
.add_child_ext(right, None, self.right_face, Align::Start);
self.view.push_child(row)
}
}

impl<'a> IntoView for Table<'a> {
type View = Flex<'a>;

fn into_view(self) -> Self::View {
self.view
}
}
52 changes: 30 additions & 22 deletions chronicler/src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use std::{
task::Poll,
};
use sweep::{
surf_n_term::view::{BoxView, Flex, Justify, Text, View},
surf_n_term::{
view::{BoxView, Flex, Justify, Text, View},
Face, FaceAttrs,
},
Haystack,
};
use time::OffsetDateTime;
Expand Down Expand Up @@ -148,38 +151,43 @@ impl Haystack for PathItem {

fn preview(
&self,
_ctx: &Self::Context,
ctx: &Self::Context,
_positions: &sweep::Positions,
_theme: &sweep::Theme,
) -> Option<sweep::HaystackPreview> {
let metadata = self.metadata.as_ref()?;
let left_face = Some(Face::default().with_attrs(FaceAttrs::BOLD));
let mut text = Text::new()
.push_fmt(format_args!(
"Mode: {}\n",
unix_mode::to_string(metadata.mode())
))
.push_fmt(format_args!(
"Size: {:.2}\n",
SizeDisplay::new(metadata.len())
))
.push_str("Mode ", left_face)
.push_fmt(format_args!("{}\n", unix_mode::to_string(metadata.mode())))
.push_str("Size ", left_face)
.push_fmt(format_args!("{:.2}\n", SizeDisplay::new(metadata.len())))
.take();
text.push_str("Owner ", left_face);
match ctx.get_user_by_uid(metadata.uid()) {
None => text.push_fmt(format_args!("{}", metadata.uid())),
Some(user) => text.push_fmt(format_args!("{}", user.name().to_string_lossy())),
};
text.push_str(":", None);
match ctx.get_group_by_gid(metadata.gid()) {
None => text.push_fmt(format_args!("{}", metadata.uid())),
Some(group) => text.push_fmt(format_args!("{}", group.name().to_string_lossy())),
};
text.push_str("\n", None);
if let Ok(created) = metadata.created() {
text.push_fmt(format_args!(
"Created: {}\n",
OffsetDateTime::from(created).format(&DATE_FORMAT).ok()?,
));
let date = OffsetDateTime::from(created).format(&DATE_FORMAT).ok()?;
text.push_str("Created ", left_face);
text.push_fmt(format_args!("{}\n", date));
}
if let Ok(modified) = metadata.modified() {
text.push_fmt(format_args!(
"Modified: {}\n",
OffsetDateTime::from(modified).format(&DATE_FORMAT).ok()?,
));
let date = OffsetDateTime::from(modified).format(&DATE_FORMAT).ok()?;
text.push_str("Modified ", left_face);
text.push_fmt(format_args!("{}\n", date));
}
if let Ok(accessed) = metadata.accessed() {
text.push_fmt(format_args!(
"Accessed: {}\n",
OffsetDateTime::from(accessed).format(&DATE_FORMAT).ok()?,
));
let date = OffsetDateTime::from(accessed).format(&DATE_FORMAT).ok()?;
text.push_str("Accessed ", left_face);
text.push_fmt(format_args!("{}\n", date));
}
Some(sweep::HaystackPreview::new(text.boxed(), None))
}
Expand Down

0 comments on commit a0c179d

Please sign in to comment.