History

commit_templater: teach elidable (or optional) commit

I think Option<Commit> is the simplest encoding of the log node. The behavior of an Option type is closer to nullable types rather than the Option in Rust. I don't think we would want to write opt.map(|x| x.f()) or opt.unwrap().f(). We can of course add opt?.f() syntax, but it will be a short for "if(opt, opt.f())"?

Yuya Nishihara committed 2 years ago

Commit 2fc7feb1 parent 2afd3412 files · +26 −1Browse files

Unified · Split

2 files
  1. cli/src/commit_templater.rs +20 −1
  2. docs/templates.md +6 −0
cli/src/commit_templater.rs+20−1
@@ -39,7 +39,7 @@ use crate::template_builder::{ · 38 unmodified lines
3939 use crate::template_parser::{self, FunctionCallNode, TemplateParseError, TemplateParseResult};
4040 use crate::templater::{
4141 self, IntoTemplate, PlainTextFormattedProperty, Template, TemplateProperty,
42− TemplatePropertyExt as _,
42+ TemplatePropertyError, TemplatePropertyExt as _,
4343 };
4444 use crate::{revset_util, text_util};
4545
@@ -126,6 +126,14 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> { · 80 unmodified lines
126126 let build = template_parser::lookup_method("Commit", table, function)?;
127127 build(self, build_ctx, property, function)
128128 }
129+ CommitTemplatePropertyKind::CommitOpt(property) => {
130+ let table = &self.build_fn_table.commit_methods;
131+ let build = template_parser::lookup_method("Commit", table, function)?;
132+ let inner_property = property.and_then(|opt| {
133+ opt.ok_or_else(|| TemplatePropertyError("No commit available".into()))
134+ });
135+ build(self, build_ctx, Box::new(inner_property), function)
136+ }
129137 CommitTemplatePropertyKind::CommitList(property) => {
130138 // TODO: migrate to table?
131139 template_builder::build_unformattable_list_method(
@@ -190,6 +198,12 @@ impl<'repo> CommitTemplateLanguage<'repo> { · 58 unmodified lines
190198 CommitTemplatePropertyKind::Commit(Box::new(property))
191199 }
192200
201+ pub fn wrap_commit_opt(
202+ property: impl TemplateProperty<Output = Option<Commit>> + 'repo,
203+ ) -> CommitTemplatePropertyKind<'repo> {
204+ CommitTemplatePropertyKind::CommitOpt(Box::new(property))
205+ }
206+
193207 pub fn wrap_commit_list(
194208 property: impl TemplateProperty<Output = Vec<Commit>> + 'repo,
195209 ) -> CommitTemplatePropertyKind<'repo> {
@@ -224,6 +238,7 @@ impl<'repo> CommitTemplateLanguage<'repo> { · 28 unmodified lines
224238 pub enum CommitTemplatePropertyKind<'repo> {
225239 Core(CoreTemplatePropertyKind<'repo>),
226240 Commit(Box<dyn TemplateProperty<Output = Commit> + 'repo>),
241+ CommitOpt(Box<dyn TemplateProperty<Output = Option<Commit>> + 'repo>),
227242 CommitList(Box<dyn TemplateProperty<Output = Vec<Commit>> + 'repo>),
228243 RefName(Box<dyn TemplateProperty<Output = RefName> + 'repo>),
229244 RefNameList(Box<dyn TemplateProperty<Output = Vec<RefName>> + 'repo>),
@@ -236,6 +251,9 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> { · 6 unmodified lines
236251 match self {
237252 CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(),
238253 CommitTemplatePropertyKind::Commit(_) => None,
254+ CommitTemplatePropertyKind::CommitOpt(property) => {
255+ Some(Box::new(property.map(|opt| opt.is_some())))
256+ }
239257 CommitTemplatePropertyKind::CommitList(property) => {
240258 Some(Box::new(property.map(|l| !l.is_empty())))
241259 }
@@ -269,6 +287,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> { · 27 unmodified lines
269287 match self {
270288 CommitTemplatePropertyKind::Core(property) => property.try_into_template(),
271289 CommitTemplatePropertyKind::Commit(_) => None,
290+ CommitTemplatePropertyKind::CommitOpt(_) => None,
272291 CommitTemplatePropertyKind::CommitList(_) => None,
273292 CommitTemplatePropertyKind::RefName(property) => Some(property.into_template()),
274293 CommitTemplatePropertyKind::RefNameList(property) => Some(property.into_template()),
docs/templates.md+6−0
@@ -137,6 +137,12 @@ The following methods are defined. · 136 unmodified lines
137137
138138 * `.short([len: Integer]) -> String`
139139
140+### Option type
141+
142+An option can be implicitly converted to `Boolean` denoting whether the
143+contained value is set. If set, all methods of the contained value can be
144+invoked. If not set, an error will be reported inline on method call.
145+
140146 ### RefName type
141147
142148 The following methods are defined.