mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-22 20:15:11 +00:00
Document and test time formats
This commit is contained in:
parent
0b87392fd4
commit
b2947ed590
@ -413,7 +413,10 @@ mod test {
|
||||
use super::*;
|
||||
use std::ffi::OsString;
|
||||
use options::flags;
|
||||
use options::parser::Flag;
|
||||
use options::parser::{Flag, Arg};
|
||||
|
||||
use options::test::parse_for_test;
|
||||
use options::test::Strictnesses::*;
|
||||
|
||||
pub fn os(input: &'static str) -> OsString {
|
||||
let mut os = OsString::new();
|
||||
@ -421,36 +424,77 @@ mod test {
|
||||
os
|
||||
}
|
||||
|
||||
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
|
||||
&flags::TIME, &flags::MODIFIED, &flags::CREATED, &flags::ACCESSED,
|
||||
&flags::COLOR, &flags::COLOUR ];
|
||||
|
||||
macro_rules! test {
|
||||
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => $result:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
use options::parser::Arg;
|
||||
use options::test::parse_for_test;
|
||||
use options::test::Strictnesses::*;
|
||||
|
||||
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES,
|
||||
&flags::TIME, &flags::MODIFIED, &flags::CREATED, &flags::ACCESSED,
|
||||
&flags::COLOR, &flags::COLOUR ];
|
||||
|
||||
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
||||
assert_eq!(result, $result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => like $pat:pat) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
||||
println!("Testing {:?}", result);
|
||||
match result {
|
||||
$pat => assert!(true),
|
||||
_ => assert!(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
mod size_formats {
|
||||
use super::*;
|
||||
|
||||
// Default behaviour
|
||||
test!(empty: SizeFormat <- []; Both => Ok(SizeFormat::DecimalBytes));
|
||||
|
||||
// Individual flags
|
||||
test!(binary: SizeFormat <- ["--binary"]; Both => Ok(SizeFormat::BinaryBytes));
|
||||
test!(bytes: SizeFormat <- ["--bytes"]; Both => Ok(SizeFormat::JustBytes));
|
||||
|
||||
// Errors
|
||||
test!(both: SizeFormat <- ["--binary", "--bytes"]; Both => Err(Misfire::Conflict(&flags::BINARY, &flags::BYTES)));
|
||||
}
|
||||
|
||||
|
||||
mod time_formats {
|
||||
use super::*;
|
||||
|
||||
// These tests use pattern matching because TimeFormat doesn’t
|
||||
// implement PartialEq.
|
||||
|
||||
// Default behaviour
|
||||
test!(empty: TimeFormat <- []; Both => like Ok(TimeFormat::DefaultFormat(_)));
|
||||
|
||||
// Individual settings
|
||||
test!(default: TimeFormat <- ["--time-style=default"]; Both => like Ok(TimeFormat::DefaultFormat(_)));
|
||||
test!(iso: TimeFormat <- ["--time-style", "iso"]; Both => like Ok(TimeFormat::ISOFormat(_)));
|
||||
test!(long_iso: TimeFormat <- ["--time-style=long-iso"]; Both => like Ok(TimeFormat::LongISO));
|
||||
test!(full_iso: TimeFormat <- ["--time-style", "full-iso"]; Both => like Ok(TimeFormat::FullISO));
|
||||
|
||||
// Overriding
|
||||
test!(actually: TimeFormat <- ["--time-style=default", "--time-style", "iso"]; Last => like Ok(TimeFormat::ISOFormat(_)));
|
||||
test!(actual_2: TimeFormat <- ["--time-style=default", "--time-style", "iso"]; Complain => like Err(Misfire::Duplicate(Flag::Long("time-style"), Flag::Long("time-style"))));
|
||||
|
||||
test!(nevermind: TimeFormat <- ["--time-style", "long-iso", "--time-style=full-iso"]; Last => like Ok(TimeFormat::FullISO));
|
||||
test!(nevermore: TimeFormat <- ["--time-style", "long-iso", "--time-style=full-iso"]; Complain => like Err(Misfire::Duplicate(Flag::Long("time-style"), Flag::Long("time-style"))));
|
||||
|
||||
// Errors
|
||||
test!(daily: TimeFormat <- ["--time-style=24-hour"]; Both => like Err(Misfire::BadArgument(_, _, _)));
|
||||
}
|
||||
|
||||
|
||||
mod time_types {
|
||||
use super::*;
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
//! Timestamp formatting.
|
||||
|
||||
use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece};
|
||||
use datetime::fmt::DateFormat;
|
||||
use locale;
|
||||
@ -6,13 +8,48 @@ use std::cmp;
|
||||
use fs::fields::Time;
|
||||
|
||||
|
||||
/// Every timestamp in exa needs to be rendered by a **time format**.
|
||||
/// Formatting times is tricky, because how a timestamp is rendered can
|
||||
/// depend on one or more of the following:
|
||||
///
|
||||
/// - The user’s locale, for printing the month name as “Feb”, or as “fév”,
|
||||
/// or as “2月”;
|
||||
/// - The current year, because certain formats will be less precise when
|
||||
/// dealing with dates far in the past;
|
||||
/// - The formatting style that the user asked for on the command-line.
|
||||
///
|
||||
/// Because not all formatting styles need the same data, they all have their
|
||||
/// own enum variants. It’s not worth looking the locale up if the formatter
|
||||
/// prints month names as numbers.
|
||||
///
|
||||
/// Currently exa does not support *custom* styles, where the user enters a
|
||||
/// format string in an environment variable or something. Just these four.
|
||||
#[derive(Debug)]
|
||||
pub enum TimeFormat {
|
||||
|
||||
/// The **default format** uses the user’s locale to print month names,
|
||||
/// and specifies the timestamp down to the minute for recent times, and
|
||||
/// day for older times.
|
||||
DefaultFormat(DefaultFormat),
|
||||
|
||||
/// Use the **ISO format**, which specifies the timestamp down to the
|
||||
/// minute for recent times, and day for older times. It uses a number
|
||||
/// for the month so it doesn’t need a locale.
|
||||
ISOFormat(ISOFormat),
|
||||
|
||||
/// Use the **long ISO format**, which specifies the timestamp down to the
|
||||
/// minute using only numbers, without needing the locale or year.
|
||||
LongISO,
|
||||
|
||||
/// Use the **full ISO format**, which specifies the timestamp down to the
|
||||
/// millisecond and includes its offset down to the minute. This too uses
|
||||
/// only numbers so doesn’t require any special consideration.
|
||||
FullISO,
|
||||
}
|
||||
|
||||
// There are two different formatting functions because local and zoned
|
||||
// timestamps are separate types.
|
||||
|
||||
impl TimeFormat {
|
||||
pub fn format_local(&self, time: Time) -> String {
|
||||
match *self {
|
||||
|
Loading…
Reference in New Issue
Block a user