Skip to content

Commit

Permalink
make it easier to fix colors in the future
Browse files Browse the repository at this point in the history
  • Loading branch information
museun committed May 28, 2020
1 parent 62d4d26 commit 8026f8b
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 56 deletions.
187 changes: 140 additions & 47 deletions src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use deps::{GroupedDeps, SortedDeps};
mod tree;
use tree::{Node, Printer as _};

mod theme;
use theme::Theme;

/// When to show yanked crates
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum YankStatus {
Expand All @@ -40,12 +43,16 @@ impl Default for YankStatus {
/// Output for the program
pub struct Printer<'a, W: ?Sized> {
writer: &'a mut W,
theme: Theme,
}

impl<'a, W: Write + ?Sized> Printer<'a, W> {
/// Create a new printer with this writer
pub fn new(writer: &'a mut W) -> Self {
Self { writer }
Self {
writer,
theme: Theme::default(),
}
}

/// Write out all of the versions, filtered by the `YankStatus`
Expand All @@ -66,21 +73,16 @@ impl<'a, W: Write + ?Sized> Printer<'a, W> {

YankStatus::Only if !*yanked => continue,
YankStatus::Only => {
write!(self.writer, "{}: ", Paint::red("yanked"))?;
write!(self.writer, "{}: ", self.theme.yanked.paint(labels::YANKED))?;
}

YankStatus::Include if *yanked => {
write!(self.writer, "{}: ", Paint::red("yanked"))?
write!(self.writer, "{}: ", self.theme.yanked.paint(labels::YANKED))?
}
YankStatus::Include => {}
}

writeln!(
self.writer,
"{}/{}",
Paint::white(name),
Paint::yellow(&version)
)?
self.write_latest(&name, &version)?
}
Ok(())
}
Expand All @@ -90,8 +92,8 @@ impl<'a, W: Write + ?Sized> Printer<'a, W> {
writeln!(
self.writer,
"{}/{}",
Paint::white(&name),
Paint::yellow(&version)
self.theme.name.paint(&name),
self.theme.version.paint(&version),
)
}

Expand All @@ -109,93 +111,159 @@ impl<'a, W: Write + ?Sized> Printer<'a, W> {
.collect();

if sorted.is_empty() {
let node = Node::empty(Paint::green("no features"));
return node.print(self.writer);
return Node::empty(self.theme.no_features.paint(labels::NO_FEATURES))
.print(self.writer, &self.theme);
}

let default_node = match sorted.remove(&"default".to_string()) {
Some(default) if !default.is_empty() => Node::new(
Paint::magenta("default"),
default.into_iter().map(Paint::green),
self.theme.default.paint(labels::DEFAULT),
default
.into_iter()
.map(|s| self.theme.default_features.paint(s)),
),
_ => Node::empty(
self.theme
.no_default_features
.paint(labels::NO_DEFAULT_FEATURES),
),
_ => Node::empty(Paint::yellow("no default features")),
};

let iter = sorted.iter().map(|(k, v)| {
let k = Paint::magenta(k);
let k = if k.starts_with('_') {
self.theme.probably_internal.paint(k)
} else {
self.theme.feature_name.paint(k)
};

if v.is_empty() {
Node::empty(k)
} else {
Node::new(k, v.iter().map(Paint::white))
Node::new(
k,
v.iter().map(|s| {
if s.starts_with('_') {
self.theme.probably_internal.paint(s)
} else {
self.theme.feature_implies.paint(s)
}
}),
)
}
});

let node = Node::new(
Paint::green("features"),
Node::new(
self.theme.features.paint(labels::FEATURES),
std::iter::once(default_node).chain(iter),
);
node.print(self.writer)
)
.print(self.writer, &self.theme)
}

/// Write all of the optional dependencies for the crate
pub fn write_opt_deps(&mut self, features: &Features) -> std::io::Result<()> {
let sorted = SortedDeps::from_kind_map(features.optional_deps.clone());
if !sorted.normal.has_deps() {
let node = Node::empty(Paint::yellow("no optional dependencies"));
return node.print(self.writer);
return Node::empty(
self.theme
.no_optional_deps
.paint(labels::NO_OPTIONAL_DEPENDENCIES),
)
.print(self.writer, &self.theme);
}

let node = build_features_tree(Paint::yellow("optional dependencies"), sorted.normal);
node.print(self.writer)
build_features_tree(
self.theme
.optional_deps
.paint(labels::OPTIONAL_DEPENDENCIES),
sorted.normal,
&self.theme,
)
.print(self.writer, &self.theme)
}

/// Write all of the other dependencies for the crate
pub fn write_deps(&mut self, features: &Features) -> std::io::Result<()> {
let sorted = SortedDeps::from_kind_map(features.required_deps.clone());
if !sorted.normal.has_deps() && !sorted.development.has_deps() && !sorted.build.has_deps() {
let node = Node::empty(Paint::cyan("no required dependencies"));
return node.print(self.writer);
return Node::empty(
self.theme
.no_required_deps
.paint(labels::NO_REQUIRED_DEPENDENCIES),
)
.print(self.writer, &self.theme);
}

let mut nodes = vec![];
if sorted.normal.has_deps() {
nodes.push(build_features_tree(Paint::blue("normal"), sorted.normal));
nodes.push(build_features_tree(
self.theme.normal_deps.paint(labels::NORMAL),
sorted.normal,
&self.theme,
));
} else {
// this should should always be visible
nodes.push(Node::empty(Paint::cyan("no normal dependencies")));
nodes.push(Node::empty(
self.theme
.no_required_deps
.paint(labels::NO_NORMAL_DEPENDENCIES),
));
}

if sorted.development.has_deps() {
nodes.push(build_features_tree(
Paint::blue("development"),
self.theme.dev_deps.paint(labels::DEVELOPMENT),
sorted.development,
&self.theme,
));
} else {
// TODO make this only visible via a verbosity flag
nodes.push(Node::empty(Paint::cyan("no development dependencies")));
nodes.push(Node::empty(
self.theme
.no_dev_deps
.paint(labels::NO_DEVELOPMENT_DEPENDENCIES),
));
}

if sorted.build.has_deps() {
nodes.push(build_features_tree(Paint::blue("build"), sorted.build));
nodes.push(build_features_tree(
self.theme.build_deps.paint(labels::BUILD),
sorted.build,
&self.theme,
));
} else {
// TODO make this only visible via a verbosity flag
nodes.push(Node::empty(Paint::cyan("no build dependencies")));
nodes.push(Node::empty(
self.theme
.no_build_deps
.paint(labels::NO_BUILD_DEPENDENCIES),
));
}

let node = Node::new(Paint::cyan("required dependencies"), nodes);
node.print(self.writer)
Node::new(
self.theme
.required_deps
.paint(labels::REQUIRED_DEPENDENCIES),
nodes,
)
.print(self.writer, &self.theme)
}
}

