Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tree): Control --charset via auto-detecting config value #13337

Merged
merged 5 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ unicase.workspace = true
unicode-width.workspace = true
url.workspace = true
walkdir.workspace = true
supports-unicode = "2.1.0"

[target.'cfg(target_has_atomic = "64")'.dependencies]
tracing-chrome.workspace = true
Expand Down
35 changes: 30 additions & 5 deletions src/bin/cargo/commands/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ pub fn cli() -> Command {
.arg(
opt("charset", "Character set to use in output")
.value_name("CHARSET")
.value_parser(["utf8", "ascii"])
.default_value("utf8"),
.value_parser(["utf8", "ascii"]),
)
.arg(
opt("format", "Format string used for printing dependencies")
Expand Down Expand Up @@ -101,6 +100,24 @@ pub fn cli() -> Command {
))
}

#[derive(Copy, Clone)]
pub enum Charset {
Utf8,
Ascii,
}

impl FromStr for Charset {
type Err = &'static str;

fn from_str(s: &str) -> Result<Charset, &'static str> {
match s {
"utf8" => Ok(Charset::Utf8),
"ascii" => Ok(Charset::Ascii),
_ => Err("invalid charset"),
}
}
}

pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
if args.flag("version") {
let verbose = args.verbose() > 0;
Expand Down Expand Up @@ -181,8 +198,17 @@ subtree of the package given to -p.\n\
print_available_packages(&ws)?;
}

