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> { 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. /// Start Zellij with the specified [`OsApi`] and command-line arguments.
// FIXME this should definitely be modularized and split into different functions. // FIXME this should definitely be modularized and split into different functions.
pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) { 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()) .name("screen".to_string())
.spawn({ .spawn({
let mut command_is_executing = command_is_executing.clone(); let mut command_is_executing = command_is_executing.clone();
let os_input = os_input.clone(); let screen_bus = Bus::new(
let send_pty_instructions = send_pty_instructions.clone(); receive_screen_instructions,
let send_plugin_instructions = send_plugin_instructions.clone(); None,
let send_app_instructions = send_app_instructions.clone(); Some(&send_pty_instructions),
Some(&send_plugin_instructions),
Some(&send_app_instructions),
Some(&os_input),
);
let max_panes = opts.max_panes; let max_panes = opts.max_panes;
move || { move || {
let mut screen = Screen::new( let mut screen = Screen::new(
receive_screen_instructions, screen_bus,
send_pty_instructions,
send_plugin_instructions,
send_app_instructions,
&full_screen_ws, &full_screen_ws,
os_input,
max_panes, max_panes,
ModeInfo::default(), ModeInfo::default(),
); );
loop { loop {
let (event, mut err_ctx) = screen let (event, mut err_ctx) = screen
.bus
.receiver .receiver
.recv() .recv()
.expect("failed to receive event on channel"); .expect("failed to receive event on channel");

View file

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