Skip to content

Commit

Permalink
Use paging for uv help display when available (#4909)
Browse files Browse the repository at this point in the history
Extends #4906

Adds paged display of "long' help to `uv help` invocations when `less`
or `more` is available.
  • Loading branch information
zanieb authored Jul 9, 2024
1 parent 8da91f5 commit bd7a25f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/uv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
49 changes: 46 additions & 3 deletions crates/uv/src/commands/help.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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)
}
Expand All @@ -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(())
}
16 changes: 8 additions & 8 deletions crates/uv/tests/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ fn help() {
success: true
exit_code: 0
----- stdout -----
----- stderr -----
An extremely fast Python package manager.
Usage: uv [OPTIONS] <COMMAND>
Expand Down Expand Up @@ -109,6 +107,8 @@ fn help() {
-V, --version
Print version
----- stderr -----
"###);
}

Expand Down Expand Up @@ -230,8 +230,6 @@ fn help_subcommand() {
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Manage Python installations
Usage: uv python [OPTIONS] <COMMAND>
Expand Down Expand Up @@ -326,6 +324,8 @@ fn help_subcommand() {
-V, --version
Print version
----- stderr -----
"###);
}

Expand All @@ -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]...
Expand Down Expand Up @@ -437,6 +435,8 @@ fn help_subsubcommand() {
-V, --version
Print version
----- stderr -----
"###);
}

Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -704,6 +702,8 @@ fn help_with_global_option() {
-V, --version
Print version
----- stderr -----
"###);
}

Expand Down

0 comments on commit bd7a25f

Please sign in to comment.