Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/configuration/joshuto.toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ line_number_style = "none"
# Options include
# - size
# - mtime
# - atime
# - btime
# - user
# - group
# - perm
# - none (can't be combined with other options)
# - all (can't be combined with other options)
# - all (same with none, but if there are not enough space to display the whole string, it will be cut off)
linemode = "size"

# Configurations related to file sorting
Expand Down
125 changes: 92 additions & 33 deletions src/config/clean/app/display/line_mode.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,79 @@
use serde::Deserialize;

use crate::error::{AppError, AppErrorKind, AppResult};

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;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct LineMode {
pub mode: [LineModeArgs; 8],
pub size: usize,
}

impl LineMode {
pub const fn all() -> Self {
Self {
mode: [
LineModeArgs::Size,
LineModeArgs::ModifyTime,
LineModeArgs::AccessTime,
LineModeArgs::BirthTime,
LineModeArgs::User,
LineModeArgs::Group,
LineModeArgs::Permission,
LineModeArgs::Null,
],
size: 7,
}
}

pub const fn empty() -> Self {
Self {
mode: [LineModeArgs::Null; 8],
size: 0,
}
}

pub fn add_mode(&mut self, mode: LineModeArgs) {
if self.mode.contains(&mode) {
return;
}

self.mode[self.size] = mode;
self.size += 1;
}
}

#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub enum LineModeArgs {
Size,
ModifyTime,
AccessTime,
BirthTime,
User,
Group,
Permission,
#[default]
Null,
}

impl AsRef<str> for LineModeArgs {
fn as_ref(&self) -> &str {
match self {
LineModeArgs::Size => "size",
LineModeArgs::ModifyTime => "mtime",
LineModeArgs::AccessTime => "atime",
LineModeArgs::BirthTime => "ctime",
LineModeArgs::User => "user",
LineModeArgs::Group => "group",
LineModeArgs::Permission => "perm",
LineModeArgs::Null => unreachable!(),
}
}
}

impl Default for LineMode {
fn default() -> Self {
Self::size
let mut mode = [Default::default(); 8];
mode[0] = LineModeArgs::Size;

Self { size: 1, mode }
}
}

Expand All @@ -26,37 +83,39 @@ impl LineMode {
"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 => {
let mut line_mode = LineMode::empty();

for mode in name.split('|').map(|mode| mode.trim()) {
match mode {
"size" => line_mode.add_mode(LineModeArgs::Size),
"mtime" => line_mode.add_mode(LineModeArgs::ModifyTime),
"atime" => line_mode.add_mode(LineModeArgs::AccessTime),
"btime" => line_mode.add_mode(LineModeArgs::BirthTime),
"user" => line_mode.add_mode(LineModeArgs::User),
"group" => line_mode.add_mode(LineModeArgs::Group),
"perm" => line_mode.add_mode(LineModeArgs::Permission),
e => {
return Err(AppError::new(
AppErrorKind::InvalidParameters,
format!("Linemode '{}' unknown.", flag),
format!("Linemode '{}' unknown.", e),
))
}
}
}

Ok(())
})?;

Ok(linemode)
Ok(line_mode)
}
}
}

pub fn as_string(&self) -> String {
self.iter_names()
.map(|f| f.0)
.collect::<Vec<_>>()
.join(" | ")
let modes: Vec<&str> = self
.mode
.iter()
.take(self.size)
.map(AsRef::as_ref)
.collect();

modes.join(" | ")
}
}
30 changes: 27 additions & 3 deletions src/config/raw/app/display/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::Deserialize;
use serde::{Deserialize, Deserializer};

use crate::config::clean::app::display::line_mode::LineMode;
use crate::config::clean::app::display::line_mode::{LineMode, LineModeArgs};

use super::sort::SortOptionRaw;

Expand Down Expand Up @@ -51,7 +51,7 @@ pub struct DisplayOptionRaw {
#[serde(default)]
pub line_number_style: String,

#[serde(default)]
#[serde(default, deserialize_with = "deserialize_line_mode")]
pub linemode: LineMode,
}

Expand All @@ -73,3 +73,27 @@ impl std::default::Default for DisplayOptionRaw {
}
}
}

