diff --git a/src/printer.rs b/src/printer.rs index 212f7ff..d9d63e4 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -9,7 +9,7 @@ use std::rc::Rc; use theme::{BorderStyle, ColorStyle, Effect, Theme}; use unicode_segmentation::UnicodeSegmentation; -use utils::prefix_length; +use utils::prefix; use vec::Vec2; /// Convenient interface to draw on a subset of the screen. @@ -73,7 +73,7 @@ impl<'a> Printer<'a> { let room = self.size.x - p.x; // We want the number of CHARACTERS, not bytes. // (Actually we want the "width" of the string, see unicode-width) - let prefix_len = prefix_length(text.graphemes(true), room, ""); + let prefix_len = prefix(text.graphemes(true), room, "").length; let text = &text[..prefix_len]; let p = p + self.offset; diff --git a/src/utils/lines_iterator.rs b/src/utils/lines_iterator.rs index e85f994..c89bcd4 100644 --- a/src/utils/lines_iterator.rs +++ b/src/utils/lines_iterator.rs @@ -3,7 +3,7 @@ use With; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; -use utils::prefix_length; +use utils::prefix; /// Generates rows of text in constrained width. /// @@ -119,11 +119,11 @@ impl<'a> Iterator for LinesIterator<'a> { // First attempt: only break on spaces. let prefix_length = - match prefix_length(content.split(' '), allowed_width, " ") { + match prefix(content.split(' '), allowed_width, " ").length { // If this fail, fallback: only break on graphemes. // There's no whitespace to skip there. // And don't reserve the white space anymore. - 0 => prefix_length(content.graphemes(true), self.width, ""), + 0 => prefix(content.graphemes(true), self.width, "").length, other => { // If it works, advance the cursor by 1 // to jump the whitespace. diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6cd6092..c7f4f47 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,7 +9,15 @@ mod reader; pub use self::lines_iterator::{LinesIterator, Row}; pub use self::reader::ProgressReader; -/// Computes the length of a prefix that fits in the given `width`. +/// The length and width of a part of a string. +pub struct Prefix { + /// The length (in bytes) of the string. + pub length: usize, + /// The unicode-width of the string. + pub width: usize +} + +/// Computes the length (number of bytes) and width of a prefix that fits in the given `width`. /// /// Takes non-breakable elements from `iter`, while keeping the /// string width under `width` (and adding the length of `delimiter` @@ -26,15 +34,15 @@ pub use self::reader::ProgressReader; /// extern crate unicode_segmentation; /// use unicode_segmentation::UnicodeSegmentation; /// -/// # use cursive::utils::prefix_length; +/// # use cursive::utils::prefix; /// # fn main() { /// let my_text = "blah..."; /// // This returns the number of bytes for a prefix of `my_text` that /// // fits within 5 cells. -/// prefix_length(my_text.graphemes(true), 5, ""); +/// prefix(my_text.graphemes(true), 5, ""); /// # } /// ``` -pub fn prefix_length<'a, I>(iter: I, available_width: usize, delimiter: &str) -> usize +pub fn prefix<'a, I>(iter: I, available_width: usize, delimiter: &str) -> Prefix where I: Iterator { let delimiter_width = delimiter.width(); @@ -58,10 +66,15 @@ pub fn prefix_length<'a, I>(iter: I, available_width: usize, delimiter: &str) -> // We counted delimiter once too many times, // but only if the iterator was non empty. - if sum == 0 { sum } else { sum - delimiter_len } + let length = if sum == 0 { sum } else { sum - delimiter_len }; + + Prefix { + length: length, + width: current_width + } } -/// Computes the length of a suffix that fits in the given `width`. +/// Computes the length (number of bytes) and width of a suffix that fits in the given `width`. /// /// Doesn't break inside elements returned by `iter`. /// @@ -69,15 +82,15 @@ pub fn prefix_length<'a, I>(iter: I, available_width: usize, delimiter: &str) -> /// suffix from `text` that fits in `width`. /// /// This is a shortcut for `prefix_length(iter.rev(), width, delimiter)` -pub fn suffix_length<'a, I>(iter: I, width: usize, delimiter: &str) -> usize +pub fn suffix<'a, I>(iter: I, width: usize, delimiter: &str) -> Prefix where I: DoubleEndedIterator { - prefix_length(iter.rev(), width, delimiter) + prefix(iter.rev(), width, delimiter) } -/// Computes the length of a suffix that fits in the given `width`. +/// Computes the length (number of bytes) and width of a suffix that fits in the given `width`. /// /// Breaks between any two graphemes. -pub fn simple_suffix_length(text: &str, width: usize) -> usize { - suffix_length(text.graphemes(true), width, "") +pub fn simple_suffix(text: &str, width: usize) -> Prefix { + suffix(text.graphemes(true), width, "") } diff --git a/src/views/edit_view.rs b/src/views/edit_view.rs index 4ac8cbd..734ef28 100644 --- a/src/views/edit_view.rs +++ b/src/views/edit_view.rs @@ -8,7 +8,7 @@ use std::rc::Rc; use theme::{ColorStyle, Effect}; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; -use utils::simple_suffix_length; +use utils::simple_suffix; use vec::Vec2; use view::View; @@ -240,8 +240,8 @@ impl EditView { // From the end, count the length until we reach `available`. // Then sum the byte lengths. let suffix_length = - simple_suffix_length(&self.content[self.offset..self.cursor], - available); + simple_suffix(&self.content[self.offset..self.cursor], + available).length; self.offset = self.cursor - suffix_length; // Make sure the cursor is in view assert!(self.cursor >= self.offset); @@ -250,8 +250,8 @@ impl EditView { // If we have too much space if self.content[self.offset..].width() < self.last_length { - let suffix_length = simple_suffix_length(&self.content, - self.last_length - 1); + let suffix_length = simple_suffix(&self.content, + self.last_length - 1).length; self.offset = self.content.len() - suffix_length; } } diff --git a/src/views/text_area.rs b/src/views/text_area.rs index eddd82a..5536e86 100644 --- a/src/views/text_area.rs +++ b/src/views/text_area.rs @@ -7,7 +7,7 @@ use odds::vec::VecExt; use theme::{ColorStyle, Effect}; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; -use utils::{LinesIterator, Row, prefix_length}; +use utils::{LinesIterator, Row, prefix}; use vec::Vec2; use view::{ScrollBase, SizeCache, View}; @@ -126,7 +126,7 @@ impl TextArea { let prev_row = self.rows[row_id - 1]; let prev_text = &self.content[prev_row.start..prev_row.end]; - let offset = prefix_length(prev_text.graphemes(true), x, ""); + let offset = prefix(prev_text.graphemes(true), x, "").length; self.cursor = prev_row.start + offset; } @@ -139,7 +139,7 @@ impl TextArea { let next_row = self.rows[row_id + 1]; let next_text = &self.content[next_row.start..next_row.end]; - let offset = prefix_length(next_text.graphemes(true), x, ""); + let offset = prefix(next_text.graphemes(true), x, "").length; self.cursor = next_row.start + offset; }