|
1 | | -use std::collections::hash_map::Entry; |
2 | | -use std::fmt::Write; |
3 | | -use std::path::{Path, PathBuf}; |
4 | | - |
5 | 1 | use anyhow::{bail, Context, Result}; |
| 2 | +use console::Term; |
6 | 3 | use itertools::Itertools; |
7 | 4 | use owo_colors::OwoColorize; |
8 | 5 | use rustc_hash::{FxBuildHasher, FxHashMap}; |
| 6 | +use std::collections::hash_map::Entry; |
| 7 | +use std::fmt::Write; |
| 8 | +use std::path::{Path, PathBuf}; |
| 9 | +use std::str::FromStr; |
| 10 | +use std::sync::LazyLock; |
9 | 11 | use tracing::debug; |
10 | 12 |
|
11 | 13 | use cache_key::RepositoryUrl; |
@@ -48,6 +50,18 @@ use crate::commands::{pip, project, ExitStatus, SharedState}; |
48 | 50 | use crate::printer::Printer; |
49 | 51 | use crate::settings::{ResolverInstallerSettings, ResolverInstallerSettingsRef}; |
50 | 52 |
|
| 53 | +static CORRECTIONS: LazyLock<FxHashMap<PackageName, PackageName>> = LazyLock::new(|| { |
| 54 | + [("dotenv", "python-dotenv"), ("sklearn", "scikit-learn")] |
| 55 | + .iter() |
| 56 | + .map(|(k, v)| { |
| 57 | + ( |
| 58 | + PackageName::from_str(k).unwrap(), |
| 59 | + PackageName::from_str(v).unwrap(), |
| 60 | + ) |
| 61 | + }) |
| 62 | + .collect() |
| 63 | +}); |
| 64 | + |
51 | 65 | /// Add one or more packages to the project requirements. |
52 | 66 | #[allow(clippy::fn_params_excessive_bools)] |
53 | 67 | pub(crate) async fn add( |
@@ -371,6 +385,23 @@ pub(crate) async fn add( |
371 | 385 | }?; |
372 | 386 | let mut edits = Vec::<DependencyEdit>::with_capacity(requirements.len()); |
373 | 387 | for mut requirement in requirements { |
| 388 | + // If the user requested a package that is often confused for another package, prompt them. |
| 389 | + if let Some(correction) = CORRECTIONS.get(&requirement.name) { |
| 390 | + let term = Term::stderr(); |
| 391 | + if term.is_term() { |
| 392 | + let prompt = format!( |
| 393 | + "`{}` is often confused for `{}`. Did you mean `{}`?", |
| 394 | + requirement.name.cyan(), |
| 395 | + correction.cyan(), |
| 396 | + format!("uv add {correction}").green() |
| 397 | + ); |
| 398 | + let confirmation = uv_console::confirm(&prompt, &term, true)?; |
| 399 | + if confirmation { |
| 400 | + requirement.name = correction.clone(); |
| 401 | + } |
| 402 | + } |
| 403 | + } |
| 404 | + |
374 | 405 | // Add the specified extras. |
375 | 406 | requirement.extras.extend(extras.iter().cloned()); |
376 | 407 | requirement.extras.sort_unstable(); |
|
0 commit comments