mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Avoid breaking up words during wrapping when possible (#47)
This commit is contained in:
parent
54a0e76823
commit
ac6ff63d25
3 changed files with 317 additions and 55 deletions
|
@ -6,7 +6,7 @@
|
||||||
//! The Matrix specification recommends limiting rendered tags and attributes to a safe subset of
|
//! The Matrix specification recommends limiting rendered tags and attributes to a safe subset of
|
||||||
//! HTML. You can read more in section 11.2.1.1, "m.room.message msgtypes":
|
//! HTML. You can read more in section 11.2.1.1, "m.room.message msgtypes":
|
||||||
//!
|
//!
|
||||||
//! https://spec.matrix.org/unstable/client-server-api/#mroommessage-msgtypes
|
//! <https://spec.matrix.org/unstable/client-server-api/#mroommessage-msgtypes>
|
||||||
//!
|
//!
|
||||||
//! This isn't as important for iamb, since it isn't a browser environment, but we do still map
|
//! This isn't as important for iamb, since it isn't a browser environment, but we do still map
|
||||||
//! input onto an enum of the safe list of tags to keep it easy to understand and process.
|
//! input onto an enum of the safe list of tags to keep it easy to understand and process.
|
||||||
|
@ -271,10 +271,12 @@ impl StyleTreeNode {
|
||||||
},
|
},
|
||||||
StyleTreeNode::Header(child, level) => {
|
StyleTreeNode::Header(child, level) => {
|
||||||
let style = style.add_modifier(StyleModifier::BOLD);
|
let style = style.add_modifier(StyleModifier::BOLD);
|
||||||
let mut hashes = "#".repeat(*level);
|
|
||||||
hashes.push(' ');
|
|
||||||
|
|
||||||
printer.push_str(hashes, style);
|
for _ in 0..*level {
|
||||||
|
printer.push_str("#", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer.push_str(" ", style);
|
||||||
child.print(printer, style);
|
child.print(printer, style);
|
||||||
},
|
},
|
||||||
StyleTreeNode::Image(None) => {},
|
StyleTreeNode::Image(None) => {},
|
||||||
|
@ -320,7 +322,9 @@ impl StyleTreeNode {
|
||||||
printer.commit();
|
printer.commit();
|
||||||
},
|
},
|
||||||
StyleTreeNode::Ruler => {
|
StyleTreeNode::Ruler => {
|
||||||
printer.push_str(line::HORIZONTAL.repeat(width), style);
|
for _ in 0..width {
|
||||||
|
printer.push_str(line::HORIZONTAL, style);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
StyleTreeNode::Table(table) => {
|
StyleTreeNode::Table(table) => {
|
||||||
let text = table.to_text(width, style);
|
let text = table.to_text(width, style);
|
||||||
|
@ -637,7 +641,10 @@ pub mod tests {
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("#", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 1", bold),
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("1", bold),
|
||||||
space_span(10, Style::default())
|
space_span(10, Style::default())
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -645,8 +652,12 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("## ", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 2", bold),
|
Span::styled("#", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("2", bold),
|
||||||
space_span(9, Style::default())
|
space_span(9, Style::default())
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -654,8 +665,13 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("### ", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 3", bold),
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("3", bold),
|
||||||
space_span(8, Style::default())
|
space_span(8, Style::default())
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -663,8 +679,14 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("#### ", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 4", bold),
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("4", bold),
|
||||||
space_span(7, Style::default())
|
space_span(7, Style::default())
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -672,8 +694,15 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("##### ", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 5", bold),
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("5", bold),
|
||||||
space_span(6, Style::default())
|
space_span(6, Style::default())
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -681,8 +710,16 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("###### ", bold),
|
Span::styled("#", bold),
|
||||||
Span::styled("Header 6", bold),
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled("#", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("Header", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("6", bold),
|
||||||
space_span(5, Style::default())
|
space_span(5, Style::default())
|
||||||
])]);
|
])]);
|
||||||
}
|
}
|
||||||
|
@ -700,7 +737,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Bold!", bold),
|
Span::styled("Bold", bold),
|
||||||
|
Span::styled("!", bold),
|
||||||
space_span(15, def)
|
space_span(15, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -708,7 +746,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Bold!", bold),
|
Span::styled("Bold", bold),
|
||||||
|
Span::styled("!", bold),
|
||||||
space_span(15, def)
|
space_span(15, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -716,7 +755,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Italic!", italic),
|
Span::styled("Italic", italic),
|
||||||
|
Span::styled("!", italic),
|
||||||
space_span(13, def)
|
space_span(13, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -724,7 +764,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Italic!", italic),
|
Span::styled("Italic", italic),
|
||||||
|
Span::styled("!", italic),
|
||||||
space_span(13, def)
|
space_span(13, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -732,7 +773,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Strikethrough!", strike),
|
Span::styled("Strikethrough", strike),
|
||||||
|
Span::styled("!", strike),
|
||||||
space_span(6, def)
|
space_span(6, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -740,7 +782,8 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Strikethrough!", strike),
|
Span::styled("Strikethrough", strike),
|
||||||
|
Span::styled("!", strike),
|
||||||
space_span(6, def)
|
space_span(6, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
|
@ -748,19 +791,28 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
Span::styled("Underline!", underl),
|
Span::styled("Underline", underl),
|
||||||
|
Span::styled("!", underl),
|
||||||
space_span(10, def)
|
space_span(10, def)
|
||||||
])]);
|
])]);
|
||||||
|
|
||||||
let s = "<font color=\"#ff0000\">Red!</u>";
|
let s = "<font color=\"#ff0000\">Red!</u>";
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![Span::styled("Red!", red), space_span(16, def)])]);
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
|
Span::styled("Red", red),
|
||||||
|
Span::styled("!", red),
|
||||||
|
space_span(16, def)
|
||||||
|
])]);
|
||||||
|
|
||||||
let s = "<font color=\"red\">Red!</u>";
|
let s = "<font color=\"red\">Red!</u>";
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(20, Style::default(), false);
|
let text = tree.to_text(20, Style::default(), false);
|
||||||
assert_eq!(text.lines, vec![Spans(vec![Span::styled("Red!", red), space_span(16, def)])]);
|
assert_eq!(text.lines, vec![Spans(vec![
|
||||||
|
Span::styled("Red", red),
|
||||||
|
Span::styled("!", red),
|
||||||
|
space_span(16, def)
|
||||||
|
])]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -769,13 +821,25 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(10, Style::default(), false);
|
let text = tree.to_text(10, Style::default(), false);
|
||||||
assert_eq!(text.lines.len(), 7);
|
assert_eq!(text.lines.len(), 7);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw("Hello worl")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[1], Spans(vec![Span::raw("d!"), Span::raw(" ")]));
|
text.lines[0],
|
||||||
|
Spans(vec![Span::raw("Hello"), Span::raw(" "), Span::raw(" ")])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[1],
|
||||||
|
Spans(vec![Span::raw("world"), Span::raw("!"), Span::raw(" ")])
|
||||||
|
);
|
||||||
assert_eq!(text.lines[2], Spans(vec![Span::raw(" ")]));
|
assert_eq!(text.lines[2], Spans(vec![Span::raw(" ")]));
|
||||||
assert_eq!(text.lines[3], Spans(vec![Span::raw("Content"), Span::raw(" ")]));
|
assert_eq!(text.lines[3], Spans(vec![Span::raw("Content"), Span::raw(" ")]));
|
||||||
assert_eq!(text.lines[4], Spans(vec![Span::raw(" ")]));
|
assert_eq!(text.lines[4], Spans(vec![Span::raw(" ")]));
|
||||||
assert_eq!(text.lines[5], Spans(vec![Span::raw("Goodbye wo")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[6], Spans(vec![Span::raw("rld!"), Span::raw(" ")]));
|
text.lines[5],
|
||||||
|
Spans(vec![Span::raw("Goodbye"), Span::raw(" "), Span::raw(" ")])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[6],
|
||||||
|
Spans(vec![Span::raw("world"), Span::raw("!"), Span::raw(" ")])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -784,8 +848,14 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(10, Style::default(), false);
|
let text = tree.to_text(10, Style::default(), false);
|
||||||
assert_eq!(text.lines.len(), 2);
|
assert_eq!(text.lines.len(), 2);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw(" "), Span::raw("Hello ")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[1], Spans(vec![Span::raw(" "), Span::raw("world!")]));
|
text.lines[0],
|
||||||
|
Spans(vec![Span::raw(" "), Span::raw("Hello"), Span::raw(" ")])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[1],
|
||||||
|
Spans(vec![Span::raw(" "), Span::raw("world"), Span::raw("!")])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -794,12 +864,60 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(8, Style::default(), false);
|
let text = tree.to_text(8, Style::default(), false);
|
||||||
assert_eq!(text.lines.len(), 6);
|
assert_eq!(text.lines.len(), 6);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw("- "), Span::raw("List I")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[1], Spans(vec![Span::raw(" "), Span::raw("tem 1"), Span::raw(" ")]));
|
text.lines[0],
|
||||||
assert_eq!(text.lines[2], Spans(vec![Span::raw("- "), Span::raw("List I")]));
|
Spans(vec![
|
||||||
assert_eq!(text.lines[3], Spans(vec![Span::raw(" "), Span::raw("tem 2"), Span::raw(" ")]));
|
Span::raw("- "),
|
||||||
assert_eq!(text.lines[4], Spans(vec![Span::raw("- "), Span::raw("List I")]));
|
Span::raw("List"),
|
||||||
assert_eq!(text.lines[5], Spans(vec![Span::raw(" "), Span::raw("tem 3"), Span::raw(" ")]));
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[1],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("1")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[2],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("- "),
|
||||||
|
Span::raw("List"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[3],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("2")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[4],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("- "),
|
||||||
|
Span::raw("List"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[5],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("3")
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -808,20 +926,59 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(9, Style::default(), false);
|
let text = tree.to_text(9, Style::default(), false);
|
||||||
assert_eq!(text.lines.len(), 6);
|
assert_eq!(text.lines.len(), 6);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw("1. "), Span::raw("List I")]));
|
assert_eq!(
|
||||||
|
text.lines[0],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("1. "),
|
||||||
|
Span::raw("List"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
text.lines[1],
|
text.lines[1],
|
||||||
Spans(vec![Span::raw(" "), Span::raw("tem 1"), Span::raw(" ")])
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("1")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[2],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("2. "),
|
||||||
|
Span::raw("List"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
);
|
);
|
||||||
assert_eq!(text.lines[2], Spans(vec![Span::raw("2. "), Span::raw("List I")]));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
text.lines[3],
|
text.lines[3],
|
||||||
Spans(vec![Span::raw(" "), Span::raw("tem 2"), Span::raw(" ")])
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("2")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[4],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("3. "),
|
||||||
|
Span::raw("List"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
);
|
);
|
||||||
assert_eq!(text.lines[4], Spans(vec![Span::raw("3. "), Span::raw("List I")]));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
text.lines[5],
|
text.lines[5],
|
||||||
Spans(vec![Span::raw(" "), Span::raw("tem 3"), Span::raw(" ")])
|
Spans(vec![
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("Item"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("3")
|
||||||
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,9 +1011,13 @@ pub mod tests {
|
||||||
]);
|
]);
|
||||||
assert_eq!(text.lines[2].0, vec![
|
assert_eq!(text.lines[2].0, vec![
|
||||||
Span::raw("│"),
|
Span::raw("│"),
|
||||||
Span::styled("mn 1", bold),
|
Span::styled("mn", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("1", bold),
|
||||||
Span::raw("│"),
|
Span::raw("│"),
|
||||||
Span::styled("mn 2", bold),
|
Span::styled("mn", bold),
|
||||||
|
Span::styled(" ", bold),
|
||||||
|
Span::styled("2", bold),
|
||||||
Span::raw("│"),
|
Span::raw("│"),
|
||||||
Span::styled("umn", bold),
|
Span::styled("umn", bold),
|
||||||
Span::raw("│")
|
Span::raw("│")
|
||||||
|
@ -867,6 +1028,7 @@ pub mod tests {
|
||||||
Span::raw("│"),
|
Span::raw("│"),
|
||||||
Span::raw(" "),
|
Span::raw(" "),
|
||||||
Span::raw("│"),
|
Span::raw("│"),
|
||||||
|
Span::styled(" ", bold),
|
||||||
Span::styled("3", bold),
|
Span::styled("3", bold),
|
||||||
Span::styled(" ", bold),
|
Span::styled(" ", bold),
|
||||||
Span::raw("│")
|
Span::raw("│")
|
||||||
|
@ -928,15 +1090,61 @@ pub mod tests {
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(10, Style::default(), false);
|
let text = tree.to_text(10, Style::default(), false);
|
||||||
assert_eq!(text.lines.len(), 4);
|
assert_eq!(text.lines.len(), 4);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw("This was r")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[1], Spans(vec![Span::raw("eplied to"), Span::raw(" ")]));
|
text.lines[0],
|
||||||
assert_eq!(text.lines[2], Spans(vec![Span::raw("This is th")]));
|
Spans(vec![
|
||||||
assert_eq!(text.lines[3], Spans(vec![Span::raw("e reply"), Span::raw(" ")]));
|
Span::raw("This"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("was"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[1],
|
||||||
|
Spans(vec![Span::raw("replied"), Span::raw(" "), Span::raw("to")])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[2],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("This"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("is"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[3],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("the"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("reply"),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
let tree = parse_matrix_html(s);
|
let tree = parse_matrix_html(s);
|
||||||
let text = tree.to_text(10, Style::default(), true);
|
let text = tree.to_text(10, Style::default(), true);
|
||||||
assert_eq!(text.lines.len(), 2);
|
assert_eq!(text.lines.len(), 2);
|
||||||
assert_eq!(text.lines[0], Spans(vec![Span::raw("This is th")]));
|
assert_eq!(
|
||||||
assert_eq!(text.lines[1], Spans(vec![Span::raw("e reply"), Span::raw(" ")]));
|
text.lines[0],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("This"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("is"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
text.lines[1],
|
||||||
|
Spans(vec![
|
||||||
|
Span::raw("the"),
|
||||||
|
Span::raw(" "),
|
||||||
|
Span::raw("reply"),
|
||||||
|
Span::raw(" ")
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -710,7 +710,11 @@ impl Message {
|
||||||
key
|
key
|
||||||
};
|
};
|
||||||
|
|
||||||
emojis.push_str(format!("[{name} {count}]"), style);
|
emojis.push_str("[", style);
|
||||||
|
emojis.push_str(name, style);
|
||||||
|
emojis.push_str(" ", style);
|
||||||
|
emojis.push_span_nobreak(Span::styled(count.to_string(), style));
|
||||||
|
emojis.push_str("]", style);
|
||||||
|
|
||||||
reactions += 1;
|
reactions += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::borrow::Cow;
|
||||||
use modalkit::tui::layout::Alignment;
|
use modalkit::tui::layout::Alignment;
|
||||||
use modalkit::tui::style::Style;
|
use modalkit::tui::style::Style;
|
||||||
use modalkit::tui::text::{Span, Spans, Text};
|
use modalkit::tui::text::{Span, Spans, Text};
|
||||||
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
use crate::util::{space_span, take_width};
|
use crate::util::{space_span, take_width};
|
||||||
|
@ -107,7 +108,7 @@ impl<'a> TextPrinter<'a> {
|
||||||
self.push();
|
self.push();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_str<T>(&mut self, s: T, style: Style)
|
fn push_str_wrapped<T>(&mut self, s: T, style: Style)
|
||||||
where
|
where
|
||||||
T: Into<Cow<'a, str>>,
|
T: Into<Cow<'a, str>>,
|
||||||
{
|
{
|
||||||
|
@ -140,6 +141,55 @@ impl<'a> TextPrinter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_span_nobreak(&mut self, span: Span<'a>) {
|
||||||
|
let sw = UnicodeWidthStr::width(span.content.as_ref());
|
||||||
|
|
||||||
|
if self.curr_width + sw > self.width {
|
||||||
|
// Span doesn't fit on this line, so start a new one.
|
||||||
|
self.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.curr_spans.push(span);
|
||||||
|
self.curr_width += sw;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_str(&mut self, s: &'a str, style: Style) {
|
||||||
|
let style = self.base_style.patch(style);
|
||||||
|
|
||||||
|
for word in UnicodeSegmentation::split_word_bounds(s) {
|
||||||
|
if self.width == 0 && word.chars().all(char::is_whitespace) {
|
||||||
|
// Drop leading whitespace.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sw = UnicodeWidthStr::width(word);
|
||||||
|
|
||||||
|
if sw > self.width {
|
||||||
|
self.push_str_wrapped(word, style);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.curr_width + sw > self.width {
|
||||||
|
// Word doesn't fit on this line, so start a new one.
|
||||||
|
self.commit();
|
||||||
|
|
||||||
|
if word.chars().all(char::is_whitespace) {
|
||||||
|
// Drop leading whitespace.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let span = Span::styled(word, style);
|
||||||
|
self.curr_spans.push(span);
|
||||||
|
self.curr_width += sw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.curr_width == self.width {
|
||||||
|
// If the last bit fills the full line, start a new one.
|
||||||
|
self.push();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_line(&mut self, spans: Spans<'a>) {
|
pub fn push_line(&mut self, spans: Spans<'a>) {
|
||||||
self.commit();
|
self.commit();
|
||||||
self.text.lines.push(spans);
|
self.text.lines.push(spans);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue