Skip to content

Commit

Permalink
refactor(shell): Move tree's unicode detection to shell
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jan 22, 2024
1 parent 0142b6c commit e83d006
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 33 deletions.
21 changes: 8 additions & 13 deletions src/bin/cargo/commands/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use crate::cli;
use crate::command_prelude::*;
use anyhow::{bail, format_err};
use cargo::core::dependency::DepKind;
use cargo::core::shell::Charset;
use cargo::ops::tree::{self, EdgeKind};
use cargo::ops::Packages;
use cargo::util::print_available_packages;
use cargo::util::CargoResult;
use std::collections::HashSet;
use std::io::IsTerminal as _;
use std::str::FromStr;

pub fn cli() -> Command {
Expand Down Expand Up @@ -184,18 +184,14 @@ subtree of the package given to -p.\n\
print_available_packages(&ws)?;
}

let charset = args.get_one::<String>("charset");
let charset = charset
.map(|c| tree::Charset::from_str(c))
if let Some(charset) = args
.get_one::<String>("charset")
.map(|c| Charset::from_str(c))
.transpose()
.map_err(|e| anyhow::anyhow!("{}", e))?;
let charset = charset.unwrap_or_else(|| {
if supports_unicode::supports_unicode() || !std::io::stdout().is_terminal() {
tree::Charset::Utf8
} else {
tree::Charset::Ascii
}
});
.map_err(|e| anyhow::anyhow!("{}", e))?
{
config.shell().set_charset(charset)?;
}
let opts = tree::TreeOptions {
cli_features: args.cli_features()?,
packages,
Expand All @@ -206,7 +202,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
59 changes: 59 additions & 0 deletions src/cargo/core/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ impl TtyWidth {
}
}

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

impl Charset {
fn auto_with(stream: &dyn IsTerminal) -> Self {
if !stream.is_terminal() || supports_unicode::supports_unicode() {
Self::Utf8
} else {
Self::Ascii
}
}
}

impl std::str::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"),
}
}
}

/// The requested verbosity of output.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
Expand Down Expand Up @@ -88,6 +116,8 @@ enum ShellOut {
stderr_tty: bool,
color_choice: ColorChoice,
hyperlinks: bool,
stdout_charset: Charset,
stderr_charset: Charset,
},
}

Expand Down Expand Up @@ -115,6 +145,8 @@ impl Shell {
stderr: AutoStream::new(std::io::stderr(), stderr_choice),
color_choice: auto_clr,
hyperlinks: supports_hyperlinks(),
stdout_charset: Charset::auto_with(&std::io::stdout()),
stderr_charset: Charset::auto_with(&std::io::stderr()),
stderr_tty: std::io::stderr().is_terminal(),
},
verbosity: Verbosity::Verbose,
Expand Down Expand Up @@ -330,6 +362,33 @@ impl Shell {
Ok(())
}

pub fn set_charset(&mut self, charset: Charset) -> CargoResult<()> {
if let ShellOut::Stream {
ref mut stdout_charset,
ref mut stderr_charset,
..
} = self.output
{
*stdout_charset = charset;
*stderr_charset = charset;
}
Ok(())
}

pub fn out_charset(&self) -> Charset {
match &self.output {
ShellOut::Write(_) => Charset::Utf8,
ShellOut::Stream { stdout_charset, .. } => *stdout_charset,
}
}

pub fn err_charset(&self) -> Charset {
match &self.output {
ShellOut::Write(_) => Charset::Utf8,
ShellOut::Stream { stderr_charset, .. } => *stderr_charset,
}
}

/// Gets the current color choice.
///
/// If we are not using a color stream, this will always return `Never`, even if the color
Expand Down
22 changes: 2 additions & 20 deletions src/cargo/ops/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use self::format::Pattern;
use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::resolver::{features::CliFeatures, ForceAllTargets, HasDevUnits};
use crate::core::shell::Charset;
use crate::core::{Package, PackageId, PackageIdSpec, PackageIdSpecQuery, Workspace};
use crate::ops::{self, Packages};
use crate::util::{CargoResult, Config};
Expand Down Expand Up @@ -39,8 +40,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 +67,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 @@ -238,7 +220,7 @@ fn print(
let format = Pattern::new(&opts.format)
.with_context(|| format!("tree format `{}` not valid", opts.format))?;

let symbols = match opts.charset {
let symbols = match config.shell().out_charset() {
Charset::Utf8 => &UTF8_SYMBOLS,
Charset::Ascii => &ASCII_SYMBOLS,
};
Expand Down

0 comments on commit e83d006

Please sign in to comment.