From e2cebacf331e4f6c68518ae6e9eaab1b78cdf3a0 Mon Sep 17 00:00:00 2001 From: Nik Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:39:47 +0000 Subject: [PATCH] feat: basic implementation of blocking Blame handler --- helix-term/src/handlers.rs | 4 +++ helix-term/src/handlers/blame.rs | 61 ++++++++++++++++++++++++++++++++ helix-view/src/editor.rs | 16 +++++++++ helix-view/src/handlers.rs | 6 ++++ 4 files changed, 87 insertions(+) create mode 100644 helix-term/src/handlers/blame.rs diff --git a/helix-term/src/handlers.rs b/helix-term/src/handlers.rs index b580e678..6f18d43b 100644 --- a/helix-term/src/handlers.rs +++ b/helix-term/src/handlers.rs @@ -11,6 +11,7 @@ use crate::handlers::signature_help::SignatureHelpHandler; pub use helix_view::handlers::Handlers; mod auto_save; +mod blame; pub mod completion; mod diagnostics; mod signature_help; @@ -22,11 +23,13 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers { let event_tx = completion::CompletionHandler::new(config).spawn(); let signature_hints = SignatureHelpHandler::new().spawn(); let auto_save = AutoSaveHandler::new().spawn(); + let blame = blame::BlameHandler.spawn(); let handlers = Handlers { completions: helix_view::handlers::completion::CompletionHandler::new(event_tx), signature_hints, auto_save, + blame, }; completion::register_hooks(&handlers); @@ -34,5 +37,6 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers { auto_save::register_hooks(&handlers); diagnostics::register_hooks(&handlers); snippet::register_hooks(&handlers); + blame::register_hooks(&handlers); handlers } diff --git a/helix-term/src/handlers/blame.rs b/helix-term/src/handlers/blame.rs new file mode 100644 index 00000000..50f1e842 --- /dev/null +++ b/helix-term/src/handlers/blame.rs @@ -0,0 +1,61 @@ +#![allow(dead_code, unused_variables)] +use helix_event::{register_hook, send_blocking}; +use helix_view::{ + handlers::{BlameEvent, Handlers}, + Editor, +}; + +use crate::{events::PostCommand, job}; + +pub struct BlameHandler; + +impl helix_event::AsyncHook for BlameHandler { + type Event = BlameEvent; + + fn handle_event( + &mut self, + event: Self::Event, + timeout: Option<tokio::time::Instant>, + ) -> Option<tokio::time::Instant> { + self.finish_debounce(); + None + } + + fn finish_debounce(&mut self) { + job::dispatch_blocking(move |editor, _| { + request_git_blame(editor); + }) + } +} + +pub(super) fn register_hooks(handlers: &Handlers) { + let tx = handlers.blame.clone(); + register_hook!(move |event: &mut PostCommand<'_, '_>| { + if event.cx.editor.config().vcs.blame { + send_blocking(&tx, BlameEvent::PostCommand); + } + + Ok(()) + }); +} + +fn request_git_blame(editor: &mut Editor) { + let (view, doc) = current_ref!(editor); + let text = doc.text(); + let selection = doc.selection(view.id); + let Some(file) = doc.path() else { + return; + }; + let Ok(cursor_line) = TryInto::<u32>::try_into( + text.char_to_line(selection.primary().cursor(doc.text().slice(..))), + ) else { + return; + }; + + let output = editor.diff_providers.blame_line(file, cursor_line); + + match output { + Ok(blame) => editor.set_status(blame.to_string()), + Err(err) => editor.set_error(err.to_string()), + } +} diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index cdc48a54..7008be51 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -171,6 +171,19 @@ impl Default for GutterLineNumbersConfig { } } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case", default, deny_unknown_fields)] +pub struct VersionControlConfig { + /// Whether to enable git blame + pub blame: bool, +} + +impl Default for VersionControlConfig { + fn default() -> Self { + Self { blame: true } + } +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] pub struct FilePickerConfig { @@ -366,6 +379,8 @@ pub struct Config { pub end_of_line_diagnostics: DiagnosticFilter, // Set to override the default clipboard provider pub clipboard_provider: ClipboardProvider, + /// Version control + pub vcs: VersionControlConfig, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)] @@ -1009,6 +1024,7 @@ impl Default for Config { inline_diagnostics: InlineDiagnosticsConfig::default(), end_of_line_diagnostics: DiagnosticFilter::Disable, clipboard_provider: ClipboardProvider::default(), + vcs: VersionControlConfig::default(), } } } diff --git a/helix-view/src/handlers.rs b/helix-view/src/handlers.rs index a26c4ddb..0bc310b6 100644 --- a/helix-view/src/handlers.rs +++ b/helix-view/src/handlers.rs @@ -16,11 +16,17 @@ pub enum AutoSaveEvent { LeftInsertMode, } +#[derive(Debug)] +pub enum BlameEvent { + PostCommand, +} + pub struct Handlers { // only public because most of the actual implementation is in helix-term right now :/ pub completions: CompletionHandler, pub signature_hints: Sender<lsp::SignatureHelpEvent>, pub auto_save: Sender<AutoSaveEvent>, + pub blame: Sender<BlameEvent>, } impl Handlers {