Add event subscription tracking
This commit is contained in:
parent
06bce9a1fd
commit
e9ab81850e
10 changed files with 85 additions and 40 deletions
18
build-all.sh
18
build-all.sh
|
|
@ -1,29 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
total=6
|
||||
total=5
|
||||
|
||||
# This is temporary while https://github.com/rust-lang/cargo/issues/7004 is open
|
||||
|
||||
echo "Building zellij-tile (1/$total)..."
|
||||
cd zellij-tile
|
||||
echo "Building status-bar (1/$total)..."
|
||||
cd default-tiles/status-bar
|
||||
cargo build --release --target-dir ../../target
|
||||
|
||||
echo "Building status-bar (2/$total)..."
|
||||
cd ../default-tiles/status-bar
|
||||
cargo build --release --target-dir ../../target
|
||||
|
||||
echo "Building strider (3/$total)..."
|
||||
echo "Building strider (2/$total)..."
|
||||
cd ../strider
|
||||
cargo build --release --target-dir ../../target
|
||||
|
||||
echo "Building tab-bar (4/$total)..."
|
||||
echo "Building tab-bar (3/$total)..."
|
||||
cd ../tab-bar
|
||||
cargo build --release --target-dir ../../target
|
||||
|
||||
echo "Optimising WASM executables (5/$total)..."
|
||||
echo "Optimising WASM executables (4/$total)..."
|
||||
cd ../..
|
||||
wasm-opt -O target/wasm32-wasi/release/status-bar.wasm -o target/status-bar.wasm || cp target/wasm32-wasi/release/status-bar.wasm target/status-bar.wasm
|
||||
wasm-opt -O target/wasm32-wasi/release/strider.wasm -o target/strider.wasm || cp target/wasm32-wasi/release/strider.wasm target/strider.wasm
|
||||
wasm-opt -O target/wasm32-wasi/release/tab-bar.wasm -o target/tab-bar.wasm || cp target/wasm32-wasi/release/tab-bar.wasm target/tab-bar.wasm
|
||||
echo "Building zellij (6/$total)..."
|
||||
echo "Building zellij (5/$total)..."
|
||||
cargo build --target-dir target $@
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl Default for BarMode {
|
|||
struct State {
|
||||
active_tab_index: usize,
|
||||
num_tabs: usize,
|
||||
tabs: Vec<TabData>,
|
||||
tabs: Vec<TabInfo>,
|
||||
mode: BarMode,
|
||||
new_name: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{fs::File, io::prelude::*};
|
||||
|
||||
use crate::common::wasm_vm::EventType;
|
||||
use crate::common::wasm_vm::NaughtyEventType;
|
||||
use crate::panes::PositionAndSize;
|
||||
|
||||
fn split_space_to_parts_vertically(
|
||||
|
|
@ -182,7 +182,7 @@ pub struct Layout {
|
|||
#[serde(default)]
|
||||
pub expansion_boundary: bool,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub events: Vec<EventType>,
|
||||
pub events: Vec<NaughtyEventType>,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ impl Display for ContextType {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Just deriving EnumDiscriminants from strum will remove the need for any of this!!!
|
||||
/// Stack call representations corresponding to the different types of [`ScreenInstruction`]s.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ScreenContext {
|
||||
|
|
@ -201,6 +202,7 @@ pub enum ScreenContext {
|
|||
UpdateTabName,
|
||||
}
|
||||
|
||||
// FIXME: Just deriving EnumDiscriminants from strum will remove the need for any of this!!!
|
||||
impl From<&ScreenInstruction> for ScreenContext {
|
||||
fn from(screen_instruction: &ScreenInstruction) -> Self {
|
||||
match *screen_instruction {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::errors::ContextType;
|
|||
use crate::os_input_output::OsApi;
|
||||
use crate::pty_bus::PtyInstruction;
|
||||
use crate::screen::ScreenInstruction;
|
||||
use crate::wasm_vm::{EventType, PluginInputType, PluginInstruction};
|
||||
use crate::wasm_vm::{NaughtyEventType, PluginInputType, PluginInstruction};
|
||||
use crate::CommandIsExecuting;
|
||||
|
||||
use termion::input::TermReadEventsAndRaw;
|
||||
|
|
@ -234,7 +234,7 @@ impl InputHandler {
|
|||
Action::TabNameInput(c) => {
|
||||
self.send_plugin_instructions
|
||||
.send(PluginInstruction::Input(
|
||||
PluginInputType::Event(EventType::Tab),
|
||||
PluginInputType::Event(NaughtyEventType::Tab),
|
||||
c.clone(),
|
||||
))
|
||||
.unwrap();
|
||||
|
|
@ -245,7 +245,7 @@ impl InputHandler {
|
|||
Action::SaveTabName => {
|
||||
self.send_plugin_instructions
|
||||
.send(PluginInstruction::Input(
|
||||
PluginInputType::Event(EventType::Tab),
|
||||
PluginInputType::Event(NaughtyEventType::Tab),
|
||||
vec![b'\n'],
|
||||
))
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -9,12 +9,16 @@ pub mod screen;
|
|||
pub mod utils;
|
||||
pub mod wasm_vm;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::{cell::RefCell, sync::mpsc::TrySendError};
|
||||
use std::{collections::HashMap, fs};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
io::Write,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::cli::CliArgs;
|
||||
use crate::layout::Layout;
|
||||
|
|
@ -31,7 +35,8 @@ use termion::input::TermRead;
|
|||
use utils::consts::{ZELLIJ_IPC_PIPE, ZELLIJ_ROOT_PLUGIN_DIR};
|
||||
use wasm_vm::PluginEnv;
|
||||
use wasm_vm::{
|
||||
wasi_stdout, wasi_write_string, zellij_imports, EventType, PluginInputType, PluginInstruction,
|
||||
wasi_stdout, wasi_write_string, zellij_imports, NaughtyEventType, PluginInputType,
|
||||
PluginInstruction,
|
||||
};
|
||||
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
|
||||
use wasmer_wasi::{Pipe, WasiState};
|
||||
|
|
@ -442,8 +447,10 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
|||
let store = Store::default();
|
||||
let mut plugin_id = 0;
|
||||
let mut plugin_map = HashMap::new();
|
||||
let handler_map: HashMap<EventType, String> =
|
||||
[(EventType::Tab, "handle_tab_rename_keypress".to_string())]
|
||||
let handler_map: HashMap<NaughtyEventType, String> = [(
|
||||
NaughtyEventType::Tab,
|
||||
"handle_tab_rename_keypress".to_string(),
|
||||
)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
|
|
@ -499,6 +506,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
|||
send_screen_instructions: send_screen_instructions.clone(),
|
||||
send_app_instructions: send_app_instructions.clone(),
|
||||
wasi_env,
|
||||
subscriptions: Arc::new(Mutex::new(HashSet::new())),
|
||||
events,
|
||||
};
|
||||
|
||||
|
|
@ -526,7 +534,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
|||
}
|
||||
PluginInstruction::UpdateTabs(mut tabs) => {
|
||||
for (instance, plugin_env) in plugin_map.values() {
|
||||
if !plugin_env.events.contains(&EventType::Tab) {
|
||||
if !plugin_env.events.contains(&NaughtyEventType::Tab) {
|
||||
continue;
|
||||
}
|
||||
let handler = instance.exports.get_function("update_tabs").unwrap();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use crate::tab::Tab;
|
|||
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};
|
||||
use crate::{layout::Layout, panes::PaneId};
|
||||
|
||||
use zellij_tile::data::TabData;
|
||||
use zellij_tile::data::TabInfo;
|
||||
|
||||
/// Instructions that can be sent to the [`Screen`].
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -272,7 +272,7 @@ impl Screen {
|
|||
let mut tab_data = vec![];
|
||||
let active_tab_index = self.active_tab_index.unwrap();
|
||||
for tab in self.tabs.values() {
|
||||
tab_data.push(TabData {
|
||||
tab_data.push(TabInfo {
|
||||
position: tab.position,
|
||||
name: tab.name.clone(),
|
||||
active: active_tab_index == tab.index,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
path::PathBuf,
|
||||
sync::mpsc::{channel, Sender},
|
||||
sync::{
|
||||
mpsc::{channel, Sender},
|
||||
Arc, Mutex,
|
||||
},
|
||||
};
|
||||
use wasmer::{imports, Function, ImportObject, Store, WasmerEnv};
|
||||
use wasmer_wasi::WasiEnv;
|
||||
use zellij_tile::data::TabData;
|
||||
use zellij_tile::data::{EventType, TabInfo};
|
||||
|
||||
use super::{
|
||||
input::handler::get_help, pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction,
|
||||
|
|
@ -13,24 +17,24 @@ use super::{
|
|||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize, Deserialize)]
|
||||
pub enum EventType {
|
||||
pub enum NaughtyEventType {
|
||||
Tab,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PluginInputType {
|
||||
Normal(u32),
|
||||
Event(EventType),
|
||||
Event(NaughtyEventType),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PluginInstruction {
|
||||
Load(Sender<u32>, PathBuf, Vec<EventType>),
|
||||
Load(Sender<u32>, PathBuf, Vec<NaughtyEventType>),
|
||||
Draw(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
|
||||
Input(PluginInputType, Vec<u8>), // plugin id, input bytes
|
||||
GlobalInput(Vec<u8>), // input bytes
|
||||
Unload(u32),
|
||||
UpdateTabs(Vec<TabData>), // num tabs, active tab
|
||||
UpdateTabs(Vec<TabInfo>), // num tabs, active tab
|
||||
Quit,
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +45,8 @@ pub struct PluginEnv {
|
|||
pub send_app_instructions: SenderWithContext<AppInstruction>,
|
||||
pub send_pty_instructions: SenderWithContext<PtyInstruction>, // FIXME: This should be a big bundle of all of the channels
|
||||
pub wasi_env: WasiEnv,
|
||||
pub events: Vec<EventType>,
|
||||
pub subscriptions: Arc<Mutex<HashSet<EventType>>>,
|
||||
pub events: Vec<NaughtyEventType>, // FIXME: Murder this very soon (should not survive into main)
|
||||
}
|
||||
|
||||
// Plugin API ---------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -49,6 +54,8 @@ pub struct PluginEnv {
|
|||
pub fn zellij_imports(store: &Store, plugin_env: &PluginEnv) -> ImportObject {
|
||||
imports! {
|
||||
"zellij" => {
|
||||
"host_subscribe" => Function::new_native_with_env(store, plugin_env.clone(), host_subscribe),
|
||||
"host_unsubscribe" => Function::new_native_with_env(store, plugin_env.clone(), host_unsubscribe),
|
||||
"host_open_file" => Function::new_native_with_env(store, plugin_env.clone(), host_open_file),
|
||||
"host_set_invisible_borders" => Function::new_native_with_env(store, plugin_env.clone(), host_set_invisible_borders),
|
||||
"host_set_max_height" => Function::new_native_with_env(store, plugin_env.clone(), host_set_max_height),
|
||||
|
|
@ -58,7 +65,18 @@ pub fn zellij_imports(store: &Store, plugin_env: &PluginEnv) -> ImportObject {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Bundle up all of the channels! Pair that with WasiEnv?
|
||||
fn host_subscribe(plugin_env: &PluginEnv) {
|
||||
let mut subscriptions = plugin_env.subscriptions.lock().unwrap();
|
||||
let new: HashSet<EventType> = serde_json::from_str(&wasi_stdout(&plugin_env.wasi_env)).unwrap();
|
||||
subscriptions.extend(new);
|
||||
}
|
||||
|
||||
fn host_unsubscribe(plugin_env: &PluginEnv) {
|
||||
let mut subscriptions = plugin_env.subscriptions.lock().unwrap();
|
||||
let old: HashSet<EventType> = serde_json::from_str(&wasi_stdout(&plugin_env.wasi_env)).unwrap();
|
||||
subscriptions.retain(|k| !old.contains(k));
|
||||
}
|
||||
|
||||
fn host_open_file(plugin_env: &PluginEnv) {
|
||||
let path = PathBuf::from(wasi_stdout(&plugin_env.wasi_env).lines().next().unwrap());
|
||||
plugin_env
|
||||
|
|
@ -67,7 +85,6 @@ fn host_open_file(plugin_env: &PluginEnv) {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
// FIXME: Think about these naming conventions – should everything be prefixed by 'host'?
|
||||
fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) {
|
||||
let selectable = selectable != 0;
|
||||
plugin_env
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::EnumIter;
|
||||
use strum_macros::{EnumDiscriminants, EnumIter, ToString};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Key {
|
||||
|
|
@ -23,6 +23,15 @@ pub enum Key {
|
|||
Esc,
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumDiscriminants, ToString, Serialize, Deserialize)]
|
||||
#[strum_discriminants(derive(Hash, Serialize, Deserialize))]
|
||||
#[strum_discriminants(name(EventType))]
|
||||
pub enum Event {
|
||||
ModeUpdate(Help), // FIXME: Rename the `Help` struct
|
||||
TabUpdate(TabInfo),
|
||||
KeyPress(Key),
|
||||
}
|
||||
|
||||
/// Describes the different input modes, which change the way that keystrokes will be interpreted.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, EnumIter, Serialize, Deserialize)]
|
||||
pub enum InputMode {
|
||||
|
|
@ -56,11 +65,12 @@ impl Default for InputMode {
|
|||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Help {
|
||||
pub mode: InputMode,
|
||||
// FIXME: This should probably return Keys and Actions, then sort out strings plugin-side
|
||||
pub keybinds: Vec<(String, String)>, // <shortcut> => <shortcut description>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct TabData {
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
||||
pub struct TabInfo {
|
||||
/* subset of fields to publish to plugins */
|
||||
pub position: usize,
|
||||
pub name: String,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@ pub fn get_key() -> Key {
|
|||
deserialize_from_stdin().unwrap()
|
||||
}
|
||||
|
||||
pub fn subscribe(event_types: &[EventType]) {
|
||||
println!("{}", serde_json::to_string(event_types).unwrap());
|
||||
unsafe { host_subscribe() };
|
||||
}
|
||||
|
||||
pub fn unsubscribe(event_types: &[EventType]) {
|
||||
println!("{}", serde_json::to_string(event_types).unwrap());
|
||||
unsafe { host_unsubscribe() };
|
||||
}
|
||||
|
||||
pub fn open_file(path: &Path) {
|
||||
println!("{}", path.to_string_lossy());
|
||||
unsafe { host_open_file() };
|
||||
|
|
@ -31,7 +41,7 @@ pub fn get_help() -> Help {
|
|||
deserialize_from_stdin().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn get_tabs() -> Vec<TabData> {
|
||||
pub fn get_tabs() -> Vec<TabInfo> {
|
||||
deserialize_from_stdin().unwrap_or_default()
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +53,8 @@ fn deserialize_from_stdin<T: DeserializeOwned>() -> Option<T> {
|
|||
|
||||
#[link(wasm_import_module = "zellij")]
|
||||
extern "C" {
|
||||
fn host_subscribe();
|
||||
fn host_unsubscribe();
|
||||
fn host_open_file();
|
||||
fn host_set_max_height(max_height: i32);
|
||||
fn host_set_selectable(selectable: i32);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue