Skip to content

Commit

Permalink
templater: port annotation line content to template
Browse files Browse the repository at this point in the history
I originally thought we would have to add BString template type first, but we
can use opaque Template type instead.
  • Loading branch information
yuja committed Feb 15, 2025
1 parent 6f51696 commit 4ec22dd
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 11 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
using `templates.backout_description`.

* New `AnnotationLine` templater type. Used in `templates.file_annotate`.
Provides `self.commit()`, `self.line_number()`, and `self.first_line_in_hunk()`.
Provides `self.commit()`, `.content()`, `.line_number()`, and
`.first_line_in_hunk()`.

### Fixed bugs

Expand Down
10 changes: 5 additions & 5 deletions cli/src/commands/file/annotate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ pub(crate) struct FileAnnotateArgs {
add = ArgValueCandidates::new(complete::all_revisions)
)]
revision: Option<RevisionArg>,
/// Render a prefix for each line using the given template
/// Render each line using the given template
///
/// All 0-argument methods of the [`AnnotationLine` type] are available as
/// keywords in the [template expression].
///
/// If not specified, this defaults to the
/// `templates.file_annotate` setting.
/// If not specified, this defaults to the `templates.file_annotate`
/// setting.
///
/// [template expression]:
/// https://jj-vcs.github.io/jj/latest/templates/
Expand Down Expand Up @@ -123,17 +123,17 @@ fn render_file_annotation(
ui.request_pager();
let mut formatter = ui.stdout_formatter();
let mut last_id = None;
for (line_number, (commit_id, line)) in annotation.lines().enumerate() {
for (line_number, (commit_id, content)) in annotation.lines().enumerate() {
let commit_id = commit_id.expect("should reached to the empty ancestor");
let commit = repo.store().get_commit(commit_id)?;
let first_line_in_hunk = last_id != Some(commit_id);
let annotation_line = AnnotationLine {
commit,
content: content.to_owned(),
line_number: line_number + 1,
first_line_in_hunk,
};
template_render.format(&annotation_line, formatter.as_mut())?;
formatter.write_all(line)?;
last_id = Some(commit_id);
}

Expand Down
12 changes: 11 additions & 1 deletion cli/src/commit_templater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::collections::HashMap;
use std::io;
use std::rc::Rc;

use bstr::BString;
use futures::stream::BoxStream;
use futures::StreamExt as _;
use futures::TryStreamExt as _;
Expand Down Expand Up @@ -2218,10 +2219,10 @@ pub fn builtin_cryptographic_signature_methods<'repo>(
map
}

// TODO: add `line: BString` field when available in template language
#[derive(Debug, Clone)]
pub struct AnnotationLine {
pub commit: Commit,
pub content: BString,
pub line_number: usize,
pub first_line_in_hunk: bool,
}
Expand All @@ -2238,6 +2239,15 @@ pub fn builtin_annotation_line_methods<'repo>(
Ok(L::wrap_commit(out_property))
},
);
map.insert(
"content",
|_language, _diagnostics, _build_ctx, self_property, function| {
function.expect_no_arguments()?;
let out_property = self_property.map(|line| line.content);
// TODO: Add Bytes or BString template type?
Ok(L::wrap_template(out_property.into_template()))
},
);
map.insert(
"line_number",
|_language, _diagnostics, _build_ctx, self_property, function| {
Expand Down
4 changes: 2 additions & 2 deletions cli/src/config/templates.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ separate(" ",
commit.change_id().shortest(8),
pad_end(8, truncate_end(8, commit.author().email().local())),
commit_timestamp(commit).local().format('%Y-%m-%d %H:%M:%S'),
pad_start(4, line_number) ++ ": ",
)
pad_start(4, line_number),
) ++ ": " ++ content
'''

config_list = '''
Expand Down
14 changes: 14 additions & 0 deletions cli/src/templater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use std::io::Write;
use std::iter;
use std::rc::Rc;

use bstr::BStr;
use bstr::BString;
use jj_lib::backend::Signature;
use jj_lib::backend::Timestamp;
use jj_lib::config::ConfigValue;
Expand Down Expand Up @@ -69,6 +71,18 @@ impl<T: Template> Template for Option<T> {
}
}

impl Template for BString {
fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> {
formatter.as_mut().write_all(self)
}
}

impl Template for &BStr {
fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> {
formatter.as_mut().write_all(self)
}
}

impl Template for ConfigValue {
fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> {
write!(formatter, "{self}")
Expand Down
2 changes: 1 addition & 1 deletion cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ Annotates a revision line by line. Each line includes the source change that int
###### **Options:**

* `-r`, `--revision <REVSET>` — an optional revision to start at
* `-T`, `--template <TEMPLATE>` — Render a prefix for each line using the given template
* `-T`, `--template <TEMPLATE>` — Render each line using the given template

All 0-argument methods of the [`AnnotationLine` type] are available as keywords in the [template expression].

Expand Down
2 changes: 1 addition & 1 deletion cli/tests/test_file_annotate_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ fn test_annotate_with_template() {
commit_timestamp(commit).local().format('%Y-%m-%d %H:%M:%S')
++ " "
++ commit.author(),
) ++ "\n") ++ pad_start(4, line_number) ++ ": "
) ++ "\n") ++ pad_start(4, line_number) ++ ": " ++ content
"#};

let stdout = test_env.jj_cmd_success(
Expand Down
1 change: 1 addition & 0 deletions docs/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ The following functions are defined.
The following methods are defined.

* `.commit() -> Commit`: Commit responsible for changing the relevant line.
* `.content() -> Template`: Line content including newline character.
* `.line_number() -> Integer`: 1-based line number.
* `.first_line_in_hunk() -> Boolean`: False when the directly preceding line
references the same commit.
Expand Down

0 comments on commit 4ec22dd

Please sign in to comment.