Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(exa PR) 1061: Resolves #270: add support for --time-style=relative #44

Merged
merged 9 commits into from
Jul 30, 2023
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
11 changes: 9 additions & 2 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 @@ -30,6 +30,7 @@ number_prefix = "0.4"
scoped_threadpool = "0.1"
term_grid = "0.1"
terminal_size = "0.1.16"
timeago = { version = "0.3.1", default-features = false }
unicode-width = "0.1"
zoneinfo_compiled = "0.5.1"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Some of the options accept parameters:
- Valid **--color** options are **always**, **automatic**, and **never**.
- Valid sort fields are **accessed**, **changed**, **created**, **extension**, **Extension**, **inode**, **modified**, **name**, **Name**, **size**, **type**, and **none**. Fields starting with a capital letter sort uppercase before lowercase. The modified field has the aliases **date**, **time**, and **newest**, while its reverse has the aliases **age** and **oldest**.
- Valid time fields are **modified**, **changed**, **accessed**, and **created**.
- Valid time styles are **default**, **iso**, **long-iso**, and **full-iso**.
- Valid time styles are **default**, **iso**, **long-iso**, **full-iso**, and **relative**.


---
Expand Down
2 changes: 1 addition & 1 deletion completions/bash/eza
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ _eza()
;;

--time-style)
COMPREPLY=( $( compgen -W 'default iso long-iso full-iso --' -- "$cur" ) )
COMPREPLY=( $( compgen -W 'default iso long-iso full-iso relative --' -- "$cur" ) )
return
;;
esac
Expand Down
1 change: 1 addition & 0 deletions completions/fish/eza.fish
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ complete -c eza -l 'time-style' -d "How to format timestamps" -x -a "
iso\t'Display brief ISO timestamps'
long-iso\t'Display longer ISO timestaps, up to the minute'
full-iso\t'Display full ISO timestamps, up to the nanosecond'
relative\t'Display relative timestamps'
"
complete -c eza -l 'no-permissions' -d "Suppress the permissions field"
complete -c eza -s 'o' -l 'octal-permissions' -d "List each file's permission in octal format"
Expand Down
2 changes: 1 addition & 1 deletion completions/zsh/_eza
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ __eza() {
{-n,--numeric}"[List numeric user and group IDs.]" \
{-S,--blocks}"[List each file's number of filesystem blocks]" \
{-t,--time}="[Which time field to show]:(time field):(accessed changed created modified)" \
--time-style="[How to format timestamps]:(time style):(default iso long-iso full-iso)" \
--time-style="[How to format timestamps]:(time style):(default iso long-iso full-iso relative)" \
--no-permissions"[Suppress the permissions field]" \
{-o, --octal-permissions}"[List each file's permission in octal format]" \
--no-filesize"[Suppress the filesize field]" \
Expand Down
2 changes: 1 addition & 1 deletion man/eza.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ These options are available when running with `--long` (`-l`):
`--time-style=STYLE`
: How to format timestamps.

: Valid timestamp styles are ‘`default`’, ‘`iso`’, ‘`long-iso`’, and ‘`full-iso`’.
: Valid timestamp styles are ‘`default`’, ‘`iso`’, ‘`long-iso`’, ‘`full-iso`’, and ‘`relative`’.

`-u`, `--accessed`
: Use the accessed timestamp field.
Expand Down
2 changes: 1 addition & 1 deletion src/options/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub static CREATED: Arg = Arg { short: Some(b'U'), long: "created", takes_
pub static TIME_STYLE: Arg = Arg { short: None, long: "time-style", takes_value: TakesValue::Necessary(Some(TIME_STYLES)) };
pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Forbidden};
const TIMES: Values = &["modified", "changed", "accessed", "created"];
const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso"];
const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso", "relative"];

// suppressing columns
pub static NO_PERMISSIONS: Arg = Arg { short: None, long: "no-permissions", takes_value: TakesValue::Forbidden };
Expand Down
2 changes: 1 addition & 1 deletion src/options/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ LONG VIEW OPTIONS
-u, --accessed use the accessed timestamp field
-U, --created use the created timestamp field
--changed use the changed timestamp field
--time-style how to format timestamps (default, iso, long-iso, full-iso)
--time-style how to format timestamps (default, iso, long-iso, full-iso, relative)
--no-permissions suppress the permissions field
-o, --octal-permissions list each file's permission in octal format
--no-filesize suppress the filesize field
Expand Down
22 changes: 8 additions & 14 deletions src/options/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,13 @@ impl TimeFormat {
}
};

