pub mod constraint_tex;
pub mod input_tex;
pub mod tex_helpers;
use crate::operation::AstEngine;
use crate::structure::NodeId;
#[derive(Debug, Clone)]
pub struct TexOutput {
pub tex: String,
pub warnings: Vec<TexWarning>,
}
#[derive(Debug, Clone)]
pub struct TexOptions {
pub section_mode: SectionMode,
pub include_holes: bool,
}
impl Default for TexOptions {
fn default() -> Self {
Self {
section_mode: SectionMode::Fragment,
include_holes: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionMode {
Fragment,
Standalone,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TexWarning {
HoleEncountered {
node_id: NodeId,
},
UnsupportedConstraint {
description: String,
},
UnresolvedReference {
name: String,
},
}
#[must_use]
pub fn render_constraints_tex(engine: &AstEngine, options: &TexOptions) -> TexOutput {
constraint_tex::render_constraints_tex_impl(engine, options)
}
#[must_use]
pub fn render_input_tex(engine: &AstEngine, options: &TexOptions) -> TexOutput {
input_tex::render_input_tex_impl(engine, options)
}
#[must_use]
pub fn render_full_tex(engine: &AstEngine, options: &TexOptions) -> TexOutput {
let input = render_input_tex(engine, options);
let constraints = render_constraints_tex(engine, options);
let mut warnings = input.warnings;
warnings.extend(constraints.warnings);
let tex = match options.section_mode {
SectionMode::Standalone => {
let mut out = String::new();
if !input.tex.is_empty() {
out.push_str("\\paragraph{入力}\n");
out.push_str(&input.tex);
}
if !constraints.tex.is_empty() {
if !out.is_empty() {
out.push('\n');
}
out.push_str("\\paragraph{制約}\n");
out.push_str(&constraints.tex);
}
out
}
SectionMode::Fragment => {
let mut out = String::new();
if !input.tex.is_empty() {
out.push_str(&input.tex);
}
if !constraints.tex.is_empty() {
if !out.is_empty() {
out.push('\n');
}
out.push_str(&constraints.tex);
}
out
}
};
TexOutput { tex, warnings }
}