From f0535ef824328cdc06bcd52205d456a5abb1234e Mon Sep 17 00:00:00 2001 From: sxyazi Date: Wed, 27 Dec 2023 23:29:39 +0800 Subject: [PATCH] fix: panic caused by `set_hook` --- yazi-adaptor/src/adaptor.rs | 2 +- yazi-fm/src/app/app.rs | 56 +++--------------------------- yazi-fm/src/app/commands/mod.rs | 1 + yazi-fm/src/app/commands/render.rs | 51 +++++++++++++++++++++++++++ yazi-fm/src/app/commands/stop.rs | 5 +-- yazi-fm/src/help/layout.rs | 2 +- yazi-fm/src/input/input.rs | 2 +- yazi-fm/src/select/select.rs | 2 +- yazi-fm/src/tasks/layout.rs | 2 +- yazi-fm/src/which/layout.rs | 2 +- yazi-plugin/src/isolate/peek.rs | 15 ++++---- 11 files changed, 74 insertions(+), 66 deletions(-) create mode 100644 yazi-fm/src/app/commands/render.rs diff --git a/yazi-adaptor/src/adaptor.rs b/yazi-adaptor/src/adaptor.rs index 1d721641..05fe017f 100644 --- a/yazi-adaptor/src/adaptor.rs +++ b/yazi-adaptor/src/adaptor.rs @@ -1,4 +1,4 @@ -use std::{env, path::Path, sync::{atomic::Ordering, Arc}}; +use std::{env, path::Path, sync::Arc}; use anyhow::{anyhow, Result}; use ratatui::prelude::Rect; diff --git a/yazi-fm/src/app/app.rs b/yazi-fm/src/app/app.rs index 113076bf..bb1ca4c3 100644 --- a/yazi-fm/src/app/app.rs +++ b/yazi-fm/src/app/app.rs @@ -1,13 +1,10 @@ -use std::sync::atomic::Ordering; - use anyhow::{Ok, Result}; use crossterm::event::KeyEvent; -use ratatui::backend::Backend; use yazi_config::{keymap::Key, ARGS}; use yazi_core::input::InputMode; -use yazi_shared::{emit, event::{Event, Exec}, term::Term, Layer, COLLISION}; +use yazi_shared::{emit, event::{Event, Exec}, term::Term, Layer}; -use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Root, Signals}; +use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Signals}; pub(crate) struct App { pub(crate) cx: Ctx, @@ -26,7 +23,7 @@ impl App { Lives::register()?; let mut app = Self { cx: Ctx::make(), term: Some(term), signals }; - app.dispatch_render()?; + app.render()?; while let Some(event) = app.signals.recv().await { match event { Event::Quit(no_cwd_file) => { @@ -35,7 +32,7 @@ impl App { } Event::Key(key) => app.dispatch_key(key), Event::Paste(str) => app.dispatch_paste(str), - Event::Render(_) => app.dispatch_render()?, + Event::Render(_) => app.render()?, Event::Resize(cols, rows) => app.dispatch_resize(cols, rows)?, Event::Call(exec, layer) => app.dispatch_call(exec, layer), event => app.dispatch_module(event), @@ -68,51 +65,9 @@ impl App { } } - fn dispatch_render(&mut self) -> Result<()> { - let Some(term) = &mut self.term else { - return Ok(()); - }; - - let collision = COLLISION.swap(false, Ordering::Relaxed); - let frame = term.draw(|f| { - Lives::scope(&self.cx, |_| { - f.render_widget(Root::new(&self.cx), f.size()); - }); - - if let Some((x, y)) = self.cx.cursor() { - f.set_cursor(x, y); - } - })?; - if !COLLISION.load(Ordering::Relaxed) { - if collision { - // Reload preview if collision is resolved - self.cx.manager.peek(true); - } - return Ok(()); - } - - let mut patches = Vec::new(); - for x in frame.area.left()..frame.area.right() { - for y in frame.area.top()..frame.area.bottom() { - let cell = frame.buffer.get(x, y); - if cell.skip { - patches.push((x, y, cell.clone())); - } - } - } - - term.backend_mut().draw(patches.iter().map(|(x, y, cell)| (*x, *y, cell)))?; - if let Some((x, y)) = self.cx.cursor() { - term.show_cursor()?; - term.set_cursor(x, y)?; - } - term.backend_mut().flush()?; - Ok(()) - } - fn dispatch_resize(&mut self, _: u16, _: u16) -> Result<()> { self.cx.manager.active_mut().preview.reset(); - self.dispatch_render()?; + self.render()?; self.cx.manager.current_mut().set_page(true); self.cx.manager.peek(false); @@ -127,7 +82,6 @@ impl App { } fn dispatch_module(&mut self, event: Event) { - let manager = &mut self.cx.manager; let tasks = &mut self.cx.tasks; match event { Event::Pages(page) => { diff --git a/yazi-fm/src/app/commands/mod.rs b/yazi-fm/src/app/commands/mod.rs index 4fddf53d..c12ef5df 100644 --- a/yazi-fm/src/app/commands/mod.rs +++ b/yazi-fm/src/app/commands/mod.rs @@ -1,2 +1,3 @@ mod plugin; +mod render; mod stop; diff --git a/yazi-fm/src/app/commands/render.rs b/yazi-fm/src/app/commands/render.rs new file mode 100644 index 00000000..02729eba --- /dev/null +++ b/yazi-fm/src/app/commands/render.rs @@ -0,0 +1,51 @@ +use std::sync::atomic::Ordering; + +use anyhow::Result; +use ratatui::backend::Backend; +use yazi_shared::COLLISION; + +use crate::{app::App, lives::Lives, root::Root}; + +impl App { + pub(crate) fn render(&mut self) -> Result<()> { + let Some(term) = &mut self.term else { + return Ok(()); + }; + + let collision = COLLISION.swap(false, Ordering::Relaxed); + let frame = term.draw(|f| { + Lives::scope(&self.cx, |_| { + f.render_widget(Root::new(&self.cx), f.size()); + }); + + if let Some((x, y)) = self.cx.cursor() { + f.set_cursor(x, y); + } + })?; + if !COLLISION.load(Ordering::Relaxed) { + if collision { + // Reload preview if collision is resolved + self.cx.manager.peek(true); + } + return Ok(()); + } + + let mut patches = Vec::new(); + for x in frame.area.left()..frame.area.right() { + for y in frame.area.top()..frame.area.bottom() { + let cell = frame.buffer.get(x, y); + if cell.skip { + patches.push((x, y, cell.clone())); + } + } + } + + term.backend_mut().draw(patches.iter().map(|(x, y, cell)| (*x, *y, cell)))?; + if let Some((x, y)) = self.cx.cursor() { + term.show_cursor()?; + term.set_cursor(x, y)?; + } + term.backend_mut().flush()?; + Ok(()) + } +} diff --git a/yazi-fm/src/app/commands/stop.rs b/yazi-fm/src/app/commands/stop.rs index e5c92bd8..dd78f85e 100644 --- a/yazi-fm/src/app/commands/stop.rs +++ b/yazi-fm/src/app/commands/stop.rs @@ -1,6 +1,6 @@ use anyhow::Result; use tokio::sync::oneshot; -use yazi_shared::{emit, event::Exec, term::Term}; +use yazi_shared::{event::Exec, term::Term}; use crate::app::App; @@ -30,9 +30,10 @@ impl App { } else { self.term = Some(Term::start().unwrap()); self.signals.stop_term(false); + // FIXME: find a better way to handle this + self.render().unwrap(); self.cx.manager.hover(None); self.cx.manager.peek(true); - emit!(Render); } if let Some(tx) = opt.tx { tx.send(()).ok(); diff --git a/yazi-fm/src/help/layout.rs b/yazi-fm/src/help/layout.rs index a34d054f..b52f0208 100644 --- a/yazi-fm/src/help/layout.rs +++ b/yazi-fm/src/help/layout.rs @@ -2,7 +2,7 @@ use ratatui::{buffer::Buffer, layout::{self, Rect}, prelude::{Constraint, Direct use yazi_config::THEME; use super::Bindings; -use crate::{Ctx, widgets}; +use crate::{widgets, Ctx}; pub(crate) struct Layout<'a> { cx: &'a Ctx, diff --git a/yazi-fm/src/input/input.rs b/yazi-fm/src/input/input.rs index 7e551bdb..bfe93743 100644 --- a/yazi-fm/src/input/input.rs +++ b/yazi-fm/src/input/input.rs @@ -6,7 +6,7 @@ use yazi_config::THEME; use yazi_core::input::InputMode; use yazi_shared::term::Term; -use crate::{Ctx, widgets}; +use crate::{widgets, Ctx}; pub(crate) struct Input<'a> { cx: &'a Ctx, diff --git a/yazi-fm/src/select/select.rs b/yazi-fm/src/select/select.rs index 19983d0f..a15e633d 100644 --- a/yazi-fm/src/select/select.rs +++ b/yazi-fm/src/select/select.rs @@ -1,7 +1,7 @@ use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, Borders, List, ListItem, Widget}}; use yazi_config::THEME; -use crate::{Ctx, widgets}; +use crate::{widgets, Ctx}; pub(crate) struct Select<'a> { cx: &'a Ctx, diff --git a/yazi-fm/src/tasks/layout.rs b/yazi-fm/src/tasks/layout.rs index 82e68ee7..14b39885 100644 --- a/yazi-fm/src/tasks/layout.rs +++ b/yazi-fm/src/tasks/layout.rs @@ -2,7 +2,7 @@ use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, R use yazi_config::THEME; use yazi_core::tasks::TASKS_PERCENT; -use crate::{Ctx, widgets}; +use crate::{widgets, Ctx}; pub(crate) struct Layout<'a> { cx: &'a Ctx, diff --git a/yazi-fm/src/which/layout.rs b/yazi-fm/src/which/layout.rs index 14a20687..b3aa4b9e 100644 --- a/yazi-fm/src/which/layout.rs +++ b/yazi-fm/src/which/layout.rs @@ -2,7 +2,7 @@ use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, widgets::{ use yazi_config::THEME; use super::Side; -use crate::{Ctx, widgets}; +use crate::{widgets, Ctx}; pub(crate) struct Which<'a> { cx: &'a Ctx, diff --git a/yazi-plugin/src/isolate/peek.rs b/yazi-plugin/src/isolate/peek.rs index c87bf4be..b1d8ef55 100644 --- a/yazi-plugin/src/isolate/peek.rs +++ b/yazi-plugin/src/isolate/peek.rs @@ -12,18 +12,19 @@ pub fn peek(exec: &Exec, file: yazi_shared::fs::File, skip: usize) -> Cancellati let ct = CancellationToken::new(); let cmd = exec.cmd.to_owned(); - let (ct1, ct2) = (ct.clone(), ct.clone()); + let ct2 = ct.clone(); tokio::task::spawn_blocking(move || { let future = async { LOADED.ensure(&cmd).await.into_lua_err()?; let lua = slim_lua()?; - lua.set_hook( - HookTriggers::new().on_calls().on_returns().every_nth_instruction(2000), - move |_, _| { - if ct1.is_cancelled() { Err("cancelled".into_lua_err()) } else { Ok(()) } - }, - ); + // FIXME: this will cause a panic + // lua.set_hook( + // HookTriggers::new().on_calls().on_returns().every_nth_instruction(2000), + // move |_, _| { + // if ct1.is_cancelled() { Err("cancelled".into_lua_err()) } else { Ok(()) } + // }, + // ); let plugin: Table = if let Some(b) = LOADED.read().get(&cmd) { lua.load(b).call(())?