Offer tip when users omits pip prefix (#1257)

## Summary

Open to other opinions here. We could just continue (and warn), prompt
the user with a confirmation, etc.

(The weird thing about those two options is we might need to validate
the command-line arguments _before_ we do that -- so you could get
errors for bad arguments, and then get a warning that your subcommand is
wrong. I can probably avoid that with more work if it feels like a
better out come though.)

Closes https://github.com/astral-sh/puffin/issues/1256.
This commit is contained in:
Charlie Marsh 2024-02-06 11:25:07 -08:00 committed by GitHub
parent 62416286e2
commit 91118a962a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 1 deletions

View File

@ -6,6 +6,7 @@ use std::str::FromStr;
use anstream::eprintln;
use anyhow::Result;
use chrono::{DateTime, Days, NaiveDate, NaiveTime, Utc};
use clap::error::{ContextKind, ContextValue};
use clap::{Args, Parser, Subcommand};
use owo_colors::OwoColorize;
use tracing::instrument;
@ -614,7 +615,48 @@ struct RemoveArgs {
#[instrument] // Anchor span to check for overhead
async fn run() -> Result<ExitStatus> {
let cli = Cli::parse();
let cli = match Cli::try_parse() {
Ok(cli) => cli,
Err(mut err) => {
if let Some(ContextValue::String(subcommand)) = err.get(ContextKind::InvalidSubcommand)
{
match subcommand.as_str() {
"compile" | "lock" => {
err.insert(
ContextKind::SuggestedSubcommand,
ContextValue::String("puffin pip compile".to_string()),
);
}
"sync" => {
err.insert(
ContextKind::SuggestedSubcommand,
ContextValue::String("puffin pip sync".to_string()),
);
}
"install" | "add" => {
err.insert(
ContextKind::SuggestedSubcommand,
ContextValue::String("puffin pip install".to_string()),
);
}
"uninstall" | "remove" => {
err.insert(
ContextKind::SuggestedSubcommand,
ContextValue::String("puffin pip uninstall".to_string()),
);
}
"freeze" => {
err.insert(
ContextKind::SuggestedSubcommand,
ContextValue::String("puffin pip freeze".to_string()),
);
}
_ => {}
}
}
err.exit()
}
};
// Configure the `tracing` crate, which controls internal logging.
#[cfg(feature = "tracing-durations-export")]

View File

@ -55,6 +55,24 @@ fn uninstall_command(context: &TestContext) -> Command {
command
}
#[test]
fn missing_pip() {
puffin_snapshot!(Command::new(get_bin()).arg("sync"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: unrecognized subcommand 'sync'
tip: a similar subcommand exists: 'puffin pip sync'
Usage: puffin [OPTIONS] <COMMAND>
For more information, try '--help'.
"###);
}
#[test]
fn missing_requirements_txt() {
let context = TestContext::new("3.12");