Wrap up the plugin system refactor, running everything through update()

This commit is contained in:
Brooks J Rady 2021-03-25 17:22:10 +00:00
parent 84a5cf95d1
commit b6f945da35
16 changed files with 121 additions and 307 deletions

View file

@ -5,8 +5,6 @@ parts:
split_size: split_size:
Fixed: 1 Fixed: 1
plugin: tab-bar plugin: tab-bar
events:
- Tab
- direction: Vertical - direction: Vertical
expansion_boundary: true expansion_boundary: true
- direction: Vertical - direction: Vertical

View file

@ -5,8 +5,6 @@ parts:
split_size: split_size:
Fixed: 1 Fixed: 1
plugin: tab-bar plugin: tab-bar
events:
- Tab
- direction: Vertical - direction: Vertical
parts: parts:
- direction: Horizontal - direction: Horizontal

View file

@ -12,23 +12,10 @@ pub struct LinePart {
len: usize, len: usize,
} }
#[derive(PartialEq)]
enum BarMode {
Normal,
Rename,
}
impl Default for BarMode {
fn default() -> Self {
BarMode::Normal
}
}
#[derive(Default)] #[derive(Default)]
struct State { struct State {
tabs: Vec<TabInfo>, tabs: Vec<TabInfo>,
mode: BarMode, mode: InputMode,
new_name: String,
} }
static ARROW_SEPARATOR: &str = ""; static ARROW_SEPARATOR: &str = "";
@ -51,12 +38,14 @@ impl ZellijTile for State {
set_selectable(false); set_selectable(false);
set_invisible_borders(true); set_invisible_borders(true);
set_max_height(1); set_max_height(1);
subscribe(&[EventType::TabUpdate]); subscribe(&[EventType::TabUpdate, EventType::ModeUpdate]);
} }
fn update(&mut self, event: Event) { fn update(&mut self, event: Event) {
if let Event::TabUpdate(tabs) = event { match event {
self.tabs = tabs; Event::ModeUpdate(mode_info) => self.mode = mode_info.mode,
Event::TabUpdate(tabs) => self.tabs = tabs,
_ => unimplemented!(), // FIXME: This should be unreachable, but this could be cleaner
} }
} }
@ -68,11 +57,9 @@ impl ZellijTile for State {
let mut active_tab_index = 0; let mut active_tab_index = 0;
for t in self.tabs.iter_mut() { for t in self.tabs.iter_mut() {
let mut tabname = t.name.clone(); let mut tabname = t.name.clone();
if t.active && self.mode == BarMode::Rename { if t.active && self.mode == InputMode::RenameTab {
if self.new_name.is_empty() { if tabname.is_empty() {
tabname = String::from("Enter name..."); tabname = String::from("Enter name...");
} else {
tabname = self.new_name.clone();
} }
active_tab_index = t.position; active_tab_index = t.position;
} else if t.active { } else if t.active {
@ -88,19 +75,4 @@ impl ZellijTile for State {
} }
println!("{}\u{1b}[48;5;238m\u{1b}[0K", s); println!("{}\u{1b}[48;5;238m\u{1b}[0K", s);
} }
fn handle_tab_rename_keypress(&mut self, key: Key) {
self.mode = BarMode::Rename;
match key {
Key::Char('\n') | Key::Esc => {
self.mode = BarMode::Normal;
self.new_name.clear();
}
Key::Char(c) => self.new_name = format!("{}{}", self.new_name, c),
Key::Backspace | Key::Delete => {
self.new_name.pop();
}
_ => {}
}
}
} }

View file

