summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLzzzzzt <101313294+Lzzzzzt@users.noreply.github.com>2023-08-05 06:36:38 +0800
committerGitHub <noreply@github.com>2023-08-04 18:36:38 -0400
commita97ca3027bf66dbf16db7737ad5288fa9aaa89f2 (patch)
tree0dbf25b3c658d109d195ca753e9b941c36e332f4
parent48e42e21dd0c0774cdee649b2134a12ea9c5960e (diff)
feat: add user & group on foot and make linemode configturable and more options (#385)
* add user & group on footer * linemode have more options * linemode have more options * linemode have more options
-rw-r--r--Cargo.lock16
-rw-r--r--Cargo.toml9
-rw-r--r--config/joshuto.toml5
-rw-r--r--config/keymap.toml5
-rw-r--r--docs/configuration/joshuto.toml.md10
-rw-r--r--src/config/general/display_raw.rs6
-rw-r--r--src/config/option/linemodes.rs69
-rw-r--r--src/key_command/impl_comment.rs11
-rw-r--r--src/key_command/impl_display.rs2
-rw-r--r--src/ui/widgets/tui_dirlist_detailed.rs23
-rw-r--r--src/ui/widgets/tui_footer.rs7
-rw-r--r--src/util/unix.rs18
12 files changed, 132 insertions, 49 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 994e4a3..bc0982a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -80,6 +80,9 @@ name = "bitflags"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+dependencies = [
+ "serde",
+]
[[package]]
name = "bstr"
@@ -471,6 +474,7 @@ version = "0.9.5"
dependencies = [
"alphanumeric-sort",
"ansi-to-tui",
+ "bitflags 2.3.3",
"chrono",
"colors-transform",
"dirs-next",
@@ -478,6 +482,7 @@ dependencies = [
"globset",
"lazy_static",
"libc",
+ "nix",
"notify",
"open",
"phf",
@@ -495,7 +500,6 @@ dependencies = [
"trash",
"unicode-segmentation",
"unicode-width",
- "users",
"uuid",
"walkdir",
"whoami",
@@ -1265,16 +1269,6 @@ dependencies = [
]
[[package]]
-name = "users"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
-dependencies = [
- "libc",
- "log",
-]
-
-[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index c6323e3..3d3b796 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@ rustyline = "^12"
serde = "^1"
serde_derive = "^1"
shell-words = "^1"
-shellexpand = { version = "^3", features = ["full"]}
+shellexpand = { version = "^3", features = ["full"] }
signal-hook = "^0"
structopt = "^0"
termion = "^2"
@@ -35,10 +35,15 @@ toml = "^0"
trash = { version = "^3", optional = true }
unicode-segmentation = "^1"
unicode-width = "^0"
-users = "^0"
whoami = "^1"
xdg = "^2"
walkdir = "^2"
+bitflags = { version = "^2", features = ["serde"] }
+
+[dependencies.nix]
+version = "^0"
+default_features = false
+features = ["user"]
[dependencies.ratatui]
version = "^0"
diff --git a/config/joshuto.toml b/config/joshuto.toml
index c106057..3986e35 100644
--- a/config/joshuto.toml
+++ b/config/joshuto.toml
@@ -22,6 +22,11 @@ tilde_in_titlebar = true
# none, absolute, relative
line_number_style = "none"
+# size, mtime, user, gourp, perm. can be combined with |.
+# `none` to disable, `all` to enable all
+# all and none can't be combined with other options
+linemode = "size"
+
[display.sort]
# lexical, mtime, natural, size, ext
sort_method = "natural"
diff --git a/config/keymap.toml b/config/keymap.toml
index 5e9e6d6..8a9f371 100644
--- a/config/keymap.toml
+++ b/config/keymap.toml
@@ -119,7 +119,10 @@ keymap = [
{ keys = ["m", "s"], command = "linemode size" },
{ keys = ["m", "m"], command = "linemode mtime" },
- { keys = ["m", "M"], command = "linemode sizemtime" },
+ { keys = ["m", "M"], command = "linemode size | mtime" },
+ { keys = ["m", "u"], command = "linemode user" },
+ { keys = ["m", "U"], command = "linemode user | group" },
+ { keys = ["m", "p"], command = "linemode perm" },
{ keys = ["g", "r"], command = "cd /" },
{ keys = ["g", "c"], command = "cd ~/.config" },
diff --git a/docs/configuration/joshuto.toml.md b/docs/configuration/joshuto.toml.md
index 4a19692..1e0ed5c 100644
--- a/docs/configuration/joshuto.toml.md
+++ b/docs/configuration/joshuto.toml.md
@@ -56,6 +56,16 @@ tilde_in_titlebar = true
# - relative
line_number_style = "none"
+# Options include
+# - size
+# - mtime
+# - user
+# - group
+# - perm
+# - none (can't be combined with other options)
+# - all (can't be combined with other options)
+linemode = "size"
+
# Configurations related to file sorting
[display.sort]
# Options include
diff --git a/src/config/general/display_raw.rs b/src/config/general/display_raw.rs
index a340305..baaa101 100644
--- a/src/config/general/display_raw.rs
+++ b/src/config/general/display_raw.rs
@@ -59,6 +59,9 @@ pub struct DisplayOptionRaw {
#[serde(default)]
pub line_number_style: String,
+
+ #[serde(default)]
+ pub linemode: LineMode,
}
impl std::default::Default for DisplayOptionRaw {
@@ -75,6 +78,7 @@ impl std::default::Default for DisplayOptionRaw {
sort_options: SortOptionRaw::default(),
tilde_in_titlebar: true,
line_number_style: "none".to_string(),
+ linemode: LineMode::default(),
}
}
}
@@ -125,7 +129,7 @@ impl From<DisplayOptionRaw> for DisplayOption {
default_tab_display_option: TabDisplayOption {
sort_options: raw.sort_options.into(),
// todo: make default line mode configurable
- linemode: LineMode::Size,
+ linemode: raw.linemode,
..Default::default()
},
}
diff --git a/src/config/option/linemodes.rs b/src/config/option/linemodes.rs
index 372a3ad..591862f 100644
--- a/src/config/option/linemodes.rs
+++ b/src/config/option/linemodes.rs
@@ -1,31 +1,62 @@
+use serde_derive::Deserialize;
+
use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult};
-#[derive(Clone, Debug, Copy, Default)]
-pub enum LineMode {
- #[default]
- Size,
- MTime,
- SizeMTime,
+bitflags::bitflags! {
+ #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
+ #[serde(transparent)]
+ pub struct LineMode: u8 {
+ const size = 1 << 0;
+ const mtime = 1 << 1;
+ const user = 1 << 2;
+ const group = 1 << 3;
+ const perm = 1 << 4;
+ }
+}
+
+impl Default for LineMode {
+ fn default() -> Self {
+ Self::size
+ }
}
impl LineMode {
pub fn from_string(name: &str) -> JoshutoResult<LineMode> {
match name {
- "size" => Ok(LineMode::Size),
- "mtime" => Ok(LineMode::MTime),
- "sizemtime" => Ok(LineMode::SizeMTime),
- _ => Err(JoshutoError::new(
- JoshutoErrorKind::InvalidParameters,
- format!("Linemode '{}' unknown.", name),
- )),
+ "all" => Ok(LineMode::all()),
+ "none" => Ok(LineMode::empty()),
+ _ => {
+ let mut flags = name.split('|');
+
+ let mut linemode = LineMode::empty();
+
+ flags.try_for_each(|flag| {
+ match flag.trim() {
+ "size" => linemode |= LineMode::size,
+ "mtime" => linemode |= LineMode::mtime,
+ "user" => linemode |= LineMode::user,
+ "group" => linemode |= LineMode::group,
+ "perm" => linemode |= LineMode::perm,
+ flag => {
+ return Err(JoshutoError::new(
+ JoshutoErrorKind::InvalidParameters,
+ format!("Linemode '{}' unknown.", flag),
+ ))
+ }
+ }
+
+ Ok(())
+ })?;
+
+ Ok(linemode)
+ }
}
}
- pub fn as_str(&self) -> &'static str {
- match self {
- Self::Size => "size",
- Self::MTime => "mtime",
- Self::SizeMTime => "sizemtime",
- }
+ pub fn as_string(&self) -> String {
+ self.iter_names()
+ .map(|f| f.0)
+ .collect::<Vec<_>>()
+ .join(" | ")
}
}
diff --git a/src/key_command/impl_comment.rs b/src/key_command/impl_comment.rs
index 82806f7..a7f373f 100644
--- a/src/key_command/impl_comment.rs
+++ b/src/key_command/impl_comment.rs
@@ -7,10 +7,13 @@ impl CommandComment for Command {
// These comments are displayed at the help page
fn comment(&self) -> &'static str {
match self {
- Self::SetLineMode(linemode) => match linemode {
- LineMode::Size => "Show files with size",
- LineMode::MTime => "Show files with modified time",
- LineMode::SizeMTime => "Show files with size and modified time",
+ Self::SetLineMode(linemode) => match *linemode {
+ LineMode::size => "Show files with size",
+ LineMode::mtime => "Show files with modified time",
+ LineMode::user => "Show files with user",
+ LineMode::group => "Show files with group",
+ LineMode::perm => "Show files with permission",
+ _ => "Show files with multi-attribution",
},
Self::Escape => "Escape from visual mode (cancel)",
Self::BulkRename => "Bulk rename",
diff --git a/src/key_command/impl_display.rs b/src/key_command/impl_display.rs
index a20031e..6049467 100644
--- a/src/key_command/impl_display.rs
+++ b/src/key_command/impl_display.rs
@@ -10,7 +10,7 @@ impl std::fmt::Display for Command {
Self::CursorMoveUp { offset } => write!(f, "{} {}", self.command(), offset),
Self::CursorMoveDown { offset } => write!(f, "{} {}", self.command(), offset),
- Self::SetLineMode(mode) => write!(f, "{} {}", self.command(), mode.as_str()),
+ Self::SetLineMode(mode) => write!(f, "{} {}", self.command(), mode.as_string()),
Self::ParentCursorMoveUp { offset } => write!(f, "{} {}", self.command(), offset),
Self::ParentCursorMoveDown { offset } => write!(f, "{} {}", self.command(), offset),
diff --git a/src/ui/widgets/tui_dirlist_detailed.rs b/src/ui/widgets/tui_dirlist_detailed.rs
index 3373134..6e2a2a8 100644
--- a/src/ui/widgets/tui_dirlist_detailed.rs
+++ b/src/ui/widgets/tui_dirlist_detailed.rs
@@ -7,9 +7,9 @@ use ratatui::widgets::Widget;
use crate::config::option::{DisplayOption, LineMode, LineNumberStyle, TabDisplayOption};
use crate::fs::{FileType, JoshutoDirEntry, JoshutoDirList, LinkType};
-use crate::util::format;
use crate::util::string::UnicodeTruncate;
use crate::util::style;
+use crate::util::{format, unix};
use unicode_width::UnicodeWidthStr;
const MIN_LEFT_LABEL_WIDTH: i32 = 15;
@@ -144,15 +144,18 @@ fn print_entry(
let right_label_original = format!(
" {}{} ",
symlink_string,
- match linemode {
- LineMode::Size => get_entry_size_string(entry),
- LineMode::MTime => format::mtime_to_string(entry.metadata.modified()),
- LineMode::SizeMTime => format!(
- "{} {}",
- get_entry_size_string(entry),
- format::mtime_to_string(entry.metadata.modified())
- ),
- }
+ linemode
+ .iter_names()
+ .map(|f| match f.0 {
+ "size" => get_entry_size_string(entry),
+ "mtime" => format::mtime_to_string(entry.metadata.modified()),
+ "user" => unix::uid_to_string(entry.metadata.uid).unwrap_or("unknown".into()),
+ "group" => unix::gid_to_string(entry.metadata.gid).unwrap_or("unknown".into()),
+ "perm" => unix::mode_to_string(entry.metadata.mode),
+ _ => unreachable!(),
+ })
+ .collect::<Vec<_>>()
+ .join(" ")
);
// draw prefix first
diff --git a/src/ui/widgets/tui_footer.rs b/src/ui/widgets/tui_footer.rs
index dc42ee6..16c4ac4 100644
--- a/src/ui/widgets/tui_footer.rs
+++ b/src/ui/widgets/tui_footer.rs
@@ -49,6 +49,9 @@ impl<'a> Widget for TuiFooter<'a> {
let mode_str = unix::mode_to_string(entry.metadata.permissions_ref().mode());
+ let user_str = unix::uid_to_string(entry.metadata.uid).unwrap_or("unknown".into());
+ let group_str = unix::gid_to_string(entry.metadata.gid).unwrap_or("unknown".into());
+
let mtime_str = format::mtime_to_string(entry.metadata.modified());
let size_str = format::file_size_to_string(entry.metadata.len());
@@ -70,6 +73,10 @@ impl<'a> Widget for TuiFooter<'a> {
}),
Span::styled(mode_str, mode_style),
Span::raw(" "),
+ Span::raw(user_str),
+ Span::raw(" "),
+ Span::raw(group_str),
+ Span::raw(" "),
Span::raw(format!("{}/{}", i + 1, self.dirlist.len())),
Span::raw(" "),
Span::raw(mtime_str),
diff --git a/src/util/unix.rs b/src/util/unix.rs
index ac66e2b..61d41fb 100644
--- a/src/util/unix.rs
+++ b/src/util/unix.rs
@@ -67,3 +67,21 @@ pub fn expand_shell_string(s: &str) -> path::PathBuf {
let tilde_path = path::PathBuf::from(tilde_cow.as_ref());
tilde_path
}
+
+pub fn uid_to_string(uid: u32) -> Option<String> {
+ use nix::unistd::{Uid, User};
+
+ match User::from_uid(Uid::from(uid)) {
+ Ok(Some(user)) => Some(user.name),
+ _ => None,
+ }
+}
+
+pub fn gid_to_string(gid: u32) -> Option<String> {
+ use nix::unistd::{Gid, Group};
+
+ match Group::from_gid(Gid::from(gid)) {
+ Ok(Some(group)) => Some(group.name),
+ _ => None,
+ }
+}