Move uvx shell completion to uvx --generate-shell-completion (#7511)

## Summary

Because a problem was found with Powershell and combining the generated
completion scripts for uv and uvx, let's try separating uv and uvx
command completion scripts.

The generated powershell script template can be seen in clap_complete
source, and it starts with `using` directives, which makes it impossible
(apparently) to concatenate two of those script outputs.

As a side effect, this is available under `uv tool run
--generate-shell-completion` too.

Fixes #7482

## Test Plan

- `eval "$(cargo run --bin uvx -- --generate-shell-completion bash)"`
- Test Powershell
This commit is contained in:
bluss 2024-09-20 03:27:25 +02:00 committed by GitHub
parent 99d354b893
commit 7a25a82fc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 65 additions and 23 deletions

View File

@ -197,6 +197,13 @@ jobs:
$uv venv $uv venv
$uv pip install ruff $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: cargo-test-macos:
timeout-minutes: 10 timeout-minutes: 10
needs: determine_changes needs: determine_changes
@ -296,6 +303,18 @@ jobs:
uv venv uv venv
uv pip install ruff 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 # Separate jobs for the nightly crate
windows-trampoline-check: windows-trampoline-check:
timeout-minutes: 10 timeout-minutes: 10

View File

@ -3247,6 +3247,9 @@ pub struct ToolRunArgs {
/// By default, environment modifications are omitted, but enabled under `--verbose`. /// By default, environment modifications are omitted, but enabled under `--verbose`.
#[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)] #[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
pub show_resolution: bool, pub show_resolution: bool,
#[arg(long, hide = true)]
pub generate_shell_completion: Option<clap_complete_command::Shell>,
} }
#[derive(Args)] #[derive(Args)]

View File

@ -780,9 +780,20 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
Ok(ExitStatus::Success) Ok(ExitStatus::Success)
} }
Commands::GenerateShellCompletion(args) => { Commands::GenerateShellCompletion(args) => {
// uv
args.shell.generate(&mut Cli::command(), &mut stdout()); args.shell.generate(&mut Cli::command(), &mut stdout());
Ok(ExitStatus::Success)
}
Commands::Tool(ToolNamespace {
command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
}) => {
let (args, invocation_source) = match run_variant {
ToolCommand::Uvx(args) => (args, ToolRunCommand::Uvx),
ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
// OK guarded by the outer match statement
_ => unreachable!(),
};
if let Some(shell) = args.generate_shell_completion {
// uvx: combine `uv tool uvx` with the top-level arguments // uvx: combine `uv tool uvx` with the top-level arguments
let mut uvx = Cli::command() let mut uvx = Cli::command()
.find_subcommand("tool") .find_subcommand("tool")
@ -802,19 +813,9 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
uvx = uvx.arg(arg); uvx = uvx.arg(arg);
} }
} }
args.shell.generate(&mut uvx, &mut stdout()); shell.generate(&mut uvx, &mut stdout());
return Ok(ExitStatus::Success);
Ok(ExitStatus::Success)
} }
Commands::Tool(ToolNamespace {
command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
}) => {
let (args, invocation_source) = match run_variant {
ToolCommand::Uvx(args) => (args, ToolRunCommand::Uvx),
ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
// OK guarded by the outer match statement
_ => unreachable!(),
};
// Resolve the settings from the command-line arguments and workspace configuration. // Resolve the settings from the command-line arguments and workspace configuration.
let args = settings::ToolRunSettings::resolve(args, filesystem, invocation_source); let args = settings::ToolRunSettings::resolve(args, filesystem, invocation_source);

View File

@ -319,6 +319,7 @@ impl ToolRunSettings {
build, build,
refresh, refresh,
python, python,
generate_shell_completion: _,
} = args; } = args;
// If `--upgrade` was passed explicitly, warn. // If `--upgrade` was passed explicitly, warn.

View File

@ -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' 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. Then restart the shell or source the shell config file.
## Uninstallation ## Uninstallation