@ -1,10 +1,8 @@
use crate::utils::consts::ZELLIJ_ROOT_LAYOUT_DIR;
use directories_next::ProjectDirs; use directories_next::ProjectDirs;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::{fs::File, io::prelude::*}; use std::{fs::File, io::prelude::*};
use crate::common::wasm_vm::NaughtyEventType;
use crate::panes::PositionAndSize; use crate::panes::PositionAndSize;
fn split_space_to_parts_vertically( fn split_space_to_parts_vertically(
@ -181,19 +179,15 @@ pub struct Layout {
pub plugin: Option<PathBuf>, pub plugin: Option<PathBuf>,
#[serde(default)] #[serde(default)]
pub expansion_boundary: bool, pub expansion_boundary: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub events: Vec<NaughtyEventType>,
} }
impl Layout { impl Layout {
pub fn new(layout_path: PathBuf) -> Self { pub fn new(layout_path: PathBuf) -> Self {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let layout_dir = project_dirs.data_dir().join("layouts/"); let layout_dir = project_dirs.data_dir().join("layouts/");
let root_layout_dir = Path::new(ZELLIJ_ROOT_LAYOUT_DIR);
let mut layout_file = File::open(&layout_path) let mut layout_file = File::open(&layout_path)
.or_else(|_| File::open(&layout_path.with_extension("yaml"))) .or_else(|_| File::open(&layout_path.with_extension("yaml")))
.or_else(|_| File::open(&layout_dir.join(&layout_path).with_extension("yaml"))) .or_else(|_| File::open(&layout_dir.join(&layout_path).with_extension("yaml")))
.or_else(|_| File::open(root_layout_dir.join(&layout_path).with_extension("yaml")))
.unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display())); .unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display()));
let mut layout = String::new(); let mut layout = String::new();

View file

@ -258,11 +258,7 @@ impl Tab {
if let Some(plugin) = &layout.plugin { if let Some(plugin) = &layout.plugin {
let (pid_tx, pid_rx) = channel(); let (pid_tx, pid_rx) = channel();
self.send_plugin_instructions self.send_plugin_instructions
.send(PluginInstruction::Load( .send(PluginInstruction::Load(pid_tx, plugin.clone()))
pid_tx,
plugin.clone(),
layout.events.clone(),
))
.unwrap(); .unwrap();
let pid = pid_rx.recv().unwrap(); let pid = pid_rx.recv().unwrap();
let new_plugin = PluginPane::new( let new_plugin = PluginPane::new(
@ -301,7 +297,6 @@ impl Tab {
self.toggle_active_pane_fullscreen(); self.toggle_active_pane_fullscreen();
} }
if !self.has_panes() { if !self.has_panes() {
// FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd( self.os_api.set_terminal_size_using_fd(
@ -352,7 +347,6 @@ impl Tab {
if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns() if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns()
&& terminal_to_split.rows() > terminal_to_split.min_height() * 2 && terminal_to_split.rows() > terminal_to_split.min_height() * 2
{ {
// FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws); let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize); let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
@ -373,7 +367,6 @@ impl Tab {
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
} else if terminal_to_split.columns() > terminal_to_split.min_width() * 2 { } else if terminal_to_split.columns() > terminal_to_split.min_width() * 2 {
// FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws); let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, right_winsize); let new_terminal = TerminalPane::new(term_pid, right_winsize);
@ -403,7 +396,6 @@ impl Tab {
self.toggle_active_pane_fullscreen(); self.toggle_active_pane_fullscreen();
} }
if !self.has_panes() { if !self.has_panes() {
// FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd( self.os_api.set_terminal_size_using_fd(
@ -414,47 +406,44 @@ impl Tab {
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
} else { } else if let PaneId::Terminal(term_pid) = pid {
// FIXME: This could use a second look // TODO: check minimum size of active terminal
if let PaneId::Terminal(term_pid) = pid { let active_pane_id = &self.get_active_pane_id().unwrap();
// TODO: check minimum size of active terminal let active_pane = self.panes.get_mut(active_pane_id).unwrap();
let active_pane_id = &self.get_active_pane_id().unwrap(); if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 {
let active_pane = self.panes.get_mut(active_pane_id).unwrap(); self.send_pty_instructions
if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 { .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
self.send_pty_instructions .unwrap();
.send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty return;
.unwrap();
return;
}
let terminal_ws = PositionAndSize {
x: active_pane.x(),
y: active_pane.y(),
rows: active_pane.rows(),
columns: active_pane.columns(),
};
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
active_pane.change_pos_and_size(&top_winsize);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
self.os_api.set_terminal_size_using_fd(
new_terminal.pid,
bottom_winsize.columns as u16,
bottom_winsize.rows as u16,
);
self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
*active_terminal_pid,
top_winsize.columns as u16,
top_winsize.rows as u16,
);
}
self.active_terminal = Some(pid);
self.render();
} }
let terminal_ws = PositionAndSize {
x: active_pane.x(),
y: active_pane.y(),
rows: active_pane.rows(),
columns: active_pane.columns(),
};
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
active_pane.change_pos_and_size(&top_winsize);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
self.os_api.set_terminal_size_using_fd(
new_terminal.pid,
bottom_winsize.columns as u16,
bottom_winsize.rows as u16,
);
self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
*active_terminal_pid,
top_winsize.columns as u16,
top_winsize.rows as u16,
);
}
self.active_terminal = Some(pid);
self.render();
} }
} }
pub fn vertical_split(&mut self, pid: PaneId) { pub fn vertical_split(&mut self, pid: PaneId) {
@ -463,7 +452,6 @@ impl Tab {
self.toggle_active_pane_fullscreen(); self.toggle_active_pane_fullscreen();
} }
if !self.has_panes() { if !self.has_panes() {
// FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd( self.os_api.set_terminal_size_using_fd(
@ -474,47 +462,44 @@ impl Tab {
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
} else { } else if let PaneId::Terminal(term_pid) = pid {
// FIXME: This could use a second look // TODO: check minimum size of active terminal
if let PaneId::Terminal(term_pid) = pid { let active_pane_id = &self.get_active_pane_id().unwrap();
// TODO: check minimum size of active terminal let active_pane = self.panes.get_mut(active_pane_id).unwrap();
let active_pane_id = &self.get_active_pane_id().unwrap(); if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 {
let active_pane = self.panes.get_mut(active_pane_id).unwrap(); self.send_pty_instructions
if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 { .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
self.send_pty_instructions .unwrap();
.send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty return;
.unwrap();
return;
}
let terminal_ws = PositionAndSize {
x: active_pane.x(),
y: active_pane.y(),
rows: active_pane.rows(),
columns: active_pane.columns(),
};
let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws);
active_pane.change_pos_and_size(&left_winsize);
let new_terminal = TerminalPane::new(term_pid, right_winsize);
self.os_api.set_terminal_size_using_fd(
new_terminal.pid,
right_winsize.columns as u16,
right_winsize.rows as u16,
);
self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
*active_terminal_pid,
left_winsize.columns as u16,
left_winsize.rows as u16,
);
}
self.active_terminal = Some(pid);
self.render();
} }
let terminal_ws = PositionAndSize {
x: active_pane.x(),
y: active_pane.y(),
rows: active_pane.rows(),
columns: active_pane.columns(),
};
let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws);
active_pane.change_pos_and_size(&left_winsize);
let new_terminal = TerminalPane::new(term_pid, right_winsize);
self.os_api.set_terminal_size_using_fd(
new_terminal.pid,
right_winsize.columns as u16,
right_winsize.rows as u16,
);
self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
*active_terminal_pid,
left_winsize.columns as u16,
left_winsize.rows as u16,
);
}
self.active_terminal = Some(pid);
self.render();
} }
} }
pub fn get_active_pane(&self) -> Option<&dyn Pane> { pub fn get_active_pane(&self) -> Option<&dyn Pane> {
@ -1680,6 +1665,7 @@ impl Tab {
self.reduce_pane_and_surroundings_right(&active_pane_id, count); self.reduce_pane_and_surroundings_right(&active_pane_id, count);
} }
} }
self.render();
} }
pub fn resize_left(&mut self) { pub fn resize_left(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much // TODO: find out by how much we actually reduced and only reduce by that much
@ -1691,6 +1677,7 @@ impl Tab {
self.reduce_pane_and_surroundings_left(&active_pane_id, count); self.reduce_pane_and_surroundings_left(&active_pane_id, count);
} }
} }
self.render();
} }
pub fn resize_down(&mut self) { pub fn resize_down(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much // TODO: find out by how much we actually reduced and only reduce by that much
@ -1702,6 +1689,7 @@ impl Tab {
self.reduce_pane_and_surroundings_down(&active_pane_id, count); self.reduce_pane_and_surroundings_down(&active_pane_id, count);
} }
} }
self.render();
} }
pub fn resize_up(&mut self) { pub fn resize_up(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much // TODO: find out by how much we actually reduced and only reduce by that much
@ -1713,6 +1701,7 @@ impl Tab {
self.reduce_pane_and_surroundings_up(&active_pane_id, count); self.reduce_pane_and_surroundings_up(&active_pane_id, count);
} }
} }
self.render();
} }
pub fn move_focus(&mut self) { pub fn move_focus(&mut self) {
if !self.has_selectable_panes() { if !self.has_selectable_panes() {

View file

@ -282,7 +282,6 @@ pub enum PluginContext {
Load, Load,
Update, Update,
Render, Render,
Input,
Unload, Unload,
Quit, Quit,
} }
@ -293,7 +292,6 @@ impl From<&PluginInstruction> for PluginContext {
PluginInstruction::Load(..) => PluginContext::Load, PluginInstruction::Load(..) => PluginContext::Load,
PluginInstruction::Update(..) => PluginContext::Update, PluginInstruction::Update(..) => PluginContext::Update,
PluginInstruction::Render(..) => PluginContext::Render, PluginInstruction::Render(..) => PluginContext::Render,
PluginInstruction::Input(..) => PluginContext::Input,
PluginInstruction::Unload(_) => PluginContext::Unload, PluginInstruction::Unload(_) => PluginContext::Unload,
PluginInstruction::Quit => PluginContext::Quit, PluginInstruction::Quit => PluginContext::Quit,
} }

View file

@ -49,5 +49,4 @@ pub enum Action {
CloseTab, CloseTab,
GoToTab(u32), GoToTab(u32),
TabNameInput(Vec<u8>), TabNameInput(Vec<u8>),
SaveTabName,
} }

View file

@ -7,7 +7,7 @@ use crate::errors::ContextType;
use crate::os_input_output::OsApi; use crate::os_input_output::OsApi;
use crate::pty_bus::PtyInstruction; use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction; use crate::screen::ScreenInstruction;
use crate::wasm_vm::{NaughtyEventType, PluginInputType, PluginInstruction}; use crate::wasm_vm::PluginInstruction;
use crate::CommandIsExecuting; use crate::CommandIsExecuting;
use termion::input::{TermRead, TermReadEventsAndRaw}; use termion::input::{TermRead, TermReadEventsAndRaw};
@ -66,11 +66,6 @@ impl InputHandler {
Ok((event, raw_bytes)) => match event { Ok((event, raw_bytes)) => match event {
termion::event::Event::Key(key) => { termion::event::Event::Key(key) => {
let key = cast_termion_key(key); let key = cast_termion_key(key);
// FIXME: This is a bit of a hack to get resizing to work!
drop(
self.send_screen_instructions
.send(ScreenInstruction::Render),
);
// FIXME this explicit break is needed because the current test // FIXME this explicit break is needed because the current test
// framework relies on it to not create dead threads that loop // framework relies on it to not create dead threads that loop
// and eat up CPUs. Do not remove until the test framework has // and eat up CPUs. Do not remove until the test framework has
@ -237,27 +232,10 @@ impl InputHandler {
.unwrap(); .unwrap();
} }
Action::TabNameInput(c) => { Action::TabNameInput(c) => {
self.send_plugin_instructions
.send(PluginInstruction::Input(
PluginInputType::Event(NaughtyEventType::Tab),
c.clone(),
))
.unwrap();
self.send_screen_instructions self.send_screen_instructions
.send(ScreenInstruction::UpdateTabName(c)) .send(ScreenInstruction::UpdateTabName(c))
.unwrap(); .unwrap();
} }
Action::SaveTabName => {
self.send_plugin_instructions
.send(PluginInstruction::Input(
PluginInputType::Event(NaughtyEventType::Tab),
vec![b'\n'],
))
.unwrap();
self.send_screen_instructions
.send(ScreenInstruction::UpdateTabName(vec![b'\n']))
.unwrap();
}
Action::NoOp => {} Action::NoOp => {}
} }

View file

@ -226,10 +226,7 @@ fn get_defaults_for_mode(mode: &InputMode) -> ModeKeybinds {
defaults.insert(Key::Up, vec![Action::ScrollUp]); defaults.insert(Key::Up, vec![Action::ScrollUp]);
} }
InputMode::RenameTab => { InputMode::RenameTab => {
defaults.insert( defaults.insert(Key::Char('\n'), vec![Action::SwitchToMode(InputMode::Tab)]);
Key::Char('\n'),
vec![Action::SaveTabName, Action::SwitchToMode(InputMode::Tab)],
);
defaults.insert( defaults.insert(
Key::Ctrl('g'), Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Normal)], vec![Action::SwitchToMode(InputMode::Normal)],

View file

@ -10,7 +10,7 @@ pub mod utils;
pub mod wasm_vm; pub mod wasm_vm;
use std::cell::RefCell; use std::cell::RefCell;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::sync::mpsc; use std::sync::mpsc;
use std::thread; use std::thread;
use std::{collections::HashMap, fs}; use std::{collections::HashMap, fs};
@ -32,16 +32,12 @@ use os_input_output::OsApi;
use pty_bus::{PtyBus, PtyInstruction}; use pty_bus::{PtyBus, PtyInstruction};
use screen::{Screen, ScreenInstruction}; use screen::{Screen, ScreenInstruction};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use termion::input::TermRead; use utils::consts::ZELLIJ_IPC_PIPE;
use utils::consts::{ZELLIJ_IPC_PIPE, ZELLIJ_ROOT_PLUGIN_DIR};
use wasm_vm::PluginEnv; use wasm_vm::PluginEnv;
use wasm_vm::{ use wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginInstruction};
wasi_stdout, wasi_write_string, zellij_imports, NaughtyEventType, PluginInputType,
PluginInstruction,
};
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value}; use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
use wasmer_wasi::{Pipe, WasiState}; use wasmer_wasi::{Pipe, WasiState};
use zellij_tile::data::{EventType, InputMode, Key}; use zellij_tile::data::{EventType, InputMode};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub enum ApiCommand { pub enum ApiCommand {
@ -352,8 +348,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.get_active_tab_mut() .get_active_tab_mut()
.unwrap() .unwrap()
.set_pane_selectable(id, selectable); .set_pane_selectable(id, selectable);
// FIXME: Is this needed?
screen.render();
} }
ScreenInstruction::SetMaxHeight(id, max_height) => { ScreenInstruction::SetMaxHeight(id, max_height) => {
screen screen
@ -417,42 +411,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let store = Store::default(); let store = Store::default();
let mut plugin_id = 0; let mut plugin_id = 0;
let mut plugin_map = HashMap::new(); let mut plugin_map = HashMap::new();
let handler_map: HashMap<NaughtyEventType, String> = [(
NaughtyEventType::Tab,
"handle_tab_rename_keypress".to_string(),
)]
.iter()
.cloned()
.collect();
move || loop { 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 let (event, mut err_ctx) = receive_plugin_instructions
.recv() .recv()
.expect("failed to receive event on channel"); .expect("failed to receive event on channel");
@ -461,18 +420,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
send_pty_instructions.update(err_ctx); send_pty_instructions.update(err_ctx);
send_app_instructions.update(err_ctx); send_app_instructions.update(err_ctx);
match event { match event {
PluginInstruction::Load(pid_tx, path, events) => { PluginInstruction::Load(pid_tx, path) => {
let project_dirs = let project_dirs =
ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let plugin_dir = project_dirs.data_dir().join("plugins/"); let plugin_dir = project_dirs.data_dir().join("plugins/");
// FIXME: This really shouldn't need to exist anymore, let's get rid of it!
let root_plugin_dir = Path::new(ZELLIJ_ROOT_PLUGIN_DIR);
let wasm_bytes = fs::read(&path) let wasm_bytes = fs::read(&path)
.or_else(|_| fs::read(&path.with_extension("wasm"))) .or_else(|_| fs::read(&path.with_extension("wasm")))
.or_else(|_| fs::read(&plugin_dir.join(&path).with_extension("wasm"))) .or_else(|_| fs::read(&plugin_dir.join(&path).with_extension("wasm")))
.or_else(|_| {
fs::read(&root_plugin_dir.join(&path).with_extension("wasm"))
})
.unwrap_or_else(|_| panic!("cannot find plugin {}", &path.display())); .unwrap_or_else(|_| panic!("cannot find plugin {}", &path.display()));
// FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that
@ -504,7 +458,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
send_app_instructions: send_app_instructions.clone(), send_app_instructions: send_app_instructions.clone(),
wasi_env, wasi_env,
subscriptions: Arc::new(Mutex::new(HashSet::new())), subscriptions: Arc::new(Mutex::new(HashSet::new())),
events,
}; };
let zellij = zellij_imports(&store, &plugin_env); let zellij = zellij_imports(&store, &plugin_env);
@ -546,29 +499,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap(); buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap();
} }
// FIXME: Deduplicate this with the callback below!
PluginInstruction::Input(input_type, input_bytes) => {
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(
&plugin_env.wasi_env,
&serde_json::to_string(&key).unwrap(),
);
handle_key.call(&[]).unwrap();
}
}
drop(send_screen_instructions.send(ScreenInstruction::Render));
}
PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)), PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
PluginInstruction::Quit => break, PluginInstruction::Quit => break,
} }

