Only use colors & text decorations on ANSI-capable terminals.

Fixes #404.
This commit is contained in:
KtorZ
2023-02-26 13:19:03 +01:00
parent 2f2be39813
commit a46a9fca41
16 changed files with 593 additions and 261 deletions

View File

@@ -15,7 +15,7 @@ hex = "0.4.3"
ignore = "0.4.18"
indoc = "1.0"
miette = { version = "5.3.0", features = ["fancy"] }
owo-colors = "3.5.0"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
pallas-addresses = "0.16.0"
pallas-codec = "0.16.0"
pallas-crypto = "0.16.0"

View File

@@ -4,7 +4,7 @@ use aiken_project::{
};
use indoc::{formatdoc, indoc};
use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use owo_colors::{OwoColorize, Stream::Stderr};
use std::{
fs,
path::{Path, PathBuf},
@@ -55,7 +55,7 @@ fn create_project(args: Args, package_name: &PackageName) -> miette::Result<()>
}
fn print_success_message(package_name: &PackageName) {
println!(
eprintln!(
"\n{}",
formatdoc! {
r#"Your Aiken project {name} has been {s} created.
@@ -64,10 +64,17 @@ fn print_success_message(package_name: &PackageName) {
{cd} {name}
{aiken} check
"#,
s = "successfully".bold().bright_green(),
cd = "cd".bold().purple(),
name = package_name.repo.bright_blue(),
aiken = "aiken".bold().purple(),
s = "successfully"
.if_supports_color(Stderr, |s| s.bright_green())
.if_supports_color(Stderr, |s| s.bold()),
cd = "cd"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
name = package_name
.if_supports_color(Stderr, |s| s.repo.bright_blue()),
aiken = "aiken"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold())
}
)
}

View File

@@ -5,7 +5,7 @@ use aiken_project::{
pretty,
};
use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use owo_colors::{OwoColorize, Stream::Stderr};
use std::{path::PathBuf, process, str::FromStr};
#[derive(clap::Args)]
@@ -43,27 +43,29 @@ pub fn exec(args: Args) -> miette::Result<()> {
}
};
println!(
eprintln!(
"{} {}",
pretty::pad_left("Package".to_string(), 13, " ")
.bold()
.purple(),
dependency.name.bright_blue(),
dependency
.name
.if_supports_color(Stderr, |s| s.bright_blue()),
);
match config.insert(&dependency, args.overwrite) {
Some(config) => {
config.save(&root).into_diagnostic()?;
println!(
eprintln!(
"{} version → {}",
pretty::pad_left(
if args.overwrite { "Changed" } else { "Added" }.to_string(),
13,
" "
)
.bold()
.purple(),
dependency.version.yellow()
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
dependency.version.if_supports_color(Stderr, |s| s.yellow())
);
Ok(())
}

View File

@@ -1,38 +1,38 @@
use aiken_project::{paths, pretty};
use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use owo_colors::{OwoColorize, Stream::Stderr};
use std::fs;
pub fn exec() -> miette::Result<()> {
let dir = paths::packages_cache();
println!(
eprintln!(
"{} {}",
pretty::pad_left("Clearing".to_string(), 13, " ")
.bold()
.purple(),
dir.display().bold(),
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
dir.display().if_supports_color(Stderr, |s| s.bold()),
);
let packages = fs::read_dir(&dir).into_diagnostic()?;
for package in packages {
let path = package.into_diagnostic()?.path();
println!(
eprintln!(
"{} {}",
pretty::pad_left("Removing".to_string(), 13, " ")
.bold()
.purple(),
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
path.file_name()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.bright_blue(),
.if_supports_color(Stderr, |s| s.bright_blue()),
);
fs::remove_file(path).into_diagnostic()?;
}
println!(
"{}",
pretty::pad_left("Done".to_string(), 13, " ")
.bold()
.purple()
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold())
);
Ok(())
}

View File

@@ -1,5 +1,5 @@
use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use owo_colors::{OwoColorize, Stream::Stderr};
use pallas_primitives::{
babbage::{Redeemer, TransactionInput, TransactionOutput},
Fragment,
@@ -54,7 +54,12 @@ pub fn exec(
zero_slot,
}: Args,
) -> miette::Result<()> {
eprintln!("{} script context", " Parsing".bold().purple(),);
eprintln!(
"{} script context",
" Parsing"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold())
);
let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor {
(
@@ -78,7 +83,13 @@ pub fn exec(
.or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))
.into_diagnostic()?;
eprintln!("{} {}", " Simulating".bold().purple(), tx.hash());
eprintln!(
"{} {}",
" Simulating"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
tx.hash()
);
let inputs = Vec::<TransactionInput>::decode_fragment(&inputs_bytes).unwrap();
let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap();
@@ -100,9 +111,11 @@ pub fn exec(
};
let with_redeemer = |redeemer: &Redeemer| {
println!(
eprintln!(
"{} {:?}{}",
" Redeemer".bold().purple(),
" Redeemer"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold()),
redeemer.tag,
redeemer.index
)
@@ -147,7 +160,13 @@ pub fn exec(
}
fn display_tx_error(err: &tx::error::Error) -> String {
let mut msg = format!("{} {}", " Error".bold().red(), err.red());
let mut msg = format!(
"{} {}",
" Error"
.if_supports_color(Stderr, |s| s.red())
.if_supports_color(Stderr, |s| s.bold()),
err.red()
);
match err {
tx::error::Error::RedeemerError { err, .. } => {
msg.push_str(&format!(
@@ -164,7 +183,15 @@ fn display_tx_error(err: &tx::error::Error) -> String {
msg.push_str(
traces
.iter()
.map(|s| format!("\n{} {}", " Trace".bold().yellow(), s.yellow()))
.map(|s| {
format!(
"\n{} {}",
" Trace"
.if_supports_color(Stderr, |s| s.yellow())
.if_supports_color(Stderr, |s| s.bold()),
s.if_supports_color(Stderr, |s| s.yellow())
)
})
.collect::<Vec<_>>()
.join("")
.as_str(),

View File

@@ -1,6 +1,9 @@
use aiken_project::{pretty, script::EvalInfo, telemetry, Project};
use miette::IntoDiagnostic;
use owo_colors::OwoColorize;
use owo_colors::{
OwoColorize,
Stream::{self, Stderr},
};
use std::{collections::BTreeMap, env, path::PathBuf, process};
use uplc::machine::cost_model::ExBudget;
@@ -41,7 +44,12 @@ where
err.report()
}
println!("\n{}", "Summary".purple().bold());
eprintln!(
"\n{}",
"Summary"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold())
);
let warning_text = format!("{warning_count} warning{plural}");
@@ -49,17 +57,29 @@ where
let error_text = format!("{} error{}", errs.len(), plural);
let full_summary = format!(" {}, {}", error_text.red(), warning_text.yellow());
let full_summary = format!(
" {}, {}",
error_text.if_supports_color(Stderr, |s| s.red()),
warning_text.if_supports_color(Stderr, |s| s.yellow())
);
println!("{full_summary}");
eprintln!("{full_summary}");
process::exit(1);
} else {
println!("\n{}", "Summary".purple().bold());
eprintln!(
"\n{}",
"Summary"
.if_supports_color(Stderr, |s| s.purple())
.if_supports_color(Stderr, |s| s.bold())
);
let warning_text = format!("{warning_count} warning{plural}");
println!(" 0 errors, {}", warning_text.yellow(),);
eprintln!(
" 0 errors, {}",
warning_text.if_supports_color(Stderr, |s| s.yellow()),
);
}
Ok(())
}
@@ -75,12 +95,15 @@ impl telemetry::EventListener for Terminal {
version,
root,
} => {
println!(
eprintln!(
"{} {} {} ({})",
" Compiling".bold().purple(),
name.bold(),
" Compiling"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
name.if_supports_color(Stderr, |s| s.bold()),
version,
root.display().bright_blue()
root.display()
.if_supports_color(Stderr, |s| s.bright_blue())
);
}
telemetry::Event::BuildingDocumentation {
@@ -88,65 +111,103 @@ impl telemetry::EventListener for Terminal {
version,
root,
} => {
println!(
eprintln!(
"{} {} {} ({})",
" Generating documentation".bold().purple(),
name.bold(),
" Generating documentation"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
name.if_supports_color(Stderr, |s| s.bold()),
version,
root.to_str().unwrap_or("").bright_blue()
root.to_str()
.unwrap_or("")
.if_supports_color(Stderr, |s| s.bright_blue())
);
}
telemetry::Event::WaitingForBuildDirLock => {
println!("{}", "Waiting for build directory lock ...".bold().purple());
eprintln!(
"{}",
"Waiting for build directory lock ..."
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple())
);
}
telemetry::Event::DumpingUPLC { path } => {
println!(
eprintln!(
"{} {} ({})",
" Exporting".bold().purple(),
"UPLC".bold(),
path.display().bright_blue()
" Exporting"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
"UPLC".if_supports_color(Stderr, |s| s.bold()),
path.display()
.if_supports_color(Stderr, |s| s.bright_blue())
);
}
telemetry::Event::GeneratingBlueprint { path } => {
println!(
eprintln!(
"{} {} ({})",
" Generating".bold().purple(),
"project's blueprint".bold(),
path.display().bright_blue()
" Generating"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
"project's blueprint".if_supports_color(Stderr, |s| s.bold()),
path.display()
.if_supports_color(Stderr, |s| s.bright_blue())
);
}
telemetry::Event::GeneratingDocFiles { output_path } => {
println!(
eprintln!(
"{} in {}",
" Generating documentation files".bold().purple(),
output_path.to_str().unwrap_or("").bright_blue()
" Generating documentation files"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
output_path
.to_str()
.unwrap_or("")
.if_supports_color(Stderr, |s| s.bright_blue())
);
}
telemetry::Event::GeneratingUPLCFor { name, path } => {
println!(
eprintln!(
"{} {}.{{{}}}",
" Generating UPLC for".bold().purple(),
path.to_str().unwrap_or("").blue(),
name.bright_blue(),
" Generating UPLC for"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
path.to_str()
.unwrap_or("")
.if_supports_color(Stderr, |s| s.blue()),
name.if_supports_color(Stderr, |s| s.bright_blue()),
);
}
telemetry::Event::EvaluatingFunction { results } => {
println!("{}\n", " Evaluating function ...".bold().purple());
eprintln!(
"{}\n",
" Evaluating function ..."
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple())
);
let (max_mem, max_cpu) = find_max_execution_units(&results);
for eval_info in &results {
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu))
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu, Stderr))
}
}
telemetry::Event::RunningTests => {
println!("{} {}\n", " Testing".bold().purple(), "...".bold());
eprintln!(
"{} {}\n",
" Testing"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
"...".if_supports_color(Stderr, |s| s.bold())
);
}
telemetry::Event::FinishedTests { tests } => {
let (max_mem, max_cpu) = find_max_execution_units(&tests);
for (module, infos) in &group_by_module(&tests) {
let title = module.bold().blue().to_string();
let title = module
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.blue())
.to_string();
let tests = infos
.iter()
@@ -156,11 +217,11 @@ impl telemetry::EventListener for Terminal {
let summary = fmt_test_summary(infos, true);
println!(
eprintln!(
"{}\n",
pretty::indent(
&pretty::open_box(&title, &tests, &summary, |border| border
.bright_black()
.if_supports_color(Stderr, |s| s.bright_black())
.to_string()),
4
)
@@ -168,7 +229,13 @@ impl telemetry::EventListener for Terminal {
}
}
telemetry::Event::DownloadingPackage { name } => {
println!("{} {}", " Downloading".bold().purple(), name.bold())
eprintln!(
"{} {}",
" Downloading"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
name.if_supports_color(Stderr, |s| s.bold())
)
}
telemetry::Event::PackagesDownloaded { start, count } => {
let elapsed = format!("{:.2}s", start.elapsed().as_millis() as f32 / 1000.);
@@ -178,10 +245,21 @@ impl telemetry::EventListener for Terminal {
_ => format!("{count} packages in {elapsed}"),
};
println!("{} {}", " Downloaded".bold().purple(), msg.bold())
eprintln!(
"{} {}",
" Downloaded"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
msg.if_supports_color(Stderr, |s| s.bold())
)
}
telemetry::Event::ResolvingVersions => {
println!("{}", " Resolving versions".bold().purple(),)
eprintln!(
"{}",
" Resolving versions"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.purple()),
)
}
}
}
@@ -203,13 +281,27 @@ fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool)
let test = format!(
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
status = if *success {
pretty::style_if(styled, "PASS".to_string(), |s| s.bold().green().to_string())
pretty::style_if(styled, "PASS".to_string(), |s| {
s.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.green())
.to_string()
})
} else {
pretty::style_if(styled, "FAIL".to_string(), |s| s.bold().red().to_string())
pretty::style_if(styled, "FAIL".to_string(), |s| {
s.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.red())
.to_string()
})
},
mem_unit = pretty::style_if(styled, mem_pad, |s| s.bright_white().to_string()),
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s.bright_white().to_string()),
module = pretty::style_if(styled, script.name.clone(), |s| s.bright_blue().to_string()),
mem_unit = pretty::style_if(styled, mem_pad, |s| s
.if_supports_color(Stderr, |s| s.bright_white())
.to_string()),
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s
.if_supports_color(Stderr, |s| s.bright_white())
.to_string()),
module = pretty::style_if(styled, script.name.clone(), |s| s
.if_supports_color(Stderr, |s| s.bright_blue())
.to_string()),
);
let logs = if logs.is_empty() {
@@ -219,8 +311,8 @@ fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool)
.map(|line| {
format!(
"{arrow} {styled_line}",
arrow = "".bright_yellow(),
styled_line = line.bright_black()
arrow = "".if_supports_color(Stderr, |s| s.bright_yellow()),
styled_line = line.if_supports_color(Stderr, |s| s.bright_black())
)
})
.collect::<Vec<_>>()
@@ -247,20 +339,20 @@ fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
format!(
"{} | {} | {}",
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
.bold()
.if_supports_color(Stderr, |s| s.bold())
.to_string()),
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
.bright_green()
.bold()
.if_supports_color(Stderr, |s| s.bright_green())
.if_supports_color(Stderr, |s| s.bold())
.to_string()),
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
.bright_red()
.bold()
.if_supports_color(Stderr, |s| s.bright_red())
.if_supports_color(Stderr, |s| s.bold())
.to_string()),
)
}
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, stream: Stream) -> String {
let EvalInfo {
output,
script,
@@ -272,8 +364,8 @@ fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
format!(
" {}::{} [mem: {}, cpu: {}]\n\n ╰─▶ {}",
script.module.blue(),
script.name.bright_blue(),
script.module.if_supports_color(stream, |s| s.blue()),
script.name.if_supports_color(stream, |s| s.bright_blue()),
pretty::pad_left(mem.to_string(), max_mem, " "),
pretty::pad_left(cpu.to_string(), max_cpu, " "),
output