refactor: centralize editor plugin lifecycle ownership

This commit is contained in:
Valdemar Lorenzen
2026-10-05 14:22:32 +02:00
parent 396ffc4f3a
commit 73b15f5134
6 changed files with 402 additions and 75 deletions
+13 -14
View File
@@ -20,7 +20,10 @@ use ratatui::{
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
use crate::editor::{Editor, Effect, Input, Invocation, Mode};
use crate::{
editor::{Editor, Effect, Input, Mode},
session::EditorSession,
};
pub const CAPABILITIES: &[&str] = &["text", "styled_text"];
const TAB_WIDTH: usize = 4;
@@ -52,9 +55,9 @@ impl Drop for TerminalSession {
}
}
/// The frontend only translates input and renders backend state.
/// Plugin dispatch is supplied by the executable, not the terminal adapter.
pub fn run(editor: &mut Editor, mut invoke: impl FnMut(&mut Editor, Invocation)) -> io::Result<()> {
/// Renders session state and translates terminal input; the session owns plugin
/// execution and retirement, so the adapter needs no lifecycle callback.
pub fn run(session: &mut EditorSession) -> io::Result<()> {
let previous_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
restore_terminal();
@@ -64,21 +67,17 @@ pub fn run(editor: &mut Editor, mut invoke: impl FnMut(&mut Editor, Invocation))
let mut terminal: Terminal<CrosstermBackend<Stdout>> =
Terminal::new(CrosstermBackend::new(io::stdout()))?;
let (mut top, mut left) = (0, 0);
while !editor.should_quit() {
terminal.draw(|frame| draw(frame, editor, &mut top, &mut left))?;
while !session.editor().should_quit() {
terminal.draw(|frame| draw(frame, session.editor(), &mut top, &mut left))?;
match event::read()? {
Event::Key(key) if key.kind != KeyEventKind::Release => {
if let Some(input) = translate(key)
&& let Some(invocation) = editor.handle(input)
{
invoke(editor, invocation);
if let Some(input) = translate(key) {
session.handle(input);
}
}
// Bracketed paste must never execute pasted Ex commands.
Event::Paste(text) if editor.mode() == Mode::Insert => {
if let Err(error) = editor.apply(vec![Effect::Insert(text)]) {
editor.set_message(error);
}
Event::Paste(text) if session.editor().mode() == Mode::Insert => {
session.apply(vec![Effect::Insert(text)]);
}
_ => {}
}