1 use {
2 crate::{
3 line::*,
4 spacing::Spacing,
5 },
6 minimad::{Alignment, CompositeStyle},
7 };
8
9 /// a sequence of lines whose line-style is Code
10 #[derive(Debug)]
11 pub struct CodeBlock {
12 pub start: usize,
13 pub height: usize, // number of lines
14 pub width: usize, // length in chars of the widest line
15 }
16 impl CodeBlock {
17 /// ensure all lines of the block have the same width
justify(&self, lines: &mut Vec<FmtLine<'_>>)18 pub fn justify(&self, lines: &mut Vec<FmtLine<'_>>) {
19 for idx in self.start..self.start + self.height {
20 if let FmtLine::Normal(ref mut fc) = lines[idx] {
21 fc.spacing = Some(Spacing {
22 width: self.width,
23 align: Alignment::Left,
24 });
25 }
26 }
27 }
28 }
29
code_line_length(line: &FmtLine<'_>) -> Option<usize>30 const fn code_line_length(line: &FmtLine<'_>) -> Option<usize> {
31 match line {
32 FmtLine::Normal(fc) => match fc.composite.style {
33 CompositeStyle::Code => Some(fc.visible_length),
34 _ => None,
35 },
36 _ => None,
37 }
38 }
39
40 /// find ranges of code lines in a text.
41 ///
42 /// Warning: the indices in a codeblock are invalid as
43 /// soon as lines are inserted or removed. This function
44 /// should normally not be used from another module or lib
find_blocks(lines: &[FmtLine<'_>]) -> Vec<CodeBlock>45 pub fn find_blocks(lines: &[FmtLine<'_>]) -> Vec<CodeBlock> {
46 let mut blocks: Vec<CodeBlock> = Vec::new();
47 let mut current: Option<CodeBlock> = None;
48 for (idx, line) in lines.iter().enumerate() {
49 if let Some(ll) = code_line_length(line) {
50 match current.as_mut() {
51 Some(b) => {
52 b.height += 1;
53 b.width = b.width.max(ll);
54 }
55 None => {
56 current = Some(CodeBlock {
57 start: idx,
58 height: 1,
59 width: ll,
60 });
61 }
62 }
63 } else if let Some(c) = current.take() {
64 blocks.push(c);
65 }
66 }
67 if let Some(c) = current.take() {
68 blocks.push(c);
69 }
70 blocks
71 }
72
73 /// ensure the widths of all lines in a code block are
74 /// the same line.
justify_blocks(lines: &mut Vec<FmtLine<'_>>)75 pub fn justify_blocks(lines: &mut Vec<FmtLine<'_>>) {
76 let blocks = find_blocks(lines);
77 for b in blocks {
78 b.justify(lines);
79 }
80 }
81