forked from mirrors/jj
templater: add TimestampRange type, migrate operation time to it
This commit is contained in:
parent
da3c1d2286
commit
eafbd977a3
3 changed files with 93 additions and 17 deletions
|
@ -7,10 +7,8 @@ use jujutsu_lib::operation::Operation;
|
|||
use crate::cli_util::{user_error, CommandError, CommandHelper};
|
||||
use crate::formatter::Formatter;
|
||||
use crate::graphlog::{get_graphlog, Edge};
|
||||
use crate::templater::Template;
|
||||
use crate::time_util::{
|
||||
format_absolute_timestamp, format_duration, format_timestamp_relative_to_now,
|
||||
};
|
||||
use crate::templater::{Template, TimestampRange};
|
||||
use crate::time_util::format_timestamp_relative_to_now;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Commands for working with the operation log
|
||||
|
@ -71,22 +69,19 @@ fn cmd_op_log(
|
|||
metadata.hostname
|
||||
)?;
|
||||
formatter.write_str(" ")?;
|
||||
let time_range = TimestampRange {
|
||||
start: metadata.start_time.clone(),
|
||||
end: metadata.end_time.clone(),
|
||||
};
|
||||
if self.relative_timestamps {
|
||||
let mut f = timeago::Formatter::new();
|
||||
f.min_unit(timeago::TimeUnit::Microseconds).ago("");
|
||||
let mut duration = format_duration(&metadata.start_time, &metadata.end_time, &f);
|
||||
if duration == "now" {
|
||||
duration = "less than a microsecond".to_string()
|
||||
}
|
||||
let start = format_timestamp_relative_to_now(&metadata.start_time);
|
||||
write!(formatter.labeled("time"), "{start}, lasted {duration}")?;
|
||||
} else {
|
||||
let start = format_timestamp_relative_to_now(&time_range.start);
|
||||
write!(
|
||||
formatter.labeled("time"),
|
||||
"{} - {}",
|
||||
format_absolute_timestamp(&metadata.start_time),
|
||||
format_absolute_timestamp(&metadata.end_time)
|
||||
"{start}, lasted {duration}",
|
||||
duration = time_range.duration()
|
||||
)?;
|
||||
} else {
|
||||
time_range.format(&(), formatter)?;
|
||||
}
|
||||
formatter.write_str("\n")?;
|
||||
write!(
|
||||
|
|
|
@ -27,7 +27,7 @@ use thiserror::Error;
|
|||
use crate::templater::{
|
||||
ConditionalTemplate, IntoTemplate, LabelTemplate, ListTemplate, Literal,
|
||||
PlainTextFormattedProperty, SeparateTemplate, Template, TemplateFunction, TemplateProperty,
|
||||
TemplatePropertyFn,
|
||||
TemplatePropertyFn, TimestampRange,
|
||||
};
|
||||
use crate::time_util;
|
||||
|
||||
|
@ -610,6 +610,10 @@ pub trait TemplateLanguage<'a> {
|
|||
&self,
|
||||
property: Box<dyn TemplateProperty<Self::Context, Output = Timestamp> + 'a>,
|
||||
) -> Self::Property;
|
||||
fn wrap_timestamp_range(
|
||||
&self,
|
||||
property: Box<dyn TemplateProperty<Self::Context, Output = TimestampRange> + 'a>,
|
||||
) -> Self::Property;
|
||||
|
||||
fn build_keyword(&self, name: &str, span: pest::Span) -> TemplateParseResult<Self::Property>;
|
||||
fn build_method(
|
||||
|
@ -635,6 +639,7 @@ macro_rules! impl_core_wrap_property_fns {
|
|||
wrap_integer(i64) => Integer,
|
||||
wrap_signature(jujutsu_lib::backend::Signature) => Signature,
|
||||
wrap_timestamp(jujutsu_lib::backend::Timestamp) => Timestamp,
|
||||
wrap_timestamp_range($crate::templater::TimestampRange) => TimestampRange,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -672,6 +677,7 @@ pub enum CoreTemplatePropertyKind<'a, I> {
|
|||
Integer(Box<dyn TemplateProperty<I, Output = i64> + 'a>),
|
||||
Signature(Box<dyn TemplateProperty<I, Output = Signature> + 'a>),
|
||||
Timestamp(Box<dyn TemplateProperty<I, Output = Timestamp> + 'a>),
|
||||
TimestampRange(Box<dyn TemplateProperty<I, Output = TimestampRange> + 'a>),
|
||||
}
|
||||
|
||||
impl<'a, I: 'a> IntoTemplateProperty<'a, I> for CoreTemplatePropertyKind<'a, I> {
|
||||
|
@ -708,6 +714,7 @@ impl<'a, I: 'a> IntoTemplate<'a, I> for CoreTemplatePropertyKind<'a, I> {
|
|||
CoreTemplatePropertyKind::Integer(property) => property.into_template(),
|
||||
CoreTemplatePropertyKind::Signature(property) => property.into_template(),
|
||||
CoreTemplatePropertyKind::Timestamp(property) => property.into_template(),
|
||||
CoreTemplatePropertyKind::TimestampRange(property) => property.into_template(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -869,6 +876,9 @@ pub fn build_core_method<'a, L: TemplateLanguage<'a>>(
|
|||
CoreTemplatePropertyKind::Timestamp(property) => {
|
||||
build_timestamp_method(language, property, function)
|
||||
}
|
||||
CoreTemplatePropertyKind::TimestampRange(property) => {
|
||||
build_timestamp_range_method(language, property, function)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,6 +987,43 @@ fn build_timestamp_method<'a, L: TemplateLanguage<'a>>(
|
|||
Ok(property)
|
||||
}
|
||||
|
||||
fn build_timestamp_range_method<'a, L: TemplateLanguage<'a>>(
|
||||
language: &L,
|
||||
self_property: impl TemplateProperty<L::Context, Output = TimestampRange> + 'a,
|
||||
function: &FunctionCallNode,
|
||||
) -> TemplateParseResult<L::Property> {
|
||||
let property = match function.name {
|
||||
"start" => {
|
||||
expect_no_arguments(function)?;
|
||||
language.wrap_timestamp(chain_properties(
|
||||
self_property,
|
||||
TemplatePropertyFn(|time_range: &TimestampRange| time_range.start.clone()),
|
||||
))
|
||||
}
|
||||
"end" => {
|
||||
expect_no_arguments(function)?;
|
||||
language.wrap_timestamp(chain_properties(
|
||||
self_property,
|
||||
TemplatePropertyFn(|time_range: &TimestampRange| time_range.end.clone()),
|
||||
))
|
||||
}
|
||||
"duration" => {
|
||||
expect_no_arguments(function)?;
|
||||
language.wrap_string(chain_properties(
|
||||
self_property,
|
||||
TemplatePropertyFn(TimestampRange::duration),
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
return Err(TemplateParseError::no_such_method(
|
||||
"TimestampRange",
|
||||
function,
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok(property)
|
||||
}
|
||||
|
||||
fn build_global_function<'a, L: TemplateLanguage<'a>>(
|
||||
language: &L,
|
||||
function: &FunctionCallNode,
|
||||
|
|
|
@ -73,6 +73,40 @@ impl Template<()> for Timestamp {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct TimestampRange {
|
||||
// Could be aliased to Range<Timestamp> if needed.
|
||||
pub start: Timestamp,
|
||||
pub end: Timestamp,
|
||||
}
|
||||
|
||||
impl TimestampRange {
|
||||
// TODO: Introduce duration type, and move formatting to it.
|
||||
pub fn duration(&self) -> String {
|
||||
let mut f = timeago::Formatter::new();
|
||||
f.min_unit(timeago::TimeUnit::Microseconds).ago("");
|
||||
let duration = time_util::format_duration(&self.start, &self.end, &f);
|
||||
if duration == "now" {
|
||||
"less than a microsecond".to_owned()
|
||||
} else {
|
||||
duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Template<()> for TimestampRange {
|
||||
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
||||
self.start.format(&(), formatter)?;
|
||||
write!(formatter, " - ")?;
|
||||
self.end.format(&(), formatter)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_content(&self, _: &()) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Template<()> for bool {
|
||||
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
||||
formatter.write_str(if *self { "true" } else { "false" })
|
||||
|
|
Loading…
Reference in a new issue