From b60108839a6c211a3c245af61b45d7ea284aaed0 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sat, 16 Feb 2019 23:57:20 +0100 Subject: Display last modification + provide sort by date --- src/listing.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 056c847..751785e 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -1,5 +1,7 @@ use actix_web::{fs, HttpRequest, HttpResponse, Result}; use bytesize::ByteSize; +use chrono::{DateTime, Duration, Utc}; +use chrono_humanize::{Accuracy, HumanTime, Tense}; use clap::{_clap_count_exprs, arg_enum}; use htmlescape::encode_minimal as escape_html_entity; use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; @@ -7,6 +9,7 @@ use std::cmp::Ordering; use std::fmt::Write as FmtWrite; use std::io; use std::path::Path; +use std::time::SystemTime; arg_enum! { #[derive(Clone, Copy, Debug)] @@ -20,10 +23,13 @@ arg_enum! { /// /// DirsFirst: directories are listed first, alphabetical sorting is also applied /// 1/ -> 2/ -> 3/ -> 11 -> 12 + /// + /// Date: sort by last modification date (most recent first) pub enum SortingMethods { Natural, Alpha, DirsFirst, + Date } } @@ -60,6 +66,9 @@ struct Entry { /// Size in byte of the entry. Only available for EntryType::File size: Option, + + /// Last modification date + last_modification_date: Option, } impl Entry { @@ -68,12 +77,14 @@ impl Entry { entry_type: EntryType, link: String, size: Option, + last_modification_date: Option, ) -> Self { Entry { name, entry_type, link, size, + last_modification_date, } } } @@ -128,14 +139,26 @@ pub fn directory_listing( if skip_symlinks && metadata.file_type().is_symlink() { continue; } + let last_modification_date = match metadata.modified() { + Ok(date) => Some(date), + Err(_) => None, + }; + if metadata.is_dir() { - entries.push(Entry::new(file_name, EntryType::Directory, file_url, None)); + entries.push(Entry::new( + file_name, + EntryType::Directory, + file_url, + None, + last_modification_date, + )); } else { entries.push(Entry::new( file_name, EntryType::File, file_url, Some(ByteSize::b(metadata.len())), + last_modification_date, )); } } else { @@ -155,6 +178,13 @@ pub fn directory_listing( entries.sort_by_key(|e| e.name.clone()); entries.sort_by(|e1, e2| e1.entry_type.partial_cmp(&e2.entry_type).unwrap()); } + SortingMethods::Date => entries.sort_by(|e1, e2| { + // If, for some reason, we can't get the last modification date of an entry + // let's consider it was modified on UNIX_EPOCH (01/01/19270 00:00:00) + e2.last_modification_date + .unwrap_or(SystemTime::UNIX_EPOCH) + .cmp(&e1.last_modification_date.unwrap_or(SystemTime::UNIX_EPOCH)) + }), }; if reverse_sort { @@ -166,17 +196,19 @@ pub fn directory_listing( EntryType::Directory => { let _ = write!( body, - "{}/", - entry.link, entry.name + "{}/{} ({})", + entry.link, entry.name, convert_to_utc(entry.last_modification_date), humanize_duration(entry.last_modification_date) ); } EntryType::File => { let _ = write!( body, - "{}{}", + "{}{}{} ({})", entry.link, entry.name, - entry.size.unwrap() + entry.size.unwrap(), + convert_to_utc(entry.last_modification_date), + humanize_duration(entry.last_modification_date) ); } } @@ -210,6 +242,7 @@ pub fn directory_listing( color: #777c82;\ text-align: left;\ line-height: 1.125rem;\ + width: 33%;\ }}\ table thead tr th {{\ padding: 0.5rem 0.625rem 0.625rem;\ @@ -236,6 +269,9 @@ pub fn directory_listing( a:visited {{\ color: #8e44ad;\ }}\ + .ago {{\ + color: #c5c5c5;\ + }}\ @media (max-width: 600px) {{\ h1 {{\ font-size: 1.375em;\ @@ -250,7 +286,7 @@ pub fn directory_listing( \

{}

\ \ - \ + \ \ {}\
NameSize
NameSizeLast modification
\n", @@ -260,3 +296,26 @@ pub fn directory_listing( .content_type("text/html; charset=utf-8") .body(html)) } + +fn convert_to_utc(src_time: Option) -> String { + match src_time { + Some(time) => { + let date_time = DateTime::::from(time); + date_time.format("%R %e").to_string() + } + None => "".to_string(), + } +} + +fn humanize_duration(src_time: Option) -> String { + match src_time { + Some(std_time) => match SystemTime::now().duration_since(std_time) { + Ok(from_now) => match Duration::from_std(from_now) { + Ok(duration) => HumanTime::from(duration).to_text_en(Accuracy::Rough, Tense::Past), + Err(_) => "".to_string(), + }, + Err(_) => "".to_string(), + }, + None => "".to_string(), + } +} -- cgit v1.2.3 From 5bb42fb80d0d147688c7b94fc5113c777016da18 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sat, 16 Feb 2019 23:59:06 +0100 Subject: Improved CSS --- src/listing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 751785e..e47f279 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -242,7 +242,7 @@ pub fn directory_listing( color: #777c82;\ text-align: left;\ line-height: 1.125rem;\ - width: 33%;\ + width: 33.333%;\ }}\ table thead tr th {{\ padding: 0.5rem 0.625rem 0.625rem;\ -- cgit v1.2.3 From 7ac525378b4e73724ebd773fa07d449ef49544d4 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sun, 17 Feb 2019 00:04:29 +0100 Subject: Improved date format --- src/listing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index e47f279..93ae04b 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -301,7 +301,7 @@ fn convert_to_utc(src_time: Option) -> String { match src_time { Some(time) => { let date_time = DateTime::::from(time); - date_time.format("%R %e").to_string() + date_time.format("%e %b  %R").to_string() } None => "".to_string(), } -- cgit v1.2.3 From 89ed21ded5d052d54a28e2a08e042f50a9ccd5a0 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sun, 17 Feb 2019 09:18:13 +0100 Subject: Improved design of last-modification column --- src/listing.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 93ae04b..b985b1e 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -190,24 +190,26 @@ pub fn directory_listing( if reverse_sort { entries.reverse(); } - for entry in entries { + let (modification_date, modification_time) = convert_to_utc(entry.last_modification_date); + match entry.entry_type { EntryType::Directory => { let _ = write!( body, - "{}/{} ({})", - entry.link, entry.name, convert_to_utc(entry.last_modification_date), humanize_duration(entry.last_modification_date) + "{}/{}{}{}", + entry.link, entry.name, modification_date, modification_time, humanize_duration(entry.last_modification_date) ); } EntryType::File => { let _ = write!( body, - "{}{}{} ({})", + "{}{}{}{}{}", entry.link, entry.name, entry.size.unwrap(), - convert_to_utc(entry.last_modification_date), + modification_date, + modification_time, humanize_duration(entry.last_modification_date) ); } @@ -269,8 +271,16 @@ pub fn directory_listing( a:visited {{\ color: #8e44ad;\ }}\ - .ago {{\ - color: #c5c5c5;\ + td.date-cell {{\ + display: flex;\ + width: calc(100% - 1.25rem);\ + }}\ + td.date-cell span:first-of-type,\ + td.date-cell span:nth-of-type(2) {{\ + flex-basis:4.5rem;\ + }}\ + td.date-cell span:nth-of-type(3) {{\ + color: #c5c5c5\ }}\ @media (max-width: 600px) {{\ h1 {{\ @@ -297,13 +307,16 @@ pub fn directory_listing( .body(html)) } -fn convert_to_utc(src_time: Option) -> String { +fn convert_to_utc(src_time: Option) -> (String, String) { match src_time { Some(time) => { let date_time = DateTime::::from(time); - date_time.format("%e %b  %R").to_string() + ( + date_time.format("%e %b").to_string(), + date_time.format("%R").to_string(), + ) } - None => "".to_string(), + None => ("".to_string(), "".to_string()), } } -- cgit v1.2.3 From 6a8622e1c37cff8d32871887137954073a5a86e6 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sun, 17 Feb 2019 09:40:47 +0100 Subject: Added docstrings --- src/listing.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index b985b1e..c9720fa 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -307,6 +307,11 @@ pub fn directory_listing( .body(html)) } +/// Converts a SystemTime object to a strings tuple (date, time) +/// Date is formatted as %e %b, e.g. Jul 12 +/// Time is formatted as %R, e.g. 22:34 +/// +/// If no SystemTime was given, returns a tuple containing empty strings fn convert_to_utc(src_time: Option) -> (String, String) { match src_time { Some(time) => { @@ -320,6 +325,11 @@ fn convert_to_utc(src_time: Option) -> (String, String) { } } +/// Converts a SystemTime to a string readable by a human, +/// i.e. calculates the duration between now() and the given SystemTime, +/// and gives a rough approximation of the elapsed time since +/// +/// If no SystemTime was given, returns an empty string fn humanize_duration(src_time: Option) -> String { match src_time { Some(std_time) => match SystemTime::now().duration_since(std_time) { -- cgit v1.2.3 From 892be32b8a9de3bdb956ada54bf46eccff4aaaa1 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 19 Feb 2019 09:07:23 +0100 Subject: Added missing ; in CSS --- src/listing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index c9720fa..0404005 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -280,7 +280,7 @@ pub fn directory_listing( flex-basis:4.5rem;\ }}\ td.date-cell span:nth-of-type(3) {{\ - color: #c5c5c5\ + color: #c5c5c5;\ }}\ @media (max-width: 600px) {{\ h1 {{\ -- cgit v1.2.3 From 89f63763dab8f74ae5f5fb474296dbb1063d0d99 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 19 Feb 2019 20:21:13 +0100 Subject: Improved code --- src/listing.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 0404005..9203f48 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -313,16 +313,15 @@ pub fn directory_listing( /// /// If no SystemTime was given, returns a tuple containing empty strings fn convert_to_utc(src_time: Option) -> (String, String) { - match src_time { - Some(time) => { - let date_time = DateTime::::from(time); + src_time + .map(|time| DateTime::::from(time)) + .map(|date_time| { ( date_time.format("%e %b").to_string(), date_time.format("%R").to_string(), ) - } - None => ("".to_string(), "".to_string()), - } + }) + .unwrap_or_default() } /// Converts a SystemTime to a string readable by a human, @@ -331,14 +330,9 @@ fn convert_to_utc(src_time: Option) -> (String, String) { /// /// If no SystemTime was given, returns an empty string fn humanize_duration(src_time: Option) -> String { - match src_time { - Some(std_time) => match SystemTime::now().duration_since(std_time) { - Ok(from_now) => match Duration::from_std(from_now) { - Ok(duration) => HumanTime::from(duration).to_text_en(Accuracy::Rough, Tense::Past), - Err(_) => "".to_string(), - }, - Err(_) => "".to_string(), - }, - None => "".to_string(), - } + src_time + .and_then(|std_time| SystemTime::now().duration_since(std_time).ok()) + .and_then(|from_now| Duration::from_std(from_now).ok()) + .map(|duration| HumanTime::from(duration).to_text_en(Accuracy::Rough, Tense::Past)) + .unwrap_or_default() } -- cgit v1.2.3 From c14072c349b7a57034a0aba288408ac06d803478 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 19 Feb 2019 20:24:34 +0100 Subject: Renamed humanize_duration to humanize_systemtime --- src/listing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 9203f48..21aebec 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -198,7 +198,7 @@ pub fn directory_listing( let _ = write!( body, "{}/{}{}{}", - entry.link, entry.name, modification_date, modification_time, humanize_duration(entry.last_modification_date) + entry.link, entry.name, modification_date, modification_time, humanize_systemtime(entry.last_modification_date) ); } EntryType::File => { @@ -210,7 +210,7 @@ pub fn directory_listing( entry.size.unwrap(), modification_date, modification_time, - humanize_duration(entry.last_modification_date) + humanize_systemtime(entry.last_modification_date) ); } } @@ -329,7 +329,7 @@ fn convert_to_utc(src_time: Option) -> (String, String) { /// and gives a rough approximation of the elapsed time since /// /// If no SystemTime was given, returns an empty string -fn humanize_duration(src_time: Option) -> String { +fn humanize_systemtime(src_time: Option) -> String { src_time .and_then(|std_time| SystemTime::now().duration_since(std_time).ok()) .and_then(|from_now| Duration::from_std(from_now).ok()) -- cgit v1.2.3