diff --git a/cli/src/commands/workspace/forget.rs b/cli/src/commands/workspace/forget.rs index 72be660d8..bc119179d 100644 --- a/cli/src/commands/workspace/forget.rs +++ b/cli/src/commands/workspace/forget.rs @@ -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; use jj_lib::op_store::WorkspaceId; use tracing::instrument; @@ -19,6 +20,7 @@ use tracing::instrument; use crate::cli_util::CommandHelper; use crate::command_error::user_error; use crate::command_error::CommandError; +use crate::complete; use crate::ui::Ui; /// Stop tracking a workspace's working-copy commit in the repo @@ -29,6 +31,7 @@ use crate::ui::Ui; pub struct WorkspaceForgetArgs { /// Names of the workspaces to forget. By default, forgets only the current /// workspace. + #[arg(add = ArgValueCandidates::new(complete::workspaces))] workspaces: Vec, } diff --git a/cli/src/complete.rs b/cli/src/complete.rs index 997c89085..d138dc432 100644 --- a/cli/src/complete.rs +++ b/cli/src/complete.rs @@ -271,6 +271,27 @@ pub fn operations() -> Vec { }) } +pub fn workspaces() -> Vec { + with_jj(|mut jj, _| { + let output = jj + .arg("--config-toml") + .arg(r#"templates.commit_summary = 'if(description, description.first_line(), "(no description set)")'"#) + .arg("workspace") + .arg("list") + .output() + .map_err(user_error)?; + let stdout = String::from_utf8_lossy(&output.stdout); + + Ok(stdout + .lines() + .map(|line| { + let (name, desc) = line.split_once(": ").unwrap_or((line, "")); + CompletionCandidate::new(name).help(Some(desc.to_string().into())) + }) + .collect()) + }) +} + /// Shell out to jj during dynamic completion generation /// /// In case of errors, print them and early return an empty vector. diff --git a/cli/tests/test_completion.rs b/cli/tests/test_completion.rs index 5ad32bd15..3bd1fff78 100644 --- a/cli/tests/test_completion.rs +++ b/cli/tests/test_completion.rs @@ -446,3 +446,29 @@ fn test_operations() { let stdout = test_env.jj_cmd_success(&repo_path, &["--", "jj", "op", "undo", "5b"]); insta::assert_snapshot!(stdout, @"5bbb4ca536a8 (2001-02-03 08:05:12) describe commit 968261075dddabf4b0e333c1cc9a49ce26a3f710"); } + +#[test] +fn test_workspaces() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "main"]); + let main_path = test_env.env_root().join("main"); + + std::fs::write(main_path.join("file"), "contents").unwrap(); + test_env.jj_cmd_ok(&main_path, &["describe", "-m", "initial"]); + + test_env.jj_cmd_ok( + &main_path, + // same prefix as "default" workspace + &["workspace", "add", "--name", "def-second", "../secondary"], + ); + + let mut test_env = test_env; + test_env.add_env_var("COMPLETE", "fish"); + let test_env = test_env; + + let stdout = test_env.jj_cmd_success(&main_path, &["--", "jj", "workspace", "forget", "def"]); + insta::assert_snapshot!(stdout, @r" + def-second (no description set) + default initial + "); +}