ok/jj
1
0
Fork 0
forked from mirrors/jj

templater: expect a list of labels instead of splitting on whitespace

It's clearly the parser's job to split labels in a string provided by
the user. This patch moves the splitting we were doing in
`LabelTemplate` and `DynamicLabelTemplate` to the parser. In the
former case, the string isn't even provided by the user and it doesn't
contain whitespace, we can drop the splitting altogether.
This commit is contained in:
Martin von Zweigbergk 2023-01-07 11:14:01 -08:00 committed by Martin von Zweigbergk
parent 2506cdee28
commit 4953467e44
2 changed files with 13 additions and 12 deletions

View file

@ -390,14 +390,14 @@ fn parse_commit_term<'a>(
} }
} }
Rule::identifier => { Rule::identifier => {
let (term_property, labels) = parse_commit_keyword(repo, workspace_id, expr); let (term_property, label) = parse_commit_keyword(repo, workspace_id, expr);
let property = parse_method_chain(maybe_method, term_property); let property = parse_method_chain(maybe_method, term_property);
let string_property = coerce_to_string(property); let string_property = coerce_to_string(property);
Box::new(LabelTemplate::new( Box::new(LabelTemplate::new(
Box::new(StringPropertyTemplate { Box::new(StringPropertyTemplate {
property: string_property, property: string_property,
}), }),
labels, vec![label],
)) ))
} }
Rule::function => { Rule::function => {
@ -420,11 +420,15 @@ fn parse_commit_term<'a>(
} }
let content: Box<dyn Template<Commit> + 'a> = let content: Box<dyn Template<Commit> + 'a> =
parse_commit_template_rule(repo, workspace_id, arg_template); parse_commit_template_rule(repo, workspace_id, arg_template);
let get_labels = move |commit: &Commit| -> String { let get_labels = move |commit: &Commit| -> Vec<String> {
let mut buf = vec![]; let mut buf = vec![];
let mut formatter = PlainTextFormatter::new(&mut buf); let mut formatter = PlainTextFormatter::new(&mut buf);
label_template.format(commit, &mut formatter).unwrap(); label_template.format(commit, &mut formatter).unwrap();
String::from_utf8(buf).unwrap() String::from_utf8(buf)
.unwrap()
.split_whitespace()
.map(ToString::to_string)
.collect()
}; };
Box::new(DynamicLabelTemplate::new(content, Box::new(get_labels))) Box::new(DynamicLabelTemplate::new(content, Box::new(get_labels)))
} }

View file

@ -64,11 +64,7 @@ pub struct LabelTemplate<'a, C> {
} }
impl<'a, C> LabelTemplate<'a, C> { impl<'a, C> LabelTemplate<'a, C> {
pub fn new(content: Box<dyn Template<C> + 'a>, labels: String) -> Self { pub fn new(content: Box<dyn Template<C> + 'a>, labels: Vec<String>) -> Self {
let labels = labels
.split_whitespace()
.map(|label| label.to_string())
.collect_vec();
LabelTemplate { content, labels } LabelTemplate { content, labels }
} }
} }
@ -86,16 +82,18 @@ impl<'a, C> Template<C> for LabelTemplate<'a, C> {
} }
} }
pub type DynamicLabelFunction<'a, C> = Box<dyn Fn(&C) -> Vec<String> + 'a>;
// TODO: figure out why this lifetime is needed // TODO: figure out why this lifetime is needed
pub struct DynamicLabelTemplate<'a, C> { pub struct DynamicLabelTemplate<'a, C> {
content: Box<dyn Template<C> + 'a>, content: Box<dyn Template<C> + 'a>,
label_property: Box<dyn Fn(&C) -> String + 'a>, label_property: DynamicLabelFunction<'a, C>,
} }
impl<'a, C> DynamicLabelTemplate<'a, C> { impl<'a, C> DynamicLabelTemplate<'a, C> {
pub fn new( pub fn new(
content: Box<dyn Template<C> + 'a>, content: Box<dyn Template<C> + 'a>,
label_property: Box<dyn Fn(&C) -> String + 'a>, label_property: DynamicLabelFunction<'a, C>,
) -> Self { ) -> Self {
DynamicLabelTemplate { DynamicLabelTemplate {
content, content,
@ -107,7 +105,6 @@ impl<'a, C> DynamicLabelTemplate<'a, C> {
impl<'a, C> Template<C> for DynamicLabelTemplate<'a, C> { impl<'a, C> Template<C> for DynamicLabelTemplate<'a, C> {
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> { fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
let labels = self.label_property.as_ref()(context); let labels = self.label_property.as_ref()(context);
let labels = labels.split_whitespace().collect_vec();
for label in &labels { for label in &labels {
formatter.add_label(label)?; formatter.add_label(label)?;
} }