Skip to content

Commit

Permalink
Merge pull request #174 from solidiquis/long-edit
Browse files Browse the repository at this point in the history
support for user and group
  • Loading branch information
solidiquis authored May 24, 2023
2 parents e0a6300 + 2d8931e commit c2bbc20
Show file tree
Hide file tree
Showing 19 changed files with 676 additions and 208 deletions.
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ chrono = "0.4.24"
clap = { version = "4.1.1", features = ["derive"] }
clap_complete = "4.1.1"
dirs = "5.0"
errno = "0.3.1"
filesize = "0.2.0"
ignore = "0.4.2"
indextree = "4.6.0"
Expand Down
14 changes: 12 additions & 2 deletions src/context/output.rs → src/context/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::convert::From;

/// Utility struct to help store maximum column widths for attributes of each node. Each width is
/// measured as the number of columns of the tty's window.
pub struct ColumnProperties {
pub struct Properties {
pub max_size_width: usize,
pub max_size_unit_width: usize,

Expand All @@ -15,9 +15,15 @@ pub struct ColumnProperties {

#[cfg(unix)]
pub max_block_width: usize,

#[cfg(unix)]
pub max_owner_width: usize,

#[cfg(unix)]
pub max_group_width: usize,
}

impl From<&Context> for ColumnProperties {
impl From<&Context> for Properties {
fn from(ctx: &Context) -> Self {
let unit_width = match ctx.unit {
PrefixKind::Bin if ctx.human => 3,
Expand All @@ -34,6 +40,10 @@ impl From<&Context> for ColumnProperties {
max_ino_width: 0,
#[cfg(unix)]
max_block_width: 0,
#[cfg(unix)]
max_owner_width: 0,
#[cfg(unix)]
max_group_width: 0,
}
}
}
40 changes: 33 additions & 7 deletions src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use ignore::{
overrides::{Override, OverrideBuilder},
DirEntry,
};
use output::ColumnProperties;
use regex::Regex;
use std::{
borrow::Borrow,
Expand Down Expand Up @@ -35,7 +34,7 @@ pub mod file;
pub mod layout;

/// Utilities to print output.
pub mod output;
pub mod column;

/// Printing order kinds.
pub mod sort;
Expand Down Expand Up @@ -87,6 +86,21 @@ pub struct Context {
#[arg(short, long)]
pub long: bool,

/// Show file's groups
#[cfg(unix)]
#[arg(long)]
pub group: bool,

/// Show each file's ino
#[cfg(unix)]
#[arg(long)]
pub ino: bool,

/// Show the total number of hardlinks to the underlying inode
#[cfg(unix)]
#[arg(long)]
pub nlink: bool,

/// Show permissions in numeric octal format instead of symbolic
#[cfg(unix)]
#[arg(long, requires = "long")]
Expand Down Expand Up @@ -142,6 +156,10 @@ pub struct Context {
#[arg(short, long, value_enum, default_value_t = PrefixKind::default())]
pub unit: PrefixKind,

/// Which kind of layout to use when rendering the output
#[arg(short = 'y', long, value_enum, default_value_t = layout::Type::default())]
pub layout: layout::Type,

/// Show hidden files
#[arg(short = '.', long)]
pub hidden: bool,
Expand All @@ -158,10 +176,6 @@ pub struct Context {
#[arg(long)]
pub dirs_only: bool,

/// Which kind of layout to use when rendering the output
#[arg(long, value_enum, default_value_t = layout::Type::default())]
pub layout: layout::Type,

/// Don't read configuration file
#[arg(long)]
pub no_config: bool,
Expand Down Expand Up @@ -208,6 +222,16 @@ pub struct Context {
#[cfg(unix)]
pub max_block_width: usize,

/// Restricts column width of file owner for long view
#[clap(skip = usize::default())]
#[cfg(unix)]
pub max_owner_width: usize,

/// Restricts column width of file group for long view
#[clap(skip = usize::default())]
#[cfg(unix)]
pub max_group_width: usize,

/// Width of the terminal emulator's window
#[clap(skip)]
pub window_width: Option<usize>,
Expand Down Expand Up @@ -486,12 +510,14 @@ impl Context {
}

/// Update column width properties.
pub fn update_column_properties(&mut self, col_props: &ColumnProperties) {
pub fn update_column_properties(&mut self, col_props: &column::Properties) {
self.max_size_width = col_props.max_size_width;
self.max_size_unit_width = col_props.max_size_unit_width;

#[cfg(unix)]
{
self.max_owner_width = col_props.max_owner_width;
self.max_group_width = col_props.max_group_width;
self.max_nlink_width = col_props.max_nlink_width;
self.max_block_width = col_props.max_block_width;
self.max_ino_width = col_props.max_ino_width;
Expand Down
93 changes: 64 additions & 29 deletions src/disk_usage/file_size/byte.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::super::units::{BinPrefix, PrefixKind, SiPrefix, UnitPrefix};
use filesize::PathExt;
use std::{
cell::{Ref, RefCell},
fmt::{self, Display},
fs::Metadata,
path::Path,
Expand All @@ -14,6 +15,11 @@ pub struct Metric {
#[allow(dead_code)]
kind: MetricKind,
prefix_kind: PrefixKind,

/// To prevent allocating the same string twice. We allocate the first time
/// in [`crate::tree::update_column_properties`] in order to compute the max column width for
/// human-readable size and the second time during the actual render.
cached_display: RefCell<String>,
}

/// Represents the appropriate method in which to compute bytes. `Logical` represent the total amount
Expand All @@ -39,26 +45,29 @@ impl Metric {
human_readable,
kind,
prefix_kind,
cached_display: RefCell::default(),
}
}

/// Initializes an empty [Metric] used to represent the total amount of bytes of a file.
pub const fn init_empty_logical(human_readable: bool, prefix_kind: PrefixKind) -> Self {
pub fn init_empty_logical(human_readable: bool, prefix_kind: PrefixKind) -> Self {
Self {
value: 0,
human_readable,
kind: MetricKind::Logical,
prefix_kind,
cached_display: RefCell::default(),
}
}

/// Initializes an empty [Metric] used to represent the total disk space of a file in bytes.
pub const fn init_empty_physical(human_readable: bool, prefix_kind: PrefixKind) -> Self {
pub fn init_empty_physical(human_readable: bool, prefix_kind: PrefixKind) -> Self {
Self {
value: 0,
human_readable,
kind: MetricKind::Physical,
prefix_kind,
cached_display: RefCell::default(),
}
}

Expand All @@ -77,46 +86,66 @@ impl Metric {
human_readable,
kind,
prefix_kind,
cached_display: RefCell::default(),
}
}

/// Returns an immutable borrow of the `cached_display`.
pub fn cached_display(&self) -> Ref<'_, String> {
self.cached_display.borrow()
}
}

impl Display for Metric {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = self.value as f64;
{
let cached_display = self.cached_display();

match self.prefix_kind {
PrefixKind::Si => {
if !self.human_readable {
return write!(f, "{} {}", self.value, SiPrefix::Base);
}
if cached_display.len() > 0 {
return write!(f, "{cached_display}");
}
}

let unit = SiPrefix::from(self.value);
let value = self.value as f64;

if matches!(unit, SiPrefix::Base) {
write!(f, "{} {unit}", self.value)
let display = match self.prefix_kind {
PrefixKind::Si => {
if self.human_readable {
let unit = SiPrefix::from(self.value);

if matches!(unit, SiPrefix::Base) {
format!("{} {unit}", self.value)
} else {
let base_value = unit.base_value();
let size = value / (base_value as f64);
format!("{size:.1} {unit}")
}
} else {
let base_value = unit.base_value();
let size = value / (base_value as f64);
write!(f, "{size:.2} {unit}")
format!("{} {}", self.value, SiPrefix::Base)
}
}
PrefixKind::Bin => {
if !self.human_readable {
return write!(f, "{} {}", self.value, BinPrefix::Base);
}

let unit = BinPrefix::from(self.value);

if matches!(unit, BinPrefix::Base) {
write!(f, "{} {unit}", self.value)
if self.human_readable {
let unit = BinPrefix::from(self.value);

if matches!(unit, BinPrefix::Base) {
format!("{} {unit}", self.value)
} else {
let base_value = unit.base_value();
let size = value / (base_value as f64);
format!("{size:.1} {unit}")
}
} else {
let base_value = unit.base_value();
let size = value / (base_value as f64);
write!(f, "{size:.2} {unit}")
format!("{} {}", self.value, BinPrefix::Base)
}
}
}
};

write!(f, "{display}")?;

self.cached_display.replace(display);

Ok(())
}
}

Expand All @@ -127,6 +156,7 @@ fn test_metric() {
kind: MetricKind::Logical,
human_readable: false,
prefix_kind: PrefixKind::Bin,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "100 B");

Expand All @@ -135,14 +165,16 @@ fn test_metric() {
kind: MetricKind::Logical,
human_readable: true,
prefix_kind: PrefixKind::Si,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "1.00 KB");
assert_eq!(format!("{}", metric), "1.0 KB");

let metric = Metric {
value: 1000,
kind: MetricKind::Logical,
human_readable: true,
prefix_kind: PrefixKind::Bin,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "1000 B");

Expand All @@ -151,22 +183,25 @@ fn test_metric() {
kind: MetricKind::Logical,
human_readable: true,
prefix_kind: PrefixKind::Bin,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "1.00 KiB");
assert_eq!(format!("{}", metric), "1.0 KiB");

let metric = Metric {
value: 2_u64.pow(20),
kind: MetricKind::Logical,
human_readable: true,
prefix_kind: PrefixKind::Bin,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "1.00 MiB");
assert_eq!(format!("{}", metric), "1.0 MiB");

let metric = Metric {
value: 123454,
kind: MetricKind::Logical,
human_readable: false,
prefix_kind: PrefixKind::Bin,
cached_display: RefCell::<String>::default(),
};
assert_eq!(format!("{}", metric), "123454 B");
}
Loading

0 comments on commit c2bbc20

Please sign in to comment.