mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 18:27:38 +00:00
templater: move Box::new() wrapping to language.wrap_() functions
Now all callers do wrap_<type>(Box::new(...)), so its responsibility can be moved to the callee without extra boxing.
This commit is contained in:
parent
96f4d8798c
commit
6af265a388
3 changed files with 68 additions and 91 deletions
|
@ -76,23 +76,23 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo, '_> {
|
||||||
impl<'repo> CommitTemplateLanguage<'repo, '_> {
|
impl<'repo> CommitTemplateLanguage<'repo, '_> {
|
||||||
fn wrap_commit_or_change_id(
|
fn wrap_commit_or_change_id(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Commit, Output = CommitOrChangeId<'repo>> + 'repo>,
|
property: impl TemplateProperty<Commit, Output = CommitOrChangeId<'repo>> + 'repo,
|
||||||
) -> CommitTemplatePropertyKind<'repo> {
|
) -> CommitTemplatePropertyKind<'repo> {
|
||||||
CommitTemplatePropertyKind::CommitOrChangeId(property)
|
CommitTemplatePropertyKind::CommitOrChangeId(Box::new(property))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_commit_or_change_id_list(
|
fn wrap_commit_or_change_id_list(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Commit, Output = Vec<CommitOrChangeId<'repo>>> + 'repo>,
|
property: impl TemplateProperty<Commit, Output = Vec<CommitOrChangeId<'repo>>> + 'repo,
|
||||||
) -> CommitTemplatePropertyKind<'repo> {
|
) -> CommitTemplatePropertyKind<'repo> {
|
||||||
CommitTemplatePropertyKind::CommitOrChangeIdList(property)
|
CommitTemplatePropertyKind::CommitOrChangeIdList(Box::new(property))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_shortest_id_prefix(
|
fn wrap_shortest_id_prefix(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo>,
|
property: impl TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo,
|
||||||
) -> CommitTemplatePropertyKind<'repo> {
|
) -> CommitTemplatePropertyKind<'repo> {
|
||||||
CommitTemplatePropertyKind::ShortestIdPrefix(property)
|
CommitTemplatePropertyKind::ShortestIdPrefix(Box::new(property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,15 +145,13 @@ fn build_commit_keyword<'repo>(
|
||||||
name: &str,
|
name: &str,
|
||||||
span: pest::Span,
|
span: pest::Span,
|
||||||
) -> TemplateParseResult<CommitTemplatePropertyKind<'repo>> {
|
) -> TemplateParseResult<CommitTemplatePropertyKind<'repo>> {
|
||||||
fn wrap_fn<'repo, O>(
|
fn wrap_fn<O, F: Fn(&Commit) -> O>(f: F) -> TemplatePropertyFn<F> {
|
||||||
f: impl Fn(&Commit) -> O + 'repo,
|
TemplatePropertyFn(f)
|
||||||
) -> Box<dyn TemplateProperty<Commit, Output = O> + 'repo> {
|
|
||||||
Box::new(TemplatePropertyFn(f))
|
|
||||||
}
|
}
|
||||||
fn wrap_repo_fn<'repo, O>(
|
fn wrap_repo_fn<'repo, O>(
|
||||||
repo: &'repo dyn Repo,
|
repo: &'repo dyn Repo,
|
||||||
f: impl Fn(&dyn Repo, &Commit) -> O + 'repo,
|
f: impl Fn(&dyn Repo, &Commit) -> O + 'repo,
|
||||||
) -> Box<dyn TemplateProperty<Commit, Output = O> + 'repo> {
|
) -> impl TemplateProperty<Commit, Output = O> + 'repo {
|
||||||
wrap_fn(move |commit| f(repo, commit))
|
wrap_fn(move |commit| f(repo, commit))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,17 +368,17 @@ fn build_commit_or_change_id_method<'repo>(
|
||||||
let property = match function.name {
|
let property = match function.name {
|
||||||
"short" => {
|
"short" => {
|
||||||
let len_property = parse_optional_integer(function)?;
|
let len_property = parse_optional_integer(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(
|
||||||
(self_property, len_property),
|
(self_property, len_property),
|
||||||
|(id, len)| id.short(len.and_then(|l| l.try_into().ok()).unwrap_or(12)),
|
|(id, len)| id.short(len.and_then(|l| l.try_into().ok()).unwrap_or(12)),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
"shortest" => {
|
"shortest" => {
|
||||||
let len_property = parse_optional_integer(function)?;
|
let len_property = parse_optional_integer(function)?;
|
||||||
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new(
|
language.wrap_shortest_id_prefix(TemplateFunction::new(
|
||||||
(self_property, len_property),
|
(self_property, len_property),
|
||||||
|(id, len)| id.shortest(len.and_then(|l| l.try_into().ok()).unwrap_or(0)),
|
|(id, len)| id.shortest(len.and_then(|l| l.try_into().ok()).unwrap_or(0)),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(TemplateParseError::no_such_method(
|
return Err(TemplateParseError::no_such_method(
|
||||||
|
@ -427,25 +425,21 @@ fn build_shortest_id_prefix_method<'repo>(
|
||||||
let property = match function.name {
|
let property = match function.name {
|
||||||
"prefix" => {
|
"prefix" => {
|
||||||
template_parser::expect_no_arguments(function)?;
|
template_parser::expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(self_property, |id| {
|
language.wrap_string(TemplateFunction::new(self_property, |id| id.prefix))
|
||||||
id.prefix
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
"rest" => {
|
"rest" => {
|
||||||
template_parser::expect_no_arguments(function)?;
|
template_parser::expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(self_property, |id| id.rest)))
|
language.wrap_string(TemplateFunction::new(self_property, |id| id.rest))
|
||||||
}
|
}
|
||||||
"upper" => {
|
"upper" => {
|
||||||
template_parser::expect_no_arguments(function)?;
|
template_parser::expect_no_arguments(function)?;
|
||||||
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new(self_property, |id| {
|
language
|
||||||
id.to_upper()
|
.wrap_shortest_id_prefix(TemplateFunction::new(self_property, |id| id.to_upper()))
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
"lower" => {
|
"lower" => {
|
||||||
template_parser::expect_no_arguments(function)?;
|
template_parser::expect_no_arguments(function)?;
|
||||||
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new(self_property, |id| {
|
language
|
||||||
id.to_lower()
|
.wrap_shortest_id_prefix(TemplateFunction::new(self_property, |id| id.to_lower()))
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(TemplateParseError::no_such_method(
|
return Err(TemplateParseError::no_such_method(
|
||||||
|
|
|
@ -62,9 +62,9 @@ impl TemplateLanguage<'static> for OperationTemplateLanguage<'_> {
|
||||||
impl OperationTemplateLanguage<'_> {
|
impl OperationTemplateLanguage<'_> {
|
||||||
fn wrap_operation_id(
|
fn wrap_operation_id(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Operation, Output = OperationId>>,
|
property: impl TemplateProperty<Operation, Output = OperationId> + 'static,
|
||||||
) -> OperationTemplatePropertyKind {
|
) -> OperationTemplatePropertyKind {
|
||||||
OperationTemplatePropertyKind::OperationId(property)
|
OperationTemplatePropertyKind::OperationId(Box::new(property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,14 +110,12 @@ fn build_operation_keyword(
|
||||||
name: &str,
|
name: &str,
|
||||||
span: pest::Span,
|
span: pest::Span,
|
||||||
) -> TemplateParseResult<OperationTemplatePropertyKind> {
|
) -> TemplateParseResult<OperationTemplatePropertyKind> {
|
||||||
fn wrap_fn<O>(
|
fn wrap_fn<O, F: Fn(&Operation) -> O>(f: F) -> TemplatePropertyFn<F> {
|
||||||
f: impl Fn(&Operation) -> O + 'static,
|
TemplatePropertyFn(f)
|
||||||
) -> Box<dyn TemplateProperty<Operation, Output = O>> {
|
|
||||||
Box::new(TemplatePropertyFn(f))
|
|
||||||
}
|
}
|
||||||
fn wrap_metadata_fn<O>(
|
fn wrap_metadata_fn<O>(
|
||||||
f: impl Fn(&OperationMetadata) -> O + 'static,
|
f: impl Fn(&OperationMetadata) -> O + 'static,
|
||||||
) -> Box<dyn TemplateProperty<Operation, Output = O>> {
|
) -> impl TemplateProperty<Operation, Output = O> {
|
||||||
wrap_fn(move |op| f(&op.store_operation().metadata))
|
wrap_fn(move |op| f(&op.store_operation().metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,14 +166,14 @@ fn build_operation_id_method(
|
||||||
let len_property = len_node
|
let len_property = len_node
|
||||||
.map(|node| template_parser::expect_integer_expression(language, node))
|
.map(|node| template_parser::expect_integer_expression(language, node))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(
|
||||||
(self_property, len_property),
|
(self_property, len_property),
|
||||||
|(id, len)| {
|
|(id, len)| {
|
||||||
let mut hex = id.hex();
|
let mut hex = id.hex();
|
||||||
hex.truncate(len.and_then(|l| l.try_into().ok()).unwrap_or(12));
|
hex.truncate(len.and_then(|l| l.try_into().ok()).unwrap_or(12));
|
||||||
hex
|
hex
|
||||||
},
|
},
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
_ => return Err(TemplateParseError::no_such_method("OperationId", function)),
|
_ => return Err(TemplateParseError::no_such_method("OperationId", function)),
|
||||||
};
|
};
|
||||||
|
|
|
@ -594,27 +594,27 @@ pub trait TemplateLanguage<'a> {
|
||||||
|
|
||||||
fn wrap_string(
|
fn wrap_string(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = String> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = String> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
fn wrap_boolean(
|
fn wrap_boolean(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = bool> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = bool> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
fn wrap_integer(
|
fn wrap_integer(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = i64> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = i64> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
fn wrap_signature(
|
fn wrap_signature(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = Signature> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = Signature> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
fn wrap_timestamp(
|
fn wrap_timestamp(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = Timestamp> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = Timestamp> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
fn wrap_timestamp_range(
|
fn wrap_timestamp_range(
|
||||||
&self,
|
&self,
|
||||||
property: Box<dyn TemplateProperty<Self::Context, Output = TimestampRange> + 'a>,
|
property: impl TemplateProperty<Self::Context, Output = TimestampRange> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
|
|
||||||
fn build_keyword(&self, name: &str, span: pest::Span) -> TemplateParseResult<Self::Property>;
|
fn build_keyword(&self, name: &str, span: pest::Span) -> TemplateParseResult<Self::Property>;
|
||||||
|
@ -652,12 +652,11 @@ macro_rules! impl_wrap_property_fns {
|
||||||
$(
|
$(
|
||||||
fn $func(
|
fn $func(
|
||||||
&self,
|
&self,
|
||||||
property: Box<
|
property: impl $crate::templater::TemplateProperty<
|
||||||
dyn $crate::templater::TemplateProperty<Self::Context, Output = $ty> + $a
|
Self::Context, Output = $ty> + $a,
|
||||||
>,
|
|
||||||
) -> Self::Property {
|
) -> Self::Property {
|
||||||
use $kind as Kind; // https://github.com/rust-lang/rust/issues/48067
|
use $kind as Kind; // https://github.com/rust-lang/rust/issues/48067
|
||||||
$outer(Kind::$var(property))
|
$outer(Kind::$var(Box::new(property)))
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
|
@ -885,28 +884,24 @@ fn build_string_method<'a, L: TemplateLanguage<'a>>(
|
||||||
let [needle_node] = expect_exact_arguments(function)?;
|
let [needle_node] = expect_exact_arguments(function)?;
|
||||||
// TODO: or .try_into_string() to disable implicit type cast?
|
// TODO: or .try_into_string() to disable implicit type cast?
|
||||||
let needle_property = build_expression(language, needle_node)?.into_plain_text();
|
let needle_property = build_expression(language, needle_node)?.into_plain_text();
|
||||||
language.wrap_boolean(Box::new(TemplateFunction::new(
|
language.wrap_boolean(TemplateFunction::new(
|
||||||
(self_property, needle_property),
|
(self_property, needle_property),
|
||||||
|(haystack, needle)| haystack.contains(&needle),
|
|(haystack, needle)| haystack.contains(&needle),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
"first_line" => {
|
"first_line" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| {
|
language.wrap_string(TemplateFunction::new(self_property, |s| {
|
||||||
s.lines().next().unwrap_or_default().to_string()
|
s.lines().next().unwrap_or_default().to_string()
|
||||||
})))
|
}))
|
||||||
}
|
}
|
||||||
"upper" => {
|
"upper" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| {
|
language.wrap_string(TemplateFunction::new(self_property, |s| s.to_uppercase()))
|
||||||
s.to_uppercase()
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
"lower" => {
|
"lower" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| {
|
language.wrap_string(TemplateFunction::new(self_property, |s| s.to_lowercase()))
|
||||||
s.to_lowercase()
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
_ => return Err(TemplateParseError::no_such_method("String", function)),
|
_ => return Err(TemplateParseError::no_such_method("String", function)),
|
||||||
};
|
};
|
||||||
|
@ -937,34 +932,28 @@ fn build_signature_method<'a, L: TemplateLanguage<'a>>(
|
||||||
let property = match function.name {
|
let property = match function.name {
|
||||||
"name" => {
|
"name" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(self_property, |signature| {
|
||||||
self_property,
|
signature.name
|
||||||
|signature| signature.name,
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
"email" => {
|
"email" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(self_property, |signature| {
|
||||||
self_property,
|
signature.email
|
||||||
|signature| signature.email,
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
"username" => {
|
"username" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(self_property, |signature| {
|
||||||
self_property,
|
let (username, _) = split_email(&signature.email);
|
||||||
|signature| {
|
username.to_owned()
|
||||||
let (username, _) = split_email(&signature.email);
|
}))
|
||||||
username.to_owned()
|
|
||||||
},
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
"timestamp" => {
|
"timestamp" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_timestamp(Box::new(TemplateFunction::new(
|
language.wrap_timestamp(TemplateFunction::new(self_property, |signature| {
|
||||||
self_property,
|
signature.timestamp
|
||||||
|signature| signature.timestamp,
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
_ => return Err(TemplateParseError::no_such_method("Signature", function)),
|
_ => return Err(TemplateParseError::no_such_method("Signature", function)),
|
||||||
};
|
};
|
||||||
|
@ -979,10 +968,9 @@ fn build_timestamp_method<'a, L: TemplateLanguage<'a>>(
|
||||||
let property = match function.name {
|
let property = match function.name {
|
||||||
"ago" => {
|
"ago" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(self_property, |timestamp| {
|
||||||
self_property,
|
time_util::format_timestamp_relative_to_now(×tamp)
|
||||||
|timestamp| time_util::format_timestamp_relative_to_now(×tamp),
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
_ => return Err(TemplateParseError::no_such_method("Timestamp", function)),
|
_ => return Err(TemplateParseError::no_such_method("Timestamp", function)),
|
||||||
};
|
};
|
||||||
|
@ -997,24 +985,21 @@ fn build_timestamp_range_method<'a, L: TemplateLanguage<'a>>(
|
||||||
let property = match function.name {
|
let property = match function.name {
|
||||||
"start" => {
|
"start" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_timestamp(Box::new(TemplateFunction::new(
|
language.wrap_timestamp(TemplateFunction::new(self_property, |time_range| {
|
||||||
self_property,
|
time_range.start
|
||||||
|time_range| time_range.start,
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
"end" => {
|
"end" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_timestamp(Box::new(TemplateFunction::new(
|
language.wrap_timestamp(TemplateFunction::new(self_property, |time_range| {
|
||||||
self_property,
|
time_range.end
|
||||||
|time_range| time_range.end,
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
"duration" => {
|
"duration" => {
|
||||||
expect_no_arguments(function)?;
|
expect_no_arguments(function)?;
|
||||||
language.wrap_string(Box::new(TemplateFunction::new(
|
language.wrap_string(TemplateFunction::new(self_property, |time_range| {
|
||||||
self_property,
|
time_range.duration()
|
||||||
|time_range| time_range.duration(),
|
}))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(TemplateParseError::no_such_method(
|
return Err(TemplateParseError::no_such_method(
|
||||||
|
@ -1108,11 +1093,11 @@ pub fn build_expression<'a, L: TemplateLanguage<'a>>(
|
||||||
Ok(Expression::Property(property, labels))
|
Ok(Expression::Property(property, labels))
|
||||||
}
|
}
|
||||||
ExpressionKind::Integer(value) => {
|
ExpressionKind::Integer(value) => {
|
||||||
let property = language.wrap_integer(Box::new(Literal(*value)));
|
let property = language.wrap_integer(Literal(*value));
|
||||||
Ok(Expression::Property(property, vec![]))
|
Ok(Expression::Property(property, vec![]))
|
||||||
}
|
}
|
||||||
ExpressionKind::String(value) => {
|
ExpressionKind::String(value) => {
|
||||||
let property = language.wrap_string(Box::new(Literal(value.clone())));
|
let property = language.wrap_string(Literal(value.clone()));
|
||||||
Ok(Expression::Property(property, vec![]))
|
Ok(Expression::Property(property, vec![]))
|
||||||
}
|
}
|
||||||
ExpressionKind::List(nodes) => {
|
ExpressionKind::List(nodes) => {
|
||||||
|
|
Loading…
Reference in a new issue