feat: split inline-blame.behaviour into two options

_

_
This commit is contained in:
Nik Revenco 2025-03-25 19:01:12 +00:00
parent b9f8226208
commit 22f9571687
6 changed files with 44 additions and 35 deletions
book/src
helix-term/src
helix-view/src

View file

@ -164,16 +164,24 @@ The following statusline elements can be configured:
### `[editor.inline-blame]` Section
Inline blame is virtual text that appears at the end of a line, displaying information about the most recent commit that affected this line.
| Key | Description | Default |
| ------- | ------------------------------------------ | ------- |
| `behaviour` | Choose the behaviour of inline blame | `"disabled"` |
| `behaviour` | Choose when to show inline blame | `"hidden"` |
| `compute` | Choose when inline blame should be computed | `"on-demand"` |
| `format` | The format in which to show the inline blame | `"{author}, {time-ago} • {message} • {commit}"` |
The `behaviour` can be one of the following:
- `"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.
- `"all-lines"`: Inline blame is on every line.
- `"cursor-line"`: Inline blame is only on the line of the primary cursor.
- `"hidden"`: Inline blame is not shown.
Inline blame will only show if the blame for the file has already been computed.
The `compute` key determines under which circumstances the blame is computed, and can be one of the following:
- `"on-demand"`: Blame for the file is computed only when explicitly requested, such as when using `space + B` to blame the line of the cursor. There may be a little delay when loading the blame. When opening new files, even with `behaviour` not set to `"hidden"`, the inline blame won't show. It needs to be computed first in order to become available. This computation can be manually triggered by requesting it with `space + B`.
- `"background"`: Blame for the file is loaded in the background. This will have zero effect on performance of the Editor, but will use a little bit extra resources. Directly requesting the blame with `space + B` will be instant. Inline blame will show as soon as the blame is available when loading new files.
`inline-blame-format` allows customization of the blame message, and can be set to any string. Variables can be used like so: `{variable}`. These are the available variables:

View file

@ -3480,8 +3480,9 @@ pub(crate) fn blame_line_impl(editor: &mut Editor, doc_id: DocumentId, cursor_li
let line_blame = match doc.line_blame(cursor_line, &inline_blame_config.format) {
result
if (result.is_ok() && doc.is_blame_potentially_out_of_date)
|| matches!(result, Err(LineBlameError::NotReadyYet) if inline_blame_config.behaviour
== helix_view::editor::InlineBlameBehaviour::Disabled) =>
|| matches!(result, Err(LineBlameError::NotReadyYet) if inline_blame_config.compute
== helix_view::editor::InlineBlameCompute::OnDemand
) =>
{
if let Some(path) = doc.path() {
let tx = editor.handlers.blame.clone();

View file

@ -1327,7 +1327,7 @@ fn reload(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyh
}
let scrolloff = cx.editor.config().scrolloff;
let inline_blame_behaviour = cx.editor.config().inline_blame.behaviour;
let inline_compute = cx.editor.config().inline_blame.compute;
let (view, doc) = current!(cx.editor);
doc.reload(view, &cx.editor.diff_providers).map(|_| {
view.ensure_cursor_in_view(doc, scrolloff);
@ -1340,7 +1340,7 @@ fn reload(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyh
.file_changed(path.clone());
}
if doc.should_request_full_file_blame(inline_blame_behaviour) {
if doc.should_request_full_file_blame(inline_compute) {
if let Some(path) = doc.path() {
helix_event::send_blocking(
&cx.editor.handlers.blame,
@ -1380,7 +1380,7 @@ fn reload_all(cx: &mut compositor::Context, _args: Args, event: PromptEvent) ->
})
.collect();
let blame_behaviour = cx.editor.config().inline_blame.behaviour;
let blame_compute = cx.editor.config().inline_blame.compute;
for (doc_id, view_ids) in docs_view_ids {
let doc = doc_mut!(cx.editor, &doc_id);
@ -1410,7 +1410,7 @@ fn reload_all(cx: &mut compositor::Context, _args: Args, event: PromptEvent) ->
}
}
if doc.should_request_full_file_blame(blame_behaviour) {
if doc.should_request_full_file_blame(blame_compute) {
if let Some(path) = doc.path() {
helix_event::send_blocking(
&cx.editor.handlers.blame,

View file

@ -3,7 +3,7 @@ use std::{mem, time::Duration};
use helix_event::register_hook;
use helix_vcs::FileBlame;
use helix_view::{
editor::InlineBlameBehaviour,
editor::InlineBlameCompute,
events::{DocumentDidOpen, EditorConfigDidChange},
handlers::{BlameEvent, Handlers},
DocumentId,
@ -44,7 +44,7 @@ impl helix_event::AsyncHook for BlameHandler {
return;
};
doc.file_blame = Some(result);
if editor.config().inline_blame.behaviour == InlineBlameBehaviour::Disabled {
if editor.config().inline_blame.compute == InlineBlameCompute::OnDemand {
if let Some(line) = line_blame {
crate::commands::blame_line_impl(editor, doc_id, line);
} else {
@ -61,7 +61,7 @@ impl helix_event::AsyncHook for BlameHandler {
pub(super) fn register_hooks(handlers: &Handlers) {
let tx = handlers.blame.clone();
register_hook!(move |event: &mut DocumentDidOpen<'_>| {
if event.editor.config().inline_blame.behaviour != InlineBlameBehaviour::Disabled {
if event.editor.config().inline_blame.compute != InlineBlameCompute::OnDemand {
helix_event::send_blocking(
&tx,
BlameEvent {
@ -75,9 +75,9 @@ pub(super) fn register_hooks(handlers: &Handlers) {
});
let tx = handlers.blame.clone();
register_hook!(move |event: &mut EditorConfigDidChange<'_>| {
let has_enabled_inline_blame = event.old_config.inline_blame.behaviour
== InlineBlameBehaviour::Disabled
&& event.editor.config().inline_blame.behaviour != InlineBlameBehaviour::Disabled;
let has_enabled_inline_blame = event.old_config.inline_blame.compute
== InlineBlameCompute::OnDemand
&& event.editor.config().inline_blame.compute == InlineBlameCompute::Background;
if has_enabled_inline_blame {
// request blame for all documents, since any of them could have

View file

@ -42,7 +42,7 @@ use helix_core::{
ChangeSet, Diagnostic, LineEnding, Range, Rope, RopeBuilder, Selection, Syntax, Transaction,
};
use crate::editor::InlineBlameBehaviour;
use crate::editor::InlineBlameCompute;
use crate::{
editor::Config,
events::{DocumentDidChange, SelectionDidChange},
@ -741,11 +741,8 @@ impl Document {
}
}
pub fn should_request_full_file_blame(
&mut self,
blame_behaviour: InlineBlameBehaviour,
) -> bool {
if blame_behaviour == InlineBlameBehaviour::Disabled {
pub fn should_request_full_file_blame(&mut self, blame_fetch: InlineBlameCompute) -> bool {
if blame_fetch == InlineBlameCompute::OnDemand {
self.is_blame_potentially_out_of_date
} else {
true

View file

@ -175,30 +175,32 @@ impl Default for GutterLineNumbersConfig {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum InlineBlameBehaviour {
/// Do not show inline blame
///
/// Loads blame for the file in the background when the document is
/// opened and request it again when it is `:reload`ed.
///
/// This allows instantaneous access to line blame with `space + B` and when
/// `:toggle inline-blame.enable` but for the cost of consuming more
/// resources in the background
Background,
/// Do not show inline blame, and do not request it in the background
///
/// When manually requesting the inline blame, it may take several seconds to appear.
Disabled,
Hidden,
/// Show the inline blame on the cursor line
CursorLine,
/// Show the inline blame on every other line
AllLines,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum InlineBlameCompute {
/// Inline blame for a file will be fetched when a document is opened or reloaded, for example
Background,
/// Inline blame for a file will be fetched when explicitly requested, e.g. when using `space + B`
OnDemand,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct InlineBlameConfig {
/// Show inline blame for a line when cursor is on that line
/// How to show the inline blame
pub behaviour: InlineBlameBehaviour,
/// Whether the inline blame should be fetched in the background
pub compute: InlineBlameCompute,
/// How the inline blame should look like and the information it includes
pub format: String,
}
@ -206,8 +208,9 @@ pub struct InlineBlameConfig {
impl Default for InlineBlameConfig {
fn default() -> Self {
Self {
behaviour: InlineBlameBehaviour::Disabled,
behaviour: InlineBlameBehaviour::Hidden,
format: "{author}, {time-ago} • {message} • {commit}".to_owned(),
compute: InlineBlameCompute::OnDemand,
}
}
}