diff --git a/helix-term/src/ui/document.rs b/helix-term/src/ui/document.rs index 8423ae8e4..356027213 100644 --- a/helix-term/src/ui/document.rs +++ b/helix-term/src/ui/document.rs @@ -81,6 +81,8 @@ pub struct LinePos { pub doc_line: usize, /// Vertical offset from the top of the inner view area pub visual_line: u16, + /// The given visual line is the last visual line of the document line + pub is_last_visual_line: bool, } #[allow(clippy::too_many_arguments)] @@ -154,6 +156,7 @@ pub fn render_text( first_visual_line: false, doc_line: usize::MAX, visual_line: u16::MAX, + is_last_visual_line: true, }; let mut last_line_end = 0; let mut is_in_indent_area = true; @@ -188,6 +191,10 @@ pub fn render_text( // apply decorations before rendering a new line if grapheme.visual_pos.row as u16 != last_line_pos.visual_line { + if last_line_pos.doc_line == grapheme.line_idx { + last_line_pos.is_last_visual_line = false; + } + // we initiate doc_line with usize::MAX because no file // can reach that size (memory allocations are limited to isize::MAX) // initially there is no "previous" line (so doc_line is set to usize::MAX) @@ -202,6 +209,7 @@ pub fn render_text( first_visual_line: grapheme.line_idx != last_line_pos.doc_line, doc_line: grapheme.line_idx, visual_line: grapheme.visual_pos.row as u16, + is_last_visual_line: true, }; decorations.decorate_line(renderer, last_line_pos); } diff --git a/helix-term/src/ui/text_decorations/blame.rs b/helix-term/src/ui/text_decorations/blame.rs index 645a0462c..a7df9f632 100644 --- a/helix-term/src/ui/text_decorations/blame.rs +++ b/helix-term/src/ui/text_decorations/blame.rs @@ -31,6 +31,17 @@ impl Decoration for InlineBlame { pos: LinePos, virt_off: Position, ) -> Position { + // Only render inline blame on the last visual line + // This prevents it being rendered multiple times per line, if the + // line is wrapping. + // + // We want to render it on the last visual line because unless the user + // has `soft-wrap.wrap-at-text-width` enabled, for a document line that wraps + // there will only be space to render inline blame at the last doc line + if !pos.is_last_visual_line { + return Position::new(0, 0); + } + let blame = match &self.lines { LineBlame::OneLine((line, blame)) => { if line == &pos.doc_line {