let charset = tree::Charset::from_str(args.get_one::<String>("charset").unwrap())
.map_err(|e| anyhow::anyhow!("{}", e))?;
let charset = args.get_one::<String>("charset");
if let Some(charset) = charset
.map(|c| Charset::from_str(c))
.transpose()
.map_err(|e| anyhow::anyhow!("{}", e))?
{
match charset {
Charset::Utf8 => gctx.shell().set_unicode(true)?,
Charset::Ascii => gctx.shell().set_unicode(false)?,
}
}
let opts = tree::TreeOptions {
cli_features: args.cli_features()?,
packages,
Expand All @@ -193,7 +219,6 @@ subtree of the package given to -p.\n\
prefix,
no_dedupe,
duplicates: args.flag("duplicates"),
charset,
format: args.get_one::<String>("format").cloned().unwrap(),
graph_features,
max_display_depth: args.value_of_u32("depth")?.unwrap_or(u32::MAX),
Expand Down
58 changes: 45 additions & 13 deletions src/cargo/core/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ impl Shell {
color_choice: auto_clr,
hyperlinks: supports_hyperlinks(),
stderr_tty: std::io::stderr().is_terminal(),
stdout_unicode: supports_unicode(&std::io::stdout()),
stderr_unicode: supports_unicode(&std::io::stderr()),
},
verbosity: Verbosity::Verbose,
needs_clear: false,
Expand Down Expand Up @@ -230,11 +232,11 @@ impl Shell {
/// Updates the color choice (always, never, or auto) from a string..
pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
if let ShellOut::Stream {
ref mut stdout,
ref mut stderr,
ref mut color_choice,
stdout,
stderr,
color_choice,
..
} = self.output
} = &mut self.output
{
let cfg = color
.map(|c| c.parse())
Expand All @@ -249,16 +251,40 @@ impl Shell {
Ok(())
}

pub fn set_hyperlinks(&mut self, yes: bool) -> CargoResult<()> {
pub fn set_unicode(&mut self, yes: bool) -> CargoResult<()> {
if let ShellOut::Stream {
ref mut hyperlinks, ..
} = self.output
stdout_unicode,
stderr_unicode,
..
} = &mut self.output
{
*stdout_unicode = yes;
*stderr_unicode = yes;
}
Ok(())
}

pub fn set_hyperlinks(&mut self, yes: bool) -> CargoResult<()> {
if let ShellOut::Stream { hyperlinks, .. } = &mut self.output {
*hyperlinks = yes;
}
Ok(())
}

pub fn out_unicode(&self) -> bool {
match &self.output {
ShellOut::Write(_) => true,
ShellOut::Stream { stdout_unicode, .. } => *stdout_unicode,
}
}

pub fn err_unicode(&self) -> bool {
match &self.output {
ShellOut::Write(_) => true,
ShellOut::Stream { stderr_unicode, .. } => *stderr_unicode,
}
}

/// Gets the current color choice.
///
/// If we are not using a color stream, this will always return `Never`, even if the color
Expand Down Expand Up @@ -384,6 +410,8 @@ enum ShellOut {
stderr_tty: bool,
color_choice: ColorChoice,
hyperlinks: bool,
stdout_unicode: bool,
stderr_unicode: bool,
},
}

Expand Down Expand Up @@ -416,17 +444,17 @@ impl ShellOut {

/// Gets stdout as a `io::Write`.
fn stdout(&mut self) -> &mut dyn Write {
match *self {
ShellOut::Stream { ref mut stdout, .. } => stdout,
ShellOut::Write(ref mut w) => w,
match self {
ShellOut::Stream { stdout, .. } => stdout,
ShellOut::Write(w) => w,
}
}

/// Gets stderr as a `io::Write`.
fn stderr(&mut self) -> &mut dyn Write {
match *self {
ShellOut::Stream { ref mut stderr, .. } => stderr,
ShellOut::Write(ref mut w) => w,
match self {
ShellOut::Stream { stderr, .. } => stderr,
ShellOut::Write(w) => w,
}
}
}
Expand Down Expand Up @@ -519,6 +547,10 @@ fn supports_color(choice: anstream::ColorChoice) -> bool {
}
}

fn supports_unicode(stream: &dyn IsTerminal) -> bool {
!stream.is_terminal() || supports_unicode::supports_unicode()
}

fn supports_hyperlinks() -> bool {
#[allow(clippy::disallowed_methods)] // We are reading the state of the system, not config
if std::env::var_os("TERM_PROGRAM").as_deref() == Some(std::ffi::OsStr::new("iTerm.app")) {
Expand Down
26 changes: 4 additions & 22 deletions src/cargo/ops/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ pub struct TreeOptions {
/// appear with different versions, and report if any where found. Implies
/// `invert`.
pub duplicates: bool,
/// The style of characters to use.
pub charset: Charset,
/// A format string indicating how each package should be displayed.
pub format: String,
/// Includes features in the tree as separate nodes.
Expand Down Expand Up @@ -68,23 +66,6 @@ impl Target {
}
}

pub enum Charset {
Utf8,
Ascii,
}

impl FromStr for Charset {
type Err = &'static str;

fn from_str(s: &str) -> Result<Charset, &'static str> {
match s {
"utf8" => Ok(Charset::Utf8),
"ascii" => Ok(Charset::Ascii),
_ => Err("invalid charset"),
}
}
}

#[derive(Clone, Copy)]
pub enum Prefix {
None,
Expand Down Expand Up @@ -236,9 +217,10 @@ fn print(
let format = Pattern::new(&opts.format)
.with_context(|| format!("tree format `{}` not valid", opts.format))?;

let symbols = match opts.charset {
Charset::Utf8 => &UTF8_SYMBOLS,
Charset::Ascii => &ASCII_SYMBOLS,
let symbols = if gctx.shell().out_unicode() {
&UTF8_SYMBOLS
} else {
&ASCII_SYMBOLS
};

// The visited deps is used to display a (*) whenever a dep has
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,9 @@ impl GlobalContext {
if let Some(hyperlinks) = term.hyperlinks {
self.shell().set_hyperlinks(hyperlinks)?;
}
if let Some(unicode) = term.unicode {
self.shell().set_unicode(unicode)?;
}

self.progress_config = term.progress.unwrap_or_default();

Expand Down Expand Up @@ -2646,6 +2649,7 @@ pub struct TermConfig {
pub quiet: Option<bool>,
pub color: Option<String>,
pub hyperlinks: Option<bool>,
pub unicode: Option<bool>,
#[serde(default)]
#[serde(deserialize_with = "progress_or_string")]
pub progress: Option<ProgressConfig>,
Expand Down
2 changes: 1 addition & 1 deletion src/doc/man/cargo-tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ The default is the host platform. Use the value `all` to include *all* targets.

{{#option "`--charset` _charset_" }}
Chooses the character set to use for the tree. Valid values are "utf8" or
"ascii". Default is "utf8".
"ascii". When unspecified, cargo will auto-select a value.
{{/option}}

{{#option "`-f` _format_" "`--format` _format_" }}
Expand Down
3 changes: 2 additions & 1 deletion src/doc/man/generated_txt/cargo-tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ OPTIONS
Tree Formatting Options
--charset charset
Chooses the character set to use for the tree. Valid values are
“utf8” or “ascii”. Default is “utf8”.
“utf8” or “ascii”. When unspecified, cargo will auto-select
a value.

-f format, --format format
Set the format string for each package. The default is “{p}”.
Expand Down
2 changes: 1 addition & 1 deletion src/doc/src/commands/cargo-tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ The default is the host platform. Use the value <code>all</code> to include <em>

<dt class="option-term" id="option-cargo-tree---charset"><a class="option-anchor" href="#option-cargo-tree---charset"></a><code>--charset</code> <em>charset</em></dt>
<dd class="option-desc">Chooses the character set to use for the tree. Valid values are “utf8” or
“ascii”. Default is “utf8”.</dd>
“ascii”. When unspecified, cargo will auto-select a value.</dd>


<dt class="option-term" id="option-cargo-tree--f"><a class="option-anchor" href="#option-cargo-tree--f"></a><code>-f</code> <em>format</em></dt>
Expand Down
8 changes: 8 additions & 0 deletions src/doc/src/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ quiet = false # whether cargo output is quiet
verbose = false # whether cargo provides verbose output
color = 'auto' # whether cargo colorizes output
hyperlinks = true # whether cargo inserts links into output
unicode = true # whether cargo can render output using non-ASCII unicode characters
progress.when = 'auto' # whether cargo shows progress bar
progress.width = 80 # width of progress bar
```
Expand Down Expand Up @@ -1298,6 +1299,13 @@ Can be overridden with the `--color` command-line option.

Controls whether or not hyperlinks are used in the terminal.

#### `term.unicode`
* Type: bool
* Default: auto-detect
* Environment: `CARGO_TERM_UNICODE`

Control whether output can be rendered using non-ASCII unicode characters.

#### `term.progress.when`
* Type: string
* Default: "auto"
Expand Down
2 changes: 1 addition & 1 deletion src/etc/man/cargo-tree.1
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ The default is the host platform. Use the value \fBall\fR to include \fIall\fR t
\fB\-\-charset\fR \fIcharset\fR
.RS 4
Chooses the character set to use for the tree. Valid values are \[lq]utf8\[rq] or
\[lq]ascii\[rq]\&. Default is \[lq]utf8\[rq]\&.
\[lq]ascii\[rq]\&. When unspecified, cargo will auto\-select a value.
.RE
.sp
\fB\-f\fR \fIformat\fR,
Expand Down
Loading