fn build_features_tree(text: impl ToString, deps: GroupedDeps) -> Node {
fn build_features(deps: Vec<Dependency>) -> impl Iterator<Item = Node> {
fn build_features_tree(text: impl ToString, deps: GroupedDeps, theme: &Theme) -> Node {
fn build_features(deps: Vec<Dependency>, theme: &Theme) -> impl Iterator<Item = Node> {
let mut tree = vec![];
for dep in deps {
let name = format_dep(&dep);
let name = format_dep(&dep, &theme);
if !dep.features.is_empty() {
tree.push(Node::new(
format!("{}{}", name, Paint::blue("(has enabled features)")),
dep.features,
format!(
"{}{}",
name, // TODO does this have a color?
theme
.has_enabled_features
.paint(labels::HAS_ENABLED_FEATURES)
),
dep.features.into_iter().map(|s| theme.dep_feature.paint(s)),
));
continue;
}
Expand All @@ -208,23 +276,48 @@ fn build_features_tree(text: impl ToString, deps: GroupedDeps) -> Node {
.with_targets
.into_iter()
.map(|(target, deps)| {
Node::new(format!("for {}", Paint::red(target)), build_features(deps))
Node::new(
format!("for {}", theme.target.paint(target)),
build_features(deps, &theme),
)
})
.chain(build_features(deps.without_targets));
.chain(build_features(deps.without_targets, &theme));

Node::new(text, iter)
}

fn format_dep(dep: &Dependency) -> String {
fn format_dep(dep: &Dependency, theme: &Theme) -> String {
format!(
"{} = {} {}",
dep.name,
Paint::yellow(&dep.req),
theme.name.paint(&dep.name),
theme.version.paint(&dep.req),
Paint::white(
dep.rename
.as_deref()
.map(|r| format!("(renamed to {}) ", Paint::blue(r)))
.map(|r| format!("(renamed to {}) ", theme.renamed.paint(r)))
.unwrap_or_else(|| "".into()),
)
)
}

mod labels {
pub const YANKED: &str = "yanked";

pub const NO_FEATURES: &str = "no features";
pub const DEFAULT: &str = "default";
pub const NO_DEFAULT_FEATURES: &str = "no default features";
pub const FEATURES: &str = "features";
pub const NO_OPTIONAL_DEPENDENCIES: &str = "no optional dependencies";
pub const OPTIONAL_DEPENDENCIES: &str = "optional dependencies";

pub const NO_REQUIRED_DEPENDENCIES: &str = "no required dependencies";
pub const NORMAL: &str = "normal";
pub const NO_NORMAL_DEPENDENCIES: &str = "no normal dependencies";
pub const DEVELOPMENT: &str = "development";
pub const NO_DEVELOPMENT_DEPENDENCIES: &str = "no development dependencies";
pub const BUILD: &str = "build";
pub const NO_BUILD_DEPENDENCIES: &str = "no build dependencies";
pub const REQUIRED_DEPENDENCIES: &str = "required dependencies";

pub const HAS_ENABLED_FEATURES: &str = "(has enabled features)";
}
79 changes: 79 additions & 0 deletions src/printer/theme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use yansi::Color;

pub struct Theme {
pub name: Color,
pub version: Color,
pub yanked: Color,

pub no_default_features: Color,
pub no_features: Color,
pub no_optional_deps: Color,
pub no_required_deps: Color,
pub no_dev_deps: Color,
pub no_build_deps: Color,

pub has_enabled_features: Color,
pub features: Color,
pub feature_name: Color,
pub feature_implies: Color,

pub probably_internal: Color,

pub default: Color,
pub default_features: Color,

pub required_deps: Color,
pub optional_deps: Color,

pub normal_deps: Color,

pub dev_deps: Color,
pub build_deps: Color,

pub renamed: Color,
pub target: Color,
pub dep_feature: Color,

pub tree: Color,
}

impl Default for Theme {
fn default() -> Self {
Self {
name: Color::RGB(255, 192, 128),
version: Color::RGB(192, 192, 0),
yanked: Color::RGB(255, 0, 0),

no_default_features: Color::RGB(255, 170, 0),
no_features: Color::RGB(255, 170, 0),
no_optional_deps: Color::RGB(255, 170, 0),
no_required_deps: Color::RGB(255, 170, 0),
no_dev_deps: Color::RGB(255, 170, 0),
no_build_deps: Color::RGB(255, 170, 0),

has_enabled_features: Color::RGB(0, 153, 238),
features: Color::RGB(255, 0, 255),
feature_name: Color::RGB(255, 255, 255),
feature_implies: Color::RGB(192, 192, 255),

probably_internal: Color::RGB(128, 32, 32),

default: Color::RGB(0, 255, 0),
default_features: Color::RGB(0, 192, 0),

required_deps: Color::RGB(192, 0, 255),
optional_deps: Color::RGB(255, 0, 255),

normal_deps: Color::RGB(255, 124, 201),

dev_deps: Color::RGB(255, 124, 201),
build_deps: Color::RGB(255, 124, 201),

renamed: Color::RGB(64, 0, 255),
target: Color::RGB(192, 0, 0),
dep_feature: Color::RGB(128, 128, 128),

tree: Color::RGB(48, 48, 48),
}
}
}
Loading

0 comments on commit 8026f8b

Please sign in to comment.