mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 18:27:38 +00:00
templater: add join method to mapped template
This commit is contained in:
parent
2fbe581a71
commit
998727266c
3 changed files with 48 additions and 4 deletions
|
@ -92,9 +92,15 @@ The following methods are defined.
|
||||||
|
|
||||||
* `.join(separator: Template) -> Template`: Concatenate elements with
|
* `.join(separator: Template) -> Template`: Concatenate elements with
|
||||||
the given `separator`.
|
the given `separator`.
|
||||||
* `.map(|item| expression) -> Template`: Apply template `expression`
|
* `.map(|item| expression) -> ListTemplate`: Apply template `expression`
|
||||||
to each element. Example: `parent_commit_ids.map(|id| id.short())`
|
to each element. Example: `parent_commit_ids.map(|id| id.short())`
|
||||||
|
|
||||||
|
### ListTemplate type
|
||||||
|
|
||||||
|
The following methods are defined. See also the `List` type.
|
||||||
|
|
||||||
|
* `.join(separator: Template) -> Template`
|
||||||
|
|
||||||
### OperationId type
|
### OperationId type
|
||||||
|
|
||||||
The following methods are defined.
|
The following methods are defined.
|
||||||
|
|
|
@ -23,8 +23,8 @@ use crate::template_parser::{
|
||||||
};
|
};
|
||||||
use crate::templater::{
|
use crate::templater::{
|
||||||
ConcatTemplate, ConditionalTemplate, IntoTemplate, LabelTemplate, ListPropertyTemplate,
|
ConcatTemplate, ConditionalTemplate, IntoTemplate, LabelTemplate, ListPropertyTemplate,
|
||||||
Literal, PlainTextFormattedProperty, PropertyPlaceholder, ReformatTemplate, SeparateTemplate,
|
ListTemplate, Literal, PlainTextFormattedProperty, PropertyPlaceholder, ReformatTemplate,
|
||||||
Template, TemplateFunction, TemplateProperty, TimestampRange,
|
SeparateTemplate, Template, TemplateFunction, TemplateProperty, TimestampRange,
|
||||||
};
|
};
|
||||||
use crate::{text_util, time_util};
|
use crate::{text_util, time_util};
|
||||||
|
|
||||||
|
@ -61,7 +61,12 @@ pub trait TemplateLanguage<'a> {
|
||||||
&self,
|
&self,
|
||||||
property: impl TemplateProperty<Self::Context, Output = TimestampRange> + 'a,
|
property: impl TemplateProperty<Self::Context, Output = TimestampRange> + 'a,
|
||||||
) -> Self::Property;
|
) -> Self::Property;
|
||||||
|
|
||||||
fn wrap_template(&self, template: Box<dyn Template<Self::Context> + 'a>) -> Self::Property;
|
fn wrap_template(&self, template: Box<dyn Template<Self::Context> + 'a>) -> Self::Property;
|
||||||
|
fn wrap_list_template(
|
||||||
|
&self,
|
||||||
|
template: Box<dyn ListTemplate<Self::Context> + 'a>,
|
||||||
|
) -> 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>;
|
||||||
fn build_method(
|
fn build_method(
|
||||||
|
@ -99,6 +104,13 @@ macro_rules! impl_core_wrap_property_fns {
|
||||||
use $crate::template_builder::CoreTemplatePropertyKind as Kind;
|
use $crate::template_builder::CoreTemplatePropertyKind as Kind;
|
||||||
$outer(Kind::Template(template))
|
$outer(Kind::Template(template))
|
||||||
}
|
}
|
||||||
|
fn wrap_list_template(
|
||||||
|
&self,
|
||||||
|
template: Box<dyn $crate::templater::ListTemplate<Self::Context> + $a>,
|
||||||
|
) -> Self::Property {
|
||||||
|
use $crate::template_builder::CoreTemplatePropertyKind as Kind;
|
||||||
|
$outer(Kind::ListTemplate(template))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +152,7 @@ pub enum CoreTemplatePropertyKind<'a, I> {
|
||||||
// capture `I` to produce `Template<()>`. The context `I` would have to be cloned
|
// capture `I` to produce `Template<()>`. The context `I` would have to be cloned
|
||||||
// to convert `Template<I>` to `Template<()>`.
|
// to convert `Template<I>` to `Template<()>`.
|
||||||
Template(Box<dyn Template<I> + 'a>),
|
Template(Box<dyn Template<I> + 'a>),
|
||||||
|
ListTemplate(Box<dyn ListTemplate<I> + 'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I: 'a> IntoTemplateProperty<'a, I> for CoreTemplatePropertyKind<'a, I> {
|
impl<'a, I: 'a> IntoTemplateProperty<'a, I> for CoreTemplatePropertyKind<'a, I> {
|
||||||
|
@ -180,6 +193,7 @@ impl<'a, I: 'a> IntoTemplate<'a, I> for CoreTemplatePropertyKind<'a, I> {
|
||||||
CoreTemplatePropertyKind::Timestamp(property) => property.into_template(),
|
CoreTemplatePropertyKind::Timestamp(property) => property.into_template(),
|
||||||
CoreTemplatePropertyKind::TimestampRange(property) => property.into_template(),
|
CoreTemplatePropertyKind::TimestampRange(property) => property.into_template(),
|
||||||
CoreTemplatePropertyKind::Template(template) => template,
|
CoreTemplatePropertyKind::Template(template) => template,
|
||||||
|
CoreTemplatePropertyKind::ListTemplate(template) => template.into_template(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,6 +302,9 @@ pub fn build_core_method<'a, L: TemplateLanguage<'a>>(
|
||||||
CoreTemplatePropertyKind::Template(_) => {
|
CoreTemplatePropertyKind::Template(_) => {
|
||||||
Err(TemplateParseError::no_such_method("Template", function))
|
Err(TemplateParseError::no_such_method("Template", function))
|
||||||
}
|
}
|
||||||
|
CoreTemplatePropertyKind::ListTemplate(template) => {
|
||||||
|
build_list_template_method(language, build_ctx, template, function)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,6 +472,23 @@ fn build_timestamp_range_method<'a, L: TemplateLanguage<'a>>(
|
||||||
Ok(property)
|
Ok(property)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_list_template_method<'a, L: TemplateLanguage<'a>>(
|
||||||
|
language: &L,
|
||||||
|
build_ctx: &BuildContext<L::Property>,
|
||||||
|
self_template: Box<dyn ListTemplate<L::Context> + 'a>,
|
||||||
|
function: &FunctionCallNode,
|
||||||
|
) -> TemplateParseResult<L::Property> {
|
||||||
|
let property = match function.name {
|
||||||
|
"join" => {
|
||||||
|
let [separator_node] = template_parser::expect_exact_arguments(function)?;
|
||||||
|
let separator = build_expression(language, build_ctx, separator_node)?.into_template();
|
||||||
|
language.wrap_template(self_template.join(separator))
|
||||||
|
}
|
||||||
|
_ => return Err(TemplateParseError::no_such_method("ListTemplate", function)),
|
||||||
|
};
|
||||||
|
Ok(property)
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds method call expression for printable list property.
|
/// Builds method call expression for printable list property.
|
||||||
pub fn build_list_method<'a, L, O>(
|
pub fn build_list_method<'a, L, O>(
|
||||||
language: &L,
|
language: &L,
|
||||||
|
@ -531,7 +565,7 @@ where
|
||||||
item_placeholder.with_value(item, || item_template.format(context, formatter))
|
item_placeholder.with_value(item, || item_template.format(context, formatter))
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Ok(language.wrap_template(Box::new(list_template)))
|
Ok(language.wrap_list_template(Box::new(list_template)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_global_function<'a, L: TemplateLanguage<'a>>(
|
fn build_global_function<'a, L: TemplateLanguage<'a>>(
|
||||||
|
|
|
@ -277,6 +277,10 @@ fn test_templater_list_method() {
|
||||||
insta::assert_snapshot!(
|
insta::assert_snapshot!(
|
||||||
render(r#""a\nb\nc".lines().map(|s| "x\ny".lines().map(|t| s ++ t))"#),
|
render(r#""a\nb\nc".lines().map(|s| "x\ny".lines().map(|t| s ++ t))"#),
|
||||||
@"ax ay bx by cx cy");
|
@"ax ay bx by cx cy");
|
||||||
|
// Nested map/join operations
|
||||||
|
insta::assert_snapshot!(
|
||||||
|
render(r#""a\nb\nc".lines().map(|s| "x\ny".lines().map(|t| s ++ t).join(",")).join(";")"#),
|
||||||
|
@"ax,ay;bx,by;cx,cy");
|
||||||
|
|
||||||
// Lambda expression in alias
|
// Lambda expression in alias
|
||||||
insta::assert_snapshot!(render(r#""a\nb\nc".lines().map(identity)"#), @"a b c");
|
insta::assert_snapshot!(render(r#""a\nb\nc".lines().map(identity)"#), @"a b c");
|
||||||
|
|
Loading…
Reference in a new issue