quicklatex 0.1.0

A program to help me write LaTeX quickly
Documentation
//! `quicklatex`
//!
//! `quicklatex` is a program to help me write LaTeX quickly.  For a
//! full explanation, see [the README
//! e.g. here](https://crates.io/crates/quicklatex).

#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo_common_metadata)]
// Anachronism
#![allow(clippy::non_ascii_literal)]
// This lint is wrong.  The escaping of the characters is intentional.
#![allow(clippy::unnecessary_debug_formatting)]
// More or less manual checked and documentation agrees with me that
// it's usually not needed.
#![allow(
    clippy::cast_possible_truncation,
    clippy::cast_sign_loss,
    clippy::cast_precision_loss,
    clippy::cast_lossless
)]

// `clippy::needless_pass_by_value` is allowed for values implementing
// the Diskit trait, because these are usually zero-sized-types (like
// the standard one or types which work similiar) or – because of the
// Clone trait bound and that the methods on the Diskit trait always
// only get a shared reference – a thin wrapper around an
// Arc<Mutex<{Something}>>.  The #[allow(...)]-s are placed at the
// places where they are needed, because clippy doesn't support
// allowing lints only for some types (or types implementing some
// traits).

use std::path::Path;

use anyhow::{Context, Error};
use diskit::Diskit;
use labels::check_labels;
use misc::read_to_string;
use replacements::literal;
use shortbrackets::add_short_brackets;

pub mod arguments;
mod first_pass;
#[cfg(test)]
mod general_tests;
mod labels;
mod misc;
mod noisy;
mod profiling;
mod replacements;
mod second_pass;
mod shortbrackets;

pub use noisy::Noisy;
pub use profiling::Timers;
pub use replacements::Replacement;

/// Does the transformation from qlx to tex
///
/// This function does the transformation from qlx to tex, so that
/// pdflatex can understand it.
///
/// # Errors
/// Gives back an error if something failed (reading a file or the
/// input isn't valid).
// Look above for justification.
#[allow(clippy::needless_pass_by_value)]
pub fn run<D: Diskit>(path: &Path, timers: &mut Timers, d: D) -> Result<(String, Noisy), Error>
{
    timers.start("lib.rs")?;
    let s = read_to_string(path, d.clone()).context("Couldn't open requested file")?;

    let (s, mut noisy, repls) =
        literal(add_short_brackets(&s)?, path, timers, d).context("Couldn't do replacements")?;
    let s = s.chars().collect::<Vec<_>>();

    let first_pass::Text { pieces } = first_pass::parse(&s);

    let b = second_pass::parse(&pieces).fix_math();

    let c = b.to_string();

    let d = check_labels(&c, &repls, &mut noisy, timers).context("Couldn't check labels")?;

    timers.stop("lib.rs")?;

    Ok((d, noisy))
}