mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-12 15:16:35 +00:00
revsets: allow the ..
operator to be used as prefix or suffix (#46)
It makes sense to omit either of the arguments of the `..` operator, even though `..x` is equivalent to `:x`. `x..`, with a implied right argument of `heads()` is more useful.
This commit is contained in:
parent
bc92b82ed4
commit
7d3d0fe83c
3 changed files with 27 additions and 6 deletions
|
@ -68,6 +68,9 @@ only symbols.
|
||||||
* `x..y`: Ancestors of `y` that are not also ancestors of `x`, both inclusive.
|
* `x..y`: Ancestors of `y` that are not also ancestors of `x`, both inclusive.
|
||||||
Equivalent to `:y ~ :x`. This is what `git log` calls `x..y` (i.e. the same as
|
Equivalent to `:y ~ :x`. This is what `git log` calls `x..y` (i.e. the same as
|
||||||
we call it).
|
we call it).
|
||||||
|
* `..x`: Ancestors of `x`, including the commits in `x` itself. Equivalent to
|
||||||
|
`:x` and provided for consistency.
|
||||||
|
* `x..`: Revisions that are not ancestors of `x`.
|
||||||
|
|
||||||
You can use parentheses to control evaluation order, such as `(x & y) | z` or
|
You can use parentheses to control evaluation order, such as `(x & y) | z` or
|
||||||
`x & (y | z)`.
|
`x & (y | z)`.
|
||||||
|
@ -113,7 +116,7 @@ jj log -r @-
|
||||||
|
|
||||||
Show commits not on any remote branch:
|
Show commits not on any remote branch:
|
||||||
```
|
```
|
||||||
jj log -r 'remote_branches()..all()'
|
jj log -r 'remote_branches()..'
|
||||||
```
|
```
|
||||||
|
|
||||||
Show all ancestors of the working copy (almost like plain `git log`)
|
Show all ancestors of the working copy (almost like plain `git log`)
|
||||||
|
|
|
@ -52,7 +52,9 @@ neighbors_expression = { primary ~ (parents_op | children_op)* }
|
||||||
range_expression = {
|
range_expression = {
|
||||||
neighbors_expression ~ dag_range_op ~ neighbors_expression
|
neighbors_expression ~ dag_range_op ~ neighbors_expression
|
||||||
| neighbors_expression ~ range_op ~ neighbors_expression
|
| neighbors_expression ~ range_op ~ neighbors_expression
|
||||||
|
| neighbors_expression ~ range_op
|
||||||
| dag_range_op ~ neighbors_expression
|
| dag_range_op ~ neighbors_expression
|
||||||
|
| range_op ~ neighbors_expression
|
||||||
| neighbors_expression ~ dag_range_op
|
| neighbors_expression ~ dag_range_op
|
||||||
| neighbors_expression
|
| neighbors_expression
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,7 +406,7 @@ fn parse_range_expression_rule(
|
||||||
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
||||||
let first = pairs.next().unwrap();
|
let first = pairs.next().unwrap();
|
||||||
match first.as_rule() {
|
match first.as_rule() {
|
||||||
Rule::dag_range_op => {
|
Rule::dag_range_op | Rule::range_op => {
|
||||||
return Ok(
|
return Ok(
|
||||||
parse_neighbors_expression_rule(pairs.next().unwrap().into_inner())?.ancestors(),
|
parse_neighbors_expression_rule(pairs.next().unwrap().into_inner())?.ancestors(),
|
||||||
);
|
);
|
||||||
|
@ -431,9 +431,13 @@ fn parse_range_expression_rule(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rule::range_op => {
|
Rule::range_op => {
|
||||||
let expression2 =
|
if let Some(heads_pair) = pairs.next() {
|
||||||
parse_neighbors_expression_rule(pairs.next().unwrap().into_inner())?;
|
let heads_expression =
|
||||||
expression = expression.range(&expression2);
|
parse_neighbors_expression_rule(heads_pair.into_inner())?;
|
||||||
|
expression = expression.range(&heads_expression);
|
||||||
|
} else {
|
||||||
|
expression = expression.range(&RevsetExpression::heads());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unxpected revset range operator rule {:?}", next.as_rule());
|
panic!("unxpected revset range operator rule {:?}", next.as_rule());
|
||||||
|
@ -1334,6 +1338,13 @@ mod tests {
|
||||||
assert_eq!(parse("@:"), Ok(checkout_symbol.descendants()));
|
assert_eq!(parse("@:"), Ok(checkout_symbol.descendants()));
|
||||||
// Parse the "dag range" operator
|
// Parse the "dag range" operator
|
||||||
assert_eq!(parse("foo:bar"), Ok(foo_symbol.dag_range_to(&bar_symbol)));
|
assert_eq!(parse("foo:bar"), Ok(foo_symbol.dag_range_to(&bar_symbol)));
|
||||||
|
// Parse the "range" prefix operator
|
||||||
|
assert_eq!(parse("..@"), Ok(checkout_symbol.ancestors()));
|
||||||
|
assert_eq!(
|
||||||
|
parse("@.."),
|
||||||
|
Ok(checkout_symbol.range(&RevsetExpression::heads()))
|
||||||
|
);
|
||||||
|
assert_eq!(parse("foo..bar"), Ok(foo_symbol.range(&bar_symbol)));
|
||||||
// Parse the "intersection" operator
|
// Parse the "intersection" operator
|
||||||
assert_eq!(parse("foo & bar"), Ok(foo_symbol.intersection(&bar_symbol)));
|
assert_eq!(parse("foo & bar"), Ok(foo_symbol.intersection(&bar_symbol)));
|
||||||
// Parse the "union" operator
|
// Parse the "union" operator
|
||||||
|
@ -1371,13 +1382,18 @@ mod tests {
|
||||||
parse("foo+++"),
|
parse("foo+++"),
|
||||||
Ok(foo_symbol.children().children().children())
|
Ok(foo_symbol.children().children().children())
|
||||||
);
|
);
|
||||||
// Parse repeated "ancestors"/"descendants"/"dag range" operators
|
// Parse repeated "ancestors"/"descendants"/"dag range"/"range" operators
|
||||||
assert_matches!(parse(":foo:"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse(":foo:"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
assert_matches!(parse("::foo"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse("::foo"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
assert_matches!(parse("foo::"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse("foo::"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
assert_matches!(parse("foo::bar"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse("foo::bar"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
assert_matches!(parse(":foo:bar"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse(":foo:bar"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
assert_matches!(parse("foo:bar:"), Err(RevsetParseError::SyntaxError(_)));
|
assert_matches!(parse("foo:bar:"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
|
assert_matches!(parse("....foo"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
|
assert_matches!(parse("foo...."), Err(RevsetParseError::SyntaxError(_)));
|
||||||
|
assert_matches!(parse("foo.....bar"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
|
assert_matches!(parse("..foo..bar"), Err(RevsetParseError::SyntaxError(_)));
|
||||||
|
assert_matches!(parse("foo..bar.."), Err(RevsetParseError::SyntaxError(_)));
|
||||||
// Parse combinations of "parents"/"children" operators and the range operators.
|
// Parse combinations of "parents"/"children" operators and the range operators.
|
||||||
// The former bind more strongly.
|
// The former bind more strongly.
|
||||||
assert_eq!(parse("foo-+"), Ok(foo_symbol.parents().children()));
|
assert_eq!(parse("foo-+"), Ok(foo_symbol.parents().children()));
|
||||||
|
|
Loading…
Reference in a new issue