adding hooks

pull/8675/merge^2
Matt Paras 2025-01-27 21:42:39 -08:00
parent 72949830ee
commit 374389e9d1
4 changed files with 179 additions and 44 deletions

View File

@ -17,7 +17,7 @@ use helix_view::{
GutterConfig, IndentGuidesConfig, LineEndingConfig, LineNumber, LspConfig, SearchConfig,
SmartTabConfig, StatusLineConfig, TerminalConfig, WhitespaceConfig,
},
events::{DocumentFocusLost, SelectionDidChange},
events::{DocumentFocusLost, DocumentOpened, SelectionDidChange},
extension::document_id_to_usize,
input::KeyEvent,
theme::Color,
@ -590,6 +590,22 @@ fn load_configuration_api(engine: &mut Engine, generate_sources: bool) {
module.register_fn("get-config-option-value", get_option_value);
module.register_fn("set-configuration-for-file!", set_configuration_for_file);
module
.register_fn(
"get-language-config",
HelixConfiguration::get_language_config,
)
.register_fn(
"get-language-config-by-filename",
HelixConfiguration::get_individual_language_config_for_filename,
)
.register_fn(
"set-language-config!",
HelixConfiguration::update_individual_language_config,
);
module
.register_fn("raw-file-picker", || FilePickerConfig::default())
.register_fn("register-file-picker", HelixConfiguration::file_picker)
@ -713,6 +729,14 @@ fn load_configuration_api(engine: &mut Engine, generate_sources: bool) {
"#,
));
builtin_configuration_module.push_str(&format!(
r#"
(provide set-configuration-for-file!)
(define (set-configuration-for-file! path config)
(helix.set-configuration-for-file! *helix.cx* path config))
"#,
));
// Register the get keybindings function
builtin_configuration_module.push_str(&format!(
r#"
@ -847,6 +871,10 @@ fn load_configuration_api(engine: &mut Engine, generate_sources: bool) {
"keybindings",
"inline-diagnostics-cursor-line-enable",
"inline-diagnostics-end-of-line-enable",
// language configuration functions
"get-language-config",
"get-language-config-by-filename",
"set-language-config!",
];
for func in functions {
@ -1449,26 +1477,60 @@ impl IndividualLanguageConfiguration {
// Apply end of line configuration on doc open?
// pub fn set_end_of_line(&mut self) {
// self.
// self.config.end
// }
}
impl Custom for HelixConfiguration {}
// impl Custom for LineNumber {}
// Set the configuration for an individual file.
fn update_configuration_for_file(ctx: &mut Context, doc: DocumentId) {
if let Some(document) = ctx.editor.documents.get_mut(&doc) {
let path = document.path().unwrap();
let config_for_file = ctx
.editor
.syn_loader
.load()
.language_config_for_file_name(path);
document.language = config_for_file;
}
}
fn set_configuration_for_file(
ctx: &mut Context,
file_name: SteelString,
configuration: IndividualLanguageConfiguration,
) {
if let Some(document) = ctx.editor.document_by_path_mut(file_name.as_str()) {
document.language = Some(Arc::new(configuration.config));
}
}
impl HelixConfiguration {
fn store_language_configuration(&self, language_config: syntax::Loader) {
self.language_configuration.store(Arc::new(language_config))
}
fn get_individual_language_config_for_filename(
fn get_language_config(
&self,
file_name: &str,
language: SteelString,
) -> Option<IndividualLanguageConfiguration> {
self.language_configuration
.load()
.language_config_for_file_name(std::path::Path::new(file_name))
.language_config_for_language_id(language.as_str())
.map(|config| IndividualLanguageConfiguration {
config: (*config).clone(),
})
}
fn get_individual_language_config_for_filename(
&self,
file_name: SteelString,
) -> Option<IndividualLanguageConfiguration> {
self.language_configuration
.load()
.language_config_for_file_name(std::path::Path::new(file_name.as_str()))
.map(|config| IndividualLanguageConfiguration {
config: (*config).clone(),
})
@ -1495,6 +1557,11 @@ impl HelixConfiguration {
}
}
// // Refresh configuration for a specific file
// fn refresh_language_configuration(&mut self) {
// todo!()
// }
fn load_config(&self) -> Config {
(*self.configuration.load().clone()).clone()
}
@ -2040,6 +2107,7 @@ fn register_hook(event_kind: String, callback_fn: SteelVal) -> steel::UnRecovera
// and act accordingly?
register_hook!(move |event: &mut DocumentFocusLost<'_>| {
let cloned_func = rooted.value().clone();
let doc_id = event.doc;
let callback = move |editor: &mut Editor,
_compositor: &mut Compositor,
@ -2058,8 +2126,13 @@ fn register_hook(event_kind: String, callback_fn: SteelVal) -> steel::UnRecovera
.consume(move |engine, args| {
let context = args[0].clone();
engine.update_value("*helix.cx*", context);
let mut args = [doc_id.into_steelval().unwrap()];
// TODO: Do something with this error!
engine.call_function_with_args(cloned_func.clone(), Vec::new())
engine.call_function_with_args_from_mut_slice(
cloned_func.clone(),
&mut args,
)
})
{
present_error_inside_engine_context(&mut ctx, guard, e);
@ -2079,34 +2152,83 @@ fn register_hook(event_kind: String, callback_fn: SteelVal) -> steel::UnRecovera
// is probably the most helpful so that way we can look the document up
// and act accordingly?
register_hook!(move |event: &mut SelectionDidChange<'_>| {
// let cloned_func = rooted.value().clone();
let cloned_func = rooted.value().clone();
let view_id = event.view;
// let callback = move |editor: &mut Editor,
// _compositor: &mut Compositor,
// jobs: &mut job::Jobs| {
// let mut ctx = Context {
// register: None,
// count: None,
// editor,
// callback: Vec::new(),
// on_next_key_callback: None,
// jobs,
// };
// enter_engine(|guard| {
// if let Err(e) = guard
// .with_mut_reference::<Context, Context>(&mut ctx)
// .consume(move |engine, args| {
// let context = args[0].clone();
// engine.update_value("*helix.cx*", context);
// // TODO: Do something with this error!
// engine.call_function_with_args(cloned_func.clone(), Vec::new())
// })
// {
// present_error_inside_engine_context(&mut ctx, guard, e);
// }
// })
// };
// job::dispatch_blocking_jobs(callback);
let callback = move |editor: &mut Editor,
_compositor: &mut Compositor,
jobs: &mut job::Jobs| {
let mut ctx = Context {
register: None,
count: None,
editor,
callback: Vec::new(),
on_next_key_callback: None,
jobs,
};
enter_engine(|guard| {
if let Err(e) = guard
.with_mut_reference::<Context, Context>(&mut ctx)
.consume(move |engine, args| {
let context = args[0].clone();
engine.update_value("*helix.cx*", context);
// TODO: Reuse this allocation
let mut args = [view_id.into_steelval().unwrap()];
engine.call_function_with_args_from_mut_slice(
cloned_func.clone(),
&mut args,
)
})
{
present_error_inside_engine_context(&mut ctx, guard, e);
}
})
};
job::dispatch_blocking_jobs(callback);
Ok(())
});
Ok(SteelVal::Void).into()
}
"document-opened" => {
// TODO: Share this code with the above since most of it is
// exactly the same
register_hook!(move |event: &mut DocumentOpened<'_>| {
let cloned_func = rooted.value().clone();
let doc_id = event.doc;
let callback = move |editor: &mut Editor,
_compositor: &mut Compositor,
jobs: &mut job::Jobs| {
let mut ctx = Context {
register: None,
count: None,
editor,
callback: Vec::new(),
on_next_key_callback: None,
jobs,
};
enter_engine(|guard| {
if let Err(e) = guard
.with_mut_reference::<Context, Context>(&mut ctx)
.consume(move |engine, args| {
let context = args[0].clone();
engine.update_value("*helix.cx*", context);
// TODO: Reuse this allocation if possible
let mut args = [doc_id.into_steelval().unwrap()];
engine.call_function_with_args_from_mut_slice(
cloned_func.clone(),
&mut args,
)
})
{
present_error_inside_engine_context(&mut ctx, guard, e);
}
})
};
job::dispatch_blocking_jobs(callback);
Ok(())
});
@ -2114,13 +2236,6 @@ fn register_hook(event_kind: String, callback_fn: SteelVal) -> steel::UnRecovera
Ok(SteelVal::Void).into()
}
// Unimplemented!
// "document-did-change" => {
// todo!()
// }
// "selection-did-change" => {
// todo!()
// }
_ => steelerr!(Generic => "Unable to register hook: Unknown event type: {}", event_kind)
.into(),
}

View File

@ -1,7 +1,7 @@
use helix_event::{events, register_event};
use helix_view::document::Mode;
use helix_view::events::{
DiagnosticsDidChange, DocumentDidChange, DocumentFocusLost, SelectionDidChange,
DiagnosticsDidChange, DocumentDidChange, DocumentFocusLost, DocumentOpened, SelectionDidChange,
};
use crate::commands;
@ -21,4 +21,5 @@ pub fn register() {
register_event::<DocumentFocusLost>();
register_event::<SelectionDidChange>();
register_event::<DiagnosticsDidChange>();
register_event::<DocumentOpened>();
}

View File

@ -2,9 +2,10 @@ use crate::{
annotations::diagnostics::{DiagnosticFilter, InlineDiagnosticsConfig},
clipboard::ClipboardProvider,
document::{
DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint,
DocumentOpenError, DocumentSavedEvent, DocumentSavedEventFuture, DocumentSavedEventResult,
Mode, SavePoint,
},
events::DocumentFocusLost,
events::{DocumentClosed, DocumentFocusLost, DocumentOpened, DocumentSaved},
graphics::{CursorKind, Rect},
handlers::Handlers,
info::Info,
@ -1784,6 +1785,11 @@ impl Editor {
let id = self.new_document(doc);
self.launch_language_servers(id);
dispatch(DocumentOpened {
editor: self,
doc: id,
});
id
};
@ -1874,6 +1880,11 @@ impl Editor {
self._refresh();
dispatch(DocumentClosed {
editor: self,
doc: doc_id,
});
Ok(())
}
@ -1911,6 +1922,11 @@ impl Editor {
self.write_count += 1;
dispatch(DocumentSaved {
editor: self,
doc: doc_id,
});
Ok(())
}

View File

@ -15,4 +15,7 @@ events! {
DiagnosticsDidChange<'a> { editor: &'a mut Editor, doc: DocumentId }
// called **after** a document loses focus (but not when its closed)
DocumentFocusLost<'a> { editor: &'a mut Editor, doc: DocumentId }
DocumentOpened<'a> { editor: &'a mut Editor, doc: DocumentId }
DocumentClosed<'a> { editor: &'a mut Editor, doc: DocumentId }
DocumentSaved<'a> { editor: &'a mut Editor, doc: DocumentId }
}