summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-03-27 19:19:34 +0200
committerGitHub <noreply@github.com>2023-03-27 19:19:34 +0200
commit341f9eb8c8771a59b2e4d238ba49ba88c3720d6d (patch)
tree51205536dd0789efb770dbe0095af7210a60eed3
parent7b609b053f3aaf466258e12be53d57614c8884c7 (diff)
feat(plugins): async plugin loading (#2327)
* work * refactor(plugins): break down start plugin async function * work * loading messages * nice ui * floating panes and error handling * cleanups and conflicting plugin/direction * find exact pane when relayouting * fix plugin pane titles * kill loading tasks on exit * refactor: move stuff around * style(fmt): rustfmt * various fixes and refactors
-rw-r--r--src/main.rs1
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__bracketed_paste.snap4
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap4
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap4
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap4
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_pane.snap4
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_tab.snap4
-rw-r--r--zellij-server/src/background_jobs.rs42
-rw-r--r--zellij-server/src/panes/plugin_pane.rs40
-rw-r--r--zellij-server/src/plugins/mod.rs38
-rw-r--r--zellij-server/src/plugins/start_plugin.rs471
-rw-r--r--zellij-server/src/plugins/wasm_bridge.rs510
-rw-r--r--zellij-server/src/route.rs16
-rw-r--r--zellij-server/src/screen.rs112
-rw-r--r--zellij-server/src/tab/layout_applier.rs61
-rw-r--r--zellij-server/src/tab/mod.rs146
-rw-r--r--zellij-server/src/ui/loading_indication.rs260
-rw-r--r--zellij-server/src/ui/mod.rs1
-rw-r--r--zellij-server/src/unit/screen_tests.rs3
-rwxr-xr-xzellij-utils/assets/plugins/compact-bar.wasmbin486821 -> 489887 bytes
-rwxr-xr-xzellij-utils/assets/plugins/status-bar.wasmbin617691 -> 622998 bytes
-rwxr-xr-xzellij-utils/assets/plugins/strider.wasmbin501338 -> 504360 bytes
-rwxr-xr-xzellij-utils/assets/plugins/tab-bar.wasmbin456049 -> 459061 bytes
-rw-r--r--zellij-utils/src/cli.rs3
-rw-r--r--zellij-utils/src/errors.rs8
-rw-r--r--zellij-utils/src/input/actions.rs29
26 files changed, 1455 insertions, 310 deletions
diff --git a/src/main.rs b/src/main.rs
index 54ca71cb4..e3737b19e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -32,6 +32,7 @@ fn main() {
{
let command_cli_action = CliAction::NewPane {
command,
+ plugin: None,
direction,
cwd,
floating,
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__bracketed_paste.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__bracketed_paste.snap
index dcb76b9e1..59bdf1ff1 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__bracketed_paste.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__bracketed_paste.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 1671
+assertion_line: 1640
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap
index 5583430da..70fa42f4b 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 803
+assertion_line: 804
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <> PANE  <> TAB  <> RESIZE  <> MOVE  <> SEARCH  <> SESSION  <> QUIT 
+ Ctrl + <g> LOCK  <> PANE  <> TAB  <> RESIZE  <> MOVE  <> SEARCH  <> SESSION  <> QUIT   BASE 
-- INTERFACE LOCKED --
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
index 6f2822c5f..b45f01142 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 107
+assertion_line: 108
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
index 5a88e98a7..065bbfe56 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 398
+assertion_line: 987
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- <F1> LOCK  <F2> PANE  <F3> TAB  <F4> RESIZE  <F5> MOVE  <F6> SEARCH  <F7> SESSION  <F8> QUIT 
+ <F1> LOCK  <F2> PANE  <F3> TAB  <F4> RESIZE  <F5> MOVE  <F6> SEARCH  <F7> SESSION  <F8> QUIT   BASE 
Tip: UNBOUND => open new pane. UNBOUND => navigate between panes. UNBOUND => increase/decrease pane size.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_pane.snap
index e8c277172..76d6ee127 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_pane.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_pane.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 1949
+assertion_line: 1881
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_tab.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_tab.snap
index 56b417d76..6f84144f1 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_tab.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__undo_rename_tab.snap
@@ -1,6 +1,6 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 1900
+assertion_line: 1832
expression: last_snapshot
---
Zellij (e2e-test)  Tab #1 
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/zellij-server/src/background_jobs.rs b/zellij-server/src/background_jobs.rs
index c612c9d57..8061b4a47 100644
--- a/zellij-server/src/background_jobs.rs
+++ b/zellij-server/src/background_jobs.rs
@@ -2,6 +2,10 @@ use zellij_utils::async_std::task;
use zellij_utils::errors::{prelude::*, BackgroundJobContext, ContextType};
use std::collections::HashMap;
+use std::sync::{
+ atomic::{AtomicBool, Ordering},
+ Arc,
+};
use std::time::{Duration, Instant};
use crate::panes::PaneId;
@@ -11,6 +15,8 @@ use crate::thread_bus::Bus;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum BackgroundJob {
DisplayPaneError(Vec<PaneId>, String),
+ AnimatePluginLoading(u32), // u32 - plugin_id
+ StopPluginLoadingAnimation(u32), // u32 - plugin_id
Exit,
}
@@ -18,16 +24,22 @@ impl From<&BackgroundJob> for BackgroundJobContext {
fn from(background_job: &BackgroundJob) -> Self {
match *background_job {
BackgroundJob::DisplayPaneError(..) => BackgroundJobContext::DisplayPaneError,
+ BackgroundJob::AnimatePluginLoading(..) => BackgroundJobContext::AnimatePluginLoading,
+ BackgroundJob::StopPluginLoadingAnimation(..) => {
+ BackgroundJobContext::StopPluginLoadingAnimation
+ },
BackgroundJob::Exit => BackgroundJobContext::Exit,
}
}
}
static FLASH_DURATION_MS: u64 = 1000;
+static PLUGIN_ANIMATION_OFFSET_DURATION_MD: u64 = 500;
pub(crate) fn background_jobs_main(bus: Bus<BackgroundJob>) -> Result<()> {
let err_context = || "failed to write to pty".to_string();
let mut running_jobs: HashMap<BackgroundJob, Instant> = HashMap::new();
+ let mut loading_plugins: HashMap<u32, Arc<AtomicBool>> = HashMap::new(); // u32 - plugin_id
loop {
let (event, mut err_ctx) = bus.recv().with_context(err_context)?;
@@ -54,7 +66,37 @@ pub(crate) fn background_jobs_main(bus: Bus<BackgroundJob>) -> Result<()> {
}
});
},
+ BackgroundJob::AnimatePluginLoading(pid) => {
+ let loading_plugin = Arc::new(AtomicBool::new(true));
+ if job_already_running(job, &mut running_jobs) {
+ continue;
+ }
+ task::spawn({
+ let senders = bus.senders.clone();
+ let loading_plugin = loading_plugin.clone();
+ async move {
+ while loading_plugin.load(Ordering::SeqCst) {
+ let _ = senders.send_to_screen(
+ ScreenInstruction::ProgressPluginLoadingOffset(pid),
+ );
+ task::sleep(std::time::Duration::from_millis(
+ PLUGIN_ANIMATION_OFFSET_DURATION_MD,
+ ))
+ .await;
+ }
+ }
+ });
+ loading_plugins.insert(pid, loading_plugin);
+ },
+ BackgroundJob::StopPluginLoadingAnimation(pid) => {
+ if let Some(loading_plugin) = loading_plugins.remove(&pid) {
+ loading_plugin.store(false, Ordering::SeqCst);
+ }
+ },
BackgroundJob::Exit => {
+ for loading_plugin in loading_plugins.values() {
+ loading_plugin.store(false, Ordering::SeqCst);
+ }
return Ok(());
},
}
diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs
index c6896f90d..28828907e 100644
--- a/zellij-server/src/panes/plugin_pane.rs
+++ b/zellij-server/src/panes/plugin_pane.rs
@@ -6,7 +6,10 @@ use crate::panes::{grid::Grid, sixel::SixelImageStore, LinkHandler, PaneId};
use crate::plugins::PluginInstruction;
use crate::pty::VteBytes;
use crate::tab::Pane;
-use crate::ui::pane_boundaries_frame::{FrameParams, PaneFrame};
+use crate::ui::{
+ loading_indication::LoadingIndication,
+ pane_boundaries_frame::{FrameParams, PaneFrame},
+};
use crate::ClientId;
use std::cell::RefCell;
use std::rc::Rc;
@@ -67,6 +70,7 @@ pub(crate) struct PluginPane {
borderless: bool,
pane_frame_color_override: Option<(PaletteColor, Option<String>)>,
invoked_with: Option<Run>,
+ loading_indication: LoadingIndication,
}
impl PluginPane {
@@ -81,10 +85,13 @@ impl PluginPane {
terminal_emulator_color_codes: Rc<RefCell<HashMap<usize, String>>>,
link_handler: Rc<RefCell<LinkHandler>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
+ currently_connected_clients: Vec<ClientId>,
style: Style,
invoked_with: Option<Run>,
) -> Self {
- Self {
+ let loading_indication = LoadingIndication::new(title.clone()).with_colors(style.colors);
+ let initial_loading_message = loading_indication.to_string();
+ let mut plugin = PluginPane {
pid,
should_render: HashMap::new(),
selectable: true,
@@ -108,7 +115,12 @@ impl PluginPane {
style,
pane_frame_color_override: None,
invoked_with,
+ loading_indication,
+ };
+ for client_id in currently_connected_clients {
+ plugin.handle_plugin_bytes(client_id, initial_loading_message.as_bytes().to_vec());
}
+ plugin
}
}
@@ -513,6 +525,24 @@ impl Pane for PluginPane {
fn set_title(&mut self, title: String) {
self.pane_title = title;
}
+ fn update_loading_indication(&mut self, loading_indication: LoadingIndication) {
+ if self.loading_indication.ended {
+ return;
+ }
+ self.loading_indication.merge(loading_indication);
+ self.handle_plugin_bytes_for_all_clients(
+ self.loading_indication.to_string().as_bytes().to_vec(),
+ );
+ }
+ fn progress_animation_offset(&mut self) {
+ if self.loading_indication.ended {
+ return;
+ }
+ self.loading_indication.progress_animation_offset();
+ self.handle_plugin_bytes_for_all_clients(
+ self.loading_indication.to_string().as_bytes().to_vec(),
+ );
+ }
}
impl PluginPane {
@@ -527,4 +557,10 @@ impl PluginPane {
fn set_client_should_render(&mut self, client_id: ClientId, should_render: bool) {
self.should_render.insert(client_id, should_render);
}
+ fn handle_plugin_bytes_for_all_clients(&mut self, bytes: VteBytes) {
+ let client_ids: Vec<ClientId> = self.grids.keys().copied().collect();
+ for client_id in client_ids {
+ self.handle_plugin_bytes(client_id, bytes.clone());
+ }
+ }
}
diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs
index 1cd034490..e1884b1e6 100644
--- a/zellij-server/src/plugins/mod.rs
+++ b/zellij-server/src/plugins/mod.rs
@@ -1,8 +1,10 @@
+mod start_plugin;
mod wasm_bridge;
use log::info;
use std::{collections::HashMap, fs, path::PathBuf};
use wasmer::Store;
+use crate::screen::ScreenInstruction;
use crate::{pty::PtyInstruction, thread_bus::Bus, ClientId};
use wasm_bridge::WasmBridge;
@@ -20,7 +22,14 @@ use zellij_utils::{
#[derive(Clone, Debug)]
pub enum PluginInstruction {
- Load(RunPlugin, usize, ClientId, Size), // plugin metadata, tab_index, client_ids
+ Load(
+ Option<bool>, // should float
+ Option<String>, // pane title
+ RunPlugin,
+ usize, // tab index
+ ClientId,
+ Size,
+ ),
Update(Vec<(Option<u32>, Option<ClientId>, Event)>), // Focused plugin / broadcast, client_id, event data
Unload(u32), // plugin_id
Resize(u32, usize, usize), // plugin_id, columns, rows
@@ -33,6 +42,7 @@ pub enum PluginInstruction {
usize, // tab_index
ClientId,
),
+ ApplyCachedEvents(u32), // u32 is the plugin id
Exit,
}
@@ -47,6 +57,7 @@ impl From<&PluginInstruction> for PluginContext {
PluginInstruction::AddClient(_) => PluginContext::AddClient,
PluginInstruction::RemoveClient(_) => PluginContext::RemoveClient,
PluginInstruction::NewTab(..) => PluginContext::NewTab,
+ PluginInstruction::ApplyCachedEvents(..) => PluginContext::ApplyCachedEvents,
}
}
}
@@ -69,8 +80,21 @@ pub(crate) fn plugin_thread_main(
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin((&event).into()));
match event {
- PluginInstruction::Load(run, tab_index, client_id, size) => {
- wasm_bridge.load_plugin(&run, tab_index, size, client_id)?;
+ PluginInstruction::Load(should_float, pane_title, run, tab_index, client_id, size) => {
+ match wasm_bridge.load_plugin(&run, tab_index, size, client_id) {
+ Ok(plugin_id) => {
+ drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
+ should_float,
+ run,
+ pane_title,
+ tab_index,
+ plugin_id,
+ )));
+ },
+ Err(e) => {
+ log::error!("Failed to load plugin: {e}");
+ },
+ }
},
PluginInstruction::Update(updates) => {
wasm_bridge.update_plugins(updates)?;
@@ -126,7 +150,13 @@ pub(crate) fn plugin_thread_main(
client_id,
)));
},
- PluginInstruction::Exit => break,
+ PluginInstruction::ApplyCachedEvents(plugin_id) => {
+ wasm_bridge.apply_cached_events(plugin_id)?;
+ },
+ PluginInstruction::Exit => {
+ wasm_bridge.cleanup();
+ break;
+ },
}
}
info!("wasm main thread exits");
diff --git a/zellij-server/src/plugins/start_plugin.rs b/zellij-server/src/plugins/start_plugin.rs
new file mode 100644
index 000000000..28000bd15
--- /dev/null
+++ b/zellij-server/src/plugins/start_plugin.rs
@@ -0,0 +1,471 @@