Beautify help messages (#791)

* Enable wrap_help feature of clap

* Enable `AppSettings::ColoredHelp` of clap

* Run `cargo fmt --all`

Co-authored-by: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com>
This commit is contained in:
QuarticCat 2021-06-30 22:00:04 +08:00 committed by GitHub
parent cc363d5f25
commit c1397f3446
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 32 deletions

2
Cargo.lock generated
View File

@ -157,6 +157,7 @@ dependencies = [
"atty",
"bitflags",
"strsim",
"term_size",
"textwrap",
"unicode-width",
"vec_map",
@ -1063,6 +1064,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"term_size",
"unicode-width",
]

View File

@ -39,7 +39,7 @@ serde_json = "1.0.64"
[dependencies]
aho-corasick = "0.7.15"
arbitrary = { version="1.0.1", features=["derive"] }
clap = "2.33.3"
clap = { version = "2.33.3", features = ["wrap_help"] }
colored = "2"
crossbeam-channel = "0.5.0"
encoding_rs_io = "0.1.7"

View File

@ -1,7 +1,7 @@
use std::mem;
use std::process;
use clap::{clap_app, crate_description, ArgMatches};
use clap::{clap_app, crate_description, AppSettings, ArgMatches};
use tokei::{Config, LanguageType, Sort};
use crate::{cli_utils::*, input::Format};
@ -58,6 +58,7 @@ impl<'a> Cli<'a> {
"Support this project on GitHub Sponsors: https://github.com/sponsors/XAMPPRocky"
)
)
(setting: AppSettings::ColoredHelp)
(@arg columns: -c --columns
+takes_value
conflicts_with[output]
@ -164,7 +165,9 @@ impl<'a> Cli<'a> {
// is supported) but this will fail if support is not compiled in and
// give a useful error to the user.
let output = matches.value_of("output").map(parse_or_exit::<Format>);
let streaming = matches.value_of("streaming").map(parse_or_exit::<Streaming>);
let streaming = matches
.value_of("streaming")
.map(parse_or_exit::<Streaming>);
crate::cli_utils::setup_logger(verbose);
@ -259,8 +262,20 @@ impl<'a> Cli<'a> {
};
config.for_each_fn = match self.streaming {
Some(Streaming::Json) => Some(|l: LanguageType, e| println!("{}", serde_json::json!({"language": l.name(), "stats": e}))),
Some(Streaming::Simple) => Some(|l: LanguageType, e| println!("{:>10} {:<80} {:>12} {:>12} {:>12} {:>12}", l.name(), e.name.to_string_lossy().to_string(), e.stats.lines(), e.stats.code, e.stats.comments, e.stats.blanks)),
Some(Streaming::Json) => Some(|l: LanguageType, e| {
println!("{}", serde_json::json!({"language": l.name(), "stats": e}))
}),
Some(Streaming::Simple) => Some(|l: LanguageType, e| {
println!(
"{:>10} {:<80} {:>12} {:>12} {:>12} {:>12}",
l.name(),
e.name.to_string_lossy().to_string(),
e.stats.lines(),
e.stats.code,
e.stats.comments,
e.stats.blanks
)
}),
_ => None,
};

View File

@ -206,11 +206,24 @@ impl<W: Write> Printer<W> {
.values()
.map(Vec::len)
.sum::<usize>()
.to_formatted_string(&self.number_format).blue(),
language.lines().to_formatted_string(&self.number_format).blue(),
language.code.to_formatted_string(&self.number_format).blue(),
language.comments.to_formatted_string(&self.number_format).blue(),
language.blanks.to_formatted_string(&self.number_format).blue(),
.to_formatted_string(&self.number_format)
.blue(),
language
.lines()
.to_formatted_string(&self.number_format)
.blue(),
language
.code
.to_formatted_string(&self.number_format)
.blue(),
language
.comments
.to_formatted_string(&self.number_format)
.blue(),
language
.blanks
.to_formatted_string(&self.number_format)
.blue(),
)
}
@ -234,7 +247,12 @@ impl<W: Write> Printer<W> {
write!(self.writer, " {:.len$}", name, len = lang_section_len - 1)?;
write!(self.writer, "|")?;
} else {
write!(self.writer, " {:<len$}", name.bold(), len = lang_section_len)?;
write!(
self.writer,
" {:<len$}",
name.bold(),
len = lang_section_len
)?;
}
if inaccurate {
write!(self.writer, "{}", IDENT_INACCURATE)?;

View File

@ -47,11 +47,11 @@ pub struct Config {
pub types: Option<Vec<LanguageType>>,
// /// A map of individual language configuration.
// pub languages: Option<HashMap<LanguageType, LanguageConfig>>,
/// Whether to output only the paths for downstream batch processing
/// Whether to output only the paths for downstream batch processing
/// *Default:* false
#[serde(skip)]
/// adds a closure for each function, e.g., print the result
pub for_each_fn: Option<fn (LanguageType, Report)>,
pub for_each_fn: Option<fn(LanguageType, Report)>,
}
impl Config {
@ -114,7 +114,9 @@ impl Config {
.or(conf_dir.treat_doc_strings_as_comments)),
sort: current_dir.sort.or(home_dir.sort.or(conf_dir.sort)),
types: current_dir.types.or(home_dir.types.or(conf_dir.types)),
for_each_fn: current_dir.for_each_fn.or(home_dir.for_each_fn.or(conf_dir.for_each_fn)),
for_each_fn: current_dir
.for_each_fn
.or(home_dir.for_each_fn.or(conf_dir.for_each_fn)),
no_ignore: current_dir
.no_ignore
.or(home_dir.no_ignore.or(conf_dir.no_ignore)),

View File

@ -52,8 +52,19 @@ fn main() -> Result<(), Box<dyn Error>> {
.max(FALLBACK_ROW_LEN);
if cli.streaming == Some(crate::cli::Streaming::Simple) {
println!("#{:^10} {:^80} {:^12} {:^12} {:^12} {:^12}", "language", "path", "lines", "code", "comments", "blanks");
println!("{:>10} {:<80} {:>12} {:>12} {:>12} {:>12}", (0..10).map(|_| "#").collect::<String>(), (0..80).map(|_| "#").collect::<String>(), (0..12).map(|_| "#").collect::<String>(), (0..12).map(|_| "#").collect::<String>(), (0..12).map(|_| "#").collect::<String>(), (0..12).map(|_| "#").collect::<String>());
println!(
"#{:^10} {:^80} {:^12} {:^12} {:^12} {:^12}",
"language", "path", "lines", "code", "comments", "blanks"
);
println!(
"{:>10} {:<80} {:>12} {:>12} {:>12} {:>12}",
(0..10).map(|_| "#").collect::<String>(),
(0..80).map(|_| "#").collect::<String>(),
(0..12).map(|_| "#").collect::<String>(),
(0..12).map(|_| "#").collect::<String>(),
(0..12).map(|_| "#").collect::<String>(),
(0..12).map(|_| "#").collect::<String>()
);
}
languages.get_statistics(&input, &cli.ignored_directories(), &config);

View File

@ -91,23 +91,23 @@ pub fn get_all_files<A: AsRef<Path>>(
.filter_map(|e| LanguageType::from_path(e.path(), &config).map(|l| (e, l)));
let process = |(entry, language): (DirEntry, LanguageType)| {
let result = language.parse(entry.into_path(), &config);
let mut lock = languages.lock();
let entry = lock.entry(language).or_insert_with(Language::new);
match result {
Ok(stats) => {
let func = config.for_each_fn;
match func {
Some(f) => f(language, stats.clone()),
None => (),
};
entry.add_report(stats)
},
Err((error, path)) => {
entry.mark_inaccurate();
error!("Error reading {}:\n{}", path.display(), error);
}
let result = language.parse(entry.into_path(), &config);
let mut lock = languages.lock();
let entry = lock.entry(language).or_insert_with(Language::new);
match result {
Ok(stats) => {
let func = config.for_each_fn;
match func {
Some(f) => f(language, stats.clone()),
None => (),
};
entry.add_report(stats)
}
Err((error, path)) => {
entry.mark_inaccurate();
error!("Error reading {}:\n{}", path.display(), error);
}
}
};
if let Some(types) = config.types.as_deref() {