diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f27c1687b95..3cc2cb9fa439 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,6 +197,13 @@ jobs: $uv venv $uv pip install ruff + - name: "Smoke test completion" + run: | + uv="./target/debug/uv" + uvx="./target/debug/uvx" + eval "$($uv generate-shell-completion bash)" + eval "$($uvx --generate-shell-completion bash)" + cargo-test-macos: timeout-minutes: 10 needs: determine_changes @@ -296,6 +303,18 @@ jobs: uv venv uv pip install ruff + - name: "Smoke test completion" + working-directory: ${{ env.UV_WORKSPACE }} + shell: powershell + env: + # Avoid debug build stack overflows. + UV_STACK_SIZE: 2000000 + run: | + Set-Alias -Name uv -Value ./target/debug/uv + Set-Alias -Name uvx -Value ./target/debug/uvx + (& uv generate-shell-completion powershell) | Out-String | Invoke-Expression + (& uvx --generate-shell-completion powershell) | Out-String | Invoke-Expression + # Separate jobs for the nightly crate windows-trampoline-check: timeout-minutes: 10 diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index e9515a9e1262..587f0d833049 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -3247,6 +3247,9 @@ pub struct ToolRunArgs { /// By default, environment modifications are omitted, but enabled under `--verbose`. #[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)] pub show_resolution: bool, + + #[arg(long, hide = true)] + pub generate_shell_completion: Option, } #[derive(Args)] diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 80b788ec2578..56e74e3bef03 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -780,30 +780,7 @@ async fn run(cli: Cli) -> Result { Ok(ExitStatus::Success) } Commands::GenerateShellCompletion(args) => { - // uv args.shell.generate(&mut Cli::command(), &mut stdout()); - - // uvx: combine `uv tool uvx` with the top-level arguments - let mut uvx = Cli::command() - .find_subcommand("tool") - .unwrap() - .find_subcommand("uvx") - .unwrap() - .clone() - // Avoid duplicating the `--help` and `--version` flags from the top-level arguments. - .disable_help_flag(true) - .disable_version_flag(true) - .version(env!("CARGO_PKG_VERSION")); - - // Copy the top-level arguments into the `uvx` command. (Like `Args::augment_args`, but - // expanded to skip collisions.) - for arg in TopLevelArgs::command().get_arguments() { - if arg.get_id() != "isolated" { - uvx = uvx.arg(arg); - } - } - args.shell.generate(&mut uvx, &mut stdout()); - Ok(ExitStatus::Success) } Commands::Tool(ToolNamespace { @@ -816,6 +793,30 @@ async fn run(cli: Cli) -> Result { _ => unreachable!(), }; + if let Some(shell) = args.generate_shell_completion { + // uvx: combine `uv tool uvx` with the top-level arguments + let mut uvx = Cli::command() + .find_subcommand("tool") + .unwrap() + .find_subcommand("uvx") + .unwrap() + .clone() + // Avoid duplicating the `--help` and `--version` flags from the top-level arguments. + .disable_help_flag(true) + .disable_version_flag(true) + .version(env!("CARGO_PKG_VERSION")); + + // Copy the top-level arguments into the `uvx` command. (Like `Args::augment_args`, but + // expanded to skip collisions.) + for arg in TopLevelArgs::command().get_arguments() { + if arg.get_id() != "isolated" { + uvx = uvx.arg(arg); + } + } + shell.generate(&mut uvx, &mut stdout()); + return Ok(ExitStatus::Success); + } + // Resolve the settings from the command-line arguments and workspace configuration. let args = settings::ToolRunSettings::resolve(args, filesystem, invocation_source); show_settings!(args); diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index c7d1eb626825..641e780a7f5e 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -319,6 +319,7 @@ impl ToolRunSettings { build, refresh, python, + generate_shell_completion: _, } = args; // If `--upgrade` was passed explicitly, warn. diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 87e530987680..34e81fa34741 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -186,6 +186,24 @@ To enable shell autocompletion for uv commands, run one of the following: Add-Content -Path $PROFILE -Value '(& uv generate-shell-completion powershell) | Out-String | Invoke-Expression' ``` +To enable shell autocompletion for uvx, run one of the following: + +=== "Linux and macOS" + + ```bash + # Determine your shell (e.g., with `echo $SHELL`), then run one of: + echo 'eval "$(uvx --generate-shell-completion bash)"' >> ~/.bashrc + echo 'eval "$(uvx --generate-shell-completion zsh)"' >> ~/.zshrc + echo 'uvx --generate-shell-completion fish | source' >> ~/.config/fish/config.fish + echo 'eval (uvx --generate-shell-completion elvish | slurp)' >> ~/.elvish/rc.elv + ``` + +=== "Windows" + + ```powershell + Add-Content -Path $PROFILE -Value '(& uvx --generate-shell-completion powershell) | Out-String | Invoke-Expression' + ``` + Then restart the shell or source the shell config file. ## Uninstallation