if &word == "default" {
Ok(Self::DefaultFormat)
}
else if &word == "iso" {
Ok(Self::ISOFormat)
}
else if &word == "long-iso" {
Ok(Self::LongISO)
}
else if &word == "full-iso" {
Ok(Self::FullISO)
}
else {
Err(OptionsError::BadArgument(&flags::TIME_STYLE, word))
match word.to_string_lossy().as_ref() {
"default" => Ok(Self::DefaultFormat),
"relative" => Ok(Self::Relative),
"iso" => Ok(Self::ISOFormat),
"long-iso" => Ok(Self::LongISO),
"full-iso" => Ok(Self::FullISO),
_ => Err(OptionsError::BadArgument(&flags::TIME_STYLE, word))
}
}
}
Expand Down Expand Up @@ -470,6 +463,7 @@ mod test {
// Individual settings
test!(default: TimeFormat <- ["--time-style=default"], None; Both => like Ok(TimeFormat::DefaultFormat));
test!(iso: TimeFormat <- ["--time-style", "iso"], None; Both => like Ok(TimeFormat::ISOFormat));
test!(relative: TimeFormat <- ["--time-style", "relative"], None; Both => like Ok(TimeFormat::Relative));
test!(long_iso: TimeFormat <- ["--time-style=long-iso"], None; Both => like Ok(TimeFormat::LongISO));
test!(full_iso: TimeFormat <- ["--time-style", "full-iso"], None; Both => like Ok(TimeFormat::FullISO));

Expand Down
1 change: 1 addition & 0 deletions src/output/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ impl Column {
Self::Inode |
Self::Blocks |
Self::GitStatus => Alignment::Right,
Self::Timestamp(_) |
_ => Alignment::Left,
}
}
Expand Down
25 changes: 23 additions & 2 deletions src/output/time.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Timestamp formatting.

use std::time::{SystemTime, UNIX_EPOCH};
use std::convert::TryInto;
use std::cmp::max;
use std::time::{SystemTime, UNIX_EPOCH, Duration};

use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece};
use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece, Instant};
use datetime::fmt::DateFormat;

use lazy_static::lazy_static;
Expand Down Expand Up @@ -46,6 +48,9 @@ pub enum TimeFormat {
/// millisecond and includes its offset down to the minute. This too uses
/// only numbers so doesn’t require any special consideration.
FullISO,

/// Use a relative but fixed width representation.
Relative,
}

// There are two different formatting functions because local and zoned
Expand All @@ -58,6 +63,7 @@ impl TimeFormat {
Self::ISOFormat => iso_local(time),
Self::LongISO => long_local(time),
Self::FullISO => full_local(time),
Self::Relative => relative(time),
}
}

Expand All @@ -67,6 +73,7 @@ impl TimeFormat {
Self::ISOFormat => iso_zoned(time, zone),
Self::LongISO => long_zoned(time, zone),
Self::FullISO => full_zoned(time, zone),
Self::Relative => relative(time),
}
}
}
Expand Down Expand Up @@ -113,6 +120,20 @@ fn long_zoned(time: SystemTime, zone: &TimeZone) -> String {
date.hour(), date.minute())
}

#[allow(trivial_numeric_casts)]
fn relative(time: SystemTime) -> String {
timeago::Formatter::new()
.ago("")
.convert(
Duration::from_secs(
max(0, Instant::now().seconds() - systemtime_epoch(time))
// this .unwrap is safe since the call above can never result in a
// value < 0
.try_into().unwrap()
)
)
}

#[allow(trivial_numeric_casts)]
fn full_local(time: SystemTime) -> String {
let date = LocalDateTime::at(systemtime_epoch(time));
Expand Down
15 changes: 15 additions & 0 deletions xtests/details-view-dates.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ stderr = { empty = true }
status = 0
tags = [ 'long', 'time' ]

[[cmd]]
name = "‘exa -l --time-style=relative’ handles dates far past and future dates"
shell = "exa -l --time-style=relative /testcases/far-dates"
stdout = { file = "outputs/far_dates_relative.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time' ]

# alternate date formats

Expand All @@ -46,6 +53,14 @@ stderr = { empty = true }
status = 0
tags = [ 'long', 'time-style' ]

[[cmd]]
name = "‘exa -l --time-style=relative’ produces a table using the relative date format"
shell = "exa -l --time-style=relative /testcases/dates"
stdout = { file = "outputs/dates_long_timestyle_relative.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time-style' ]

[[cmd]]
name = "‘exa -l --time-style=full-iso’ produces a table using the full-iso date format"
shell = "exa -l --time-style=full-iso /testcases/dates"
Expand Down
2 changes: 1 addition & 1 deletion xtests/input-options.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ tags = [ 'options' ]
name = "exa displays an error for option that takes the wrong parameter"
shell = "exa -l --time-style=24"
stdout = { empty = true }
stderr = { string = "Option --time-style has no \"24\" setting (choices: default, long-iso, full-iso, iso)" }
stderr = { string = "Option --time-style has no \"24\" setting (choices: default, long-iso, full-iso, iso, relative)" }
status = 3
tags = [ 'options' ]

Expand Down
3 changes: 3 additions & 0 deletions xtests/outputs/dates_long_timestyle_relative.ansitxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.rw-rw-r-- 0 cassowary 15 years peach
.rw-rw-r-- 0 cassowary 19 years pear
.rw-rw-r-- 0 cassowary 12 years plum
2 changes: 2 additions & 0 deletions xtests/outputs/far_dates_relative.ansitxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.rw-rw-r-- 0 vagrant now beyond-the-future
.rw-rw-r-- 0 vagrant now the-distant-past
2 changes: 1 addition & 1 deletion xtests/outputs/help.ansitxt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ LONG VIEW OPTIONS
-u, --accessed use the accessed timestamp field
-U, --created use the created timestamp field
--changed use the changed timestamp field
--time-style how to format timestamps (default, iso, long-iso, full-iso)
--time-style how to format timestamps (default, iso, long-iso, full-iso, relative)
--no-permissions suppress the permissions field
-o, --octal-permissions list each file's permission in octal format
--no-filesize suppress the filesize field
Expand Down