boxworks_knuthplass/
debug.rs1use std::{cell::RefCell, rc::Rc};
2
3use boxworks::ds;
4
5pub struct FeasibleBreakpoint {
6 pub elem_index: usize,
7 pub badness: i32,
8 pub penalty: i32,
9 pub demerits: i32,
10 pub previous_node_index: usize,
11}
12
13pub struct NewActiveNode {
14 pub node_index: usize,
15 pub line_number: usize,
16 pub fitness_class: u8,
17 pub hyphenated: bool,
18 pub total_demerits: i32,
19 pub previous_node_index: usize,
20}
21
22pub trait Logger {
23 fn log_attempt(&mut self, attempt_number: u8);
24 fn log_feasible_breakpoint(&mut self, list: &[ds::Horizontal], fb: FeasibleBreakpoint);
25 fn log_new_active_node(&mut self, an: NewActiveNode);
26}
27
28pub struct TexLogger {
29 writer: Rc<RefCell<dyn std::fmt::Write>>,
30 next_elem_to_write: usize,
31 pending_fbs: Vec<(FeasibleBreakpoint, String)>,
32}
33
34impl TexLogger {
35 pub fn new(writer: Rc<RefCell<dyn std::fmt::Write>>) -> Self {
36 Self {
37 writer,
38 next_elem_to_write: 0,
39 pending_fbs: Default::default(),
40 }
41 }
42}
43
44impl Logger for TexLogger {
45 fn log_attempt(&mut self, attempt_number: u8) {
46 self.next_elem_to_write = 0;
47 let _ = writeln!(
49 self.writer.borrow_mut(),
50 "@{}",
51 match attempt_number {
52 1 => "firstpass",
53 2 => "secondpass",
54 _ => "emergencypass",
55 }
56 );
57 }
58 fn log_feasible_breakpoint(&mut self, list: &[ds::Horizontal], fb: FeasibleBreakpoint) {
59 if self.next_elem_to_write <= fb.elem_index {
60 let upper = if fb.elem_index >= list.len() {
61 list.len() - 1
62 } else {
63 fb.elem_index
64 };
65 _ = boxworks::ds::short_display_hlist(
66 &mut *self.writer.borrow_mut(),
67 &list[self.next_elem_to_write..=upper],
68 );
69 _ = writeln!(&mut *self.writer.borrow_mut());
70 }
71 self.next_elem_to_write = fb.elem_index + 1;
72 let line = format!(
78 "@{} via @@{} b={} p={} d={}",
79 match list.get(fb.elem_index) {
80 None => r"\par",
81 Some(elem) => {
82 use ds::Horizontal::*;
83 match elem {
84 Discretionary(discretionary) => {
85 self.next_elem_to_write += discretionary.replace_count as usize;
86 r"\discretionary"
87 }
88 _ => "",
89 }
90 }
91 },
92 fb.previous_node_index,
93 fb.badness,
94 fb.penalty,
95 fb.demerits,
96 );
97 self.pending_fbs.push((fb, line));
98 }
99 fn log_new_active_node(&mut self, an: NewActiveNode) {
100 self.pending_fbs.sort_by_key(|a| a.0.previous_node_index);
101 for (_, line) in &self.pending_fbs {
102 _ = writeln!(self.writer.borrow_mut(), "{}", line);
103 }
104 self.pending_fbs.clear();
105 let _ = writeln!(
107 self.writer.borrow_mut(),
108 "@@{}: line {}.{}{} t={} -> @@{}",
109 an.node_index,
110 an.line_number,
111 an.fitness_class,
112 if an.hyphenated { "-" } else { "" },
113 an.total_demerits,
114 an.previous_node_index,
115 );
116 }
117}