Merge pull request #327 from chrisvest/avoid-grapheme-iteration

Avoid iterating graphemes unless we have to.
This commit is contained in:
Alexandre Bury 2019-03-12 13:55:49 -07:00 committed by GitHub
commit e5ef01c90f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -129,46 +129,55 @@ impl<'a, 'b> Printer<'a, 'b> {
return; return;
} }
let text_width = text.width(); let mut text_width = text.width();
// If we're waaaay too far left, just give up. // If we're waaaay too far left, just give up.
if hidden_part.x > text_width { if hidden_part.x > text_width {
return; return;
} }
// We have to drop hidden_part.x width from the start of the string. let mut text = text;
// prefix() may be too short if there's a double-width character. let mut start = start;
// So instead, keep the suffix and drop the prefix.
// TODO: use a different prefix method that is *at least* the width if hidden_part.x > 0 {
// (and not *at most*) // We have to drop hidden_part.x width from the start of the string.
let tail = // prefix() may be too short if there's a double-width character.
suffix(text.graphemes(true), text_width - hidden_part.x, ""); // So instead, keep the suffix and drop the prefix.
let skipped_len = text.len() - tail.length;
let skipped_width = text_width - tail.width;
assert_eq!(text[..skipped_len].width(), skipped_width);
// This should be equal most of the time, except when there's a double // TODO: use a different prefix method that is *at least* the width
// character preventing us from splitting perfectly. // (and not *at most*)
assert!(skipped_width >= hidden_part.x); let tail =
suffix(text.graphemes(true), text_width - hidden_part.x, "");
let skipped_len = text.len() - tail.length;
let skipped_width = text_width - tail.width;
assert_eq!(text[..skipped_len].width(), skipped_width);
// This should be equal most of the time, except when there's a double
// character preventing us from splitting perfectly.
assert!(skipped_width >= hidden_part.x);
// Drop part of the text, and move the cursor correspondingly.
text = &text[skipped_len..];
start = start + (skipped_width, 0);
text_width -= skipped_width;
}
// Drop part of the text, and move the cursor correspondingly.
let text = &text[skipped_len..];
let start = start + (skipped_width, 0);
assert!(start.fits(self.content_offset)); assert!(start.fits(self.content_offset));
// What we did before should guarantee that this won't overflow. // What we did before should guarantee that this won't overflow.
let start = start - self.content_offset; start = start - self.content_offset;
// Do we have enough room for the entire line? // Do we have enough room for the entire line?
let room = self.output_size.x - start.x; let room = self.output_size.x - start.x;
// Drop the end of the text if it's too long if room < text_width {
// We want the number of CHARACTERS, not bytes. // Drop the end of the text if it's too long
// (Actually we want the "width" of the string, see unicode-width) // We want the number of CHARACTERS, not bytes.
let prefix_len = prefix(text.graphemes(true), room, "").length; // (Actually we want the "width" of the string, see unicode-width)
let text = &text[..prefix_len]; let prefix_len = prefix(text.graphemes(true), room, "").length;
assert!(text.width() <= room); text = &text[..prefix_len];
assert!(text.width() <= room);
}
let start = start + self.offset; let start = start + self.offset;
self.backend.print_at(start, text); self.backend.print_at(start, text);