diff --git a/src/completion.rs b/src/completion.rs index 65187872c..5aad1619e 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -11,6 +11,11 @@ use crate::display::format_relative_time_short; use worktrunk::config::{ProjectConfig, WorktrunkConfig}; use worktrunk::git::{BranchCategory, HookType, Repository}; +/// Deprecated args that should never appear in completions. +/// These are hidden from help AND completions, unlike other hidden args +/// that appear when completing `--`. +const DEPRECATED_ARGS: &[&str] = &["--no-background"]; + /// Handle shell-initiated completion requests via `COMPLETE=$SHELL wt` pub fn maybe_handle_env_completion() -> bool { let Some(shell_name) = std::env::var_os("COMPLETE") else { @@ -104,6 +109,15 @@ pub fn maybe_handle_env_completion() -> bool { completions }; + // Filter out deprecated args - they should never appear in completions + let completions: Vec<_> = completions + .into_iter() + .filter(|c| { + let value = c.get_value().to_string_lossy(); + !DEPRECATED_ARGS.contains(&value.as_ref()) + }) + .collect(); + // Write completions in the appropriate format for the shell let shell_name = shell_name.to_string_lossy(); let ifs = std::env::var("_CLAP_IFS").ok(); diff --git a/tests/integration_tests/completion.rs b/tests/integration_tests/completion.rs index 2c6795280..00ac719c0 100644 --- a/tests/integration_tests/completion.rs +++ b/tests/integration_tests/completion.rs @@ -1147,3 +1147,79 @@ fn test_complete_single_dash_shows_both_short_and_long_flags(repo: TestRepo) { ); } } + +/// Deprecated args should never appear in completions. +/// +/// Args like `--no-background` are deprecated and hidden from help. They should also +/// be hidden from tab completion, even when completing `--` (which shows other hidden args). +#[rstest] +fn test_complete_excludes_deprecated_args(repo: TestRepo) { + repo.commit("initial"); + + // Deprecated args that should never appear + let deprecated = ["--no-background"]; + + for shell in ["bash", "zsh", "fish"] { + // Test: wt remove -- - should NOT show --no-background + let output = repo + .completion_cmd_for_shell(&["wt", "remove", "--"], shell) + .output() + .unwrap(); + assert!(output.status.success(), "{shell}: completion failed"); + let stdout = String::from_utf8_lossy(&output.stdout); + + // Should have regular options + assert!( + stdout.contains("--foreground"), + "{shell}: should show --foreground, got:\n{stdout}" + ); + + // Should NOT have deprecated options + for arg in &deprecated { + assert!( + !stdout.contains(arg), + "{shell}: should NOT show deprecated {arg}, got:\n{stdout}" + ); + } + + // Test: wt hook post-start -- - same behavior + let output = repo + .completion_cmd_for_shell(&["wt", "hook", "post-start", "--"], shell) + .output() + .unwrap(); + assert!(output.status.success(), "{shell}: completion failed"); + let stdout = String::from_utf8_lossy(&output.stdout); + + assert!( + stdout.contains("--foreground"), + "{shell}: hook post-start should show --foreground, got:\n{stdout}" + ); + + for arg in &deprecated { + assert!( + !stdout.contains(arg), + "{shell}: hook post-start should NOT show deprecated {arg}, got:\n{stdout}" + ); + } + + // Test: wt hook post-switch -- - same behavior + let output = repo + .completion_cmd_for_shell(&["wt", "hook", "post-switch", "--"], shell) + .output() + .unwrap(); + assert!(output.status.success(), "{shell}: completion failed"); + let stdout = String::from_utf8_lossy(&output.stdout); + + assert!( + stdout.contains("--foreground"), + "{shell}: hook post-switch should show --foreground, got:\n{stdout}" + ); + + for arg in &deprecated { + assert!( + !stdout.contains(arg), + "{shell}: hook post-switch should NOT show deprecated {arg}, got:\n{stdout}" + ); + } + } +}