Use IPC for Server to client as well
Add router thread
This commit is contained in:
parent
831a02b9c0
commit
5ece7f44cc
6 changed files with 98 additions and 74 deletions
|
|
@ -194,7 +194,7 @@ pub enum ScreenContext {
|
|||
MoveFocusDown,
|
||||
MoveFocusUp,
|
||||
MoveFocusRight,
|
||||
Quit,
|
||||
Exit,
|
||||
ScrollUp,
|
||||
ScrollDown,
|
||||
PageScrollUp,
|
||||
|
|
@ -239,7 +239,7 @@ impl From<&ScreenInstruction> for ScreenContext {
|
|||
ScreenInstruction::MoveFocusDown => ScreenContext::MoveFocusDown,
|
||||
ScreenInstruction::MoveFocusUp => ScreenContext::MoveFocusUp,
|
||||
ScreenInstruction::MoveFocusRight => ScreenContext::MoveFocusRight,
|
||||
ScreenInstruction::Quit => ScreenContext::Quit,
|
||||
ScreenInstruction::Exit => ScreenContext::Exit,
|
||||
ScreenInstruction::ScrollUp => ScreenContext::ScrollUp,
|
||||
ScreenInstruction::ScrollDown => ScreenContext::ScrollDown,
|
||||
ScreenInstruction::PageScrollUp => ScreenContext::PageScrollUp,
|
||||
|
|
@ -276,7 +276,7 @@ pub enum PtyContext {
|
|||
NewTab,
|
||||
ClosePane,
|
||||
CloseTab,
|
||||
Quit,
|
||||
Exit,
|
||||
}
|
||||
|
||||
impl From<&PtyInstruction> for PtyContext {
|
||||
|
|
@ -288,7 +288,7 @@ impl From<&PtyInstruction> for PtyContext {
|
|||
PtyInstruction::ClosePane(_) => PtyContext::ClosePane,
|
||||
PtyInstruction::CloseTab(_) => PtyContext::CloseTab,
|
||||
PtyInstruction::NewTab => PtyContext::NewTab,
|
||||
PtyInstruction::Quit => PtyContext::Quit,
|
||||
PtyInstruction::Exit => PtyContext::Exit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +304,7 @@ pub enum PluginContext {
|
|||
Update,
|
||||
Render,
|
||||
Unload,
|
||||
Quit,
|
||||
Exit,
|
||||
}
|
||||
|
||||
impl From<&PluginInstruction> for PluginContext {
|
||||
|
|
@ -314,7 +314,7 @@ impl From<&PluginInstruction> for PluginContext {
|
|||
PluginInstruction::Update(..) => PluginContext::Update,
|
||||
PluginInstruction::Render(..) => PluginContext::Render,
|
||||
PluginInstruction::Unload(_) => PluginContext::Unload,
|
||||
PluginInstruction::Quit => PluginContext::Quit,
|
||||
PluginInstruction::Exit => PluginContext::Exit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use std::{collections::HashMap, fs};
|
|||
use crate::panes::PaneId;
|
||||
use directories_next::ProjectDirs;
|
||||
use input::handler::InputMode;
|
||||
use ipmpsc::{Sender as IpcSender, SharedRingBuffer};
|
||||
use ipmpsc::{Receiver as IpcReceiver, Sender as IpcSender, SharedRingBuffer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use termion::input::TermRead;
|
||||
use wasm_vm::PluginEnv;
|
||||
|
|
@ -48,10 +48,11 @@ pub enum ServerInstruction {
|
|||
SplitHorizontally,
|
||||
SplitVertically,
|
||||
MoveFocus,
|
||||
NewClient(String),
|
||||
ToPty(PtyInstruction),
|
||||
ToScreen(ScreenInstruction),
|
||||
ClosePluginPane(u32),
|
||||
Quit,
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
|
@ -59,6 +60,7 @@ pub enum ClientInstruction {
|
|||
ToScreen(ScreenInstruction),
|
||||
ClosePluginPane(u32),
|
||||
Error(String),
|
||||
Exit,
|
||||
}
|
||||
|
||||
// FIXME: It would be good to add some more things to this over time
|
||||
|
|
@ -177,6 +179,19 @@ pub enum AppInstruction {
|
|||
ToPlugin(PluginInstruction),
|
||||
}
|
||||
|
||||
impl From<ClientInstruction> for AppInstruction {
|
||||
fn from(item: ClientInstruction) -> Self {
|
||||
match item {
|
||||
ClientInstruction::ToScreen(s) => AppInstruction::ToScreen(s),
|
||||
ClientInstruction::Error(e) => AppInstruction::Error(e),
|
||||
ClientInstruction::ClosePluginPane(p) => {
|
||||
AppInstruction::ToPlugin(PluginInstruction::Unload(p))
|
||||
}
|
||||
ClientInstruction::Exit => AppInstruction::Exit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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, config: Config) {
|
||||
|
|
@ -207,15 +222,16 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
|
||||
let (send_app_instructions, receive_app_instructions): SyncChannelWithContext<AppInstruction> =
|
||||
mpsc::sync_channel(500);
|
||||
let send_app_instructions =
|
||||
SenderWithContext::new(SenderType::SyncSender(send_app_instructions));
|
||||
let mut send_app_instructions =
|
||||
SenderWithContext::new(err_ctx, SenderType::SyncSender(send_app_instructions));
|
||||
|
||||
let ipc_thread = start_server(
|
||||
os_input.clone(),
|
||||
opts.clone(),
|
||||
command_is_executing.clone(),
|
||||
send_app_instructions.clone(),
|
||||
);
|
||||
let ipc_thread = start_server(os_input.clone(), opts.clone(), command_is_executing.clone());
|
||||
|
||||
let (client_buffer_path, client_buffer) = SharedRingBuffer::create_temp(8192).unwrap();
|
||||
let mut send_server_instructions = IpcSenderWithContext::to_server();
|
||||
send_server_instructions
|
||||
.send(ServerInstruction::NewClient(client_buffer_path))
|
||||
.unwrap();
|
||||
|
||||
#[cfg(not(test))]
|
||||
std::panic::set_hook({
|
||||
|
|
@ -405,26 +421,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
screen.apply_layout(Layout::new(layout), new_pane_pids);
|
||||
command_is_executing.done_opening_new_pane();
|
||||
}
|
||||
ScreenInstruction::GoToTab(tab_index) => {
|
||||
screen.go_to_tab(tab_index as usize)
|
||||
}
|
||||
ScreenInstruction::UpdateTabName(c) => {
|
||||
screen.update_active_tab_name(c);
|
||||
}
|
||||
ScreenInstruction::TerminalResize => {
|
||||
screen.resize_to_screen();
|
||||
}
|
||||
ScreenInstruction::ChangeMode(mode_info) => {
|
||||
screen.change_mode(mode_info);
|
||||
}
|
||||
ScreenInstruction::ToggleActiveSyncPanes => {
|
||||
screen
|
||||
.get_active_tab_mut()
|
||||
.unwrap()
|
||||
.toggle_sync_panes_is_active();
|
||||
screen.update_tabs();
|
||||
}
|
||||
ScreenInstruction::Quit => {
|
||||
ScreenInstruction::Exit => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -525,7 +522,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
buf_tx.send(wasi_read_string(&plugin_env.wasi_env)).unwrap();
|
||||
}
|
||||
PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
|
||||
PluginInstruction::Quit => break,
|
||||
PluginInstruction::Exit => break,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -536,6 +533,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
.spawn({
|
||||
let send_screen_instructions = send_screen_instructions.clone();
|
||||
let send_plugin_instructions = send_plugin_instructions.clone();
|
||||
let send_app_instructions = send_app_instructions.clone();
|
||||
let os_input = os_input.clone();
|
||||
let config = config;
|
||||
move || {
|
||||
|
|
@ -550,7 +548,25 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
}
|
||||
});
|
||||
|
||||
let mut send_server_instructions = IpcSenderWithContext::to_server();
|
||||
let router_thread = thread::Builder::new()
|
||||
.name("router".to_string())
|
||||
.spawn({
|
||||
let recv_client_instructions = IpcReceiver::new(client_buffer);
|
||||
move || loop {
|
||||
let (err_ctx, instruction): (ErrorContext, ClientInstruction) =
|
||||
recv_client_instructions.recv().unwrap();
|
||||
send_app_instructions.update(err_ctx);
|
||||
match instruction {
|
||||
ClientInstruction::Exit => break,
|
||||
_ => {
|
||||
send_app_instructions
|
||||
.send(AppInstruction::from(instruction))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
#[warn(clippy::never_loop)]
|
||||
loop {
|
||||
|
|
@ -562,16 +578,17 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
send_screen_instructions.update(err_ctx);
|
||||
send_server_instructions.update(err_ctx);
|
||||
match app_instruction {
|
||||
AppInstruction::Exit => {
|
||||
break;
|
||||
}
|
||||
AppInstruction::GetState(state_tx) => drop(state_tx.send(app_state.clone())),
|
||||
AppInstruction::SetState(state) => app_state = state,
|
||||
AppInstruction::Exit => break,
|
||||
AppInstruction::Error(backtrace) => {
|
||||
let _ = send_server_instructions.send(ServerInstruction::Quit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Quit);
|
||||
let _ = send_server_instructions.send(ServerInstruction::Exit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Exit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Exit);
|
||||
let _ = screen_thread.join();
|
||||
let _ = wasm_thread.join();
|
||||
let _ = ipc_thread.join();
|
||||
//let _ = router_thread.join();
|
||||
os_input.unset_raw_mode(0);
|
||||
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
|
||||
let error = format!("{}\n{}", goto_start_of_last_line, backtrace);
|
||||
|
|
@ -593,12 +610,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
|||
}
|
||||
}
|
||||
|
||||
let _ = send_server_instructions.send(ServerInstruction::Quit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Quit);
|
||||
let _ = send_server_instructions.send(ServerInstruction::Exit);
|
||||
let _ = send_screen_instructions.send(ScreenInstruction::Exit);
|
||||
let _ = send_plugin_instructions.send(PluginInstruction::Exit);
|
||||
screen_thread.join().unwrap();
|
||||
wasm_thread.join().unwrap();
|
||||
ipc_thread.join().unwrap();
|
||||
router_thread.join().unwrap();
|
||||
|
||||
// cleanup();
|
||||
let reset_style = "\u{1b}[m";
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ pub enum PtyInstruction {
|
|||
NewTab,
|
||||
ClosePane(PaneId),
|
||||
CloseTab(Vec<PaneId>),
|
||||
Quit,
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub struct PtyBus {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub enum ScreenInstruction {
|
|||
MoveFocusDown,
|
||||
MoveFocusUp,
|
||||
MoveFocusRight,
|
||||
Quit,
|
||||
Exit,
|
||||
ScrollUp,
|
||||
ScrollDown,
|
||||
PageScrollUp,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub enum PluginInstruction {
|
|||
Update(Option<u32>, Event), // Focused plugin / broadcast, event data
|
||||
Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
|
||||
Unload(u32),
|
||||
Quit,
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(WasmerEnv, Clone)]
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
use crate::cli::CliArgs;
|
||||
use crate::command_is_executing::CommandIsExecuting;
|
||||
use crate::common::{
|
||||
AppInstruction, ChannelWithContext, IpcSenderWithContext, SenderType, SenderWithContext,
|
||||
ChannelWithContext, ClientInstruction, IpcSenderWithContext, SenderType, SenderWithContext,
|
||||
ServerInstruction,
|
||||
};
|
||||
use crate::errors::{ContextType, ErrorContext, PtyContext};
|
||||
use crate::layout::Layout;
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::panes::PaneId;
|
||||
use crate::pty_bus::{PtyBus, PtyInstruction};
|
||||
use crate::screen::ScreenInstruction;
|
||||
use crate::utils::consts::ZELLIJ_IPC_PIPE;
|
||||
use crate::wasm_vm::PluginInstruction;
|
||||
use ipmpsc::{Receiver, SharedRingBuffer};
|
||||
use std::io::{BufReader, Read};
|
||||
use ipmpsc::{Receiver as IpcReceiver, SharedRingBuffer};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
|
@ -22,7 +19,6 @@ pub fn start_server(
|
|||
os_input: Box<dyn OsApi>,
|
||||
opts: CliArgs,
|
||||
command_is_executing: CommandIsExecuting,
|
||||
mut send_app_instructions: SenderWithContext<AppInstruction>,
|
||||
) -> thread::JoinHandle<()> {
|
||||
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
|
||||
channel();
|
||||
|
|
@ -31,7 +27,6 @@ pub fn start_server(
|
|||
SenderType::Sender(send_pty_instructions),
|
||||
);
|
||||
|
||||
std::fs::remove_file(ZELLIJ_IPC_PIPE).ok();
|
||||
let server_buffer = SharedRingBuffer::create(ZELLIJ_IPC_PIPE, 8192).unwrap();
|
||||
|
||||
// Don't use default layouts in tests, but do everywhere else
|
||||
|
|
@ -54,7 +49,6 @@ pub fn start_server(
|
|||
.name("pty".to_string())
|
||||
.spawn({
|
||||
let mut command_is_executing = command_is_executing.clone();
|
||||
send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
|
||||
move || loop {
|
||||
let (event, mut err_ctx) = pty_bus
|
||||
.receive_pty_instructions
|
||||
|
|
@ -108,7 +102,7 @@ pub fn start_server(
|
|||
pty_bus.close_tab(ids);
|
||||
command_is_executing.done_closing_pane();
|
||||
}
|
||||
PtyInstruction::Quit => {
|
||||
PtyInstruction::Exit => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -119,15 +113,20 @@ pub fn start_server(
|
|||
thread::Builder::new()
|
||||
.name("ipc_server".to_string())
|
||||
.spawn({
|
||||
let recv_server_instructions = Receiver::new(server_buffer);
|
||||
let recv_server_instructions = IpcReceiver::new(server_buffer);
|
||||
// Fixme: We cannot use uninitialised sender, therefore this Vec.
|
||||
// We make sure that the first message is `NewClient` so there are no out of bouns panics.
|
||||
let mut send_client_instructions: Vec<IpcSenderWithContext> = Vec::with_capacity(1);
|
||||
move || loop {
|
||||
let (mut err_ctx, decoded): (ErrorContext, ServerInstruction) =
|
||||
let (mut err_ctx, instruction): (ErrorContext, ServerInstruction) =
|
||||
recv_server_instructions.recv().unwrap();
|
||||
err_ctx.add_call(ContextType::IPCServer);
|
||||
send_pty_instructions.update(err_ctx);
|
||||
send_app_instructions.update(err_ctx);
|
||||
if send_client_instructions.len() == 1 {
|
||||
send_client_instructions[0].update(err_ctx);
|
||||
}
|
||||
|
||||
match decoded {
|
||||
match instruction {
|
||||
ServerInstruction::OpenFile(file_name) => {
|
||||
let path = PathBuf::from(file_name);
|
||||
send_pty_instructions
|
||||
|
|
@ -145,26 +144,33 @@ pub fn start_server(
|
|||
.unwrap();
|
||||
}
|
||||
ServerInstruction::MoveFocus => {
|
||||
send_app_instructions
|
||||
.send(AppInstruction::ToScreen(ScreenInstruction::MoveFocus))
|
||||
send_client_instructions[0]
|
||||
.send(ClientInstruction::ToScreen(ScreenInstruction::MoveFocus))
|
||||
.unwrap();
|
||||
}
|
||||
ServerInstruction::ToPty(instruction) => {
|
||||
send_pty_instructions.send(instruction).unwrap();
|
||||
ServerInstruction::NewClient(buffer_path) => {
|
||||
send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
|
||||
send_client_instructions.push(IpcSenderWithContext::new(
|
||||
SharedRingBuffer::open(&buffer_path).unwrap(),
|
||||
));
|
||||
}
|
||||
ServerInstruction::ToScreen(instruction) => {
|
||||
send_app_instructions
|
||||
.send(AppInstruction::ToScreen(instruction))
|
||||
ServerInstruction::ToPty(instr) => {
|
||||
send_pty_instructions.send(instr).unwrap();
|
||||
}
|
||||
ServerInstruction::ToScreen(instr) => {
|
||||
send_client_instructions[0]
|
||||
.send(ClientInstruction::ToScreen(instr))
|
||||
.unwrap();
|
||||
}
|
||||
ServerInstruction::ClosePluginPane(pid) => {
|
||||
send_app_instructions
|
||||
.send(AppInstruction::ToPlugin(PluginInstruction::Unload(pid)))
|
||||
send_client_instructions[0]
|
||||
.send(ClientInstruction::ClosePluginPane(pid))
|
||||
.unwrap();
|
||||
}
|
||||
ServerInstruction::Quit => {
|
||||
let _ = send_pty_instructions.send(PtyInstruction::Quit);
|
||||
ServerInstruction::Exit => {
|
||||
let _ = send_pty_instructions.send(PtyInstruction::Exit);
|
||||
let _ = pty_thread.join();
|
||||
let _ = send_client_instructions[0].send(ClientInstruction::Exit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue