mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-24 12:48:55 +00:00
templater: add "parents" keyword in place of "parent_commit_ids"
All commit keywords are mapped to nullary methods. No matter if we'll introduce .field syntax and/or self. keyword, this implementation can be reused.
This commit is contained in:
parent
f4235464c2
commit
75d68fe24c
3 changed files with 76 additions and 38 deletions
|
@ -18,7 +18,7 @@ The following keywords can be used in `jj log`/`jj obslog` templates.
|
|||
* `description: String`
|
||||
* `change_id: ChangeId`
|
||||
* `commit_id: CommitId`
|
||||
* `parent_commit_ids: List<CommitId>`
|
||||
* `parents: List<Commit>`
|
||||
* `author: Signature`
|
||||
* `committer: Signature`
|
||||
* `working_copies: String`: For multi-workspace repository, indicate
|
||||
|
@ -75,6 +75,11 @@ The following functions are defined.
|
|||
|
||||
No methods are defined.
|
||||
|
||||
### Commit type
|
||||
|
||||
This type cannot be printed. All commit keywords are accessible as 0-argument
|
||||
methods.
|
||||
|
||||
### CommitId / ChangeId type
|
||||
|
||||
The following methods are defined.
|
||||
|
@ -93,7 +98,7 @@ The following methods are defined.
|
|||
* `.join(separator: Template) -> Template`: Concatenate elements with
|
||||
the given `separator`.
|
||||
* `.map(|item| expression) -> ListTemplate`: Apply template `expression`
|
||||
to each element. Example: `parent_commit_ids.map(|id| id.short())`
|
||||
to each element. Example: `parents.map(|c| c.commit_id().short())`
|
||||
|
||||
### ListTemplate type
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ use crate::template_parser::{
|
|||
self, FunctionCallNode, TemplateAliasesMap, TemplateParseError, TemplateParseResult,
|
||||
};
|
||||
use crate::templater::{
|
||||
self, IntoTemplate, PlainTextFormattedProperty, Template, TemplateFunction, TemplateProperty,
|
||||
IntoTemplate, PlainTextFormattedProperty, Template, TemplateFunction, TemplateProperty,
|
||||
TemplatePropertyFn,
|
||||
};
|
||||
use crate::text_util;
|
||||
|
@ -61,18 +61,21 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo, '_> {
|
|||
CommitTemplatePropertyKind::Core(property) => {
|
||||
template_builder::build_core_method(self, build_ctx, property, function)
|
||||
}
|
||||
CommitTemplatePropertyKind::CommitOrChangeId(property) => {
|
||||
build_commit_or_change_id_method(self, build_ctx, property, function)
|
||||
CommitTemplatePropertyKind::Commit(property) => {
|
||||
build_commit_method(self, build_ctx, property, function)
|
||||
}
|
||||
CommitTemplatePropertyKind::CommitOrChangeIdList(property) => {
|
||||
template_builder::build_formattable_list_method(
|
||||
CommitTemplatePropertyKind::CommitList(property) => {
|
||||
template_builder::build_unformattable_list_method(
|
||||
self,
|
||||
build_ctx,
|
||||
property,
|
||||
function,
|
||||
|item| self.wrap_commit_or_change_id(item),
|
||||
|item| self.wrap_commit(item),
|
||||
)
|
||||
}
|
||||
CommitTemplatePropertyKind::CommitOrChangeId(property) => {
|
||||
build_commit_or_change_id_method(self, build_ctx, property, function)
|
||||
}
|
||||
CommitTemplatePropertyKind::ShortestIdPrefix(property) => {
|
||||
build_shortest_id_prefix_method(self, build_ctx, property, function)
|
||||
}
|
||||
|
@ -83,6 +86,20 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo, '_> {
|
|||
// If we need to add multiple languages that support Commit types, this can be
|
||||
// turned into a trait which extends TemplateLanguage.
|
||||
impl<'repo> CommitTemplateLanguage<'repo, '_> {
|
||||
fn wrap_commit(
|
||||
&self,
|
||||
property: impl TemplateProperty<Commit, Output = Commit> + 'repo,
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::Commit(Box::new(property))
|
||||
}
|
||||
|
||||
fn wrap_commit_list(
|
||||
&self,
|
||||
property: impl TemplateProperty<Commit, Output = Vec<Commit>> + 'repo,
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::CommitList(Box::new(property))
|
||||
}
|
||||
|
||||
fn wrap_commit_or_change_id(
|
||||
&self,
|
||||
property: impl TemplateProperty<Commit, Output = CommitOrChangeId> + 'repo,
|
||||
|
@ -90,13 +107,6 @@ impl<'repo> CommitTemplateLanguage<'repo, '_> {
|
|||
CommitTemplatePropertyKind::CommitOrChangeId(Box::new(property))
|
||||
}
|
||||
|
||||
fn wrap_commit_or_change_id_list(
|
||||
&self,
|
||||
property: impl TemplateProperty<Commit, Output = Vec<CommitOrChangeId>> + 'repo,
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::CommitOrChangeIdList(Box::new(property))
|
||||
}
|
||||
|
||||
fn wrap_shortest_id_prefix(
|
||||
&self,
|
||||
property: impl TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo,
|
||||
|
@ -107,8 +117,9 @@ impl<'repo> CommitTemplateLanguage<'repo, '_> {
|
|||
|
||||
enum CommitTemplatePropertyKind<'repo> {
|
||||
Core(CoreTemplatePropertyKind<'repo, Commit>),
|
||||
Commit(Box<dyn TemplateProperty<Commit, Output = Commit> + 'repo>),
|
||||
CommitList(Box<dyn TemplateProperty<Commit, Output = Vec<Commit>> + 'repo>),
|
||||
CommitOrChangeId(Box<dyn TemplateProperty<Commit, Output = CommitOrChangeId> + 'repo>),
|
||||
CommitOrChangeIdList(Box<dyn TemplateProperty<Commit, Output = Vec<CommitOrChangeId>> + 'repo>),
|
||||
ShortestIdPrefix(Box<dyn TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo>),
|
||||
}
|
||||
|
||||
|
@ -143,12 +154,11 @@ impl<'repo> IntoTemplateProperty<'repo, Commit> for CommitTemplatePropertyKind<'
|
|||
fn try_into_template(self) -> Option<Box<dyn Template<Commit> + 'repo>> {
|
||||
match self {
|
||||
CommitTemplatePropertyKind::Core(property) => property.try_into_template(),
|
||||
CommitTemplatePropertyKind::Commit(_) => None,
|
||||
CommitTemplatePropertyKind::CommitList(_) => None,
|
||||
CommitTemplatePropertyKind::CommitOrChangeId(property) => {
|
||||
Some(property.into_template())
|
||||
}
|
||||
CommitTemplatePropertyKind::CommitOrChangeIdList(property) => {
|
||||
Some(property.into_template())
|
||||
}
|
||||
CommitTemplatePropertyKind::ShortestIdPrefix(property) => {
|
||||
Some(property.into_template())
|
||||
}
|
||||
|
@ -171,6 +181,20 @@ fn build_commit_keyword<'repo>(
|
|||
.ok_or_else(|| TemplateParseError::no_such_keyword(name, span))
|
||||
}
|
||||
|
||||
fn build_commit_method<'repo>(
|
||||
language: &CommitTemplateLanguage<'repo, '_>,
|
||||
_build_ctx: &BuildContext<CommitTemplatePropertyKind<'repo>>,
|
||||
self_property: impl TemplateProperty<Commit, Output = Commit> + 'repo,
|
||||
function: &FunctionCallNode,
|
||||
) -> TemplateParseResult<CommitTemplatePropertyKind<'repo>> {
|
||||
if let Some(property) = build_commit_keyword_opt(language, self_property, function.name) {
|
||||
template_parser::expect_no_arguments(function)?;
|
||||
Ok(property)
|
||||
} else {
|
||||
Err(TemplateParseError::no_such_method("Commit", function))
|
||||
}
|
||||
}
|
||||
|
||||
fn build_commit_keyword_opt<'repo>(
|
||||
language: &CommitTemplateLanguage<'repo, '_>,
|
||||
property: impl TemplateProperty<Commit, Output = Commit> + 'repo,
|
||||
|
@ -201,15 +225,7 @@ fn build_commit_keyword_opt<'repo>(
|
|||
"commit_id" => language.wrap_commit_or_change_id(wrap_fn(property, |commit| {
|
||||
CommitOrChangeId::Commit(commit.id().to_owned())
|
||||
})),
|
||||
"parent_commit_ids" => {
|
||||
language.wrap_commit_or_change_id_list(wrap_fn(property, move |commit| {
|
||||
commit
|
||||
.parent_ids()
|
||||
.iter()
|
||||
.map(|id| CommitOrChangeId::Commit(id.to_owned()))
|
||||
.collect()
|
||||
}))
|
||||
}
|
||||
"parents" => language.wrap_commit_list(wrap_fn(property, |commit| commit.parents())),
|
||||
"author" => language.wrap_signature(wrap_fn(property, |commit| commit.author().clone())),
|
||||
"committer" => {
|
||||
language.wrap_signature(wrap_fn(property, |commit| commit.committer().clone()))
|
||||
|
@ -381,12 +397,6 @@ impl Template<()> for CommitOrChangeId {
|
|||
}
|
||||
}
|
||||
|
||||
impl Template<()> for Vec<CommitOrChangeId> {
|
||||
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
||||
templater::format_joined(&(), formatter, self, " ")
|
||||
}
|
||||
}
|
||||
|
||||
fn build_commit_or_change_id_method<'repo>(
|
||||
language: &CommitTemplateLanguage<'repo, '_>,
|
||||
build_ctx: &BuildContext<CommitTemplatePropertyKind<'repo>>,
|
||||
|
|
|
@ -18,7 +18,7 @@ use regex::Regex;
|
|||
pub mod common;
|
||||
|
||||
#[test]
|
||||
fn test_log_parent_commit_ids() {
|
||||
fn test_log_parents() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
@ -27,7 +27,7 @@ fn test_log_parent_commit_ids() {
|
|||
test_env.jj_cmd_success(&repo_path, &["new", "@-"]);
|
||||
test_env.jj_cmd_success(&repo_path, &["new", "@", "@-"]);
|
||||
|
||||
let template = r#"commit_id ++ "\nP: " ++ parent_commit_ids ++ "\n""#;
|
||||
let template = r#"commit_id ++ "\nP: " ++ parents.map(|c| c.commit_id()) ++ "\n""#;
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", template]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ c067170d4ca1bc6162b64f7550617ec809647f84
|
||||
|
@ -40,16 +40,39 @@ fn test_log_parent_commit_ids() {
|
|||
P:
|
||||
"###);
|
||||
|
||||
let template = r#"parent_commit_ids.map(|id| id.shortest(4))"#;
|
||||
let template = r#"parents.map(|c| c.commit_id().shortest(4))"#;
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&repo_path,
|
||||
&["log", "-T", template, "-r@", "--color=always"],
|
||||
);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ [1m4[0m[38;5;8mdb4[39m [1m2[0m[38;5;8m30d[39m
|
||||
@ [1m[38;5;4m4[0m[38;5;8mdb4[39m [1m[38;5;4m2[0m[38;5;8m30d[39m
|
||||
│
|
||||
~
|
||||
"###);
|
||||
|
||||
// Commit object isn't printable
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-T", "parents"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse template: --> 1:1
|
||||
|
|
||||
1 | parents
|
||||
| ^-----^
|
||||
|
|
||||
= Expected expression of type "Template"
|
||||
"###);
|
||||
|
||||
// Redundant argument passed to keyword method
|
||||
let template = r#"parents.map(|c| c.commit_id(""))"#;
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-T", template]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse template: --> 1:29
|
||||
|
|
||||
1 | parents.map(|c| c.commit_id(""))
|
||||
| ^^
|
||||
|
|
||||
= Function "commit_id": Expected 0 arguments
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue