Commit graph

164 commits

Author SHA1 Message Date
Yuya Nishihara
81c8543621 cli: switch "debug template" command to new AST
This should be more readable than raw pest tree.
2023-02-13 02:11:19 +09:00
Yuya Nishihara
677ac54855 templater: build evaluatable expression from AST nodes 2023-02-13 02:11:19 +09:00
Yuya Nishihara
9dc68af4f9 templater: introduce AST structs
This prepares for template aliases support #1190. Unlike revset, template
expressions can be of various types, whereas alias substitution will process
untyped nodes. That's one reason that ExpressionNode is closer to parsed tree
than evaluatable Property structs. Another reason is that it's uneasy to split
name/type checking into "parsing" and "building property function" stages.

We could do alias expansion at once while building Property functions, but
that would make testing harder because Property isn't Debug + PartialEq.
2023-02-13 02:11:19 +09:00
Yuya Nishihara
7c6ddf9773 templater: duplicate parsing functions for reference
I'm going to split 'parse() -> Expression' functions into 'parse() -> AST'
and 'build(AST) -> Expression'. The duplicated functions will be baseline of
new 'parse() -> AST' functions.
2023-02-13 02:11:19 +09:00
Vamsi Avula
aacdcf629b author/committer templates: add a username method
I haven't used a proper email address parser as I'm not really sure if it's
worth the extra dependency and effort -- thoughts?
2023-02-11 15:38:27 +05:30
Yuya Nishihara
686c1fb522 templater: allow trailing comma
While rewriting the default log template, I find it's annoying that I have
to remove "," from the last line.
2023-02-07 23:19:36 +09:00
Yuya Nishihara
cd164be762 templater: inline extract_entire_prefix_and_trimmed_tail() and simplify 2023-02-07 11:42:39 +09:00
Yuya Nishihara
ebf9887d65 templater: migrate shortest_prefix_and_brackets() over shortest() 2023-02-07 11:42:39 +09:00
Yuya Nishihara
3ccac9cda5 templater: rename shortest_styled_prefix() to shortest()
Now it is the true "shortest prefix" function with the default parameter,
so let's simply call it "shortest()".
2023-02-07 11:42:39 +09:00
Ilya Grigoriev
de163216c0 Templater: make shortest id functions default to 0 length
This makes them print the shortest unique prefix only.
2023-02-05 22:15:27 -08:00
Ilya Grigoriev
b87facff7a Templater: Give short id function a total_len argument
This will be tested in the next commit.
2023-02-05 21:18:42 -08:00
Ilya Grigoriev
58828803d4 Templater: Give shortest id functions a total_len argument. 2023-02-05 21:18:42 -08:00
Yuya Nishihara
5bfecf112a templater: add parsing rule for integer literal, add i64 property
This will be used as a parameter of id.shortest*() methods. For now, only
decimal literal is supported, and there's no unary negate operator.
"0"-prefix is disallowed because it looks like an octal number.

I don't think we would want multiple integer types in the template language,
so I chose i64 as the integer type of reasonable width.
2023-02-05 17:21:54 +09:00
Yuya Nishihara
fe8c41bbd7 templater: extract primary rule, inline maybe_method instead 2023-02-05 17:21:54 +09:00
Yuya Nishihara
e4fbb1fe83 templater: extract "function" parsing to function
It's getting bigger.
2023-02-05 17:21:54 +09:00
Yuya Nishihara
9a5a88238b templater: fix handling of method chaining of parenthesized expression 2023-02-05 17:21:54 +09:00
Yuya Nishihara
16a744fe18 templater: make internal parse_template_str() return expression
An "Expression" object is more useful while writing tests.
2023-02-05 17:21:54 +09:00
Yuya Nishihara
5342d2cfb7 templater: implement string.contains() method as example 2023-02-05 11:53:11 +09:00
Yuya Nishihara
a4be118981 templater: check number of method arguments 2023-02-05 11:53:11 +09:00
Yuya Nishihara
28c1989257 templater: add helper to extract argument pairs 2023-02-05 11:53:11 +09:00
Yuya Nishihara
945f9c1552 templater: pass parse_keyword() down to method parsing functions
It's needed to parse argument expressions.
2023-02-05 11:53:11 +09:00
Yuya Nishihara
db172aa7c9 templater: process property composition by parse_<type>_method()
This prepares for adding method arguments support. Since a method argument
should be evaluated in the surrounding scope, its type will be
'TemplateProperty<I>', not 'TemplateProperty<J>' for the receiver type 'J'.
Then, the receiver of type 'TemplateProperty<I, Output = J>', and arguments
of type 'TemplateProperty<I, Output = Pn>' will be composed to an input of
type 'TemplateProperty<I, Output = (J, Pn...)>'.

wrap_fn() is removed since it's only useful for nullary methods, and we
no longer need Box<dyn> to abstract the return value.
2023-02-05 11:53:11 +09:00
Yuya Nishihara
bdf809c6c3 templater: do not turn method arguments into iterator by caller
parse_<type>_method() will need args_pair.as_span() to report invalid
argument error.
2023-02-05 11:53:11 +09:00
Yuya Nishihara
5072469eca templater: extract generic parsing functions
We'll probably need a better abstraction, but a parameterized keyword
function is a good first step. This unblocks the use of parse_term() for
context-less properties (or literals). I'm going to add a proper support
for context-aware method arguments, but literals can be parsed without it.

parse_keyword() closure is passed by reference to avoid infinite expansion.
2023-02-05 11:53:11 +09:00
Yuya Nishihara
1b78fb5b5d templater: add shorthand for Result<T, TemplateParseError>
This will appear in "impl Fn(..) -> .." and we can't alias it.
2023-02-05 11:53:11 +09:00
Yuya Nishihara
13b5661094 templater: add separate(sep, contents...) function
This is a copy of Mercurial's separate() function.
2023-02-04 15:19:02 +09:00
Yuya Nishihara
5850575d53 templater: add separate variants for exact/range argument count errors
I believe this isn't a good abstraction, but I need to add one more variant
for "at least n arguments" error. A stringified count like "2 to 3" could be
embedded in an error variant, but I don't think it's good idea to build error
message in that way.
2023-02-04 15:19:02 +09:00
Yuya Nishihara
e2eda9f72f templater: inline "current_working_copy" keyword
Maybe I didn't make this change before because the closure needs to capture
WorkspaceId by value. Since the inlined version looks pretty simple, let's
go forward to do that.
2023-02-04 01:58:13 +09:00
Yuya Nishihara
45a018ec6b templater: report invalid argument count as error
We'll probably need a helper to extract N..M arguments, but let's revisit
it later.
2023-02-03 12:06:04 +09:00
Yuya Nishihara
baf911459f templater: report invalid argument type as error 2023-02-03 12:06:04 +09:00
Yuya Nishihara
4eff802d87 templater: report keyword/function/method name error 2023-02-03 12:06:04 +09:00
Yuya Nishihara
8653cc885a templater: wrap inner parsing functions with Result<T> 2023-02-03 12:06:04 +09:00
Yuya Nishihara
7090fa0374 templater: report syntax error, don't panic()
Even though the template syntax is experimental, panicking parser makes
it difficult to write tests. So let's add minimal error handling. The error
types are basically copied from the revset module.

I made write_commit_summary() fall back to the default template if user
template had syntax error. It should be better than reporting parse error
after e.g. "jj abandon" finished successfully.
2023-02-03 12:06:04 +09:00
Yuya Nishihara
d6592573d0 templater: abstract Dynamic/LabelTemplate over labels type, unify them 2023-02-02 01:12:23 +09:00
Yuya Nishihara
1911734acc templater: add wrapper that turns template back to string property
I have no idea whether or not any template expressions are intentionally
allowed as a label, but it makes sense to write something like
'label("phase-" phase, ...)' (if we had a phase keyword.) So I decided to
add .into_plain_text() instead of stricter .try_into_string().
2023-02-02 01:12:23 +09:00
Yuya Nishihara
6da43734cb templater: migrate trivial commit keywords to closure wrapper
Perhaps, non-trivial keywords can be extracted to free functions, and both
parsing and property functions can be eventually moved to a commit templater
module?
2023-02-01 17:54:35 +09:00
Yuya Nishihara
e4cb1afd61 templater: fix crash on "".first_line() 2023-02-01 16:13:43 +09:00
Yuya Nishihara
259314b442 templater: reuse parse_commit_term() to coerce if() condition to bool
This should fix some inconsistent parsing of condition term.
2023-02-01 10:25:28 +09:00
Yuya Nishihara
553bee6ac4 templater: extract method that coerces property to boolean 2023-02-01 10:25:28 +09:00
Yuya Nishihara
5eee7186ba 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.
2023-02-01 10:25:28 +09:00
Yuya Nishihara
8d7ba8ddd3 templater: extract PropertyAndLabels::into_template() 2023-02-01 10:25:28 +09:00
Yuya Nishihara
41afdd48c7 templater: reorder declaration of PropertyAndLabels struct 2023-02-01 10:25:28 +09:00
Yuya Nishihara
f1e6146d6d templater: add newtype to implement property over closure
Many template keywords and methods are one liners, and I think that's actually
good because writing tests for templater would be more involved than for pure
functions.

This patch introduces a wrapper for such one-line functions, and migrates
method parser to that. Some of the commit keyword structs can also be ported
to this wrapper.
2023-01-31 16:27:52 +09:00
Ilya Grigoriev
26cc290157 Templater: Create shortest_styled_prefix function for ids 2023-01-30 22:48:38 -08:00
Ilya Grigoriev
3ee87aa5a7 Rename short => shortest 2023-01-30 22:48:38 -08:00
Martin von Zweigbergk
6cf7d98465 templater: replace is_git_head keyword by git_head keyword
I'm about to make it possible for `HEAD@git` to be conflicted. For
that, we need to be able to include the trailing `?`. This patch
prepares for that.
2023-01-30 09:05:03 -08:00
Yuya Nishihara
3d965f22ab templater: disallow empty template in function arguments and parens
Before, "f()" was parsed as a function call with one empty argument. In
practice, this change means "if(divergent,,false_template)" is no longer
valid.
2023-01-30 12:50:40 +09:00
Yuya Nishihara
a5bb48d47e templater: introduce top-level rule that wraps template terms
An epsilon rule will be moved here to disambiguate f() with f("").
2023-01-30 12:50:40 +09:00
Yuya Nishihara
c44dda55e3 templater: extract function arguments to inner node
This should help to represent an empty argument properly.
2023-01-30 12:50:40 +09:00
Yuya Nishihara
62def97f58 templater: remove redundant boxing of single template term
It was a copy-paste error.
2023-01-30 12:50:40 +09:00
Yuya Nishihara
a3d3947499 templater: move epsilon rule out of term rule
Suppose "template" is a sequence of "term"s, it makes more sense to handle
an empty sequence there. It might be even better to disallow empty template
other than the top-level one.
2023-01-29 08:54:14 +09:00
Yuya Nishihara
d1281ef48e templater: ensure "template" node is passed to parse_commit_template_rule()
Assertion will be added by the next commit.
2023-01-29 08:54:14 +09:00
Yuya Nishihara
bf66beab36 templater: fix parsing of parenthesized expression
A "list" is a sequence of more than one "term" nodes, so it shouldn't contain
a single parenthesized node.

Also, a parenthesized "term" rule wasn't handled.
2023-01-29 08:54:14 +09:00
Yuya Nishihara
f7993f0fe9 templater: eliminate whitespace nodes from parse tree 2023-01-29 08:54:14 +09:00
Yuya Nishihara
29eb7a16b8 templater: process method chaining from left to right
A method call is typically left associative, and LTR processing is simpler.
2023-01-28 10:53:03 +09:00
Yuya Nishihara
2ae892efab templater: reuse function rule to represent a method chain
A method call is typically parsed as (obj.meth)(), not as obj.(meth()),
but the latter is good enough for our needs. It's unlikely we'll add a
first-class function support.

.into_inner().next().unwrap() mess will be cleaned up by the next commit.
2023-01-28 10:53:03 +09:00
Yuya Nishihara
2c4856c47b templater: remove Box<dyn> from generic wrappers, parameterize type
This basically removes 'a lifetime from these wrappers, and add trait bounds
instead. I have no idea which version would look less scary, but let's see.

I also added trait bounds to constructor functions. They aren't strictly
required, but help type inference of closure (and will probably improve
an error message.)
2023-01-26 23:42:13 +09:00
Yuya Nishihara
8163b87a54 templater: store repo in CommitOrChangeId struct
This one was the outlier, and I think propagating 'repo' by context variable
is more correct.
2023-01-24 01:46:41 +09:00
Yuya Nishihara
e15b35ba56 templater: remove unused repo from CommitOrChangeIdShort 2023-01-24 01:46:41 +09:00
Yuya Nishihara
f47552b744 templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.

    impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
    where
        P: TemplateProperty<C, O>, // 'O' isn't constrained by type
        O: Template<()>,

According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.

https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

With this change, I can express the type constraint as follows:

    impl<C, P> Template<C> for FormattablePropertyTemplate<P>
    where
        P: TemplateProperty<C>,
        P::Output: Template<()>,
2023-01-24 01:46:41 +09:00
Yuya Nishihara
4e661ecd40 templater: format context-less property value instead of coercing to string
This unblocks labeled outputs for these value types.
2023-01-23 15:23:26 +09:00
Yuya Nishihara
431395a7ee templater: generalize Literal/Constant wrapper for any context-less template
Now we have 'impl Template<()> for String', 'LiteralTemplate(String)' is
a bit redundant. Let's generalize it for any 'Template<()>'. I noticed
'ConstantTemplateProperty' serves as a similar role, so unified these.
2023-01-23 15:23:26 +09:00
Yuya Nishihara
c1f0ca9b5a templater: rewrite Property match arms with generic function
We might want to go further by rewriting the Property enum with trait, but
let's start small.
2023-01-23 15:23:26 +09:00
Yuya Nishihara
1a6e71170e templater: remove string.short() method
I think this is a remainder of 68ad712e12 "Templater: Combine Change and
Commit id templates." It doesn't make sense that description.short() prints
the first 12 characters.
2023-01-23 00:29:55 +09:00
Ilya Grigoriev
1bcdcea3ef Fix typo in function name 2023-01-20 22:05:33 -08:00
Yuya Nishihara
38e6924482 templater: move CommitOrChangeIdKeyword functions to CommitOrChangeId
CommitOrChangeIdKeyword is no longer needed.
2023-01-19 16:41:50 +09:00
Yuya Nishihara
bf58051c55 templater: split tag structs for commit_id/change_id property
These structs are basically functions taking &Commit, so there's no point
to abstract them.
2023-01-19 16:41:50 +09:00
Ilya Grigoriev
19d341d32a Templater: naive implementation of shortest prefix highlight for ids
This creates a templater function `short_underscore_prefix` for commit and
change ids. It is similar to `short` function, but shows one fewer hexadecimal
digit and inserts an underscore after the shortest unique prefix.

Highlighting with an underline and perhaps color/bold will be in a follow-up
PR.

The implementation is quadratic, a simple comparison of each id with every
other id. It is replaced in a subsequent commit. The problem with it is that,
while it works fine for a `jj`-sized repo, it becomes is painfully slow with a
repo the size of git/git. 

Still, this naive implemenation is included here since it's simple, and could
be used as a reference implementation. 

