mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-25 10:15:09 +03:00
Don't commit to master like an idiot... :(
This commit is contained in:
parent
2eadcb86a5
commit
69d34c3e09
@ -1,4 +1,4 @@
|
||||
use crate::{common::SenderWithContext, common::pty::VteBytes, tab::Pane, wasm_vm::PluginInstruction};
|
||||
use crate::{common::SenderWithContext, pty_bus::VteBytes, tab::Pane, wasm_vm::PluginInstruction};
|
||||
|
||||
use crate::panes::{PaneId, PositionAndSize};
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::panes::grid::Grid;
|
||||
use crate::panes::terminal_character::{
|
||||
CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER,
|
||||
};
|
||||
use crate::common::pty::VteBytes;
|
||||
use crate::pty_bus::VteBytes;
|
||||
|
||||
#[derive(PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy, Debug)]
|
||||
pub enum PaneId {
|
||||
|
@ -7,7 +7,7 @@ use crate::common::{input::handler::parse_keys, AppInstruction, SenderWithContex
|
||||
use crate::layout::Layout;
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::panes::{PaneId, PositionAndSize, TerminalPane};
|
||||
use crate::common::pty::{PtyInstruction, VteBytes};
|
||||
use crate::pty_bus::{PtyInstruction, VteBytes};
|
||||
use crate::utils::shared::adjust_to_size;
|
||||
use crate::wasm_vm::PluginInstruction;
|
||||
use crate::{boundaries::Boundaries, panes::PluginPane};
|
||||
|
@ -2,7 +2,7 @@
|
||||
//! the instructions that are sent between threads.
|
||||
|
||||
use super::{AppInstruction, ASYNCOPENCALLS, OPENCALLS};
|
||||
use crate::common::pty::PtyInstruction;
|
||||
use crate::pty_bus::PtyInstruction;
|
||||
use crate::screen::ScreenInstruction;
|
||||
|
||||
use std::fmt::{Display, Error, Formatter};
|
||||
|
@ -6,7 +6,7 @@ use crate::common::input::config::Config;
|
||||
use crate::common::{AppInstruction, SenderWithContext, OPENCALLS};
|
||||
use crate::errors::ContextType;
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::common::pty::PtyInstruction;
|
||||
use crate::pty_bus::PtyInstruction;
|
||||
use crate::screen::ScreenInstruction;
|
||||
use crate::wasm_vm::PluginInstruction;
|
||||
use crate::CommandIsExecuting;
|
||||
|
@ -4,7 +4,7 @@ pub mod input;
|
||||
pub mod install;
|
||||
pub mod ipc;
|
||||
pub mod os_input_output;
|
||||
pub mod pty;
|
||||
pub mod pty_bus;
|
||||
pub mod screen;
|
||||
pub mod utils;
|
||||
pub mod wasm_vm;
|
||||
@ -36,7 +36,7 @@ use errors::{
|
||||
use input::handler::input_loop;
|
||||
use install::populate_data_dir;
|
||||
use os_input_output::OsApi;
|
||||
use pty::{Pty, PtyInstruction};
|
||||
use pty_bus::{PtyBus, PtyInstruction};
|
||||
use screen::{Screen, ScreenInstruction};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utils::consts::ZELLIJ_IPC_PIPE;
|
||||
@ -118,35 +118,6 @@ pub enum AppInstruction {
|
||||
Error(String),
|
||||
}
|
||||
|
||||
pub struct Bus<T> {
|
||||
receiver: Option<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: Option<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) {
|
||||
@ -172,17 +143,34 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
|
||||
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
||||
os_input.set_raw_mode(0);
|
||||
let (to_screen, from_screen): ChannelWithContext<ScreenInstruction> = mpsc::channel();
|
||||
let to_screen = SenderWithContext::new(SenderType::Sender(to_screen));
|
||||
let (send_screen_instructions, receive_screen_instructions): ChannelWithContext<
|
||||
ScreenInstruction,
|
||||
> = mpsc::channel();
|
||||
let send_screen_instructions =
|
||||
SenderWithContext::new(SenderType::Sender(send_screen_instructions));
|
||||
|
||||
let (to_pty, from_pty): ChannelWithContext<PtyInstruction> = mpsc::channel();
|
||||
let to_pty = SenderWithContext::new(SenderType::Sender(to_pty));
|
||||
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
|
||||
mpsc::channel();
|
||||
let send_pty_instructions = SenderWithContext::new(SenderType::Sender(send_pty_instructions));
|
||||
|
||||
let (to_plugin, from_plugin): ChannelWithContext<PluginInstruction> = mpsc::channel();
|
||||
let to_plugin = SenderWithContext::new(SenderType::Sender(to_plugin));
|
||||
let (send_plugin_instructions, receive_plugin_instructions): ChannelWithContext<
|
||||
PluginInstruction,
|
||||
> = mpsc::channel();
|
||||
let send_plugin_instructions =
|
||||
SenderWithContext::new(SenderType::Sender(send_plugin_instructions));
|
||||
|
||||
let (to_app, from_app): SyncChannelWithContext<AppInstruction> = mpsc::sync_channel(0);
|
||||
let to_app = SenderWithContext::new(SenderType::SyncSender(to_app));
|
||||
let (send_app_instructions, receive_app_instructions): SyncChannelWithContext<AppInstruction> =
|
||||
mpsc::sync_channel(0);
|
||||
let send_app_instructions =
|
||||
SenderWithContext::new(SenderType::SyncSender(send_app_instructions));
|
||||
|
||||
let mut pty_bus = PtyBus::new(
|
||||
receive_pty_instructions,
|
||||
send_screen_instructions.clone(),
|
||||
send_plugin_instructions.clone(),
|
||||
os_input.clone(),
|
||||
opts.debug,
|
||||
);
|
||||
|
||||
// Determine and initialize the data directory
|
||||
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
|
||||
@ -204,85 +192,62 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
#[cfg(not(test))]
|
||||
std::panic::set_hook({
|
||||
use crate::errors::handle_panic;
|
||||
let to_app = to_app.clone();
|
||||
let send_app_instructions = send_app_instructions.clone();
|
||||
Box::new(move |info| {
|
||||
handle_panic(info, &to_app);
|
||||
handle_panic(info, &send_app_instructions);
|
||||
})
|
||||
});
|
||||
|
||||
let pty_thread = thread::Builder::new()
|
||||
.name("pty".to_string())
|
||||
.spawn({
|
||||
let mut pty = Pty::new(
|
||||
Bus::new(
|
||||
Some(from_pty),
|
||||
Some(&to_screen),
|
||||
None,
|
||||
Some(&to_plugin),
|
||||
None,
|
||||
Some(&os_input),
|
||||
),
|
||||
opts.debug,
|
||||
);
|
||||
|
||||
let mut command_is_executing = command_is_executing.clone();
|
||||
to_pty.send(PtyInstruction::NewTab).unwrap();
|
||||
send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
|
||||
move || loop {
|
||||
let (event, mut err_ctx) = pty
|
||||
.bus
|
||||
.receiver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let (event, mut err_ctx) = pty_bus
|
||||
.receive_pty_instructions
|
||||
.recv()
|
||||
.expect("failed to receive event on channel");
|
||||
err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
|
||||
match event {
|
||||
PtyInstruction::SpawnTerminal(file_to_open) => {
|
||||
let pid = pty.spawn_terminal(file_to_open);
|
||||
pty.bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let pid = pty_bus.spawn_terminal(file_to_open);
|
||||
pty_bus
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::NewPane(PaneId::Terminal(pid)))
|
||||
.unwrap();
|
||||
}
|
||||
PtyInstruction::SpawnTerminalVertically(file_to_open) => {
|
||||
let pid = pty.spawn_terminal(file_to_open);
|
||||
pty.bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let pid = pty_bus.spawn_terminal(file_to_open);
|
||||
pty_bus
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)))
|
||||
.unwrap();
|
||||
}
|
||||
PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
|
||||
let pid = pty.spawn_terminal(file_to_open);
|
||||
pty.bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let pid = pty_bus.spawn_terminal(file_to_open);
|
||||
pty_bus
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)))
|
||||
.unwrap();
|
||||
}
|
||||
PtyInstruction::NewTab => {
|
||||
if let Some(layout) = maybe_layout.clone() {
|
||||
pty.spawn_terminals_for_layout(layout);
|
||||
pty_bus.spawn_terminals_for_layout(layout);
|
||||
} else {
|
||||
let pid = pty.spawn_terminal(None);
|
||||
pty.bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let pid = pty_bus.spawn_terminal(None);
|
||||
pty_bus
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::NewTab(pid))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
PtyInstruction::ClosePane(id) => {
|
||||
pty.close_pane(id);
|
||||
pty_bus.close_pane(id);
|
||||
command_is_executing.done_closing_pane();
|
||||
}
|
||||
PtyInstruction::CloseTab(ids) => {
|
||||
pty.close_tab(ids);
|
||||
pty_bus.close_tab(ids);
|
||||
command_is_executing.done_closing_pane();
|
||||
}
|
||||
PtyInstruction::Quit => {
|
||||
@ -297,25 +262,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 screen_bus = Bus::new(
|
||||
Some(from_screen),
|
||||
None,
|
||||
Some(&to_pty),
|
||||
Some(&to_plugin),
|
||||
Some(&to_app),
|
||||
Some(&os_input),
|
||||
);
|
||||
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 max_panes = opts.max_panes;
|
||||
|
||||
move || {
|
||||
let mut screen =
|
||||
Screen::new(screen_bus, &full_screen_ws, max_panes, ModeInfo::default());
|
||||
let mut screen = Screen::new(
|
||||
receive_screen_instructions,
|
||||
send_pty_instructions,
|
||||
send_plugin_instructions,
|
||||
send_app_instructions,
|
||||
&full_screen_ws,
|
||||
os_input,
|
||||
max_panes,
|
||||
ModeInfo::default(),
|
||||
);
|
||||
loop {
|
||||
let (event, mut err_ctx) = screen
|
||||
.bus
|
||||
.receiver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.recv()
|
||||
.expect("failed to receive event on channel");
|
||||
err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
|
||||
@ -498,23 +464,16 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
let wasm_thread = thread::Builder::new()
|
||||
.name("wasm".to_string())
|
||||
.spawn({
|
||||
let plugin_bus = Bus::new(
|
||||
Some(from_plugin),
|
||||
Some(&to_screen),
|
||||
Some(&to_pty),
|
||||
Some(&to_plugin),
|
||||
Some(&to_app),
|
||||
None,
|
||||
);
|
||||
let send_pty_instructions = send_pty_instructions.clone();
|
||||
let send_screen_instructions = send_screen_instructions.clone();
|
||||
let send_app_instructions = send_app_instructions.clone();
|
||||
let send_plugin_instructions = send_plugin_instructions.clone();
|
||||
|
||||
let store = Store::default();
|
||||
let mut plugin_id = 0;
|
||||
let mut plugin_map = HashMap::new();
|
||||
move || loop {
|
||||
let (event, mut err_ctx) = plugin_bus
|
||||
.receiver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let (event, mut err_ctx) = receive_plugin_instructions
|
||||
.recv()
|
||||
.expect("failed to receive event on channel");
|
||||
err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
|
||||
@ -550,10 +509,10 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
|
||||
let plugin_env = PluginEnv {
|
||||
plugin_id,
|
||||
to_pty: plugin_bus.to_pty.as_ref().unwrap().clone(),
|
||||
to_screen: plugin_bus.to_screen.as_ref().unwrap().clone(),
|
||||
to_app: plugin_bus.to_app.as_ref().unwrap().clone(),
|
||||
to_plugin: plugin_bus.to_plugin.as_ref().unwrap().clone(),
|
||||
send_pty_instructions: send_pty_instructions.clone(),
|
||||
send_screen_instructions: send_screen_instructions.clone(),
|
||||
send_app_instructions: send_app_instructions.clone(),
|
||||
send_plugin_instructions: send_plugin_instructions.clone(),
|
||||
wasi_env,
|
||||
subscriptions: Arc::new(Mutex::new(HashSet::new())),
|
||||
};
|
||||
@ -581,13 +540,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
update.call(&[]).unwrap();
|
||||
}
|
||||
}
|
||||
drop(
|
||||
plugin_bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(ScreenInstruction::Render),
|
||||
);
|
||||
drop(send_screen_instructions.send(ScreenInstruction::Render));
|
||||
}
|
||||
PluginInstruction::Render(buf_tx, pid, rows, cols) => {
|
||||
let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
|
||||
@ -611,10 +564,10 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
.name("signal_listener".to_string())
|
||||
.spawn({
|
||||
let os_input = os_input.clone();
|
||||
let to_screen = to_screen.clone();
|
||||
let send_screen_instructions = send_screen_instructions.clone();
|
||||
move || {
|
||||
os_input.receive_sigwinch(Box::new(move || {
|
||||
let _ = to_screen.send(ScreenInstruction::TerminalResize);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::TerminalResize);
|
||||
}));
|
||||
}
|
||||
})
|
||||
@ -628,8 +581,8 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
.name("ipc_server".to_string())
|
||||
.spawn({
|
||||
use std::io::Read;
|
||||
let to_pty = to_pty.clone();
|
||||
let to_screen = to_screen.clone();
|
||||
let send_pty_instructions = send_pty_instructions.clone();
|
||||
let send_screen_instructions = send_screen_instructions.clone();
|
||||
move || {
|
||||
std::fs::remove_file(ZELLIJ_IPC_PIPE).ok();
|
||||
let listener = std::os::unix::net::UnixListener::bind(ZELLIJ_IPC_PIPE)
|
||||
@ -649,22 +602,24 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
match &decoded {
|
||||
ApiCommand::OpenFile(file_name) => {
|
||||
let path = PathBuf::from(file_name);
|
||||
to_pty
|
||||
send_pty_instructions
|
||||
.send(PtyInstruction::SpawnTerminal(Some(path)))
|
||||
.unwrap();
|
||||
}
|
||||
ApiCommand::SplitHorizontally => {
|
||||
to_pty
|
||||
send_pty_instructions
|
||||
.send(PtyInstruction::SpawnTerminalHorizontally(None))
|
||||
.unwrap();
|
||||
}
|
||||
ApiCommand::SplitVertically => {
|
||||
to_pty
|
||||
send_pty_instructions
|
||||
.send(PtyInstruction::SpawnTerminalVertically(None))
|
||||
.unwrap();
|
||||
}
|
||||
ApiCommand::MoveFocus => {
|
||||
to_screen.send(ScreenInstruction::FocusNextPane).unwrap();
|
||||
send_screen_instructions
|
||||
.send(ScreenInstruction::FocusNextPane)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -680,9 +635,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
let _stdin_thread = thread::Builder::new()
|
||||
.name("stdin_handler".to_string())
|
||||
.spawn({
|
||||
let to_screen = to_screen.clone();
|
||||
let to_pty = to_pty.clone();
|
||||
let to_plugin = to_plugin.clone();
|
||||
let send_screen_instructions = send_screen_instructions.clone();
|
||||
let send_pty_instructions = send_pty_instructions.clone();
|
||||
let send_plugin_instructions = send_plugin_instructions.clone();
|
||||
let os_input = os_input.clone();
|
||||
let config = config;
|
||||
move || {
|
||||
@ -690,17 +645,17 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
os_input,
|
||||
config,
|
||||
command_is_executing,
|
||||
to_screen,
|
||||
to_pty,
|
||||
to_plugin,
|
||||
to_app,
|
||||
send_screen_instructions,
|
||||
send_pty_instructions,
|
||||
send_plugin_instructions,
|
||||
send_app_instructions,
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
#[warn(clippy::never_loop)]
|
||||
loop {
|
||||
let (app_instruction, mut err_ctx) = from_app
|
||||
let (app_instruction, mut err_ctx) = receive_app_instructions
|
||||
.recv()
|
||||
.expect("failed to receive app instruction on channel");
|
||||
|
||||
@ -710,11 +665,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
break;
|
||||
}
|
||||
AppInstruction::Error(backtrace) => {
|
||||
let _ = to_screen.send(ScreenInstruction::Quit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
|
||||
let _ = screen_thread.join();
|
||||
let _ = to_pty.send(PtyInstruction::Quit);
|
||||
let _ = send_pty_instructions.send(PtyInstruction::Quit);
|
||||
let _ = pty_thread.join();
|
||||
let _ = to_plugin.send(PluginInstruction::Quit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Quit);
|
||||
let _ = wasm_thread.join();
|
||||
os_input.unset_raw_mode(0);
|
||||
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
|
||||
@ -732,11 +687,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
let _ = to_pty.send(PtyInstruction::Quit);
|
||||
let _ = send_pty_instructions.send(PtyInstruction::Quit);
|
||||
pty_thread.join().unwrap();
|
||||
let _ = to_screen.send(ScreenInstruction::Quit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
|
||||
screen_thread.join().unwrap();
|
||||
let _ = to_plugin.send(PluginInstruction::Quit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Quit);
|
||||
wasm_thread.join().unwrap();
|
||||
|
||||
// cleanup();
|
||||
|
@ -4,6 +4,7 @@ use ::async_std::task::*;
|
||||
use ::std::collections::HashMap;
|
||||
use ::std::os::unix::io::RawFd;
|
||||
use ::std::pin::*;
|
||||
use ::std::sync::mpsc::Receiver;
|
||||
use ::std::time::{Duration, Instant};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -11,8 +12,7 @@ use super::{ScreenInstruction, SenderWithContext};
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::utils::logging::debug_to_file;
|
||||
use crate::{
|
||||
common::Bus,
|
||||
errors::{get_current_ctx, ContextType},
|
||||
errors::{get_current_ctx, ContextType, ErrorContext},
|
||||
panes::PaneId,
|
||||
};
|
||||
use crate::{layout::Layout, wasm_vm::PluginInstruction};
|
||||
@ -77,9 +77,12 @@ pub enum PtyInstruction {
|
||||
Quit,
|
||||
}
|
||||
|
||||
pub struct Pty {
|
||||
pub bus: Bus<PtyInstruction>,
|
||||
pub struct PtyBus {
|
||||
pub send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
|
||||
pub receive_pty_instructions: Receiver<(PtyInstruction, ErrorContext)>,
|
||||
pub id_to_child_pid: HashMap<RawFd, RawFd>,
|
||||
os_input: Box<dyn OsApi>,
|
||||
debug_to_file: bool,
|
||||
task_handles: HashMap<RawFd, JoinHandle<()>>,
|
||||
}
|
||||
@ -153,29 +156,31 @@ fn stream_terminal_bytes(
|
||||
})
|
||||
}
|
||||
|
||||
impl Pty {
|
||||
impl PtyBus {
|
||||
pub fn new(
|
||||
bus: Bus<PtyInstruction>,
|
||||
receive_pty_instructions: Receiver<(PtyInstruction, ErrorContext)>,
|
||||
send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
send_plugin_instructions: SenderWithContext<PluginInstruction>,
|
||||
os_input: Box<dyn OsApi>,
|
||||
debug_to_file: bool,
|
||||
) -> Self {
|
||||
Pty {
|
||||
bus,
|
||||
PtyBus {
|
||||
send_screen_instructions,
|
||||
send_plugin_instructions,
|
||||
receive_pty_instructions,
|
||||
os_input,
|
||||
id_to_child_pid: HashMap::new(),
|
||||
debug_to_file,
|
||||
task_handles: HashMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn spawn_terminal(&mut self, file_to_open: Option<PathBuf>) -> RawFd {
|
||||
let (pid_primary, pid_secondary): (RawFd, RawFd) = self
|
||||
.bus
|
||||
.os_input
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.spawn_terminal(file_to_open);
|
||||
let (pid_primary, pid_secondary): (RawFd, RawFd) =
|
||||
self.os_input.spawn_terminal(file_to_open);
|
||||
let task_handle = stream_terminal_bytes(
|
||||
pid_primary,
|
||||
self.bus.to_screen.as_ref().unwrap().clone(),
|
||||
self.bus.os_input.as_ref().unwrap().clone(),
|
||||
self.send_screen_instructions.clone(),
|
||||
self.os_input.clone(),
|
||||
self.debug_to_file,
|
||||
);
|
||||
self.task_handles.insert(pid_primary, task_handle);
|
||||
@ -186,15 +191,11 @@ impl Pty {
|
||||
let total_panes = layout.total_terminal_panes();
|
||||
let mut new_pane_pids = vec![];
|
||||
for _ in 0..total_panes {
|
||||
let (pid_primary, pid_secondary): (RawFd, RawFd) =
|
||||
self.bus.os_input.as_mut().unwrap().spawn_terminal(None);
|
||||
let (pid_primary, pid_secondary): (RawFd, RawFd) = self.os_input.spawn_terminal(None);
|
||||
self.id_to_child_pid.insert(pid_primary, pid_secondary);
|
||||
new_pane_pids.push(pid_primary);
|
||||
}
|
||||
self.bus
|
||||
.to_screen
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
self.send_screen_instructions
|
||||
.send(ScreenInstruction::ApplyLayout((
|
||||
layout,
|
||||
new_pane_pids.clone(),
|
||||
@ -203,8 +204,8 @@ impl Pty {
|
||||
for id in new_pane_pids {
|
||||
let task_handle = stream_terminal_bytes(
|
||||
id,
|
||||
self.bus.to_screen.as_ref().unwrap().clone(),
|
||||
self.bus.os_input.as_ref().unwrap().clone(),
|
||||
self.send_screen_instructions.clone(),
|
||||
self.os_input.clone(),
|
||||
self.debug_to_file,
|
||||
);
|
||||
self.task_handles.insert(id, task_handle);
|
||||
@ -215,16 +216,13 @@ impl Pty {
|
||||
PaneId::Terminal(id) => {
|
||||
let child_pid = self.id_to_child_pid.remove(&id).unwrap();
|
||||
let handle = self.task_handles.remove(&id).unwrap();
|
||||
self.bus.os_input.as_mut().unwrap().kill(child_pid).unwrap();
|
||||
self.os_input.kill(child_pid).unwrap();
|
||||
task::block_on(async {
|
||||
handle.cancel().await;
|
||||
});
|
||||
}
|
||||
PaneId::Plugin(pid) => drop(
|
||||
self.bus
|
||||
.to_plugin
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
self.send_plugin_instructions
|
||||
.send(PluginInstruction::Unload(pid)),
|
||||
),
|
||||
}
|
||||
@ -236,7 +234,7 @@ impl Pty {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Pty {
|
||||
impl Drop for PtyBus {
|
||||
fn drop(&mut self) {
|
||||
let child_ids: Vec<RawFd> = self.id_to_child_pid.keys().copied().collect();
|
||||
for id in child_ids {
|
@ -3,13 +3,14 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::str;
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
use super::AppInstruction;
|
||||
use crate::common::Bus;
|
||||
use super::{AppInstruction, SenderWithContext};
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::panes::PositionAndSize;
|
||||
use crate::common::pty::{PtyInstruction, VteBytes};
|
||||
use crate::pty_bus::{PtyInstruction, VteBytes};
|
||||
use crate::tab::Tab;
|
||||
use crate::wasm_vm::PluginInstruction;
|
||||
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};
|
||||
use crate::{layout::Layout, panes::PaneId};
|
||||
|
||||
use zellij_tile::data::{Event, ModeInfo, TabInfo};
|
||||
@ -61,33 +62,51 @@ 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 Bus for sending and receiving messages with the other threads.
|
||||
pub bus: Bus<ScreenInstruction>,
|
||||
/// A [`ScreenInstruction`] and [`ErrorContext`] receiver.
|
||||
pub receiver: Receiver<(ScreenInstruction, ErrorContext)>,
|
||||
/// 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(
|
||||
bus: Bus<ScreenInstruction>,
|
||||
receive_screen_instructions: Receiver<(ScreenInstruction, ErrorContext)>,
|
||||
send_pty_instructions: SenderWithContext<PtyInstruction>,
|
||||
send_plugin_instructions: SenderWithContext<PluginInstruction>,
|
||||
send_app_instructions: SenderWithContext<AppInstruction>,
|
||||
full_screen_ws: &PositionAndSize,
|
||||
os_api: Box<dyn OsApi>,
|
||||
max_panes: Option<usize>,
|
||||
mode_info: ModeInfo,
|
||||
) -> Self {
|
||||
Screen {
|
||||
bus,
|
||||
receiver: receive_screen_instructions,
|
||||
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,
|
||||
}
|
||||
}
|
||||
@ -102,10 +121,10 @@ impl Screen {
|
||||
position,
|
||||
String::new(),
|
||||
&self.full_screen_ws,
|
||||
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.os_api.clone(),
|
||||
self.send_pty_instructions.clone(),
|
||||
self.send_plugin_instructions.clone(),
|
||||
self.send_app_instructions.clone(),
|
||||
self.max_panes,
|
||||
Some(PaneId::Terminal(pane_id)),
|
||||
self.mode_info.clone(),
|
||||
@ -188,14 +207,11 @@ 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
|
||||
.bus
|
||||
.to_pty
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send_pty_instructions
|
||||
.send(PtyInstruction::CloseTab(pane_ids));
|
||||
if self.tabs.is_empty() {
|
||||
self.active_tab_index = None;
|
||||
self.bus.to_app.as_ref().unwrap()
|
||||
self.send_app_instructions
|
||||
.send(AppInstruction::Exit)
|
||||
.unwrap();
|
||||
} else {
|
||||
@ -209,7 +225,7 @@ impl Screen {
|
||||
}
|
||||
|
||||
pub fn resize_to_screen(&mut self) {
|
||||
let new_screen_size = self.bus.os_input.as_ref().unwrap().get_terminal_size_using_fd(0);
|
||||
let new_screen_size = self.os_api.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);
|
||||
@ -260,10 +276,10 @@ impl Screen {
|
||||
position,
|
||||
String::new(),
|
||||
&self.full_screen_ws,
|
||||
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.os_api.clone(),
|
||||
self.send_pty_instructions.clone(),
|
||||
self.send_plugin_instructions.clone(),
|
||||
self.send_app_instructions.clone(),
|
||||
self.max_panes,
|
||||
None,
|
||||
self.mode_info.clone(),
|
||||
@ -285,7 +301,7 @@ impl Screen {
|
||||
is_sync_panes_active: tab.is_sync_panes_active(),
|
||||
});
|
||||
}
|
||||
self.bus.to_plugin.as_ref().unwrap()
|
||||
self.send_plugin_instructions
|
||||
.send(PluginInstruction::Update(None, Event::TabUpdate(tab_data)))
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use wasmer_wasi::WasiEnv;
|
||||
use zellij_tile::data::{Event, EventType, PluginIds};
|
||||
|
||||
use super::{
|
||||
pty::PtyInstruction, screen::ScreenInstruction, AppInstruction, PaneId, SenderWithContext,
|
||||
pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction, PaneId, SenderWithContext,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -28,10 +28,10 @@ pub enum PluginInstruction {
|
||||
pub struct PluginEnv {
|
||||
pub plugin_id: u32,
|
||||
// FIXME: This should be a big bundle of all of the channels
|
||||
pub to_screen: SenderWithContext<ScreenInstruction>,
|
||||
pub to_app: SenderWithContext<AppInstruction>,
|
||||
pub to_pty: SenderWithContext<PtyInstruction>,
|
||||
pub to_plugin: SenderWithContext<PluginInstruction>,
|
||||
pub send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
pub send_app_instructions: SenderWithContext<AppInstruction>,
|
||||
pub send_pty_instructions: SenderWithContext<PtyInstruction>,
|
||||
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
|
||||
pub wasi_env: WasiEnv,
|
||||
pub subscriptions: Arc<Mutex<HashSet<EventType>>>,
|
||||
}
|
||||
@ -77,7 +77,7 @@ fn host_unsubscribe(plugin_env: &PluginEnv) {
|
||||
fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) {
|
||||
let selectable = selectable != 0;
|
||||
plugin_env
|
||||
.to_screen
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::SetSelectable(
|
||||
PaneId::Plugin(plugin_env.plugin_id),
|
||||
selectable,
|
||||
@ -88,7 +88,7 @@ fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) {
|
||||
fn host_set_max_height(plugin_env: &PluginEnv, max_height: i32) {
|
||||
let max_height = max_height as usize;
|
||||
plugin_env
|
||||
.to_screen
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::SetMaxHeight(
|
||||
PaneId::Plugin(plugin_env.plugin_id),
|
||||
max_height,
|
||||
@ -99,7 +99,7 @@ fn host_set_max_height(plugin_env: &PluginEnv, max_height: i32) {
|
||||
fn host_set_invisible_borders(plugin_env: &PluginEnv, invisible_borders: i32) {
|
||||
let invisible_borders = invisible_borders != 0;
|
||||
plugin_env
|
||||
.to_screen
|
||||
.send_screen_instructions
|
||||
.send(ScreenInstruction::SetInvisibleBorders(
|
||||
PaneId::Plugin(plugin_env.plugin_id),
|
||||
invisible_borders,
|
||||
@ -118,7 +118,7 @@ fn host_get_plugin_ids(plugin_env: &PluginEnv) {
|
||||
fn host_open_file(plugin_env: &PluginEnv) {
|
||||
let path: PathBuf = wasi_read_object(&plugin_env.wasi_env);
|
||||
plugin_env
|
||||
.to_pty
|
||||
.send_pty_instructions
|
||||
.send(PtyInstruction::SpawnTerminal(Some(path)))
|
||||
.unwrap();
|
||||
}
|
||||
@ -133,7 +133,7 @@ fn host_set_timeout(plugin_env: &PluginEnv, secs: f64) {
|
||||
// timers as we'd like.
|
||||
//
|
||||
// But that's a lot of code, and this is a few lines:
|
||||
let send_plugin_instructions = plugin_env.to_plugin.clone();
|
||||
let send_plugin_instructions = plugin_env.send_plugin_instructions.clone();
|
||||
let update_target = Some(plugin_env.plugin_id);
|
||||
thread::spawn(move || {
|
||||
let start_time = Instant::now();
|
||||
|
@ -14,7 +14,7 @@ use crate::utils::{
|
||||
};
|
||||
use client::{boundaries, layout, panes, tab};
|
||||
use common::{
|
||||
command_is_executing, errors, install, os_input_output, screen, start, utils, wasm_vm,
|
||||
command_is_executing, errors, install, os_input_output, pty_bus, screen, start, utils, wasm_vm,
|
||||
ApiCommand,
|
||||
};
|
||||
use std::io::Write;
|
||||
|
Loading…
Reference in New Issue
Block a user