mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-10 07:04:17 +00:00
feat(line): implement iterators for Line (#896)
This allows iterating over the `Span`s of a line using `for` loops and other iterator methods. - add `iter` and `iter_mut` methods to `Line` - implement `IntoIterator` for `Line`, `&Line`, and `&mut Line` traits - update call sites to iterate over `Line` rather than `Line::spans`
This commit is contained in:
parent
86168aa711
commit
4278b4088d
3 changed files with 130 additions and 4 deletions
|
@ -243,7 +243,7 @@ impl Buffer {
|
|||
pub fn set_line(&mut self, x: u16, y: u16, line: &Line<'_>, width: u16) -> (u16, u16) {
|
||||
let mut remaining_width = width;
|
||||
let mut x = x;
|
||||
for span in &line.spans {
|
||||
for span in line {
|
||||
if remaining_width == 0 {
|
||||
break;
|
||||
}
|
||||
|
|
129
src/text/line.rs
129
src/text/line.rs
|
@ -368,6 +368,43 @@ impl<'a> Line<'a> {
|
|||
pub fn reset_style(self) -> Self {
|
||||
self.patch_style(Style::reset())
|
||||
}
|
||||
|
||||
/// Returns an iterator over the spans of this line.
|
||||
pub fn iter(&self) -> std::slice::Iter<Span<'a>> {
|
||||
self.spans.iter()
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the spans of this line.
|
||||
pub fn iter_mut(&mut self) -> std::slice::IterMut<Span<'a>> {
|
||||
self.spans.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for Line<'a> {
|
||||
type Item = Span<'a>;
|
||||
type IntoIter = std::vec::IntoIter<Span<'a>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.spans.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Line<'a> {
|
||||
type Item = &'a Span<'a>;
|
||||
type IntoIter = std::slice::Iter<'a, Span<'a>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Line<'a> {
|
||||
type Item = &'a mut Span<'a>;
|
||||
type IntoIter = std::slice::IterMut<'a, Span<'a>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<String> for Line<'a> {
|
||||
|
@ -399,7 +436,7 @@ impl<'a> From<Span<'a>> for Line<'a> {
|
|||
|
||||
impl<'a> From<Line<'a>> for String {
|
||||
fn from(line: Line<'a>) -> String {
|
||||
line.spans.iter().fold(String::new(), |mut acc, s| {
|
||||
line.iter().fold(String::new(), |mut acc, s| {
|
||||
acc.push_str(s.content.as_ref());
|
||||
acc
|
||||
})
|
||||
|
@ -461,6 +498,8 @@ impl std::fmt::Display for Line<'_> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rstest::{fixture, rstest};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -752,4 +791,92 @@ mod tests {
|
|||
let line = Line::from("Hello, world!").right_aligned();
|
||||
assert_eq!(line.alignment, Some(Alignment::Right));
|
||||
}
|
||||
|
||||
mod iterators {
|
||||
use super::*;
|
||||
|
||||
/// a fixture used in the tests below to avoid repeating the same setup
|
||||
#[fixture]
|
||||
fn hello_world() -> Line<'static> {
|
||||
Line::from(vec![
|
||||
Span::styled("Hello ", Color::Blue),
|
||||
Span::styled("world!", Color::Green),
|
||||
])
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn iter(hello_world: Line<'_>) {
|
||||
let mut iter = hello_world.iter();
|
||||
assert_eq!(iter.next(), Some(&Span::styled("Hello ", Color::Blue)));
|
||||
assert_eq!(iter.next(), Some(&Span::styled("world!", Color::Green)));
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn iter_mut(mut hello_world: Line<'_>) {
|
||||
let mut iter = hello_world.iter_mut();
|
||||
assert_eq!(iter.next(), Some(&mut Span::styled("Hello ", Color::Blue)));
|
||||
assert_eq!(iter.next(), Some(&mut Span::styled("world!", Color::Green)));
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn into_iter(hello_world: Line<'_>) {
|
||||
let mut iter = hello_world.into_iter();
|
||||
assert_eq!(iter.next(), Some(Span::styled("Hello ", Color::Blue)));
|
||||
assert_eq!(iter.next(), Some(Span::styled("world!", Color::Green)));
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn into_iter_ref(hello_world: Line<'_>) {
|
||||
let mut iter = (&hello_world).into_iter();
|
||||
assert_eq!(iter.next(), Some(&Span::styled("Hello ", Color::Blue)));
|
||||
assert_eq!(iter.next(), Some(&Span::styled("world!", Color::Green)));
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_iter_mut_ref() {
|
||||
let mut hello_world = Line::from(vec![
|
||||
Span::styled("Hello ", Color::Blue),
|
||||
Span::styled("world!", Color::Green),
|
||||
]);
|
||||
let mut iter = (&mut hello_world).into_iter();
|
||||
assert_eq!(iter.next(), Some(&mut Span::styled("Hello ", Color::Blue)));
|
||||
assert_eq!(iter.next(), Some(&mut Span::styled("world!", Color::Green)));
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn for_loop_ref(hello_world: Line<'_>) {
|
||||
let mut result = String::new();
|
||||
for span in &hello_world {
|
||||
result.push_str(span.content.as_ref());
|
||||
}
|
||||
assert_eq!(result, "Hello world!");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn for_loop_mut_ref() {
|
||||
let mut hello_world = Line::from(vec![
|
||||
Span::styled("Hello ", Color::Blue),
|
||||
Span::styled("world!", Color::Green),
|
||||
]);
|
||||
let mut result = String::new();
|
||||
for span in &mut hello_world {
|
||||
result.push_str(span.content.as_ref());
|
||||
}
|
||||
assert_eq!(result, "Hello world!");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn for_loop_into(hello_world: Line<'_>) {
|
||||
let mut result = String::new();
|
||||
for span in hello_world {
|
||||
result.push_str(span.content.as_ref());
|
||||
}
|
||||
assert_eq!(result, "Hello world!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,8 +357,7 @@ mod test {
|
|||
let text = text.into();
|
||||
let styled_lines = text.lines.iter().map(|line| {
|
||||
(
|
||||
line.spans
|
||||
.iter()
|
||||
line.iter()
|
||||
.flat_map(|span| span.styled_graphemes(Style::default())),
|
||||
line.alignment.unwrap_or(Alignment::Left),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue