Use Bus type for screen thread

This commit is contained in:
Kyle Sutherland-Cash 2021-05-01 08:26:57 -07:00
parent f01887463f
commit ae6192d698
2 changed files with 58 additions and 43 deletions

View File

@ -119,6 +119,34 @@ pub enum AppInstruction {
}
pub struct Bus<T> {
receiver: mpsc::Receiver<(T, ErrorContext)>,
to_screen: Option<SenderWithContext<ScreenInstruction>>,
to_pty: Option<SenderWithContext<PtyInstruction>>,
to_plugin: Option<SenderWithContext<PluginInstruction>>,
to_app: Option<SenderWithContext<AppInstruction>>,
os_input: Option<Box<dyn OsApi>>,
}
impl<T> Bus<T> {
fn new(
receiver: mpsc::Receiver<(T, ErrorContext)>,
to_screen: Option<&SenderWithContext<ScreenInstruction>>,
to_pty: Option<&SenderWithContext<PtyInstruction>>,
to_plugin: Option<&SenderWithContext<PluginInstruction>>,
to_app: Option<&SenderWithContext<AppInstruction>>,
os_input: Option<&Box<dyn OsApi>>,
) -> Self {
Bus {
receiver,
to_screen: to_screen.cloned(),
to_pty: to_pty.cloned(),
to_plugin: to_plugin.cloned(),
to_app: to_app.cloned(),
os_input: os_input.cloned(),
}
}
}
/// Start Zellij with the specified [`OsApi`] and command-line arguments.
// FIXME this should definitely be modularized and split into different functions.
pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
@ -263,25 +291,26 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.name("screen".to_string())
.spawn({
let mut command_is_executing = command_is_executing.clone();
let os_input = os_input.clone();
let send_pty_instructions = send_pty_instructions.clone();
let send_plugin_instructions = send_plugin_instructions.clone();
let send_app_instructions = send_app_instructions.clone();
let screen_bus = Bus::new(
receive_screen_instructions,
None,
Some(&send_pty_instructions),
Some(&send_plugin_instructions),
Some(&send_app_instructions),
Some(&os_input),
);
let max_panes = opts.max_panes;
move || {
let mut screen = Screen::new(
receive_screen_instructions,
send_pty_instructions,
send_plugin_instructions,
send_app_instructions,
screen_bus,
&full_screen_ws,
os_input,
max_panes,
ModeInfo::default(),
);
loop {
let (event, mut err_ctx) = screen
.bus
.receiver
.recv()
.expect("failed to receive event on channel");

View File

@ -6,6 +6,7 @@ use std::str;
use std::sync::mpsc::Receiver;
use super::{AppInstruction, SenderWithContext};
use crate::common::Bus;
use crate::os_input_output::OsApi;
use crate::panes::PositionAndSize;
use crate::pty_bus::{PtyInstruction, VteBytes};
@ -62,51 +63,33 @@ pub enum ScreenInstruction {
/// A [`Screen`] holds multiple [`Tab`]s, each one holding multiple [`panes`](crate::client::panes).
/// It only directly controls which tab is active, delegating the rest to the individual `Tab`.
pub struct Screen {
/// A [`ScreenInstruction`] and [`ErrorContext`] receiver.
pub receiver: Receiver<(ScreenInstruction, ErrorContext)>,
/// A Bus for sending and receiving messages with the other threads.
pub bus: Bus<ScreenInstruction>,
/// An optional maximal amount of panes allowed per [`Tab`] in this [`Screen`] instance.
max_panes: Option<usize>,
/// A map between this [`Screen`]'s tabs and their ID/key.
tabs: BTreeMap<usize, Tab>,
/// A [`PtyInstruction`] and [`ErrorContext`] sender.
pub send_pty_instructions: SenderWithContext<PtyInstruction>,
/// A [`PluginInstruction`] and [`ErrorContext`] sender.
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
/// An [`AppInstruction`] and [`ErrorContext`] sender.
pub send_app_instructions: SenderWithContext<AppInstruction>,
/// The full size of this [`Screen`].
full_screen_ws: PositionAndSize,
/// The index of this [`Screen`]'s active [`Tab`].
active_tab_index: Option<usize>,
/// The [`OsApi`] this [`Screen`] uses.
os_api: Box<dyn OsApi>,
mode_info: ModeInfo,
}
impl Screen {
// FIXME: This lint needs actual fixing! Maybe by bundling the Senders
/// Creates and returns a new [`Screen`].
#[allow(clippy::too_many_arguments)]
pub fn new(
receive_screen_instructions: Receiver<(ScreenInstruction, ErrorContext)>,
send_pty_instructions: SenderWithContext<PtyInstruction>,
send_plugin_instructions: SenderWithContext<PluginInstruction>,
send_app_instructions: SenderWithContext<AppInstruction>,
bus: Bus<ScreenInstruction>,
full_screen_ws: &PositionAndSize,
os_api: Box<dyn OsApi>,
max_panes: Option<usize>,
mode_info: ModeInfo,
) -> Self {
Screen {
receiver: receive_screen_instructions,
bus,
max_panes,
send_pty_instructions,
send_plugin_instructions,
send_app_instructions,
full_screen_ws: *full_screen_ws,
active_tab_index: None,
tabs: BTreeMap::new(),
os_api,
mode_info,
}
}
@ -121,10 +104,10 @@ impl Screen {
position,
String::new(),
&self.full_screen_ws,
self.os_api.clone(),
self.send_pty_instructions.clone(),
self.send_plugin_instructions.clone(),
self.send_app_instructions.clone(),
self.bus.os_input.as_ref().unwrap().clone(),
self.bus.to_pty.as_ref().unwrap().clone(),
self.bus.to_plugin.as_ref().unwrap().clone(),
self.bus.to_app.as_ref().unwrap().clone(),
self.max_panes,
Some(PaneId::Terminal(pane_id)),
self.mode_info.clone(),
@ -207,11 +190,14 @@ impl Screen {
// because this might be happening when the app is closing, at which point the pty thread
// has already closed and this would result in an error
let _ = self
.send_pty_instructions
.bus
.to_pty
.as_ref()
.unwrap()
.send(PtyInstruction::CloseTab(pane_ids));
if self.tabs.is_empty() {
self.active_tab_index = None;
self.send_app_instructions
self.bus.to_app.as_ref().unwrap()
.send(AppInstruction::Exit)
.unwrap();
} else {
@ -225,7 +211,7 @@ impl Screen {
}
pub fn resize_to_screen(&mut self) {
let new_screen_size = self.os_api.get_terminal_size_using_fd(0);
let new_screen_size = self.bus.os_input.as_ref().unwrap().get_terminal_size_using_fd(0);
self.full_screen_ws = new_screen_size;
for (_, tab) in self.tabs.iter_mut() {
tab.resize_whole_tab(new_screen_size);
@ -276,10 +262,10 @@ impl Screen {
position,
String::new(),
&self.full_screen_ws,
self.os_api.clone(),
self.send_pty_instructions.clone(),
self.send_plugin_instructions.clone(),
self.send_app_instructions.clone(),
self.bus.os_input.as_ref().unwrap().clone(),
self.bus.to_pty.as_ref().unwrap().clone(),
self.bus.to_plugin.as_ref().unwrap().clone(),
self.bus.to_app.as_ref().unwrap().clone(),
self.max_panes,
None,
self.mode_info.clone(),
@ -301,7 +287,7 @@ impl Screen {
is_sync_panes_active: tab.is_sync_panes_active(),
});
}
self.send_plugin_instructions
self.bus.to_plugin.as_ref().unwrap()
.send(PluginInstruction::Update(None, Event::TabUpdate(tab_data)))
.unwrap();
}