Skip to content

Commit

Permalink
Merge pull request #136 from epage/color
Browse files Browse the repository at this point in the history
feat: Color support
  • Loading branch information
epage committed Oct 7, 2021
2 parents 036ef47 + 0b1629f commit 33a0399
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 22 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Expand Up @@ -69,7 +69,7 @@ jobs:
- name: No-default features
run: cargo test --workspace --no-default-features
msrv:
name: "Check MSRV: 1.46.0"
name: "Check MSRV: 1.54.0"
needs: smoke
runs-on: ubuntu-latest
steps:
Expand All @@ -78,7 +78,7 @@ jobs:
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: 1.46.0 # MSRV
toolchain: 1.54.0 # MSRV
profile: minimal
override: true
- uses: Swatinem/rust-cache@v1
Expand Down Expand Up @@ -133,7 +133,7 @@ jobs:
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: 1.46.0 # MSRV
toolchain: 1.54.0 # MSRV
profile: minimal
override: true
components: clippy
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/rust-next.yml
Expand Up @@ -66,9 +66,9 @@ jobs:
strategy:
matrix:
rust:
- 1.46.0 # MSRV
- 1.54.0 # MSRV
- stable
continue-on-error: ${{ matrix.rust != '1.46.0' }} # MSRV
continue-on-error: ${{ matrix.rust != '1.54.0' }} # MSRV
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand Down
10 changes: 6 additions & 4 deletions Cargo.toml
Expand Up @@ -12,10 +12,6 @@ categories = ["development-tools::testing"]
keywords = ["cli", "test", "assert", "command", "duct"]
edition = "2018"

[badges]
codecov = { repository = "assert-rs/assert_cmd" }
maintenance = { status = "passively-maintained" }

[package.metadata.release]
pre-release-replacements = [
{file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1},
Expand All @@ -25,6 +21,10 @@ pre-release-replacements = [
{file="CHANGELOG.md", search="<!-- next-url -->", replace="<!-- next-url -->\n[Unreleased]: https://github.com/assert-rs/assert_cmd/compare/{{tag_name}}...HEAD", exactly=1},
]

[features]
color = ["yansi", "concolor-control/std", "predicates/color"]
color-auto = ["color", "concolor-control/auto"]

[[bin]]
name = "bin_fixture"

Expand All @@ -35,6 +35,8 @@ predicates-tree = "1.0"
doc-comment = "0.3"
wait-timeout = "0.2.0"
bstr = "0.2.14"
yansi = { version = "0.5.0", optional = true }
concolor-control = { version = "0.0.7", optional = true }

[dev-dependencies]
escargot = "0.5"
10 changes: 10 additions & 0 deletions examples/failure.rs
@@ -0,0 +1,10 @@
use assert_cmd::prelude::*;

use std::process::Command;

fn main() {
Command::new("ls")
.args(["non-existent"])
.assert()
.code(&[3, 42] as &[i32]);
}
8 changes: 7 additions & 1 deletion src/assert.rs
Expand Up @@ -482,8 +482,14 @@ impl Assert {

impl fmt::Display for Assert {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::current();
for &(ref name, ref context) in &self.context {
writeln!(f, "{}=`{}`", name, context)?;
writeln!(
f,
"{}=`{}`",
palette.key.paint(name),
palette.value.paint(context)
)?;
}
output_fmt(&self.output, f)
}
Expand Down
48 changes: 48 additions & 0 deletions src/color.rs
@@ -0,0 +1,48 @@
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Palette {
pub(crate) key: styled::Style,
pub(crate) value: styled::Style,
}

impl Palette {
#[cfg(feature = "color")]
pub(crate) fn current() -> Self {
if concolor_control::get(concolor_control::Stream::Either).ansi_color() {
Self {
key: styled::Style(yansi::Style::new(yansi::Color::Blue).bold()),
value: styled::Style(yansi::Style::new(yansi::Color::Yellow).bold()),
}
} else {
Self::default()
}
}

#[cfg(not(feature = "color"))]
pub(crate) fn current() -> Self {
Self::default()
}
}

#[cfg(feature = "color")]
mod styled {
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Style(pub(crate) yansi::Style);

impl Style {
pub(crate) fn paint<T: std::fmt::Display>(self, item: T) -> impl std::fmt::Display {
self.0.paint(item)
}
}
}

#[cfg(not(feature = "color"))]
mod styled {
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Style;

impl Style {
pub(crate) fn paint<T: std::fmt::Display>(self, item: T) -> impl std::fmt::Display {
item
}
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Expand Up @@ -144,4 +144,7 @@ pub mod prelude {

pub use crate::cmd::Command;

mod color;
use color::Palette;

doc_comment::doctest!("../README.md");
43 changes: 31 additions & 12 deletions src/output.rs
Expand Up @@ -4,7 +4,6 @@ use bstr::ByteSlice;
use std::error::Error;
use std::fmt;
use std::process;
use std::str;

/// Converts a type to an [`OutputResult`].
///
Expand Down Expand Up @@ -242,15 +241,22 @@ impl Error for OutputError {}

impl fmt::Display for OutputError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::current();
if let Some(ref cmd) = self.cmd {
writeln!(f, "command=`{}`", cmd)?;
writeln!(
f,
"{}={}",
palette.key.paint("command"),
palette.value.paint(cmd)
)?;
}
if let Some(ref stdin) = self.stdin {
if let Ok(stdin) = str::from_utf8(stdin) {
writeln!(f, "stdin=```{}```", stdin)?;
} else {
writeln!(f, "stdin=```{:?}```", stdin)?;
}
writeln!(
f,
"{}={}",
palette.key.paint("stdin"),
palette.value.paint(DebugBytes::new(stdin))
)?;
}
write!(f, "{}", self.cause)
}
Expand Down Expand Up @@ -283,17 +289,30 @@ impl fmt::Display for Output {
}

pub(crate) fn output_fmt(output: &process::Output, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::current();
if let Some(code) = output.status.code() {
writeln!(f, "code={}", code)?;
writeln!(
f,
"{}={}",
palette.key.paint("code"),
palette.value.paint(code)
)?;
} else {
writeln!(f, "code=<interrupted>")?;
writeln!(
f,
"{}={}",
palette.key.paint("code"),
palette.value.paint("<interrupted>")
)?;
}

write!(
f,
"stdout=```{}```\nstderr=```{}```\n",
DebugBytes::new(&output.stdout),
DebugBytes::new(&output.stderr),
"{}={}\n{}={}\n",
palette.key.paint("stdout"),
palette.value.paint(DebugBytes::new(&output.stdout)),
palette.key.paint("stderr"),
palette.value.paint(DebugBytes::new(&output.stderr)),
)?;
Ok(())
}
Expand Down

0 comments on commit 33a0399

Please sign in to comment.