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

add support for NO_COLOR #58

Merged
merged 3 commits into from
Apr 25, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
.vscode
.idea
venv
tmp*
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ ls *.py | entr clash run --auto-advance --command "python3 sol.py"
nodemon --ext py --exec clash -- run --auto-advance --command "python3 sol.py"
```

### Disabling color output

You may disable colors by setting the [NO_COLOR](http://no-color.org/) environment variable to any non-empty value:

```console
$ NO_COLOR=1 clash show
```


## Installation

Expand Down
10 changes: 2 additions & 8 deletions src/clash/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,10 @@ impl TestCase {
}

pub fn styled_input(&self, ostyle: &OutputStyle) -> String {
match ostyle.input_whitespace {
Some(ws_style) => show_whitespace(&self.test_in, &ostyle.input, &ws_style),
None => ostyle.input.paint(&self.test_in).to_string(),
}
show_whitespace(&self.test_in, &ostyle.input, &ostyle.input_whitespace)
}

pub fn styled_output(&self, ostyle: &OutputStyle) -> String {
match ostyle.output_whitespace {
Some(ws_style) => show_whitespace(&self.test_out, &ostyle.output, &ws_style),
None => ostyle.output.paint(&self.test_out).to_string(),
}
show_whitespace(&self.test_out, &ostyle.output, &ostyle.output_whitespace)
}
}
19 changes: 12 additions & 7 deletions src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,18 @@ fn format_remove_excessive_newlines(text: &str) -> String {

/// 1. Replaces spaces with • and newlines with ⏎. Paints them with `ws_style`.
/// 2. Paints the rest with `style`.
pub fn show_whitespace(text: &str, style: &Style, ws_style: &Style) -> String {
let newl = format!("{}\n", ws_style.paint("⏎"));
let space = format!("{}", ws_style.paint("•"));
let fmt_non_ws = RE_NONWHITESPACE
.replace_all(text, |caps: &regex::Captures| style.paint(&caps[0]).to_string())
.to_string();
fmt_non_ws.replace('\n', &newl).replace(' ', &space)
pub fn show_whitespace(text: &str, style: &Style, ws_style: &Option<Style>) -> String {
match ws_style {
None => style.paint(text).to_string(),
Some(ws_style) => {
let newl = format!("{}\n", ws_style.paint("⏎"));
let space = format!("{}", ws_style.paint("•"));
let fmt_non_ws = RE_NONWHITESPACE
.replace_all(text, |caps: &regex::Captures| style.paint(&caps[0]).to_string())
.to_string();
fmt_non_ws.replace('\n', &newl).replace(' ', &space)
}
}
}

/// Construct a new style that is the combination of `inner` and `outer` style.
Expand Down
53 changes: 15 additions & 38 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ use clashlib::{solution, stub};
use directories::ProjectDirs;
use rand::seq::IteratorRandom;

#[derive(Clone)]
pub enum OutputStyleOption {
Default,
Plain,
}

fn command_from_argument(cmd_arg: Option<&String>) -> Result<Option<Command>> {
let cmd = match cmd_arg {
Some(cmd) => cmd,
Expand Down Expand Up @@ -48,7 +42,6 @@ fn cli() -> clap::Command {
.subcommand(
Command::new("show")
.about("Show clash")
.arg(arg!(--"no-color" "don't use ANSI colors in the output"))
.arg(
arg!(--"show-whitespace" [BOOL] "render ⏎ and • in place of newlines and spaces")
// This means show-whitespace=1 also works
Expand Down Expand Up @@ -96,6 +89,13 @@ fn cli() -> clap::Command {
.value_parser(value_parser!(u64).range(1..99))
.value_delimiter(',')
)
.arg(
arg!(--"show-whitespace" [BOOL] "render ⏎ and • in place of newlines and spaces")
// This means show-whitespace=1 also works
.value_parser(clap::builder::BoolishValueParser::new())
.default_value("true")
.default_missing_value("true")
)
.arg(
arg!([PUBLIC_HANDLE] "hexadecimal handle of the clash")
.value_parser(value_parser!(PublicHandle))
Expand Down Expand Up @@ -125,7 +125,6 @@ fn cli() -> clap::Command {
.subcommand(
Command::new("showtests")
.about("Print testcases and validators of current clash")
.arg(arg!(--"no-color" "don't use ANSI colors in the output"))
.arg(
arg!(--"show-whitespace" [BOOL] "render ⏎ and • in place of newlines and spaces")
// This means show-whitespace=1 also works
Expand Down Expand Up @@ -285,20 +284,8 @@ impl App {
};
let clash = self.read_clash(&handle)?;

let mut ostyle = if args.get_flag("no-color") {
OutputStyle::plain()
} else {
OutputStyle::default()
};
if let Some(show_ws) = args.get_one::<bool>("show-whitespace") {
if *show_ws {
ostyle.input_whitespace = ostyle.input_whitespace.or(Some(ostyle.input));
ostyle.output_whitespace = ostyle.output_whitespace.or(Some(ostyle.output));
} else {
ostyle.input_whitespace = None;
ostyle.output_whitespace = None;
}
}
let show_whitespace = *args.get_one::<bool>("show-whitespace").unwrap_or(&false);
let ostyle = OutputStyle::from_env(show_whitespace);

// --reverse flag
if args.get_flag("reverse") {
Expand Down Expand Up @@ -389,11 +376,13 @@ impl App {
let suite_run = solution::run(testcases, run_command, timeout);

let ignore_failures = args.get_flag("ignore-failures");
let style = &OutputStyle::default();
let show_whitespace = *args.get_one::<bool>("show-whitespace").unwrap_or(&false);
let ostyle = OutputStyle::from_env(show_whitespace);

let mut num_passed = 0;

for test_run in suite_run {
test_run.print_result(style);
test_run.print_result(&ostyle);

if test_run.is_successful() {
num_passed += 1;
Expand Down Expand Up @@ -438,20 +427,8 @@ impl App {
let clash = self.read_clash(&handle)?;
let all_testcases = clash.testcases();

let mut ostyle = if args.get_flag("no-color") {
OutputStyle::plain()
} else {
OutputStyle::default()
};
if let Some(show_ws) = args.get_one::<bool>("show-whitespace") {
if *show_ws {
ostyle.input_whitespace = ostyle.input_whitespace.or(Some(ostyle.input));
ostyle.output_whitespace = ostyle.output_whitespace.or(Some(ostyle.output));
} else {
ostyle.input_whitespace = None;
ostyle.output_whitespace = None;
}
}
let show_whitespace = *args.get_one::<bool>("show-whitespace").unwrap_or(&false);
let ostyle = OutputStyle::from_env(show_whitespace);

let num_testcases = all_testcases.len();
let testcase_indices: Vec<u64> = match args.get_many::<u64>("TESTCASE") {
Expand Down
34 changes: 34 additions & 0 deletions src/outputstyle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ pub struct OutputStyle {
pub failure: Style,
pub error: Style,
pub stderr: Style,
pub dim_color: Style,
pub diff_green: Style,
pub diff_green_whitespace: Option<Style>,
pub diff_red: Style,
pub diff_red_whitespace: Option<Style>,
}

impl OutputStyle {
Expand All @@ -36,8 +41,32 @@ impl OutputStyle {
failure: Style::default(),
error: Style::default(),
stderr: Style::default(),
dim_color: Style::default(),
diff_green: Style::default(),
diff_green_whitespace: Some(Style::default()),
diff_red: Style::default(),
diff_red_whitespace: Some(Style::default()),
}
}
pub fn from_env(show_whitespace: bool) -> Self {
let mut ostyle = match std::env::var_os("NO_COLOR") {
Some(s) if s.is_empty() => OutputStyle::default(),
Some(_) => OutputStyle::plain(),
None => OutputStyle::default(),
};
if show_whitespace {
ostyle.input_whitespace = ostyle.input_whitespace.or(Some(ostyle.input));
ostyle.output_whitespace = ostyle.output_whitespace.or(Some(ostyle.output));
ostyle.diff_green_whitespace = ostyle.diff_green_whitespace.or(Some(ostyle.diff_green));
ostyle.diff_red_whitespace = ostyle.diff_red_whitespace.or(Some(ostyle.diff_red));
} else {
ostyle.input_whitespace = None;
ostyle.output_whitespace = None;
ostyle.diff_green_whitespace = None;
ostyle.diff_red_whitespace = None;
}
ostyle
}
}

impl Default for OutputStyle {
Expand All @@ -58,6 +87,11 @@ impl Default for OutputStyle {
failure: Style::new().on(Color::Red),
error: Style::new().on(Color::Red),
stderr: Style::new().fg(Color::Red),
dim_color: Style::new().fg(Color::RGB(50, 50, 50)),
diff_green: Style::new().fg(Color::RGB(111, 255, 111)),
diff_green_whitespace: Some(Style::new().fg(Color::RGB(0, 70, 0))),
diff_red: Style::new().fg(Color::RGB(255, 111, 111)),
diff_red_whitespace: Some(Style::new().fg(Color::Red).on(Color::RGB(70, 0, 0))),
}
}
}
24 changes: 11 additions & 13 deletions src/solution/test_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,13 @@ fn print_diff(testcase: &TestCase, stdout: &str, ostyle: &OutputStyle) {
use itertools::EitherOrBoth::{Both, Left, Right};
use itertools::Itertools;

// (TODO) temporary styling, to be replaced with OutputStyle eventually
let green = ansi_term::Style::new().fg(ansi_term::Color::RGB(111, 255, 111));
let red = ansi_term::Style::new().fg(ansi_term::Color::RGB(255, 111, 111));
let error_red = ansi_term::Style::new().fg(ansi_term::Color::Red).on(ansi_term::Color::RGB(70, 0, 0));
let dim_color = ansi_term::Style::new().fg(ansi_term::Color::RGB(50, 50, 50));
let ws_style = &ostyle.output_whitespace.unwrap_or(ostyle.output);
let diff_red = &ostyle.diff_red;
let diff_ws_red = &ostyle.diff_red_whitespace;
let diff_green = &ostyle.diff_green;
let diff_ws_green = &ostyle.diff_green_whitespace;

if stdout.is_empty() {
println!("{}", dim_color.paint("(no output)"));
println!("{}", ostyle.dim_color.paint("(no output)"));
return
}

Expand All @@ -134,7 +132,7 @@ fn print_diff(testcase: &TestCase, stdout: &str, ostyle: &OutputStyle) {
for either_or_both in expected_lines.zip_longest(actual_lines) {
match either_or_both {
Left(_) => missing_lines += 1,
Right(s) => print!("{}", show_whitespace(s, &red, &error_red)),
Right(s) => print!("{}", show_whitespace(s, diff_red, diff_ws_red)),
Both(a, b) => {
let mut prev_deleted = false;

Expand All @@ -144,13 +142,13 @@ fn print_diff(testcase: &TestCase, stdout: &str, ostyle: &OutputStyle) {
let mut chars = text.chars();
let first_char = chars.next().expect("no chars???").to_string();
let rest = chars.as_str();
print!("{}", show_whitespace(&first_char, &red, &error_red));
print!("{}", show_whitespace(&first_char, diff_red, diff_ws_red));
if !rest.is_empty() {
print!("{}", show_whitespace(rest, &green, ws_style));
print!("{}", show_whitespace(rest, diff_green, diff_ws_green));
}
}
Equal(text) => print!("{}", show_whitespace(text, &green, ws_style)),
Insert(text) => print!("{}", show_whitespace(text, &red, &error_red)),
Equal(text) => print!("{}", show_whitespace(text, diff_green, diff_ws_green)),
Insert(text) => print!("{}", show_whitespace(text, diff_red, diff_ws_red)),
Delete(_) => {}
}

Expand All @@ -166,6 +164,6 @@ fn print_diff(testcase: &TestCase, stdout: &str, ostyle: &OutputStyle) {

if missing_lines > 0 {
let msg = format!("(expected {} more lines)", missing_lines);
println!("{}", dim_color.paint(msg));
println!("{}", ostyle.dim_color.paint(msg));
}
}