Presently when you `^C` in `zola serve` it is painted with the same color as the previous message. This PR always ensures to reset the color in colorize, before writing the newline.
131 lines
4.1 KiB
Rust
131 lines
4.1 KiB
Rust
use std::env;
|
|
use std::error::Error as StdError;
|
|
use std::io::Write;
|
|
use std::time::Instant;
|
|
|
|
use atty;
|
|
use chrono::Duration;
|
|
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
|
|
|
use errors::Error;
|
|
use site::Site;
|
|
|
|
lazy_static! {
|
|
/// Termcolor color choice.
|
|
/// We do not rely on ColorChoice::Auto behavior
|
|
/// as the check is already performed by has_color.
|
|
static ref COLOR_CHOICE: ColorChoice =
|
|
if has_color() {
|
|
ColorChoice::Always
|
|
} else {
|
|
ColorChoice::Never
|
|
};
|
|
}
|
|
|
|
pub fn info(message: &str) {
|
|
colorize(message, ColorSpec::new().set_bold(true));
|
|
}
|
|
|
|
pub fn warn(message: &str) {
|
|
colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Yellow)));
|
|
}
|
|
|
|
pub fn success(message: &str) {
|
|
colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Green)));
|
|
}
|
|
|
|
pub fn error(message: &str) {
|
|
colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Red)));
|
|
}
|
|
|
|
/// Print a colorized message to stdout
|
|
fn colorize(message: &str, color: &ColorSpec) {
|
|
let mut stdout = StandardStream::stdout(*COLOR_CHOICE);
|
|
stdout.set_color(color).unwrap();
|
|
write!(&mut stdout, "{}", message).unwrap();
|
|
stdout.set_color(&ColorSpec::new()).unwrap();
|
|
writeln!(&mut stdout).unwrap();
|
|
}
|
|
|
|
/// Display in the console the number of pages/sections in the site, and number of images to process
|
|
pub fn notify_site_size(site: &Site) {
|
|
let library = site.library.read().unwrap();
|
|
println!(
|
|
"-> Creating {} pages ({} orphan), {} sections, and processing {} images",
|
|
library.pages().len(),
|
|
site.get_number_orphan_pages(),
|
|
library.sections().len() - 1, // -1 since we do not count the index as a section there
|
|
site.num_img_ops(),
|
|
);
|
|
}
|
|
|
|
/// Display in the console only the number of pages/sections in the site
|
|
pub fn check_site_summary(site: &Site) {
|
|
let library = site.library.read().unwrap();
|
|
let orphans = library.get_all_orphan_pages();
|
|
println!(
|
|
"-> Site content: {} pages ({} orphan), {} sections",
|
|
library.pages().len(),
|
|
orphans.len(),
|
|
library.sections().len() - 1, // -1 since we do not count the index as a section there
|
|
);
|
|
|
|
for orphan in orphans {
|
|
warn(&format!("Orphan page found: {}", orphan.path));
|
|
}
|
|
}
|
|
|
|
/// Display a warning in the console if there are ignored pages in the site
|
|
pub fn warn_about_ignored_pages(site: &Site) {
|
|
let library = site.library.read().unwrap();
|
|
let ignored_pages: Vec<_> = library
|
|
.sections_values()
|
|
.iter()
|
|
.flat_map(|s| s.ignored_pages.iter().map(|k| library.get_page_by_key(*k).file.path.clone()))
|
|
.collect();
|
|
|
|
if !ignored_pages.is_empty() {
|
|
warn(&format!(
|
|
"{} page(s) ignored (missing date or weight in a sorted section):",
|
|
ignored_pages.len()
|
|
));
|
|
for path in ignored_pages {
|
|
warn(&format!("- {}", path.display()));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Print the time elapsed rounded to 1 decimal
|
|
pub fn report_elapsed_time(instant: Instant) {
|
|
let duration_ms = Duration::from_std(instant.elapsed()).unwrap().num_milliseconds() as f64;
|
|
|
|
if duration_ms < 1000.0 {
|
|
success(&format!("Done in {}ms.\n", duration_ms));
|
|
} else {
|
|
let duration_sec = duration_ms / 1000.0;
|
|
success(&format!("Done in {:.1}s.\n", ((duration_sec * 10.0).round() / 10.0)));
|
|
}
|
|
}
|
|
|
|
/// Display an error message and the actual error(s)
|
|
pub fn unravel_errors(message: &str, error: &Error) {
|
|
if !message.is_empty() {
|
|
self::error(message);
|
|
}
|
|
self::error(&format!("Error: {}", error));
|
|
let mut cause = error.source();
|
|
while let Some(e) = cause {
|
|
self::error(&format!("Reason: {}", e));
|
|
cause = e.source();
|
|
}
|
|
}
|
|
|
|
/// Check whether to output colors
|
|
fn has_color() -> bool {
|
|
let use_colors = env::var("CLICOLOR").unwrap_or_else(|_| "1".to_string()) != "0"
|
|
&& env::var("NO_COLOR").is_err();
|
|
let force_colors = env::var("CLICOLOR_FORCE").unwrap_or_else(|_| "0".to_string()) != "0";
|
|
|
|
force_colors || use_colors && atty::is(atty::Stream::Stdout)
|
|
}
|