wip: helper functions for ServerInstruction

This commit is contained in:
denis 2021-03-30 14:17:16 +03:00 committed by Kunal Mohan
parent ea732166e3
commit ee14d5f5dd
5 changed files with 176 additions and 54 deletions

View file

@ -358,8 +358,8 @@ impl Tab {
// can query the screen as to how many panes it needs to create a layout
// fixing this will require a bit of an architecture change
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(
PaneId::Terminal(*unused_pid),
.send_to_server(ServerInstruction::pty_close_pane(PaneId::Terminal(
*unused_pid,
)));
}
self.active_terminal = self.panes.iter().map(|(id, _)| id.to_owned()).next();
@ -406,7 +406,7 @@ impl Tab {
);
if terminal_id_to_split.is_none() {
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.send_to_server(ServerInstruction::pty_close_pane(pid)); // we can't open this pane, close the pty
return; // likely no terminal large enough to split
}
let terminal_id_to_split = terminal_id_to_split.unwrap();
@ -496,7 +496,7 @@ impl Tab {
let active_pane = self.panes.get_mut(active_pane_id).unwrap();
if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 {
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.send_to_server(ServerInstruction::pty_close_pane(pid)); // we can't open this pane, close the pty
return;
}
let terminal_ws = PositionAndSize {
@ -557,7 +557,7 @@ impl Tab {
let active_pane = self.panes.get_mut(active_pane_id).unwrap();
if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 {
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.send_to_server(ServerInstruction::pty_close_pane(pid)); // we can't open this pane, close the pty
return;
}
let terminal_ws = PositionAndSize {
@ -2145,7 +2145,7 @@ impl Tab {
let terminals = self.get_pane_ids();
for &pid in terminals.iter().skip(max_panes - 1) {
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid)));
.send_to_server(ServerInstruction::pty_close_pane(pid));
self.close_pane_without_rerender(pid);
}
}
@ -2256,9 +2256,7 @@ impl Tab {
if let Some(active_pane_id) = self.get_active_pane_id() {
self.close_pane(active_pane_id);
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(
active_pane_id,
)));
.send_to_server(ServerInstruction::pty_close_pane(active_pane_id));
}
}
pub fn scroll_active_terminal_up(&mut self) {

View file

@ -241,7 +241,7 @@ impl InputHandler {
Action::NewTab => {
self.command_is_executing.updating_tabs();
self.os_input
.send_to_server(ServerInstruction::ToPty(PtyInstruction::NewTab));
.send_to_server(ServerInstruction::pty_new_tab());
self.command_is_executing.wait_until_tabs_are_updated();
}
Action::GoToNextTab => {

View file

@ -97,18 +97,12 @@ impl VteEventSender {
impl vte::Perform for VteEventSender {
fn print(&mut self, c: char) {
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
self.id,
VteEvent::Print(c),
)))
.send(ServerInstruction::pty(self.id, VteEvent::Print(c)))
.unwrap();
}
fn execute(&mut self, byte: u8) {
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
self.id,
VteEvent::Execute(byte),
)))
.send(ServerInstruction::pty(self.id, VteEvent::Execute(byte)))
.unwrap();
}
@ -116,38 +110,32 @@ impl vte::Perform for VteEventSender {
let params = params.iter().copied().collect();
let intermediates = intermediates.iter().copied().collect();
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
.send(ServerInstruction::pty(
self.id,
VteEvent::Hook(params, intermediates, ignore, c),
)))
))
.unwrap();
}
fn put(&mut self, byte: u8) {
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
self.id,
VteEvent::Put(byte),
)))
.send(ServerInstruction::pty(self.id, VteEvent::Put(byte)))
.unwrap();
}
fn unhook(&mut self) {
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
self.id,
VteEvent::Unhook,
)))
.send(ServerInstruction::pty(self.id, VteEvent::Unhook))
.unwrap();
}
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
let params = params.iter().map(|p| p.to_vec()).collect();
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
.send(ServerInstruction::pty(
self.id,
VteEvent::OscDispatch(params, bell_terminated),
)))
))
.unwrap();
}
@ -155,20 +143,20 @@ impl vte::Perform for VteEventSender {
let params = params.iter().copied().collect();
let intermediates = intermediates.iter().copied().collect();
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
.send(ServerInstruction::pty(
self.id,
VteEvent::CsiDispatch(params, intermediates, ignore, c),
)))
))
.unwrap();
}
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
let intermediates = intermediates.iter().copied().collect();
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Pty(
.send(ServerInstruction::pty(
self.id,
VteEvent::EscDispatch(intermediates, ignore, byte),
)))
))
.unwrap();
}
}
@ -233,7 +221,7 @@ fn stream_terminal_bytes(
if receive_time.elapsed() > max_render_pause {
pending_render = false;
send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Render))
.send(ServerInstruction::render())
.unwrap();
last_byte_receive_time = Some(Instant::now());
} else {
@ -249,7 +237,7 @@ fn stream_terminal_bytes(
if pending_render {
pending_render = false;
send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Render))
.send(ServerInstruction::render())
.unwrap();
}
last_byte_receive_time = None;
@ -257,16 +245,14 @@ fn stream_terminal_bytes(
}
}
send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::Render))
.send(ServerInstruction::render())
.unwrap();
#[cfg(not(test))]
// this is a little hacky, and is because the tests end the file as soon as
// we read everything, rather than hanging until there is new data
// a better solution would be to fix the test fakes, but this will do for now
send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::ClosePane(
PaneId::Terminal(pid),
)))
.send(ServerInstruction::screen_close_pane(PaneId::Terminal(pid)))
.unwrap();
}
})
@ -311,8 +297,9 @@ impl PtyBus {
new_pane_pids.push(pid_primary);
}
self.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::ApplyLayout(
(layout_path, new_pane_pids.clone()),
.send(ServerInstruction::apply_layout((
layout_path,
new_pane_pids.clone(),
)))
.unwrap();
for id in new_pane_pids {

View file

@ -212,7 +212,7 @@ 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
self.os_api
.send_to_server(ServerInstruction::ToPty(PtyInstruction::CloseTab(pane_ids)));
.send_to_server(ServerInstruction::pty_close_tab(pane_ids));
if self.tabs.is_empty() {
self.active_tab_index = None;
self.send_app_instructions

View file

@ -1,4 +1,3 @@
use crate::cli::CliArgs;
use crate::client::ClientInstruction;
use crate::common::{ChannelWithContext, SenderType, SenderWithContext};
use crate::errors::{ContextType, ErrorContext, OsContext, PtyContext, ServerContext};
@ -6,10 +5,13 @@ use crate::os_input_output::{ServerOsApi, ServerOsApiInstruction};
use crate::panes::PaneId;
use crate::pty_bus::{PtyBus, PtyInstruction};
use crate::screen::ScreenInstruction;
use crate::{cli::CliArgs, common::pty_bus::VteEvent};
use serde::{Deserialize, Serialize};
use std::os::unix::io::RawFd;
use std::path::PathBuf;
use std::sync::mpsc::channel;
use std::thread;
use zellij_tile::prelude::InputMode;
/// Instructions related to server-side application including the
/// ones sent by client to server
@ -28,6 +30,147 @@ pub enum ServerInstruction {
ClientExit,
Exit,
}
impl ServerInstruction {
// ToPty
pub fn spawn_terminal(path: Option<PathBuf>) -> Self {
Self::ToPty(PtyInstruction::SpawnTerminal(path))
}
pub fn spawn_terminal_vertically(path: Option<PathBuf>) -> Self {
Self::ToPty(PtyInstruction::SpawnTerminalVertically(path))
}
pub fn spawn_terminal_horizontally(path: Option<PathBuf>) -> Self {
Self::ToPty(PtyInstruction::SpawnTerminalHorizontally(path))
}
pub fn pty_new_tab() -> Self {
Self::ToPty(PtyInstruction::NewTab)
}
pub fn pty_close_pane(id: PaneId) -> Self {
Self::ToPty(PtyInstruction::ClosePane(id))
}
pub fn pty_close_tab(ids: Vec<PaneId>) -> Self {
Self::ToPty(PtyInstruction::CloseTab(ids))
}
pub fn pty_exit() -> Self {
Self::ToPty(PtyInstruction::Exit)
}
// ToScreen
pub fn render() -> Self {
Self::ToScreen(ScreenInstruction::Render)
}
pub fn new_pane(id: PaneId) -> Self {
Self::ToScreen(ScreenInstruction::NewPane(id))
}
pub fn horizontal_split(id: PaneId) -> Self {
Self::ToScreen(ScreenInstruction::HorizontalSplit(id))
}
pub fn vertical_split(id: PaneId) -> Self {
Self::ToScreen(ScreenInstruction::VerticalSplit(id))
}
pub fn write_character(chars: Vec<u8>) -> Self {
Self::ToScreen(ScreenInstruction::WriteCharacter(chars))
}
pub fn resize_left() -> Self {
Self::ToScreen(ScreenInstruction::ResizeLeft)
}
pub fn resize_right() -> Self {
Self::ToScreen(ScreenInstruction::ResizeRight)
}
pub fn resize_down() -> Self {
Self::ToScreen(ScreenInstruction::ResizeDown)
}
pub fn resize_up() -> Self {
Self::ToScreen(ScreenInstruction::ResizeUp)
}
pub fn move_focus() -> Self {
Self::ToScreen(ScreenInstruction::MoveFocus)
}
pub fn move_focus_left() -> Self {
Self::ToScreen(ScreenInstruction::MoveFocusLeft)
}
pub fn move_focus_right() -> Self {
Self::ToScreen(ScreenInstruction::MoveFocusRight)
}
pub fn move_focus_down() -> Self {
Self::ToScreen(ScreenInstruction::MoveFocusDown)
}
pub fn move_focus_up() -> Self {
Self::ToScreen(ScreenInstruction::MoveFocusUp)
}
pub fn screen_exit() -> Self {
Self::ToScreen(ScreenInstruction::Exit)
}
pub fn scroll_up() -> Self {
Self::ToScreen(ScreenInstruction::ScrollUp)
}
pub fn scroll_down() -> Self {
Self::ToScreen(ScreenInstruction::ScrollDown)
}
pub fn clear_scroll() -> Self {
Self::ToScreen(ScreenInstruction::ClearScroll)
}
pub fn close_focused_pane() -> Self {
Self::ToScreen(ScreenInstruction::CloseFocusedPane)
}
pub fn toggle_active_terminal_fullscreen() -> Self {
Self::ToScreen(ScreenInstruction::ToggleActiveTerminalFullscreen)
}
pub fn set_selectable(pane_id: PaneId, value: bool) -> Self {
Self::ToScreen(ScreenInstruction::SetSelectable(pane_id, value))
}
pub fn set_max_height(pane_id: PaneId, max_height: usize) -> Self {
Self::ToScreen(ScreenInstruction::SetMaxHeight(pane_id, max_height))
}
pub fn set_invisible_borders(pane_id: PaneId, value: bool) -> Self {
Self::ToScreen(ScreenInstruction::SetInvisibleBorders(pane_id, value))
}
pub fn screen_close_pane(pane_id: PaneId) -> Self {
Self::ToScreen(ScreenInstruction::ClosePane(pane_id))
}
pub fn apply_layout(layout: (PathBuf, Vec<RawFd>)) -> Self {
Self::ToScreen(ScreenInstruction::ApplyLayout(layout))
}
pub fn screen_new_tab(fd: RawFd) -> Self {
Self::ToScreen(ScreenInstruction::NewTab(fd))
}
pub fn switch_tab_prev() -> Self {
Self::ToScreen(ScreenInstruction::SwitchTabPrev)
}
pub fn switch_tab_next() -> Self {
Self::ToScreen(ScreenInstruction::SwitchTabPrev)
}
pub fn screen_close_tab() -> Self {
Self::ToScreen(ScreenInstruction::CloseTab)
}
pub fn go_to_tab(tab_id: u32) -> Self {
Self::ToScreen(ScreenInstruction::GoToTab(tab_id))
}
pub fn update_tab_name(tab_ids: Vec<u8>) -> Self {
Self::ToScreen(ScreenInstruction::UpdateTabName(tab_ids))
}
pub fn change_input_mode(input_mode: InputMode) -> Self {
Self::ToScreen(ScreenInstruction::ChangeInputMode(input_mode))
}
pub fn pty(fd: RawFd, event: VteEvent) -> Self {
Self::ToScreen(ScreenInstruction::Pty(fd, event))
}
// OsApi
pub fn set_terminal_size_using_fd(fd: RawFd, cols: u16, rows: u16) -> Self {
Self::OsApi(ServerOsApiInstruction::SetTerminalSizeUsingFd(
fd, cols, rows,
))
}
pub fn write_to_tty_stdin(fd: RawFd, buf: Vec<u8>) -> Self {
Self::OsApi(ServerOsApiInstruction::WriteToTtyStdin(fd, buf))
}
pub fn tc_drain(fd: RawFd) -> Self {
Self::OsApi(ServerOsApiInstruction::TcDrain(fd))
}
pub fn os_exit() -> Self {
Self::OsApi(ServerOsApiInstruction::Exit)
}
}
pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread::JoinHandle<()> {
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
@ -80,27 +223,21 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
let pid = pty_bus.spawn_terminal(file_to_open);
pty_bus
.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::NewPane(
PaneId::Terminal(pid),
)))
.send(ServerInstruction::new_pane(PaneId::Terminal(pid)))
.unwrap();
}
PtyInstruction::SpawnTerminalVertically(file_to_open) => {
let pid = pty_bus.spawn_terminal(file_to_open);
pty_bus
.send_server_instructions
.send(ServerInstruction::ToScreen(
ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)),
))
.send(ServerInstruction::vertical_split(PaneId::Terminal(pid)))
.unwrap();
}
PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
let pid = pty_bus.spawn_terminal(file_to_open);
pty_bus
.send_server_instructions
.send(ServerInstruction::ToScreen(
ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)),
))
.send(ServerInstruction::horizontal_split(PaneId::Terminal(pid)))
.unwrap();
}
PtyInstruction::NewTab => {
@ -110,7 +247,7 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
let pid = pty_bus.spawn_terminal(None);
pty_bus
.send_server_instructions
.send(ServerInstruction::ToScreen(ScreenInstruction::NewTab(pid)))
.send(ServerInstruction::screen_new_tab(pid))
.unwrap();
}
}