Merge pull request #107 from dermetfan/prefix

return length and width from utils::prefix(_length)
This commit is contained in:
Alexandre Bury 2017-02-01 11:56:04 -08:00 committed by GitHub
commit 57c1c1ad61
5 changed files with 37 additions and 24 deletions

View File

@ -9,7 +9,7 @@ use std::rc::Rc;
use theme::{BorderStyle, ColorStyle, Effect, Theme}; use theme::{BorderStyle, ColorStyle, Effect, Theme};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use utils::prefix_length; use utils::prefix;
use vec::Vec2; use vec::Vec2;
/// Convenient interface to draw on a subset of the screen. /// 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; let room = self.size.x - p.x;
// We want the number of CHARACTERS, not bytes. // We want the number of CHARACTERS, not bytes.
// (Actually we want the "width" of the string, see unicode-width) // (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 text = &text[..prefix_len];
let p = p + self.offset; let p = p + self.offset;

View File

@ -3,7 +3,7 @@
use With; use With;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use utils::prefix_length; use utils::prefix;
/// Generates rows of text in constrained width. /// Generates rows of text in constrained width.
/// ///
@ -119,11 +119,11 @@ impl<'a> Iterator for LinesIterator<'a> {
// First attempt: only break on spaces. // First attempt: only break on spaces.
let prefix_length = 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. // If this fail, fallback: only break on graphemes.
// There's no whitespace to skip there. // There's no whitespace to skip there.
// And don't reserve the white space anymore. // 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 => { other => {
// If it works, advance the cursor by 1 // If it works, advance the cursor by 1
// to jump the whitespace. // to jump the whitespace.

View File

@ -9,7 +9,15 @@ mod reader;
pub use self::lines_iterator::{LinesIterator, Row}; pub use self::lines_iterator::{LinesIterator, Row};
pub use self::reader::ProgressReader; 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 /// Takes non-breakable elements from `iter`, while keeping the
/// string width under `width` (and adding the length of `delimiter` /// string width under `width` (and adding the length of `delimiter`
@ -26,15 +34,15 @@ pub use self::reader::ProgressReader;
/// extern crate unicode_segmentation; /// extern crate unicode_segmentation;
/// use unicode_segmentation::UnicodeSegmentation; /// use unicode_segmentation::UnicodeSegmentation;
/// ///
/// # use cursive::utils::prefix_length; /// # use cursive::utils::prefix;
/// # fn main() { /// # fn main() {
/// let my_text = "blah..."; /// let my_text = "blah...";
/// // This returns the number of bytes for a prefix of `my_text` that /// // This returns the number of bytes for a prefix of `my_text` that
/// // fits within 5 cells. /// // 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<Item = &'a str> where I: Iterator<Item = &'a str>
{ {
let delimiter_width = delimiter.width(); 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, // We counted delimiter once too many times,
// but only if the iterator was non empty. // 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`. /// 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`. /// suffix from `text` that fits in `width`.
/// ///
/// This is a shortcut for `prefix_length(iter.rev(), width, delimiter)` /// 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<Item = &'a str> where I: DoubleEndedIterator<Item = &'a str>
{ {
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. /// Breaks between any two graphemes.
pub fn simple_suffix_length(text: &str, width: usize) -> usize { pub fn simple_suffix(text: &str, width: usize) -> Prefix {
suffix_length(text.graphemes(true), width, "") suffix(text.graphemes(true), width, "")
} }

View File

@ -8,7 +8,7 @@ use std::rc::Rc;
use theme::{ColorStyle, Effect}; use theme::{ColorStyle, Effect};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use utils::simple_suffix_length; use utils::simple_suffix;
use vec::Vec2; use vec::Vec2;
use view::View; use view::View;
@ -240,8 +240,8 @@ impl EditView {
// From the end, count the length until we reach `available`. // From the end, count the length until we reach `available`.
// Then sum the byte lengths. // Then sum the byte lengths.
let suffix_length = let suffix_length =
simple_suffix_length(&self.content[self.offset..self.cursor], simple_suffix(&self.content[self.offset..self.cursor],
available); available).length;
self.offset = self.cursor - suffix_length; self.offset = self.cursor - suffix_length;
// Make sure the cursor is in view // Make sure the cursor is in view
assert!(self.cursor >= self.offset); assert!(self.cursor >= self.offset);
@ -250,8 +250,8 @@ impl EditView {
// If we have too much space // If we have too much space
if self.content[self.offset..].width() < self.last_length { if self.content[self.offset..].width() < self.last_length {
let suffix_length = simple_suffix_length(&self.content, let suffix_length = simple_suffix(&self.content,
self.last_length - 1); self.last_length - 1).length;
self.offset = self.content.len() - suffix_length; self.offset = self.content.len() - suffix_length;
} }
} }

View File

@ -7,7 +7,7 @@ use odds::vec::VecExt;
use theme::{ColorStyle, Effect}; use theme::{ColorStyle, Effect};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use utils::{LinesIterator, Row, prefix_length}; use utils::{LinesIterator, Row, prefix};
use vec::Vec2; use vec::Vec2;
use view::{ScrollBase, SizeCache, View}; use view::{ScrollBase, SizeCache, View};
@ -126,7 +126,7 @@ impl TextArea {
let prev_row = self.rows[row_id - 1]; let prev_row = self.rows[row_id - 1];
let prev_text = &self.content[prev_row.start..prev_row.end]; 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; self.cursor = prev_row.start + offset;
} }
@ -139,7 +139,7 @@ impl TextArea {
let next_row = self.rows[row_id + 1]; let next_row = self.rows[row_id + 1];
let next_text = &self.content[next_row.start..next_row.end]; 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; self.cursor = next_row.start + offset;
} }