feat: all-lines option for inline blame

This commit is contained in:
Nik Revenco 2025-03-25 12:25:12 +00:00
parent 7478d9e688
commit 76a92aff2f
4 changed files with 31 additions and 16 deletions
book/src
helix-term/src/ui
editor.rs
text_decorations
helix-view/src

View file

@ -170,7 +170,8 @@ The following statusline elements can be configured:
| `format` | The format in which to show the inline blame | `"{author}, {time-ago} • {message} • {commit}"` |
The `behaviour` can be one of the following:
- `"visible"`: Inline blame is turned on. Virtual text will appear at the end of each non-empty line, showing information about the latest commit for that line.
- `"all-lines"`: Inline blame is turned on. Virtual text will appear at the end of each non-empty line, showing information about the latest commit for that line.
- `"cursor-line"`: Inline blame is turned on. Virtual text will appear at the end of the current cursor line, showing information about the latest commit for that line.
- `"background"`: Inline blame is turned off, but the blame is still requested in the background when opening and reloading files. This will have zero impact on performance, but will use slightly more resources in the background. This allows blame for line (`space + B`) to be retrieved instantaneously with zero delay.
- `"disabled"`: Inline blame is turned off, with no requests happening in the background. When you run `space + B` for the first time in a file, it will load the blame for this file. You may have to wait a little bit for the blame to become available, depending on the size of your repository. After it becomes available, for this file `space + B` will retrieve the blame for any line in this file with zero delay. If the file is reloaded, the process will repeat as the blame is potentially out of date and needs to be refreshed.

View file

@ -31,7 +31,7 @@ use helix_view::{
keyboard::{KeyCode, KeyModifiers},
Document, Editor, Theme, View,
};
use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc};
use std::{collections::HashMap, mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc};
use tui::{buffer::Buffer as Surface, text::Span};
@ -204,7 +204,7 @@ impl EditorView {
config.end_of_line_diagnostics,
));
if config.inline_blame.behaviour == InlineBlameBehaviour::Visible {
if config.inline_blame.behaviour == InlineBlameBehaviour::CursorLine {
let cursor_line_idx = doc.cursor_line(view.id);
// do not render inline blame for empty lines to reduce visual noise
@ -214,11 +214,23 @@ impl EditorView {
{
decorations.add_decoration(InlineBlame::new(
theme,
cursor_line_idx,
line_blame,
HashMap::from([(cursor_line_idx, line_blame)]),
));
};
}
} else if config.inline_blame.behaviour == InlineBlameBehaviour::AllLines {
let blame_for_all_lines = (0..doc.text().len_lines())
.filter_map(|line_idx| {
(doc.text().line(line_idx) != doc.line_ending.as_str())
.then(|| {
doc.line_blame(line_idx as u32, &config.inline_blame.format)
.ok()
.map(|blame| (line_idx, blame))
})
.flatten()
})
.collect();
decorations.add_decoration(InlineBlame::new(theme, blame_for_all_lines));
}
render_document(

View file

@ -1,3 +1,5 @@
use std::collections::HashMap;
use helix_core::Position;
use helix_view::theme::Style;
@ -7,17 +9,15 @@ use crate::ui::document::{LinePos, TextRenderer};
use crate::ui::text_decorations::Decoration;
pub struct InlineBlame {
message: String,
cursor: usize,
lines: HashMap<usize, String>,
style: Style,
}
impl InlineBlame {
pub fn new(theme: &Theme, cursor: usize, message: String) -> Self {
pub fn new(theme: &Theme, lines: HashMap<usize, String>) -> Self {
InlineBlame {
style: theme.get("ui.virtual.inline-blame"),
message,
cursor,
lines,
}
}
}
@ -29,10 +29,10 @@ impl Decoration for InlineBlame {
pos: LinePos,
virt_off: Position,
) -> Position {
// do not draw inline blame for lines other than the cursor line
if self.cursor != pos.doc_line {
let Some(blame) = self.lines.get(&pos.doc_line) else {
// do not draw inline blame for lines that have no content in them
return Position::new(0, 0);
}
};
// where the line in the document ends
let end_of_line = virt_off.col as u16;
@ -48,7 +48,7 @@ impl Decoration for InlineBlame {
.set_string_truncated(
renderer.viewport.x + start_drawing_at,
pos.visual_line,
&self.message,
&blame,
renderer.viewport.width.saturating_sub(start_drawing_at) as usize,
|_| self.style,
true,

View file

@ -188,8 +188,10 @@ pub enum InlineBlameBehaviour {
///
/// When manually requesting the inline blame, it may take several seconds to appear.
Disabled,
/// Show the inline blame
Visible,
/// Show the inline blame on the cursor line
CursorLine,
/// Show the inline blame on every other line
AllLines,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]