Skip to content

Commit

Permalink
completion: teach commands about bookmark names
Browse files Browse the repository at this point in the history
  • Loading branch information
senekor committed Nov 11, 2024
1 parent 6d78537 commit ba989ce
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 13 deletions.
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::op_store::RefTarget;
use jj_lib::str_util::StringPattern;

use super::find_local_bookmarks;
use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::complete;
use crate::ui::Ui;

/// Delete an existing bookmark and propagate the deletion to remotes on the
Expand All @@ -30,7 +32,11 @@ pub struct BookmarkDeleteArgs {
/// By default, the specified name matches exactly. Use `glob:` prefix to
/// select bookmarks by wildcard pattern. For details, see
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
#[arg(required = true, value_parser = StringPattern::parse)]
#[arg(
required = true,
value_parser = StringPattern::parse,
add = ArgValueCandidates::new(complete::local_bookmarks),
)]
names: Vec<StringPattern>,
}

Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/forget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::op_store::BookmarkTarget;
use jj_lib::op_store::RefTarget;
Expand All @@ -22,6 +23,7 @@ use jj_lib::view::View;
use super::find_bookmarks_with;
use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::complete;
use crate::ui::Ui;

/// Forget everything about a bookmark, including its local and remote
Expand All @@ -36,7 +38,11 @@ pub struct BookmarkForgetArgs {
/// By default, the specified name matches exactly. Use `glob:` prefix to
/// select bookmarks by wildcard pattern. For details, see
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
#[arg(required = true, value_parser = StringPattern::parse)]
#[arg(
required = true,
value_parser = StringPattern::parse,
add = ArgValueCandidates::new(complete::bookmarks),
)]
names: Vec<StringPattern>,
}

Expand Down
4 changes: 3 additions & 1 deletion cli/src/commands/bookmark/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::collections::HashSet;

use clap_complete::ArgValueCandidates;
use itertools::Itertools;
use jj_lib::git;
use jj_lib::revset::RevsetExpression;
Expand All @@ -24,6 +25,7 @@ use crate::cli_util::RevisionArg;
use crate::command_error::CommandError;
use crate::commit_templater::CommitTemplateLanguage;
use crate::commit_templater::RefName;
use crate::complete;
use crate::ui::Ui;

/// List bookmarks and their targets
Expand Down Expand Up @@ -74,7 +76,7 @@ pub struct BookmarkListArgs {
/// By default, the specified name matches exactly. Use `glob:` prefix to
/// select bookmarks by wildcard pattern. For details, see
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
#[arg(value_parser = StringPattern::parse)]
#[arg(value_parser = StringPattern::parse, add = ArgValueCandidates::new(complete::bookmarks))]
names: Option<Vec<StringPattern>>,

/// Show bookmarks whose local targets are in the given revisions
Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::object_id::ObjectId as _;
use jj_lib::op_store::RefTarget;
Expand All @@ -23,6 +24,7 @@ use crate::cli_util::CommandHelper;
use crate::cli_util::RevisionArg;
use crate::command_error::user_error_with_hint;
use crate::command_error::CommandError;
use crate::complete;
use crate::ui::Ui;

/// Move existing bookmarks to target revision
Expand Down Expand Up @@ -62,7 +64,11 @@ pub struct BookmarkMoveArgs {
/// By default, the specified name matches exactly. Use `glob:` prefix to
/// select bookmarks by wildcard pattern. For details, see
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
#[arg(group = "source", value_parser = StringPattern::parse)]
#[arg(
group = "source",
value_parser = StringPattern::parse,
add = ArgValueCandidates::new(complete::local_bookmarks),
)]
names: Vec<StringPattern>,
}

Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use clap::builder::NonEmptyStringValueParser;
use clap_complete::ArgValueCandidates;
use jj_lib::object_id::ObjectId as _;
use jj_lib::op_store::RefTarget;

Expand All @@ -22,6 +23,7 @@ use crate::cli_util::CommandHelper;
use crate::cli_util::RevisionArg;
use crate::command_error::user_error_with_hint;
use crate::command_error::CommandError;
use crate::complete;
use crate::ui::Ui;

/// Create or update a bookmark to point to a certain commit
Expand All @@ -36,7 +38,11 @@ pub struct BookmarkSetArgs {
allow_backwards: bool,

/// The bookmarks to update
#[arg(required = true, value_parser = NonEmptyStringValueParser::new())]
#[arg(
required = true,
value_parser = NonEmptyStringValueParser::new(),
add = ArgValueCandidates::new(complete::local_bookmarks),
)]
names: Vec<String>,
}

Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::collections::HashMap;

use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;

use super::find_remote_bookmarks;
Expand All @@ -22,6 +23,7 @@ use crate::cli_util::RemoteBookmarkNamePattern;
use crate::command_error::CommandError;
use crate::commit_templater::CommitTemplateLanguage;
use crate::commit_templater::RefName;
use crate::complete;
use crate::ui::Ui;

/// Start tracking given remote bookmarks
Expand All @@ -38,7 +40,11 @@ pub struct BookmarkTrackArgs {
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
///
/// Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
#[arg(required = true, value_name = "BOOKMARK@REMOTE")]
#[arg(
required = true,
value_name = "BOOKMARK@REMOTE",
add = ArgValueCandidates::new(complete::untracked_bookmarks),
)]
names: Vec<RemoteBookmarkNamePattern>,
}

Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/bookmark/untrack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::git;

use super::find_remote_bookmarks;
use crate::cli_util::CommandHelper;
use crate::cli_util::RemoteBookmarkNamePattern;
use crate::command_error::CommandError;
use crate::complete;
use crate::ui::Ui;

/// Stop tracking given remote bookmarks
Expand All @@ -34,7 +36,11 @@ pub struct BookmarkUntrackArgs {
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
///
/// Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
#[arg(required = true, value_name = "BOOKMARK@REMOTE")]
#[arg(
required = true,
value_name = "BOOKMARK@REMOTE",
add = ArgValueCandidates::new(complete::tracked_bookmarks)
)]
names: Vec<RemoteBookmarkNamePattern>,
}

Expand Down
98 changes: 98 additions & 0 deletions cli/src/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,104 @@ pub fn local_bookmarks() -> Vec<CompletionCandidate> {
})
}

pub fn tracked_bookmarks() -> Vec<CompletionCandidate> {
with_jj(|jj, _| {
let output = jj
.build()
.arg("bookmark")
.arg("list")
.arg("--tracked")
.arg("--template")
.arg(r#"if(!remote, name ++ "\n")"#)
.output()
.map_err(user_error)?;

Ok(String::from_utf8_lossy(&output.stdout)
.lines()
.filter(|bookmark| !bookmark.ends_with("@git"))
.map(CompletionCandidate::new)
.collect())
})
}

pub fn untracked_bookmarks() -> Vec<CompletionCandidate> {
with_jj(|jj, config| {
let tracked = jj
.build()
.arg("bookmark")
.arg("list")
.arg("--tracked")
.arg("--template")
.arg(r#"if(remote, name ++ "@" ++ remote ++ "\n")"#)
.output()
.map_err(user_error)?;
let tracked = String::from_utf8_lossy(&tracked.stdout);
let tracked: Vec<_> = tracked.lines().collect();

let output = jj
.build()
.arg("bookmark")
.arg("list")
.arg("--all-remotes")
.arg("--template")
.arg(r#"if(remote, name ++ "@" ++ remote ++ "\n")"#)
.output()
.map_err(user_error)?;

Ok(String::from_utf8_lossy(&output.stdout)
.lines()
.filter(|bookmark| !bookmark.ends_with("@git"))
.filter(|bookmark| !tracked.contains(bookmark))
.map(|bookmark| {
let mut display_order = 0;
if let Ok(prefix) = config.get::<String>("git.push-bookmark-prefix") {
if !bookmark.starts_with(&prefix) {
// other people's bookmarks are less interesting
display_order += 1;
}
}
CompletionCandidate::new(bookmark).display_order(Some(display_order))
})
.collect())
})
}

pub fn bookmarks() -> Vec<CompletionCandidate> {
with_jj(|jj, config| {
let output = jj
.build()
.arg("bookmark")
.arg("list")
.arg("--all-remotes")
.arg("--template")
.arg(r#"separate("@", name, remote) ++ "\n""#)
.output()
.map_err(user_error)?;

Ok(String::from_utf8_lossy(&output.stdout)
.lines()
.map(|bookmark| {
let mut display_order = match () {
// git references are least interesting
_ if bookmark.ends_with("@git") => 2,
// remote bookmarks are less interesting than local ones
_ if bookmark.contains("@") => 1,
// local bookmarks are most interesting
_ => 0,
};
if let Ok(prefix) = config.get::<String>("git.push-bookmark-prefix") {
display_order *= 2; // make space for the tie-breaker
if !bookmark.starts_with(&prefix) {
// other people's bookmarks are less interesting
display_order += 1;
}
}
CompletionCandidate::new(bookmark).display_order(Some(display_order))
})
.collect())
})
}

/// Shell out to jj during dynamic completion generation
///
/// In case of errors, print them and early return an empty vector.
Expand Down
Loading

0 comments on commit ba989ce

Please sign in to comment.