templater: generalize formattable list template for map operation

This commit is contained in:
Yuya Nishihara 2023-03-14 19:17:50 +09:00
parent ea0cc374aa
commit 369c119053
2 changed files with 22 additions and 17 deletions

View file

@ -20,9 +20,9 @@ use crate::template_parser::{
TemplateParseResult, TemplateParseResult,
}; };
use crate::templater::{ use crate::templater::{
ConcatTemplate, ConditionalTemplate, FormattablePropertyListTemplate, IntoTemplate, ConcatTemplate, ConditionalTemplate, IntoTemplate, LabelTemplate, ListPropertyTemplate,
LabelTemplate, Literal, PlainTextFormattedProperty, ReformatTemplate, SeparateTemplate, Literal, PlainTextFormattedProperty, ReformatTemplate, SeparateTemplate, Template,
Template, TemplateFunction, TemplateProperty, TimestampRange, TemplateFunction, TemplateProperty, TimestampRange,
}; };
use crate::{text_util, time_util}; use crate::{text_util, time_util};
@ -444,7 +444,10 @@ pub fn build_list_method<'a, L: TemplateLanguage<'a>, P: Template<()> + 'a>(
"join" => { "join" => {
let [separator_node] = template_parser::expect_exact_arguments(function)?; let [separator_node] = template_parser::expect_exact_arguments(function)?;
let separator = build_expression(language, separator_node)?.into_template(); let separator = build_expression(language, separator_node)?.into_template();
let template = FormattablePropertyListTemplate::new(self_property, separator); let template =
ListPropertyTemplate::new(self_property, separator, |_, formatter, item| {
item.format(&(), formatter)
});
language.wrap_template(template) language.wrap_template(template)
} }
// TODO: .map() // TODO: .map()

View file

@ -366,36 +366,38 @@ impl<C, T: Template<C>> TemplateProperty<C> for PlainTextFormattedProperty<T> {
} }
} }
/// Renders a list of template properties with the given separator. /// Renders template property of list type with the given separator.
/// ///
/// Each template property can be extracted as a context-less value, but /// Each list item will be formatted by the given `format_item()` function.
/// the separator takes a context of type `C`. /// The separator takes a context of type `C`.
pub struct FormattablePropertyListTemplate<P, S> { pub struct ListPropertyTemplate<P, S, F> {
property: P, property: P,
separator: S, separator: S,
format_item: F,
} }
impl<P, S> FormattablePropertyListTemplate<P, S> { impl<P, S, F> ListPropertyTemplate<P, S, F> {
pub fn new<C>(property: P, separator: S) -> Self pub fn new<C, O>(property: P, separator: S, format_item: F) -> Self
where where
P: TemplateProperty<C>, P: TemplateProperty<C>,
P::Output: IntoIterator, P::Output: IntoIterator<Item = O>,
<P::Output as IntoIterator>::Item: Template<()>,
S: Template<C>, S: Template<C>,
F: Fn(&C, &mut dyn Formatter, O) -> io::Result<()>,
{ {
FormattablePropertyListTemplate { ListPropertyTemplate {
property, property,
separator, separator,
format_item,
} }
} }
} }
impl<C, P, S> Template<C> for FormattablePropertyListTemplate<P, S> impl<C, O, P, S, F> Template<C> for ListPropertyTemplate<P, S, F>
where where
P: TemplateProperty<C>, P: TemplateProperty<C>,
P::Output: IntoIterator, P::Output: IntoIterator<Item = O>,
<P::Output as IntoIterator>::Item: Template<()>,
S: Template<C>, S: Template<C>,
F: Fn(&C, &mut dyn Formatter, O) -> io::Result<()>,
{ {
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> { fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
let contents = self.property.extract(context); let contents = self.property.extract(context);
@ -404,7 +406,7 @@ where
formatter, formatter,
contents, contents,
&self.separator, &self.separator,
|_, formatter, item| item.format(&(), formatter), &self.format_item,
) )
} }
} }