Skip to content

Commit

Permalink
feat: more linemode (#549)
Browse files Browse the repository at this point in the history
* refactor: refact line mode, and make it more flexible

user now can change the order of line mode

* refactor: refact line mode, and make it more flexible

user now can change the order of line mode

* feat: add more line_mode

* feat: add more line_mode
  • Loading branch information
Lzzzzzt authored Jul 6, 2024
1 parent f7ad385 commit 85ba4a1
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 122 deletions.
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

0 comments on commit 85ba4a1

Please sign in to comment.