fixed/
fixed.rs

1extern crate fixed;
2extern crate text_layout;
3
4use fixed::types::I16F16;
5use std::fmt::{self, Write};
6use text_layout::{Fixed, Item, KnuthPlass, ParagraphLayout};
7
8type F = Fixed<I16F16>;
9
10fn layout_paragraph<'a, P: ParagraphLayout<(), (), (), F>>(
11    paragraph: &'a str,
12    layout: &P,
13    max_width: F,
14) -> Vec<&'a str> {
15    // Process the paragraph into its items.
16    let mut items = Vec::new();
17    for c in paragraph.chars() {
18        items.push(if c.is_whitespace() && items.len() != 0 {
19            Item::Glue {
20                width: F::from_num(1),
21                stretch: F::from_num(1),
22                shrink: F::from_num(0),
23                data: (),
24            }
25        } else {
26            Item::Box {
27                width: F::from_num(1),
28                data: (),
29            }
30        });
31    }
32    items.push(Item::Glue {
33        width: F::from_num(0),
34        stretch: F::MAX,
35        shrink: F::from_num(0),
36        data: (),
37    });
38    items.push(Item::Penalty {
39        width: F::from_num(0),
40        cost: F::MIN,
41        flagged: true,
42        data: (),
43    });
44
45    // Calculate the paragraph's breaks.
46    let breaks = layout.layout_paragraph(&items, max_width);
47
48    // Render the laid-out paragraph using the break positions.
49    let mut cursor = 0;
50    let mut lines = Vec::new();
51    let mut start = 0;
52    for (i, _) in paragraph.chars().enumerate() {
53        if i == breaks[cursor].break_at {
54            lines.push(&paragraph[start..i]);
55            start = i + 1;
56            cursor += 1;
57        }
58    }
59    lines.push(&paragraph[start..]);
60    lines
61}
62
63fn layout_text() -> Result<String, fmt::Error> {
64    let text = "  Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy lies a small unregarded yellow sun. Orbiting this at a distance of roughly ninety-two million miles is an utterly insignificant little blue-green planet whose ape-descended life forms are so amazingly primitive that they still think digital watches are a pretty neat idea.";
65    let knuth_plass = KnuthPlass::new().with_threshold(F::MAX);
66    let lines = layout_paragraph(&text, &knuth_plass, F::from_num(80));
67    let mut result = String::new();
68    writeln!(&mut result, "┏{}┓", "━".repeat(80))?;
69    for l in lines {
70        let pad = 80 - l.chars().count();
71        writeln!(&mut result, "┃{}{}┃", l, " ".repeat(pad))?;
72    }
73    writeln!(&mut result, "┗{}┛", "━".repeat(80))?;
74    Ok(result)
75}
76
77fn main() -> Result<(), fmt::Error> {
78    print!("{}", layout_text()?);
79    Ok(())
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn fixed() {
88        let expected = r#"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
89┃  Far out in the uncharted backwaters of the unfashionable end of the western   ┃
90┃spiral arm of the Galaxy lies a small unregarded yellow sun. Orbiting this at a ┃
91┃distance of roughly ninety-two million miles is an utterly insignificant little ┃
92┃blue-green planet whose ape-descended life forms are so amazingly primitive that┃
93┃they still think digital watches are a pretty neat idea.                        ┃
94┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
95"#;
96        let actual = layout_text().unwrap();
97        assert!(actual == expected);
98    }
99}