Skip to content

Commit

Permalink
Refactor terminal to not use trait objects
Browse files Browse the repository at this point in the history
  • Loading branch information
melody-rs committed Feb 23, 2024
1 parent b0d6669 commit af8b511
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 36 deletions.
10 changes: 8 additions & 2 deletions crates/term/src/backends/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,17 @@ impl Channel {
}

impl super::Backend for Channel {
fn with_term(&mut self, f: &mut dyn FnMut(&mut Term<EventListener>)) {
fn with_term<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Term<EventListener>) -> T,
{
f(&mut self.term)
}

fn with_event_recv(&mut self, f: &mut dyn FnMut(&mut Receiver<Event>)) {
fn with_event_recv<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Receiver<Event>) -> T,
{
f(&mut self.event_reciever)
}

Expand Down
14 changes: 10 additions & 4 deletions crates/term/src/backends/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use channel::Channel;
pub use process::Process;

#[derive(Clone)]
pub(crate) struct EventListener(Sender<Event>);
pub struct EventListener(Sender<Event>);

impl alacritty_terminal::event::EventListener for EventListener {
fn send_event(&self, event: Event) {
Expand All @@ -41,16 +41,22 @@ impl alacritty_terminal::event::EventListener for EventListener {
}
}

pub(crate) trait Backend {
fn with_term(&mut self, f: &mut dyn FnMut(&mut alacritty_terminal::Term<EventListener>));
pub trait Backend {
fn with_term<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut alacritty_terminal::Term<EventListener>) -> T;

fn with_event_recv(&mut self, f: &mut dyn FnMut(&mut Receiver<Event>));
fn with_event_recv<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Receiver<Event>) -> T;

fn size(&self) -> (usize, usize);

fn resize(&mut self, rows: usize, cols: usize);

fn update(&mut self) {}

fn send(&mut self, _msg: alacritty_terminal::event_loop::Msg) {}

fn kill(&mut self) {}
}
17 changes: 13 additions & 4 deletions crates/term/src/backends/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,17 @@ impl Process {
}

impl super::Backend for Process {
fn with_term(&mut self, f: &mut dyn FnMut(&mut Term<EventListener>)) {
let mut lock = self.term.lock();
f(&mut lock)
fn with_term<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Term<EventListener>) -> T,
{
f(&mut self.term.lock())
}

fn with_event_recv(&mut self, f: &mut dyn FnMut(&mut Receiver<Event>)) {
fn with_event_recv<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Receiver<Event>) -> T,
{
f(&mut self.event_reciever)
}

Expand All @@ -107,6 +112,10 @@ impl super::Backend for Process {
self.term.lock().resize(TermSize::new(cols, rows))
}

fn send(&mut self, msg: alacritty_terminal::event_loop::Msg) {
let _ = self.event_loop_sender.send(msg);
}

fn kill(&mut self) {
let _ = self.event_loop_sender.send(Msg::Shutdown);
}
Expand Down
61 changes: 37 additions & 24 deletions crates/term/src/widget/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,42 @@ use crate::backends::Backend;
mod theme;
pub use theme::Theme;

pub struct Terminal {
// REVIEW should we use generics or trait objects?
backend: Box<dyn Backend>,
pub struct Terminal<T> {
backend: T,
theme: Theme, // TODO convert into shared config (possibly do this in luminol-preferences)
title: String,
}

impl Terminal {
fn new(backend: impl Backend + 'static) -> Self {
pub type ProcessTerminal = Terminal<crate::backends::Process>;
pub type ChannelTerminal = Terminal<crate::backends::Channel>;

impl<T> Terminal<T> {
fn new(backend: T) -> Self {
Self {
backend: Box::new(backend),
backend,
theme: Theme::default(),
title: "Luminol Terminal".to_string(),
}
}
}

impl ProcessTerminal {
pub fn process(options: &alacritty_terminal::tty::Options) -> std::io::Result<Self> {
crate::backends::Process::new(options).map(Self::new)
}
}

impl ChannelTerminal {
pub fn channel(recv: std::sync::mpsc::Receiver<u8>) -> Self {
let backend = crate::backends::Channel::new(recv);
Self::new(backend)
}
}

impl Terminal {
impl<T> Terminal<T>
where
T: Backend,
{
pub fn title(&self) -> String {
self.title.to_string()
}
Expand Down Expand Up @@ -89,13 +98,13 @@ impl Terminal {
}

pub fn erase_scrollback(&mut self) {
self.backend.with_term(&mut |term| {
self.backend.with_term(|term| {
term.grid_mut().clear_history();
});
}

pub fn erase_scrollback_and_viewport(&mut self) {
self.backend.with_term(&mut |term| {
self.backend.with_term(|term| {
term.grid_mut().clear_viewport();
});
}
Expand All @@ -107,7 +116,8 @@ impl Terminal {
pub fn ui(&mut self, ui: &mut egui::Ui) -> color_eyre::Result<()> {
self.backend.update();

self.backend.with_term(&mut |term| {
// TODO cache render jobs
let job = self.backend.with_term(|term| {
let content = term.renderable_content();

let mut job = egui::text::LayoutJob::default();
Expand All @@ -128,23 +138,26 @@ impl Terminal {
job.append("\n", 0.0, Default::default());
}
}
let galley = ui.fonts(|f| f.layout_job(job));
let (response, painter) =
ui.allocate_painter(galley.rect.size(), egui::Sense::click_and_drag());

painter.rect_filled(
galley.rect.translate(response.rect.min.to_vec2()),
0.0,
egui::Color32::from_rgb(40, 39, 39),
);
job
});

painter.galley(response.rect.min, galley, egui::Color32::WHITE);
let galley = ui.fonts(|f| f.layout_job(job));
let (response, painter) =
ui.allocate_painter(galley.rect.size(), egui::Sense::click_and_drag());

if response.hovered() {
ui.output_mut(|o| o.mutable_text_under_cursor = true);
ui.ctx().set_cursor_icon(egui::CursorIcon::Text);
}
});
painter.rect_filled(
galley.rect.translate(response.rect.min.to_vec2()),
0.0,
egui::Color32::from_rgb(40, 39, 39),
);

painter.galley(response.rect.min, galley, egui::Color32::WHITE);

if response.hovered() {
ui.output_mut(|o| o.mutable_text_under_cursor = true);
ui.ctx().set_cursor_icon(egui::CursorIcon::Text);
}

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ui/src/windows/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
// Program grant you additional permission to convey the resulting work.

pub struct Window {
term: luminol_term::widget::Terminal,
term: luminol_term::widget::ProcessTerminal,
}

impl Window {
Expand Down
2 changes: 1 addition & 1 deletion src/app/log_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

pub struct LogWindow {
pub(super) term_shown: bool,
term: luminol_term::widget::Terminal,
term: luminol_term::widget::ChannelTerminal,
save_promise: Option<poll_promise::Promise<luminol_filesystem::Result<()>>>,
}

Expand Down

0 comments on commit af8b511

Please sign in to comment.