mirror of
https://github.com/Llewellynvdm/starship.git
synced 2024-11-11 15:51:01 +00:00
feat(time): Show module with time range (#992)
* Creation of range field in TimeConfig * time_range parsing * Hide time module if outside of time_range * Tidying of code, and properly handling more cases * is_inside_time_range function * Tests and fmt * Update docs * The configuration needs the 24-hours format * Fix clippy errors
This commit is contained in:
parent
ab1c3d1c54
commit
fe2b3d491e
@ -1327,11 +1327,12 @@ To enable it, set `disabled` to `false` in your configuration file.
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
| ----------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `use_12hr` | `false` | Enables 12 hour formatting |
|
| `use_12hr` | `false` | Enables 12 hour formatting. |
|
||||||
| `format` | see below | The [chrono format string](https://docs.rs/chrono/0.4.7/chrono/format/strftime/index.html) used to format the time. |
|
| `format` | see below | The [chrono format string](https://docs.rs/chrono/0.4.7/chrono/format/strftime/index.html) used to format the time. |
|
||||||
| `style` | `"bold yellow"` | The style for the module time |
|
| `style` | `"bold yellow"` | The style for the module time. |
|
||||||
| `utc_time_offset` | `"local"` | Sets the UTC offset to use. Range from -24 < x < 24. Allows floats to accommodate 30/45 minute timezone offsets. |
|
| `utc_time_offset` | `"local"` | Sets the UTC offset to use. Range from -24 < x < 24. Allows floats to accommodate 30/45 minute timezone offsets. |
|
||||||
| `disabled` | `true` | Disables the `time` module. |
|
| `disabled` | `true` | Disables the `time` module. |
|
||||||
|
| `time_range` | `"-"` | Sets the time range during which the module will be shown. Times must be specified in 24-hours format |
|
||||||
|
|
||||||
If `use_12hr` is `true`, then `format` defaults to `"%r"`. Otherwise, it defaults to `"%T"`.
|
If `use_12hr` is `true`, then `format` defaults to `"%r"`. Otherwise, it defaults to `"%T"`.
|
||||||
Manually setting `format` will override the `use_12hr` setting.
|
Manually setting `format` will override the `use_12hr` setting.
|
||||||
@ -1345,6 +1346,7 @@ Manually setting `format` will override the `use_12hr` setting.
|
|||||||
disabled = false
|
disabled = false
|
||||||
format = "🕙[ %T ]"
|
format = "🕙[ %T ]"
|
||||||
utc_time_offset = "-5"
|
utc_time_offset = "-5"
|
||||||
|
time_range = "10:00:00-14:00:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Username
|
## Username
|
||||||
|
@ -10,6 +10,7 @@ pub struct TimeConfig<'a> {
|
|||||||
pub style: Style,
|
pub style: Style,
|
||||||
pub disabled: bool,
|
pub disabled: bool,
|
||||||
pub utc_time_offset: &'a str,
|
pub utc_time_offset: &'a str,
|
||||||
|
pub time_range: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RootModuleConfig<'a> for TimeConfig<'a> {
|
impl<'a> RootModuleConfig<'a> for TimeConfig<'a> {
|
||||||
@ -20,6 +21,7 @@ impl<'a> RootModuleConfig<'a> for TimeConfig<'a> {
|
|||||||
style: Color::Yellow.bold(),
|
style: Color::Yellow.bold(),
|
||||||
disabled: true,
|
disabled: true,
|
||||||
utc_time_offset: "local",
|
utc_time_offset: "local",
|
||||||
|
time_range: "-",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use chrono::{DateTime, FixedOffset, Local, Utc};
|
use chrono::{DateTime, FixedOffset, Local, NaiveTime, Utc};
|
||||||
|
|
||||||
use super::{Context, Module};
|
use super::{Context, Module};
|
||||||
|
|
||||||
@ -15,6 +15,13 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hide prompt if current time is not inside time_range
|
||||||
|
let (display_start, display_end) = parse_time_range(config.time_range);
|
||||||
|
let time_now = Local::now().time();
|
||||||
|
if !is_inside_time_range(time_now, display_start, display_end) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let default_format = if config.use_12hr { "%r" } else { "%T" };
|
let default_format = if config.use_12hr { "%r" } else { "%T" };
|
||||||
let time_format = config.format.unwrap_or(default_format);
|
let time_format = config.format.unwrap_or(default_format);
|
||||||
|
|
||||||
@ -87,6 +94,52 @@ fn format_time_fixed_offset(time_format: &str, utc_time: DateTime<FixedOffset>)
|
|||||||
utc_time.format(time_format).to_string()
|
utc_time.format(time_format).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if time_now is between time_start and time_end.
|
||||||
|
/// If one of these values is not given, then it is ignored.
|
||||||
|
/// It also handles cases where time_start and time_end have a midnight in between
|
||||||
|
fn is_inside_time_range(
|
||||||
|
time_now: NaiveTime,
|
||||||
|
time_start: Option<NaiveTime>,
|
||||||
|
time_end: Option<NaiveTime>,
|
||||||
|
) -> bool {
|
||||||
|
match (time_start, time_end) {
|
||||||
|
(None, None) => true,
|
||||||
|
(Some(i), None) => time_now > i,
|
||||||
|
(None, Some(i)) => time_now < i,
|
||||||
|
(Some(i), Some(j)) => {
|
||||||
|
if i < j {
|
||||||
|
i < time_now && time_now < j
|
||||||
|
} else {
|
||||||
|
time_now > i || time_now < j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the config's time_range field and returns the starting time and ending time.
|
||||||
|
/// The range is in the format START_TIME-END_TIME, with START_TIME and END_TIME being optional.
|
||||||
|
///
|
||||||
|
/// If one of the ranges is invalid or not provided, then the corresponding field in the output
|
||||||
|
/// tuple is None
|
||||||
|
fn parse_time_range(time_range: &str) -> (Option<NaiveTime>, Option<NaiveTime>) {
|
||||||
|
let value = String::from(time_range);
|
||||||
|
|
||||||
|
// Check if there is exactly one hyphen, and fail otherwise
|
||||||
|
if value.matches('-').count() != 1 {
|
||||||
|
return (None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split time_range into the two ranges
|
||||||
|
let (start, end) = value.split_at(value.find('-').unwrap());
|
||||||
|
let end = &end[1..];
|
||||||
|
|
||||||
|
// Parse the ranges
|
||||||
|
let start_time = NaiveTime::parse_from_str(start, "%H:%M:%S").ok();
|
||||||
|
let end_time = NaiveTime::parse_from_str(end, "%H:%M:%S").ok();
|
||||||
|
|
||||||
|
(start_time, end_time)
|
||||||
|
}
|
||||||
|
|
||||||
/* Because we cannot make acceptance tests for the time module, these unit
|
/* Because we cannot make acceptance tests for the time module, these unit
|
||||||
tests become extra important */
|
tests become extra important */
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -308,4 +361,101 @@ mod tests {
|
|||||||
.err()
|
.err()
|
||||||
.expect("Invalid timezone offset.");
|
.expect("Invalid timezone offset.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_invalid_time_range() {
|
||||||
|
let time_range = "10:00:00-12:00:00-13:00:00";
|
||||||
|
let time_range_2 = "10:00:00";
|
||||||
|
|
||||||
|
assert_eq!(parse_time_range(time_range), (None, None));
|
||||||
|
assert_eq!(parse_time_range(time_range_2), (None, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_start_time_range() {
|
||||||
|
let time_range = "10:00:00-";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_time_range(time_range),
|
||||||
|
(Some(NaiveTime::from_hms(10, 00, 00)), None)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_end_time_range() {
|
||||||
|
let time_range = "-22:00:00";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_time_range(time_range),
|
||||||
|
(None, Some(NaiveTime::from_hms(22, 00, 00)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_both_time_ranges() {
|
||||||
|
let time_range = "10:00:00-16:00:00";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_time_range(time_range),
|
||||||
|
(
|
||||||
|
Some(NaiveTime::from_hms(10, 00, 00)),
|
||||||
|
Some(NaiveTime::from_hms(16, 00, 00))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_inside_time_range_with_no_range() {
|
||||||
|
let time_start = None;
|
||||||
|
let time_end = None;
|
||||||
|
let time_now = NaiveTime::from_hms(10, 00, 00);
|
||||||
|
|
||||||
|
assert_eq!(is_inside_time_range(time_now, time_start, time_end), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_inside_time_range_with_start_range() {
|
||||||
|
let time_start = Some(NaiveTime::from_hms(10, 00, 00));
|
||||||
|
let time_now = NaiveTime::from_hms(12, 00, 00);
|
||||||
|
let time_now2 = NaiveTime::from_hms(8, 00, 00);
|
||||||
|
|
||||||
|
assert_eq!(is_inside_time_range(time_now, time_start, None), true);
|
||||||
|
assert_eq!(is_inside_time_range(time_now2, time_start, None), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_inside_time_range_with_end_range() {
|
||||||
|
let time_end = Some(NaiveTime::from_hms(16, 00, 00));
|
||||||
|
let time_now = NaiveTime::from_hms(15, 00, 00);
|
||||||
|
let time_now2 = NaiveTime::from_hms(19, 00, 00);
|
||||||
|
|
||||||
|
assert_eq!(is_inside_time_range(time_now, None, time_end), true);
|
||||||
|
assert_eq!(is_inside_time_range(time_now2, None, time_end), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_inside_time_range_with_complete_range() {
|
||||||
|
let time_start = Some(NaiveTime::from_hms(9, 00, 00));
|
||||||
|
let time_end = Some(NaiveTime::from_hms(18, 00, 00));
|
||||||
|
let time_now = NaiveTime::from_hms(3, 00, 00);
|
||||||
|
let time_now2 = NaiveTime::from_hms(13, 00, 00);
|
||||||
|
let time_now3 = NaiveTime::from_hms(20, 00, 00);
|
||||||
|
|
||||||
|
assert_eq!(is_inside_time_range(time_now, time_start, time_end), false);
|
||||||
|
assert_eq!(is_inside_time_range(time_now2, time_start, time_end), true);
|
||||||
|
assert_eq!(is_inside_time_range(time_now3, time_start, time_end), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_inside_time_range_with_complete_range_passing_midnight() {
|
||||||
|
let time_start = Some(NaiveTime::from_hms(19, 00, 00));
|
||||||
|
let time_end = Some(NaiveTime::from_hms(12, 00, 00));
|
||||||
|
let time_now = NaiveTime::from_hms(3, 00, 00);
|
||||||
|
let time_now2 = NaiveTime::from_hms(13, 00, 00);
|
||||||
|
let time_now3 = NaiveTime::from_hms(20, 00, 00);
|
||||||
|
|
||||||
|
assert_eq!(is_inside_time_range(time_now, time_start, time_end), true);
|
||||||
|
assert_eq!(is_inside_time_range(time_now2, time_start, time_end), false);
|
||||||
|
assert_eq!(is_inside_time_range(time_now3, time_start, time_end), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user