View file

@ -82,15 +82,10 @@ fn handle_command_exit(mut child: Child) {
} }
for signal in signals.pending() { for signal in signals.pending() {
// FIXME: We need to handle more signals here! if signal == signal_hook::SIGINT {
#[allow(clippy::single_match)] child.kill().unwrap();
match signal { child.wait().unwrap();
signal_hook::SIGINT => { break 'handle_exit;
child.kill().unwrap();
child.wait().unwrap();
break 'handle_exit;
}
_ => {}
} }
} }
} }

View file

@ -74,7 +74,6 @@ pub struct Screen {
active_tab_index: Option<usize>, active_tab_index: Option<usize>,
/// The [`OsApi`] this [`Screen`] uses. /// The [`OsApi`] this [`Screen`] uses.
os_api: Box<dyn OsApi>, os_api: Box<dyn OsApi>,
tabname_buf: String,
input_mode: InputMode, input_mode: InputMode,
} }
@ -100,7 +99,6 @@ impl Screen {
active_tab_index: None, active_tab_index: None,
tabs: BTreeMap::new(), tabs: BTreeMap::new(),
os_api, os_api,
tabname_buf: String::new(),
input_mode, input_mode,
} }
} }
@ -288,25 +286,20 @@ impl Screen {
pub fn update_active_tab_name(&mut self, buf: Vec<u8>) { pub fn update_active_tab_name(&mut self, buf: Vec<u8>) {
let s = str::from_utf8(&buf).unwrap(); let s = str::from_utf8(&buf).unwrap();
let active_tab = self.get_active_tab_mut().unwrap();
match s { match s {
"\0" => { "\0" => {
self.tabname_buf = String::new(); active_tab.name = String::new();
}
"\n" => {
let new_name = self.tabname_buf.clone();
let active_tab = self.get_active_tab_mut().unwrap();
active_tab.name = new_name;
self.update_tabs();
self.render();
} }
"\u{007F}" | "\u{0008}" => { "\u{007F}" | "\u{0008}" => {
//delete and backspace keys //delete and backspace keys
self.tabname_buf.pop(); active_tab.name.pop();
} }
c => { c => {
self.tabname_buf.push_str(c); active_tab.name.push_str(c);
} }
} }
self.update_tabs();
} }
pub fn change_input_mode(&mut self, input_mode: InputMode) { pub fn change_input_mode(&mut self, input_mode: InputMode) {
self.input_mode = input_mode; self.input_mode = input_mode;

View file

@ -4,5 +4,3 @@ pub const ZELLIJ_TMP_DIR: &str = "/tmp/zellij";
pub const ZELLIJ_TMP_LOG_DIR: &str = "/tmp/zellij/zellij-log"; pub const ZELLIJ_TMP_LOG_DIR: &str = "/tmp/zellij/zellij-log";
pub const ZELLIJ_TMP_LOG_FILE: &str = "/tmp/zellij/zellij-log/log.txt"; pub const ZELLIJ_TMP_LOG_FILE: &str = "/tmp/zellij/zellij-log/log.txt";
pub const ZELLIJ_IPC_PIPE: &str = "/tmp/zellij/ipc"; pub const ZELLIJ_IPC_PIPE: &str = "/tmp/zellij/ipc";
pub const ZELLIJ_ROOT_PLUGIN_DIR: &str = "/usr/share/zellij/plugins";
pub const ZELLIJ_ROOT_LAYOUT_DIR: &str = "/usr/share/zellij/layouts";

View file

@ -1,4 +1,3 @@
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::HashSet, collections::HashSet,
path::PathBuf, path::PathBuf,
@ -12,22 +11,11 @@ use super::{
pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction, PaneId, SenderWithContext, pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction, PaneId, SenderWithContext,
}; };
#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub enum NaughtyEventType {
Tab,
}
#[derive(Clone, Debug)]
pub enum PluginInputType {
Event(NaughtyEventType),
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PluginInstruction { pub enum PluginInstruction {
Load(Sender<u32>, PathBuf, Vec<NaughtyEventType>), Load(Sender<u32>, PathBuf),
Update(Option<u32>, Event), // Focused plugin / broadcast, event data Update(Option<u32>, Event), // Focused plugin / broadcast, event data
Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
Input(PluginInputType, Vec<u8>), // plugin id, input bytes
Unload(u32), Unload(u32),
Quit, Quit,
} }
@ -40,7 +28,6 @@ pub struct PluginEnv {
pub send_pty_instructions: SenderWithContext<PtyInstruction>, // FIXME: This should be a big bundle of all of the channels pub send_pty_instructions: SenderWithContext<PtyInstruction>, // FIXME: This should be a big bundle of all of the channels
pub wasi_env: WasiEnv, pub wasi_env: WasiEnv,
pub subscriptions: Arc<Mutex<HashSet<EventType>>>, pub subscriptions: Arc<Mutex<HashSet<EventType>>>,
pub events: Vec<NaughtyEventType>, // FIXME: Murder this very soon (should not survive into main)
} }
// Plugin API --------------------------------------------------------------------------------------------------------- // Plugin API ---------------------------------------------------------------------------------------------------------

View file

@ -9,8 +9,6 @@ pub trait ZellijTile {
fn load(&mut self) {} fn load(&mut self) {}
fn update(&mut self, event: Event) {} fn update(&mut self, event: Event) {}
fn render(&mut self, rows: usize, cols: usize) {} fn render(&mut self, rows: usize, cols: usize) {}
// FIXME: Everything below this line should be purged
fn handle_tab_rename_keypress(&mut self, key: Key) {}
} }
#[macro_export] #[macro_export]
@ -29,9 +27,7 @@ macro_rules! register_tile {
#[no_mangle] #[no_mangle]
pub fn update() { pub fn update() {
STATE.with(|state| { STATE.with(|state| {
state state.borrow_mut().update($crate::shim::object_from_stdin());
.borrow_mut()
.update($crate::shim::deserialize_from_stdin().unwrap());
}); });
} }
@ -41,14 +37,5 @@ macro_rules! register_tile {
state.borrow_mut().render(rows as usize, cols as usize); state.borrow_mut().render(rows as usize, cols as usize);
}); });
} }
#[no_mangle]
pub fn handle_tab_rename_keypress() {
STATE.with(|state| {
state
.borrow_mut()
.handle_tab_rename_keypress($crate::shim::get_key());
})
}
}; };
} }

