1
0
mirror of https://github.com/lise-henry/crowbook synced 2024-09-28 07:09:40 +02:00

Make indicatif dependency optional

This commit is contained in:
Elisabeth Henry 2017-10-08 20:50:13 +02:00
parent 167650d774
commit d5c7acff79
6 changed files with 215 additions and 155 deletions

View File

@ -37,7 +37,7 @@ doc = false
[features]
default = ["binary", "proofread", "syntect"]
proofread = ["caribon", "hyper", "url"]
binary = ["clap", "simplelog", "tempdir", "console"]
binary = ["clap", "simplelog", "tempdir", "console", "indicatif"]
[build-dependencies]
crowbook-intl = "0.2"
@ -57,7 +57,7 @@ crowbook-intl-runtime = "0.1"
numerals = "0.1"
epub-builder = "0.3"
log = "0.3"
indicatif = "0.7"
indicatif = { version = "0.7", optional = true }
console = { version = "0.5", optional = true }
caribon = { version = "0.8", optional = true }
clap = { version = "2.19", optional = true }

View File

@ -172,7 +172,7 @@ pub fn try_main() -> Result<()> {
{
let mut book = Book::new();
if fancy_ui {
book.add_progress_bar();
book.add_progress_bar(true);
}
book.set_options(&get_book_options(&matches));

View File

@ -35,21 +35,18 @@ use book_renderer::BookRenderer;
use chapter::Chapter;
use token::Token;
use text_view::view_as_text;
#[cfg(feature = "indicatif")]
use book_bars::Bars;
use std::thread;
use std::sync::Arc;
use indicatif::{ProgressBar, MultiProgress};
#[cfg(not(feature = "indicatif"))]
use book_bars_stubs::Bars;
#[cfg(feature = "proofread")]
use repetition_check::RepetitionDetector;
#[cfg(feature = "proofread")]
use grammar_check::GrammarChecker;
#[cfg(feature = "proofread")]
use grammalecte::GrammalecteChecker;
// Dummy grammarchecker thas does nothing to let the compiler compile
#[cfg(not(feature = "proofread"))]
struct GrammarChecker {}
@ -117,6 +114,23 @@ pub struct HeaderData {
pub title: String,
}
/// The types of bars
#[derive(Copy, Clone)]
pub enum Crowbar {
Main,
Second,
Spinner(usize),
}
/// The state of bars
#[derive(Copy, Clone)]
pub enum CrowbarState {
Running,
Success,
Error,
}
impl fmt::Display for HeaderData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.text)
@ -215,7 +229,7 @@ impl Book {
/// Sets an error message to the progress bar, if it is set
pub fn set_error(&self, msg: &str) {
self.private_set_error(msg)
self.bar_finish(Crowbar::Main, CrowbarState::Error, msg)
}
@ -223,8 +237,8 @@ impl Book {
/// Adds a progress bar where where info should be written.
///
/// See [indicatif doc](https://docs.rs/indicatif) for more information.
pub fn add_progress_bar(&mut self) {
self.private_add_progress_bar();
pub fn add_progress_bar(&mut self, emoji: bool) {
self.private_add_progress_bar(emoji);
}
/// Register a format that can be rendered.
@ -481,7 +495,7 @@ impl Book {
Ok(words[0])
}
self.mainbar_set_message(&lformat!("setting options"));
self.bar_set_message(Crowbar::Main, &lformat!("setting options"));
let mut s = String::new();
source.read_to_string(&mut s)
@ -566,7 +580,7 @@ impl Book {
// Update grammar checker according to options (proofread.*)
self.init_checker();
self.mainbar_set_message(&lformat!("Parsing chapters"));
self.bar_set_message(Crowbar::Main, &lformat!("Parsing chapters"));
// Parse chapters
let lines: Vec<_> = lines.collect();
@ -664,7 +678,7 @@ impl Book {
}
}
self.finish_second_bar();
self.bar_finish(Crowbar::Second, CrowbarState::Success, "");
self.source.unset_line();
self.set_chapter_template()?;
@ -785,7 +799,7 @@ impl Book {
self.render_format_with_bar(fmt, i);
});
self.set_finished(&lformat!("Finished"));
self.bar_finish(Crowbar::Main, CrowbarState::Success, &lformat!("Finished"));
// if handles.is_empty() {
// Logger::display_warning(lformat!("Crowbook generated no file because no output file was \
@ -798,10 +812,12 @@ impl Book {
let mut key = String::from("output.");
key.push_str(format);
if let Ok(path) = self.options.get_path(&key) {
self.nth_bar_set_message(bar, &lformat!("rendering..."));
self.bar_set_message(Crowbar::Spinner(bar), &lformat!("rendering..."));
let result = self.render_format_to_file_with_bar(format, path, bar);
if let Err(err) = result {
self.finish_nth_spinner_error(bar, format, &format!("{}", err));
self.bar_finish(Crowbar::Spinner(bar),
CrowbarState::Error,
&format!("{}", err));
error!("{}", lformat!("Error rendering {name}: {error}", name = format, error = err));
}
}
@ -840,10 +856,10 @@ impl Book {
format = description,
path = &path);
info!("{}", &msg);
self.finish_nth_spinner_success(bar,
format,
&lformat!("generated {path}",
path = path));
self.bar_finish(Crowbar::Spinner(bar),
CrowbarState::Success,
&lformat!("generated {path}",
path = path));
Ok(())
},
None => {
@ -875,19 +891,19 @@ impl Book {
match self.formats.get(format) {
Some(&(ref description, ref renderer)) => {
renderer.render(self, f)?;
self.finish_nth_spinner_success(bar,
format,
&lformat!("generated {format}",
format = format));
self.set_finished(&lformat!("Finished"));
self.bar_finish(Crowbar::Spinner(bar),
CrowbarState::Success,
&lformat!("generated {format}",
format = format));
self.bar_finish(Crowbar::Main, CrowbarState::Success, &lformat!("Finished"));
info!("{}", lformat!("Succesfully generated {format}",
format = description));
Ok(())
},
None => {
self.finish_nth_spinner_error(bar,
format,
&lformat!("unknown format"));
self.bar_finish(Crowbar::Spinner(bar),
CrowbarState::Error,
&lformat!("unknown format"));
Err(Error::default(Source::empty(),
lformat!("unknown format {format}",
format = format)))
@ -919,11 +935,11 @@ impl Book {
let path = path.into();
let normalized = misc::normalize(&path);
self.render_format_to_file_with_bar(format, path, bar)?;
self.finish_nth_spinner_success(bar,
format,
&lformat!("generated {path}",
path = normalized));
self.set_finished(&lformat!("Finished"));
self.bar_finish(Crowbar::Spinner(bar),
CrowbarState::Success,
&lformat!("generated {path}",
path = normalized));
self.bar_finish(Crowbar::Main, CrowbarState::Success, &lformat!("Finished"));
Ok(())
}
@ -937,7 +953,7 @@ impl Book {
file: &str,
mut source: R)
-> Result<&mut Self> {
self.mainbar_set_message(&lformat!("Processing {file}...", file = file));
self.bar_set_message(Crowbar::Main, &lformat!("Processing {file}...", file = file));
let mut content = String::new();
source.read_to_string(&mut content)
.map_err(|_| {
@ -950,7 +966,7 @@ impl Book {
self.parse_yaml(&mut content);
// parse the file
self.secondbar_set_message(&lformat!("Parsing..."));
self.bar_set_message(Crowbar::Second, &lformat!("Parsing..."));
let mut parser = Parser::from(self);
parser.set_source_file(file);
@ -999,7 +1015,7 @@ impl Book {
if cfg!(feature = "proofread") && self.is_proofread() {
let normalized = misc::normalize(file);
if let Some(ref checker) = self.checker {
self.secondbar_set_message(&lformat!("Running languagetool"));
self.bar_set_message(Crowbar::Second, &lformat!("Running languagetool"));
info!("{}", lformat!("Trying to run languagetool on {file}, this might take a \
while...",
@ -1011,7 +1027,7 @@ impl Book {
}
}
if let Some(ref checker) = self.grammalecte {
self.secondbar_set_message(&lformat!("Running grammalecte"));
self.bar_set_message(Crowbar::Second, &lformat!("Running grammalecte"));
info!("{}", lformat!("Trying to run grammalecte on {file}, this might take a \
while...",
@ -1023,7 +1039,7 @@ impl Book {
}
}
if let Some(ref detector) = self.detector {
self.secondbar_set_message(&lformat!("Detecting repetitions"));
self.bar_set_message(Crowbar::Second, &lformat!("Detecting repetitions"));
info!("{}", lformat!("Trying to run repetition detector on {file}, this might take a \
while...",
@ -1035,7 +1051,7 @@ impl Book {
}
}
}
self.secondbar_set_message("");
self.bar_set_message(Crowbar::Second, "");
self.chapters.push(Chapter::new(number, file, tokens));
@ -1089,8 +1105,9 @@ impl Book {
/// **Returns** an error if `file` does not exist, could not be read, of if there was
/// some error parsing it.
pub fn add_chapter(&mut self, number: Number, file: &str) -> Result<&mut Self> {
self.mainbar_set_message(&lformat!("Parsing {file}",
file = misc::normalize(file)));
self.bar_set_message(Crowbar::Main,
&lformat!("Parsing {file}",
file = misc::normalize(file)));
debug!("{}", lformat!("Parsing chapter: {file}...",
file = misc::normalize(file)));

View File

@ -18,19 +18,18 @@
// Progress bars implementation. Moved into a different file so it is possible
// to make some dependencies (incidacitf) optional.
use book::Book;
use error::{Result, Error, Source};
use misc;
use book::{Book, Crowbar, CrowbarState};
use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
use std::sync::Arc;
use std::thread;
use std::mem;
use std::path::{Path, PathBuf};
/// Store the progress bars needed for the book
pub struct Bars {
/// Whether or not to use emoji
pub emoji: bool,
/// Container for the progress bars
pub multibar: Option<Arc<MultiProgress>>,
/// Main progress bar (actually a spinner)
@ -47,6 +46,7 @@ impl Bars {
/// Create a new bars storage
pub fn new() -> Bars {
Bars {
emoji: false,
multibar: None,
mainbar: None,
secondbar: None,
@ -56,24 +56,28 @@ impl Bars {
}
}
/// Return the style of a bar
impl Book {
/// Adds a progress bar where where info should be written.
///
/// See [indicatif doc](https://docs.rs/indicatif) for more information.
pub fn private_add_progress_bar(&mut self) {
pub fn private_add_progress_bar(&mut self, emoji: bool) {
self.bars.emoji = emoji;
let multibar = Arc::new(MultiProgress::new());
self.bars.multibar = Some(multibar.clone());
let b = self.bars.multibar
.as_ref()
.unwrap()
.add(ProgressBar::new_spinner());
let sty = ProgressStyle::default_spinner()
.tick_chars("🕛🕐🕑🕒🕓🕔🕔🕕🕖🕗🕘🕘🕙🕚V")
// .tick_chars("/|\\-V")
.template("{spinner:.dim.bold.yellow} {prefix} {wide_msg}");
b.set_style(sty);
b.enable_steady_tick(200);
self.bars.mainbar = Some(b);
// let sty = ProgressStyle::default_spinner()
// .tick_chars("🕛🕐🕑🕒🕓🕔🕔🕕🕖🕗🕘🕘🕙🕚V")
// .tick_chars("/|\\-V")
// .template("{spinner:.dim.bold.yellow} {prefix} {wide_msg}");
self.bar_set_style(Crowbar::Main, CrowbarState::Running);
self.bars.guard = Some(thread::spawn(move || {
if let Err(_) = multibar.join() {
error!("{}", lformat!("could not display fancy UI, try running crowbook with --no-fancy"));
@ -81,49 +85,31 @@ impl Book {
}));
}
/// Sets an error message to the progress bar, if it is set
pub fn private_set_error(&self, msg: &str) {
if let Some(ref mainbar) = self.bars.mainbar {
let sty = ProgressStyle::default_spinner()
.tick_chars("/|\\-X")
.template("{spinner:.dim.bold.red} {wide_msg}");
mainbar.set_style(sty);
mainbar.set_message(msg);
}
}
/// Sets a finished message to the progress bar, if it is set
pub fn set_finished(&self, msg: &str) {
if let Some(ref bar) = self.bars.mainbar {
let sty = ProgressStyle::default_spinner()
.tick_chars("/|\\-V")
.template("{spinner:.dim.bold.cyan} {wide_msg}");
bar.set_style(sty);
bar.set_message(msg);
}
pub fn bar_finish(&self, bar: Crowbar, state: CrowbarState, msg: &str) {
self.bar_set_style(bar, state);
let pb = match bar {
Crowbar::Main => if let Some(ref bar) = self.bars.mainbar { bar } else { return; },
Crowbar::Second => if let Some(ref bar) = self.bars.secondbar { bar } else { return; },
Crowbar::Spinner(i) => if i < self.bars.spinners.len() { &self.bars.spinners[i] } else { return; },
};
match bar {
Crowbar::Second => pb.finish_and_clear(),
_ => pb.finish_with_message(msg),
};
}
/// Adds a secondary progress bar to display progress of book parsing
pub fn add_second_bar(&mut self, msg: &str, len: u64) {
if let Some(ref multibar) = self.bars.multibar {
let bar = multibar.add(ProgressBar::new(len));
bar.set_style(ProgressStyle::default_bar()
.template("{bar:40.cyan/blue} {percent:>7}% {msg}")
.progress_chars("##-"));
self.bar_set_style(Crowbar::Second, CrowbarState::Running);
bar.set_message(msg);
self.bars.secondbar = Some(bar);
}
}
/// Finish secondary prograss bar
pub fn finish_second_bar(&self) {
if let Some(ref bar) = self.bars.secondbar {
bar.finish_and_clear();
}
}
/// Increment second bar
pub fn inc_second_bar(&self) {
if let Some(ref bar) = self.bars.secondbar {
@ -139,87 +125,82 @@ impl Book {
}
let bar = multibar.add(ProgressBar::new_spinner());
let sty = ProgressStyle::default_spinner()
.tick_chars("/|\\-X")
.template(&format!("{{spinner:.dim.bold.yellow}} {format}: {{wide_msg:.yellow}}",
format = key));
bar.set_style(sty);
bar.enable_steady_tick(200);
bar.set_message(&lformat!("waiting..."));
bar.tick();
bar.set_prefix(&format!("{}:", key));
let i = self.bars.spinners.len();
self.bars.spinners.push(bar);
return self.bars.spinners.len() - 1;
self.bar_set_style(Crowbar::Spinner(i), CrowbarState::Running);
i
} else {
0
}
}
pub fn mainbar_set_message(&self, msg: &str) {
if let Some(ref bar) = self.bars.mainbar {
bar.set_message(msg);
bar.tick();
}
pub fn bar_set_message(&self, bar: Crowbar, msg: &str) {
let bar = match bar {
Crowbar::Main => if let Some(ref bar) = self.bars.mainbar { bar } else { return; },
Crowbar::Second => if let Some(ref bar) = self.bars.secondbar { bar } else { return; },
Crowbar::Spinner(i) => if i < self.bars.spinners.len() { &self.bars.spinners[i] } else { return; },
};
bar.set_message(msg);
}
pub fn secondbar_set_message(&self, msg: &str) {
if let Some(ref bar) = self.bars.secondbar {
bar.set_message(msg);
bar.tick();
}
}
pub fn nth_bar_set_message(&self, bar: usize, msg: &str) {
if bar < self.bars.spinners.len() {
let bar = &self.bars.spinners[bar];
bar.set_message(msg);
bar.tick();
/// Sets the style of a bar
fn bar_set_style(&self, bar: Crowbar, state: CrowbarState) -> () {
let pb = match bar {
Crowbar::Main => if let Some(ref bar) = self.bars.mainbar { bar } else { return; },
Crowbar::Second => if let Some(ref bar) = self.bars.secondbar { bar } else { return; },
Crowbar::Spinner(i) => if i < self.bars.spinners.len() { &self.bars.spinners[i] } else { return; },
};
let emoji = self.bars.emoji;
let mut style = match bar {
Crowbar::Second => ProgressStyle::default_bar(),
_ => ProgressStyle::default_spinner()
};
let color = match state {
CrowbarState::Running => "magenta",
CrowbarState::Success => "cyan",
CrowbarState::Error => "red",
};
let tick_chars = match (bar, emoji) {
(Crowbar::Main, false) | (Crowbar::Spinner(_), false) => "-\\|/",
(Crowbar::Main, true) => "🕛🕐🕑🕒🕓🕔🕔🕕🕖🕗🕘🕘🕙🕚",
(Crowbar::Spinner(_), true) => "-\\|/",
(_, _) => ""
};
let end_tick = match (state, emoji) {
(CrowbarState::Running, _) => "V",
(CrowbarState::Success, true) => "",
(CrowbarState::Error, true) => "",
(CrowbarState::Success, false) => "V",
(CrowbarState::Error, false) => "X",
};
match bar {
Crowbar::Second => {
style = style.template("{bar:40.cyan/blue} {percent:>7} {wide_msg}")
.progress_chars("##-");
},
bar => {
style = style.tick_chars(&format!("{}{}", tick_chars, end_tick));
match bar {
Crowbar::Spinner(_) => {
style = style
.template(&format!("{{spinner:.bold.{color}}} {{prefix}} {{wide_msg}}",
color = color));
},
_ => {
style = style
.template(&format!("{{spinner:.bold.{color}}} {{prefix}}{{wide_msg}}",
color = color));
},
};
},
}
}
// Finish a spinner with an error message
pub fn finish_nth_spinner_error(&self, bar: usize, key: &str, msg: &str) {
if bar < self.bars.spinners.len() {
let bar = &self.bars.spinners[bar];
bar.set_style(ProgressStyle::default_spinner()
.tick_chars("/|\\-X")
.template(&format!("{{spinner:.dim.bold.red}} {format}: {{wide_msg:.red}}",
format = key)));
bar.finish_with_message(msg);
}
}
// Finish a spinner with success message
pub fn finish_nth_spinner_success(&self, bar: usize, key: &str, msg: &str) {
if bar < self.bars.spinners.len() {
let bar = &self.bars.spinners[bar];
let sty = ProgressStyle::default_spinner()
.tick_chars("/|\\-V")
.template(&format!("{{spinner:.dim.bold.cyan}} {format}: {{wide_msg:.cyan}}",
format = key));
bar.set_style(sty);
bar.finish_with_message(msg);
}
}
// Finish a spinner with an error message
pub fn finish_spinner_error(&self, bar: &ProgressBar, key: &str, msg: &str) {
bar.set_style(ProgressStyle::default_spinner()
.tick_chars("/|\\-X")
.template(&format!("{{spinner:.dim.bold.red}} {format}: {{wide_msg:.red}}",
format = key)));
bar.finish_with_message(msg);
}
// Finish a spinner with success message
pub fn finish_spinner_success(&self, bar: &ProgressBar, key: &str, msg: &str) {
let sty = ProgressStyle::default_spinner()
.tick_chars("/|\\-V")
.template(&format!("{{spinner:.dim.bold.cyan}} {format}: {{wide_msg:.cyan}}",
format = key));
bar.set_style(sty);
bar.finish_with_message(msg);
pb.set_style(style);
}
}

View File

@ -0,0 +1,57 @@
// Copyright (C) 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook. If not, see <http://www.gnu.org/licenses/>.
// Progress bars non-implementation. Used when indicatif is not compiled.
use book::{Book, Crowbar, CrowbarState};
/// Dummy bars implementation
pub struct Bars {
}
impl Bars {
pub fn new() -> Bars {
Bars {
}
}
}
impl Book {
pub fn private_add_progress_bar(&mut self, _: bool) {
}
/// Sets a finished message to the progress bar, if it is set
pub fn bar_finish(&self, _: Crowbar, _: CrowbarState, _: &str) {
}
/// Adds a secondary progress bar to display progress of book parsing
pub fn add_second_bar(&mut self, _: &str, _: u64) {
}
/// Increment second bar
pub fn inc_second_bar(&self) {
}
/// Adds a spinner labeled key to the multibar, and set mainbar to "rendering"
pub fn add_spinner_to_multibar(&mut self, _: &str) -> usize {
0
}
pub fn bar_set_message(&self, _: Crowbar, _: &str) {
}
}

View File

@ -116,12 +116,13 @@ extern crate crowbook_intl_runtime;
extern crate numerals;
extern crate epub_builder;
extern crate uuid;
extern crate indicatif;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "indicatif")]
extern crate indicatif;
#[cfg(feature = "proofread")]
extern crate hyper;
#[cfg(feature = "proofread")]
@ -171,7 +172,11 @@ mod html_single;
mod html_if;
mod syntax;
mod stats;
#[cfg(feature = "indicatif")]
mod book_bars;
#[cfg(not(feature = "indicatif"))]
mod book_bars_stubs;
mod zipper;
mod templates;