Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 105 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"examples/tiny_skia_render",
"examples/vello_cpu_render",
"examples/editor",
"examples/rich_editor",
"xtask",
]

Expand All @@ -33,6 +34,7 @@ repository = "https://github.com/linebender/parley"

[workspace.dependencies]
# Local crates
attributed_text = { version = "0.1.0", default-features = false, path = "attributed_text" }
parlance = { version = "0.1.0", default-features = false, path = "parlance" }
fontique = { version = "0.11.0", default-features = false, path = "fontique" }
parley = { version = "0.11.0", default-features = false, path = "parley" }
Expand Down
45 changes: 29 additions & 16 deletions attributed_text/src/attribute_segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ fn build_segment_state_from_ranges<I>(
}
}

fn build_segment_state<T: Debug + TextStorage, Attr: Debug>(
fn build_segment_state<T: Clone + Debug + TextStorage, Attr: Clone + Debug>(
attributed: &AttributedText<T, Attr>,
workspace: &mut AttributeSegmentsWorkspace,
) {
Expand Down Expand Up @@ -202,7 +202,7 @@ impl AttributeSegmentsWorkspace {
}

/// Build an iterator using this workspace's retained allocations.
pub fn segments<'w, 'a, T: Debug + TextStorage, Attr: Debug>(
pub fn segments<'w, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug>(
&'w mut self,
attributed: &'a AttributedText<T, Attr>,
) -> AttributeSegments<'w, 'a, T, Attr> {
Expand Down Expand Up @@ -271,7 +271,7 @@ impl AttributeSegmentsWorkspace {
/// ```
/// use attributed_text::{AttributeSegmentsWorkspace, AttributedText, TextRange};
///
/// #[derive(Debug, PartialEq, Eq)]
/// #[derive(Clone, Debug, PartialEq, Eq)]
/// enum Color {
/// Red,
/// Blue,
Expand Down Expand Up @@ -358,13 +358,15 @@ impl AttributeSegmentsWorkspace {
/// Zero-length attribute ranges are excluded from the active span set, but their boundaries are
/// still included in segmentation, so they can split output ranges.
#[derive(Debug)]
pub struct AttributeSegments<'w, 'a, T: Debug + TextStorage, Attr: Debug> {
pub struct AttributeSegments<'w, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> {
attributed: &'a AttributedText<T, Attr>,
workspace: &'w mut AttributeSegmentsWorkspace,
index: usize,
}

impl<'w, 'a, T: Debug + TextStorage, Attr: Debug> AttributeSegments<'w, 'a, T, Attr> {
impl<'w, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug>
AttributeSegments<'w, 'a, T, Attr>
{
fn update_active_for_boundary(&mut self, boundary_index: usize) {
update_active_for_boundary(self.workspace, boundary_index);
}
Expand Down Expand Up @@ -397,13 +399,15 @@ impl<'w, 'a, T: Debug + TextStorage, Attr: Debug> AttributeSegments<'w, 'a, T, A

/// A range yielded by [`AttributeSegments`] with its active attribute spans.
#[derive(Clone, Debug)]
pub struct AttributeSegment<'s, 'a, T: Debug + TextStorage, Attr: Debug> {
pub struct AttributeSegment<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> {
range: TextRange,
active_ids: &'s [u32],
attributed: &'a AttributedText<T, Attr>,
}

impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> AttributeSegment<'s, 'a, T, Attr> {
impl<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug>
AttributeSegment<'s, 'a, T, Attr>
{
/// Returns the segment range.
#[must_use]
pub const fn range(&self) -> TextRange {
Expand All @@ -420,7 +424,9 @@ impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> AttributeSegment<'s, 'a, T, At
}
}

impl<T: Debug + TextStorage, Attr: Debug> Iterator for AttributeSegments<'_, '_, T, Attr> {
impl<T: Clone + Debug + TextStorage, Attr: Clone + Debug> Iterator
for AttributeSegments<'_, '_, T, Attr>
{
type Item = TextRange;

fn size_hint(&self) -> (usize, Option<usize>) {
Expand Down Expand Up @@ -448,7 +454,9 @@ impl<T: Debug + TextStorage, Attr: Debug> Iterator for AttributeSegments<'_, '_,
}
}

impl<T: Debug + TextStorage, Attr: Debug> ExactSizeIterator for AttributeSegments<'_, '_, T, Attr> {
impl<T: Clone + Debug + TextStorage, Attr: Clone + Debug> ExactSizeIterator
for AttributeSegments<'_, '_, T, Attr>
{
fn len(&self) -> usize {
// Remaining segments are remaining adjacent boundary pairs: [i, i + 1).
self.workspace
Expand All @@ -463,7 +471,7 @@ impl<T: Debug + TextStorage, Attr: Debug> ExactSizeIterator for AttributeSegment
/// Provides iteration in both application order (ascending span id) and reverse
/// application order (descending span id — useful for last-writer-wins resolution).
#[derive(Clone, Debug)]
pub struct ActiveSpans<'s, 'a, T: Debug + TextStorage, Attr: Debug> {
pub struct ActiveSpans<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> {
active_ids: &'s [u32],
attributed: &'a AttributedText<T, Attr>,
}
Expand All @@ -473,12 +481,14 @@ pub struct ActiveSpans<'s, 'a, T: Debug + TextStorage, Attr: Debug> {
/// Obtain this by calling [`ActiveSpans::iter`] or by iterating `&ActiveSpans`
/// via [`IntoIterator`].
#[derive(Clone, Debug)]
pub struct ActiveSpansIter<'s, 'a, T: Debug + TextStorage, Attr: Debug> {
pub struct ActiveSpansIter<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> {
ids: core::slice::Iter<'s, u32>,
attributed: &'a AttributedText<T, Attr>,
}

impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> Iterator for ActiveSpansIter<'s, 'a, T, Attr> {
impl<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> Iterator
for ActiveSpansIter<'s, 'a, T, Attr>
{
type Item = (TextRange, &'a Attr);

fn size_hint(&self) -> (usize, Option<usize>) {
Expand All @@ -495,9 +505,12 @@ impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> Iterator for ActiveSpansIter<'
}
}

impl<T: Debug + TextStorage, Attr: Debug> ExactSizeIterator for ActiveSpansIter<'_, '_, T, Attr> {}
impl<T: Clone + Debug + TextStorage, Attr: Clone + Debug> ExactSizeIterator
for ActiveSpansIter<'_, '_, T, Attr>
{
}

impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> DoubleEndedIterator
impl<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> DoubleEndedIterator
for ActiveSpansIter<'s, 'a, T, Attr>
{
fn next_back(&mut self) -> Option<Self::Item> {
Expand All @@ -510,7 +523,7 @@ impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> DoubleEndedIterator
}
}

impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> ActiveSpans<'s, 'a, T, Attr> {
impl<'s, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> ActiveSpans<'s, 'a, T, Attr> {
/// Iterate over the active spans in application order (ascending span id).
///
/// Each item is `(TextRange, &Attr)`.
Expand All @@ -532,7 +545,7 @@ impl<'s, 'a, T: Debug + TextStorage, Attr: Debug> ActiveSpans<'s, 'a, T, Attr> {
}
}

impl<'active, 's, 'a, T: Debug + TextStorage, Attr: Debug> IntoIterator
impl<'active, 's, 'a, T: Clone + Debug + TextStorage, Attr: Clone + Debug> IntoIterator
for &'active ActiveSpans<'s, 'a, T, Attr>
{
type Item = (TextRange, &'a Attr);
Expand Down
8 changes: 4 additions & 4 deletions attributed_text/src/attributed_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ use crate::text_range::validate_range;
use crate::{Error, TextChunk, TextRange, TextStorage};

/// A block of text with attributes applied to ranges within the text.
#[derive(Debug)]
pub struct AttributedText<T: Debug + TextStorage, Attr: Debug> {
#[derive(Clone, Debug)]
pub struct AttributedText<T: Clone + Debug + TextStorage, Attr: Clone + Debug> {
text: T,
attributes: Vec<(TextRange, Attr)>,
}

impl<T: Debug + TextStorage, Attr: Debug> AttributedText<T, Attr> {
impl<T: Clone + Debug + TextStorage, Attr: Clone + Debug> AttributedText<T, Attr> {
/// Create an `AttributedText` with no attributes applied.
pub fn new(text: T) -> Self {
Self {
Expand Down Expand Up @@ -166,7 +166,7 @@ mod tests {
use alloc::vec;
use alloc::vec::Vec;

#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
enum TestAttribute {
Keep,
Remove,
Expand Down
Loading
Loading