View file

@ -3,9 +3,7 @@ use std::{io, path::Path};
use crate::data::*; use crate::data::*;
pub fn get_key() -> Key { // Subscription Handling
deserialize_from_stdin().unwrap()
}
pub fn subscribe(event_types: &[EventType]) { pub fn subscribe(event_types: &[EventType]) {
println!("{}", serde_json::to_string(event_types).unwrap()); println!("{}", serde_json::to_string(event_types).unwrap());
@ -17,31 +15,34 @@ pub fn unsubscribe(event_types: &[EventType]) {
unsafe { host_unsubscribe() }; unsafe { host_unsubscribe() };
} }
pub fn open_file(path: &Path) { // Plugin Settings
println!("{}", path.to_string_lossy());
unsafe { host_open_file() };
}
pub fn set_max_height(max_height: i32) { pub fn set_max_height(max_height: i32) {
unsafe { host_set_max_height(max_height) }; unsafe { host_set_max_height(max_height) };
} }
pub fn set_invisible_borders(invisible_borders: bool) { pub fn set_invisible_borders(invisible_borders: bool) {
let invisible_borders = if invisible_borders { 1 } else { 0 }; unsafe { host_set_invisible_borders(if invisible_borders { 1 } else { 0 }) };
unsafe { host_set_invisible_borders(invisible_borders) };
} }
pub fn set_selectable(selectable: bool) { pub fn set_selectable(selectable: bool) {
let selectable = if selectable { 1 } else { 0 }; unsafe { host_set_selectable(if selectable { 1 } else { 0 }) };
unsafe { host_set_selectable(selectable) };
} }
// Host Functions
pub fn open_file(path: &Path) {
println!("{}", path.to_string_lossy());
unsafe { host_open_file() };
}
// Internal Functions
#[doc(hidden)] #[doc(hidden)]
// FIXME: Make this just return T and do a .unwrap() at the end; also naming? pub fn object_from_stdin<T: DeserializeOwned>() -> T {
pub fn deserialize_from_stdin<T: DeserializeOwned>() -> Option<T> {
let mut json = String::new(); let mut json = String::new();
io::stdin().read_line(&mut json).unwrap(); io::stdin().read_line(&mut json).unwrap();
serde_json::from_str(&json).ok() serde_json::from_str(&json).unwrap()
} }
#[link(wasm_import_module = "zellij")] #[link(wasm_import_module = "zellij")]