From e298259dd5d8281367303e50c72ce857a03c8f8a Mon Sep 17 00:00:00 2001 From: tigregalis Date: Mon, 8 May 2023 18:11:36 +0800 Subject: [PATCH 1/4] introduce `BidiParagraphs` iterator --- src/bidi_para.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ 2 files changed, 42 insertions(+) create mode 100644 src/bidi_para.rs diff --git a/src/bidi_para.rs b/src/bidi_para.rs new file mode 100644 index 0000000..461665e --- /dev/null +++ b/src/bidi_para.rs @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use unicode_bidi::{bidi_class, BidiClass, BidiInfo, ParagraphInfo}; + +/// An iterator over the paragraphs in the input text. +/// It is equivalent to [`core::str::Lines`] but follows `unicode-bidi` behaviour. +pub struct BidiParagraphs<'text> { + text: &'text str, + info: std::vec::IntoIter, +} + +impl<'text> BidiParagraphs<'text> { + /// Create an iterator to split the input text into paragraphs + /// in accordance with `unicode-bidi` behaviour. + pub fn new(text: &'text str) -> Self { + let info = BidiInfo::new(text, None); + let info = info.paragraphs.into_iter(); + Self { text, info } + } +} + +impl<'text> Iterator for BidiParagraphs<'text> { + type Item = &'text str; + + fn next(&mut self) -> Option { + let para = self.info.next()?; + let paragraph = &self.text[para.range]; + // `para.range` includes the newline that splits the line, so remove it if present + let mut char_indices = paragraph.char_indices(); + if let Some(i) = char_indices.next_back().and_then(|(i, c)| { + // `BidiClass::B` is a Paragraph_Separator (various newline characters) + (bidi_class(c) == BidiClass::B).then_some(i) + }) { + Some(¶graph[0..i]) + } else { + Some(paragraph) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index f4b700e..a07eecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,6 +95,9 @@ extern crate alloc; pub use self::attrs::*; mod attrs; +pub use self::bidi_para::*; +mod bidi_para; + pub use self::buffer::*; mod buffer; From 6e336ad1cded98c3b4eeabb0521ad7048216d226 Mon Sep 17 00:00:00 2001 From: tigregalis Date: Mon, 8 May 2023 18:12:36 +0800 Subject: [PATCH 2/4] replace use of `str::lines` with `BidiParagraphs` --- examples/editor-test/src/main.rs | 5 +++-- src/buffer.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/editor-test/src/main.rs b/examples/editor-test/src/main.rs index ea859d5..12318ce 100644 --- a/examples/editor-test/src/main.rs +++ b/examples/editor-test/src/main.rs @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use cosmic_text::{ - Action, BorrowedWithFontSystem, Buffer, Color, Edit, Editor, FontSystem, Metrics, SwashCache, + Action, BidiParagraphs, BorrowedWithFontSystem, Buffer, Color, Edit, Editor, FontSystem, + Metrics, SwashCache, }; use orbclient::{EventOption, Renderer, Window, WindowFlag}; use std::{env, fs, process, time::Instant}; @@ -84,7 +85,7 @@ fn main() { let test_start = Instant::now(); //TODO: support bidi - for line in text.lines() { + for line in BidiParagraphs::new(&text) { log::debug!("Line {:?}", line); for grapheme in line.graphemes(true) { diff --git a/src/buffer.rs b/src/buffer.rs index 7ddd20d..0807911 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -9,8 +9,8 @@ use core::{cmp, fmt}; use unicode_segmentation::UnicodeSegmentation; use crate::{ - Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, Color, FontSystem, LayoutGlyph, - LayoutLine, ShapeLine, Shaping, Wrap, + Attrs, AttrsList, BidiParagraphs, BorrowedWithFontSystem, BufferLine, Color, FontSystem, + LayoutGlyph, LayoutLine, ShapeLine, Shaping, Wrap, }; /// Current cursor location @@ -580,7 +580,7 @@ impl Buffer { shaping: Shaping, ) { self.lines.clear(); - for line in text.lines() { + for line in BidiParagraphs::new(text) { self.lines.push(BufferLine::new( line.to_string(), AttrsList::new(attrs), From 053efa77b66cbf6ae3a6d36ba9a7252af801593b Mon Sep 17 00:00:00 2001 From: tigregalis Date: Mon, 8 May 2023 18:24:38 +0800 Subject: [PATCH 3/4] remove todo comment --- examples/editor-test/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/editor-test/src/main.rs b/examples/editor-test/src/main.rs index 12318ce..8f3effe 100644 --- a/examples/editor-test/src/main.rs +++ b/examples/editor-test/src/main.rs @@ -84,7 +84,6 @@ fn main() { let test_start = Instant::now(); - //TODO: support bidi for line in BidiParagraphs::new(&text) { log::debug!("Line {:?}", line); From 5ab509ebaa3bce7c41bd1111a94c462297883cda Mon Sep 17 00:00:00 2001 From: tigregalis Date: Thu, 11 May 2023 17:14:52 +0800 Subject: [PATCH 4/4] use `alloc::vec` instead of `std::vec` --- src/bidi_para.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bidi_para.rs b/src/bidi_para.rs index 461665e..fd50d0d 100644 --- a/src/bidi_para.rs +++ b/src/bidi_para.rs @@ -6,7 +6,7 @@ use unicode_bidi::{bidi_class, BidiClass, BidiInfo, ParagraphInfo}; /// It is equivalent to [`core::str::Lines`] but follows `unicode-bidi` behaviour. pub struct BidiParagraphs<'text> { text: &'text str, - info: std::vec::IntoIter, + info: alloc::vec::IntoIter, } impl<'text> BidiParagraphs<'text> {