mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Use paging for uv help
display when available (#4909)
Extends https://github.com/astral-sh/uv/pull/4906 Adds paged display of "long' help to `uv help` invocations when `less` or `more` is available.
This commit is contained in:
parent
8da91f5a97
commit
bd7a25f604
4 changed files with 56 additions and 11 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4507,6 +4507,7 @@ dependencies = [
|
|||
"uv-types",
|
||||
"uv-virtualenv",
|
||||
"uv-warnings",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -70,6 +70,7 @@ tracing-subscriber = { workspace = true, features = ["json"] }
|
|||
tracing-tree = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
url = { workspace = true }
|
||||
which = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
mimalloc = { version = "0.1.39" }
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::fmt::Write;
|
||||
use std::{fmt::Display, fmt::Write};
|
||||
|
||||
use anstream::{stream::IsTerminal, ColorChoice};
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::CommandFactory;
|
||||
use itertools::Itertools;
|
||||
use itertools::{Either, Itertools};
|
||||
use which::which;
|
||||
|
||||
use super::ExitStatus;
|
||||
use crate::printer::Printer;
|
||||
|
@ -35,7 +37,25 @@ pub(crate) fn help(query: &[String], printer: Printer) -> Result<ExitStatus> {
|
|||
|
||||
let mut command = command.clone();
|
||||
let help = command.render_long_help();
|
||||
writeln!(printer.stderr(), "{}", help.ansi())?;
|
||||
|
||||
let help_ansi = match anstream::Stdout::choice(&std::io::stdout()) {
|
||||
ColorChoice::Always | ColorChoice::AlwaysAnsi => Either::Left(help.ansi()),
|
||||
ColorChoice::Never => Either::Right(help.clone()),
|
||||
// We just asked anstream for a choice, that can't be auto
|
||||
ColorChoice::Auto => unreachable!(),
|
||||
};
|
||||
|
||||
let is_terminal = std::io::stdout().is_terminal();
|
||||
if is_terminal && which("less").is_ok() {
|
||||
// When using less, we use the command name as the file name and can support colors
|
||||
let prompt = format!("help: uv {}", query.join(" "));
|
||||
spawn_pager("less", &["-R", "-P", &prompt], &help_ansi)?;
|
||||
} else if is_terminal && which("more").is_ok() {
|
||||
// When using more, we skip the ANSI color codes
|
||||
spawn_pager("more", &[], &help)?;
|
||||
} else {
|
||||
writeln!(printer.stdout(), "{help_ansi}")?;
|
||||
}
|
||||
|
||||
Ok(ExitStatus::Success)
|
||||
}
|
||||
|
@ -54,3 +74,26 @@ fn find_command<'a>(
|
|||
let subcommand = cmd.find_subcommand(next).ok_or((query, cmd))?;
|
||||
find_command(&query[1..], subcommand)
|
||||
}
|
||||
|
||||
/// Spawn a paging command to display contents.
|
||||
fn spawn_pager(command: &str, args: &[&str], contents: impl Display) -> Result<()> {
|
||||
use std::io::Write;
|
||||
|
||||
let mut child = std::process::Command::new(command)
|
||||
.args(args)
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
let mut stdin = child
|
||||
.stdin
|
||||
.take()
|
||||
.ok_or_else(|| anyhow!("Failed to take child process stdin"))?;
|
||||
|
||||
let contents = contents.to_string();
|
||||
let writer = std::thread::spawn(move || stdin.write_all(contents.as_bytes()));
|
||||
|
||||
drop(child.wait());
|
||||
drop(writer.join());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ fn help() {
|
|||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
An extremely fast Python package manager.
|
||||
|
||||
Usage: uv [OPTIONS] <COMMAND>
|
||||
|
@ -109,6 +107,8 @@ fn help() {
|
|||
-V, --version
|
||||
Print version
|
||||
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
||||
|
@ -230,8 +230,6 @@ fn help_subcommand() {
|
|||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Manage Python installations
|
||||
|
||||
Usage: uv python [OPTIONS] <COMMAND>
|
||||
|
@ -326,6 +324,8 @@ fn help_subcommand() {
|
|||
-V, --version
|
||||
Print version
|
||||
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
||||
|
@ -337,8 +337,6 @@ fn help_subsubcommand() {
|
|||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Download and install Python versions
|
||||
|
||||
Usage: uv python install [OPTIONS] [TARGETS]...
|
||||
|
@ -437,6 +435,8 @@ fn help_subsubcommand() {
|
|||
-V, --version
|
||||
Print version
|
||||
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
||||
|
@ -606,8 +606,6 @@ fn help_with_global_option() {
|
|||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
An extremely fast Python package manager.
|
||||
|
||||
Usage: uv [OPTIONS] <COMMAND>
|
||||
|
@ -704,6 +702,8 @@ fn help_with_global_option() {
|
|||
-V, --version
|
||||
Print version
|
||||
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue