mirror of
https://github.com/lise-henry/crowbook
synced 2024-09-29 08:11:25 +02:00
Refactor in progress (bar)
This commit is contained in:
parent
3aaffcbf72
commit
167650d774
292
src/lib/book.rs
292
src/lib/book.rs
@ -35,10 +35,10 @@ use book_renderer::BookRenderer;
|
|||||||
use chapter::Chapter;
|
use chapter::Chapter;
|
||||||
use token::Token;
|
use token::Token;
|
||||||
use text_view::view_as_text;
|
use text_view::view_as_text;
|
||||||
|
use book_bars::Bars;
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use indicatif::{ProgressBar, MultiProgress};
|
use indicatif::{ProgressBar, MultiProgress};
|
||||||
|
|
||||||
@ -178,13 +178,7 @@ pub struct Book {
|
|||||||
formats: HashMap<&'static str, (String, Box<BookRenderer>)>,
|
formats: HashMap<&'static str, (String, Box<BookRenderer>)>,
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub multibar: Option<Arc<MultiProgress>>,
|
pub bars: Bars,
|
||||||
#[doc(hidden)]
|
|
||||||
pub mainbar: Option<ProgressBar>,
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub secondbar: Option<ProgressBar>,
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub guard: Option<thread::JoinHandle<()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Book {
|
impl Book {
|
||||||
@ -203,10 +197,7 @@ impl Book {
|
|||||||
detector: None,
|
detector: None,
|
||||||
formats: HashMap::new(),
|
formats: HashMap::new(),
|
||||||
features: Features::new(),
|
features: Features::new(),
|
||||||
multibar: None,
|
bars: Bars::new(),
|
||||||
mainbar: None,
|
|
||||||
secondbar: None,
|
|
||||||
guard: None,
|
|
||||||
};
|
};
|
||||||
book.add_format("html", lformat!("HTML (standalone page)"), Box::new(HtmlSingle{}))
|
book.add_format("html", lformat!("HTML (standalone page)"), Box::new(HtmlSingle{}))
|
||||||
.add_format("proofread.html", lformat!("HTML (standalone page/proofreading)"), Box::new(ProofHtmlSingle{}))
|
.add_format("proofread.html", lformat!("HTML (standalone page/proofreading)"), Box::new(ProofHtmlSingle{}))
|
||||||
@ -490,10 +481,7 @@ impl Book {
|
|||||||
Ok(words[0])
|
Ok(words[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref bar) = self.mainbar {
|
self.mainbar_set_message(&lformat!("setting options"));
|
||||||
bar.set_message(&lformat!("setting options"));
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
source.read_to_string(&mut s)
|
source.read_to_string(&mut s)
|
||||||
@ -509,10 +497,6 @@ impl Book {
|
|||||||
let mut line_number = 0;
|
let mut line_number = 0;
|
||||||
let mut is_next_line_ok: bool;
|
let mut is_next_line_ok: bool;
|
||||||
|
|
||||||
if let Some(ref bar) = self.mainbar {
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(next_line) = lines.peek() {
|
if let Some(next_line) = lines.peek() {
|
||||||
if next_line.starts_with(|c| match c {
|
if next_line.starts_with(|c| match c {
|
||||||
@ -582,10 +566,7 @@ impl Book {
|
|||||||
// Update grammar checker according to options (proofread.*)
|
// Update grammar checker according to options (proofread.*)
|
||||||
self.init_checker();
|
self.init_checker();
|
||||||
|
|
||||||
if let Some(ref bar) = self.mainbar {
|
self.mainbar_set_message(&lformat!("Parsing chapters"));
|
||||||
bar.set_message(&lformat!("parsing chapters"));
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse chapters
|
// Parse chapters
|
||||||
let lines: Vec<_> = lines.collect();
|
let lines: Vec<_> = lines.collect();
|
||||||
@ -733,24 +714,6 @@ impl Book {
|
|||||||
#[cfg(not(feature = "proofread"))]
|
#[cfg(not(feature = "proofread"))]
|
||||||
fn init_checker(&mut self) {}
|
fn init_checker(&mut self) {}
|
||||||
|
|
||||||
/// Renders the book to the given format and reports to progress bar if set
|
|
||||||
pub fn render_format_with_bar(&self, format: &str, bar: Option<&ProgressBar>) -> () {
|
|
||||||
let mut key = String::from("output.");
|
|
||||||
key.push_str(format);
|
|
||||||
if let Ok(path) = self.options.get_path(&key) {
|
|
||||||
if let Some(bar) = bar {
|
|
||||||
bar.set_message(&lformat!("rendering..."));
|
|
||||||
}
|
|
||||||
let result = self.render_format_to_file_with_bar(format, path, bar);
|
|
||||||
if let Err(err) = result {
|
|
||||||
if let Some(bar) = bar {
|
|
||||||
self.finish_spinner_error(bar, format, &format!("{}", err));
|
|
||||||
}
|
|
||||||
error!("{}", lformat!("Error rendering {name}: {error}", name = format, error = err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Renders the book to the given format if output.{format} is set;
|
/// Renders the book to the given format if output.{format} is set;
|
||||||
/// do nothing otherwise.
|
/// do nothing otherwise.
|
||||||
///
|
///
|
||||||
@ -763,7 +726,8 @@ impl Book {
|
|||||||
/// book.render_format("pdf");
|
/// book.render_format("pdf");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn render_format(&self, format: &str) -> () {
|
pub fn render_format(&self, format: &str) -> () {
|
||||||
self.render_format_with_bar(format, None)
|
// TODO: check that it doesn't break everything, or use option?
|
||||||
|
self.render_format_with_bar(format, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates output files acccording to book options.
|
/// Generates output files acccording to book options.
|
||||||
@ -787,7 +751,7 @@ impl Book {
|
|||||||
/// .unwrap()
|
/// .unwrap()
|
||||||
/// .render_all(); // renders foo.tex in /tmp
|
/// .render_all(); // renders foo.tex in /tmp
|
||||||
/// ```
|
/// ```
|
||||||
pub fn render_all(&self) -> () {
|
pub fn render_all(&mut self) -> () {
|
||||||
let mut keys: Vec<_> = self.formats
|
let mut keys: Vec<_> = self.formats
|
||||||
.keys()
|
.keys()
|
||||||
.filter(|fmt| {
|
.filter(|fmt| {
|
||||||
@ -798,6 +762,7 @@ impl Book {
|
|||||||
}
|
}
|
||||||
self.options.get_path(&format!("output.{}", fmt)).is_ok()
|
self.options.get_path(&format!("output.{}", fmt)).is_ok()
|
||||||
})
|
})
|
||||||
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
// Make sure that PDF comes first since running latex takes lots of time
|
// Make sure that PDF comes first since running latex takes lots of time
|
||||||
keys.sort_by(|fmt1, fmt2| {
|
keys.sort_by(|fmt1, fmt2| {
|
||||||
@ -810,22 +775,14 @@ impl Book {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut bars = vec![];
|
for key in &keys {
|
||||||
if let Some(ref multibar) = self.multibar {
|
self.add_spinner_to_multibar(key);
|
||||||
for key in &keys {
|
|
||||||
let bar = self.add_spinner_to_multibar(multibar, key);
|
|
||||||
bars.push(bar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keys.par_iter()
|
keys.par_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, fmt)| {
|
.for_each(|(i, fmt)| {
|
||||||
if self.multibar.is_some() {
|
self.render_format_with_bar(fmt, i);
|
||||||
self.render_format_with_bar(fmt, Some(&bars[i]));
|
|
||||||
} else {
|
|
||||||
self.render_format_with_bar(fmt, None);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.set_finished(&lformat!("Finished"));
|
self.set_finished(&lformat!("Finished"));
|
||||||
@ -836,87 +793,24 @@ impl Book {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders the book to the given format and reports to progress bar if set
|
||||||
/// Render book to specified format according to book options, and write the results
|
pub fn render_format_with_bar(&self, format: &str, bar: usize) -> () {
|
||||||
/// in the `Write` object.
|
let mut key = String::from("output.");
|
||||||
///
|
key.push_str(format);
|
||||||
/// This method will fail if the format is not handled by the book, or if there is a
|
if let Ok(path) = self.options.get_path(&key) {
|
||||||
/// problem during rendering, or if the renderer can't render to a byte stream (e.g.
|
self.nth_bar_set_message(bar, &lformat!("rendering..."));
|
||||||
/// multiple files HTML renderer can't, as it must create a directory.)
|
let result = self.render_format_to_file_with_bar(format, path, bar);
|
||||||
///
|
if let Err(err) = result {
|
||||||
/// # See also
|
self.finish_nth_spinner_error(bar, format, &format!("{}", err));
|
||||||
/// * `render_format_to_file`, which creates a new file (that *can* be a directory).
|
error!("{}", lformat!("Error rendering {name}: {error}", name = format, error = err));
|
||||||
/// * `render_format`, which won't do anything if `output.{format}` isn't specified
|
|
||||||
/// in the book configuration file.
|
|
||||||
pub fn render_format_to<T: Write>(&self, format: &str, f: &mut T) -> Result<()> {
|
|
||||||
debug!("{}", lformat!("Attempting to generate {format}...",
|
|
||||||
format = format));
|
|
||||||
match self.formats.get(format) {
|
|
||||||
Some(&(ref description, ref renderer)) => {
|
|
||||||
if let Some(ref multibar) = self.multibar {
|
|
||||||
let bar = self.add_spinner_to_multibar(multibar, format);
|
|
||||||
renderer.render(self, f)?;
|
|
||||||
self.finish_spinner_success(&bar,
|
|
||||||
format,
|
|
||||||
&lformat!("generated {format}",
|
|
||||||
format = format));
|
|
||||||
self.set_finished(&lformat!("Finished"));
|
|
||||||
} else {
|
|
||||||
renderer.render(self, f)?;
|
|
||||||
}
|
|
||||||
info!("{}", lformat!("Succesfully generated {format}",
|
|
||||||
format = description));
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
Err(Error::default(Source::empty(),
|
|
||||||
lformat!("unknown format {format}",
|
|
||||||
format = format)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render book to specified format according to book options. Creates a new file
|
pub fn render_format_to_file_with_bar<P:Into<PathBuf>>(&self,
|
||||||
/// and write the result in it.
|
format: &str,
|
||||||
///
|
path: P,
|
||||||
/// This method will fail if the format is not handled by the book, or if there is a
|
bar: usize) -> Result<()> {
|
||||||
/// problem during rendering.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `format`: the format to render;
|
|
||||||
/// * `path`: a path to the file that will be created;
|
|
||||||
/// * `bar`: a Progressbar, or `None`
|
|
||||||
///
|
|
||||||
/// # See also
|
|
||||||
/// * `render_format_to`, which writes in any `Write`able object.
|
|
||||||
/// * `render_format`, which won't do anything if `output.{format}` isn't specified
|
|
||||||
/// in the book configuration file.
|
|
||||||
|
|
||||||
pub fn render_format_to_file<P:Into<PathBuf>>(&self,
|
|
||||||
format: &str,
|
|
||||||
path: P) -> Result<()> {
|
|
||||||
if let Some(ref multibar) = self.multibar {
|
|
||||||
let bar = self.add_spinner_to_multibar(multibar, format);
|
|
||||||
let path = path.into();
|
|
||||||
let normalized = misc::normalize(&path);
|
|
||||||
self.render_format_to_file_with_bar(format, path, Some(&bar))?;
|
|
||||||
self.finish_spinner_success(&bar,
|
|
||||||
format,
|
|
||||||
&lformat!("generated {path}",
|
|
||||||
path = normalized));
|
|
||||||
self.set_finished(&lformat!("Finished"));
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
self.render_format_to_file_with_bar(format, path, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn render_format_to_file_with_bar<P:Into<PathBuf>>(&self,
|
|
||||||
format: &str,
|
|
||||||
path: P,
|
|
||||||
bar: Option<&ProgressBar>) -> Result<()> {
|
|
||||||
debug!("{}", lformat!("Attempting to generate {format}...",
|
debug!("{}", lformat!("Attempting to generate {format}...",
|
||||||
format = format));
|
format = format));
|
||||||
let path = path.into();
|
let path = path.into();
|
||||||
@ -946,12 +840,10 @@ impl Book {
|
|||||||
format = description,
|
format = description,
|
||||||
path = &path);
|
path = &path);
|
||||||
info!("{}", &msg);
|
info!("{}", &msg);
|
||||||
if let Some(bar) = bar {
|
self.finish_nth_spinner_success(bar,
|
||||||
self.finish_spinner_success(bar,
|
format,
|
||||||
format,
|
&lformat!("generated {path}",
|
||||||
&lformat!("generated {path}",
|
path = path));
|
||||||
path = path));
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
@ -962,6 +854,81 @@ impl Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Render book to specified format according to book options, and write the results
|
||||||
|
/// in the `Write` object.
|
||||||
|
///
|
||||||
|
/// This method will fail if the format is not handled by the book, or if there is a
|
||||||
|
/// problem during rendering, or if the renderer can't render to a byte stream (e.g.
|
||||||
|
/// multiple files HTML renderer can't, as it must create a directory.)
|
||||||
|
///
|
||||||
|
/// # See also
|
||||||
|
/// * `render_format_to_file`, which creates a new file (that *can* be a directory).
|
||||||
|
/// * `render_format`, which won't do anything if `output.{format}` isn't specified
|
||||||
|
/// in the book configuration file.
|
||||||
|
pub fn render_format_to<T: Write>(&mut self, format: &str, f: &mut T) -> Result<()> {
|
||||||
|
debug!("{}", lformat!("Attempting to generate {format}...",
|
||||||
|
format = format));
|
||||||
|
let bar = self.add_spinner_to_multibar(format);
|
||||||
|
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"));
|
||||||
|
info!("{}", lformat!("Succesfully generated {format}",
|
||||||
|
format = description));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.finish_nth_spinner_error(bar,
|
||||||
|
format,
|
||||||
|
&lformat!("unknown format"));
|
||||||
|
Err(Error::default(Source::empty(),
|
||||||
|
lformat!("unknown format {format}",
|
||||||
|
format = format)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render book to specified format according to book options. Creates a new file
|
||||||
|
/// and write the result in it.
|
||||||
|
///
|
||||||
|
/// This method will fail if the format is not handled by the book, or if there is a
|
||||||
|
/// problem during rendering.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `format`: the format to render;
|
||||||
|
/// * `path`: a path to the file that will be created;
|
||||||
|
/// * `bar`: a Progressbar, or `None`
|
||||||
|
///
|
||||||
|
/// # See also
|
||||||
|
/// * `render_format_to`, which writes in any `Write`able object.
|
||||||
|
/// * `render_format`, which won't do anything if `output.{format}` isn't specified
|
||||||
|
/// in the book configuration file.
|
||||||
|
|
||||||
|
pub fn render_format_to_file<P:Into<PathBuf>>(&mut self,
|
||||||
|
format: &str,
|
||||||
|
path: P) -> Result<()> {
|
||||||
|
let bar = self.add_spinner_to_multibar(format);
|
||||||
|
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"));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds a chapter to the book.
|
/// Adds a chapter to the book.
|
||||||
///
|
///
|
||||||
/// This method is the backend used both by `add_chapter` and `add_chapter_from_source`.
|
/// This method is the backend used both by `add_chapter` and `add_chapter_from_source`.
|
||||||
@ -970,10 +937,7 @@ impl Book {
|
|||||||
file: &str,
|
file: &str,
|
||||||
mut source: R)
|
mut source: R)
|
||||||
-> Result<&mut Self> {
|
-> Result<&mut Self> {
|
||||||
if let Some(ref bar) = self.mainbar {
|
self.mainbar_set_message(&lformat!("Processing {file}...", file = file));
|
||||||
bar.set_message(&lformat!("Processing {file}...", file = file));
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
source.read_to_string(&mut content)
|
source.read_to_string(&mut content)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@ -986,10 +950,8 @@ impl Book {
|
|||||||
self.parse_yaml(&mut content);
|
self.parse_yaml(&mut content);
|
||||||
|
|
||||||
// parse the file
|
// parse the file
|
||||||
if let Some(ref bar) = self.secondbar {
|
self.secondbar_set_message(&lformat!("Parsing..."));
|
||||||
bar.set_message(&lformat!("Parsing..."));
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
let mut parser = Parser::from(self);
|
let mut parser = Parser::from(self);
|
||||||
parser.set_source_file(file);
|
parser.set_source_file(file);
|
||||||
let mut tokens = parser.parse(&content)?;
|
let mut tokens = parser.parse(&content)?;
|
||||||
@ -1037,9 +999,7 @@ impl Book {
|
|||||||
if cfg!(feature = "proofread") && self.is_proofread() {
|
if cfg!(feature = "proofread") && self.is_proofread() {
|
||||||
let normalized = misc::normalize(file);
|
let normalized = misc::normalize(file);
|
||||||
if let Some(ref checker) = self.checker {
|
if let Some(ref checker) = self.checker {
|
||||||
if let Some(ref bar) = self.secondbar {
|
self.secondbar_set_message(&lformat!("Running languagetool"));
|
||||||
bar.set_message(&lformat!("Running languagetool"));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("{}", lformat!("Trying to run languagetool on {file}, this might take a \
|
info!("{}", lformat!("Trying to run languagetool on {file}, this might take a \
|
||||||
while...",
|
while...",
|
||||||
@ -1051,9 +1011,7 @@ impl Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref checker) = self.grammalecte {
|
if let Some(ref checker) = self.grammalecte {
|
||||||
if let Some(ref bar) = self.secondbar {
|
self.secondbar_set_message(&lformat!("Running grammalecte"));
|
||||||
bar.set_message(&lformat!("Running grammalecte"));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("{}", lformat!("Trying to run grammalecte on {file}, this might take a \
|
info!("{}", lformat!("Trying to run grammalecte on {file}, this might take a \
|
||||||
while...",
|
while...",
|
||||||
@ -1065,9 +1023,7 @@ impl Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref detector) = self.detector {
|
if let Some(ref detector) = self.detector {
|
||||||
if let Some(ref bar) = self.secondbar {
|
self.secondbar_set_message(&lformat!("Detecting repetitions"));
|
||||||
bar.set_message(&lformat!("Detecting repetitions"));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("{}", lformat!("Trying to run repetition detector on {file}, this might take a \
|
info!("{}", lformat!("Trying to run repetition detector on {file}, this might take a \
|
||||||
while...",
|
while...",
|
||||||
@ -1079,9 +1035,8 @@ impl Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref bar) = self.secondbar {
|
self.secondbar_set_message("");
|
||||||
bar.set_message("");
|
|
||||||
}
|
|
||||||
self.chapters.push(Chapter::new(number, file, tokens));
|
self.chapters.push(Chapter::new(number, file, tokens));
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
@ -1134,11 +1089,8 @@ impl Book {
|
|||||||
/// **Returns** an error if `file` does not exist, could not be read, of if there was
|
/// **Returns** an error if `file` does not exist, could not be read, of if there was
|
||||||
/// some error parsing it.
|
/// some error parsing it.
|
||||||
pub fn add_chapter(&mut self, number: Number, file: &str) -> Result<&mut Self> {
|
pub fn add_chapter(&mut self, number: Number, file: &str) -> Result<&mut Self> {
|
||||||
if let Some(ref bar) = self.mainbar {
|
self.mainbar_set_message(&lformat!("Parsing {file}",
|
||||||
bar.set_message(&lformat!("Parsing {file}",
|
file = misc::normalize(file)));
|
||||||
file = misc::normalize(file)));
|
|
||||||
bar.tick();
|
|
||||||
}
|
|
||||||
debug!("{}", lformat!("Parsing chapter: {file}...",
|
debug!("{}", lformat!("Parsing chapter: {file}...",
|
||||||
file = misc::normalize(file)));
|
file = misc::normalize(file)));
|
||||||
|
|
||||||
@ -1527,20 +1479,6 @@ impl Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Drop for Book {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(ref bar) = self.mainbar {
|
|
||||||
bar.finish();
|
|
||||||
let guard = mem::replace(&mut self.guard, None);
|
|
||||||
guard.unwrap()
|
|
||||||
.join()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Calls mustache::compile_str but catches panics and returns a result
|
/// Calls mustache::compile_str but catches panics and returns a result
|
||||||
pub fn compile_str<O>(template: &str, source: O, template_name: &str) -> Result<mustache::Template>
|
pub fn compile_str<O>(template: &str, source: O, template_name: &str) -> Result<mustache::Template>
|
||||||
where O: Into<Source>
|
where O: Into<Source>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2016, 2017 Élisabeth HENRY.
|
// Copyright (C) 2017 Élisabeth HENRY.
|
||||||
//
|
//
|
||||||
// This file is part of Crowbook.
|
// This file is part of Crowbook.
|
||||||
//
|
//
|
||||||
@ -19,11 +19,42 @@
|
|||||||
// to make some dependencies (incidacitf) optional.
|
// to make some dependencies (incidacitf) optional.
|
||||||
|
|
||||||
use book::Book;
|
use book::Book;
|
||||||
|
use error::{Result, Error, Source};
|
||||||
|
use misc;
|
||||||
|
|
||||||
use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
|
use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// Store the progress bars needed for the book
|
||||||
|
pub struct Bars {
|
||||||
|
/// Container for the progress bars
|
||||||
|
pub multibar: Option<Arc<MultiProgress>>,
|
||||||
|
/// Main progress bar (actually a spinner)
|
||||||
|
pub mainbar: Option<ProgressBar>,
|
||||||
|
/// Secondary bar
|
||||||
|
pub secondbar: Option<ProgressBar>,
|
||||||
|
/// Guard for thread
|
||||||
|
pub guard: Option<thread::JoinHandle<()>>,
|
||||||
|
/// Spinners for each renderier
|
||||||
|
pub spinners: Vec<ProgressBar>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bars {
|
||||||
|
/// Create a new bars storage
|
||||||
|
pub fn new() -> Bars {
|
||||||
|
Bars {
|
||||||
|
multibar: None,
|
||||||
|
mainbar: None,
|
||||||
|
secondbar: None,
|
||||||
|
guard: None,
|
||||||
|
spinners: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Book {
|
impl Book {
|
||||||
/// Adds a progress bar where where info should be written.
|
/// Adds a progress bar where where info should be written.
|
||||||
@ -31,8 +62,8 @@ impl Book {
|
|||||||
/// See [indicatif doc](https://docs.rs/indicatif) for more information.
|
/// 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) {
|
||||||
let multibar = Arc::new(MultiProgress::new());
|
let multibar = Arc::new(MultiProgress::new());
|
||||||
self.multibar = Some(multibar.clone());
|
self.bars.multibar = Some(multibar.clone());
|
||||||
let b = self.multibar
|
let b = self.bars.multibar
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.add(ProgressBar::new_spinner());
|
.add(ProgressBar::new_spinner());
|
||||||
@ -42,8 +73,8 @@ impl Book {
|
|||||||
.template("{spinner:.dim.bold.yellow} {prefix} {wide_msg}");
|
.template("{spinner:.dim.bold.yellow} {prefix} {wide_msg}");
|
||||||
b.set_style(sty);
|
b.set_style(sty);
|
||||||
b.enable_steady_tick(200);
|
b.enable_steady_tick(200);
|
||||||
self.mainbar = Some(b);
|
self.bars.mainbar = Some(b);
|
||||||
self.guard = Some(thread::spawn(move || {
|
self.bars.guard = Some(thread::spawn(move || {
|
||||||
if let Err(_) = multibar.join() {
|
if let Err(_) = multibar.join() {
|
||||||
error!("{}", lformat!("could not display fancy UI, try running crowbook with --no-fancy"));
|
error!("{}", lformat!("could not display fancy UI, try running crowbook with --no-fancy"));
|
||||||
}
|
}
|
||||||
@ -52,7 +83,7 @@ impl Book {
|
|||||||
|
|
||||||
/// Sets an error message to the progress bar, if it is set
|
/// Sets an error message to the progress bar, if it is set
|
||||||
pub fn private_set_error(&self, msg: &str) {
|
pub fn private_set_error(&self, msg: &str) {
|
||||||
if let Some(ref mainbar) = self.mainbar {
|
if let Some(ref mainbar) = self.bars.mainbar {
|
||||||
let sty = ProgressStyle::default_spinner()
|
let sty = ProgressStyle::default_spinner()
|
||||||
.tick_chars("/|\\-X")
|
.tick_chars("/|\\-X")
|
||||||
.template("{spinner:.dim.bold.red} {wide_msg}");
|
.template("{spinner:.dim.bold.red} {wide_msg}");
|
||||||
@ -64,7 +95,7 @@ impl Book {
|
|||||||
|
|
||||||
/// Sets a finished message to the progress bar, if it is set
|
/// Sets a finished message to the progress bar, if it is set
|
||||||
pub fn set_finished(&self, msg: &str) {
|
pub fn set_finished(&self, msg: &str) {
|
||||||
if let Some(ref bar) = self.mainbar {
|
if let Some(ref bar) = self.bars.mainbar {
|
||||||
let sty = ProgressStyle::default_spinner()
|
let sty = ProgressStyle::default_spinner()
|
||||||
.tick_chars("/|\\-V")
|
.tick_chars("/|\\-V")
|
||||||
.template("{spinner:.dim.bold.cyan} {wide_msg}");
|
.template("{spinner:.dim.bold.cyan} {wide_msg}");
|
||||||
@ -76,48 +107,101 @@ impl Book {
|
|||||||
|
|
||||||
/// Adds a secondary progress bar to display progress of book parsing
|
/// Adds a secondary progress bar to display progress of book parsing
|
||||||
pub fn add_second_bar(&mut self, msg: &str, len: u64) {
|
pub fn add_second_bar(&mut self, msg: &str, len: u64) {
|
||||||
if let Some(ref multibar) = self.multibar {
|
if let Some(ref multibar) = self.bars.multibar {
|
||||||
let bar = multibar.add(ProgressBar::new(len));
|
let bar = multibar.add(ProgressBar::new(len));
|
||||||
bar.set_style(ProgressStyle::default_bar()
|
bar.set_style(ProgressStyle::default_bar()
|
||||||
.template("{bar:40.cyan/blue} {percent:>7}% {msg}")
|
.template("{bar:40.cyan/blue} {percent:>7}% {msg}")
|
||||||
.progress_chars("##-"));
|
.progress_chars("##-"));
|
||||||
bar.set_message(msg);
|
bar.set_message(msg);
|
||||||
self.secondbar = Some(bar);
|
self.bars.secondbar = Some(bar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish secondary prograss bar
|
/// Finish secondary prograss bar
|
||||||
pub fn finish_second_bar(&self) {
|
pub fn finish_second_bar(&self) {
|
||||||
if let Some(ref bar) = self.secondbar {
|
if let Some(ref bar) = self.bars.secondbar {
|
||||||
bar.finish_and_clear();
|
bar.finish_and_clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increment second bar
|
/// Increment second bar
|
||||||
pub fn inc_second_bar(&self) {
|
pub fn inc_second_bar(&self) {
|
||||||
if let Some(ref bar) = self.secondbar {
|
if let Some(ref bar) = self.bars.secondbar {
|
||||||
bar.inc(1);
|
bar.inc(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a spinner labeled key to the multibar, and set mainbar to "rendering"
|
/// Adds a spinner labeled key to the multibar, and set mainbar to "rendering"
|
||||||
pub fn add_spinner_to_multibar(&self, multibar: &MultiProgress, key: &str) -> ProgressBar {
|
pub fn add_spinner_to_multibar(&mut self, key: &str) -> usize {
|
||||||
if let Some(ref mainbar) = self.mainbar {
|
if let Some(ref multibar) = self.bars.multibar {
|
||||||
mainbar.set_message(&lformat!("Rendering..."));
|
if let Some(ref mainbar) = self.bars.mainbar {
|
||||||
}
|
mainbar.set_message(&lformat!("Rendering..."));
|
||||||
|
}
|
||||||
|
|
||||||
let bar = multibar.add(ProgressBar::new_spinner());
|
let bar = multibar.add(ProgressBar::new_spinner());
|
||||||
let sty = ProgressStyle::default_spinner()
|
let sty = ProgressStyle::default_spinner()
|
||||||
.tick_chars("/|\\-X")
|
.tick_chars("/|\\-X")
|
||||||
.template(&format!("{{spinner:.dim.bold.yellow}} {format}: {{wide_msg:.yellow}}",
|
.template(&format!("{{spinner:.dim.bold.yellow}} {format}: {{wide_msg:.yellow}}",
|
||||||
format = key));
|
format = key));
|
||||||
bar.set_style(sty);
|
bar.set_style(sty);
|
||||||
bar.enable_steady_tick(200);
|
bar.enable_steady_tick(200);
|
||||||
bar.set_message(&lformat!("waiting..."));
|
bar.set_message(&lformat!("waiting..."));
|
||||||
bar.tick();
|
bar.tick();
|
||||||
bar
|
self.bars.spinners.push(bar);
|
||||||
|
return self.bars.spinners.len() - 1;
|
||||||
|
} 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 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// Finish a spinner with an error message
|
||||||
pub fn finish_spinner_error(&self, bar: &ProgressBar, key: &str, msg: &str) {
|
pub fn finish_spinner_error(&self, bar: &ProgressBar, key: &str, msg: &str) {
|
||||||
bar.set_style(ProgressStyle::default_spinner()
|
bar.set_style(ProgressStyle::default_spinner()
|
||||||
@ -138,3 +222,15 @@ impl Book {
|
|||||||
bar.finish_with_message(msg);
|
bar.finish_with_message(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Book {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(ref bar) = self.bars.mainbar {
|
||||||
|
bar.finish();
|
||||||
|
let guard = mem::replace(&mut self.bars.guard, None);
|
||||||
|
guard.unwrap()
|
||||||
|
.join()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user