Add width field to Span and IndexedSpan

This commit is contained in:
Alexandre Bury 2019-03-20 16:48:48 -07:00
parent 57f9b05d64
commit c9dc371223
5 changed files with 34 additions and 22 deletions

View File

@ -102,7 +102,7 @@ impl<'a, 'b> Printer<'a, 'b> {
for span in text.spans() {
self.with_style(*span.attr, |printer| {
printer.print((x, y), span.content);
x += span.content.width();
x += span.width;
});
}
}
@ -135,10 +135,10 @@ impl<'a, 'b> Printer<'a, 'b> {
if hidden_part.x > text_width {
return;
}
let mut text = text;
let mut start = start;
if hidden_part.x > 0 {
// We have to drop hidden_part.x width from the start of the string.
// prefix() may be too short if there's a double-width character.
@ -161,7 +161,7 @@ impl<'a, 'b> Printer<'a, 'b> {
start = start + (skipped_width, 0);
text_width -= skipped_width;
}
assert!(start.fits(self.content_offset));
// What we did before should guarantee that this won't overflow.

View File

@ -20,7 +20,7 @@ struct DummySpannedText<'a> {
impl<'a> DummySpannedText<'a> {
fn new(content: &'a str) -> Self {
let attrs = vec![IndexedSpan::simple(content, ())];
let attrs = vec![IndexedSpan::simple_borrowed(content, ())];
DummySpannedText { content, attrs }
}
}

View File

@ -26,6 +26,7 @@ impl Segment {
Span {
content,
attr: &span.attr,
width: self.width,
}
}

View File

@ -2,13 +2,13 @@
//!
//! Needs the `markdown` feature to be enabled.
use pulldown_cmark;
use self::pulldown_cmark::{Event, Tag};
use crate::theme::{Effect, Style};
use crate::utils::markup::{StyledIndexedSpan, StyledString};
use crate::utils::span::IndexedCow;
use pulldown_cmark::{self, Event, Tag};
use unicode_width::UnicodeWidthStr;
/// Parses the given string as markdown text.
pub fn parse<S>(input: S) -> StyledString
where
@ -45,10 +45,7 @@ impl<'a> Parser<'a> {
where
S: Into<String>,
{
StyledIndexedSpan {
content: IndexedCow::Owned(text.into()),
attr: Style::merge(&self.stack),
}
StyledIndexedSpan::simple_owned(text.into(), Style::merge(&self.stack))
}
}
@ -110,10 +107,12 @@ impl<'a> Iterator for Parser<'a> {
| Event::InlineHtml(text)
| Event::Html(text)
| Event::Text(text) => {
let width = text.width();
// Return something!
return Some(StyledIndexedSpan {
content: IndexedCow::from_cow(text, self.input),
attr: Style::merge(&self.stack),
width,
});
}
}

View File

@ -193,13 +193,7 @@ impl<T> SpannedString<T> {
{
let source = source.into();
let spans = vec![IndexedSpan {
content: IndexedCow::Borrowed {
start: 0,
end: source.len(),
},
attr,
}];
let spans = vec![IndexedSpan::simple_borrowed(&source, attr)];
Self::with_spans(source, spans)
}
@ -256,7 +250,7 @@ impl<T> SpannedString<T> {
///
/// This is the sum of the width of each span.
pub fn width(&self) -> usize {
self.spans().map(|s| s.content.width()).sum()
self.spans().map(|s| s.width).sum()
}
}
@ -274,6 +268,9 @@ pub struct IndexedSpan<T> {
/// Attribute applied to the span.
pub attr: T,
/// Width of the text for this span.
pub width: usize,
}
impl<T> AsRef<IndexedCow> for IndexedSpan<T> {
@ -290,6 +287,9 @@ pub struct Span<'a, T> {
/// Attribute associated to this span.
pub attr: &'a T,
/// Width of the text for this span.
pub width: usize,
}
impl<T> IndexedSpan<T> {
@ -301,6 +301,7 @@ impl<T> IndexedSpan<T> {
Span {
content: self.content.resolve(source),
attr: &self.attr,
width: self.width,
}
}
@ -309,14 +310,25 @@ impl<T> IndexedSpan<T> {
self.content.is_empty()
}
/// Returns a single span around the entire text.
pub fn simple(content: &str, attr: T) -> Self {
/// Returns a single indexed span around the entire text.
pub fn simple_borrowed(content: &str, attr: T) -> Self {
IndexedSpan {
content: IndexedCow::Borrowed {
start: 0,
end: content.len(),
},
attr,
width: content.width(),
}
}
/// Returns a single owned indexed span around the entire text.
pub fn simple_owned(content: String, attr: T) -> Self {
let width = content.width();
IndexedSpan {
content: IndexedCow::Owned(content),
attr,
width,
}
}
}