Repository: helix-editor/helix
File: helix-term/src/ui/document.rs (Rust)

Code before:
use helix_view::Document;
use helix_view::Theme;
use tui::buffer::Buffer as Surface;

pub trait LineDecoration {
    fn render_background(&mut self, _renderer: &mut TextRenderer, _pos: LinePos) {}
    fn render_foreground(
        &mut self,
        _renderer: &mut TextRenderer,
        _pos: LinePos,
        _end_char_idx: usize,
    ) {
    }
}

impl<F: FnMut(&mut TextRenderer, LinePos)> LineDecoration for F {
    fn render_background(&mut self, renderer: &mut TextRenderer, pos: LinePos) {
        self(renderer, pos)
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum StyleIterKind {
    /// base highlights (usually emitted by TS), byte indecies (potentially not codepoint aligned)
    BaseHighlights,
    /// overaly highlights (emitted by cumstom code from selections), char indecies
    Overlay,
}

/// A wrapper around a HighlightIterator
/// that merges the layered highlights to create the final text style
/// and yields the active text style and the char_idx where the active
/// style will have to be recomputed.
///
/// IS_BYTE_ITER indicates wether the source iterator provides byte or char
/// ranges
///
/// TODO(ropey2): hopefully one day helix and ropey will operate entirely
/// on byte ranges and we can remove this
struct StyleIter<'a, H: Iterator<Item = HighlightEvent>> {
    text_style: Style,
    active_highlights: Vec<Highlight>,
    highlight_iter: H,
    kind: StyleIterKind,
    text: RopeSlice<'a>,
    theme: &'a Theme,
}

impl<H: Iterator<Item = HighlightEvent>> Iterator for StyleIter<'_, H> {
    type Item = (Style, usize);
    fn next(&mut self) -> Option<(Style, usize)> {

Review comment (suggestion):
```suggestion
    /// base highlights (usually emitted by TS), byte indices (potentially not codepoint aligned)
    BaseHighlights,
    /// overlay highlights (emitted by custom code from selections), char indices
```

Code after:
use helix_view::Document;
use helix_view::Theme;
use tui::buffer::Buffer as Surface;

pub trait LineDecoration {
    fn render_background(&mut self, _renderer: &mut TextRenderer, _pos: LinePos) {}
    fn render_foreground(
        &mut self,
        _renderer: &mut TextRenderer,
        _pos: LinePos,
        _end_char_idx: usize,
    ) {
    }
}

impl<F: FnMut(&mut TextRenderer, LinePos)> LineDecoration for F {
    fn render_background(&mut self, renderer: &mut TextRenderer, pos: LinePos) {
        self(renderer, pos)
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum StyleIterKind {
    /// base highlights (usually emitted by TS), byte indices (potentially not codepoint aligned)
    BaseHighlights,
    /// overlay highlights (emitted by custom code from selections), char indices
    Overlay,
}

/// A wrapper around a HighlightIterator
/// that merges the layered highlights to create the final text style
/// and yields the active text style and the char_idx where the active
/// style will have to be recomputed.
///
/// TODO(ropey2): hopefully one day helix and ropey will operate entirely
/// on byte ranges and we can remove this
struct StyleIter<'a, H: Iterator<Item = HighlightEvent>> {
    text_style: Style,
    active_highlights: Vec<Highlight>,
    highlight_iter: H,
    kind: StyleIterKind,
    text: RopeSlice<'a>,
    theme: &'a Theme,
}

impl<H: Iterator<Item = HighlightEvent>> Iterator for StyleIter<'_, H> {
    type Item = (Style, usize);
    fn next(&mut self) -> Option<(Style, usize)> {
        while let Some(event) = self.highlight_iter.next() {
            match event {
                HighlightEvent::HighlightStart(highlights) => {