Commit Graph

105 Commits

Author SHA1 Message Date
Josh Steadmon
d7fa04f510 templater: add parents() method for Operation
Add a parents() method for `Operation` template objects, copied from the
implementation for `Commit`s.

The test case added in test_operations.rs was heavily inspired by
test_commit_templates.rs:test_log_parents().

Fixes #6979
2025-07-18 17:16:09 +00:00
Alexander Kobjolke
d858d8cb41 docs: document Commit.signature() 2025-07-08 00:47:52 +00:00
Pavan Kumar Sunkara
c038ef4bc3 workspaces: Add templating support to workspace list 2025-07-07 19:14:07 +00:00
Yuya Nishihara
49fc8abe69 docs: document the purpose of Stringify template type 2025-07-01 00:30:22 +00:00
Yuya Nishihara
e3b6599424 templater: rename PlainText pseudo type to Stringify
Since the goal of this pseudo type is to get a String value, it can be called a
ToString or Stringify. I chose the latter because Stringify sounds similar to
Serialize (verb), and I don't want to rename the internal functions to
.try_into_to_string().

https://github.com/jj-vcs/jj/pull/6840#discussion_r2173076763
2025-07-01 00:30:22 +00:00
Yuya Nishihara
4d3fa2b5d4 docs: show which template types support implicit conversions 2025-06-28 00:40:14 +00:00
Yuya Nishihara
a561fab59c templater: add PlainText/Serialize pseudo types for documentation purpose 2025-06-28 00:40:14 +00:00
Yuya Nishihara
0a60e85525 templater: add json() function
This was discussed in #3219 and #3262, and apparently, people don't agree
whether we should implement machine-readable formatting by using templater.
However, there are recurring requests about JSON output, and "jj api" is still
vaporware. So I think it's good to add some support for JSON output.

I'm not going to add syntax to build custom JSON object/list for now. Instead,
property types such as Commit will implement fixed serialization output. The
user might have to write ad-hoc JSON constructs to concatenate the default JSON
output and their custom JSON fields.

We'll need a documentation about which types are serializable. I think this can
be added later when more types get serialization support.
2025-06-18 18:34:37 +00:00
Yuya Nishihara
1e4c636a02 docs: add section about naming convention of template labels 2025-05-19 01:41:15 +00:00
T6
13c6257aac templater: add arithmetic operators 2025-05-16 12:45:09 +00:00
Yuya Nishihara
a9bae8bc91 templater: deprecate CommitId::normal_hex()
If CommitId and ChangeId were separate types in templates, we wouldn't add
CommitId::normal_hex().
2025-05-16 11:12:33 +00:00
Yuya Nishihara
2d79c6431d templater: introduce newtype to format ref/remote name in revset syntax
This is the last part of the series 02722eae54 "view: port bookmark/tag name
types to RefName/RemoteName." Templater doesn't use these name types internally
because we wouldn't gain much type safety in template language.

The return type of .remote() is changed to Option<RefSymbol>. An empty symbol is
rendered with quotes, so it would be weird if local_bookmark.remote() returned
an empty RefSymbol.
2025-05-13 23:54:47 +00:00
Yuya Nishihara
cb877a94c1 templater: allow comparison between optional and non-optional values
I'm going to add RefSymbol(String) type to format bookmark/remote name in revset
syntax. Since an empty symbol will be rendered differently from an empty string,
bookmark.remote() -> String will be changed to -> Option<RefSymbol>. Then, we'll
need to add support for comparison between optional and non-optional values.

In template language, method call on None produces an error. If we followed this
rule, comparison would have to be expressed as `opt && opt == lit`. I feel this
would be too verbose, and wouldn't help eliminate user error caused by
unintended comparison between Option<T> and T anyway. So this patch implements
comparison by lifting T to Option<T> implicitly.
2025-05-13 00:18:02 +00:00
Vincent Ging Ho Yim
8c4840135f docs/templates: surround type names with backticks in section headings
In particular, this fixes the section heading for the `List<Trailer>` type. Before this
commit, that heading was rendered incorrectly as 'List type'.
2025-05-11 13:14:36 +00:00
Gaëtan Lehmann
2c4a0328f9 templates: add self.trailers().contains_key(key)
as a simpler and more readable alternative to

    self.trailers().filter(|t| t.key() == "Change-Id")
2025-04-29 06:36:12 +00:00
Mateus Auler
968806bc64 templates: implement Commit.trailers() 2025-04-27 18:29:25 +00:00
Nicole Patricia Mazzuca
02687ac7e5 docs: standardize on .method() syntax
In docs/templates.md, the Commit type and Operation type looked like:

`method() -> ReturnType`

rather than everything else, which looks like:

`.method() -> ReturnType`

This commit changes the Commit and Operation types to look more like the
rest of the documentation.
2025-04-04 13:58:33 +00:00
Yuya Nishihara
896424db76 templater: rename RefName type to CommitRef
I'm thinking of adding RefName(str) and RemoteName(str) newtypes, and the
templater type name would conflict with that. Since the templater RefName type
is basically a (name, target) pair, I think it should be called a "Ref", and I
added "Commit" prefix for disambiguation.

This isn't a breaking change since template type names only appear in docs and
error messages.
2025-03-14 14:58:29 +00:00
George Christou
e1abaca21c templater: add trim methods to String type 2025-02-21 21:23:11 +00:00
Andrew Gilbert
5dac0ef4d1 docs templates: add link to templates toml file 2025-02-17 21:02:23 +00:00
Yuya Nishihara
4ec22dde38 templater: port annotation line content to template
I originally thought we would have to add BString template type first, but we
can use opaque Template type instead.
2025-02-15 11:07:17 +00:00
Bryce Berger
3bc111e60e annotate: make AnnotationLine template type
Allows:
* self.commit()
* self.line_number()
* self.first_line_in_hunk()

Certain pagers (like `delta`), when used for `git blame`, only show the
commit information for the first line in a hunk. This would be a nice
addition to `jj file annotate`.

`jj file annotate` already uses a template to control the rendering of
commit information --- `templates.annotate_commit_summary`. Instead of
a custom CLI flag, the tools necessary to do this should be available in
the template language.

If `1 % 2` or `1.is_even()` was available in the template language, this
would also allow alternating colors (using `raw_escape_sequence`).

Example:

```toml
[templates]
# only show commit info for the first line of each hunk
annotate_commit_summary = '''
if(first_line_in_hunk,
  show_commit_info(commit),
  pad_end(20, " "),
)
'''
```
2025-02-15 02:34:38 +00:00
Yuya Nishihara
0d2becbac3 templater: add stringify(x) function to call string methods on template
It's also useful to remove color labels from the inner template.
2025-02-14 00:54:03 +00:00
Yuya Nishihara
78f08d9e6c docs: use single-quoted template string in JSON example
It's easier to parse than \".
2025-02-14 00:54:03 +00:00
hkalbasi
272955f4fe templater: add .escape_json method to string 2025-02-12 22:17:30 +00:00
Josh Steadmon
975e1e1e24 templater: add optional ellipsis arg to truncate template functions
If an ellipsis arg is given to the truncate_* template functions, append (or
prepend) the ellipsis when the template content is truncated to fit the maximum
width.

Fixes #5085.
2025-02-06 11:34:33 -08:00
Yuya Nishihara
891fe085a6 templater: add DiffStats type to provide raw stats values
I originally considered adding `stats() -> DiffStats` which returns an
unprintable object, with deprecation of `.stat(width)` in favor of
`.stats().<method_to_render>(width)`. However, I couldn't find a good name for
the rendering function. This patch instead made the width parameter optional. I
think that's good because template language doesn't have to be overly strict.

Closes #4154
2025-02-05 00:31:16 +00:00
Josh Steadmon
227eccefdb templater: add pad_centered template function
Add a new pad_center function that centers content within a minimum
width. If an odd number of fill characters is required, the trailing
fill will be one character longer than the leading fill.

Fixes #5066.
2025-02-04 18:16:20 +00:00
Jonathan Frere
11fbbf6ad4 docs: fix typo in templating language example 2025-01-28 17:42:12 +00:00
Yuya Nishihara
fe54c6276e templater: add diff.files() method
This can be used in order to count the number of added files by
diff.files().filter(..).len(), for example. If we add more advanced fileset
predicates, it can also be expressed as diff("added()").files().len(). The
latter would be cheaper to compute.

For #4154, I'll probably add DiffStats template type. It might be doable by
extending diff.files() method, but I don't think it's good idea to write stats
calculation logic in template language.

Closes #5272
2025-01-26 01:54:33 +00:00
Yuya Nishihara
b22347e80b templater: add TreeDiffEntry types
Tests will be added later.
2025-01-26 01:54:33 +00:00
Yuya Nishihara
362be5914f templater: add list.filter(predicate) method
If we add generic diff template, we'll probably want to filter diff entries by
status, etc.

Closes #5291
2025-01-24 03:42:39 +00:00
Yuya Nishihara
7db343ec32 templater: add TreeEntry type
I'm going to add "file list" template, and I think it's better to provide a file
path as "path", not "self". This patch also adds some tree value properties
which seemed useful.

Tests will be added later.
2025-01-23 02:21:15 +00:00
Yuya Nishihara
5062ae83d3 templater: add RepoPath types
This will be used in "file list" template. Option<RepoPath> type isn't
needed for that, but I think it'll appear somewhere in custom diff template.
The path.parent() method is added mainly for testing Option<RepoPath>.

Tests will be added later.
2025-01-23 02:21:15 +00:00
Ilya Grigoriev
ac1be9374b docs templates: document the Email type methods in more detail 2025-01-15 05:07:53 +00:00
Yuya Nishihara
98724278c5 templater: add config(name) function
This could be used in order to switch template outputs conditionally, or to
get the default push remote for example.
2025-01-11 01:40:23 +00:00
Yuya Nishihara
83d237a32c templater: introduce ConfigValue type, port "config list" value to it
I'm going to add config(name) accessor, which returns ConfigValue.
2025-01-11 01:40:23 +00:00
Anton Bulakh
c99c97c646 sign: Add templater methods to show signature info
Disclaimer: this is the work of @necauqua and @julienvincent (see
#3141). I simply materialized the changes by rebasing them on latest
`main` and making the necessary adjustments to pass CI.

---

I had to fix an issue in `TestSignatureBackend::sign()`.

The following test was failing:
```
---- test_signature_templates::test_signature_templates stdout ----
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Snapshot Summary ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Snapshot: signature_templates
Source: cli/tests/test_signature_templates.rs:28
────────────────────────────────────────────────────────────────────────────────
Expression: stdout
────────────────────────────────────────────────────────────────────────────────
-old snapshot
+new results
────────────┬───────────────────────────────────────────────────────────────────
    0     0 │ @  Commit ID: 05ac066d05701071af20e77506a0f2195194cbc9
    1     1 │ │  Change ID: qpvuntsmwlqtpsluzzsnyyzlmlwvmlnu
    2     2 │ │  Author: Test User <test.user@example.com> (2001-02-03 08:05:07)
    3     3 │ │  Committer: Test User <test.user@example.com> (2001-02-03 08:05:07)
    4       │-│  Signature: Good test signature
          4 │+│  Signature: Bad test signature
    5     5 │ │
    6     6 │ │      (no description set)
    7     7 │ │
    8     8 │ ◆  Commit ID: 0000000000000000000000000000000000000000
────────────┴───────────────────────────────────────────────────────────────────
```

Print debugging revealed that the signature was bad, because of a
missing trailing `\n` in `TestSignatureBackend::sign()`.

```diff
diff --git a/lib/src/test_signing_backend.rs b/lib/src/test_signing_backend.rs
index d47fef1086..0ba249e358 100644
--- a/lib/src/test_signing_backend.rs
+++ b/lib/src/test_signing_backend.rs
@@ -59,6 +59,8 @@
         let key = (!key.is_empty()).then_some(std::str::from_utf8(key).unwrap().to_owned());

         let sig = self.sign(data, key.as_deref())?;
+        dbg!(&std::str::from_utf8(&signature).unwrap());
+        dbg!(&std::str::from_utf8(&sig).unwrap());
         if sig == signature {
             Ok(Verification::new(
                 SigStatus::Good,
```

```
[lib/src/test_signing_backend.rs:62:9] &std::str::from_utf8(&signature).unwrap() = \"--- JJ-TEST-SIGNATURE ---\\nKEY: \\n5300977ff3ecda4555bd86d383b070afac7b7459c07f762af918943975394a8261d244629e430c8554258904f16dd9c18d737f8969f2e7d849246db0d93cc004\\n\"
[lib/src/test_signing_backend.rs:63:9] &std::str::from_utf8(&sig).unwrap() = \"--- JJ-TEST-SIGNATURE ---\\nKEY: \\n5300977ff3ecda4555bd86d383b070afac7b7459c07f762af918943975394a8261d244629e430c8554258904f16dd9c18d737f8969f2e7d849246db0d93cc004\"
```

Thankfully, @yuja pointed out that libgit2 appends a trailing newline
(see bfb7613d5d).

Co-authored-by: necauqua <him@necauq.ua>
Co-authored-by: julienvincent <m@julienvincent.io>
2025-01-04 13:24:08 +01:00
Benjamin Tan
dc16830151 templater: add Email template type, deprecate Signature.username()
The `Signature.email()` method is also updated to return the new Email
type. The `Signature.username()` method is deprecated for
`Signature.email().local()`.
2024-12-15 16:03:34 +08:00
Yuya Nishihara
53b8eeb5ab templater: rename "logical" eq/ne operators
They are the equality operators. There aren't logical, bitwise, arithmetic
thingy.
2024-12-12 22:48:45 +09:00
Benjamin Tan
da5b790f7a templater: add relational operators (>=, >, <=, <)
Closes #5062.
2024-12-12 19:56:29 +08:00
Yuya Nishihara
6739dccc6d templater: add != operator as user would probably expect that it exists 2024-11-10 21:41:24 +09:00
Martin von Zweigbergk
86de9139b3 docs: fix a few typos noticed by automation at Google 2024-11-07 23:04:11 -08:00
Benjamin Tan
1372b39341 template: add support for logical equality operator 2024-11-08 01:55:18 +08:00
Yuya Nishihara
5dd6185fbc templater: make "git_head" return boolean, render it as "git_head()"
For the same reason as the root revision is indicated by "root()".
2024-10-21 09:21:34 +09:00
Yuya Nishihara
009284736d templater: add pad/truncate functions
As I said in the preceding patch, I settled on separate pad/truncate functions
instead of a function taking multiple optional parameters. It's less efficient
to process truncation and padding independently, but I don't think that would
matter.

The order of arguments follows the current f(..., content) convention. We can
also add a method syntax, but I'm not sure if it's useful. In order to call a
method of Template type, we'll need to coerce printable object to Template:

  concat(author.email()).truncate_end(10).pad_end(10)
  ^^^^^^
  String -> Template

FWIW, String type could provide more efficient truncate/pad methods.

Closes #3183
2024-10-21 08:47:08 +09:00
Benjamin Tan
0f605b8aae templates: Timestamp: add after, before methods
This allows for more fine-grained control of timestamp formatting, for
example:

```
[template-aliases]
'format_timestamp(timestamp)' = '''
if(timestamp.before("1 week ago"),
  timestamp.format("%b %d %Y %H:%M"),
  timestamp.ago()
)
'''
```

Closes #3782.
2024-10-16 13:46:06 +08:00
Vamsi Avula
92103f4db2 formatters: implement raw() for FormatRecorder
This adds `raw_escape_sequence(...)` support for things that use
FormatRecorder like wrapped text / `fill(...)` / `indent(...)`.

Change-Id: Id00000004248b10feb2acd54d90115b783fac0ff
2024-10-13 12:02:40 +05:30
Vamsi Avula
fb93394610 templates: add raw_escape_sequence
Templates can be formatted (using labels) and are usually sanitized
(unless for plain text output).
`raw_escape_sequence(content)` bypasses both.

```toml
	'hyperlink(url, text)' = '''
		raw_escape_sequence("\e]8;;" ++ url ++ "\e\\") ++
		text ++
		raw_escape_sequence("\e]8;;\e\\")
	'''
```

In this example, `raw_escape_sequence` not only outputs the intended
escape codes, it also strips away any escape codes that might otherwise
be part of the `url` (from any labels attached to the `url` content).

Not all formatters (namely FormatRecorder) are supported yet.

Change-Id: Id00000004492dbf39e50f3b7090706839d1d8d45
2024-10-13 12:02:40 +05:30
Vamsi Avula
a6aa25c9eb templates: support hex bytes in string literals
One particular use case for these is escape sequences -- and to that
end, I'm also adding `\e` as a shorthand for `\x1b`.

Change-Id: Id000000040ea6fd8e2d720219931485960c570dd
2024-10-13 12:02:40 +05:30