use With;
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
use utils::prefix_length;
pub struct LinesIterator<'a> {
content: &'a str,
offset: usize,
width: usize,
show_spaces: bool,
}
impl<'a> LinesIterator<'a> {
pub fn new(content: &'a str, width: usize) -> Self {
LinesIterator {
content: content,
width: width,
offset: 0,
show_spaces: false,
}
}
pub fn show_spaces(mut self) -> Self {
self.show_spaces = true;
self
}
}
#[derive(Debug, Clone, Copy)]
pub struct Row {
pub start: usize,
pub end: usize,
pub width: usize,
}
impl Row {
pub fn shift(&mut self, offset: usize) {
self.start += offset;
self.end += offset;
}
pub fn shifted(self, offset: usize) -> Self {
self.with(|s| s.shift(offset))
}
pub fn rev_shift(&mut self, offset: usize) {
self.start -= offset;
self.end -= offset;
}
}
impl<'a> Iterator for LinesIterator<'a> {
type Item = Row;
fn next(&mut self) -> Option<Row> {
if self.offset >= self.content.len() {
return None;
}
let start = self.offset;
let content = &self.content[start..];
let next = content.find('\n').unwrap_or(content.len());
let content = &content[..next];
let allowed_width = if self.show_spaces {
self.width - 1
} else {
self.width
};
let line_width = content.width();
if line_width <= allowed_width {
self.offset += next + 1;
return Some(Row {
start: start,
end: start + next,
width: line_width,
});
}
let prefix_length =
match prefix_length(content.split(' '), allowed_width, " ") {
0 => prefix_length(content.graphemes(true), self.width, ""),
other => {
self.offset += 1;
other
}
};
if prefix_length == 0 {
return None;
}
self.offset += prefix_length;
Some(Row {
start: start,
end: start + prefix_length,
width: self.width,
})
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_layout() {}
}