aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authora-kenji <aks.kenji@protonmail.com>2021-03-26 23:33:36 +0100
committera-kenji <aks.kenji@protonmail.com>2021-03-26 23:33:36 +0100
commit84488a35aa2cef3505e9b40f7f0345cff73d62c8 (patch)
tree880d5019c40675177ea0402a186f6826d2bffa6f /src
parentConfig: Fix README (diff)
parentfeat(plugin): refactored to a new and more general plugin API (diff)
downloadsl0ppij-84488a35aa2cef3505e9b40f7f0345cff73d62c8.tar.gz
sl0ppij-84488a35aa2cef3505e9b40f7f0345cff73d62c8.tar.xz
sl0ppij-84488a35aa2cef3505e9b40f7f0345cff73d62c8.zip
Merge branch 'main' of https://github.com/zellij-org/zellij into config-file
Diffstat (limited to 'src')
-rw-r--r--src/client/boundaries.rs128
-rw-r--r--src/client/layout.rs8
-rw-r--r--src/client/panes/plugin_pane.rs2
-rw-r--r--src/client/panes/terminal_character.rs10
-rw-r--r--src/client/panes/terminal_pane.rs36
-rw-r--r--src/client/tab.rs193
-rw-r--r--src/common/errors.rs24
-rw-r--r--src/common/input/actions.rs6
-rw-r--r--src/common/input/handler.rs137
-rw-r--r--src/common/input/keybinds.rs8
-rw-r--r--src/common/input/unit/keybinds_test.rs2
-rw-r--r--src/common/ipc.rs8
-rw-r--r--src/common/mod.rs197
-rw-r--r--src/common/os_input_output.rs13
-rw-r--r--src/common/screen.rs50
-rw-r--r--src/common/utils/consts.rs2
-rw-r--r--src/common/wasm_vm.rs62
-rw-r--r--src/tests/fakes.rs11
-rw-r--r--src/tests/integration/expansion_boundary.rs11
-rw-r--r--src/tests/integration/resize_down.rs16
-rw-r--r--src/tests/integration/resize_left.rs15
-rw-r--r--src/tests/integration/resize_right.rs15
-rw-r--r--src/tests/integration/resize_up.rs15
-rw-r--r--src/tests/utils.rs1
24 files changed, 469 insertions, 501 deletions
diff --git a/src/client/boundaries.rs b/src/client/boundaries.rs
index 67733c12..e498da89 100644
--- a/src/client/boundaries.rs
+++ b/src/client/boundaries.rs
@@ -1,5 +1,7 @@
use crate::tab::Pane;
+use ansi_term::Colour;
use std::collections::HashMap;
+use zellij_tile::data::InputMode;
use std::fmt::{Display, Error, Formatter};
@@ -17,12 +19,20 @@ pub mod boundary_type {
pub const CROSS: &str = "┼";
}
+pub mod colors {
+ use ansi_term::Colour::{self, Fixed};
+ pub const WHITE: Colour = Fixed(255);
+ pub const GREEN: Colour = Fixed(154);
+ pub const GRAY: Colour = Fixed(238);
+}
+
pub type BoundaryType = &'static str; // easy way to refer to boundary_type above
#[derive(Clone, Copy, Debug)]
pub struct BoundarySymbol {
boundary_type: BoundaryType,
invisible: bool,
+ color: Option<Colour>,
}
impl BoundarySymbol {
@@ -30,20 +40,27 @@ impl BoundarySymbol {
BoundarySymbol {
boundary_type,
invisible: false,
+ color: Some(colors::GRAY),
}
}
pub fn invisible(mut self) -> Self {
self.invisible = true;
self
}
+ pub fn color(&mut self, color: Option<Colour>) -> Self {
+ self.color = color;
+ *self
+ }
}
impl Display for BoundarySymbol {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- if self.invisible {
- write!(f, " ")
- } else {
- write!(f, "{}", self.boundary_type)
+ match self.invisible {
+ true => write!(f, " "),
+ false => match self.color {
+ Some(color) => write!(f, "{}", color.paint(self.boundary_type)),
+ None => write!(f, "{}", self.boundary_type),
+ },
}
}
}
@@ -53,6 +70,10 @@ fn combine_symbols(
next_symbol: BoundarySymbol,
) -> Option<BoundarySymbol> {
let invisible = current_symbol.invisible || next_symbol.invisible;
+ let color = match (current_symbol.color.is_some(), next_symbol.color.is_some()) {
+ (true, _) => current_symbol.color,
+ _ => next_symbol.color,
+ };
let current_symbol = current_symbol.boundary_type;
let next_symbol = next_symbol.boundary_type;
match (current_symbol, next_symbol) {
@@ -62,6 +83,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::VERTICAL) => {
@@ -70,6 +92,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::HORIZONTAL) => {
@@ -78,6 +101,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::TOP_LEFT) => {
@@ -86,6 +110,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::BOTTOM_RIGHT) => {
@@ -94,6 +119,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::BOTTOM_LEFT) => {
@@ -102,6 +128,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::VERTICAL_LEFT) => {
@@ -110,6 +137,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::VERTICAL_RIGHT) => {
@@ -118,6 +146,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::HORIZONTAL_DOWN) => {
@@ -126,6 +155,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::HORIZONTAL_UP) => {
@@ -134,6 +164,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_RIGHT, boundary_type::CROSS) => {
@@ -142,6 +173,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::HORIZONTAL) => {
@@ -150,6 +182,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::VERTICAL) => {
@@ -158,6 +191,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::TOP_LEFT) => {
@@ -166,6 +200,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::BOTTOM_RIGHT) => {
@@ -174,6 +209,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::BOTTOM_LEFT) => {
@@ -182,6 +218,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::VERTICAL_LEFT) => {
@@ -190,6 +227,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::VERTICAL_RIGHT) => {
@@ -198,6 +236,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::HORIZONTAL_DOWN) => {
@@ -206,6 +245,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::HORIZONTAL_UP) => {
@@ -214,6 +254,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL, boundary_type::CROSS) => {
@@ -222,6 +263,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::VERTICAL) => {
@@ -230,6 +272,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::TOP_LEFT) => {
@@ -238,6 +281,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::BOTTOM_RIGHT) => {
@@ -246,6 +290,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::BOTTOM_LEFT) => {
@@ -254,6 +299,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::VERTICAL_LEFT) => {
@@ -262,6 +308,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::VERTICAL_RIGHT) => {
@@ -270,6 +317,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::HORIZONTAL_DOWN) => {
@@ -278,6 +326,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::HORIZONTAL_UP) => {
@@ -286,6 +335,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL, boundary_type::CROSS) => {
@@ -294,6 +344,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::TOP_LEFT) => {
@@ -302,6 +353,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::BOTTOM_RIGHT) => {
@@ -310,6 +362,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::BOTTOM_LEFT) => {
@@ -318,6 +371,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::VERTICAL_LEFT) => {
@@ -326,6 +380,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::VERTICAL_RIGHT) => {
@@ -334,6 +389,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::HORIZONTAL_DOWN) => {
@@ -342,6 +398,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::HORIZONTAL_UP) => {
@@ -350,6 +407,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::TOP_LEFT, boundary_type::CROSS) => {
@@ -358,6 +416,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::BOTTOM_RIGHT) => {
@@ -366,6 +425,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::BOTTOM_LEFT) => {
@@ -374,6 +434,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::VERTICAL_LEFT) => {
@@ -382,6 +443,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::VERTICAL_RIGHT) => {
@@ -390,6 +452,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::HORIZONTAL_DOWN) => {
@@ -398,6 +461,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::HORIZONTAL_UP) => {
@@ -406,6 +470,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_RIGHT, boundary_type::CROSS) => {
@@ -414,6 +479,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::BOTTOM_LEFT) => {
@@ -422,6 +488,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::VERTICAL_LEFT) => {
@@ -430,6 +497,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::VERTICAL_RIGHT) => {
@@ -438,6 +506,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::HORIZONTAL_DOWN) => {
@@ -446,6 +515,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::HORIZONTAL_UP) => {
@@ -454,6 +524,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::BOTTOM_LEFT, boundary_type::CROSS) => {
@@ -462,6 +533,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_LEFT, boundary_type::VERTICAL_LEFT) => {
@@ -470,6 +542,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_LEFT, boundary_type::VERTICAL_RIGHT) => {
@@ -478,6 +551,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_LEFT, boundary_type::HORIZONTAL_DOWN) => {
@@ -486,6 +560,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_LEFT, boundary_type::HORIZONTAL_UP) => {
@@ -494,6 +569,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_LEFT, boundary_type::CROSS) => {
@@ -502,6 +578,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_RIGHT, boundary_type::VERTICAL_RIGHT) => {
@@ -510,6 +587,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_RIGHT, boundary_type::HORIZONTAL_DOWN) => {
@@ -518,6 +596,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_RIGHT, boundary_type::HORIZONTAL_UP) => {
@@ -526,6 +605,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::VERTICAL_RIGHT, boundary_type::CROSS) => {
@@ -534,6 +614,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL_DOWN, boundary_type::HORIZONTAL_DOWN) => {
@@ -542,6 +623,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL_DOWN, boundary_type::HORIZONTAL_UP) => {
@@ -550,6 +632,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL_DOWN, boundary_type::CROSS) => {
@@ -558,6 +641,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL_UP, boundary_type::HORIZONTAL_UP) => {
@@ -566,6 +650,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::HORIZONTAL_UP, boundary_type::CROSS) => {
@@ -574,6 +659,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(boundary_type::CROSS, boundary_type::CROSS) => {
@@ -582,6 +668,7 @@ fn combine_symbols(
Some(BoundarySymbol {
boundary_type,
invisible,
+ color,
})
}
(_, _) => None,
@@ -677,7 +764,14 @@ impl Boundaries {
boundary_characters: HashMap::new(),
}
}
- pub fn add_rect(&mut self, rect: &dyn Pane) {
+ pub fn add_rect(&mut self, rect: &dyn Pane, input_mode: InputMode, color: Option<Colour>) {
+ let color = match color.is_some() {
+ true => match input_mode {
+ InputMode::Normal | InputMode::Locked => Some(colors::GREEN),
+ _ => Some(colors::WHITE),
+ },
+ false => None,
+ };
if rect.x() > 0 {
let boundary_x_coords = rect.x() - 1;
let first_row_coordinates = self.rect_right_boundary_row_start(rect);
@@ -685,11 +779,11 @@ impl Boundaries {
for row in first_row_coordinates..last_row_coordinates {
let coordinates = Coordinates::new(boundary_x_coords, row);
let mut symbol_to_add = if row == first_row_coordinates && row != 0 {
- BoundarySymbol::new(boundary_type::TOP_LEFT)
+ BoundarySymbol::new(boundary_type::TOP_LEFT).color(color)
} else if row == last_row_coordinates - 1 && row != self.rows - 1 {
- BoundarySymbol::new(boundary_type::BOTTOM_LEFT)
+ BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color)
} else {
- BoundarySymbol::new(boundary_type::VERTICAL)
+ BoundarySymbol::new(boundary_type::VERTICAL).color(color)
};
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
@@ -709,11 +803,11 @@ impl Boundaries {
for col in first_col_coordinates..last_col_coordinates {
let coordinates = Coordinates::new(col, boundary_y_coords);
let mut symbol_to_add = if col == first_col_coordinates && col != 0 {
- BoundarySymbol::new(boundary_type::TOP_LEFT)
+ BoundarySymbol::new(boundary_type::TOP_LEFT).color(color)
} else if col == last_col_coordinates - 1 && col != self.columns - 1 {
- BoundarySymbol::new(boundary_type::TOP_RIGHT)
+ BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color)
} else {
- BoundarySymbol::new(boundary_type::HORIZONTAL)
+ BoundarySymbol::new(boundary_type::HORIZONTAL).color(color)
};
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
@@ -734,11 +828,11 @@ impl Boundaries {
for row in first_row_coordinates..last_row_coordinates {
let coordinates = Coordinates::new(boundary_x_coords, row);
let mut symbol_to_add = if row == first_row_coordinates && row != 0 {
- BoundarySymbol::new(boundary_type::TOP_RIGHT)
+ BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color)
} else if row == last_row_coordinates - 1 && row != self.rows - 1 {
- BoundarySymbol::new(boundary_type::BOTTOM_RIGHT)
+ BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color)
} else {
- BoundarySymbol::new(boundary_type::VERTICAL)
+ BoundarySymbol::new(boundary_type::VERTICAL).color(color)
};
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
@@ -758,11 +852,11 @@ impl Boundaries {
for col in first_col_coordinates..last_col_coordinates {
let coordinates = Coordinates::new(col, boundary_y_coords);
let mut symbol_to_add = if col == first_col_coordinates && col != 0 {
- BoundarySymbol::new(boundary_type::BOTTOM_LEFT)
+ BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color)
} else if col == last_col_coordinates - 1 && col != self.columns - 1 {
- BoundarySymbol::new(boundary_type::BOTTOM_RIGHT)
+ BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color)
} else {
- BoundarySymbol::new(boundary_type::HORIZONTAL)
+ BoundarySymbol::new(boundary_type::HORIZONTAL).color(color)
};
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
diff --git a/src/client/layout.rs b/src/client/layout.rs
index 1b383540..2d1daaf4 100644
--- a/src/client/layout.rs
+++ b/src/client/layout.rs
@@ -1,10 +1,8 @@
-use crate::utils::consts::ZELLIJ_ROOT_LAYOUT_DIR;
use directories_next::ProjectDirs;
use serde::{Deserialize, Serialize};
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
use std::{fs::File, io::prelude::*};
-use crate::common::wasm_vm::EventType;
use crate::panes::PositionAndSize;
fn split_space_to_parts_vertically(
@@ -181,19 +179,15 @@ pub struct Layout {
pub plugin: Option<PathBuf>,
#[serde(default)]
pub expansion_boundary: bool,
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub events: Vec<EventType>,
}
impl Layout {
pub fn new(layout_path: PathBuf) -> Self {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
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)
.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(root_layout_dir.join(&layout_path).with_extension("yaml")))
.unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display()));
let mut layout = String::new();
diff --git a/src/client/panes/plugin_pane.rs b/src/client/panes/plugin_pane.rs
index 588cffd6..4cffff5f 100644
--- a/src/client/panes/plugin_pane.rs
+++ b/src/client/panes/plugin_pane.rs
@@ -120,7 +120,7 @@ impl Pane for PluginPane {
let (buf_tx, buf_rx) = channel();
self.send_plugin_instructions
- .send(PluginInstruction::Draw(
+ .send(PluginInstruction::Render(
buf_tx,
self.pid,
self.rows(),
diff --git a/src/client/panes/terminal_character.rs b/src/client/panes/terminal_character.rs
index 80c3162b..053ebd3f 100644
--- a/src/client/panes/terminal_character.rs
+++ b/src/client/panes/terminal_character.rs
@@ -23,7 +23,7 @@ pub enum AnsiCode {
On,
Reset,
NamedColor(NamedColor),
- RGBCode((u8, u8, u8)),
+ RgbCode((u8, u8, u8)),
ColorIndex(u8),
}
@@ -336,7 +336,7 @@ impl CharacterStyles {
[36, ..] => *self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Cyan))),
[37, ..] => *self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::White))),
[38, 2, ..] => {
- let ansi_code = AnsiCode::RGBCode((
+ let ansi_code = AnsiCode::RgbCode((
*ansi_params.get(2).unwrap() as u8,
*ansi_params.get(3).unwrap() as u8,
*ansi_params.get(4).unwrap() as u8,
@@ -364,7 +364,7 @@ impl CharacterStyles {
[46, ..] => *self = self.background(Some(AnsiCode::NamedColor(NamedColor::Cyan))),
[47, ..] => *self = self.background(Some(AnsiCode::NamedColor(NamedColor::White))),
[48, 2, ..] => {
- let ansi_code = AnsiCode::RGBCode((
+ let ansi_code = AnsiCode::RgbCode((
*ansi_params.get(2).unwrap() as u8,
*ansi_params.get(3).unwrap() as u8,
*ansi_params.get(4).unwrap() as u8,
@@ -416,7 +416,7 @@ impl Display for CharacterStyles {
}
if let Some(ansi_code) = self.foreground {
match ansi_code {
- AnsiCode::RGBCode((r, g, b)) => {
+ AnsiCode::RgbCode((r, g, b)) => {
write!(f, "\u{1b}[38;2;{};{};{}m", r, g, b)?;
}
AnsiCode::ColorIndex(color_index) => {
@@ -433,7 +433,7 @@ impl Display for CharacterStyles {
};
if let Some(ansi_code) = self.background {
match ansi_code {
- AnsiCode::RGBCode((r, g, b)) => {
+ AnsiCode::RgbCode((r, g, b)) => {
write!(f, "\u{1b}[48;2;{};{};{}m", r, g, b)?;
}
AnsiCode::ColorIndex(color_index) => {
diff --git a/src/client/panes/terminal_pane.rs b/src/client/panes/terminal_pane.rs
index fd83d571..f0b15e50 100644
--- a/src/client/panes/terminal_pane.rs
+++ b/src/client/panes/terminal_pane.rs
@@ -70,13 +70,11 @@ impl Pane for TerminalPane {
fn reset_size_and_position_override(&mut self) {
self.position_and_size_override = None;
self.reflow_lines();
- self.mark_for_rerender();
}
fn change_pos_and_size(&mut self, position_and_size: &PositionAndSize) {
self.position_and_size.columns = position_and_size.columns;
self.position_and_size.rows = position_and_size.rows;
self.reflow_lines();
- self.mark_for_rerender();
}
fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize) {
let position_and_size_override = PositionAndSize {
@@ -87,7 +85,6 @@ impl Pane for TerminalPane {
};
self.position_and_size_override = Some(position_and_size_override);
self.reflow_lines();
- self.mark_for_rerender();
}
fn handle_event(&mut self, event: VteEvent) {
match event {
@@ -191,12 +188,14 @@ impl Pane for TerminalPane {
self.max_height
}
fn render(&mut self) -> Option<String> {
- // if self.should_render {
+ // FIXME:
+ // the below conditional is commented out because it causes several bugs:
+ // 1. When panes are resized or tabs are switched the previous contents of the screen stick
+ // around
+ // 2. When there are wide characters in a pane, since we don't yet handle them properly,
+ // the spill over to the pane to the right
+ // if self.should_render || cfg!(test) {
if true {
- // while checking should_render rather than rendering each pane every time
- // is more performant, it causes some problems when the pane to the left should be
- // rendered and has wide characters (eg. Chinese characters or emoji)
- // as a (hopefully) temporary hack, we render all panes until we find a better solution
let mut vte_output = String::new();
let buffer_lines = &self.read_buffer_as_lines();
let display_cols = self.get_columns();
@@ -205,12 +204,11 @@ impl Pane for TerminalPane {
for line_index in 0..self.grid.height {
let x = self.get_x();
let y = self.get_y();
- vte_output = format!(
- "{}\u{1b}[{};{}H\u{1b}[m",
- vte_output,
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m",
y + line_index + 1,
x + 1
- ); // goto row/col and reset styles
+ )); // goto row/col and reset styles
for _col_index in 0..self.grid.width {
vte_output.push(EMPTY_TERMINAL_CHARACTER.character);
}
@@ -220,7 +218,7 @@ impl Pane for TerminalPane {
for (row, line) in buffer_lines.iter().enumerate() {
let x = self.get_x();
let y = self.get_y();
- vte_output = format!("{}\u{1b}[{};{}H\u{1b}[m", vte_output, y + row + 1, x + 1); // goto row/col and reset styles
+ vte_output.push_str(&format!("\u{1b}[{};{}H\u{1b}[m", y + row + 1, x + 1)); // goto row/col and reset styles
for (col, t_character) in line.iter().enumerate() {
if col < display_cols {
// in some cases (eg. while resizing) some characters will spill over
@@ -232,14 +230,14 @@ impl Pane for TerminalPane {
// the terminal keeps the previous styles as long as we're in the same
// line, so we only want to update the new styles here (this also
// includes resetting previous styles as needed)
- vte_output = format!("{}{}", vte_output, new_styles);
+ vte_output.push_str(&new_styles.to_string());
}
vte_output.push(t_character.character);
}
}
character_styles.clear();
}
- self.mark_for_rerender();
+ self.should_render = false;
Some(vte_output)
} else {
None
@@ -252,45 +250,37 @@ impl Pane for TerminalPane {
self.position_and_size.y += count;
self.position_and_size.rows -= count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn increase_height_down(&mut self, count: usize) {
self.position_and_size.rows += count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn increase_height_up(&mut self, count: usize) {
self.position_and_size.y -= count;
self.position_and_size.rows += count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn reduce_height_up(&mut self, count: usize) {
self.position_and_size.rows -= count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn reduce_width_right(&mut self, count: usize) {
self.position_and_size.x += count;
self.position_and_size.columns -= count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn reduce_width_left(&mut self, count: usize) {
self.position_and_size.columns -= count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn increase_width_left(&mut self, count: usize) {
self.position_and_size.x -= count;
self.position_and_size.columns += count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn increase_width_right(&mut self, count: usize) {
self.position_and_size.columns += count;
self.reflow_lines();
- self.mark_for_rerender();
}
fn scroll_up(&mut self, count: usize) {
self.grid.move_viewport_up(count);
diff --git a/src/client/tab.rs b/src/client/tab.rs
index 1ef0b720..1e56fd8b 100644
--- a/src/client/tab.rs
+++ b/src/client/tab.rs
@@ -1,20 +1,21 @@
//! `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::boundaries::colors;
+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 serde::{Deserialize, Serialize};
use std::os::unix::io::RawFd;
use std::{
cmp::Reverse,
collections::{BTreeMap, HashSet},
};
use std::{io::Write, sync::mpsc::channel};
+use zellij_tile::data::{Event, InputMode};
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;
@@ -65,14 +66,7 @@ pub struct Tab {
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
pub send_app_instructions: SenderWithContext<AppInstruction>,
expansion_boundary: Option<PositionAndSize>,
-}
-
-#[derive(Clone, Debug, Default, Serialize, Deserialize)]
-pub struct TabData {
- /* subset of fields to publish to plugins */
- pub position: usize,
- pub name: String,
- pub active: bool,
+ pub input_mode: InputMode,
}
// FIXME: Use a struct that has a pane_type enum, to reduce all of the duplication
@@ -189,6 +183,7 @@ impl Tab {
send_app_instructions: SenderWithContext<AppInstruction>,
max_panes: Option<usize>,
pane_id: Option<PaneId>,
+ input_mode: InputMode,
) -> Self {
let panes = if let Some(PaneId::Terminal(pid)) = pane_id {
let new_terminal = TerminalPane::new(pid, *full_screen_ws);
@@ -218,6 +213,7 @@ impl Tab {
send_pty_instructions,
send_plugin_instructions,
expansion_boundary: None,
+ input_mode,
}
}
@@ -262,11 +258,7 @@ impl Tab {
if let Some(plugin) = &layout.plugin {
let (pid_tx, pid_rx) = channel();
self.send_plugin_instructions
- .send(PluginInstruction::Load(
- pid_tx,
- plugin.clone(),
- layout.events.clone(),
- ))
+ .send(PluginInstruction::Load(pid_tx, plugin.clone()))
.unwrap();
let pid = pid_rx.recv().unwrap();
let new_plugin = PluginPane::new(
@@ -305,7 +297,6 @@ impl Tab {
self.toggle_active_pane_fullscreen();
}
if !self.has_panes() {
- // FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd(
@@ -356,7 +347,6 @@ impl Tab {
if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns()
&& terminal_to_split.rows() > terminal_to_split.min_height() * 2
{
- // FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid {
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
@@ -377,7 +367,6 @@ impl Tab {
self.active_terminal = Some(pid);
}
} 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 {
let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, right_winsize);
@@ -407,7 +396,6 @@ impl Tab {
self.toggle_active_pane_fullscreen();
}
if !self.has_panes() {
- // FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd(
@@ -418,47 +406,44 @@ impl Tab {
self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid);
}
- } else {
- // FIXME: This could use a second look
- if let PaneId::Terminal(term_pid) = pid {
- // TODO: check minimum size of active terminal
- let active_pane_id = &self.get_active_pane_id().unwrap();
- let active_pane = self.panes.get_mut(active_pane_id).unwrap();
- if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 {
- self.send_pty_instructions
- .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
- .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);
+ } else if let PaneId::Terminal(term_pid) = pid {
+ // TODO: check minimum size of active terminal
+ let active_pane_id = &self.get_active_pane_id().unwrap();
+ let active_pane = self.panes.get_mut(active_pane_id).unwrap();
+ if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 {
+ self.send_pty_instructions
+ .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
+ .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);
- 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));
- let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
+ if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
- new_terminal.pid,
- bottom_winsize.columns as u16,
- bottom_winsize.rows as u16,
+ *active_terminal_pid,
+ top_winsize.columns as u16,
+ top_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();
}
+
+ self.active_terminal = Some(pid);
+ self.render();
}
}
pub fn vertical_split(&mut self, pid: PaneId) {
@@ -467,7 +452,6 @@ impl Tab {
self.toggle_active_pane_fullscreen();
}
if !self.has_panes() {
- // FIXME: This could use a second look
if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.os_api.set_terminal_size_using_fd(
@@ -478,47 +462,44 @@ impl Tab {
self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid);
}
- } else {
- // FIXME: This could use a second look
- if let PaneId::Terminal(term_pid) = pid {
- // TODO: check minimum size of active terminal
- let active_pane_id = &self.get_active_pane_id().unwrap();
- let active_pane = self.panes.get_mut(active_pane_id).unwrap();
- if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 {
- self.send_pty_instructions
- .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
- .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);
+ } else if let PaneId::Terminal(term_pid) = pid {
+ // TODO: check minimum size of active terminal
+ let active_pane_id = &self.get_active_pane_id().unwrap();
+ let active_pane = self.panes.get_mut(active_pane_id).unwrap();
+ if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 {
+ self.send_pty_instructions
+ .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty
+ .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);
+ 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));
- let new_terminal = TerminalPane::new(term_pid, right_winsize);
+ if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.os_api.set_terminal_size_using_fd(
- new_terminal.pid,
- right_winsize.columns as u16,
- right_winsize.rows as u16,
+ *active_terminal_pid,
+ left_winsize.columns as u16,
+ left_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();
}
+
+ self.active_terminal = Some(pid);
+ self.render();
}
}
pub fn get_active_pane(&self) -> Option<&dyn Pane> {
@@ -562,12 +543,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()
+ }
}
_ => {}
}
@@ -645,7 +625,12 @@ impl Tab {
.expect("cannot write to stdout");
for (kind, terminal) in self.panes.iter_mut() {
if !self.panes_to_hide.contains(&terminal.pid()) {
- boundaries.add_rect(terminal.as_ref());
+ match self.active_terminal.unwrap() == terminal.pid() {
+ true => {
+ boundaries.add_rect(terminal.as_ref(), self.input_mode, Some(colors::GREEN))
+ }
+ false => boundaries.add_rect(terminal.as_ref(), self.input_mode, None),
+ }
if let Some(vte_output) = terminal.render() {
let vte_output = if let PaneId::Terminal(_) = kind {
vte_output
@@ -1679,8 +1664,8 @@ impl Tab {
} else if self.can_reduce_pane_and_surroundings_right(&active_pane_id, count) {
self.reduce_pane_and_surroundings_right(&active_pane_id, count);
}
- self.render();
}
+ self.render();
}
pub fn resize_left(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much
@@ -1691,8 +1676,8 @@ impl Tab {
} else if self.can_reduce_pane_and_surroundings_left(&active_pane_id, count) {
self.reduce_pane_and_surroundings_left(&active_pane_id, count);
}
- self.render();
}
+ self.render();
}
pub fn resize_down(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much
@@ -1703,8 +1688,8 @@ impl Tab {
} else if self.can_reduce_pane_and_surroundings_down(&active_pane_id, count) {
self.reduce_pane_and_surroundings_down(&active_pane_id, count);
}
- self.render();
}
+ self.render();
}
pub fn resize_up(&mut self) {
// TODO: find out by how much we actually reduced and only reduce by that much
@@ -1715,8 +1700,8 @@ impl Tab {
} else if self.can_reduce_pane_and_surroundings_up(&active_pane_id, count) {
self.reduce_pane_and_surroundings_up(&active_pane_id, count);
}
- self.render();
}
+ self.render();
}
pub fn move_focus(&mut self) {
if !self.has_selectable_panes() {
diff --git a/src/common/errors.rs b/src/common/errors.rs
index df741629..f5aeae85 100644
--- a/src/common/errors.rs
+++ b/src/common/errors.rs
@@ -133,7 +133,7 @@ pub enum ContextType {
Plugin(PluginContext),
/// An app-related call.
App(AppContext),
- IPCServer,
+ IpcServer,
StdinHandler,
AsyncTask,
/// An empty, placeholder call. This should be thought of as representing no call at all.
@@ -152,7 +152,7 @@ impl Display for ContextType {
ContextType::Plugin(c) => write!(f, "{}plugin_thread: {}{:?}", purple, green, c),
ContextType::App(c) => write!(f, "{}main_thread: {}{:?}", purple, green, c),
- ContextType::IPCServer => write!(f, "{}ipc_server: {}AcceptInput", purple, green),
+ ContextType::IpcServer => write!(f, "{}ipc_server: {}AcceptInput", purple, green),
ContextType::StdinHandler => {
write!(f, "{}stdin_handler_thread: {}AcceptInput", purple, green)
}
@@ -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 {
@@ -199,8 +200,10 @@ pub enum ScreenContext {
CloseTab,
GoToTab,
UpdateTabName,
+ ChangeInputMode,
}
+// 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 {
@@ -238,6 +241,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::CloseTab => ScreenContext::CloseTab,
ScreenInstruction::GoToTab(_) => ScreenContext::GoToTab,
ScreenInstruction::UpdateTabName(_) => ScreenContext::UpdateTabName,
+ ScreenInstruction::ChangeInputMode(_) => ScreenContext::ChangeInputMode,
}
}
}
@@ -276,24 +280,20 @@ use crate::wasm_vm::PluginInstruction;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PluginContext {
Load,
- Draw,
- Input,
- GlobalInput,
+ Update,
+ Render,
Unload,
Quit,
- Tabs,
}
impl From<&PluginInstruction> for PluginContext {
fn from(plugin_instruction: &PluginInstruction) -> Self {
match *plugin_instruction {
PluginInstruction::Load(..) => PluginContext::Load,
- PluginInstruction::Draw(..) => PluginContext::Draw,
- PluginInstruction::Input(..) => PluginContext::Input,
- PluginInstruction::GlobalInput(_) => PluginContext::GlobalInput,
+ PluginInstruction::Update(..) => PluginContext::Update,
+ PluginInstruction::Render(..) => PluginContext::Render,
PluginInstruction::Unload(_) => PluginContext::Unload,
PluginInstruction::Quit => PluginContext::Quit,
- PluginInstruction::UpdateTabs(..) => PluginContext::Tabs,
}
}
}
@@ -301,8 +301,6 @@ impl From<&PluginInstruction> for PluginContext {
/// Stack call representations corresponding to the different types of [`AppInstruction`]s.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AppContext {
- GetState,
- SetState,
Exit,
Error,
}
@@ -310,8 +308,6 @@ pub enum AppContext {
impl From<&AppInstruction> for AppContext {
fn from(app_instruction: &AppInstruction) -> Self {
match *app_instruction {
- AppInstruction::GetState(_) => AppContext::GetState,
- AppInstruction::SetState(_) => AppContext::SetState,
AppInstruction::Exit => AppContext::Exit,
AppInstruction::Error(_) => AppContext::Error,
}
diff --git a/src/common/input/actions.rs b/src/common/input/actions.rs
index a8a3d600..ac923f7d 100644
--- a/src/common/input/actions.rs
+++ b/src/common/input/actions.rs
@@ -1,8 +1,7 @@
//! Definition of the actions that can be bound to keys.
-use super::handler;
-//use super::macros;
use serde::{Deserialize, Serialize};
+use zellij_tile::data::InputMode;
/// The four directions (left, right, up, down).
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
@@ -21,7 +20,7 @@ pub enum Action {
/// Write to the terminal.
Write(Vec<u8>),
/// Switch to the specified input mode.
- SwitchToMode(handler::InputMode),
+ SwitchToMode(InputMode),
/// Resize focus pane in specified direction.
Resize(Direction),
/// Switch focus to next pane in specified direction.
@@ -51,5 +50,4 @@ pub enum Action {
CloseTab,
GoToTab(u32),
TabNameInput(Vec<u8>),
- SaveTabName,
}
diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs
index 49d87124..0d30530a 100644
--- a/src/common/input/handler.rs
+++ b/src/common/input/handler.rs
@@ -3,17 +3,16 @@
use super::actions::Action;
use super::keybinds::Keybinds;
use crate::common::input::config::Config;
-use crate::common::{update_state, AppInstruction, AppState, SenderWithContext, OPENCALLS};
+use crate::common::{AppInstruction, SenderWithContext, OPENCALLS};
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::PluginInstruction;
use crate::CommandIsExecuting;
-use serde::{Deserialize, Serialize};
-use strum_macros::EnumIter;
-use termion::input::TermReadEventsAndRaw;
+use termion::input::{TermRead, TermReadEventsAndRaw};
+use zellij_tile::data::{Event, InputMode, Key, ModeInfo};
/// Handles the dispatching of [`Action`]s according to the current
/// [`InputMode`], and keep tracks of the current [`InputMode`].
@@ -64,27 +63,22 @@ impl InputHandler {
'input_loop: loop {
//@@@ I think this should actually just iterate over stdin directly
let stdin_buffer = self.os_input.read_from_stdin();
- 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 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
// been revised. Sorry about this (@categorille)
- if {
- let mut should_break = false;
- for action in
- Keybinds::key_to_actions(&key, raw_bytes, &self.mode, &keybinds)
- {
- should_break |= self.dispatch_action(action);
- }
- should_break
- } {
+ let mut should_break = false;
+ for action in
+ Keybinds::key_to_actions(&key, raw_bytes, &self.mode, &keybinds)
+ {
+ should_break |= self.dispatch_action(action);
+ }
+ if should_break {
break 'input_loop;
}
}
@@ -127,9 +121,15 @@ impl InputHandler {
}
Action::SwitchToMode(mode) => {
self.mode = mode;
- update_state(&self.send_app_instructions, |_| AppState {
- input_mode: self.mode,
- });
+ self.send_plugin_instructions
+ .send(PluginInstruction::Update(
+ None,
+ Event::ModeUpdate(get_mode_info(mode)),
+ ))
+ .unwrap();
+ self.send_screen_instructions
+ .send(ScreenInstruction::ChangeInputMode(mode))
+ .unwrap();
self.send_screen_instructions
.send(ScreenInstruction::Render)
.unwrap();
@@ -230,27 +230,10 @@ impl InputHandler {
.unwrap();
}
Action::TabNameInput(c) => {
- self.send_plugin_instructions
- .send(PluginInstruction::Input(
- PluginInputType::Event(EventType::Tab),
- c.clone(),
- ))
- .unwrap();
self.send_screen_instructions
.send(ScreenInstruction::UpdateTabName(c))
.unwrap();
}
- Action::SaveTabName => {
- self.send_plugin_instructions
- .send(PluginInstruction::Input(
- PluginInputType::Event(EventType::Tab),
- vec![b'\n'],
- ))
- .unwrap();
- self.send_screen_instructions
- .send(ScreenInstruction::UpdateTabName(vec![b'\n']))
- .unwrap();
- }
Action::NoOp => {}
}
@@ -266,52 +249,10 @@ impl InputHandler {
}
}
-/// 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 {
- /// In `Normal` mode, input is always written to the terminal, except for the shortcuts leading
- /// to other modes
- #[serde(alias = "normal")]
- Normal,
- /// In `Locked` mode, input is always written to the terminal and all shortcuts are disabled
- /// except the one leading back to normal mode
- #[serde(alias = "locked")]
- Locked,
- /// `Resize` mode allows resizing the different existing panes.
- #[serde(alias = "resize")]
- Resize,
- /// `Pane` mode allows creating and closing panes, as well as moving between them.
- #[serde(alias = "pane")]
- Pane,
- /// `Tab` mode allows creating and closing tabs, as well as moving between them.
- #[serde(alias = "tab")]
- Tab,
- /// `Scroll` mode allows scrolling up and down within a pane.
- #[serde(alias = "scroll")]
- Scroll,
- #[serde(alias = "renametab")]
- RenameTab,
-}
-
-/// Represents the contents of the help message that is printed in the status bar,
-/// which indicates the current [`InputMode`] and what the keybinds for that mode
-/// are. Related to the default `status-bar` plugin.
-#[derive(Default, Debug, Clone, Serialize, Deserialize)]
-pub struct Help {
- pub mode: InputMode,
- pub keybinds: Vec<(String, String)>, // <shortcut> => <shortcut description>
-}
-
-impl Default for InputMode {
- fn default() -> InputMode {
- InputMode::Normal
- }
-}
-
/// Creates a [`Help`] struct indicating the current [`InputMode`] and its keybinds
/// (as pairs of [`String`]s).
// TODO this should probably be automatically generated in some way
-pub fn get_help(mode: InputMode) -> Help {
+pub fn get_mode_info(mode: InputMode) -> ModeInfo {
let mut keybinds: Vec<(String, String)> = vec![];
match mode {
InputMode::Normal | InputMode::Locked => {}
@@ -340,7 +281,7 @@ pub fn get_help(mode: InputMode) -> Help {
keybinds.push(("Enter".to_string(), "when done".to_string()));
}
}
- Help { mode, keybinds }
+ ModeInfo { mode, keybinds }
}
/// Entry point to the module. Instantiates an [`InputHandler`] and starts
@@ -365,3 +306,35 @@ 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 {
+ 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 c70123b6..6a14a182 100644
--- a/src/common/input/keybinds.rs
+++ b/src/common/input/keybinds.rs
@@ -2,11 +2,10 @@
use std::collections::HashMap;
use super::actions::{Action, Direction};
-use super::handler::InputMode;
use serde::Deserialize;
use strum::IntoEnumIterator;
-use termion::event::Key;
+use zellij_tile::data::*;
#[derive(Clone, Debug, PartialEq)]
pub struct Keybinds(HashMap<InputMode, ModeKeybinds>);
@@ -275,10 +274,7 @@ impl Keybinds {
defaults.insert(Key::Up, vec![Action::ScrollUp]);
}
InputMode::RenameTab => {
- defaults.insert(
- Key::Char('\n'),
- vec![Action::SaveTabName, Action::SwitchToMode(InputMode::Tab)],
- );
+ defaults.insert(Key::Char('\n'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Normal)],
diff --git a/src/common/input/unit/keybinds_test.rs b/src/common/input/unit/keybinds_test.rs
index 2b306bc3..6411d017 100644
--- a/src/common/input/unit/keybinds_test.rs
+++ b/src/common/input/unit/keybinds_test.rs
@@ -1,6 +1,6 @@
use super::super::actions::*;
use super::super::keybinds::*;
-use termion::event::Key;
+use zellij_tile::data::Key;
#[test]
fn merge_keybinds_merges_different_keys() {
diff --git a/src/common/ipc.rs b/src/common/ipc.rs
index 77d57df3..81576b86 100644
--- a/src/common/ipc.rs
+++ b/src/common/ipc.rs
@@ -3,12 +3,12 @@
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
-type SessionID = u64;
+type SessionId = u64;
#[derive(PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct Session {
// Unique ID for this session
- id: SessionID,
+ id: SessionId,
// Identifier for the underlying IPC primitive (socket, pipe)
conn_name: String,
// User configured alias for the session
@@ -30,9 +30,9 @@ pub enum ClientToServerMsg {
// Create a new session
CreateSession,
// Attach to a running session
- AttachToSession(SessionID, ClientType),
+ AttachToSession(SessionId, ClientType),
// Force detach
- DetachSession(SessionID),
+ DetachSession(SessionId),
// Disconnect from the session we're connected to
DisconnectFromSession,
}
diff --git a/src/common/mod.rs b/src/common/mod.rs
index 777b615f..57c21155 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -9,35 +9,36 @@ pub mod screen;
pub mod utils;
pub mod wasm_vm;
-use std::io::Write;
-use std::path::{Path, PathBuf};
+use std::cell::RefCell;
+use std::path::PathBuf;
use std::sync::mpsc;
use std::thread;
-use std::{cell::RefCell, sync::mpsc::TrySendError};
use std::{collections::HashMap, fs};
-
-use crate::panes::PaneId;
-use directories_next::ProjectDirs;
-use input::handler::InputMode;
-use serde::{Deserialize, Serialize};
-use termion::input::TermRead;
-use wasm_vm::PluginEnv;
-use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
-use wasmer_wasi::{Pipe, WasiState};
+use std::{
+ collections::HashSet,
+ io::Write,
+ str::FromStr,
+ sync::{Arc, Mutex},
+};
use crate::cli::CliArgs;
use crate::common::input::config::Config;
use crate::layout::Layout;
+use crate::panes::PaneId;
use command_is_executing::CommandIsExecuting;
+use directories_next::ProjectDirs;
use errors::{AppContext, ContextType, ErrorContext, PluginContext, PtyContext, ScreenContext};
use input::handler::input_loop;
use os_input_output::OsApi;
use pty_bus::{PtyBus, PtyInstruction};
use screen::{Screen, ScreenInstruction};
-use utils::consts::{ZELLIJ_IPC_PIPE, ZELLIJ_ROOT_PLUGIN_DIR};
-use wasm_vm::{
- wasi_stdout, wasi_write_string, zellij_imports, EventType, PluginInputType, PluginInstruction,
-};
+use serde::{Deserialize, Serialize};
+use utils::consts::ZELLIJ_IPC_PIPE;
+use wasm_vm::PluginEnv;
+use wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginInstruction};
+use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
+use wasmer_wasi::{Pipe, WasiState};
+use zellij_tile::data::{EventType, InputMode};
#[derive(Serialize, Deserialize, Debug)]
pub enum ApiCommand {
@@ -46,33 +47,6 @@ pub enum ApiCommand {
SplitVertically,
MoveFocus,
}
-// FIXME: It would be good to add some more things to this over time
-#[derive(Debug, Clone)]
-pub struct AppState {
- pub input_mode: InputMode,
-}
-
-impl Default for AppState {
- fn default() -> Self {
- AppState {
- input_mode: InputMode::default(),
- }
- }
-}
-
-// FIXME: Make this a method on the big `Communication` struct, so that app_tx can be extracted
-// from self instead of being explicitly passed here
-pub fn update_state(
- app_tx: &SenderWithContext<AppInstruction>,
- update_fn: impl FnOnce(AppState) -> AppState,
-) {
- let (state_tx, state_rx) = mpsc::channel();
-
- drop(app_tx.send(AppInstruction::GetState(state_tx)));
- let state = state_rx.recv().unwrap();
-
- drop(app_tx.send(AppInstruction::SetState(update_fn(state))))
-}
/// An [MPSC](mpsc) asynchronous channel with added error context.
pub type ChannelWithContext<T> = (
@@ -116,19 +90,6 @@ impl<T: Clone> SenderWithContext<T> {
}
}
- /// Attempts to send an event on this sender's channel, terminating instead of blocking
- /// if the event could not be sent (buffer full or connection closed).
- ///
- /// This can only be called on [`SyncSender`](SenderType::SyncSender)s, and will
- /// panic if called on an asynchronous [`Sender`](SenderType::Sender).
- pub fn try_send(&self, event: T) -> Result<(), TrySendError<(T, ErrorContext)>> {
- if let SenderType::SyncSender(ref s) = self.sender {
- s.try_send((event, self.err_ctx))
- } else {
- panic!("try_send can only be called on SyncSenders!")
- }
- }
-
/// Updates this [`SenderWithContext`]'s [`ErrorContext`]. This is the way one adds
/// a call to the error context.
///
@@ -151,8 +112,6 @@ thread_local!(
/// Instructions related to the entire application.
#[derive(Clone)]
pub enum AppInstruction {
- GetState(mpsc::Sender<AppState>),
- SetState(AppState),
Exit,
Error(String),
}
@@ -167,8 +126,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.write(take_snapshot.as_bytes())
.unwrap();
- let mut app_state = AppState::default();
-
let config = Config::from_cli_config(opts.config)
.map_err(|e| {
eprintln!("There was an error in the config file:\n{}", e);
@@ -307,6 +264,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
&full_screen_ws,
os_input,
max_panes,
+ InputMode::Normal,
);
loop {
let (event, mut err_ctx) = screen
@@ -398,8 +356,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.get_active_tab_mut()
.unwrap()
.set_pane_selectable(id, selectable);
- // FIXME: Is this needed?
- screen.render();
}
ScreenInstruction::SetMaxHeight(id, max_height) => {
screen
@@ -441,6 +397,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
ScreenInstruction::UpdateTabName(c) => {
screen.update_active_tab_name(c);
}
+ ScreenInstruction::ChangeInputMode(input_mode) => {
+ screen.change_input_mode(input_mode);
+ }
ScreenInstruction::Quit => {
break;
}
@@ -460,12 +419,6 @@ 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())]
- .iter()
- .cloned()
- .collect();
-
move || loop {
let (event, mut err_ctx) = receive_plugin_instructions
.recv()
@@ -475,18 +428,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
send_pty_instructions.update(err_ctx);
send_app_instructions.update(err_ctx);
match event {
- PluginInstruction::Load(pid_tx, path, events) => {
+ PluginInstruction::Load(pid_tx, path) => {
let project_dirs =
ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
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)
.or_else(|_| fs::read(&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()));
// FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that
@@ -517,7 +465,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,
- events,
+ subscriptions: Arc::new(Mutex::new(HashSet::new())),
};
let zellij = zellij_imports(&store, &plugin_env);
@@ -532,88 +480,33 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
pid_tx.send(plugin_id).unwrap();
plugin_id += 1;
}
- PluginInstruction::Draw(buf_tx, pid, rows, cols) => {
+ 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();
- let draw = instance.exports.get_function("draw").unwrap();
+ let render = instance.exports.get_function("render").unwrap();
- draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)])
+ render
+ .call(&[Value::I32(rows as i32), Value::I32(cols as i32)])
.unwrap();
buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap();
}
- PluginInstruction::UpdateTabs(mut tabs) => {
- for (instance, plugin_env) in plugin_map.values() {
- if !plugin_env.events.contains(&EventType::Tab) {
- continue;
- }
- let handler = instance.exports.get_function("update_tabs").unwrap();
- tabs.sort_by(|a, b| a.position.cmp(&b.position));
- wasi_write_string(
- &plugin_env.wasi_env,
- &serde_json::to_string(&tabs).unwrap(),
- );
- handler.call(&[]).unwrap();
- }
- }
- // 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();
- for key in input_bytes.keys() {
- if let Ok(key) = key {
- wasi_write_string(
- &plugin_env.wasi_env,
- &serde_json::to_string(&key).unwrap(),
- );
- 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() {
- if let Ok(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() {
- if let Ok(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,
}
@@ -636,7 +529,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let listener = std::os::unix::net::UnixListener::bind(ZELLIJ_IPC_PIPE)
.expect("could not listen on ipc socket");
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
- err_ctx.add_call(ContextType::IPCServer);
+ err_ctx.add_call(ContextType::IpcServer);
send_pty_instructions.update(err_ctx);
send_screen_instructions.update(err_ctx);
@@ -713,8 +606,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
send_screen_instructions.update(err_ctx);
send_pty_instructions.update(err_ctx);
match app_instruction {
- AppInstruction::GetState(state_tx) => drop(state_tx.send(app_state.clone())),
- AppInstruction::SetState(state) => app_state = state,
AppInstruction::Exit => {
break;
}
diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs
index 26a7d497..043a9aea 100644
--- a/src/common/os_input_output.rs
+++ b/src/common/os_input_output.rs
@@ -82,15 +82,10 @@ fn handle_command_exit(mut child: Child) {
}
for signal in signals.pending() {
- // FIXME: We need to handle more signals here!
- #[allow(clippy::single_match)]
- match signal {
- signal_hook::SIGINT => {
- child.kill().unwrap();
- child.wait().unwrap();
- break 'handle_exit;
- }
- _ => {}
+ if signal == signal_hook::SIGINT {
+ child.kill().unwrap();
+ child.wait().unwrap();
+ break 'handle_exit;
}
}
}
diff --git a/src/common/screen.rs b/src/common/screen.rs
index 199a1223..5208834a 100644
--- a/src/common/screen.rs
+++ b/src/common/screen.rs
@@ -9,10 +9,12 @@ use super::{AppInstruction, SenderWithContext};
use crate::os_input_output::OsApi;
use crate::panes::PositionAndSize;
use crate::pty_bus::{PtyInstruction, VteEvent};
-use crate::tab::{Tab, TabData};
+use crate::tab::Tab;
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};
use crate::{layout::Layout, panes::PaneId};
+use zellij_tile::data::{Event, InputMode, TabInfo};
+
/// Instructions that can be sent to the [`Screen`].
#[derive(Debug, Clone)]
pub enum ScreenInstruction {
@@ -48,6 +50,7 @@ pub enum ScreenInstruction {
CloseTab,
GoToTab(u32),
UpdateTabName(Vec<u8>),
+ ChangeInputMode(InputMode),
}
/// A [`Screen`] holds multiple [`Tab`]s, each one holding multiple [`panes`](crate::client::panes).
@@ -71,7 +74,7 @@ pub struct Screen {
active_tab_index: Option<usize>,
/// The [`OsApi`] this [`Screen`] uses.
os_api: Box<dyn OsApi>,
- tabname_buf: String,
+ input_mode: InputMode,
}
impl Screen {
@@ -84,6 +87,7 @@ impl Screen {
full_screen_ws: &PositionAndSize,
os_api: Box<dyn OsApi>,
max_panes: Option<usize>,
+ input_mode: InputMode,
) -> Self {
Screen {
receiver: receive_screen_instructions,
@@ -95,7 +99,7 @@ impl Screen {
active_tab_index: None,
tabs: BTreeMap::new(),
os_api,
- tabname_buf: String::new(),
+ input_mode,
}
}
@@ -115,6 +119,7 @@ impl Screen {
self.send_app_instructions.clone(),
self.max_panes,
Some(PaneId::Terminal(pane_id)),
+ self.input_mode,
);
self.active_tab_index = Some(tab_index);
self.tabs.insert(tab_index, tab);
@@ -169,15 +174,12 @@ impl Screen {
pub fn go_to_tab(&mut self, mut tab_index: usize) {
tab_index -= 1;
let active_tab = self.get_active_tab().unwrap();
- match self.tabs.values().find(|t| t.position == tab_index) {
- Some(t) => {
- if t.index != active_tab.index {
- self.active_tab_index = Some(t.index);
- self.update_tabs();
- self.render();
- }
+ if let Some(t) = self.tabs.values().find(|t| t.position == tab_index) {
+ if t.index != active_tab.index {
+ self.active_tab_index = Some(t.index);
+ self.update_tabs();
+ self.render();
}
- None => {}
}
}
@@ -259,6 +261,7 @@ impl Screen {
self.send_app_instructions.clone(),
self.max_panes,
None,
+ self.input_mode,
);
tab.apply_layout(layout, new_pids);
self.active_tab_index = Some(tab_index);
@@ -270,33 +273,38 @@ 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,
});
}
self.send_plugin_instructions
- .send(PluginInstruction::UpdateTabs(tab_data))
+ .send(PluginInstruction::Update(None, Event::TabUpdate(tab_data)))
.unwrap();
}
pub fn update_active_tab_name(&mut self, buf: Vec<u8>) {
let s = str::from_utf8(&buf).unwrap();
+ let active_tab = self.get_active_tab_mut().unwrap();
match s {
"\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}" => {
+ //delete and backspace keys
+ active_tab.name.pop();
}
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) {
+ self.input_mode = input_mode;
+ for tab in self.tabs.values_mut() {
+ tab.input_mode = self.input_mode;
+ }
}
}
diff --git a/src/common/utils/consts.rs b/src/common/utils/consts.rs
index fa9eee0d..663a545d 100644
--- a/src/common/utils/consts.rs
+++ b/src/common/utils/consts.rs
@@ -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_FILE: &str = "/tmp/zellij/zellij-log/log.txt";
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";
diff --git a/src/common/wasm_vm.rs b/src/common/wasm_vm.rs
index 15b920ad..29b110ae 100644
--- a/src/common/wasm_vm.rs
+++ b/src/common/wasm_vm.rs
@@ -1,36 +1,22 @@
-use crate::tab::TabData;
-use serde::{Deserialize, Serialize};
use std::{
+ collections::HashSet,
path::PathBuf,
- sync::mpsc::{channel, Sender},
+ sync::{mpsc::Sender, Arc, Mutex},
};
use wasmer::{imports, Function, ImportObject, Store, WasmerEnv};
use wasmer_wasi::WasiEnv;
+use zellij_tile::data::{Event, EventType};
use super::{
- input::handler::get_help, 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 EventType {
- Tab,
-}
-
-#[derive(Clone, Debug)]
-pub enum PluginInputType {
- Normal(u32),
- Event(EventType),
-}
-
#[derive(Clone, Debug)]
pub enum PluginInstruction {
- Load(Sender<u32>, PathBuf, Vec<EventType>),
- 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
+ Load(Sender<u32>, PathBuf),
+ Update(Option<u32>, Event), // Focused plugin / broadcast, event data
+ Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
Unload(u32),
- UpdateTabs(Vec<TabData>), // num tabs, active tab
Quit,
}
@@ -41,7 +27,7 @@ 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>>>,
}
// Plugin API ---------------------------------------------------------------------------------------------------------
@@ -49,16 +35,28 @@ 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),
"host_set_selectable" => Function::new_native_with_env(store, plugin_env.clone(), host_set_selectable),
- "host_get_help" => Function::new_native_with_env(store, plugin_env.clone(), host_get_help),
}
}
}
-// 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 +65,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
@@ -101,21 +98,6 @@ fn host_set_invisible_borders(plugin_env: &PluginEnv, invisible_borders: i32) {
.unwrap()
}
-fn host_get_help(plugin_env: &PluginEnv) {
- let (state_tx, state_rx) = channel();
- // FIXME: If I changed the application so that threads were sent the termination
- // signal and joined one at a time, there would be an order to shutdown, so I
- // could get rid of this .is_ok() check and the .try_send()
- if plugin_env
- .send_app_instructions
- .try_send(AppInstruction::GetState(state_tx))
- .is_ok()
- {
- let help = get_help(state_rx.recv().unwrap().input_mode);
- wasi_write_string(&plugin_env.wasi_env, &serde_json::to_string(&help).unwrap());
- }
-}
-
// Helper Functions ---------------------------------------------------------------------------------------------------
// FIXME: Unwrap city
diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs
index fa9c6f0e..c800de97 100644
--- a/src/tests/fakes.rs
+++ b/src/tests/fakes.rs
@@ -10,6 +10,8 @@ use std::time::{Duration, Instant};
use crate::os_input_output::OsApi;
use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
+use crate::tests::utils::commands::SLEEP;
+
const MIN_TIME_BETWEEN_SNAPSHOTS: Duration = Duration::from_millis(50);
#[derive(Clone)]
@@ -189,11 +191,16 @@ impl OsApi for FakeInputOutput {
::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS - last_snapshot_time.elapsed());
}
}
- self.stdin_commands
+ let command = self
+ .stdin_commands
.lock()
.unwrap()
.pop_front()
- .unwrap_or(vec![])
+ .unwrap_or(vec![]);
+ if command == SLEEP {
+ std::thread::sleep(std::time::Duration::from_millis(200));
+ }
+ command
}
fn get_stdout_writer(&self) -> Box<dyn Write> {
Box::new(self.stdout_writer.clone())
diff --git a/src/tests/integration/expansion_boundary.rs b/src/tests/integration/expansion_boundary.rs
index 7cb0b0f7..c68c1d5a 100644
--- a/src/tests/integration/expansion_boundary.rs
+++ b/src/tests/integration/expansion_boundary.rs
@@ -4,7 +4,7 @@ use std::path::PathBuf;
use crate::panes::PositionAndSize;
use crate::tests::fakes::FakeInputOutput;
use crate::tests::utils::commands::{
- PANE_MODE, QUIT, RESIZE_DOWN_IN_RESIZE_MODE, RESIZE_MODE, SPAWN_TERMINAL_IN_PANE_MODE,
+ PANE_MODE, QUIT, RESIZE_DOWN_IN_RESIZE_MODE, RESIZE_MODE, SLEEP, SPAWN_TERMINAL_IN_PANE_MODE,
TOGGLE_ACTIVE_TERMINAL_FULLSCREEN_IN_PANE_MODE,
};
use crate::tests::utils::{get_next_to_last_snapshot, get_output_frame_snapshots};
@@ -23,7 +23,12 @@ pub fn new_panes_are_open_inside_expansion_border() {
y: 0,
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
- fake_input_output.add_terminal_input(&[&PANE_MODE, &SPAWN_TERMINAL_IN_PANE_MODE, &QUIT]);
+ fake_input_output.add_terminal_input(&[
+ &PANE_MODE,
+ &SPAWN_TERMINAL_IN_PANE_MODE,
+ &SLEEP,
+ &QUIT,
+ ]);
let mut opts = CliArgs::default();
opts.layout = Some(PathBuf::from(
"src/tests/fixtures/layouts/expansion-boundary-in-the-middle.yaml",
@@ -55,6 +60,7 @@ pub fn resize_pane_inside_expansion_border() {
&SPAWN_TERMINAL_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
let mut opts = CliArgs::default();
@@ -87,6 +93,7 @@ pub fn toggling_fullcsreen_in_expansion_border_expands_only_until_border() {
&PANE_MODE,
&SPAWN_TERMINAL_IN_PANE_MODE,
&TOGGLE_ACTIVE_TERMINAL_FULLSCREEN_IN_PANE_MODE,
+ &SLEEP,
&QUIT,
]);
let mut opts = CliArgs::default();
diff --git a/src/tests/integration/resize_down.rs b/src/tests/integration/resize_down.rs
index 0171cea2..4957b33e 100644
--- a/src/tests/integration/resize_down.rs
+++ b/src/tests/integration/resize_down.rs
@@ -7,7 +7,8 @@ use crate::{start, CliArgs};
use crate::tests::utils::commands::{
MOVE_FOCUS_IN_PANE_MODE, PANE_MODE, QUIT, RESIZE_DOWN_IN_RESIZE_MODE,
- RESIZE_LEFT_IN_RESIZE_MODE, RESIZE_MODE, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
+ RESIZE_LEFT_IN_RESIZE_MODE, RESIZE_MODE, SLEEP, SPLIT_DOWN_IN_PANE_MODE,
+ SPLIT_RIGHT_IN_PANE_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@@ -37,6 +38,7 @@ pub fn resize_down_with_pane_above() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -75,6 +77,7 @@ pub fn resize_down_with_pane_below() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -118,6 +121,7 @@ pub fn resize_down_with_panes_above_and_below() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -160,6 +164,7 @@ pub fn resize_down_with_multiple_panes_above() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -205,6 +210,7 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -249,6 +255,7 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -291,6 +298,7 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -334,6 +342,7 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -380,6 +389,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -428,6 +438,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -493,6 +504,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -560,6 +572,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -596,6 +609,7 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_DOWN_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
diff --git a/src/tests/integration/resize_left.rs b/src/tests/integration/resize_left.rs
index 0d0d61a5..a9d229d9 100644
--- a/src/tests/integration/resize_left.rs
+++ b/src/tests/integration/resize_left.rs
@@ -7,7 +7,7 @@ use crate::{start, CliArgs};
use crate::tests::utils::commands::{
MOVE_FOCUS_IN_PANE_MODE, PANE_MODE, QUIT, RESIZE_LEFT_IN_RESIZE_MODE, RESIZE_MODE,
- RESIZE_UP_IN_RESIZE_MODE, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
+ RESIZE_UP_IN_RESIZE_MODE, SLEEP, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@@ -34,6 +34,7 @@ pub fn resize_left_with_pane_to_the_left() {
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -70,6 +71,7 @@ pub fn resize_left_with_pane_to_the_right() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -108,6 +110,7 @@ pub fn resize_left_with_panes_to_the_left_and_right() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -148,6 +151,7 @@ pub fn resize_left_with_multiple_panes_to_the_left() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -191,6 +195,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -231,6 +236,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -273,6 +279,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -314,6 +321,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -360,6 +368,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -408,6 +417,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -473,6 +483,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -541,6 +552,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -577,6 +589,7 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() {
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
diff --git a/src/tests/integration/resize_right.rs b/src/tests/integration/resize_right.rs
index 8f1928ee..fef33e84 100644
--- a/src/tests/integration/resize_right.rs
+++ b/src/tests/integration/resize_right.rs
@@ -7,7 +7,7 @@ use crate::{start, CliArgs};
use crate::tests::utils::commands::{
MOVE_FOCUS_IN_PANE_MODE, PANE_MODE, QUIT, RESIZE_MODE, RESIZE_RIGHT_IN_RESIZE_MODE,
- RESIZE_UP_IN_RESIZE_MODE, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
+ RESIZE_UP_IN_RESIZE_MODE, SLEEP, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@@ -34,6 +34,7 @@ pub fn resize_right_with_pane_to_the_left() {
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -70,6 +71,7 @@ pub fn resize_right_with_pane_to_the_right() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -108,6 +110,7 @@ pub fn resize_right_with_panes_to_the_left_and_right() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -148,6 +151,7 @@ pub fn resize_right_with_multiple_panes_to_the_left() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -191,6 +195,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -231,6 +236,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -273,6 +279,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -314,6 +321,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -360,6 +368,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -408,6 +417,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -473,6 +483,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -540,6 +551,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -576,6 +588,7 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() {
&SPLIT_RIGHT_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_RIGHT_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
diff --git a/src/tests/integration/resize_up.rs b/src/tests/integration/resize_up.rs
index 2df6dfa7..9d4dd05a 100644
--- a/src/tests/integration/resize_up.rs
+++ b/src/tests/integration/resize_up.rs
@@ -7,7 +7,7 @@ use crate::{start, CliArgs};
use crate::tests::utils::commands::{
MOVE_FOCUS_IN_PANE_MODE, PANE_MODE, QUIT, RESIZE_LEFT_IN_RESIZE_MODE, RESIZE_MODE,
- RESIZE_UP_IN_RESIZE_MODE, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
+ RESIZE_UP_IN_RESIZE_MODE, SLEEP, SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@@ -36,6 +36,7 @@ pub fn resize_up_with_pane_above() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -74,6 +75,7 @@ pub fn resize_up_with_pane_below() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -117,6 +119,7 @@ pub fn resize_up_with_panes_above_and_below() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
@@ -158,6 +161,7 @@ pub fn resize_up_with_multiple_panes_above() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -201,6 +205,7 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -245,6 +250,7 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -287,6 +293,7 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -330,6 +337,7 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -376,6 +384,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -424,6 +433,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() {
&MOVE_FOCUS_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -489,6 +499,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -556,6 +567,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_LEFT_IN_RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
@@ -592,6 +604,7 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() {
&SPLIT_DOWN_IN_PANE_MODE,
&RESIZE_MODE,
&RESIZE_UP_IN_RESIZE_MODE,
+ &SLEEP,
&QUIT,
]);
start(Box::new(fake_input_output.clone()), CliArgs::default());
diff --git a/src/tests/utils.rs b/src/tests/utils.rs
index 86973d74..14f4cfa0 100644
--- a/src/tests/utils.rs
+++ b/src/tests/utils.rs
@@ -76,4 +76,5 @@ pub mod commands {
pub const SWITCH_NEXT_TAB_IN_TAB_MODE: [u8; 1] = [108]; // l
pub const SWITCH_PREV_TAB_IN_TAB_MODE: [u8; 1] = [104]; // h
pub const CLOSE_TAB_IN_TAB_MODE: [u8; 1] = [120]; // x
+ pub const SLEEP: [u8; 0] = [];
}