Skip to content

Commit

Permalink
Generate shell completion for uvx
Browse files Browse the repository at this point in the history
Create a dummy uvx top level command by grabbing the `uv tool uvx`
subcommand (hidden alias of `uv tool run`).

Global arguments need to be added to this dummy top level command; this
is accomplished by splitting Cli into subcommands and top level
arguments: then top level arguments can be added onto the dummy uvx top
level.
  • Loading branch information
bluss committed Sep 14, 2024
1 parent a4a1982 commit fbc91b9
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
10 changes: 10 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ pub struct Cli {
#[command(subcommand)]
pub command: Box<Commands>,

#[command(flatten)]
pub top_level: TopLevelArgs,
}

#[derive(Parser)]
#[command(
disable_help_flag = true,
disable_version_flag = true
)]
pub struct TopLevelArgs {
#[command(flatten)]
pub cache_args: Box<CacheArgs>,

Expand Down
38 changes: 25 additions & 13 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::process::ExitCode;
use anstream::eprintln;
use anyhow::Result;
use clap::error::{ContextKind, ContextValue};
use clap::{CommandFactory, Parser};
use clap::{Args, CommandFactory, Parser};
use owo_colors::OwoColorize;
use settings::PipTreeSettings;
use tracing::{debug, instrument};
Expand All @@ -16,7 +16,7 @@ use uv_cli::{
compat::CompatArgs, CacheCommand, CacheNamespace, Cli, Commands, PipCommand, PipNamespace,
ProjectCommand,
};
use uv_cli::{PythonCommand, PythonNamespace, ToolCommand, ToolNamespace};
use uv_cli::{PythonCommand, PythonNamespace, ToolCommand, ToolNamespace, TopLevelArgs};
#[cfg(feature = "self-update")]
use uv_cli::{SelfCommand, SelfNamespace, SelfUpdateArgs};
use uv_fs::CWD;
Expand Down Expand Up @@ -58,12 +58,12 @@ pub(crate) mod version;
#[instrument(skip_all)]
async fn run(cli: Cli) -> Result<ExitStatus> {
// Enable flag to pick up warnings generated by workspace loading.
if !cli.global_args.quiet {
if !cli.top_level.global_args.quiet {
uv_warnings::enable();
}

// Switch directories as early as possible.
if let Some(directory) = cli.global_args.directory.as_ref() {
if let Some(directory) = cli.top_level.global_args.directory.as_ref() {
std::env::set_current_dir(directory)?;
}

Expand Down Expand Up @@ -106,15 +106,15 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
// If found, this file is combined with the user configuration file.
// 3. The nearest configuration file (`uv.toml` or `pyproject.toml`) in the directory tree,
// starting from the current directory.
let filesystem = if let Some(config_file) = cli.config_file.as_ref() {
let filesystem = if let Some(config_file) = cli.top_level.config_file.as_ref() {
if config_file
.file_name()
.is_some_and(|file_name| file_name == "pyproject.toml")
{
warn_user!("The `--config-file` argument expects to receive a `uv.toml` file, not a `pyproject.toml`. If you're trying to run a command from another project, use the `--directory` argument instead.");
}
Some(FilesystemOptions::from_file(config_file)?)
} else if deprecated_isolated || cli.no_config {
} else if deprecated_isolated || cli.top_level.no_config {
None
} else if matches!(&*cli.command, Commands::Tool(_)) {
// For commands that operate at the user-level, ignore local configuration.
Expand Down Expand Up @@ -175,10 +175,10 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
.combine(filesystem);

// Resolve the global settings.
let globals = GlobalSettings::resolve(&cli.global_args, filesystem.as_ref());
let globals = GlobalSettings::resolve(&cli.top_level.global_args, filesystem.as_ref());

// Resolve the cache settings.
let cache_settings = CacheSettings::resolve(*cli.cache_args, filesystem.as_ref());
let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());

// Configure the `tracing` crate, which controls internal logging.
#[cfg(feature = "tracing-durations-export")]
Expand Down Expand Up @@ -687,7 +687,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
args.hash_checking,
args.python,
args.settings,
cli.no_config,
cli.top_level.no_config,
globals.python_preference,
globals.python_downloads,
globals.connectivity,
Expand Down Expand Up @@ -743,7 +743,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
args.settings.exclude_newer,
globals.concurrency,
globals.native_tls,
cli.no_config,
cli.top_level.no_config,
args.no_project,
&cache,
printer,
Expand All @@ -757,7 +757,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
run_command,
script,
globals,
cli.no_config,
cli.top_level.no_config,
filesystem,
cache,
printer,
Expand All @@ -778,6 +778,18 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
}
Commands::GenerateShellCompletion(args) => {
args.shell.generate(&mut Cli::command(), &mut stdout());

// Create uvx as a combination of top level arguments and the uv tool uvx subcommand
let mut uvx = Cli::command()
.find_subcommand("tool")
.unwrap()
.find_subcommand("uvx")
.unwrap()
.clone();
uvx = TopLevelArgs::augment_args(uvx);
uvx = uvx.version("dummy_for_completion");
args.shell.generate(&mut uvx, &mut stdout());

Ok(ExitStatus::Success)
}
Commands::Tool(ToolNamespace {
Expand Down Expand Up @@ -974,7 +986,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
globals.python_downloads,
globals.native_tls,
globals.connectivity,
cli.no_config,
cli.top_level.no_config,
printer,
)
.await
Expand All @@ -1000,7 +1012,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
commands::python_find(
args.request,
args.no_project,
cli.no_config,
cli.top_level.no_config,
args.system,
globals.python_preference,
&cache,
Expand Down

0 comments on commit fbc91b9

Please sign in to comment.