fn deserialize_line_mode<'de, D>(deserializer: D) -> Result<LineMode, D::Error>
where
D: Deserializer<'de>,
{
let line_mode_string: String = Deserialize::deserialize(deserializer)?;

let mut line_mode = LineMode::empty();

for mode in line_mode_string.split('|').map(|mode| mode.trim()) {
match mode {
"size" => line_mode.add_mode(LineModeArgs::Size),
"mtime" => line_mode.add_mode(LineModeArgs::ModifyTime),
"atime" => line_mode.add_mode(LineModeArgs::AccessTime),
"btime" => line_mode.add_mode(LineModeArgs::BirthTime),
"user" => line_mode.add_mode(LineModeArgs::User),
"group" => line_mode.add_mode(LineModeArgs::Group),
"perm" => line_mode.add_mode(LineModeArgs::Permission),
e => eprintln!("{e} is an unsupportted line mode, will be ignored"),
}
}

Ok(line_mode)
}
70 changes: 45 additions & 25 deletions src/fs/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ pub enum LinkType {

#[derive(Clone, Debug)]
pub struct JoshutoMetadata {
_len: u64,
_directory_size: Option<usize>,
_modified: time::SystemTime,
_permissions: fs::Permissions,
_file_type: FileType,
_link_type: LinkType,
len: u64,
directory_size: Option<usize>,
modified: time::SystemTime,
accessed: time::SystemTime,
created: time::SystemTime,
permissions: fs::Permissions,
file_type: FileType,
link_type: LinkType,
#[cfg(unix)]
pub uid: u32,
#[cfg(unix)]
Expand All @@ -45,21 +47,29 @@ impl JoshutoMetadata {

let symlink_metadata = fs::symlink_metadata(path)?;
let metadata = fs::metadata(path);
let (_len, _modified, _permissions) = match metadata.as_ref() {
Ok(m) => (m.len(), m.modified()?, m.permissions()),
let (len, modified, accessed, created, permissions) = match metadata.as_ref() {
Ok(m) => (
m.len(),
m.modified()?,
m.accessed()?,
m.created()?,
m.permissions(),
),
Err(_) => (
symlink_metadata.len(),
symlink_metadata.modified()?,
symlink_metadata.accessed()?,
symlink_metadata.created()?,
symlink_metadata.permissions(),
),
};

let (_file_type, _directory_size) = match metadata.as_ref() {
let (file_type, directory_size) = match metadata.as_ref() {
Ok(m) if m.file_type().is_dir() => (FileType::Directory, None),
_ => (FileType::File, None),
};

let _link_type = if symlink_metadata.file_type().is_symlink() {
let link_type = if symlink_metadata.file_type().is_symlink() {
let mut link = "".to_string();

if let Ok(path) = fs::read_link(path) {
Expand All @@ -85,12 +95,14 @@ impl JoshutoMetadata {
let mode = symlink_metadata.mode();

Ok(Self {
_len,
_directory_size,
_modified,
_permissions,
_file_type,
_link_type,
len,
directory_size,
modified,
accessed,
created,
permissions,
file_type,
link_type,
#[cfg(unix)]
uid,
#[cfg(unix)]
Expand All @@ -101,38 +113,46 @@ impl JoshutoMetadata {
}

pub fn len(&self) -> u64 {
self._len
self.len
}

pub fn directory_size(&self) -> Option<usize> {
self._directory_size
self.directory_size
}

pub fn update_directory_size(&mut self, size: usize) {
self._directory_size = Some(size);
self.directory_size = Some(size);
}

pub fn modified(&self) -> time::SystemTime {
self._modified
self.modified
}

pub fn accessed(&self) -> time::SystemTime {
self.accessed
}

pub fn created(&self) -> time::SystemTime {
self.created
}

pub fn permissions_ref(&self) -> &fs::Permissions {
&self._permissions
&self.permissions
}

pub fn permissions_mut(&mut self) -> &mut fs::Permissions {
&mut self._permissions
&mut self.permissions
}

pub fn file_type(&self) -> &FileType {
&self._file_type
&self.file_type
}

pub fn link_type(&self) -> &LinkType {
&self._link_type
&self.link_type
}

pub fn is_dir(&self) -> bool {
self._file_type == FileType::Directory
self.file_type == FileType::Directory
}
}
14 changes: 2 additions & 12 deletions src/key_command/impl_comment.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
config::clean::app::display::{line_mode::LineMode, sort_type::SortType},
io::FileOperationOptions,
};
use crate::{config::clean::app::display::sort_type::SortType, io::FileOperationOptions};

use crate::commands::sub_process::SubprocessCallMode;

Expand All @@ -11,14 +8,7 @@ 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::user => "Show files with user",
LineMode::group => "Show files with group",
LineMode::perm => "Show files with permission",
_ => "Show files with multi-attribution",
},
Self::SetLineMode(_) => "Show File's metadata in line",
Self::Escape => "Escape from visual mode (cancel)",
Self::BulkRename => "Bulk rename",

Expand Down
Loading