The `shortest_unique_prefix_length` function goes into `repo.rs` since that's
convenient for follow-up commits in this PR to have nicer diffs.
2023-01-17 22:01:09 -08:00
Ilya Grigoriev
10794461b9 Templater: Pass Repo to CommitOrChageIdShortest template objects
It will be necessary to compute the shorter unique prefix.
2023-01-17 22:01:09 -08:00
Ilya Grigoriev
dae42ea34a Templater: change some names from "shortest" to "short"
This matches the templater function name
2023-01-17 22:01:09 -08:00
Ilya Grigoriev
68ad712e12 Templater: Combine Change and Commit id templates
They will both need the unique prefix functionality.

Change ids previously were just strings.
2023-01-17 22:01:09 -08:00
Ilya Grigoriev
1f6c085c4e Move the definition of Property to before its use 2023-01-17 22:01:09 -08:00
Samuel Tardieu
efceccb17d refactor: separate timestamp related utilities in time_util module 2023-01-14 16:07:09 +01:00
Samuel Tardieu
f563e550c4 template: add "empty" template item 2023-01-14 16:00:42 +01:00
Martin von Zweigbergk
ff94725361 templater: auto-label template method calls 2023-01-08 23:01:53 -08:00
Martin von Zweigbergk
0b9ab871b2 templater: create a type for property+labels
I'm going to make `parse_method_chain` also return a list of labels to
add, so we can make e.g. `author.timestamp()` automatically get
labeled with both "author" and "timestamp".
2023-01-08 23:01:53 -08:00
Martin von Zweigbergk
4953467e44 templater: expect a list of labels instead of splitting on whitespace
It's clearly the parser's job to split labels in a string provided by
the user. This patch moves the splitting we were doing in
`LabelTemplate` and `DynamicLabelTemplate` to the parser. In the
former case, the string isn't even provided by the user and it doesn't
contain whitespace, we can drop the splitting altogether.
2023-01-08 23:01:53 -08:00
Ilya Grigoriev
e32342a6c4 jj op log: Show durations with relative timestamps
Before, the humanized versions of start and end times often were identical.
2023-01-07 12:08:00 -08:00
Ilya Grigoriev
c5563115a4 Consolidate and extract timestamp display functions in one file
The functionality for absolute timestamps was duplicated. A
function for displaying relative timestamps will be needed in
the next commit.
2023-01-07 12:08:00 -08:00
Martin von Zweigbergk
7f9a0a2820 cleanup: let new Clippy move variables into format strings
I ran an upgraded Clippy on the codebase. All the changes seem to be
about using variables directly in format strings instead of passing
them as separate arguments.
2022-12-14 21:30:58 -08:00
Martin von Zweigbergk
d8feed9be4 copyright: change from "Google LLC" to "The Jujutsu Authors"
Let's acknowledge everyone's contributions by replacing "Google LLC"
in the copyright header by "The Jujutsu Authors". If I understand
correctly, it won't have any legal effect, but maybe it still helps
reduce concerns from contributors (though I haven't heard any
concerns).

Google employees can read about Google's policy at
go/releasing/contributions#copyright.
2022-11-28 06:05:45 -10:00
Ruben Slabbert
01817e4321 feature: support relative timestamps as a config option 2022-11-27 08:35:17 +10:00
Martin von Zweigbergk
2cf99d1e35 cargo: upgrade chrono to version 0.4.23 2022-11-14 13:18:36 -08:00
Martin von Zweigbergk
2ae2010007 cleanup: replace an assert! by assert_eq!
As pointed out by IntelliJ.
2022-11-13 20:24:24 -08:00
Martin von Zweigbergk
4ec2092e57 templates: allow using string in if-condition; use in default template
Given how easy this was, I can't believe I didn't make the change
sooner.

