forked from mirrors/jj
templater: add enum that holds property or template
This allows us to merge parse_boolean_commit_property() into parse_commit_term(). We'll probably need similar type coercion methods for the other basic types. I considered adding something like Property::Template(), which could be reused for map operation (e.g. 'revset().map(commit_id).join(" ")'.) However, a mapped commit template would be different from the top-level commit template regarding the lifetime of the context. "Expression::<Commit>::Template()" takes "for<'b> &'b Commit" as an argument, whereas a mapped template property would capture Commit object somewhere.
This commit is contained in:
parent
8d7ba8ddd3
commit
5eee7186ba
1 changed files with 39 additions and 19 deletions
|
@ -119,6 +119,20 @@ impl<'a, C: 'a> PropertyAndLabels<'a, C> {
|
|||
}
|
||||
}
|
||||
|
||||
enum Expression<'a, C> {
|
||||
Property(PropertyAndLabels<'a, C>),
|
||||
Template(Box<dyn Template<C> + 'a>),
|
||||
}
|
||||
|
||||
impl<'a, C: 'a> Expression<'a, C> {
|
||||
fn into_template(self) -> Box<dyn Template<C> + 'a> {
|
||||
match self {
|
||||
Expression::Property(property_labels) => property_labels.into_template(),
|
||||
Expression::Template(template) => template,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_method_chain<'a, I: 'a>(
|
||||
pair: Pair<Rule>,
|
||||
input_property: PropertyAndLabels<'a, I>,
|
||||
|
@ -274,7 +288,7 @@ fn parse_commit_term<'a>(
|
|||
repo: RepoRef<'a>,
|
||||
workspace_id: &WorkspaceId,
|
||||
pair: Pair<Rule>,
|
||||
) -> Box<dyn Template<Commit> + 'a> {
|
||||
) -> Expression<'a, Commit> {
|
||||
assert_eq!(pair.as_rule(), Rule::term);
|
||||
let mut inner = pair.into_inner();
|
||||
let expr = inner.next().unwrap();
|
||||
|
@ -284,11 +298,11 @@ fn parse_commit_term<'a>(
|
|||
Rule::literal => {
|
||||
let text = parse_string_literal(expr);
|
||||
let term = PropertyAndLabels(Property::String(Box::new(Literal(text))), vec![]);
|
||||
parse_method_chain(maybe_method, term).into_template()
|
||||
Expression::Property(parse_method_chain(maybe_method, term))
|
||||
}
|
||||
Rule::identifier => {
|
||||
let term = parse_commit_keyword(repo, workspace_id, expr);
|
||||
parse_method_chain(maybe_method, term).into_template()
|
||||
Expression::Property(parse_method_chain(maybe_method, term))
|
||||
}
|
||||
Rule::function => {
|
||||
let (name, mut args) = {
|
||||
|
@ -302,7 +316,8 @@ fn parse_commit_term<'a>(
|
|||
match name.as_str() {
|
||||
"label" => {
|
||||
let label_pair = args.next().unwrap();
|
||||
let label_template = parse_commit_template_rule(repo, workspace_id, label_pair);
|
||||
let label_template =
|
||||
parse_commit_template_rule(repo, workspace_id, label_pair).into_template();
|
||||
let arg_template = match args.next() {
|
||||
None => panic!("label() requires two arguments"),
|
||||
Some(pair) => pair,
|
||||
|
@ -310,8 +325,8 @@ fn parse_commit_term<'a>(
|
|||
if args.next().is_some() {
|
||||
panic!("label() accepts only two arguments")
|
||||
}
|
||||
let content: Box<dyn Template<Commit> + 'a> =
|
||||
parse_commit_template_rule(repo, workspace_id, arg_template);
|
||||
let content = parse_commit_template_rule(repo, workspace_id, arg_template)
|
||||
.into_template();
|
||||
let get_labels = move |commit: &Commit| -> Vec<String> {
|
||||
let mut buf = vec![];
|
||||
let mut formatter = PlainTextFormatter::new(&mut buf);
|
||||
|
@ -322,7 +337,8 @@ fn parse_commit_term<'a>(
|
|||
.map(ToString::to_string)
|
||||
.collect()
|
||||
};
|
||||
Box::new(DynamicLabelTemplate::new(content, get_labels))
|
||||
let template = Box::new(DynamicLabelTemplate::new(content, get_labels));
|
||||
Expression::Template(template)
|
||||
}
|
||||
"if" => {
|
||||
let condition_pair = args.next().unwrap();
|
||||
|
@ -332,19 +348,22 @@ fn parse_commit_term<'a>(
|
|||
|
||||
let true_template = match args.next() {
|
||||
None => panic!("if() requires at least two arguments"),
|
||||
Some(pair) => parse_commit_template_rule(repo, workspace_id, pair),
|
||||
Some(pair) => {
|
||||
parse_commit_template_rule(repo, workspace_id, pair).into_template()
|
||||
}
|
||||
};
|
||||
let false_template = args
|
||||
.next()
|
||||
.map(|pair| parse_commit_template_rule(repo, workspace_id, pair));
|
||||
let false_template = args.next().map(|pair| {
|
||||
parse_commit_template_rule(repo, workspace_id, pair).into_template()
|
||||
});
|
||||
if args.next().is_some() {
|
||||
panic!("if() accepts at most three arguments")
|
||||
}
|
||||
Box::new(ConditionalTemplate::new(
|
||||
let template = Box::new(ConditionalTemplate::new(
|
||||
condition,
|
||||
true_template,
|
||||
false_template,
|
||||
))
|
||||
));
|
||||
Expression::Template(template)
|
||||
}
|
||||
name => panic!("function {name} not implemented"),
|
||||
}
|
||||
|
@ -358,16 +377,17 @@ fn parse_commit_template_rule<'a>(
|
|||
repo: RepoRef<'a>,
|
||||
workspace_id: &WorkspaceId,
|
||||
pair: Pair<Rule>,
|
||||
) -> Box<dyn Template<Commit> + 'a> {
|
||||
) -> Expression<'a, Commit> {
|
||||
assert_eq!(pair.as_rule(), Rule::template);
|
||||
let inner = pair.into_inner();
|
||||
let mut templates = inner
|
||||
let mut expressions = inner
|
||||
.map(|term| parse_commit_term(repo, workspace_id, term))
|
||||
.collect_vec();
|
||||
if templates.len() == 1 {
|
||||
templates.pop().unwrap()
|
||||
if expressions.len() == 1 {
|
||||
expressions.pop().unwrap()
|
||||
} else {
|
||||
Box::new(ListTemplate(templates))
|
||||
let templates = expressions.into_iter().map(|x| x.into_template()).collect();
|
||||
Expression::Template(Box::new(ListTemplate(templates)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,6 +401,6 @@ pub fn parse_commit_template<'a>(
|
|||
if first_pair.as_rule() == Rule::EOI {
|
||||
Box::new(Literal(String::new()))
|
||||
} else {
|
||||
parse_commit_template_rule(repo, workspace_id, first_pair)
|
||||
parse_commit_template_rule(repo, workspace_id, first_pair).into_template()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue