Fix after rebase

This commit is contained in:
Kunal Mohan 2021-04-14 01:41:40 +05:30
parent 30d0ec2a40
commit fedb588330
14 changed files with 194 additions and 265 deletions

89
Cargo.lock generated
View File

@ -209,9 +209,9 @@ dependencies = [
[[package]]
name = "bincode"
version = "1.3.2"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
@ -265,9 +265,9 @@ checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byteorder"
version = "1.3.4"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cache-padded"
@ -491,9 +491,9 @@ dependencies = [
[[package]]
name = "darling"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06d4a9551359071d1890820e3571252b91229e0712e7c36b08940e603c5a8fc"
checksum = "e9d6ddad5866bb2170686ed03f6839d31a76e5407d80b1c334a2c24618543ffa"
dependencies = [
"darling_core",
"darling_macro",
@ -501,9 +501,9 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b443e5fb0ddd56e0c9bfa47dc060c5306ee500cb731f2b91432dd65589a77684"
checksum = "a9ced1fd13dc386d5a8315899de465708cf34ee2a6d9394654515214e67bb846"
dependencies = [
"fnv",
"ident_case",
@ -515,9 +515,9 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0220073ce504f12a70efc4e7cdaea9e9b1b324872e7ad96a208056d7a638b81"
checksum = "0a7a1445d54b2f9792e3b31a3e715feabbace393f38dc4ffd49d94ee9bc487d5"
dependencies = [
"darling_core",
"quote",
@ -637,9 +637,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "futures"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
dependencies = [
"futures-channel",
"futures-core",
@ -652,9 +652,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
dependencies = [
"futures-core",
"futures-sink",
@ -662,15 +662,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
[[package]]
name = "futures-executor"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
dependencies = [
"futures-core",
"futures-task",
@ -679,9 +679,9 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
[[package]]
name = "futures-lite"
@ -700,9 +700,9 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
dependencies = [
"proc-macro-hack",
"proc-macro2",
@ -712,21 +712,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
[[package]]
name = "futures-task"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
[[package]]
name = "futures-util"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
dependencies = [
"futures-channel",
"futures-core",
@ -872,9 +872,9 @@ dependencies = [
[[package]]
name = "insta"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1b6cf41e31a7e7b78055b548826da45c7dc74e6a13a3fa6b897a17a01322f26"
checksum = "c4a1b21a2971cea49ca4613c0e9fe8225ecaf5de64090fddc6002284726e9244"
dependencies = [
"console",
"lazy_static",
@ -1030,9 +1030,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "lock_api"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
dependencies = [
"scopeguard",
]
@ -1108,9 +1108,9 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
[[package]]
name = "nb-connect"
version = "1.0.3"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f"
checksum = "a19900e7eee95eb2b3c2e26d12a874cc80aaf750e31be6fcbe743ead369fa45d"
dependencies = [
"libc",
"socket2",
@ -1563,9 +1563,9 @@ dependencies = [
[[package]]
name = "signal-hook"
version = "0.3.6"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7f3f92a1da3d6b1d32245d0cbcbbab0cfc45996d8df619c42bccfa6d2bbb5f"
checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
dependencies = [
"libc",
"signal-hook-registry",
@ -1600,11 +1600,10 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "socket2"
version = "0.3.19"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
dependencies = [
"cfg-if 1.0.0",
"libc",
"winapi",
]
@ -1844,9 +1843,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.13"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07"
checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
dependencies = [
"proc-macro2",
"quote",
@ -2291,18 +2290,18 @@ checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf"
[[package]]
name = "wast"
version = "35.0.0"
version = "35.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db5ae96da18bb5926341516fd409b5a8ce4e4714da7f0a1063d3b20ac9f9a1e1"
checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68"
dependencies = [
"leb128",
]
[[package]]
name = "wat"
version = "1.0.36"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b0fa059022c5dabe129f02b429d67086400deb8277f89c975555dacc1dadbcc"
checksum = "8ec280a739b69173e0ffd12c1658507996836ba4e992ed9bc1e5385a0bd72a02"
dependencies = [
"wast",
]

View File

@ -2,7 +2,7 @@ use super::common::utils::consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(StructOpt, Debug, Default, Clone)]
#[derive(StructOpt, Default, Debug, Clone)]
#[structopt(name = "zellij")]
pub struct CliArgs {
/// Send "split (direction h == horizontal / v == vertical)" to active zellij session
@ -44,7 +44,7 @@ pub struct CliArgs {
pub debug: bool,
}
#[derive(Debug, StructOpt)]
#[derive(Debug, StructOpt, Clone)]
pub enum ConfigCli {
/// Change the behaviour of zellij
#[structopt(name = "option")]

View File

@ -9,12 +9,14 @@ use std::io::Write;
use std::sync::mpsc;
use std::thread;
use crate::cli::CliArgs;
use crate::common::{
command_is_executing::CommandIsExecuting,
errors::{ClientContext, ContextType},
input::config::Config,
input::handler::input_loop,
os_input_output::ClientOsApi,
SenderType, SenderWithContext, SyncChannelWithContext, OPENCALLS,
SenderType, SenderWithContext, SyncChannelWithContext,
};
use crate::server::ServerInstruction;
@ -29,7 +31,7 @@ pub enum ClientInstruction {
Exit,
}
pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs) {
let take_snapshot = "\u{1b}[?1049h";
os_input.unset_raw_mode(0);
let _ = os_input
@ -37,17 +39,23 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
.write(take_snapshot.as_bytes())
.unwrap();
let config = Config::from_cli_config(opts.config)
.map_err(|e| {
eprintln!("There was an error in the config file:\n{}", e);
std::process::exit(1);
})
.unwrap();
let mut command_is_executing = CommandIsExecuting::new();
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
os_input.set_raw_mode(0);
let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
let (send_client_instructions, receive_client_instructions): SyncChannelWithContext<
ClientInstruction,
> = mpsc::sync_channel(500);
let mut send_client_instructions =
SenderWithContext::new(err_ctx, SenderType::SyncSender(send_client_instructions));
let send_client_instructions =
SenderWithContext::new(SenderType::SyncSender(send_client_instructions));
os_input.connect_to_server(full_screen_ws);
@ -66,7 +74,14 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
let send_client_instructions = send_client_instructions.clone();
let command_is_executing = command_is_executing.clone();
let os_input = os_input.clone();
move || input_loop(os_input, command_is_executing, send_client_instructions)
move || {
input_loop(
os_input,
config,
command_is_executing,
send_client_instructions,
)
}
});
let _signal_thread = thread::Builder::new()
@ -92,8 +107,7 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
let os_input = os_input.clone();
move || {
loop {
let (instruction, err_ctx) = os_input.client_recv();
send_client_instructions.update(err_ctx);
let (instruction, _err_ctx) = os_input.client_recv();
if let ClientInstruction::Exit = instruction {
break;
}
@ -122,7 +136,11 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
let _ = os_input.send_to_server(ServerInstruction::ClientExit);
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);
let restore_snapshot = "\u{1b}[?1049l";
let error = format!(
"{}\n{}{}",
goto_start_of_last_line, restore_snapshot, backtrace
);
let _ = os_input
.get_stdout_writer()
.write(error.as_bytes())

View File

@ -1,7 +1,6 @@
use crate::tab::Pane;
use ::nix::pty::Winsize;
use ::std::os::unix::io::RawFd;
use ::vte::Perform;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::time::Instant;

View File

@ -7,7 +7,7 @@ use crate::common::{input::handler::parse_keys, SenderWithContext};
use crate::layout::Layout;
use crate::os_input_output::ServerOsApi;
use crate::panes::{PaneId, PositionAndSize, TerminalPane};
use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::pty_bus::{PtyInstruction, VteBytes};
use crate::server::ServerInstruction;
use crate::utils::shared::adjust_to_size;
use crate::wasm_vm::PluginInstruction;

View File

@ -1,7 +1,7 @@
//! Error context system based on a thread-local representation of the call stack, itself based on
//! the instructions that are sent between threads.
use super::{ServerInstruction, OPENCALLS};
use super::{ServerInstruction, ASYNCOPENCALLS, OPENCALLS};
use crate::client::ClientInstruction;
use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction;

View File

@ -1,12 +1,14 @@
//! Main input logic.
use super::actions::Action;
use super::keybinds::get_default_keybinds;
use super::keybinds::Keybinds;
use crate::client::ClientInstruction;
use crate::common::input::config::Config;
use crate::common::{SenderWithContext, OPENCALLS};
use crate::errors::ContextType;
use crate::os_input_output::ClientOsApi;
use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction;
use crate::server::ServerInstruction;
use crate::CommandIsExecuting;
@ -19,8 +21,10 @@ struct InputHandler {
/// The current input mode
mode: InputMode,
os_input: Box<dyn ClientOsApi>,
config: Config,
command_is_executing: CommandIsExecuting,
send_client_instructions: SenderWithContext<ClientInstruction>,
should_exit: bool,
}
impl InputHandler {
@ -28,6 +32,7 @@ impl InputHandler {
fn new(
os_input: Box<dyn ClientOsApi>,
command_is_executing: CommandIsExecuting,
config: Config,
send_client_instructions: SenderWithContext<ClientInstruction>,
) -> Self {
InputHandler {
@ -36,6 +41,7 @@ impl InputHandler {
config,
command_is_executing,
send_client_instructions,
should_exit: false,
}
}
@ -44,34 +50,26 @@ impl InputHandler {
fn handle_input(&mut self) {
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
err_ctx.add_call(ContextType::StdinHandler);
self.send_client_instructions.update(err_ctx);
self.os_input.update_senders(err_ctx);
if let Ok(keybinds) = get_default_keybinds() {
'input_loop: loop {
//@@@ I think this should actually just iterate over stdin directly
let stdin_buffer = self.os_input.read_from_stdin();
for key_result in stdin_buffer.events_and_raw() {
match key_result {
Ok((event, raw_bytes)) => match event {
termion::event::Event::Key(key) => {
let key = cast_termion_key(key);
// FIXME this explicit break is needed because the current test
// framework relies on it to not create dead threads that loop
// and eat up CPUs. Do not remove until the test framework has
// been revised. Sorry about this (@categorille)
let mut should_break = false;
for action in key_to_actions(&key, raw_bytes, &self.mode, &keybinds)
{
should_break |= self.dispatch_action(action);
}
if should_break {
break 'input_loop;
}
}
termion::event::Event::Mouse(_)
| termion::event::Event::Unsupported(_) => {
// Mouse and unsupported events aren't implemented yet,
// use a NoOp untill then.
let keybinds = self.config.keybinds.clone();
let alt_left_bracket = vec![27, 91];
loop {
if self.should_exit {
break;
}
let stdin_buffer = self.os_input.read_from_stdin();
for key_result in stdin_buffer.events_and_raw() {
match key_result {
Ok((event, raw_bytes)) => match event {
termion::event::Event::Key(key) => {
let key = cast_termion_key(key);
self.handle_key(&key, raw_bytes, &keybinds);
}
termion::event::Event::Unsupported(unsupported_key) => {
// we have to do this because of a bug in termion
// this should be a key event and not an unsupported event
if unsupported_key == alt_left_bracket {
let key = Key::Alt('[');
self.handle_key(&key, raw_bytes, &keybinds);
}
}
termion::event::Event::Mouse(_) => {
@ -139,8 +137,19 @@ impl InputHandler {
};
self.os_input.send_to_server(screen_instr);
}
Action::SwitchFocus(_) => {
self.os_input.send_to_server(ServerInstruction::MoveFocus);
Action::SwitchFocus => {
self.os_input
.send_to_server(ServerInstruction::ToScreen(ScreenInstruction::SwitchFocus));
}
Action::FocusNextPane => {
self.os_input.send_to_server(ServerInstruction::ToScreen(
ScreenInstruction::FocusNextPane,
));
}
Action::FocusPreviousPane => {
self.os_input.send_to_server(ServerInstruction::ToScreen(
ScreenInstruction::FocusPreviousPane,
));
}
Action::MoveFocus(direction) => {
let screen_instr = match direction {
@ -299,11 +308,17 @@ pub fn get_mode_info(mode: InputMode, palette: Palette) -> ModeInfo {
/// its [`InputHandler::handle_input()`] loop.
pub fn input_loop(
os_input: Box<dyn ClientOsApi>,
config: Config,
command_is_executing: CommandIsExecuting,
send_client_instructions: SenderWithContext<ClientInstruction>,
) {
let _handler =
InputHandler::new(os_input, command_is_executing, send_client_instructions).handle_input();
let _handler = InputHandler::new(
os_input,
command_is_executing,
config,
send_client_instructions,
)
.handle_input();
}
pub fn parse_keys(input_bytes: &[u8]) -> Vec<Key> {

View File

@ -11,7 +11,8 @@ pub mod wasm_vm;
use crate::panes::PaneId;
use crate::server::ServerInstruction;
use errors::ErrorContext;
use async_std::task_local;
use errors::{get_current_ctx, ErrorContext};
use std::cell::RefCell;
use std::sync::mpsc;
@ -43,8 +44,8 @@ pub struct SenderWithContext<T: Clone> {
}
impl<T: Clone> SenderWithContext<T> {
pub fn new(err_ctx: ErrorContext, sender: SenderType<T>) -> Self {
Self { err_ctx, sender }
pub fn new(sender: SenderType<T>) -> Self {
Self { sender }
}
/// Sends an event, along with the current [`ErrorContext`], on this
@ -66,3 +67,9 @@ thread_local!(
/// stack in the form of an [`ErrorContext`].
pub static OPENCALLS: RefCell<ErrorContext> = RefCell::default()
);
task_local! {
/// A key to some task local storage that holds a representation of the task's call
/// stack in the form of an [`ErrorContext`].
static ASYNCOPENCALLS: RefCell<ErrorContext> = RefCell::default()
}

View File

@ -256,7 +256,13 @@ impl ServerOsApi for ServerOsInputOutput {
Box::new((*self).clone())
}
fn kill(&mut self, pid: RawFd) -> Result<(), nix::Error> {
kill(Pid::from_raw(pid), Some(Signal::SIGINT)).unwrap();
// TODO:
// Ideally, we should be using SIGINT rather than SIGKILL here, but there are cases in which
// the terminal we're trying to kill hangs on SIGINT and so all the app gets stuck
// that's why we're sending SIGKILL here
// A better solution would be to send SIGINT here and not wait for it, and then have
// a background thread do the waitpid stuff and send SIGKILL if the process is stuck
kill(Pid::from_raw(pid), Some(Signal::SIGKILL)).unwrap();
waitpid(Pid::from_raw(pid), None).unwrap();
Ok(())
}

View File

@ -6,16 +6,15 @@ use ::std::os::unix::io::RawFd;
use ::std::pin::*;
use ::std::sync::mpsc::Receiver;
use ::std::time::{Duration, Instant};
use ::vte;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use super::{SenderWithContext, OPENCALLS};
use super::SenderWithContext;
use crate::layout::Layout;
use crate::os_input_output::ServerOsApi;
use crate::utils::logging::debug_to_file;
use crate::{
errors::{ContextType, ErrorContext},
errors::{get_current_ctx, ContextType, ErrorContext},
panes::PaneId,
screen::ScreenInstruction,
wasm_vm::PluginInstruction,
@ -67,99 +66,7 @@ impl Stream for ReadFromPid {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VteEvent {
// TODO: try not to allocate Vecs
Print(char),
Execute(u8), // byte
Hook(Vec<i64>, Vec<u8>, bool, char), // params, intermediates, ignore, char
Put(u8), // byte
Unhook,
OscDispatch(Vec<Vec<u8>>, bool), // params, bell_terminated
CsiDispatch(Vec<i64>, Vec<u8>, bool, char), // params, intermediates, ignore, char
EscDispatch(Vec<u8>, bool, u8), // intermediates, ignore, byte
}
struct VteEventSender {
id: RawFd,
send_screen_instructions: SenderWithContext<ScreenInstruction>,
}
impl VteEventSender {
pub fn new(id: RawFd, send_screen_instructions: SenderWithContext<ScreenInstruction>) -> Self {
VteEventSender {
id,
send_screen_instructions,
}
}
}
impl vte::Perform for VteEventSender {
fn print(&mut self, c: char) {
self.send_screen_instructions
.send(ScreenInstruction::Pty(self.id, VteEvent::Print(c)))
.unwrap();
}
fn execute(&mut self, byte: u8) {
self.send_screen_instructions
.send(ScreenInstruction::Pty(self.id, VteEvent::Execute(byte)))
.unwrap();
}
fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
let params = params.iter().copied().collect();
let intermediates = intermediates.iter().copied().collect();
self.send_screen_instructions
.send(ScreenInstruction::Pty(
self.id,
VteEvent::Hook(params, intermediates, ignore, c),
))
.unwrap();
}
fn put(&mut self, byte: u8) {
self.send_screen_instructions
.send(ScreenInstruction::Pty(self.id, VteEvent::Put(byte)))
.unwrap();
}
fn unhook(&mut self) {
self.send_screen_instructions
.send(ScreenInstruction::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_screen_instructions
.send(ScreenInstruction::Pty(
self.id,
VteEvent::OscDispatch(params, bell_terminated),
))
.unwrap();
}
fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
let params = params.iter().copied().collect();
let intermediates = intermediates.iter().copied().collect();
self.send_screen_instructions
.send(ScreenInstruction::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_screen_instructions
.send(ScreenInstruction::Pty(
self.id,
VteEvent::EscDispatch(intermediates, ignore, byte),
))
.unwrap();
}
}
pub type VteBytes = Vec<u8>;
/// Instructions related to PTYs (pseudoterminals).
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -185,18 +92,15 @@ pub struct PtyBus {
fn stream_terminal_bytes(
pid: RawFd,
send_screen_instructions: SenderWithContext<ScreenInstruction>,
os_input: Box<dyn ServerOsApi>,
mut send_screen_instructions: SenderWithContext<ScreenInstruction>,
debug: bool,
) -> JoinHandle<()> {
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
let mut err_ctx = get_current_ctx();
task::spawn({
async move {
err_ctx.add_call(ContextType::AsyncTask);
send_screen_instructions.update(err_ctx);
let mut vte_parser = vte::Parser::new();
let mut vte_event_sender = VteEventSender::new(pid, send_screen_instructions.clone());
let mut terminal_bytes = ReadFromPid::new(&pid, os_input.clone());
let mut terminal_bytes = ReadFromPid::new(&pid, os_input);
let mut last_byte_receive_time: Option<Instant> = None;
let mut pending_render = false;
@ -282,8 +186,8 @@ impl PtyBus {
self.os_input.spawn_terminal(file_to_open);
let task_handle = stream_terminal_bytes(
pid_primary,
self.os_input.clone(),
self.send_screen_instructions.clone(),
self.os_input.clone(),
self.debug_to_file,
);
self.task_handles.insert(pid_primary, task_handle);
@ -308,8 +212,8 @@ impl PtyBus {
for id in new_pane_pids {
let task_handle = stream_terminal_bytes(
id,
self.os_input.clone(),
self.send_screen_instructions.clone(),
self.os_input.clone(),
self.debug_to_file,
);
self.task_handles.insert(id, task_handle);

View File

@ -10,7 +10,7 @@ use std::sync::mpsc::Receiver;
use crate::common::SenderWithContext;
use crate::os_input_output::ServerOsApi;
use crate::panes::PositionAndSize;
use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::pty_bus::{PtyInstruction, VteBytes};
use crate::server::ServerInstruction;
use crate::tab::Tab;
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};

View File

@ -13,7 +13,6 @@ use structopt::StructOpt;
use crate::cli::CliArgs;
use crate::command_is_executing::CommandIsExecuting;
use crate::os_input_output::{get_client_os_input, get_server_os_input, ClientOsApi, ServerOsApi};
use crate::pty_bus::VteEvent;
use crate::utils::{
consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
logging::*,
@ -89,7 +88,7 @@ pub fn start(
opts: CliArgs,
server_os_input: Box<dyn ServerOsApi>,
) {
let ipc_thread = start_server(server_os_input, opts);
start_client(client_os_input);
let ipc_thread = start_server(server_os_input, opts.clone());
start_client(client_os_input, opts);
drop(ipc_thread.join());
}

View File

@ -16,14 +16,13 @@ use zellij_tile::data::{Event, EventType, ModeInfo};
use crate::cli::CliArgs;
use crate::client::ClientInstruction;
use crate::common::pty_bus::VteEvent;
use crate::common::{
errors::{ContextType, ErrorContext, PluginContext, PtyContext, ScreenContext, ServerContext},
errors::{ContextType, PluginContext, PtyContext, ScreenContext, ServerContext},
os_input_output::ServerOsApi,
pty_bus::{PtyBus, PtyInstruction},
pty_bus::{PtyBus, PtyInstruction, VteBytes},
screen::{Screen, ScreenInstruction},
wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginEnv, PluginInstruction},
ChannelWithContext, SenderType, SenderWithContext, OPENCALLS,
ChannelWithContext, SenderType, SenderWithContext,
};
use crate::layout::Layout;
use crate::panes::PaneId;
@ -102,9 +101,6 @@ impl ServerInstruction {
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)
}
@ -171,8 +167,8 @@ impl ServerInstruction {
pub fn change_mode(mode_info: ModeInfo) -> Self {
Self::ToScreen(ScreenInstruction::ChangeMode(mode_info))
}
pub fn pty(fd: RawFd, event: VteEvent) -> Self {
Self::ToScreen(ScreenInstruction::Pty(fd, event))
pub fn pty(fd: RawFd, bytes: VteBytes) -> Self {
Self::ToScreen(ScreenInstruction::PtyBytes(fd, bytes))
}
pub fn terminal_resize(new_size: PositionAndSize) -> Self {
Self::ToScreen(ScreenInstruction::TerminalResize(new_size))
@ -188,14 +184,6 @@ struct ClientMetaData {
wasm_thread: Option<thread::JoinHandle<()>>,
}
impl ClientMetaData {
fn update(&mut self, err_ctx: ErrorContext) {
self.send_plugin_instructions.update(err_ctx);
self.send_screen_instructions.update(err_ctx);
self.send_pty_instructions.update(err_ctx);
}
}
impl Drop for ClientMetaData {
fn drop(&mut self) {
let _ = self.send_pty_instructions.send(PtyInstruction::Exit);
@ -211,18 +199,15 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
let (send_server_instructions, receive_server_instructions): ChannelWithContext<
ServerInstruction,
> = channel();
let send_server_instructions = SenderWithContext::new(
ErrorContext::new(),
SenderType::Sender(send_server_instructions),
);
let send_server_instructions =
SenderWithContext::new(SenderType::Sender(send_server_instructions));
let router_thread = thread::Builder::new()
.name("server_router".to_string())
.spawn({
let os_input = os_input.clone();
let mut send_server_instructions = send_server_instructions.clone();
let send_server_instructions = send_server_instructions.clone();
move || loop {
let (instruction, err_ctx) = os_input.server_recv();
send_server_instructions.update(err_ctx);
let (instruction, _err_ctx) = os_input.server_recv();
match instruction {
ServerInstruction::Exit => break,
_ => {
@ -243,9 +228,6 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
let (instruction, mut err_ctx) = receive_server_instructions.recv().unwrap();
err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
os_input.update_senders(err_ctx);
if let Some(ref c) = client {
clients.get_mut(c).unwrap().update(err_ctx);
}
match instruction {
ServerInstruction::OpenFile(file_name) => {
let path = PathBuf::from(file_name);
@ -269,7 +251,7 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
ServerInstruction::MoveFocus => {
clients[client.as_ref().unwrap()]
.send_screen_instructions
.send(ScreenInstruction::MoveFocus)
.send(ScreenInstruction::FocusNextPane)
.unwrap();
}
ServerInstruction::NewClient(buffer_path, full_screen_ws) => {
@ -340,22 +322,20 @@ fn init_client(
send_server_instructions: SenderWithContext<ServerInstruction>,
full_screen_ws: PositionAndSize,
) -> ClientMetaData {
let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
let (send_screen_instructions, receive_screen_instructions): ChannelWithContext<
ScreenInstruction,
> = channel();
let send_screen_instructions =
SenderWithContext::new(err_ctx, SenderType::Sender(send_screen_instructions));
SenderWithContext::new(SenderType::Sender(send_screen_instructions));
let (send_plugin_instructions, receive_plugin_instructions): ChannelWithContext<
PluginInstruction,
> = channel();
let send_plugin_instructions =
SenderWithContext::new(err_ctx, SenderType::Sender(send_plugin_instructions));
SenderWithContext::new(SenderType::Sender(send_plugin_instructions));
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
channel();
let send_pty_instructions =
SenderWithContext::new(err_ctx, SenderType::Sender(send_pty_instructions));
let send_pty_instructions = SenderWithContext::new(SenderType::Sender(send_pty_instructions));
// Don't use default layouts in tests, but do everywhere else
#[cfg(not(test))]
@ -461,15 +441,24 @@ fn init_client(
.recv()
.expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
screen.send_server_instructions.update(err_ctx);
screen.send_pty_instructions.update(err_ctx);
screen.send_plugin_instructions.update(err_ctx);
match event {
ScreenInstruction::Pty(pid, vte_event) => {
screen
.get_active_tab_mut()
.unwrap()
.handle_pty_event(pid, vte_event);
ScreenInstruction::PtyBytes(pid, vte_bytes) => {
let active_tab = screen.get_active_tab_mut().unwrap();
if active_tab.has_terminal_pid(pid) {
// it's most likely that this event is directed at the active tab
// look there first
active_tab.handle_pty_bytes(pid, vte_bytes);
} else {
// if this event wasn't directed at the active tab, start looking
// in other tabs
let all_tabs = screen.get_tabs_mut();
for tab in all_tabs.values_mut() {
if tab.has_terminal_pid(pid) {
tab.handle_pty_bytes(pid, vte_bytes);
break;
}
}
}
}
ScreenInstruction::Render => {
screen.render();
@ -513,9 +502,15 @@ fn init_client(
ScreenInstruction::ResizeUp => {
screen.get_active_tab_mut().unwrap().resize_up();
}
ScreenInstruction::MoveFocus => {
ScreenInstruction::SwitchFocus => {
screen.get_active_tab_mut().unwrap().move_focus();
}
ScreenInstruction::FocusNextPane => {
screen.get_active_tab_mut().unwrap().focus_next_pane();
}
ScreenInstruction::FocusPreviousPane => {
screen.get_active_tab_mut().unwrap().focus_previous_pane();
}
ScreenInstruction::MoveFocusLeft => {
screen.get_active_tab_mut().unwrap().move_focus_left();
}
@ -646,8 +641,8 @@ fn init_client(
let wasm_thread = thread::Builder::new()
.name("wasm".to_string())
.spawn({
let mut send_screen_instructions = send_screen_instructions.clone();
let mut send_pty_instructions = send_pty_instructions.clone();
let send_screen_instructions = send_screen_instructions.clone();
let send_pty_instructions = send_pty_instructions.clone();
let store = Store::default();
let mut plugin_id = 0;
@ -657,8 +652,6 @@ fn init_client(
.recv()
.expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
send_screen_instructions.update(err_ctx);
send_pty_instructions.update(err_ctx);
match event {
PluginInstruction::Load(pid_tx, path) => {
let project_dirs =

View File

@ -89,12 +89,10 @@ impl FakeInputOutput {
let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone());
let (client_sender, client_receiver): ChannelWithContext<ClientInstruction> =
mpsc::channel();
let client_sender =
SenderWithContext::new(ErrorContext::new(), SenderType::Sender(client_sender));
let client_sender = SenderWithContext::new(SenderType::Sender(client_sender));
let (server_sender, server_receiver): ChannelWithContext<ServerInstruction> =
mpsc::channel();
let server_sender =
SenderWithContext::new(ErrorContext::new(), SenderType::Sender(server_sender));
let server_sender = SenderWithContext::new(SenderType::Sender(server_sender));
win_sizes.insert(0, winsize); // 0 is the current terminal
FakeInputOutput {
@ -198,10 +196,7 @@ impl ClientOsApi for FakeInputOutput {
fn send_to_server(&self, msg: ServerInstruction) {
self.server_sender.send(msg).unwrap();
}
fn update_senders(&mut self, new_ctx: ErrorContext) {
self.server_sender.update(new_ctx);
self.client_sender.update(new_ctx);
}
fn update_senders(&mut self, new_ctx: ErrorContext) {}
fn connect_to_server(&mut self, full_screen_ws: PositionAndSize) {
ClientOsApi::send_to_server(
self,
@ -293,11 +288,5 @@ impl ServerOsApi for FakeInputOutput {
self.client_sender.send(msg).unwrap();
}
fn add_client_sender(&mut self, _buffer_path: String) {}
fn update_senders(&mut self, new_ctx: ErrorContext) {
self.server_sender.update(new_ctx);
self.client_sender.update(new_ctx);
}
fn load_palette(&self) -> Palette {
default_palette()
}
fn update_senders(&mut self, new_ctx: ErrorContext) {}
}