I haven't updated the screenshots in the readme because I plan to make
some further changes to the default template. I'll update them after
those changes.
2022-11-13 20:24:24 -08:00
Martin von Zweigbergk
1d97f39da1 cleanup: avoid an unnecessary Box for argument to formatter
I think this cleanup was enabled by a recent refactoring that replaced
a trait object by a type parameter (3392e83486).
2022-11-05 22:49:54 -07:00
Martin von Zweigbergk
91ee32b183 templater: drop support for open template keyword 2022-11-05 06:14:37 -07:00
Martin von Zweigbergk
3b3f6129e6 backend: allow negative timestamps in commits and operations
I was reading a draft of "Git Rev News: Edition 91" [1] where Peff
mentions some unfinished patches to allow negative timestamps in
Git. So I figured I should add support for that before I forget. I
haven't checked if libgit2 supports it, so it might be that our Git
backend still doesn't support it after this patch.

 [1] https://github.com/git/git.github.io/blob/master/rev_news/drafts/edition-91.md
2022-09-30 00:50:17 -07:00
Martin von Zweigbergk
b654a1fe84 cleanup: remove extern crate declarations
`extern crate` is no longer needed since edition 2018.
2022-09-21 22:24:09 -07:00
Martin von Zweigbergk
6812bd9584 cleanup: rename checkout to wc_commit
`wc_commit` seems clearer than `checkout` and not too much longer. I
considered `working_copy` but it was less clear (could be the path to
the working copy, or an instance of `WorkingCopy`). I also considered
`working_copy_commit`, but that seems a bit too long.
2022-09-18 16:19:58 -07:00
Martin von Zweigbergk
c36b720dd4 cli: rename checkout to working_copy in template 2022-09-18 16:19:58 -07:00
Martin von Zweigbergk
bcece02084 cli: indicate each workspace's checkout in log (#13)
It seems helpful to show in the log output which commit is checked out
in which workspace, so let's try that. I made it only show the
information if there are multiple checkouts for now.
2022-02-02 21:36:14 -08:00
Martin von Zweigbergk
92af544de0 templater: make current_checkout be about the current workspace (#13)
We don't use the `current_checkout` keyword in out default templates,
but let's still fix it, so it refers to the current workspace.
2022-02-02 10:33:10 -08:00
Martin von Zweigbergk
c678a89794 cleanup: fix some issues reported by new clippy and/or rustc 2021-12-10 14:12:45 -08:00
Martin von Zweigbergk
626fbee0dd cli: show Git HEAD in log output
It's useful to know which commit is checked out in the underlying Git
repo (if there is one), so let's show that. This patch indicates that
commit with `HEAD@git` in the log output. It's probably not very
useful when the Git repo is "internal" (i.e. stored inside `.jj/`),
because then it's unlikely to change often. I therefore considered not
showing it when the Git repo is internal. However, it turned out that
`HEAD` points to a non-existent branch in the repo I use, so it won't
get imported anyway (by the function added in the previous patch). We
can always review this decision later.

This is part of #44.
2021-12-01 11:08:53 -08:00
Martin von Zweigbergk
6687f98d8a cli and docs: replace "id" by more correct "ID" 2021-10-27 15:06:10 -07:00
Martin von Zweigbergk
8bbfe9731e cleanup: let newer Clippy fix a few things it found 2021-10-13 08:27:44 -07:00
Martin von Zweigbergk
09feb2e281 cli: reimplement divergent template keyword without evolution (#32)
This rewrites the `divergent` template keyword to be based on the
number of visible commits with a given change id. That's the same as
before; it's just that it's not based on the `Evolution` object's view
of which commits are visible anymore.

This is the last thing that depended on the evolution state!
2021-10-06 23:20:23 -07:00
Martin von Zweigbergk
a750be2b9b cli: remove most evolution-related template keywords (#32)
`obsolete`, `orphan`, and `abandoned` almost never appear in log
output these days, so let's remove them.
2021-10-06 23:20:23 -07:00
Martin von Zweigbergk
ae7f00e7b1 cli: rename jj prune to jj abandon
The command's help text says "Abandon a revision", which I think is a
good indication that the command's name should be `abandon`. This
patch renames the command and other user-facing occurrences of the
word. The remaining occurrences should be removed when I remove
support for evolution.
2021-09-19 22:51:12 -07:00