2025-03-18 09:11:57 +08:00
|
|
|
use helix_core::Position;
|
|
|
|
|
|
|
|
use helix_view::theme::Style;
|
|
|
|
use helix_view::Theme;
|
|
|
|
|
|
|
|
use crate::ui::document::{LinePos, TextRenderer};
|
|
|
|
use crate::ui::text_decorations::Decoration;
|
|
|
|
|
2025-03-26 04:02:05 +08:00
|
|
|
pub enum LineBlame {
|
|
|
|
OneLine((usize, String)),
|
|
|
|
// Optimization: Use `Vec<T>` insted of `HashMap<usize, T>`
|
|
|
|
// because we know that the amount of lines visible in the viewport X3 cannot be a very large number,
|
|
|
|
// most likely up to a few hundred. In the absolute extreme case, maybe 5,000.
|
|
|
|
ManyLines(Vec<Option<String>>),
|
|
|
|
}
|
|
|
|
|
2025-03-18 09:11:57 +08:00
|
|
|
pub struct InlineBlame {
|
2025-03-26 04:02:05 +08:00
|
|
|
lines: LineBlame,
|
2025-03-18 09:11:57 +08:00
|
|
|
style: Style,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InlineBlame {
|
2025-03-26 04:02:05 +08:00
|
|
|
pub fn new(theme: &Theme, lines: LineBlame) -> Self {
|
2025-03-18 09:11:57 +08:00
|
|
|
InlineBlame {
|
|
|
|
style: theme.get("ui.virtual.inline-blame"),
|
2025-03-25 20:25:12 +08:00
|
|
|
lines,
|
2025-03-18 09:11:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decoration for InlineBlame {
|
|
|
|
fn render_virt_lines(
|
|
|
|
&mut self,
|
|
|
|
renderer: &mut TextRenderer,
|
|
|
|
pos: LinePos,
|
|
|
|
virt_off: Position,
|
|
|
|
) -> Position {
|
2025-03-26 04:02:05 +08:00
|
|
|
let blame = match &self.lines {
|
|
|
|
LineBlame::OneLine((line, blame)) => {
|
|
|
|
if line != &pos.doc_line {
|
|
|
|
// do not draw inline blame for lines that have no content in them
|
|
|
|
blame
|
|
|
|
} else {
|
|
|
|
return Position::new(0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LineBlame::ManyLines(lines) => {
|
|
|
|
if let Some(Some(blame)) = lines.get(pos.doc_line) {
|
|
|
|
blame
|
|
|
|
} else {
|
|
|
|
// do not draw inline blame for lines that have no content in them
|
|
|
|
return Position::new(0, 0);
|
|
|
|
}
|
|
|
|
}
|
2025-03-25 20:25:12 +08:00
|
|
|
};
|
2025-03-18 09:11:57 +08:00
|
|
|
|
|
|
|
// where the line in the document ends
|
|
|
|
let end_of_line = virt_off.col as u16;
|
|
|
|
// length of line in the document
|
|
|
|
// draw the git blame 6 spaces after the end of the line
|
|
|
|
let start_drawing_at = end_of_line + 6;
|
|
|
|
|
|
|
|
let amount_of_characters_drawn = renderer
|
|
|
|
.column_in_bounds(start_drawing_at as usize, 1)
|
|
|
|
.then(|| {
|
|
|
|
// the column where we stop drawing the blame
|
|
|
|
let stopped_drawing_at = renderer
|
|
|
|
.set_string_truncated(
|
|
|
|
renderer.viewport.x + start_drawing_at,
|
|
|
|
pos.visual_line,
|
2025-03-25 20:34:01 +08:00
|
|
|
blame,
|
2025-03-18 09:11:57 +08:00
|
|
|
renderer.viewport.width.saturating_sub(start_drawing_at) as usize,
|
|
|
|
|_| self.style,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let line_length = end_of_line - renderer.offset.col as u16;
|
|
|
|
|
|
|
|
stopped_drawing_at - line_length
|
|
|
|
})
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
|
|
|
Position::new(0, amount_of_characters_drawn as usize)
|
|
|
|
}
|
|
|
|
}
|