Skip to content

Commit

Permalink
feat: add support for --time-style=relative
Browse files Browse the repository at this point in the history
(exa PR) 1061: Merge pull request #44 from cafkafk/pr-1061
  • Loading branch information
cafkafk authored Jul 30, 2023
2 parents ad13b62 + 165d6e2 commit 935b7e1
Show file tree
Hide file tree
Showing 17 changed files with 71 additions and 26 deletions.
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

0 comments on commit 935b7e1

Please sign in to comment.