feat(status): display duration#650
Conversation
| enqueue_at.format(format_string).to_string() | ||
| } | ||
|
|
||
| pub fn humanize_duration(d: TimeDelta) -> String { |
There was a problem hiding this comment.
Since I don't know if this pr is eve desired, I intentionally avoided overhead and didn't add any tests for this function.
Considered using chrono-humanize but didn't want to add a dependency without asking, that crate is being used by nushell too.
There was a problem hiding this comment.
I'm ok with chrono-humanize :).
Although, I'm wondering, whether we should have a configurable duration format.
Personally, I would like to have the duration be as compact as possible. Something along the line of 1 days 05:35:45.
From what I've seen, there's no strftime-like API for Duration, which is a bit annoying. In practice, it shouldn't be too hard to build this ourselves (with a limited set of variables), since we already have handlebars templating in pueue due to the callback logic. With that, we could provide a simple strftime-like duration_format configuration option on top. Maybe even a days_duration_format for very long tasks?
fd3fef5 to
eea58e1
Compare
|
I like it. The main reason why there aren't more columns in the If there's task with delays, dependencies and priorities, we're already at 9 columns. Meaning, while I like this feature, I feel like we can only add this if we come up with a good solution to toggle this. Preferably via the config file. While we're at it, we should probably come up with something more "general" regarding We already have these settings: /// Whether aliases specified in `pueue_aliases.yml` should be expanded in the `pueue status`
/// or shown in their short form.
#[serde(default = "Default::default")]
pub show_expanded_aliases: bool,
/// The max amount of lines each task get's in the `pueue status` view.
pub max_status_lines: Option<usize>,
/// The format that will be used to display time formats in `pueue status`.
#[serde(default = "default_status_time_format")]
pub status_time_format: String,
/// The format that will be used to display datetime formats in `pueue status`.
#[serde(default = "default_status_datetime_format")]
pub status_datetime_format: String,They should probably be enclosed in a custom In there, we could have something like an I.e. client:
# .. other client settings
status:
show_expanded_aliases: true
max_status_lines: 5
status_time_format: "foo"
status_datetime_format: "foo"
additional_columns:
- "Duration" |
eea58e1 to
3d4857f
Compare
|
|
| let (_settings, config_found) = Settings::read(&Some(old_settings_path)) | ||
| let (settings, config_found) = Settings::read(&Some(old_settings_path)) | ||
| .wrap_err("Failed to read old config with defaults:")?; | ||
| assert_eq!(settings.client.status.show_expanded_aliases, false); |
There was a problem hiding this comment.
unless i missed something here basically I added a test to show that the migration hack works
| end: Local::now(), | ||
| start, | ||
| end, | ||
| duration, |
There was a problem hiding this comment.
Yeah. I feel like seconds would be good enough. But if we would need a custom serializer for this, I'm also okay with a struct. The lesser code and (code) complexity, the better :D
| /// Replicate deprecated fields into their new location. | ||
| /// WARN: This should only be used until deprecated fields are fully removed. | ||
| #[expect(deprecated)] | ||
| pub fn replicate_deprecated_fields(&mut self) { |
There was a problem hiding this comment.
@Nukesor this is basically a hack to replicate old values into the new structure fields.
Maybe there is a cleaner way of achieving the same thing but other things like modifiying serde deserializers made my head spin and felt overcomplicated.
There must be a better way but this is what I came up with
5242308 to
f23920a
Compare
f23920a to
c9c011f
Compare
|
@Nukesor if you could have a look again it would be great, i added |
|
Heyo, I'll probaly only get to reviewing this in the new year :D |
Nukesor
left a comment
There was a problem hiding this comment.
Neat, thanks for your work :)
I have a few improvements in mind, but the overall thing already looks pretty good!
| end: Local::now(), | ||
| start, | ||
| end, | ||
| duration, |
There was a problem hiding this comment.
Yeah. I feel like seconds would be good enough. But if we would need a custom serializer for this, I'm also okay with a struct. The lesser code and (code) complexity, the better :D
| let days = millis / 86_400_000; | ||
| millis %= 86_400_000; | ||
|
|
||
| let hours = millis / 3_600_000; | ||
| millis %= 3_600_000; | ||
|
|
||
| let minutes = millis / 60_000; | ||
| millis %= 60_000; | ||
|
|
||
| let seconds = millis / 1000; | ||
| millis %= 1000; |
There was a problem hiding this comment.
TimeDelta has num_* functions. They do exactly what you're doing here.
| enqueue_at.format(format_string).to_string() | ||
| } | ||
|
|
||
| pub fn humanize_duration(d: TimeDelta) -> String { |
There was a problem hiding this comment.
I'm ok with chrono-humanize :).
Although, I'm wondering, whether we should have a configurable duration format.
Personally, I would like to have the duration be as compact as possible. Something along the line of 1 days 05:35:45.
From what I've seen, there's no strftime-like API for Duration, which is a bit annoying. In practice, it shouldn't be too hard to build this ourselves (with a limited set of variables), since we already have handlebars templating in pueue due to the callback logic. With that, we could provide a simple strftime-like duration_format configuration option on top. Maybe even a days_duration_format for very long tasks?
| fn test_restore_from_4_0_2() -> Result<()> { | ||
| let settings_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) | ||
| .join("tests") | ||
| .join("data") | ||
| .join("v4.0.2_settings.yml"); | ||
|
|
||
| // Open v4.0.2 file and ensure the settings file can be read. | ||
| let (settings, config_found) = Settings::read(&Some(settings_path)) | ||
| .wrap_err("Failed to read old config with defaults:")?; | ||
| assert_eq!(settings.client.status.show_expanded_aliases, true); | ||
| assert_eq!(settings.client.status.max_lines, Some(42)); | ||
| assert_eq!(settings.client.status.time_format, "mock402-%H:%M:%S"); | ||
| assert_eq!( | ||
| settings.client.status.datetime_format, | ||
| "mock402-%Y-%m-%d\n%H:%M:%S" | ||
| ); | ||
| assert_eq!( | ||
| settings.client.status.additional_columns, | ||
| vec!["Duration".to_owned(),] | ||
| ); | ||
|
|
||
| assert!(config_found); |
There was a problem hiding this comment.
Since we're not introducing a new major version, this test isn't necessary. We just need to ensure backwards compatibility to the oldest supported version.
Just remove it :)
| time_format: "mock402-%H:%M:%S" | ||
| datetime_format: "mock402-%Y-%m-%d\n%H:%M:%S" |
There was a problem hiding this comment.
Why mock402?
Same above for the mock015
| #[serde(default = "Default::default")] | ||
| #[deprecated(since = "4.0.1", note = "use `status` instead")] | ||
| pub show_expanded_aliases: bool, | ||
| /// The max amount of lines each task get's in the `pueue status` view. | ||
| #[deprecated(since = "4.0.1", note = "use `status` instead")] | ||
| pub max_status_lines: Option<usize>, | ||
| /// The format that will be used to display time formats in `pueue status`. | ||
| #[serde(default = "default_status_time_format")] | ||
| #[deprecated(since = "4.0.1", note = "use `status` instead")] | ||
| pub status_time_format: String, | ||
| /// The format that will be used to display datetime formats in `pueue status`. | ||
| #[serde(default = "default_status_datetime_format")] | ||
| #[deprecated(since = "4.0.1", note = "use `status` instead")] | ||
| pub status_datetime_format: String, |
There was a problem hiding this comment.
Neat! Clean deprecation :)
I think, I like this config format a lot better. The old one started to become a bit crowded and overloaded/unclear.
| pub struct Status { | ||
| /// Whether aliases specified in `pueue_aliases.yml` should be expanded in the `pueue status` | ||
| /// or shown in their short form. | ||
| #[serde(default = "Default::default")] | ||
| pub show_expanded_aliases: bool, | ||
| /// The max amount of lines each task get's in the `pueue status` view. | ||
| pub max_lines: Option<usize>, | ||
| /// The format that will be used to display time formats in `pueue status`. | ||
| #[serde(default = "default_status_time_format")] | ||
| pub time_format: String, | ||
| /// The format that will be used to display datetime formats in `pueue status`. | ||
| #[serde(default = "default_status_datetime_format")] | ||
| pub datetime_format: String, | ||
| #[serde(default = "default_additional_columns")] | ||
| pub additional_columns: Vec<String>, | ||
| } |
There was a problem hiding this comment.
I have a proposal to ease the transition.
How about, we make all of these optional?
We then expose getters for these fields on Settings, which return the Status configs (if set), with a fallback to the old configs.
When the old config options are removed in the future, we then simply return the default_status_datetime_format, etc. when a config value is None.
-> We move the default value logic from the deserialization step to a function.
This should make the whole replicate_deprecated_fields logic unnecessary and make this thing easier.
|
I didn’t forget your feedback. I’ll get back to you as soon as life allows me to sit down on this again |
|
No worries. I sometimes disappear for weeks at a time as well. Life happens and open-source is volunteer work ;D Don't stress yourself. |


Problem when looking at
pueue statusit takes too many brain cycles to figure out how long a task took.This pr adds duration column to

pueue statusChecklist
Please make sure the PR adheres to this project's standards:
CHANGELOG.md.cargo clippyandcargo fmt. The CI will fail otherwise anyway.