mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-05 15:32:49 +00:00
completion: revset expression completer
This commit is contained in:
parent
8936a7bc4b
commit
87f6db0a70
@ -73,6 +73,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
* `jj config edit` will now roll back to previous version if a syntax error has been introduced in the new config.
|
||||
|
||||
* When using dynamic command-line completion, revision names will be completed
|
||||
in more complex expressions. For example, typing
|
||||
`jj log -r first-bookmark..sec` and then pressing Tab could complete the
|
||||
expression to `first-bookmark..second-bookmark`.
|
||||
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
|
@ -16,7 +16,7 @@ use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::commit::CommitIteratorExt as _;
|
||||
@ -47,14 +47,14 @@ pub(crate) struct AbandonArgs {
|
||||
/// The revision(s) to abandon (default: @)
|
||||
#[arg(
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions_pos: Vec<RevisionArg>,
|
||||
#[arg(
|
||||
short = 'r',
|
||||
hide = true,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions_opt: Vec<RevisionArg>,
|
||||
// TODO: Remove in jj 0.34+
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::absorb::absorb_hunks;
|
||||
use jj_lib::absorb::split_hunks_to_trees;
|
||||
use jj_lib::absorb::AbsorbSource;
|
||||
@ -46,7 +46,7 @@ pub(crate) struct AbsorbArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
from: RevisionArg,
|
||||
/// Destination revisions to absorb into
|
||||
@ -56,7 +56,7 @@ pub(crate) struct AbsorbArgs {
|
||||
long, short = 't', visible_alias = "to",
|
||||
default_value = "mutable()",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
into: Vec<RevisionArg>,
|
||||
/// Move only changes to these paths (instead of all paths)
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use bstr::ByteVec as _;
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::rewrite::merge_commit_trees;
|
||||
@ -38,7 +38,7 @@ pub(crate) struct BackoutArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
/// The revision to apply the reverse changes on top of
|
||||
@ -48,7 +48,7 @@ pub(crate) struct BackoutArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
destination: Vec<RevisionArg>,
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
@ -41,7 +41,7 @@ pub struct BookmarkCreateArgs {
|
||||
long, short,
|
||||
visible_alias = "to",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: Option<RevisionArg>,
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
@ -47,7 +48,7 @@ pub struct BookmarkMoveArgs {
|
||||
long, short,
|
||||
group = "source",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
from: Vec<RevisionArg>,
|
||||
|
||||
@ -58,7 +59,7 @@ pub struct BookmarkMoveArgs {
|
||||
#[arg(
|
||||
long, short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
to: Option<RevisionArg>,
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
@ -40,7 +41,7 @@ pub struct BookmarkSetArgs {
|
||||
long, short,
|
||||
visible_alias = "to",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: Option<RevisionArg>,
|
||||
|
||||
|
@ -17,7 +17,7 @@ use std::io;
|
||||
use std::io::Read as _;
|
||||
use std::iter;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::Signature;
|
||||
use jj_lib::commit::CommitIteratorExt as _;
|
||||
@ -49,14 +49,14 @@ pub(crate) struct DescribeArgs {
|
||||
/// The revision(s) whose description to edit (default: @)
|
||||
#[arg(
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable)
|
||||
)]
|
||||
revisions_pos: Vec<RevisionArg>,
|
||||
#[arg(
|
||||
short = 'r',
|
||||
hide = true,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable)
|
||||
)]
|
||||
revisions_opt: Vec<RevisionArg>,
|
||||
/// The change description to use (don't open editor)
|
||||
|
@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools as _;
|
||||
@ -63,7 +62,7 @@ pub(crate) struct DiffArgs {
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
alias = "revision",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Option<Vec<RevisionArg>>,
|
||||
/// Show changes from this revision
|
||||
@ -72,7 +71,7 @@ pub(crate) struct DiffArgs {
|
||||
short,
|
||||
conflicts_with = "revisions",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
from: Option<RevisionArg>,
|
||||
/// Show changes to this revision
|
||||
@ -81,7 +80,7 @@ pub(crate) struct DiffArgs {
|
||||
short,
|
||||
conflicts_with = "revisions",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
to: Option<RevisionArg>,
|
||||
/// Restrict the diff to these paths
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::matchers::EverythingMatcher;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
@ -54,7 +54,7 @@ pub(crate) struct DiffeditArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revision: Option<RevisionArg>,
|
||||
/// Show changes from this revision
|
||||
@ -64,7 +64,7 @@ pub(crate) struct DiffeditArgs {
|
||||
long, short,
|
||||
conflicts_with = "revision",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
from: Option<RevisionArg>,
|
||||
/// Edit changes in this revision
|
||||
@ -74,7 +74,7 @@ pub(crate) struct DiffeditArgs {
|
||||
long, short,
|
||||
conflicts_with = "revision",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
to: Option<RevisionArg>,
|
||||
/// Specify diff editor to be used
|
||||
|
@ -15,7 +15,7 @@
|
||||
use std::io::Write as _;
|
||||
|
||||
use bstr::ByteVec as _;
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::BackendResult;
|
||||
use jj_lib::backend::CommitId;
|
||||
@ -56,14 +56,14 @@ pub(crate) struct DuplicateArgs {
|
||||
/// The revision(s) to duplicate (default: @)
|
||||
#[arg(
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions_pos: Vec<RevisionArg>,
|
||||
#[arg(
|
||||
short = 'r',
|
||||
hide = true,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions_opt: Vec<RevisionArg>,
|
||||
/// The revision(s) to duplicate onto (can be repeated to create a merge
|
||||
@ -72,7 +72,7 @@ pub(crate) struct DuplicateArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
destination: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert after (can be repeated to create a merge
|
||||
@ -83,7 +83,7 @@ pub(crate) struct DuplicateArgs {
|
||||
visible_alias = "after",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
insert_after: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert before (can be repeated to create a merge
|
||||
@ -94,7 +94,7 @@ pub(crate) struct DuplicateArgs {
|
||||
visible_alias = "before",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
insert_before: Option<Vec<RevisionArg>>,
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
use tracing::instrument;
|
||||
|
||||
@ -34,7 +34,7 @@ use crate::ui::Ui;
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub(crate) struct EditArgs {
|
||||
/// The commit to edit
|
||||
#[arg(value_name = "REVSET", add = ArgValueCandidates::new(complete::mutable_revisions))]
|
||||
#[arg(value_name = "REVSET", add = ArgValueCompleter::new(complete::revset_expression_mutable))]
|
||||
revision: RevisionArg,
|
||||
/// Ignored (but lets you pass `-r` for consistency with other commands)
|
||||
#[arg(short = 'r', hide = true)]
|
||||
|
@ -15,6 +15,7 @@
|
||||
use std::convert::Infallible;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::commit::Commit;
|
||||
use jj_lib::dag_walk::topo_order_reverse_ok;
|
||||
@ -46,7 +47,7 @@ pub(crate) struct EvologArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Limit number of revisions to show
|
||||
|
@ -47,7 +47,7 @@ pub(crate) struct FileAnnotateArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: Option<RevisionArg>,
|
||||
/// Render each line using the given template
|
||||
|
@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::backend::TreeValue;
|
||||
use jj_lib::merged_tree::MergedTreeBuilder;
|
||||
@ -50,7 +49,7 @@ pub(crate) struct FileChmodArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Paths to change the executable bit for
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::cli_util::CommandHelper;
|
||||
@ -31,7 +31,7 @@ pub(crate) struct FileListArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
use std::io;
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::backend::BackendResult;
|
||||
use jj_lib::conflicts::materialize_merge_result;
|
||||
@ -49,7 +48,7 @@ pub(crate) struct FileShowArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Paths to print
|
||||
|
@ -17,7 +17,7 @@ use std::io::Write as _;
|
||||
use std::path::Path;
|
||||
use std::process::Stdio;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::backend::FileId;
|
||||
@ -108,7 +108,7 @@ pub(crate) struct FixArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
source: Vec<RevisionArg>,
|
||||
/// Fix only these paths
|
||||
|
@ -160,7 +160,7 @@ pub struct GitPushArgs {
|
||||
// While `-r` will often be used with mutable revisions, immutable
|
||||
// revisions can be useful as parts of revsets or to push
|
||||
// special-purpose branches.
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
/// Push this commit by creating a bookmark based on its change ID (can be
|
||||
@ -177,7 +177,7 @@ pub struct GitPushArgs {
|
||||
// recently created mutable revisions, even though it can in theory
|
||||
// be used with immutable ones as well. We can change it if the guess
|
||||
// turns out to be wrong.
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
change: Vec<RevisionArg>,
|
||||
/// Specify a new bookmark name and a revision to push under that name, e.g.
|
||||
|
@ -15,7 +15,6 @@
|
||||
use std::slice;
|
||||
|
||||
use clap::ArgGroup;
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use tracing::instrument;
|
||||
|
||||
@ -41,7 +40,7 @@ pub(crate) struct InterdiffArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
from: Option<RevisionArg>,
|
||||
/// Show changes to this revision
|
||||
@ -49,7 +48,7 @@ pub(crate) struct InterdiffArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
to: Option<RevisionArg>,
|
||||
/// Restrict the diff to these paths
|
||||
|
@ -74,7 +74,7 @@ pub(crate) struct LogArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
/// Show revisions modifying the given paths
|
||||
|
@ -15,7 +15,7 @@
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::repo::Repo as _;
|
||||
@ -49,7 +49,7 @@ pub(crate) struct NewArgs {
|
||||
#[arg(
|
||||
default_value = "@",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Option<Vec<RevisionArg>>,
|
||||
/// Ignored (but lets you pass `-d`/`-r` for consistency with other
|
||||
@ -98,7 +98,7 @@ pub(crate) struct NewArgs {
|
||||
conflicts_with = "revisions",
|
||||
value_name = "REVSETS",
|
||||
verbatim_doc_comment,
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
insert_after: Option<Vec<RevisionArg>>,
|
||||
/// Insert the new change before the given commit(s)
|
||||
@ -137,7 +137,7 @@ pub(crate) struct NewArgs {
|
||||
conflicts_with = "revisions",
|
||||
value_name = "REVSETS",
|
||||
verbatim_doc_comment,
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
insert_before: Option<Vec<RevisionArg>>,
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
@ -59,7 +59,7 @@ pub(crate) struct ParallelizeArgs {
|
||||
/// Revisions to parallelize
|
||||
#[arg(
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use std::io::Write as _;
|
||||
use std::sync::Arc;
|
||||
|
||||
use clap::ArgGroup;
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::commit::Commit;
|
||||
@ -278,7 +278,7 @@ pub(crate) struct RebaseArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
branch: Vec<RevisionArg>,
|
||||
|
||||
@ -294,7 +294,7 @@ pub(crate) struct RebaseArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
source: Vec<RevisionArg>,
|
||||
/// Rebase the given revisions, rebasing descendants onto this revision's
|
||||
@ -308,7 +308,7 @@ pub(crate) struct RebaseArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
|
||||
@ -336,7 +336,7 @@ pub struct RebaseDestinationArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
destination: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert after (can be repeated to create a merge
|
||||
@ -347,7 +347,7 @@ pub struct RebaseDestinationArgs {
|
||||
visible_alias = "after",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
insert_after: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert before (can be repeated to create a merge
|
||||
@ -358,7 +358,7 @@ pub struct RebaseDestinationArgs {
|
||||
visible_alias = "before",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
insert_before: Option<Vec<RevisionArg>>,
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
@ -50,7 +49,7 @@ pub(crate) struct ResolveArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Instead of resolving conflicts, list all the conflicts
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indoc::formatdoc;
|
||||
use itertools::Itertools as _;
|
||||
@ -58,7 +57,7 @@ pub(crate) struct RestoreArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
from: Option<RevisionArg>,
|
||||
/// Revision to restore into (destination)
|
||||
@ -66,7 +65,7 @@ pub(crate) struct RestoreArgs {
|
||||
long, short = 't',
|
||||
visible_alias = "to",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
into: Option<RevisionArg>,
|
||||
/// Undo the changes in a revision as compared to the merge of its parents.
|
||||
@ -81,7 +80,7 @@ pub(crate) struct RestoreArgs {
|
||||
long, short,
|
||||
value_name = "REVSET",
|
||||
conflicts_with_all = ["into", "from"],
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
changes_in: Option<RevisionArg>,
|
||||
/// Prints an error. DO NOT USE.
|
||||
|
@ -16,7 +16,7 @@ use std::collections::HashSet;
|
||||
|
||||
use bstr::ByteVec as _;
|
||||
use clap::ArgGroup;
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
@ -48,14 +48,14 @@ pub(crate) struct RevertArgs {
|
||||
#[arg(
|
||||
long, short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
/// The revision(s) to apply the reverse changes on top of
|
||||
#[arg(
|
||||
long, short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
destination: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert the reverse changes after (can be repeated to
|
||||
@ -66,7 +66,7 @@ pub(crate) struct RevertArgs {
|
||||
visible_alias = "after",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::all_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
insert_after: Option<Vec<RevisionArg>>,
|
||||
/// The revision(s) to insert the reverse changes before (can be repeated to
|
||||
@ -77,7 +77,7 @@ pub(crate) struct RevertArgs {
|
||||
visible_alias = "before",
|
||||
conflicts_with = "destination",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
insert_before: Option<Vec<RevisionArg>>,
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::matchers::EverythingMatcher;
|
||||
use tracing::instrument;
|
||||
|
||||
@ -30,7 +31,7 @@ pub(crate) struct ShowArgs {
|
||||
#[arg(
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::all_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_all),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Ignored (but lets you pass `-r` for consistency with other commands)
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::commit::Commit;
|
||||
@ -52,7 +52,7 @@ pub struct SignArgs {
|
||||
#[arg(
|
||||
long, short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::BackendError;
|
||||
use jj_lib::revset::RevsetExpression;
|
||||
@ -28,7 +28,7 @@ pub(crate) struct SimplifyParentsArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
source: Vec<RevisionArg>,
|
||||
/// Simplify specified revision(s) (can be repeated)
|
||||
@ -40,7 +40,7 @@ pub(crate) struct SimplifyParentsArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
use std::io::Write as _;
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use jj_lib::commit::Commit;
|
||||
use jj_lib::matchers::Matcher;
|
||||
@ -67,7 +66,7 @@ pub(crate) struct SplitArgs {
|
||||
long, short,
|
||||
default_value = "@",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revision: RevisionArg,
|
||||
/// Split the revision into two parallel revisions instead of a parent and
|
||||
|
@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indoc::formatdoc;
|
||||
use itertools::Itertools as _;
|
||||
@ -69,7 +68,7 @@ pub(crate) struct SquashArgs {
|
||||
long,
|
||||
short,
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions)
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revision: Option<RevisionArg>,
|
||||
/// Revision(s) to squash from (default: @)
|
||||
@ -77,7 +76,7 @@ pub(crate) struct SquashArgs {
|
||||
long, short,
|
||||
conflicts_with = "revision",
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
from: Vec<RevisionArg>,
|
||||
/// Revision to squash into (default: @)
|
||||
@ -86,7 +85,7 @@ pub(crate) struct SquashArgs {
|
||||
conflicts_with = "revision",
|
||||
visible_alias = "to",
|
||||
value_name = "REVSET",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
into: Option<RevisionArg>,
|
||||
/// The description to use for squashed revision (don't open editor)
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::commit::Commit;
|
||||
@ -38,7 +38,7 @@ pub struct UnsignArgs {
|
||||
#[arg(
|
||||
long, short,
|
||||
value_name = "REVSETS",
|
||||
add = ArgValueCandidates::new(complete::mutable_revisions),
|
||||
add = ArgValueCompleter::new(complete::revset_expression_mutable),
|
||||
)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ pub fn aliases() -> Vec<CompletionCandidate> {
|
||||
})
|
||||
}
|
||||
|
||||
fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
fn revisions(match_prefix: &str, revset_filter: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
with_jj(|jj, settings| {
|
||||
// display order
|
||||
const LOCAL_BOOKMARK_MINE: usize = 0;
|
||||
@ -257,15 +257,18 @@ fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
.arg(
|
||||
r#"if(remote != "git", name ++ if(remote, "@" ++ remote) ++ bookmark_help() ++ "\n")"#,
|
||||
);
|
||||
if let Some(revs) = revisions {
|
||||
if let Some(revs) = revset_filter {
|
||||
cmd.arg("--revisions").arg(revs);
|
||||
}
|
||||
let output = cmd.output().map_err(user_error)?;
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
|
||||
candidates.extend(stdout.lines().map(|line| {
|
||||
let (bookmark, help) = split_help_text(line);
|
||||
|
||||
candidates.extend(
|
||||
stdout
|
||||
.lines()
|
||||
.map(split_help_text)
|
||||
.filter(|(bookmark, _)| bookmark.starts_with(match_prefix))
|
||||
.map(|(bookmark, help)| {
|
||||
let local = !bookmark.contains('@');
|
||||
let mine = prefix.as_ref().is_some_and(|p| bookmark.starts_with(p));
|
||||
|
||||
@ -278,15 +281,16 @@ fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
CompletionCandidate::new(bookmark)
|
||||
.help(help)
|
||||
.display_order(Some(display_order))
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
// tags
|
||||
|
||||
// Tags cannot be filtered by revisions. In order to avoid suggesting
|
||||
// immutable tags for mutable revision args, we skip tags entirely if
|
||||
// revisions is set. This is not a big loss, since tags usually point
|
||||
// revset_filter is set. This is not a big loss, since tags usually point
|
||||
// to immutable revisions anyway.
|
||||
if revisions.is_none() {
|
||||
if revset_filter.is_none() {
|
||||
let output = jj
|
||||
.build()
|
||||
.arg("tag")
|
||||
@ -295,6 +299,7 @@ fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
.arg(BOOKMARK_HELP_TEMPLATE)
|
||||
.arg("--template")
|
||||
.arg(r#"name ++ bookmark_help() ++ "\n""#)
|
||||
.arg(format!("glob:{}*", glob::Pattern::escape(match_prefix)))
|
||||
.output()
|
||||
.map_err(user_error)?;
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
@ -309,7 +314,7 @@ fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
|
||||
// change IDs
|
||||
|
||||
let revisions = revisions
|
||||
let revisions = revset_filter
|
||||
.map(String::from)
|
||||
.or_else(|| settings.get_string("revsets.short-prefixes").ok())
|
||||
.or_else(|| settings.get_string("revsets.log").ok())
|
||||
@ -329,35 +334,92 @@ fn revisions(revisions: Option<&str>) -> Vec<CompletionCandidate> {
|
||||
.map_err(user_error)?;
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
|
||||
candidates.extend(stdout.lines().map(|line| {
|
||||
let (id, desc) = split_help_text(line);
|
||||
candidates.extend(
|
||||
stdout
|
||||
.lines()
|
||||
.map(split_help_text)
|
||||
.filter(|(id, _)| id.starts_with(match_prefix))
|
||||
.map(|(id, desc)| {
|
||||
CompletionCandidate::new(id)
|
||||
.help(desc)
|
||||
.display_order(Some(CHANGE_ID))
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
// revset aliases
|
||||
|
||||
let revset_aliases = load_revset_aliases(&Ui::null(), settings.config())?;
|
||||
let mut symbol_names: Vec<_> = revset_aliases.symbol_names().collect();
|
||||
symbol_names.sort();
|
||||
candidates.extend(symbol_names.into_iter().map(|symbol| {
|
||||
candidates.extend(
|
||||
symbol_names
|
||||
.into_iter()
|
||||
.filter(|symbol| symbol.starts_with(match_prefix))
|
||||
.map(|symbol| {
|
||||
let (_, defn) = revset_aliases.get_symbol(symbol).unwrap();
|
||||
CompletionCandidate::new(symbol)
|
||||
.help(Some(defn.into()))
|
||||
.display_order(Some(REVSET_ALIAS))
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
Ok(candidates)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn mutable_revisions() -> Vec<CompletionCandidate> {
|
||||
revisions(Some("mutable()"))
|
||||
fn revset_expression(
|
||||
current: &std::ffi::OsStr,
|
||||
revset_filter: Option<&str>,
|
||||
) -> Vec<CompletionCandidate> {
|
||||
let Some(current) = current.to_str() else {
|
||||
return Vec::new();
|
||||
};
|
||||
let (prepend, match_prefix) = split_revset_trailing_name(current).unwrap_or(("", current));
|
||||
let candidates = revisions(match_prefix, revset_filter);
|
||||
if prepend.is_empty() {
|
||||
candidates
|
||||
} else {
|
||||
candidates
|
||||
.into_iter()
|
||||
.map(|candidate| candidate.add_prefix(prepend))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_revisions() -> Vec<CompletionCandidate> {
|
||||
revisions(None)
|
||||
pub fn revset_expression_all(current: &std::ffi::OsStr) -> Vec<CompletionCandidate> {
|
||||
revset_expression(current, None)
|
||||
}
|
||||
|
||||
pub fn revset_expression_mutable(current: &std::ffi::OsStr) -> Vec<CompletionCandidate> {
|
||||
revset_expression(current, Some("mutable()"))
|
||||
}
|
||||
|
||||
/// Identifies if an incomplete expression ends with a name, or may be continued
|
||||
/// with a name.
|
||||
///
|
||||
/// If the expression ends with an name or a partial name, returns a tuple that
|
||||
/// splits the string at the point the name starts.
|
||||
/// If the expression is empty or ends with a prefix or infix operator that
|
||||
/// could plausibly be followed by a name, returns a tuple where the first
|
||||
/// item is the entire input string, and the second item is empty.
|
||||
/// Otherwise, returns `None`.
|
||||
///
|
||||
/// The input expression may be incomplete (e.g. missing closing parentheses),
|
||||
/// and the ability to reject invalid expressions is limited.
|
||||
fn split_revset_trailing_name(incomplete_revset_str: &str) -> Option<(&str, &str)> {
|
||||
let final_part = incomplete_revset_str
|
||||
.rsplit_once([':', '~', '|', '&', '(', ','])
|
||||
.map(|(_, rest)| rest)
|
||||
.unwrap_or(incomplete_revset_str);
|
||||
let final_part = final_part
|
||||
.rsplit_once("..")
|
||||
.map(|(_, rest)| rest)
|
||||
.unwrap_or(final_part)
|
||||
.trim_ascii_start();
|
||||
|
||||
let re = regex::Regex::new(r"^(?:[\p{XID_CONTINUE}_/]+[@.+-])*[\p{XID_CONTINUE}_/]*$").unwrap();
|
||||
re.is_match(final_part)
|
||||
.then(|| incomplete_revset_str.split_at(incomplete_revset_str.len() - final_part.len()))
|
||||
}
|
||||
|
||||
pub fn operations() -> Vec<CompletionCandidate> {
|
||||
@ -557,13 +619,8 @@ pub fn branch_name_equals_any_revision(current: &std::ffi::OsStr) -> Vec<Complet
|
||||
// Don't complete branch names since we want to create a new branch
|
||||
return Vec::new();
|
||||
};
|
||||
all_revisions()
|
||||
revset_expression(revision.as_ref(), None)
|
||||
.into_iter()
|
||||
.filter(|rev| {
|
||||
rev.get_value()
|
||||
.to_str()
|
||||
.is_some_and(|s| s.starts_with(revision))
|
||||
})
|
||||
.map(|rev| rev.add_prefix(format!("{branch_name}=")))
|
||||
.collect()
|
||||
}
|
||||
@ -1022,6 +1079,71 @@ mod parse {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_split_revset_trailing_name() {
|
||||
assert_eq!(split_revset_trailing_name(""), Some(("", "")));
|
||||
assert_eq!(split_revset_trailing_name(" "), Some((" ", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo"), Some(("", "foo")));
|
||||
assert_eq!(split_revset_trailing_name(" foo"), Some((" ", "foo")));
|
||||
assert_eq!(split_revset_trailing_name("foo "), None);
|
||||
assert_eq!(split_revset_trailing_name("foo_"), Some(("", "foo_")));
|
||||
assert_eq!(split_revset_trailing_name("foo/"), Some(("", "foo/")));
|
||||
assert_eq!(split_revset_trailing_name("foo/b"), Some(("", "foo/b")));
|
||||
|
||||
assert_eq!(split_revset_trailing_name("foo-"), Some(("", "foo-")));
|
||||
assert_eq!(split_revset_trailing_name("foo+"), Some(("", "foo+")));
|
||||
assert_eq!(
|
||||
split_revset_trailing_name("foo-bar-"),
|
||||
Some(("", "foo-bar-"))
|
||||
);
|
||||
assert_eq!(
|
||||
split_revset_trailing_name("foo-bar-b"),
|
||||
Some(("", "foo-bar-b"))
|
||||
);
|
||||
|
||||
assert_eq!(split_revset_trailing_name("foo."), Some(("", "foo.")));
|
||||
assert_eq!(split_revset_trailing_name("foo..b"), Some(("foo..", "b")));
|
||||
assert_eq!(split_revset_trailing_name("..foo"), Some(("..", "foo")));
|
||||
|
||||
assert_eq!(split_revset_trailing_name("foo(bar"), Some(("foo(", "bar")));
|
||||
assert_eq!(split_revset_trailing_name("foo(bar)"), None);
|
||||
assert_eq!(split_revset_trailing_name("(f"), Some(("(", "f")));
|
||||
|
||||
assert_eq!(split_revset_trailing_name("foo@"), Some(("", "foo@")));
|
||||
assert_eq!(split_revset_trailing_name("foo@b"), Some(("", "foo@b")));
|
||||
assert_eq!(split_revset_trailing_name("..foo@"), Some(("..", "foo@")));
|
||||
assert_eq!(
|
||||
split_revset_trailing_name("::F(foo@origin.1..bar@origin."),
|
||||
Some(("::F(foo@origin.1..", "bar@origin."))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_revset_trailing_name_with_trailing_operator() {
|
||||
assert_eq!(split_revset_trailing_name("foo|"), Some(("foo|", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo | "), Some(("foo | ", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo&"), Some(("foo&", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo~"), Some(("foo~", "")));
|
||||
|
||||
assert_eq!(split_revset_trailing_name(".."), Some(("..", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo.."), Some(("foo..", "")));
|
||||
assert_eq!(split_revset_trailing_name("::"), Some(("::", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo::"), Some(("foo::", "")));
|
||||
|
||||
assert_eq!(split_revset_trailing_name("("), Some(("(", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo("), Some(("foo(", "")));
|
||||
assert_eq!(split_revset_trailing_name("foo()"), None);
|
||||
assert_eq!(split_revset_trailing_name("foo(bar)"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_revset_trailing_name_with_modifier() {
|
||||
assert_eq!(split_revset_trailing_name("all:"), Some(("all:", "")));
|
||||
assert_eq!(split_revset_trailing_name("all: "), Some(("all: ", "")));
|
||||
assert_eq!(split_revset_trailing_name("all:f"), Some(("all:", "f")));
|
||||
assert_eq!(split_revset_trailing_name("all: f"), Some(("all: ", "f")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_keys() {
|
||||
// Just make sure the schema is parsed without failure.
|
||||
|
@ -792,6 +792,22 @@ fn test_revisions() {
|
||||
[EOF]
|
||||
");
|
||||
|
||||
// complete all revisions in a revset expression
|
||||
let output = work_dir.complete_fish(["log", "-r", ".."]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
..immutable_bookmark immutable
|
||||
..mutable_bookmark mutable
|
||||
..k working_copy
|
||||
..y mutable
|
||||
..q immutable
|
||||
..zq remote_commit
|
||||
..zz (no description set)
|
||||
..remote_bookmark@origin remote_commit
|
||||
..alias_with_newline roots(
|
||||
..siblings @-+ ~@
|
||||
[EOF]
|
||||
");
|
||||
|
||||
// complete only mutable revisions
|
||||
let output = work_dir.complete_fish(["squash", "--into", ""]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
@ -804,6 +820,25 @@ fn test_revisions() {
|
||||
[EOF]
|
||||
");
|
||||
|
||||
// complete only mutable revisions in a revset expression
|
||||
let output = work_dir.complete_fish(["abandon", "y::"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
y::mutable_bookmark mutable
|
||||
y::k working_copy
|
||||
y::y mutable
|
||||
y::zq remote_commit
|
||||
y::alias_with_newline roots(
|
||||
y::siblings @-+ ~@
|
||||
[EOF]
|
||||
");
|
||||
|
||||
// complete remote bookmarks in a revset expression
|
||||
let output = work_dir.complete_fish(["log", "-r", "remote_bookmark@"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
remote_bookmark@origin remote_commit
|
||||
[EOF]
|
||||
");
|
||||
|
||||
// complete args of the default command
|
||||
test_env.add_config("ui.default-command = 'log'");
|
||||
let output = work_dir.complete_fish(["-r", ""]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user