aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrooks J Rady <b.j.rady@gmail.com>2021-03-23 23:57:18 +0000
committerBrooks J Rady <b.j.rady@gmail.com>2021-03-23 23:57:18 +0000
commit23df8e447a1e73b8e3536fbf9781f1aafcee2765 (patch)
treeeb462c458798ca3ff14f79f1e23d4d22c115f456
parentInitial implementation of the update callback + upstream termion (diff)
downloadsl0ppij-23df8e447a1e73b8e3536fbf9781f1aafcee2765.tar.gz
sl0ppij-23df8e447a1e73b8e3536fbf9781f1aafcee2765.tar.xz
sl0ppij-23df8e447a1e73b8e3536fbf9781f1aafcee2765.zip
Move most key handling to the update() + event system
-rw-r--r--default-tiles/strider/src/main.rs67
-rw-r--r--src/client/tab.rs16
-rw-r--r--src/common/errors.rs4
-rw-r--r--src/common/input/handler.rs18
-rw-r--r--src/common/mod.rs76
-rw-r--r--src/common/wasm_vm.rs5
-rw-r--r--zellij-tile/src/data.rs4
-rw-r--r--zellij-tile/src/lib.rs18
8 files changed, 82 insertions, 126 deletions
diff --git a/default-tiles/strider/src/main.rs b/default-tiles/strider/src/main.rs
index 08f44707..c2867fe4 100644
--- a/default-tiles/strider/src/main.rs
+++ b/default-tiles/strider/src/main.rs
@@ -10,6 +10,41 @@ register_tile!(State);
impl ZellijTile for State {
fn load(&mut self) {
refresh_directory(self);
+ subscribe(&[EventType::KeyPress]);
+ }
+
+ fn update(&mut self, event: Event) {
+ if let Event::KeyPress(key) = event {
+ match key {
+ Key::Up | Key::Char('k') => {
+ *self.selected_mut() = self.selected().saturating_sub(1);
+ }
+ Key::Down | Key::Char('j') => {
+ let next = self.selected().saturating_add(1);
+ *self.selected_mut() = min(self.files.len() - 1, next);
+ }
+ Key::Right | Key::Char('\n') | Key::Char('l') => {
+ match self.files[self.selected()].clone() {
+ FsEntry::Dir(p, _) => {
+ self.path = p;
+ refresh_directory(self);
+ }
+ FsEntry::File(p, _) => open_file(&p),
+ }
+ }
+ Key::Left | Key::Char('h') => {
+ self.path.pop();
+ refresh_directory(self);
+ }
+
+ Key::Char('.') => {
+ self.toggle_hidden_files();
+ refresh_directory(self);
+ }
+
+ _ => (),
+ };
+ }
}
fn render(&mut self, rows: usize, cols: usize) {
@@ -38,38 +73,6 @@ impl ZellijTile for State {
}
}
}
-
- fn handle_key(&mut self, key: Key) {
- match key {
- Key::Up | Key::Char('k') => {
- *self.selected_mut() = self.selected().saturating_sub(1);
- }
- Key::Down | Key::Char('j') => {
- let next = self.selected().saturating_add(1);
- *self.selected_mut() = min(self.files.len() - 1, next);
- }
- Key::Right | Key::Char('\n') | Key::Char('l') => {
- match self.files[self.selected()].clone() {
- FsEntry::Dir(p, _) => {
- self.path = p;
- refresh_directory(self);
- }
- FsEntry::File(p, _) => open_file(&p),
- }
- }
- Key::Left | Key::Char('h') => {
- self.path.pop();
- refresh_directory(self);
- }
-
- Key::Char('.') => {
- self.toggle_hidden_files();
- refresh_directory(self);
- }
-
- _ => (),
- };
- }
}
fn refresh_directory(state: &mut State) {
diff --git a/src/client/tab.rs b/src/client/tab.rs
index 1818672b..1a3f411d 100644
--- a/src/client/tab.rs
+++ b/src/client/tab.rs
@@ -1,11 +1,11 @@
//! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size,
//! as well as how they should be resized
-use crate::common::{AppInstruction, SenderWithContext};
+use crate::common::{input::handler::parse_keys, AppInstruction, SenderWithContext};
use crate::layout::Layout;
use crate::panes::{PaneId, PositionAndSize, TerminalPane};
use crate::pty_bus::{PtyInstruction, VteEvent};
-use crate::wasm_vm::{PluginInputType, PluginInstruction};
+use crate::wasm_vm::PluginInstruction;
use crate::{boundaries::Boundaries, panes::PluginPane};
use crate::{os_input_output::OsApi, utils::shared::pad_to_size};
use std::os::unix::io::RawFd;
@@ -14,6 +14,7 @@ use std::{
collections::{BTreeMap, HashSet},
};
use std::{io::Write, sync::mpsc::channel};
+use zellij_tile::data::Event;
const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this
const MIN_TERMINAL_HEIGHT: usize = 2;
@@ -553,12 +554,11 @@ impl Tab {
.expect("failed to drain terminal");
}
Some(PaneId::Plugin(pid)) => {
- self.send_plugin_instructions
- .send(PluginInstruction::Input(
- PluginInputType::Normal(pid),
- input_bytes,
- ))
- .unwrap();
+ for key in parse_keys(&input_bytes) {
+ self.send_plugin_instructions
+ .send(PluginInstruction::Update(Some(pid), Event::KeyPress(key)))
+ .unwrap()
+ }
}
_ => {}
}
diff --git a/src/common/errors.rs b/src/common/errors.rs
index 11d13c7e..b12a57a1 100644
--- a/src/common/errors.rs
+++ b/src/common/errors.rs
@@ -281,7 +281,6 @@ pub enum PluginContext {
Update,
Render,
Input,
- GlobalInput,
Unload,
Quit,
Tabs,
@@ -291,10 +290,9 @@ impl From<&PluginInstruction> for PluginContext {
fn from(plugin_instruction: &PluginInstruction) -> Self {
match *plugin_instruction {
PluginInstruction::Load(..) => PluginContext::Load,
- PluginInstruction::Update(_) => PluginContext::Update,
+ PluginInstruction::Update(..) => PluginContext::Update,
PluginInstruction::Render(..) => PluginContext::Render,
PluginInstruction::Input(..) => PluginContext::Input,
- PluginInstruction::GlobalInput(_) => PluginContext::GlobalInput,
PluginInstruction::Unload(_) => PluginContext::Unload,
PluginInstruction::Quit => PluginContext::Quit,
PluginInstruction::UpdateTabs(..) => PluginContext::Tabs,
diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs
index 90afb64c..4b948cbf 100644
--- a/src/common/input/handler.rs
+++ b/src/common/input/handler.rs
@@ -10,8 +10,8 @@ use crate::screen::ScreenInstruction;
use crate::wasm_vm::{NaughtyEventType, PluginInputType, PluginInstruction};
use crate::CommandIsExecuting;
-use termion::input::TermReadEventsAndRaw;
-use zellij_tile::data::{Event, Help, InputMode, Key};
+use termion::input::{TermRead, TermReadEventsAndRaw};
+use zellij_tile::data::{Help, InputMode, Key};
use super::keybinds::key_to_actions;
@@ -61,19 +61,15 @@ 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())),
- );
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 is a bit of a hack to get resizing to work!
drop(
- self.send_plugin_instructions
- .send(PluginInstruction::Update(Event::KeyPress(key))),
+ self.send_screen_instructions
+ .send(ScreenInstruction::Render),
);
// FIXME this explicit break is needed because the current test
// framework relies on it to not create dead threads that loop
@@ -327,6 +323,10 @@ pub fn input_loop(
.handle_input();
}
+pub fn parse_keys(input_bytes: &[u8]) -> Vec<Key> {
+ input_bytes.keys().flatten().map(cast_termion_key).collect()
+}
+
// 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 {
diff --git a/src/common/mod.rs b/src/common/mod.rs
index 70edcea8..b8a4c671 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -17,6 +17,7 @@ use std::{collections::HashMap, fs};
use std::{
collections::HashSet,
io::Write,
+ str::FromStr,
sync::{Arc, Mutex},
};
@@ -40,7 +41,7 @@ use wasm_vm::{
};
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
use wasmer_wasi::{Pipe, WasiState};
-use zellij_tile::data::{InputMode, Key};
+use zellij_tile::data::{EventType, InputMode, Key};
#[derive(Serialize, Deserialize, Debug)]
pub enum ApiCommand {
@@ -549,16 +550,21 @@ pub fn start(mut os_input: Box<dyn OsApi>, 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::Update(pid, event) => {
+ for (&i, (instance, plugin_env)) in &plugin_map {
+ let subs = plugin_env.subscriptions.lock().unwrap();
+ // FIXME: This is very janky... Maybe I should write my own macro for Event -> EventType?
+ let event_type = EventType::from_str(&event.to_string()).unwrap();
+ if pid.is_none() || pid == Some(i) && subs.contains(&event_type) {
+ let update = instance.exports.get_function("update").unwrap();
+ wasi_write_string(
+ &plugin_env.wasi_env,
+ &serde_json::to_string(&event).unwrap(),
+ );
+ update.call(&[]).unwrap();
+ }
}
+ drop(send_screen_instructions.send(ScreenInstruction::Render));
}
PluginInstruction::Render(buf_tx, pid, rows, cols) => {
let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
@@ -587,11 +593,15 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
}
// FIXME: Deduplicate this with the callback below!
PluginInstruction::Input(input_type, input_bytes) => {
- match input_type {
- PluginInputType::Normal(pid) => {
- let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
- let handle_key =
- instance.exports.get_function("handle_key").unwrap();
+ if let PluginInputType::Event(event) = input_type {
+ for (instance, plugin_env) in plugin_map.values() {
+ if !plugin_env.events.contains(&event) {
+ continue;
+ }
+ let handle_key = instance
+ .exports
+ .get_function(handler_map.get(&event).unwrap())
+ .unwrap();
for key in input_bytes.keys().flatten() {
let key = cast_termion_key(key);
wasi_write_string(
@@ -601,45 +611,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
handle_key.call(&[]).unwrap();
}
}
- PluginInputType::Event(event) => {
- for (instance, plugin_env) in plugin_map.values() {
- if !plugin_env.events.contains(&event) {
- continue;
- }
- let handle_key = instance
- .exports
- .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(),
- );
- handle_key.call(&[]).unwrap();
- }
- }
- }
}
drop(send_screen_instructions.send(ScreenInstruction::Render));
}
- PluginInstruction::GlobalInput(input_bytes) => {
- // FIXME: Set up an event subscription system, and timed callbacks
- for (instance, plugin_env) in plugin_map.values() {
- 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(),
- );
- handler.call(&[]).unwrap();
- }
- }
-
- drop(send_screen_instructions.send(ScreenInstruction::Render));
- }
PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
PluginInstruction::Quit => break,
}
diff --git a/src/common/wasm_vm.rs b/src/common/wasm_vm.rs
index 2f2a0cf6..24b947d6 100644
--- a/src/common/wasm_vm.rs
+++ b/src/common/wasm_vm.rs
@@ -30,10 +30,9 @@ pub enum PluginInputType {
#[derive(Clone, Debug)]
pub enum PluginInstruction {
Load(Sender<u32>, PathBuf, Vec<NaughtyEventType>),
- Update(Event),
+ Update(Option<u32>, Event), // Focused plugin / broadcast, event data
Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
- Input(PluginInputType, Vec<u8>), // plugin id, input bytes
- GlobalInput(Vec<u8>), // input bytes
+ Input(PluginInputType, Vec<u8>), // plugin id, input bytes
Unload(u32),
UpdateTabs(Vec<TabInfo>), // num tabs, active tab
Quit,
diff --git a/zellij-tile/src/data.rs b/zellij-tile/src/data.rs
index abca9994..a6e07983 100644
--- a/zellij-tile/src/data.rs
+++ b/zellij-tile/src/data.rs
@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
-use strum_macros::{EnumDiscriminants, EnumIter, ToString};
+use strum_macros::{EnumDiscriminants, EnumIter, EnumString, ToString};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Key {
@@ -24,7 +24,7 @@ pub enum Key {
}
#[derive(Debug, Clone, EnumDiscriminants, ToString, Serialize, Deserialize)]
-#[strum_discriminants(derive(Hash, Serialize, Deserialize))]
+#[strum_discriminants(derive(EnumString, Hash, Serialize, Deserialize))]
#[strum_discriminants(name(EventType))]
pub enum Event {
ModeUpdate(Help), // FIXME: Rename the `Help` struct
diff --git a/zellij-tile/src/lib.rs b/zellij-tile/src/lib.rs
index eb1b08fb..771edb2d 100644
--- a/zellij-tile/src/lib.rs
+++ b/zellij-tile/src/lib.rs
@@ -10,8 +10,6 @@ pub trait ZellijTile {
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) {}
- fn handle_global_key(&mut self, key: Key) {}
fn update_tabs(&mut self) {}
fn handle_tab_rename_keypress(&mut self, key: Key) {}
}
@@ -46,22 +44,6 @@ macro_rules! register_tile {
}
#[no_mangle]
- pub fn handle_key() {
- STATE.with(|state| {
- state.borrow_mut().handle_key($crate::shim::get_key());
- });
- }
-
- #[no_mangle]
- pub fn handle_global_key() {
- STATE.with(|state| {
- state
- .borrow_mut()
- .handle_global_key($crate::shim::get_key());
- });
- }
-
- #[no_mangle]
pub fn update_tabs() {
STATE.with(|state| {
state.borrow_mut().update_tabs();