diff --git a/Cargo.lock b/Cargo.lock index b618c1c3..bb23c131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1269,12 +1269,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.5" @@ -1290,7 +1284,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" dependencies = [ - "redox_syscall 0.2.5", + "redox_syscall", ] [[package]] @@ -1300,7 +1294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom", - "redox_syscall 0.2.5", + "redox_syscall", ] [[package]] @@ -1621,7 +1615,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand", - "redox_syscall 0.2.5", + "redox_syscall", "remove_dir_all", "winapi", ] @@ -1637,16 +1631,15 @@ dependencies = [ ] [[package]] -name = "termion_temporary_zellij_fork" -version = "1.6.0" +name = "termion" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65175afb01727f72d690bc8b2a2ac411c0243ec43988b7bd96d428301197bed0" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" dependencies = [ "libc", "numtoa", - "redox_syscall 0.1.57", + "redox_syscall", "redox_termios", - "serde", ] [[package]] @@ -2269,7 +2262,7 @@ dependencies = [ "strip-ansi-escapes", "structopt", "strum", - "termion_temporary_zellij_fork", + "termion", "termios", "toml", "unicode-truncate", diff --git a/Cargo.toml b/Cargo.toml index b5266a8c..fec3c7b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ signal-hook = "0.1.10" strip-ansi-escapes = "0.1.0" structopt = "0.3" # termion = { git = "https://gitlab.com/TheLostLambda/termion.git", version = "1.6.0", features = ["serde"] } -termion = { package = "termion_temporary_zellij_fork", version = "1.6.0", features = ["serde"]} +termion = "1.5.0" termios = "0.3" unicode-truncate = "0.2.0" unicode-width = "0.1.8" diff --git a/src/common/errors.rs b/src/common/errors.rs index b5b96342..11d13c7e 100644 --- a/src/common/errors.rs +++ b/src/common/errors.rs @@ -278,6 +278,7 @@ use crate::wasm_vm::PluginInstruction; #[derive(Debug, Clone, Copy, PartialEq)] pub enum PluginContext { Load, + Update, Render, Input, GlobalInput, @@ -290,6 +291,7 @@ impl From<&PluginInstruction> for PluginContext { fn from(plugin_instruction: &PluginInstruction) -> Self { match *plugin_instruction { PluginInstruction::Load(..) => PluginContext::Load, + PluginInstruction::Update(_) => PluginContext::Update, PluginInstruction::Render(..) => PluginContext::Render, PluginInstruction::Input(..) => PluginContext::Input, PluginInstruction::GlobalInput(_) => PluginContext::GlobalInput, diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index 29a504f5..90afb64c 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -11,7 +11,7 @@ use crate::wasm_vm::{NaughtyEventType, PluginInputType, PluginInstruction}; use crate::CommandIsExecuting; use termion::input::TermReadEventsAndRaw; -use zellij_tile::data::{Help, InputMode}; +use zellij_tile::data::{Event, Help, InputMode, Key}; use super::keybinds::key_to_actions; @@ -61,6 +61,7 @@ impl InputHandler { 'input_loop: loop { //@@@ I think this should actually just iterate over stdin directly let stdin_buffer = self.os_input.read_from_stdin(); + // FIXME: Kill me someday (soon) drop( self.send_plugin_instructions .send(PluginInstruction::GlobalInput(stdin_buffer.clone())), @@ -69,6 +70,11 @@ impl InputHandler { match key_result { Ok((event, raw_bytes)) => match event { termion::event::Event::Key(key) => { + let key = cast_termion_key(key); + drop( + self.send_plugin_instructions + .send(PluginInstruction::Update(Event::KeyPress(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 @@ -320,3 +326,31 @@ pub fn input_loop( ) .handle_input(); } + +// FIXME: This is an absolutely cursed function that should be destroyed as soon +// as an alternative that doesn't touch zellij-tile can be developed... +fn cast_termion_key(event: termion::event::Key) -> Key { + match event { + termion::event::Key::Backspace => Key::Backspace, + termion::event::Key::Left => Key::Left, + termion::event::Key::Right => Key::Right, + termion::event::Key::Up => Key::Up, + termion::event::Key::Down => Key::Down, + termion::event::Key::Home => Key::Home, + termion::event::Key::End => Key::End, + termion::event::Key::PageUp => Key::PageUp, + termion::event::Key::PageDown => Key::PageDown, + termion::event::Key::BackTab => Key::BackTab, + termion::event::Key::Delete => Key::Delete, + termion::event::Key::Insert => Key::Insert, + termion::event::Key::F(n) => Key::F(n), + termion::event::Key::Char(c) => Key::Char(c), + termion::event::Key::Alt(c) => Key::Alt(c), + termion::event::Key::Ctrl(c) => Key::Ctrl(c), + termion::event::Key::Null => Key::Null, + termion::event::Key::Esc => Key::Esc, + _ => { + unimplemented!("Encountered an unknown key!") + } + } +} diff --git a/src/common/input/keybinds.rs b/src/common/input/keybinds.rs index 183b9a2c..e48d3115 100644 --- a/src/common/input/keybinds.rs +++ b/src/common/input/keybinds.rs @@ -5,7 +5,6 @@ use super::actions::{Action, Direction}; use std::collections::HashMap; use strum::IntoEnumIterator; -use termion::event::Key; use zellij_tile::data::*; type Keybinds = HashMap; diff --git a/src/common/mod.rs b/src/common/mod.rs index 675fe828..70edcea8 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -40,7 +40,7 @@ use wasm_vm::{ }; use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value}; use wasmer_wasi::{Pipe, WasiState}; -use zellij_tile::data::InputMode; +use zellij_tile::data::{InputMode, Key}; #[derive(Serialize, Deserialize, Debug)] pub enum ApiCommand { @@ -456,6 +456,33 @@ pub fn start(mut os_input: Box, opts: CliArgs) { .collect(); move || loop { + // FIXME: This 100% *must* be destroyed before this makes in into main!!!!!!!!!!! + fn cast_termion_key(event: termion::event::Key) -> Key { + match event { + termion::event::Key::Backspace => Key::Backspace, + termion::event::Key::Left => Key::Left, + termion::event::Key::Right => Key::Right, + termion::event::Key::Up => Key::Up, + termion::event::Key::Down => Key::Down, + termion::event::Key::Home => Key::Home, + termion::event::Key::End => Key::End, + termion::event::Key::PageUp => Key::PageUp, + termion::event::Key::PageDown => Key::PageDown, + termion::event::Key::BackTab => Key::BackTab, + termion::event::Key::Delete => Key::Delete, + termion::event::Key::Insert => Key::Insert, + termion::event::Key::F(n) => Key::F(n), + termion::event::Key::Char(c) => Key::Char(c), + termion::event::Key::Alt(c) => Key::Alt(c), + termion::event::Key::Ctrl(c) => Key::Ctrl(c), + termion::event::Key::Null => Key::Null, + termion::event::Key::Esc => Key::Esc, + _ => { + unimplemented!("Encountered an unknown key!") + } + } + } + let (event, mut err_ctx) = receive_plugin_instructions .recv() .expect("failed to receive event on channel"); @@ -522,6 +549,17 @@ pub fn start(mut os_input: Box, opts: CliArgs) { pid_tx.send(plugin_id).unwrap(); plugin_id += 1; } + PluginInstruction::Update(event) => { + for (instance, plugin_env) in plugin_map.values() { + let update = instance.exports.get_function("update").unwrap(); + + wasi_write_string( + &plugin_env.wasi_env, + &serde_json::to_string(&event).unwrap(), + ); + update.call(&[]).unwrap(); + } + } PluginInstruction::Render(buf_tx, pid, rows, cols) => { let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); @@ -555,6 +593,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { let handle_key = instance.exports.get_function("handle_key").unwrap(); for key in input_bytes.keys().flatten() { + let key = cast_termion_key(key); wasi_write_string( &plugin_env.wasi_env, &serde_json::to_string(&key).unwrap(), @@ -572,6 +611,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { .get_function(handler_map.get(&event).unwrap()) .unwrap(); for key in input_bytes.keys().flatten() { + let key = cast_termion_key(key); wasi_write_string( &plugin_env.wasi_env, &serde_json::to_string(&key).unwrap(), @@ -589,6 +629,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { let handler = instance.exports.get_function("handle_global_key").unwrap(); for key in input_bytes.keys().flatten() { + let key = cast_termion_key(key); wasi_write_string( &plugin_env.wasi_env, &serde_json::to_string(&key).unwrap(), diff --git a/src/common/wasm_vm.rs b/src/common/wasm_vm.rs index 788219a4..2f2a0cf6 100644 --- a/src/common/wasm_vm.rs +++ b/src/common/wasm_vm.rs @@ -9,7 +9,7 @@ use std::{ }; use wasmer::{imports, Function, ImportObject, Store, WasmerEnv}; use wasmer_wasi::WasiEnv; -use zellij_tile::data::{EventType, TabInfo}; +use zellij_tile::data::{Event, EventType, TabInfo}; use super::{ input::handler::get_help, pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction, @@ -30,6 +30,7 @@ pub enum PluginInputType { #[derive(Clone, Debug)] pub enum PluginInstruction { Load(Sender, PathBuf, Vec), + Update(Event), Render(Sender, u32, usize, usize), // String buffer, plugin id, rows, cols Input(PluginInputType, Vec), // plugin id, input bytes GlobalInput(Vec), // input bytes diff --git a/zellij-tile/src/data.rs b/zellij-tile/src/data.rs index 2a03b94c..abca9994 100644 --- a/zellij-tile/src/data.rs +++ b/zellij-tile/src/data.rs @@ -23,7 +23,7 @@ pub enum Key { Esc, } -#[derive(Debug, EnumDiscriminants, ToString, Serialize, Deserialize)] +#[derive(Debug, Clone, EnumDiscriminants, ToString, Serialize, Deserialize)] #[strum_discriminants(derive(Hash, Serialize, Deserialize))] #[strum_discriminants(name(EventType))] pub enum Event { diff --git a/zellij-tile/src/lib.rs b/zellij-tile/src/lib.rs index 6adc9f6d..eb1b08fb 100644 --- a/zellij-tile/src/lib.rs +++ b/zellij-tile/src/lib.rs @@ -7,6 +7,7 @@ use data::*; #[allow(unused_variables)] pub trait ZellijTile { fn load(&mut self) {} + fn update(&mut self, event: Event) {} fn render(&mut self, rows: usize, cols: usize) {} // FIXME: Everything below this line should be purged fn handle_key(&mut self, key: Key) {} @@ -28,6 +29,15 @@ macro_rules! register_tile { }); } + #[no_mangle] + pub fn update() { + STATE.with(|state| { + state + .borrow_mut() + .update($crate::shim::deserialize_from_stdin().unwrap()); + }); + } + #[no_mangle] pub fn render(rows: i32, cols: i32) { STATE.with(|state| { diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index 3681e9ba..e0e65490 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -45,7 +45,9 @@ pub fn get_tabs() -> Vec { deserialize_from_stdin().unwrap_or_default() } -fn deserialize_from_stdin() -> Option { +#[doc(hidden)] +// FIXME: Make this just return T and do a .unwrap() at the end; also naming? +pub fn deserialize_from_stdin() -> Option { let mut json = String::new(); io::stdin().read_line(&mut json).unwrap(); serde_json::from_str(&json).ok()