feat(plugins): introduce plugin aliases (#3157)
* working prototype with passing tests * new tests and passing plugin tests as well * style(code): cleanups * cleanup strider from unused search feature * prototype of removing old plugin block from the config * aliases working from config file and all tests passing * fixups and cleanups * use aliases in layouts * update test snapshot * style(fmt): rustfmt
This commit is contained in:
parent
27bffbf153
commit
21273ac95a
71 changed files with 2097 additions and 3242 deletions
|
|
@ -1,49 +1,22 @@
|
||||||
mod search;
|
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use search::{FileContentsWorker, FileNameWorker, MessageToSearch, ResultsOfSearch};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json;
|
|
||||||
use state::{refresh_directory, FsEntry, State};
|
use state::{refresh_directory, FsEntry, State};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::{cmp::min, time::Instant};
|
use std::{cmp::min, time::Instant};
|
||||||
use zellij_tile::prelude::*;
|
use zellij_tile::prelude::*;
|
||||||
|
|
||||||
register_plugin!(State);
|
register_plugin!(State);
|
||||||
register_worker!(FileNameWorker, file_name_search_worker, FILE_NAME_WORKER);
|
|
||||||
register_worker!(
|
|
||||||
FileContentsWorker,
|
|
||||||
file_contents_search_worker,
|
|
||||||
FILE_CONTENTS_WORKER
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ZellijPlugin for State {
|
impl ZellijPlugin for State {
|
||||||
fn load(&mut self, _configuration: BTreeMap<String, String>) {
|
fn load(&mut self, _configuration: BTreeMap<String, String>) {
|
||||||
refresh_directory(self);
|
refresh_directory(self);
|
||||||
self.search_state.loading = true;
|
|
||||||
subscribe(&[
|
subscribe(&[
|
||||||
EventType::Key,
|
EventType::Key,
|
||||||
EventType::Mouse,
|
EventType::Mouse,
|
||||||
EventType::CustomMessage,
|
EventType::CustomMessage,
|
||||||
EventType::Timer,
|
EventType::Timer,
|
||||||
EventType::FileSystemCreate,
|
|
||||||
EventType::FileSystemUpdate,
|
|
||||||
EventType::FileSystemDelete,
|
|
||||||
EventType::PermissionRequestResult,
|
|
||||||
]);
|
]);
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_name_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
|
||||||
payload: "".into(),
|
|
||||||
});
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_contents_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
|
||||||
payload: "".into(),
|
|
||||||
});
|
|
||||||
self.search_state.loading = true;
|
|
||||||
set_timeout(0.5); // for displaying loading animation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, event: Event) -> bool {
|
fn update(&mut self, event: Event) -> bool {
|
||||||
|
|
@ -55,58 +28,8 @@ impl ZellijPlugin for State {
|
||||||
};
|
};
|
||||||
self.ev_history.push_back((event.clone(), Instant::now()));
|
self.ev_history.push_back((event.clone(), Instant::now()));
|
||||||
match event {
|
match event {
|
||||||
Event::PermissionRequestResult(_) => {
|
|
||||||
should_render = true;
|
|
||||||
},
|
|
||||||
Event::Timer(_elapsed) => {
|
|
||||||
if self.search_state.loading {
|
|
||||||
set_timeout(0.5);
|
|
||||||
self.search_state.progress_animation();
|
|
||||||
should_render = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::CustomMessage(message, payload) => match serde_json::from_str(&message) {
|
|
||||||
Ok(MessageToPlugin::UpdateFileNameSearchResults) => {
|
|
||||||
if let Ok(results_of_search) = serde_json::from_str::<ResultsOfSearch>(&payload)
|
|
||||||
{
|
|
||||||
self.search_state
|
|
||||||
.update_file_name_search_results(results_of_search);
|
|
||||||
should_render = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(MessageToPlugin::UpdateFileContentsSearchResults) => {
|
|
||||||
if let Ok(results_of_search) = serde_json::from_str::<ResultsOfSearch>(&payload)
|
|
||||||
{
|
|
||||||
self.search_state
|
|
||||||
.update_file_contents_search_results(results_of_search);
|
|
||||||
should_render = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(MessageToPlugin::DoneScanningFolder) => {
|
|
||||||
self.search_state.loading = false;
|
|
||||||
should_render = true;
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("Failed to deserialize custom message: {:?}", e),
|
|
||||||
},
|
|
||||||
Event::Key(key) => match key {
|
Event::Key(key) => match key {
|
||||||
Key::Esc if self.typing_search_term() => {
|
|
||||||
if self.search_state.search_term.is_empty() {
|
|
||||||
self.stop_typing_search_term();
|
|
||||||
} else {
|
|
||||||
self.search_state.handle_key(key);
|
|
||||||
}
|
|
||||||
should_render = true;
|
|
||||||
},
|
|
||||||
_ if self.typing_search_term() => {
|
|
||||||
self.search_state.handle_key(key);
|
|
||||||
should_render = true;
|
|
||||||
},
|
|
||||||
Key::Char('/') => {
|
|
||||||
self.start_typing_search_term();
|
|
||||||
should_render = true;
|
|
||||||
},
|
|
||||||
Key::Esc => {
|
Key::Esc => {
|
||||||
self.stop_typing_search_term();
|
|
||||||
hide_self();
|
hide_self();
|
||||||
should_render = true;
|
should_render = true;
|
||||||
},
|
},
|
||||||
|
|
@ -190,54 +113,6 @@ impl ZellijPlugin for State {
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
Event::FileSystemCreate(paths) => {
|
|
||||||
let paths: Vec<String> = paths
|
|
||||||
.iter()
|
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
|
||||||
.collect();
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_name_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_contents_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Event::FileSystemUpdate(paths) => {
|
|
||||||
let paths: Vec<String> = paths
|
|
||||||
.iter()
|
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
|
||||||
.collect();
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_name_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_contents_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Event::FileSystemDelete(paths) => {
|
|
||||||
let paths: Vec<String> = paths
|
|
||||||
.iter()
|
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
|
||||||
.collect();
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_name_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_contents_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
|
||||||
payload: serde_json::to_string(&paths).unwrap(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
dbg!("Unknown event {:?}", event);
|
dbg!("Unknown event {:?}", event);
|
||||||
},
|
},
|
||||||
|
|
@ -246,12 +121,6 @@ impl ZellijPlugin for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, rows: usize, cols: usize) {
|
fn render(&mut self, rows: usize, cols: usize) {
|
||||||
if self.typing_search_term() {
|
|
||||||
self.search_state.change_size(rows, cols);
|
|
||||||
print!("{}", self.search_state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..rows {
|
for i in 0..rows {
|
||||||
if self.selected() < self.scroll() {
|
if self.selected() < self.scroll() {
|
||||||
*self.scroll_mut() = self.selected();
|
*self.scroll_mut() = self.selected();
|
||||||
|
|
@ -288,10 +157,3 @@ impl ZellijPlugin for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub enum MessageToPlugin {
|
|
||||||
UpdateFileNameSearchResults,
|
|
||||||
UpdateFileContentsSearchResults,
|
|
||||||
DoneScanningFolder,
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,353 +0,0 @@
|
||||||
use crate::search::search_state::SearchType;
|
|
||||||
use crate::search::ui::{
|
|
||||||
arrow, bold, color_line_to_end, dot, styled_text, BLACK, GRAY_DARK, GRAY_LIGHT, RED, WHITE,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ControlsLine {
|
|
||||||
controls: Vec<Control>,
|
|
||||||
scanning_indication: Option<Vec<&'static str>>,
|
|
||||||
animation_offset: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlsLine {
|
|
||||||
pub fn new(controls: Vec<Control>, scanning_indication: Option<Vec<&'static str>>) -> Self {
|
|
||||||
ControlsLine {
|
|
||||||
controls,
|
|
||||||
scanning_indication,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn with_animation_offset(mut self, animation_offset: u8) -> Self {
|
|
||||||
self.animation_offset = animation_offset;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn render(&self, max_width: usize, show_controls: bool) -> String {
|
|
||||||
if show_controls {
|
|
||||||
self.render_controls(max_width)
|
|
||||||
} else {
|
|
||||||
self.render_empty_line(max_width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn render_controls(&self, max_width: usize) -> String {
|
|
||||||
let loading_animation =
|
|
||||||
LoadingAnimation::new(&self.scanning_indication, self.animation_offset);
|
|
||||||
let full_length = loading_animation.full_len()
|
|
||||||
+ self.controls.iter().map(|c| c.full_len()).sum::<usize>();
|
|
||||||
let mid_length =
|
|
||||||
loading_animation.mid_len() + self.controls.iter().map(|c| c.mid_len()).sum::<usize>();
|
|
||||||
let short_length = loading_animation.short_len()
|
|
||||||
+ self.controls.iter().map(|c| c.short_len()).sum::<usize>();
|
|
||||||
if max_width >= full_length {
|
|
||||||
let mut to_render = String::new();
|
|
||||||
for control in &self.controls {
|
|
||||||
to_render.push_str(&control.render_full_length());
|
|
||||||
}
|
|
||||||
to_render.push_str(&self.render_padding(max_width.saturating_sub(full_length)));
|
|
||||||
to_render.push_str(&loading_animation.render_full_length());
|
|
||||||
to_render
|
|
||||||
} else if max_width >= mid_length {
|
|
||||||
let mut to_render = String::new();
|
|
||||||
for control in &self.controls {
|
|
||||||
to_render.push_str(&control.render_mid_length());
|
|
||||||
}
|
|
||||||
to_render.push_str(&self.render_padding(max_width.saturating_sub(mid_length)));
|
|
||||||
to_render.push_str(&loading_animation.render_mid_length());
|
|
||||||
to_render
|
|
||||||
} else if max_width >= short_length {
|
|
||||||
let mut to_render = String::new();
|
|
||||||
for control in &self.controls {
|
|
||||||
to_render.push_str(&control.render_short_length());
|
|
||||||
}
|
|
||||||
to_render.push_str(&self.render_padding(max_width.saturating_sub(short_length)));
|
|
||||||
to_render.push_str(&loading_animation.render_short_length());
|
|
||||||
to_render
|
|
||||||
} else {
|
|
||||||
format!("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn render_empty_line(&self, max_width: usize) -> String {
|
|
||||||
let loading_animation =
|
|
||||||
LoadingAnimation::new(&self.scanning_indication, self.animation_offset);
|
|
||||||
let mut to_render = String::new();
|
|
||||||
if max_width >= loading_animation.full_len() {
|
|
||||||
to_render.push_str(
|
|
||||||
&self.render_padding(max_width.saturating_sub(loading_animation.full_len())),
|
|
||||||
);
|
|
||||||
to_render.push_str(&loading_animation.render_full_length());
|
|
||||||
} else if max_width >= loading_animation.mid_len() {
|
|
||||||
to_render.push_str(
|
|
||||||
&self.render_padding(max_width.saturating_sub(loading_animation.mid_len())),
|
|
||||||
);
|
|
||||||
to_render.push_str(&loading_animation.render_mid_length());
|
|
||||||
} else if max_width >= loading_animation.short_len() {
|
|
||||||
to_render.push_str(
|
|
||||||
&self.render_padding(max_width.saturating_sub(loading_animation.short_len())),
|
|
||||||
);
|
|
||||||
to_render.push_str(&loading_animation.render_short_length());
|
|
||||||
}
|
|
||||||
to_render
|
|
||||||
}
|
|
||||||
fn render_padding(&self, padding: usize) -> String {
|
|
||||||
// TODO: color whole line
|
|
||||||
format!("{}\u{1b}[{}C", color_line_to_end(GRAY_LIGHT), padding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Control {
|
|
||||||
key: &'static str,
|
|
||||||
options: Vec<&'static str>,
|
|
||||||
option_index: (usize, usize), // eg. 1 out of 2 (1, 2)
|
|
||||||
keycode_background_color: u8,
|
|
||||||
keycode_foreground_color: u8,
|
|
||||||
control_text_background_color: u8,
|
|
||||||
control_text_foreground_color: u8,
|
|
||||||
active_dot_color: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Control {
|
|
||||||
fn default() -> Self {
|
|
||||||
Control {
|
|
||||||
key: "",
|
|
||||||
options: vec![],
|
|
||||||
option_index: (0, 0),
|
|
||||||
keycode_background_color: GRAY_LIGHT,
|
|
||||||
keycode_foreground_color: WHITE,
|
|
||||||
control_text_background_color: GRAY_DARK,
|
|
||||||
control_text_foreground_color: BLACK,
|
|
||||||
active_dot_color: RED,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Control {
|
|
||||||
pub fn new(
|
|
||||||
key: &'static str,
|
|
||||||
options: Vec<&'static str>,
|
|
||||||
option_index: (usize, usize),
|
|
||||||
) -> Self {
|
|
||||||
Control {
|
|
||||||
key,
|
|
||||||
options,
|
|
||||||
option_index,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new_floating_control(key: &'static str, should_open_floating: bool) -> Self {
|
|
||||||
if should_open_floating {
|
|
||||||
Control::new(key, vec!["OPEN FLOATING", "FLOATING", "F"], (2, 2))
|
|
||||||
} else {
|
|
||||||
Control::new(key, vec!["OPEN TILED", "TILED", "T"], (1, 2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new_filter_control(key: &'static str, search_filter: &SearchType) -> Self {
|
|
||||||
match search_filter {
|
|
||||||
SearchType::NamesAndContents => Control::new(
|
|
||||||
key,
|
|
||||||
vec!["FILE NAMES AND CONTENTS", "NAMES + CONTENTS", "N+C"],
|
|
||||||
(1, 3),
|
|
||||||
),
|
|
||||||
SearchType::Names => Control::new(key, vec!["FILE NAMES", "NAMES", "N"], (2, 3)),
|
|
||||||
SearchType::Contents => {
|
|
||||||
Control::new(key, vec!["FILE CONTENTS", "CONTENTS", "C"], (3, 3))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn short_len(&self) -> usize {
|
|
||||||
let short_text = self
|
|
||||||
.options
|
|
||||||
.get(2)
|
|
||||||
.or_else(|| self.options.get(1))
|
|
||||||
.or_else(|| self.options.get(0))
|
|
||||||
.unwrap_or(&"");
|
|
||||||
short_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7
|
|
||||||
// 7 for all the spaces and decorations
|
|
||||||
}
|
|
||||||
pub fn mid_len(&self) -> usize {
|
|
||||||
let mid_text = self
|
|
||||||
.options
|
|
||||||
.get(1)
|
|
||||||
.or_else(|| self.options.get(0))
|
|
||||||
.unwrap_or(&"");
|
|
||||||
mid_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7
|
|
||||||
// 7 for all the spaces and decorations
|
|
||||||
}
|
|
||||||
pub fn full_len(&self) -> usize {
|
|
||||||
let full_text = self.options.get(0).unwrap_or(&"");
|
|
||||||
full_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7
|
|
||||||
// 7 for all the spaces and decorations
|
|
||||||
}
|
|
||||||
pub fn render_short_length(&self) -> String {
|
|
||||||
let short_text = self
|
|
||||||
.options
|
|
||||||
.get(2)
|
|
||||||
.or_else(|| self.options.get(1))
|
|
||||||
.or_else(|| self.options.get(0))
|
|
||||||
.unwrap_or(&"");
|
|
||||||
self.render(short_text)
|
|
||||||
}
|
|
||||||
pub fn render_mid_length(&self) -> String {
|
|
||||||
let mid_text = self
|
|
||||||
.options
|
|
||||||
.get(1)
|
|
||||||
.or_else(|| self.options.get(0))
|
|
||||||
.unwrap_or(&"");
|
|
||||||
self.render(mid_text)
|
|
||||||
}
|
|
||||||
pub fn render_full_length(&self) -> String {
|
|
||||||
let full_text = self.options.get(0).unwrap_or(&"");
|
|
||||||
self.render(full_text)
|
|
||||||
}
|
|
||||||
fn render(&self, text: &str) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}{}{}{}{}",
|
|
||||||
self.render_keycode(&format!(" {} ", self.key)),
|
|
||||||
arrow(
|
|
||||||
self.keycode_background_color,
|
|
||||||
self.control_text_background_color
|
|
||||||
),
|
|
||||||
self.render_selection_dots(),
|
|
||||||
self.render_control_text(&format!("{} ", text)),
|
|
||||||
arrow(
|
|
||||||
self.control_text_background_color,
|
|
||||||
self.keycode_background_color
|
|
||||||
),
|
|
||||||
color_line_to_end(self.keycode_background_color),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn render_keycode(&self, text: &str) -> String {
|
|
||||||
styled_text(
|
|
||||||
self.keycode_foreground_color,
|
|
||||||
self.keycode_background_color,
|
|
||||||
&bold(text),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn render_control_text(&self, text: &str) -> String {
|
|
||||||
styled_text(
|
|
||||||
self.control_text_foreground_color,
|
|
||||||
self.control_text_background_color,
|
|
||||||
&bold(text),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn render_selection_dots(&self) -> String {
|
|
||||||
let mut selection_dots = String::from(" ");
|
|
||||||
for i in 1..=self.option_index.1 {
|
|
||||||
if i == self.option_index.0 {
|
|
||||||
selection_dots.push_str(&dot(
|
|
||||||
self.active_dot_color,
|
|
||||||
self.control_text_background_color,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
selection_dots.push_str(&dot(
|
|
||||||
self.control_text_foreground_color,
|
|
||||||
self.control_text_background_color,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selection_dots.push_str(" ");
|
|
||||||
selection_dots
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LoadingAnimation {
|
|
||||||
scanning_indication: Option<Vec<&'static str>>,
|
|
||||||
animation_offset: u8,
|
|
||||||
background_color: u8,
|
|
||||||
foreground_color: u8,
|
|
||||||
}
|
|
||||||
impl LoadingAnimation {
|
|
||||||
pub fn new(scanning_indication: &Option<Vec<&'static str>>, animation_offset: u8) -> Self {
|
|
||||||
LoadingAnimation {
|
|
||||||
scanning_indication: scanning_indication.clone(),
|
|
||||||
animation_offset,
|
|
||||||
background_color: GRAY_LIGHT,
|
|
||||||
foreground_color: WHITE,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn full_len(&self) -> usize {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| scanning_indication.get(0))
|
|
||||||
.map(|s| s.chars().count() + 3) // 3 for animation dots
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
|
||||||
pub fn mid_len(&self) -> usize {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| {
|
|
||||||
scanning_indication
|
|
||||||
.get(1)
|
|
||||||
.or_else(|| scanning_indication.get(0))
|
|
||||||
})
|
|
||||||
.map(|s| s.chars().count() + 3) // 3 for animation dots
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
|
||||||
pub fn short_len(&self) -> usize {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| {
|
|
||||||
scanning_indication
|
|
||||||
.get(2)
|
|
||||||
.or_else(|| scanning_indication.get(1))
|
|
||||||
.or_else(|| scanning_indication.get(0))
|
|
||||||
})
|
|
||||||
.map(|s| s.chars().count() + 3) // 3 for animation dots
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
|
||||||
pub fn render_full_length(&self) -> String {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| scanning_indication.get(0))
|
|
||||||
.map(|s| {
|
|
||||||
styled_text(
|
|
||||||
self.foreground_color,
|
|
||||||
self.background_color,
|
|
||||||
&bold(&(s.to_string() + &self.animation_dots())),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(String::new)
|
|
||||||
}
|
|
||||||
pub fn render_mid_length(&self) -> String {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| {
|
|
||||||
scanning_indication
|
|
||||||
.get(1)
|
|
||||||
.or_else(|| scanning_indication.get(0))
|
|
||||||
})
|
|
||||||
.map(|s| {
|
|
||||||
styled_text(
|
|
||||||
self.background_color,
|
|
||||||
self.foreground_color,
|
|
||||||
&bold(&(s.to_string() + &self.animation_dots())),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(String::new)
|
|
||||||
}
|
|
||||||
pub fn render_short_length(&self) -> String {
|
|
||||||
self.scanning_indication
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|scanning_indication| {
|
|
||||||
scanning_indication
|
|
||||||
.get(2)
|
|
||||||
.or_else(|| scanning_indication.get(1))
|
|
||||||
.or_else(|| scanning_indication.get(0))
|
|
||||||
})
|
|
||||||
.map(|s| {
|
|
||||||
styled_text(
|
|
||||||
self.background_color,
|
|
||||||
self.foreground_color,
|
|
||||||
&bold(&(s.to_string() + &self.animation_dots())),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(String::new)
|
|
||||||
}
|
|
||||||
fn animation_dots(&self) -> String {
|
|
||||||
let mut to_render = String::from("");
|
|
||||||
let dot_count = self.animation_offset % 4;
|
|
||||||
for _ in 0..dot_count {
|
|
||||||
to_render.push('.');
|
|
||||||
}
|
|
||||||
to_render
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,317 +0,0 @@
|
||||||
pub mod controls_line;
|
|
||||||
pub mod search_results;
|
|
||||||
pub mod search_state;
|
|
||||||
pub mod selection_controls_area;
|
|
||||||
pub mod ui;
|
|
||||||
|
|
||||||
use crate::state::{CURRENT_SEARCH_TERM, ROOT};
|
|
||||||
use crate::MessageToPlugin;
|
|
||||||
use search_state::SearchType;
|
|
||||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use unicode_width::UnicodeWidthStr;
|
|
||||||
use zellij_tile::prelude::*;
|
|
||||||
|
|
||||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
|
||||||
use ignore::Walk;
|
|
||||||
use search_results::SearchResult;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use std::io::{self, BufRead};
|
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize)]
|
|
||||||
pub struct Search {
|
|
||||||
search_type: SearchType,
|
|
||||||
file_names: BTreeSet<String>,
|
|
||||||
file_contents: BTreeMap<(String, usize), String>, // file_name, line_number, line
|
|
||||||
cached_file_name_results: HashMap<String, Vec<SearchResult>>,
|
|
||||||
cached_file_contents_results: HashMap<String, Vec<SearchResult>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Search {
|
|
||||||
pub fn new(search_type: SearchType) -> Self {
|
|
||||||
Search {
|
|
||||||
search_type,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn on_message(&mut self, message: String, payload: String) {
|
|
||||||
match serde_json::from_str::<MessageToSearch>(&message) {
|
|
||||||
Ok(MessageToSearch::ScanFolder) => {
|
|
||||||
self.scan_hd();
|
|
||||||
post_message_to_plugin(PluginMessage {
|
|
||||||
worker_name: None,
|
|
||||||
name: serde_json::to_string(&MessageToPlugin::DoneScanningFolder).unwrap(),
|
|
||||||
payload: "".to_owned(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Ok(MessageToSearch::Search) => {
|
|
||||||
if let Some(current_search_term) = self.read_search_term_from_hd_cache() {
|
|
||||||
self.search(current_search_term);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(MessageToSearch::FileSystemCreate) => {
|
|
||||||
self.rescan_files(payload);
|
|
||||||
},
|
|
||||||
Ok(MessageToSearch::FileSystemUpdate) => {
|
|
||||||
self.rescan_files(payload);
|
|
||||||
},
|
|
||||||
Ok(MessageToSearch::FileSystemDelete) => {
|
|
||||||
self.delete_files(payload);
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("Failed to deserialize worker message {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn scan_hd(&mut self) {
|
|
||||||
for result in Walk::new(ROOT) {
|
|
||||||
if let Ok(entry) = result {
|
|
||||||
self.add_file_entry(entry.path(), entry.metadata().ok());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn search(&mut self, search_term: String) {
|
|
||||||
let search_results_limit = 100; // artificial limit to prevent probably unwanted chaos
|
|
||||||
// let mut matcher = SkimMatcherV2::default().use_cache(true).element_limit(search_results_limit);
|
|
||||||
let mut file_names_search_results = None;
|
|
||||||
let mut file_contents_search_results = None;
|
|
||||||
if let SearchType::Names | SearchType::NamesAndContents = self.search_type {
|
|
||||||
let file_names_matches = match self.cached_file_name_results.get(&search_term) {
|
|
||||||
Some(cached_results) => cached_results.clone(),
|
|
||||||
None => {
|
|
||||||
let mut matcher = SkimMatcherV2::default().use_cache(true);
|
|
||||||
let results = self.search_file_names(&search_term, &mut matcher);
|
|
||||||
self.cached_file_name_results
|
|
||||||
.insert(search_term.clone(), results.clone());
|
|
||||||
results
|
|
||||||
},
|
|
||||||
};
|
|
||||||
file_names_search_results = Some(
|
|
||||||
ResultsOfSearch::new(search_term.clone(), file_names_matches)
|
|
||||||
.limit_search_results(search_results_limit),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
if let SearchType::Contents | SearchType::NamesAndContents = self.search_type {
|
|
||||||
let file_contents_matches = match self.cached_file_contents_results.get(&search_term) {
|
|
||||||
Some(cached_results) => cached_results.clone(),
|
|
||||||
None => {
|
|
||||||
let mut matcher = SkimMatcherV2::default().use_cache(true);
|
|
||||||
let results = self.search_file_contents(&search_term, &mut matcher);
|
|
||||||
self.cached_file_contents_results
|
|
||||||
.insert(search_term.clone(), results.clone());
|
|
||||||
results
|
|
||||||
},
|
|
||||||
};
|
|
||||||
file_contents_search_results = Some(
|
|
||||||
ResultsOfSearch::new(search_term.clone(), file_contents_matches)
|
|
||||||
.limit_search_results(search_results_limit),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// if the search term changed before we finished, let's search again!
|
|
||||||
if let Some(current_search_term) = self.read_search_term_from_hd_cache() {
|
|
||||||
if current_search_term != search_term {
|
|
||||||
return self.search(current_search_term.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(file_names_search_results) = file_names_search_results {
|
|
||||||
post_message_to_plugin(PluginMessage {
|
|
||||||
name: serde_json::to_string(&MessageToPlugin::UpdateFileNameSearchResults).unwrap(),
|
|
||||||
payload: serde_json::to_string(&file_names_search_results).unwrap(),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if let Some(file_contents_search_results) = file_contents_search_results {
|
|
||||||
post_message_to_plugin(PluginMessage {
|
|
||||||
name: serde_json::to_string(&MessageToPlugin::UpdateFileContentsSearchResults)
|
|
||||||
.unwrap(),
|
|
||||||
payload: serde_json::to_string(&file_contents_search_results).unwrap(),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn rescan_files(&mut self, paths: String) {
|
|
||||||
match serde_json::from_str::<Vec<PathBuf>>(&paths) {
|
|
||||||
Ok(paths) => {
|
|
||||||
for path in paths {
|
|
||||||
self.add_file_entry(&path, path.metadata().ok());
|
|
||||||
}
|
|
||||||
self.cached_file_name_results.clear();
|
|
||||||
self.cached_file_contents_results.clear();
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("Failed to deserialize paths: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn delete_files(&mut self, paths: String) {
|
|
||||||
match serde_json::from_str::<Vec<PathBuf>>(&paths) {
|
|
||||||
Ok(paths) => {
|
|
||||||
self.remove_existing_entries(&paths);
|
|
||||||
self.cached_file_name_results.clear();
|
|
||||||
self.cached_file_contents_results.clear();
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("Failed to deserialize paths: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn add_file_entry(&mut self, file_name: &Path, file_metadata: Option<std::fs::Metadata>) {
|
|
||||||
let file_path = file_name.display().to_string();
|
|
||||||
let file_path_stripped_prefix = self.strip_file_prefix(&file_name);
|
|
||||||
|
|
||||||
self.file_names.insert(file_path_stripped_prefix.clone());
|
|
||||||
if let SearchType::NamesAndContents | SearchType::Contents = self.search_type {
|
|
||||||
if file_metadata.map(|f| f.is_file()).unwrap_or(false) {
|
|
||||||
if let Ok(file) = std::fs::File::open(&file_path) {
|
|
||||||
let lines = io::BufReader::new(file).lines();
|
|
||||||
for (index, line) in lines.enumerate() {
|
|
||||||
match line {
|
|
||||||
Ok(line) => {
|
|
||||||
self.file_contents.insert(
|
|
||||||
(file_path_stripped_prefix.clone(), index + 1),
|
|
||||||
String::from_utf8_lossy(
|
|
||||||
&strip_ansi_escapes::strip(line).unwrap(),
|
|
||||||
)
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
break; // probably a binary file, skip it
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn search_file_names(
|
|
||||||
&self,
|
|
||||||
search_term: &str,
|
|
||||||
matcher: &mut SkimMatcherV2,
|
|
||||||
) -> Vec<SearchResult> {
|
|
||||||
let mut matches = vec![];
|
|
||||||
for entry in &self.file_names {
|
|
||||||
if let Some((score, indices)) = matcher.fuzzy_indices(&entry, &search_term) {
|
|
||||||
matches.push(SearchResult::new_file_name(
|
|
||||||
score,
|
|
||||||
indices,
|
|
||||||
entry.to_owned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matches
|
|
||||||
}
|
|
||||||
fn search_file_contents(
|
|
||||||
&self,
|
|
||||||
search_term: &str,
|
|
||||||
matcher: &mut SkimMatcherV2,
|
|
||||||
) -> Vec<SearchResult> {
|
|
||||||
let mut matches = vec![];
|
|
||||||
for ((file_name, line_number), line_entry) in &self.file_contents {
|
|
||||||
if let Some((score, indices)) = matcher.fuzzy_indices(&line_entry, &search_term) {
|
|
||||||
matches.push(SearchResult::new_file_line(
|
|
||||||
score,
|
|
||||||
indices,
|
|
||||||
file_name.clone(),
|
|
||||||
line_entry.clone(),
|
|
||||||
*line_number,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matches
|
|
||||||
}
|
|
||||||
fn strip_file_prefix(&self, file_name: &Path) -> String {
|
|
||||||
let mut file_path_stripped_prefix = file_name.display().to_string().split_off(ROOT.width());
|
|
||||||
if file_path_stripped_prefix.starts_with('/') {
|
|
||||||
file_path_stripped_prefix.remove(0);
|
|
||||||
}
|
|
||||||
file_path_stripped_prefix
|
|
||||||
}
|
|
||||||
fn read_search_term_from_hd_cache(&self) -> Option<String> {
|
|
||||||
match std::fs::read(CURRENT_SEARCH_TERM) {
|
|
||||||
Ok(current_search_term) => {
|
|
||||||
Some(String::from_utf8_lossy(¤t_search_term).to_string())
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn remove_existing_entries(&mut self, paths: &Vec<PathBuf>) {
|
|
||||||
let file_path_stripped_prefixes: Vec<String> =
|
|
||||||
paths.iter().map(|p| self.strip_file_prefix(&p)).collect();
|
|
||||||
self.file_names
|
|
||||||
.retain(|file_name| !file_path_stripped_prefixes.contains(file_name));
|
|
||||||
self.file_contents.retain(|(file_name, _line_in_file), _| {
|
|
||||||
!file_path_stripped_prefixes.contains(file_name)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub enum MessageToSearch {
|
|
||||||
ScanFolder,
|
|
||||||
Search,
|
|
||||||
FileSystemCreate,
|
|
||||||
FileSystemUpdate,
|
|
||||||
FileSystemDelete,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct FileNameWorker {
|
|
||||||
search: Search,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FileNameWorker {
|
|
||||||
fn default() -> Self {
|
|
||||||
FileNameWorker {
|
|
||||||
search: Search::new(SearchType::Names),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct FileContentsWorker {
|
|
||||||
search: Search,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FileContentsWorker {
|
|
||||||
fn default() -> Self {
|
|
||||||
FileContentsWorker {
|
|
||||||
search: Search::new(SearchType::Contents),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> ZellijWorker<'de> for FileNameWorker {
|
|
||||||
fn on_message(&mut self, message: String, payload: String) {
|
|
||||||
self.search.on_message(message, payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> ZellijWorker<'de> for FileContentsWorker {
|
|
||||||
fn on_message(&mut self, message: String, payload: String) {
|
|
||||||
self.search.on_message(message, payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct ResultsOfSearch {
|
|
||||||
pub search_term: String,
|
|
||||||
pub search_results: Vec<SearchResult>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ResultsOfSearch {
|
|
||||||
pub fn new(search_term: String, search_results: Vec<SearchResult>) -> Self {
|
|
||||||
ResultsOfSearch {
|
|
||||||
search_term,
|
|
||||||
search_results,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn limit_search_results(mut self, max_results: usize) -> Self {
|
|
||||||
self.search_results
|
|
||||||
.sort_by(|a, b| b.score().cmp(&a.score()));
|
|
||||||
self.search_results = if self.search_results.len() > max_results {
|
|
||||||
self.search_results.drain(..max_results).collect()
|
|
||||||
} else {
|
|
||||||
self.search_results.drain(..).collect()
|
|
||||||
};
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,308 +0,0 @@
|
||||||
use crate::search::ui::{
|
|
||||||
bold, styled_text, styled_text_background, styled_text_foreground, underline, GRAY_LIGHT,
|
|
||||||
GREEN, ORANGE,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use unicode_width::UnicodeWidthStr;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub enum SearchResult {
|
|
||||||
File {
|
|
||||||
path: String,
|
|
||||||
score: i64,
|
|
||||||
indices: Vec<usize>,
|
|
||||||
},
|
|
||||||
LineInFile {
|
|
||||||
path: String,
|
|
||||||
line: String,
|
|
||||||
line_number: usize,
|
|
||||||
score: i64,
|
|
||||||
indices: Vec<usize>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SearchResult {
|
|
||||||
pub fn new_file_name(score: i64, indices: Vec<usize>, path: String) -> Self {
|
|
||||||
SearchResult::File {
|
|
||||||
path,
|
|
||||||
score,
|
|
||||||
indices,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new_file_line(
|
|
||||||
score: i64,
|
|
||||||
indices: Vec<usize>,
|
|
||||||
path: String,
|
|
||||||
line: String,
|
|
||||||
line_number: usize,
|
|
||||||
) -> Self {
|
|
||||||
SearchResult::LineInFile {
|
|
||||||
path,
|
|
||||||
score,
|
|
||||||
indices,
|
|
||||||
line,
|
|
||||||
line_number,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn score(&self) -> i64 {
|
|
||||||
match self {
|
|
||||||
SearchResult::File { score, .. } => *score,
|
|
||||||
SearchResult::LineInFile { score, .. } => *score,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn rendered_height(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
SearchResult::File { .. } => 1,
|
|
||||||
SearchResult::LineInFile { .. } => 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_same_entry(&self, other: &Self) -> bool {
|
|
||||||
match (&self, other) {
|
|
||||||
(
|
|
||||||
SearchResult::File { path: my_path, .. },
|
|
||||||
SearchResult::File {
|
|
||||||
path: other_path, ..
|
|
||||||
},
|
|
||||||
) => my_path == other_path,
|
|
||||||
(
|
|
||||||
SearchResult::LineInFile {
|
|
||||||
path: my_path,
|
|
||||||
line_number: my_line_number,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
SearchResult::LineInFile {
|
|
||||||
path: other_path,
|
|
||||||
line_number: other_line_number,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
) => my_path == other_path && my_line_number == other_line_number,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn render(
|
|
||||||
&self,
|
|
||||||
max_width: usize,
|
|
||||||
is_selected: bool,
|
|
||||||
is_below_search_result: bool,
|
|
||||||
) -> String {
|
|
||||||
let max_width = max_width.saturating_sub(4); // for the UI left line separator
|
|
||||||
match self {
|
|
||||||
SearchResult::File { path, indices, .. } => self.render_file_result(
|
|
||||||
path,
|
|
||||||
indices,
|
|
||||||
is_selected,
|
|
||||||
is_below_search_result,
|
|
||||||
max_width,
|
|
||||||
),
|
|
||||||
SearchResult::LineInFile {
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
line_number,
|
|
||||||
indices,
|
|
||||||
..
|
|
||||||
} => self.render_line_in_file_result(
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
*line_number,
|
|
||||||
indices,
|
|
||||||
is_selected,
|
|
||||||
is_below_search_result,
|
|
||||||
max_width,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn render_file_result(
|
|
||||||
&self,
|
|
||||||
path: &String,
|
|
||||||
indices: &Vec<usize>,
|
|
||||||
is_selected: bool,
|
|
||||||
is_below_search_result: bool,
|
|
||||||
max_width: usize,
|
|
||||||
) -> String {
|
|
||||||
if is_selected {
|
|
||||||
let line = self.render_line_with_indices(
|
|
||||||
path,
|
|
||||||
indices,
|
|
||||||
max_width.saturating_sub(3),
|
|
||||||
Some(GREEN),
|
|
||||||
);
|
|
||||||
let selection_arrow = styled_text_foreground(ORANGE, "┌>");
|
|
||||||
format!("{} {}", selection_arrow, line)
|
|
||||||
} else {
|
|
||||||
let line_prefix = if is_below_search_result { "│ " } else { " " };
|
|
||||||
let line =
|
|
||||||
self.render_line_with_indices(path, indices, max_width.saturating_sub(3), None);
|
|
||||||
format!("{} {}", line_prefix, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn render_line_in_file_result(
|
|
||||||
&self,
|
|
||||||
path: &String,
|
|
||||||
line: &String,
|
|
||||||
line_number: usize,
|
|
||||||
indices: &Vec<usize>,
|
|
||||||
is_selected: bool,
|
|
||||||
is_below_search_result: bool,
|
|
||||||
max_width: usize,
|
|
||||||
) -> String {
|
|
||||||
let line_number_prefix_text = format!("└ {} ", line_number);
|
|
||||||
let max_width_of_line_in_file = max_width
|
|
||||||
.saturating_sub(3)
|
|
||||||
.saturating_sub(line_number_prefix_text.width());
|
|
||||||
if is_selected {
|
|
||||||
let file_name_line = self.render_line_with_indices(
|
|
||||||
path,
|
|
||||||
&vec![],
|
|
||||||
max_width.saturating_sub(3),
|
|
||||||
Some(GREEN),
|
|
||||||
);
|
|
||||||
let line_in_file = self.render_line_with_indices(
|
|
||||||
line,
|
|
||||||
indices,
|
|
||||||
max_width_of_line_in_file,
|
|
||||||
Some(GREEN),
|
|
||||||
);
|
|
||||||
let line_number_prefix = styled_text_foreground(GREEN, &bold(&line_number_prefix_text));
|
|
||||||
format!(
|
|
||||||
"{} {}\n│ {}{}",
|
|
||||||
styled_text_foreground(ORANGE, "┌>"),
|
|
||||||
file_name_line,
|
|
||||||
line_number_prefix,
|
|
||||||
line_in_file
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let file_name_line =
|
|
||||||
self.render_line_with_indices(path, &vec![], max_width.saturating_sub(3), None);
|
|
||||||
let line_in_file =
|
|
||||||
self.render_line_with_indices(line, indices, max_width_of_line_in_file, None);
|
|
||||||
let line_number_prefix = bold(&line_number_prefix_text);
|
|
||||||
let line_prefix = if is_below_search_result { "│ " } else { " " };
|
|
||||||
format!(
|
|
||||||
"{} {}\n{} {}{}",
|
|
||||||
line_prefix, file_name_line, line_prefix, line_number_prefix, line_in_file
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn render_line_with_indices(
|
|
||||||
&self,
|
|
||||||
line_to_render: &String,
|
|
||||||
indices: &Vec<usize>,
|
|
||||||
max_width: usize,
|
|
||||||
foreground_color: Option<u8>,
|
|
||||||
) -> String {
|
|
||||||
let non_index_character_style = |c: &str| match foreground_color {
|
|
||||||
Some(foreground_color) => styled_text_foreground(foreground_color, &bold(c)),
|
|
||||||
None => bold(c),
|
|
||||||
};
|
|
||||||
let index_character_style = |c: &str| match foreground_color {
|
|
||||||
Some(foreground_color) => {
|
|
||||||
styled_text(foreground_color, GRAY_LIGHT, &bold(&underline(c)))
|
|
||||||
},
|
|
||||||
None => styled_text_background(GRAY_LIGHT, &bold(&underline(c))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let truncate_positions =
|
|
||||||
self.truncate_line_with_indices(line_to_render, indices, max_width);
|
|
||||||
let truncate_start_position = truncate_positions.map(|p| p.0).unwrap_or(0);
|
|
||||||
let truncate_end_position = truncate_positions
|
|
||||||
.map(|p| p.1)
|
|
||||||
.unwrap_or(line_to_render.chars().count());
|
|
||||||
let mut visible_portion = String::new();
|
|
||||||
for (i, character) in line_to_render.chars().enumerate() {
|
|
||||||
if i >= truncate_start_position && i <= truncate_end_position {
|
|
||||||
if indices.contains(&i) {
|
|
||||||
visible_portion.push_str(&index_character_style(&character.to_string()));
|
|
||||||
} else {
|
|
||||||
visible_portion.push_str(&non_index_character_style(&character.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if truncate_positions.is_some() {
|
|
||||||
let left_truncate_sign = if truncate_start_position == 0 {
|
|
||||||
""
|
|
||||||
} else {
|
|
||||||
".."
|
|
||||||
};
|
|
||||||
let right_truncate_sign = if truncate_end_position == line_to_render.chars().count() {
|
|
||||||
""
|
|
||||||
} else {
|
|
||||||
".."
|
|
||||||
};
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
non_index_character_style(left_truncate_sign),
|
|
||||||
visible_portion,
|
|
||||||
non_index_character_style(right_truncate_sign)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
visible_portion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn truncate_line_with_indices(
|
|
||||||
&self,
|
|
||||||
line_to_render: &String,
|
|
||||||
indices: &Vec<usize>,
|
|
||||||
max_width: usize,
|
|
||||||
) -> Option<(usize, usize)> {
|
|
||||||
let first_index = indices.get(0).copied().unwrap_or(0);
|
|
||||||
let last_index = indices
|
|
||||||
.last()
|
|
||||||
.copied()
|
|
||||||
.unwrap_or_else(|| std::cmp::min(line_to_render.chars().count(), max_width));
|
|
||||||
if line_to_render.width() <= max_width {
|
|
||||||
// there's enough room, no need to truncate
|
|
||||||
None
|
|
||||||
} else if last_index.saturating_sub(first_index) < max_width {
|
|
||||||
// truncate around the indices
|
|
||||||
let mut width_remaining = max_width
|
|
||||||
.saturating_sub(1)
|
|
||||||
.saturating_sub(last_index.saturating_sub(first_index));
|
|
||||||
|
|
||||||
let mut string_start_position = first_index;
|
|
||||||
let mut string_end_position = last_index;
|
|
||||||
|
|
||||||
let mut i = 0;
|
|
||||||
loop {
|
|
||||||
if i >= width_remaining {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if string_start_position > 0 && string_end_position < line_to_render.chars().count()
|
|
||||||
{
|
|
||||||
let take_from_start = i % 2 == 0;
|
|
||||||
if take_from_start {
|
|
||||||
string_start_position -= 1;
|
|
||||||
if string_start_position == 0 {
|
|
||||||
width_remaining += 2; // no need for truncating dots
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
string_end_position += 1;
|
|
||||||
if string_end_position == line_to_render.chars().count() {
|
|
||||||
width_remaining += 2; // no need for truncating dots
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if string_end_position < line_to_render.chars().count() {
|
|
||||||
string_end_position += 1;
|
|
||||||
if string_end_position == line_to_render.chars().count() {
|
|
||||||
width_remaining += 2; // no need for truncating dots
|
|
||||||
}
|
|
||||||
} else if string_start_position > 0 {
|
|
||||||
string_start_position -= 1;
|
|
||||||
if string_start_position == 0 {
|
|
||||||
width_remaining += 2; // no need for truncating dots
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
Some((string_start_position, string_end_position))
|
|
||||||
} else if !indices.is_empty() {
|
|
||||||
// no room for all indices, remove the last one and try again
|
|
||||||
let mut new_indices = indices.clone();
|
|
||||||
new_indices.pop();
|
|
||||||
self.truncate_line_with_indices(line_to_render, &new_indices, max_width)
|
|
||||||
} else {
|
|
||||||
Some((first_index, last_index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
use crate::search::search_results::SearchResult;
|
|
||||||
use crate::search::{MessageToSearch, ResultsOfSearch};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use zellij_tile::prelude::{
|
|
||||||
hide_self, open_file, open_file_floating, open_terminal, open_terminal_floating,
|
|
||||||
post_message_to, FileToOpen, Key, PluginMessage,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term";
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct SearchState {
|
|
||||||
pub search_term: String,
|
|
||||||
pub file_name_search_results: Vec<SearchResult>,
|
|
||||||
pub file_contents_search_results: Vec<SearchResult>,
|
|
||||||
pub loading: bool,
|
|
||||||
pub loading_animation_offset: u8,
|
|
||||||
pub selected_search_result: usize,
|
|
||||||
pub should_open_floating: bool,
|
|
||||||
pub search_filter: SearchType,
|
|
||||||
pub display_rows: usize,
|
|
||||||
pub display_columns: usize,
|
|
||||||
pub displayed_search_results: (usize, Vec<SearchResult>), // usize is selected index
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SearchState {
|
|
||||||
pub fn handle_key(&mut self, key: Key) {
|
|
||||||
match key {
|
|
||||||
Key::Down => self.move_search_selection_down(),
|
|
||||||
Key::Up => self.move_search_selection_up(),
|
|
||||||
Key::Char('\n') => self.open_search_result_in_editor(),
|
|
||||||
Key::BackTab => self.open_search_result_in_terminal(),
|
|
||||||
Key::Ctrl('f') => {
|
|
||||||
self.should_open_floating = !self.should_open_floating;
|
|
||||||
},
|
|
||||||
Key::Ctrl('r') => self.toggle_search_filter(),
|
|
||||||
Key::Esc => {
|
|
||||||
if !self.search_term.is_empty() {
|
|
||||||
self.clear_state();
|
|
||||||
} else {
|
|
||||||
hide_self();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => self.append_to_search_term(key),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn update_file_name_search_results(&mut self, mut results_of_search: ResultsOfSearch) {
|
|
||||||
if self.search_term == results_of_search.search_term {
|
|
||||||
self.file_name_search_results = results_of_search.search_results.drain(..).collect();
|
|
||||||
self.update_displayed_search_results();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn update_file_contents_search_results(&mut self, mut results_of_search: ResultsOfSearch) {
|
|
||||||
if self.search_term == results_of_search.search_term {
|
|
||||||
self.file_contents_search_results =
|
|
||||||
results_of_search.search_results.drain(..).collect();
|
|
||||||
self.update_displayed_search_results();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn change_size(&mut self, rows: usize, cols: usize) {
|
|
||||||
self.display_rows = rows;
|
|
||||||
self.display_columns = cols;
|
|
||||||
}
|
|
||||||
pub fn progress_animation(&mut self) {
|
|
||||||
if self.loading_animation_offset == u8::MAX {
|
|
||||||
self.loading_animation_offset = 0;
|
|
||||||
} else {
|
|
||||||
self.loading_animation_offset = self.loading_animation_offset.saturating_add(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn number_of_lines_in_displayed_search_results(&self) -> usize {
|
|
||||||
self.displayed_search_results
|
|
||||||
.1
|
|
||||||
.iter()
|
|
||||||
.map(|l| l.rendered_height())
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
fn move_search_selection_down(&mut self) {
|
|
||||||
if self.displayed_search_results.0 < self.max_search_selection_index() {
|
|
||||||
self.displayed_search_results.0 += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn move_search_selection_up(&mut self) {
|
|
||||||
self.displayed_search_results.0 = self.displayed_search_results.0.saturating_sub(1);
|
|
||||||
}
|
|
||||||
fn open_search_result_in_editor(&mut self) {
|
|
||||||
match self.selected_search_result_entry() {
|
|
||||||
Some(SearchResult::File { path, .. }) => {
|
|
||||||
if self.should_open_floating {
|
|
||||||
open_file_floating(
|
|
||||||
FileToOpen {
|
|
||||||
path: PathBuf::from(path),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
open_file(FileToOpen {
|
|
||||||
path: PathBuf::from(path),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(SearchResult::LineInFile {
|
|
||||||
path, line_number, ..
|
|
||||||
}) => {
|
|
||||||
if self.should_open_floating {
|
|
||||||
open_file_floating(
|
|
||||||
FileToOpen {
|
|
||||||
path: PathBuf::from(path),
|
|
||||||
line_number: Some(line_number),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
open_file(FileToOpen {
|
|
||||||
path: PathBuf::from(path),
|
|
||||||
line_number: Some(line_number),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => eprintln!("Search results not found"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn open_search_result_in_terminal(&mut self) {
|
|
||||||
let dir_path_of_result = |path: &str| -> PathBuf {
|
|
||||||
let file_path = PathBuf::from(path);
|
|
||||||
let mut dir_path = file_path.components();
|
|
||||||
dir_path.next_back(); // remove file name to stay with just the folder
|
|
||||||
dir_path.as_path().into()
|
|
||||||
};
|
|
||||||
let selected_search_result_entry = self.selected_search_result_entry();
|
|
||||||
if let Some(SearchResult::File { path, .. }) | Some(SearchResult::LineInFile { path, .. }) =
|
|
||||||
selected_search_result_entry
|
|
||||||
{
|
|
||||||
let dir_path = dir_path_of_result(&path);
|
|
||||||
if self.should_open_floating {
|
|
||||||
open_terminal_floating(&dir_path, None);
|
|
||||||
} else {
|
|
||||||
open_terminal(&dir_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn toggle_search_filter(&mut self) {
|
|
||||||
self.search_filter.progress();
|
|
||||||
self.send_search_query();
|
|
||||||
}
|
|
||||||
fn clear_state(&mut self) {
|
|
||||||
self.file_name_search_results.clear();
|
|
||||||
self.file_contents_search_results.clear();
|
|
||||||
self.displayed_search_results = (0, vec![]);
|
|
||||||
self.search_term.clear();
|
|
||||||
}
|
|
||||||
fn append_to_search_term(&mut self, key: Key) {
|
|
||||||
match key {
|
|
||||||
Key::Char(character) => {
|
|
||||||
self.search_term.push(character);
|
|
||||||
},
|
|
||||||
Key::Backspace => {
|
|
||||||
self.search_term.pop();
|
|
||||||
if self.search_term.len() == 0 {
|
|
||||||
self.clear_state();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
self.send_search_query();
|
|
||||||
}
|
|
||||||
fn send_search_query(&mut self) {
|
|
||||||
match std::fs::write(CURRENT_SEARCH_TERM, &self.search_term) {
|
|
||||||
Ok(_) => {
|
|
||||||
if !self.search_term.is_empty() {
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_name_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
|
||||||
payload: "".into(),
|
|
||||||
});
|
|
||||||
post_message_to(PluginMessage {
|
|
||||||
worker_name: Some("file_contents_search".into()),
|
|
||||||
name: serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
|
||||||
payload: "".into(),
|
|
||||||
});
|
|
||||||
self.file_name_search_results.clear();
|
|
||||||
self.file_contents_search_results.clear();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("Failed to write search term to HD, aborting search: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn max_search_selection_index(&self) -> usize {
|
|
||||||
self.displayed_search_results.1.len().saturating_sub(1)
|
|
||||||
}
|
|
||||||
fn update_displayed_search_results(&mut self) {
|
|
||||||
if self.search_term.is_empty() {
|
|
||||||
self.clear_state();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut search_results_of_interest = match self.search_filter {
|
|
||||||
SearchType::NamesAndContents => {
|
|
||||||
let mut all_search_results = self.file_name_search_results.clone();
|
|
||||||
all_search_results.append(&mut self.file_contents_search_results.clone());
|
|
||||||
all_search_results.sort_by(|a, b| b.score().cmp(&a.score()));
|
|
||||||
all_search_results
|
|
||||||
},
|
|
||||||
SearchType::Names => self.file_name_search_results.clone(),
|
|
||||||
SearchType::Contents => self.file_contents_search_results.clone(),
|
|
||||||
};
|
|
||||||
let mut height_taken_up_by_results = 0;
|
|
||||||
let mut displayed_search_results = vec![];
|
|
||||||
for search_result in search_results_of_interest.drain(..) {
|
|
||||||
if height_taken_up_by_results + search_result.rendered_height()
|
|
||||||
> self.rows_for_results()
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
height_taken_up_by_results += search_result.rendered_height();
|
|
||||||
displayed_search_results.push(search_result);
|
|
||||||
}
|
|
||||||
let new_index = self
|
|
||||||
.selected_search_result_entry()
|
|
||||||
.and_then(|currently_selected_search_result| {
|
|
||||||
displayed_search_results
|
|
||||||
.iter()
|
|
||||||
.position(|r| r.is_same_entry(¤tly_selected_search_result))
|
|
||||||
})
|
|
||||||
.unwrap_or(0);
|
|
||||||
self.displayed_search_results = (new_index, displayed_search_results);
|
|
||||||
}
|
|
||||||
fn selected_search_result_entry(&self) -> Option<SearchResult> {
|
|
||||||
self.displayed_search_results
|
|
||||||
.1
|
|
||||||
.get(self.displayed_search_results.0)
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
pub fn rows_for_results(&self) -> usize {
|
|
||||||
self.display_rows.saturating_sub(3) // search line and 2 controls lines
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub enum SearchType {
|
|
||||||
NamesAndContents,
|
|
||||||
Names,
|
|
||||||
Contents,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SearchType {
|
|
||||||
pub fn progress(&mut self) {
|
|
||||||
match &self {
|
|
||||||
&SearchType::NamesAndContents => *self = SearchType::Names,
|
|
||||||
&SearchType::Names => *self = SearchType::Contents,
|
|
||||||
&SearchType::Contents => *self = SearchType::NamesAndContents,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SearchType {
|
|
||||||
fn default() -> Self {
|
|
||||||
SearchType::NamesAndContents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
use crate::search::ui::{bold, styled_text_foreground, ORANGE};
|
|
||||||
|
|
||||||
pub struct SelectionControlsArea {
|
|
||||||
display_lines: usize,
|
|
||||||
display_columns: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectionControlsArea {
|
|
||||||
pub fn new(display_lines: usize, display_columns: usize) -> Self {
|
|
||||||
SelectionControlsArea {
|
|
||||||
display_lines,
|
|
||||||
display_columns,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn render(&self, result_count: usize) -> String {
|
|
||||||
let mut to_render = String::new();
|
|
||||||
let padding = self.display_lines.saturating_sub(result_count);
|
|
||||||
for _ in 0..padding {
|
|
||||||
to_render.push_str(&self.render_padding_line());
|
|
||||||
}
|
|
||||||
let selection_controls = self.render_selection_controls();
|
|
||||||
to_render.push_str(&selection_controls);
|
|
||||||
to_render
|
|
||||||
}
|
|
||||||
pub fn render_empty_lines(&self) -> String {
|
|
||||||
let mut to_render = String::new();
|
|
||||||
for _ in 0..self.display_lines {
|
|
||||||
to_render.push_str("\n");
|
|
||||||
}
|
|
||||||
to_render
|
|
||||||
}
|
|
||||||
fn render_padding_line(&self) -> String {
|
|
||||||
format!("│\n")
|
|
||||||
}
|
|
||||||
fn render_selection_controls(&self) -> String {
|
|
||||||
if self.display_columns >= self.full_selection_controls_len() {
|
|
||||||
self.render_full_selection_controls()
|
|
||||||
} else {
|
|
||||||
self.render_truncated_selection_controls()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn full_selection_controls_len(&self) -> usize {
|
|
||||||
62
|
|
||||||
}
|
|
||||||
fn render_full_selection_controls(&self) -> String {
|
|
||||||
let arrow_tail = "└ ";
|
|
||||||
let enter = styled_text_foreground(ORANGE, &bold("<ENTER>"));
|
|
||||||
let enter_tip = bold(" - open in editor. ");
|
|
||||||
let tab = styled_text_foreground(ORANGE, &bold("<TAB>"));
|
|
||||||
let tab_tip = bold(" - open terminal at location.");
|
|
||||||
format!("{}{}{}{}{}", arrow_tail, enter, enter_tip, tab, tab_tip)
|
|
||||||
}
|
|
||||||
fn render_truncated_selection_controls(&self) -> String {
|
|
||||||
let arrow_tail = "└ ";
|
|
||||||
let enter = styled_text_foreground(ORANGE, &bold("<ENTER>"));
|
|
||||||
let enter_tip = bold(" - edit. ");
|
|
||||||
let tab = styled_text_foreground(ORANGE, &bold("<TAB>"));
|
|
||||||
let tab_tip = bold(" - terminal.");
|
|
||||||
format!("{}{}{}{}{}", arrow_tail, enter, enter_tip, tab, tab_tip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
use crate::search::controls_line::{Control, ControlsLine};
|
|
||||||
use crate::search::search_state::SearchState;
|
|
||||||
use crate::search::selection_controls_area::SelectionControlsArea;
|
|
||||||
use std::fmt::{Display, Formatter, Result};
|
|
||||||
|
|
||||||
pub const CYAN: u8 = 51;
|
|
||||||
pub const GRAY_LIGHT: u8 = 238;
|
|
||||||
pub const GRAY_DARK: u8 = 245;
|
|
||||||
pub const WHITE: u8 = 15;
|
|
||||||
pub const BLACK: u8 = 16;
|
|
||||||
pub const RED: u8 = 124;
|
|
||||||
pub const GREEN: u8 = 154;
|
|
||||||
pub const ORANGE: u8 = 166;
|
|
||||||
|
|
||||||
impl Display for SearchState {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
|
||||||
write!(f, "{}", self.render_search_line())?;
|
|
||||||
write!(f, "{}", self.render_search_results())?;
|
|
||||||
write!(f, "{}", self.render_selection_control_area())?;
|
|
||||||
write!(f, "{}", self.render_controls_line())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SearchState {
|
|
||||||
pub fn render_search_line(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}\n",
|
|
||||||
styled_text_foreground(CYAN, &bold("SEARCH: ")),
|
|
||||||
self.search_term
|
|
||||||
)
|
|
||||||
}
|
|
||||||
pub fn render_search_results(&self) -> String {
|
|
||||||
let mut space_for_results = self.display_rows.saturating_sub(3); // title and both controls lines
|
|
||||||
let mut to_render = String::new();
|
|
||||||
for (i, search_result) in self.displayed_search_results.1.iter().enumerate() {
|
|
||||||
let result_height = search_result.rendered_height();
|
|
||||||
if space_for_results < result_height {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
space_for_results -= result_height;
|
|
||||||
let index_of_selected_result = self.displayed_search_results.0;
|
|
||||||
let is_selected = i == index_of_selected_result;
|
|
||||||
let is_below_search_result = i > index_of_selected_result;
|
|
||||||
let rendered_result =
|
|
||||||
search_result.render(self.display_columns, is_selected, is_below_search_result);
|
|
||||||
to_render.push_str(&format!("{}", rendered_result));
|
|
||||||
to_render.push('\n')
|
|
||||||
}
|
|
||||||
to_render
|
|
||||||
}
|
|
||||||
pub fn render_selection_control_area(&self) -> String {
|
|
||||||
let rows_for_results = self.rows_for_results();
|
|
||||||
if !self.displayed_search_results.1.is_empty() {
|
|
||||||
format!(
|
|
||||||
"{}\n",
|
|
||||||
SelectionControlsArea::new(rows_for_results, self.display_columns)
|
|
||||||
.render(self.number_of_lines_in_displayed_search_results())
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"{}\n",
|
|
||||||
SelectionControlsArea::new(rows_for_results, self.display_columns)
|
|
||||||
.render_empty_lines()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn render_controls_line(&self) -> String {
|
|
||||||
let has_results = !self.displayed_search_results.1.is_empty();
|
|
||||||
let tiled_floating_control =
|
|
||||||
Control::new_floating_control("Ctrl f", self.should_open_floating);
|
|
||||||
let names_contents_control = Control::new_filter_control("Ctrl r", &self.search_filter);
|
|
||||||
if self.loading {
|
|
||||||
ControlsLine::new(
|
|
||||||
vec![tiled_floating_control, names_contents_control],
|
|
||||||
Some(vec!["Scanning folder", "Scanning", "S"]),
|
|
||||||
)
|
|
||||||
.with_animation_offset(self.loading_animation_offset)
|
|
||||||
.render(self.display_columns, has_results)
|
|
||||||
} else {
|
|
||||||
ControlsLine::new(vec![tiled_floating_control, names_contents_control], None)
|
|
||||||
.render(self.display_columns, has_results)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bold(text: &str) -> String {
|
|
||||||
format!("\u{1b}[1m{}\u{1b}[m", text)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn underline(text: &str) -> String {
|
|
||||||
format!("\u{1b}[4m{}\u{1b}[m", text)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn styled_text(foreground_color: u8, background_color: u8, text: &str) -> String {
|
|
||||||
format!(
|
|
||||||
"\u{1b}[38;5;{};48;5;{}m{}\u{1b}[m",
|
|
||||||
foreground_color, background_color, text
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn styled_text_foreground(foreground_color: u8, text: &str) -> String {
|
|
||||||
format!("\u{1b}[38;5;{}m{}\u{1b}[m", foreground_color, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn styled_text_background(background_color: u8, text: &str) -> String {
|
|
||||||
format!("\u{1b}[48;5;{}m{}\u{1b}[m", background_color, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn color_line_to_end(background_color: u8) -> String {
|
|
||||||
format!("\u{1b}[48;5;{}m\u{1b}[0K", background_color)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn arrow(foreground: u8, background: u8) -> String {
|
|
||||||
format!("\u{1b}[38;5;{}m\u{1b}[48;5;{}m", foreground, background)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dot(foreground: u8, background: u8) -> String {
|
|
||||||
format!("\u{1b}[38;5;{};48;5;{}m•", foreground, background)
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
use crate::search::search_results::SearchResult;
|
|
||||||
use crate::search::search_state::SearchState;
|
|
||||||
use crate::search::search_state::SearchType;
|
|
||||||
use pretty_bytes::converter as pb;
|
use pretty_bytes::converter as pb;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
|
|
@ -11,7 +8,6 @@ use std::{
|
||||||
use zellij_tile::prelude::*;
|
use zellij_tile::prelude::*;
|
||||||
|
|
||||||
pub const ROOT: &str = "/host";
|
pub const ROOT: &str = "/host";
|
||||||
pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term";
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
|
@ -20,30 +16,12 @@ pub struct State {
|
||||||
pub cursor_hist: HashMap<PathBuf, (usize, usize)>,
|
pub cursor_hist: HashMap<PathBuf, (usize, usize)>,
|
||||||
pub hide_hidden_files: bool,
|
pub hide_hidden_files: bool,
|
||||||
pub ev_history: VecDeque<(Event, Instant)>, // stores last event, can be expanded in future
|
pub ev_history: VecDeque<(Event, Instant)>, // stores last event, can be expanded in future
|
||||||
pub search_state: SearchState,
|
|
||||||
pub search_paths: Vec<String>,
|
|
||||||
pub search_term: Option<String>,
|
|
||||||
pub file_name_search_results: Vec<SearchResult>,
|
|
||||||
pub file_contents_search_results: Vec<SearchResult>,
|
|
||||||
pub loading: bool,
|
pub loading: bool,
|
||||||
pub loading_animation_offset: u8,
|
pub loading_animation_offset: u8,
|
||||||
pub typing_search_term: bool,
|
|
||||||
pub selected_search_result: usize,
|
|
||||||
pub processed_search_index: usize,
|
|
||||||
pub should_open_floating: bool,
|
pub should_open_floating: bool,
|
||||||
pub search_filter: SearchType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn typing_search_term(&self) -> bool {
|
|
||||||
self.typing_search_term
|
|
||||||
}
|
|
||||||
pub fn start_typing_search_term(&mut self) {
|
|
||||||
self.typing_search_term = true;
|
|
||||||
}
|
|
||||||
pub fn stop_typing_search_term(&mut self) {
|
|
||||||
self.typing_search_term = false;
|
|
||||||
}
|
|
||||||
pub fn selected_mut(&mut self) -> &mut usize {
|
pub fn selected_mut(&mut self) -> &mut usize {
|
||||||
&mut self.cursor_hist.entry(self.path.clone()).or_default().0
|
&mut self.cursor_hist.entry(self.path.clone()).or_default().0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ pub fn start_client(
|
||||||
Box::new(opts),
|
Box::new(opts),
|
||||||
Box::new(config_options.clone()),
|
Box::new(config_options.clone()),
|
||||||
Box::new(layout.unwrap()),
|
Box::new(layout.unwrap()),
|
||||||
Some(config.plugins.clone()),
|
Box::new(config.plugins.clone()),
|
||||||
),
|
),
|
||||||
ipc_pipe,
|
ipc_pipe,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ use zellij_utils::{
|
||||||
get_mode_info,
|
get_mode_info,
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
options::Options,
|
options::Options,
|
||||||
plugins::PluginsConfig,
|
plugins::PluginAliases,
|
||||||
},
|
},
|
||||||
ipc::{ClientAttributes, ExitReason, ServerToClientMsg},
|
ipc::{ClientAttributes, ExitReason, ServerToClientMsg},
|
||||||
};
|
};
|
||||||
|
|
@ -65,8 +65,8 @@ pub enum ServerInstruction {
|
||||||
Box<CliArgs>,
|
Box<CliArgs>,
|
||||||
Box<Options>,
|
Box<Options>,
|
||||||
Box<Layout>,
|
Box<Layout>,
|
||||||
|
Box<PluginAliases>,
|
||||||
ClientId,
|
ClientId,
|
||||||
Option<PluginsConfig>,
|
|
||||||
),
|
),
|
||||||
Render(Option<HashMap<ClientId, String>>),
|
Render(Option<HashMap<ClientId, String>>),
|
||||||
UnblockInputThread,
|
UnblockInputThread,
|
||||||
|
|
@ -365,8 +365,8 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
opts,
|
opts,
|
||||||
config_options,
|
config_options,
|
||||||
layout,
|
layout,
|
||||||
|
plugin_aliases,
|
||||||
client_id,
|
client_id,
|
||||||
plugins,
|
|
||||||
) => {
|
) => {
|
||||||
let session = init_session(
|
let session = init_session(
|
||||||
os_input.clone(),
|
os_input.clone(),
|
||||||
|
|
@ -375,9 +375,9 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
SessionOptions {
|
SessionOptions {
|
||||||
opts,
|
opts,
|
||||||
layout: layout.clone(),
|
layout: layout.clone(),
|
||||||
plugins,
|
|
||||||
config_options: config_options.clone(),
|
config_options: config_options.clone(),
|
||||||
},
|
},
|
||||||
|
plugin_aliases,
|
||||||
);
|
);
|
||||||
*session_data.write().unwrap() = Some(session);
|
*session_data.write().unwrap() = Some(session);
|
||||||
session_state
|
session_state
|
||||||
|
|
@ -832,7 +832,6 @@ pub struct SessionOptions {
|
||||||
pub opts: Box<CliArgs>,
|
pub opts: Box<CliArgs>,
|
||||||
pub config_options: Box<Options>,
|
pub config_options: Box<Options>,
|
||||||
pub layout: Box<Layout>,
|
pub layout: Box<Layout>,
|
||||||
pub plugins: Option<PluginsConfig>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_session(
|
fn init_session(
|
||||||
|
|
@ -840,12 +839,12 @@ fn init_session(
|
||||||
to_server: SenderWithContext<ServerInstruction>,
|
to_server: SenderWithContext<ServerInstruction>,
|
||||||
client_attributes: ClientAttributes,
|
client_attributes: ClientAttributes,
|
||||||
options: SessionOptions,
|
options: SessionOptions,
|
||||||
|
plugin_aliases: Box<PluginAliases>,
|
||||||
) -> SessionMetaData {
|
) -> SessionMetaData {
|
||||||
let SessionOptions {
|
let SessionOptions {
|
||||||
opts,
|
opts,
|
||||||
config_options,
|
config_options,
|
||||||
layout,
|
layout,
|
||||||
plugins,
|
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
let _ = SCROLL_BUFFER_SIZE.set(
|
let _ = SCROLL_BUFFER_SIZE.set(
|
||||||
|
|
@ -975,13 +974,13 @@ fn init_session(
|
||||||
plugin_bus,
|
plugin_bus,
|
||||||
store,
|
store,
|
||||||
data_dir,
|
data_dir,
|
||||||
plugins.unwrap_or_default(),
|
|
||||||
layout,
|
layout,
|
||||||
path_to_default_shell,
|
path_to_default_shell,
|
||||||
zellij_cwd,
|
zellij_cwd,
|
||||||
capabilities,
|
capabilities,
|
||||||
client_attributes,
|
client_attributes,
|
||||||
default_shell,
|
default_shell,
|
||||||
|
plugin_aliases,
|
||||||
)
|
)
|
||||||
.fatal()
|
.fatal()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use zellij_utils::{
|
||||||
data::{ModeInfo, Style},
|
data::{ModeInfo, Style},
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::command::RunCommand,
|
input::command::RunCommand,
|
||||||
input::layout::{FloatingPaneLayout, Run, RunPlugin},
|
input::layout::{FloatingPaneLayout, Run, RunPlugin, RunPluginOrAlias},
|
||||||
pane_size::{Dimension, Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
pane_size::{Dimension, Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -872,11 +872,10 @@ impl FloatingPanes {
|
||||||
self.focus_pane_for_all_clients(active_pane_id);
|
self.focus_pane_for_all_clients(active_pane_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_plugin_pane_id(&self, run_plugin: &RunPlugin) -> Option<PaneId> {
|
pub fn get_plugin_pane_id(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option<PaneId> {
|
||||||
let run = Some(Run::Plugin(run_plugin.clone()));
|
|
||||||
self.panes
|
self.panes
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_id, s_p)| s_p.invoked_with() == &run)
|
.find(|(_id, pane)| run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with()))
|
||||||
.map(|(id, _)| *id)
|
.map(|(id, _)| *id)
|
||||||
}
|
}
|
||||||
pub fn focus_pane_if_exists(&mut self, pane_id: PaneId, client_id: ClientId) -> Result<()> {
|
pub fn focus_pane_if_exists(&mut self, pane_id: PaneId, client_id: ClientId) -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use zellij_utils::{
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::{
|
input::{
|
||||||
command::RunCommand,
|
command::RunCommand,
|
||||||
layout::{Run, RunPlugin, SplitDirection},
|
layout::{Run, RunPlugin, RunPluginOrAlias, SplitDirection},
|
||||||
},
|
},
|
||||||
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
||||||
};
|
};
|
||||||
|
|
@ -1744,11 +1744,10 @@ impl TiledPanes {
|
||||||
fn reset_boundaries(&mut self) {
|
fn reset_boundaries(&mut self) {
|
||||||
self.client_id_to_boundaries.clear();
|
self.client_id_to_boundaries.clear();
|
||||||
}
|
}
|
||||||
pub fn get_plugin_pane_id(&self, run_plugin: &RunPlugin) -> Option<PaneId> {
|
pub fn get_plugin_pane_id(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option<PaneId> {
|
||||||
let run = Some(Run::Plugin(run_plugin.clone()));
|
|
||||||
self.panes
|
self.panes
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_id, s_p)| s_p.invoked_with() == &run)
|
.find(|(_id, pane)| run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with()))
|
||||||
.map(|(id, _)| *id)
|
.map(|(id, _)| *id)
|
||||||
}
|
}
|
||||||
pub fn pane_info(&self) -> Vec<PaneInfo> {
|
pub fn pane_info(&self) -> Vec<PaneInfo> {
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,8 @@ use zellij_utils::{
|
||||||
errors::{prelude::*, ContextType, PluginContext},
|
errors::{prelude::*, ContextType, PluginContext},
|
||||||
input::{
|
input::{
|
||||||
command::TerminalAction,
|
command::TerminalAction,
|
||||||
layout::{
|
layout::{FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginOrAlias, TiledPaneLayout},
|
||||||
FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation,
|
plugins::PluginAliases,
|
||||||
TiledPaneLayout,
|
|
||||||
},
|
|
||||||
plugins::PluginsConfig,
|
|
||||||
},
|
},
|
||||||
ipc::ClientAttributes,
|
ipc::ClientAttributes,
|
||||||
pane_size::Size,
|
pane_size::Size,
|
||||||
|
|
@ -50,7 +47,7 @@ pub enum PluginInstruction {
|
||||||
Option<bool>, // should float
|
Option<bool>, // should float
|
||||||
bool, // should be opened in place
|
bool, // should be opened in place
|
||||||
Option<String>, // pane title
|
Option<String>, // pane title
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
usize, // tab index
|
usize, // tab index
|
||||||
Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
||||||
ClientId,
|
ClientId,
|
||||||
|
|
@ -63,7 +60,7 @@ pub enum PluginInstruction {
|
||||||
Reload(
|
Reload(
|
||||||
Option<bool>, // should float
|
Option<bool>, // should float
|
||||||
Option<String>, // pane title
|
Option<String>, // pane title
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
usize, // tab index
|
usize, // tab index
|
||||||
Size,
|
Size,
|
||||||
),
|
),
|
||||||
|
|
@ -173,19 +170,18 @@ pub(crate) fn plugin_thread_main(
|
||||||
bus: Bus<PluginInstruction>,
|
bus: Bus<PluginInstruction>,
|
||||||
store: Store,
|
store: Store,
|
||||||
data_dir: PathBuf,
|
data_dir: PathBuf,
|
||||||
plugins: PluginsConfig,
|
mut layout: Box<Layout>,
|
||||||
layout: Box<Layout>,
|
|
||||||
path_to_default_shell: PathBuf,
|
path_to_default_shell: PathBuf,
|
||||||
zellij_cwd: PathBuf,
|
zellij_cwd: PathBuf,
|
||||||
capabilities: PluginCapabilities,
|
capabilities: PluginCapabilities,
|
||||||
client_attributes: ClientAttributes,
|
client_attributes: ClientAttributes,
|
||||||
default_shell: Option<TerminalAction>,
|
default_shell: Option<TerminalAction>,
|
||||||
|
plugin_aliases: Box<PluginAliases>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("Wasm main thread starts");
|
info!("Wasm main thread starts");
|
||||||
|
|
||||||
let plugin_dir = data_dir.join("plugins/");
|
let plugin_dir = data_dir.join("plugins/");
|
||||||
let plugin_global_data_dir = plugin_dir.join("data");
|
let plugin_global_data_dir = plugin_dir.join("data");
|
||||||
|
layout.populate_plugin_aliases_in_layout(&plugin_aliases);
|
||||||
let store = Arc::new(Mutex::new(store));
|
let store = Arc::new(Mutex::new(store));
|
||||||
|
|
||||||
// use this channel to ensure that tasks spawned from this thread terminate before exiting
|
// use this channel to ensure that tasks spawned from this thread terminate before exiting
|
||||||
|
|
@ -193,7 +189,6 @@ pub(crate) fn plugin_thread_main(
|
||||||
let (shutdown_send, shutdown_receive) = channel::bounded::<()>(1);
|
let (shutdown_send, shutdown_receive) = channel::bounded::<()>(1);
|
||||||
|
|
||||||
let mut wasm_bridge = WasmBridge::new(
|
let mut wasm_bridge = WasmBridge::new(
|
||||||
plugins,
|
|
||||||
bus.senders.clone(),
|
bus.senders.clone(),
|
||||||
store,
|
store,
|
||||||
plugin_dir,
|
plugin_dir,
|
||||||
|
|
@ -213,38 +208,42 @@ pub(crate) fn plugin_thread_main(
|
||||||
should_float,
|
should_float,
|
||||||
should_be_open_in_place,
|
should_be_open_in_place,
|
||||||
pane_title,
|
pane_title,
|
||||||
run,
|
mut run_plugin_or_alias,
|
||||||
tab_index,
|
tab_index,
|
||||||
pane_id_to_replace,
|
pane_id_to_replace,
|
||||||
client_id,
|
client_id,
|
||||||
size,
|
size,
|
||||||
cwd,
|
cwd,
|
||||||
skip_cache,
|
skip_cache,
|
||||||
) => match wasm_bridge.load_plugin(
|
) => {
|
||||||
&run,
|
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
|
||||||
Some(tab_index),
|
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
||||||
size,
|
match wasm_bridge.load_plugin(
|
||||||
cwd.clone(),
|
&run_plugin,
|
||||||
skip_cache,
|
Some(tab_index),
|
||||||
Some(client_id),
|
size,
|
||||||
None,
|
cwd.clone(),
|
||||||
) {
|
skip_cache,
|
||||||
Ok((plugin_id, client_id)) => {
|
Some(client_id),
|
||||||
drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
None,
|
||||||
should_float,
|
) {
|
||||||
should_be_open_in_place,
|
Ok((plugin_id, client_id)) => {
|
||||||
run,
|
drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
||||||
pane_title,
|
should_float,
|
||||||
Some(tab_index),
|
should_be_open_in_place,
|
||||||
plugin_id,
|
run_plugin_or_alias,
|
||||||
pane_id_to_replace,
|
pane_title,
|
||||||
cwd,
|
Some(tab_index),
|
||||||
Some(client_id),
|
plugin_id,
|
||||||
)));
|
pane_id_to_replace,
|
||||||
},
|
cwd,
|
||||||
Err(e) => {
|
Some(client_id),
|
||||||
log::error!("Failed to load plugin: {e}");
|
)));
|
||||||
},
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to load plugin: {e}");
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
PluginInstruction::Update(updates) => {
|
PluginInstruction::Update(updates) => {
|
||||||
wasm_bridge.update_plugins(updates, shutdown_send.clone())?;
|
wasm_bridge.update_plugins(updates, shutdown_send.clone())?;
|
||||||
|
|
@ -252,50 +251,69 @@ pub(crate) fn plugin_thread_main(
|
||||||
PluginInstruction::Unload(pid) => {
|
PluginInstruction::Unload(pid) => {
|
||||||
wasm_bridge.unload_plugin(pid)?;
|
wasm_bridge.unload_plugin(pid)?;
|
||||||
},
|
},
|
||||||
PluginInstruction::Reload(should_float, pane_title, run, tab_index, size) => {
|
PluginInstruction::Reload(
|
||||||
match wasm_bridge.reload_plugin(&run) {
|
should_float,
|
||||||
Ok(_) => {
|
pane_title,
|
||||||
let _ = bus
|
mut run_plugin_or_alias,
|
||||||
.senders
|
tab_index,
|
||||||
.send_to_server(ServerInstruction::UnblockInputThread);
|
size,
|
||||||
},
|
) => {
|
||||||
Err(err) => match err.downcast_ref::<ZellijError>() {
|
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
|
||||||
Some(ZellijError::PluginDoesNotExist) => {
|
match run_plugin_or_alias.get_run_plugin() {
|
||||||
log::warn!("Plugin {} not found, starting it instead", run.location);
|
Some(run_plugin) => {
|
||||||
// we intentionally do not provide the client_id here because it belongs to
|
match wasm_bridge.reload_plugin(&run_plugin) {
|
||||||
// the cli who spawned the command and is not an existing client_id
|
Ok(_) => {
|
||||||
let skip_cache = true; // when reloading we always skip cache
|
let _ = bus
|
||||||
match wasm_bridge.load_plugin(
|
.senders
|
||||||
&run,
|
.send_to_server(ServerInstruction::UnblockInputThread);
|
||||||
Some(tab_index),
|
},
|
||||||
size,
|
Err(err) => match err.downcast_ref::<ZellijError>() {
|
||||||
None,
|
Some(ZellijError::PluginDoesNotExist) => {
|
||||||
skip_cache,
|
log::warn!(
|
||||||
None,
|
"Plugin {} not found, starting it instead",
|
||||||
None,
|
run_plugin.location
|
||||||
) {
|
);
|
||||||
Ok((plugin_id, _client_id)) => {
|
// we intentionally do not provide the client_id here because it belongs to
|
||||||
let should_be_open_in_place = false;
|
// the cli who spawned the command and is not an existing client_id
|
||||||
drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
let skip_cache = true; // when reloading we always skip cache
|
||||||
should_float,
|
match wasm_bridge.load_plugin(
|
||||||
should_be_open_in_place,
|
&Some(run_plugin),
|
||||||
run,
|
|
||||||
pane_title,
|
|
||||||
Some(tab_index),
|
Some(tab_index),
|
||||||
plugin_id,
|
size,
|
||||||
|
None,
|
||||||
|
skip_cache,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
) {
|
||||||
)));
|
Ok((plugin_id, _client_id)) => {
|
||||||
|
let should_be_open_in_place = false;
|
||||||
|
drop(bus.senders.send_to_screen(
|
||||||
|
ScreenInstruction::AddPlugin(
|
||||||
|
should_float,
|
||||||
|
should_be_open_in_place,
|
||||||
|
run_plugin_or_alias,
|
||||||
|
pane_title,
|
||||||
|
Some(tab_index),
|
||||||
|
plugin_id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to load plugin: {e}");
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
Err(e) => {
|
_ => {
|
||||||
log::error!("Failed to load plugin: {e}");
|
return Err(err);
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
},
|
}
|
||||||
_ => {
|
},
|
||||||
return Err(err);
|
None => {
|
||||||
},
|
log::error!("Failed to find plugin info for: {:?}", run_plugin_or_alias)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -311,15 +329,21 @@ pub(crate) fn plugin_thread_main(
|
||||||
PluginInstruction::NewTab(
|
PluginInstruction::NewTab(
|
||||||
cwd,
|
cwd,
|
||||||
terminal_action,
|
terminal_action,
|
||||||
tab_layout,
|
mut tab_layout,
|
||||||
floating_panes_layout,
|
mut floating_panes_layout,
|
||||||
tab_index,
|
tab_index,
|
||||||
client_id,
|
client_id,
|
||||||
) => {
|
) => {
|
||||||
let mut plugin_ids: HashMap<
|
let mut plugin_ids: HashMap<RunPluginOrAlias, Vec<PluginId>> = HashMap::new();
|
||||||
(RunPluginLocation, PluginUserConfiguration),
|
tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0));
|
||||||
Vec<PluginId>,
|
tab_layout
|
||||||
> = HashMap::new();
|
.as_mut()
|
||||||
|
.map(|t| t.populate_plugin_aliases_in_layout(&plugin_aliases));
|
||||||
|
floating_panes_layout.iter_mut().for_each(|f| {
|
||||||
|
f.run
|
||||||
|
.as_mut()
|
||||||
|
.map(|f| f.populate_run_plugin_if_needed(&plugin_aliases));
|
||||||
|
});
|
||||||
let mut extracted_run_instructions = tab_layout
|
let mut extracted_run_instructions = tab_layout
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| layout.new_tab().0)
|
.unwrap_or_else(|| layout.new_tab().0)
|
||||||
|
|
@ -337,10 +361,11 @@ pub(crate) fn plugin_thread_main(
|
||||||
.collect();
|
.collect();
|
||||||
extracted_run_instructions.append(&mut extracted_floating_plugins);
|
extracted_run_instructions.append(&mut extracted_floating_plugins);
|
||||||
for run_instruction in extracted_run_instructions {
|
for run_instruction in extracted_run_instructions {
|
||||||
if let Some(Run::Plugin(run)) = run_instruction {
|
if let Some(Run::Plugin(run_plugin_or_alias)) = run_instruction {
|
||||||
|
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
||||||
let skip_cache = false;
|
let skip_cache = false;
|
||||||
let (plugin_id, _client_id) = wasm_bridge.load_plugin(
|
let (plugin_id, _client_id) = wasm_bridge.load_plugin(
|
||||||
&run,
|
&run_plugin,
|
||||||
Some(tab_index),
|
Some(tab_index),
|
||||||
size,
|
size,
|
||||||
None,
|
None,
|
||||||
|
|
@ -349,7 +374,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
plugin_ids
|
plugin_ids
|
||||||
.entry((run.location, run.configuration))
|
.entry(run_plugin_or_alias.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(plugin_id);
|
.push(plugin_id);
|
||||||
}
|
}
|
||||||
|
|
@ -488,6 +513,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
&args,
|
&args,
|
||||||
&bus,
|
&bus,
|
||||||
&mut wasm_bridge,
|
&mut wasm_bridge,
|
||||||
|
&plugin_aliases,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -550,6 +576,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
&Some(message.message_args),
|
&Some(message.message_args),
|
||||||
&bus,
|
&bus,
|
||||||
&mut wasm_bridge,
|
&mut wasm_bridge,
|
||||||
|
&plugin_aliases,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -660,16 +687,19 @@ fn pipe_to_specific_plugins(
|
||||||
args: &Option<BTreeMap<String, String>>,
|
args: &Option<BTreeMap<String, String>>,
|
||||||
bus: &Bus<PluginInstruction>,
|
bus: &Bus<PluginInstruction>,
|
||||||
wasm_bridge: &mut WasmBridge,
|
wasm_bridge: &mut WasmBridge,
|
||||||
|
plugin_aliases: &PluginAliases,
|
||||||
) {
|
) {
|
||||||
let is_private = true;
|
let is_private = true;
|
||||||
let size = Size::default();
|
let size = Size::default();
|
||||||
match RunPlugin::from_url(&plugin_url) {
|
match RunPluginOrAlias::from_url(
|
||||||
Ok(mut run_plugin) => {
|
&plugin_url,
|
||||||
if let Some(configuration) = configuration {
|
configuration,
|
||||||
run_plugin.configuration = PluginUserConfiguration::new(configuration.clone());
|
Some(plugin_aliases),
|
||||||
}
|
cwd.clone(),
|
||||||
|
) {
|
||||||
|
Ok(run_plugin_or_alias) => {
|
||||||
let all_plugin_ids = wasm_bridge.get_or_load_plugins(
|
let all_plugin_ids = wasm_bridge.get_or_load_plugins(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
size,
|
size,
|
||||||
cwd.clone(),
|
cwd.clone(),
|
||||||
skip_cache,
|
skip_cache,
|
||||||
|
|
@ -683,7 +713,7 @@ fn pipe_to_specific_plugins(
|
||||||
pipe_messages.push((
|
pipe_messages.push((
|
||||||
Some(plugin_id),
|
Some(plugin_id),
|
||||||
client_id,
|
client_id,
|
||||||
PipeMessage::new(pipe_source.clone(), name, payload, args, is_private), // PipeMessage::new(PipeSource::Cli(pipe_id.clone()), &name, &payload, &args, is_private)
|
PipeMessage::new(pipe_source.clone(), name, payload, args, is_private),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
|
assertion_line: 706
|
||||||
|
expression: "format!(\"{:#?}\", plugin_bytes_event)"
|
||||||
|
---
|
||||||
|
Some(
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
"Rows: 20, Cols: 121, Received events: [InputReceived]\n\r",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 2931
|
assertion_line: 3700
|
||||||
expression: "format!(\"{:#?}\", new_tab_event)"
|
expression: "format!(\"{:#?}\", new_tab_event)"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
StartOrReloadPluginPane(
|
StartOrReloadPluginPane(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: File(
|
_allow_exec_host_cmd: false,
|
||||||
"/path/to/my/plugin.wasm",
|
location: File(
|
||||||
),
|
"/path/to/my/plugin.wasm",
|
||||||
configuration: PluginUserConfiguration(
|
),
|
||||||
{},
|
configuration: PluginUserConfiguration(
|
||||||
),
|
{},
|
||||||
},
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ use zellij_utils::{
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::{
|
input::{
|
||||||
command::TerminalAction,
|
command::TerminalAction,
|
||||||
layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation},
|
layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias},
|
||||||
plugins::PluginsConfig,
|
plugins::PluginConfig,
|
||||||
},
|
},
|
||||||
ipc::ClientAttributes,
|
ipc::ClientAttributes,
|
||||||
pane_size::Size,
|
pane_size::Size,
|
||||||
|
|
@ -76,7 +76,6 @@ impl PluginRenderAsset {
|
||||||
|
|
||||||
pub struct WasmBridge {
|
pub struct WasmBridge {
|
||||||
connected_clients: Arc<Mutex<Vec<ClientId>>>,
|
connected_clients: Arc<Mutex<Vec<ClientId>>>,
|
||||||
plugins: PluginsConfig,
|
|
||||||
senders: ThreadSenders,
|
senders: ThreadSenders,
|
||||||
store: Arc<Mutex<Store>>,
|
store: Arc<Mutex<Store>>,
|
||||||
plugin_dir: PathBuf,
|
plugin_dir: PathBuf,
|
||||||
|
|
@ -106,7 +105,6 @@ pub struct WasmBridge {
|
||||||
|
|
||||||
impl WasmBridge {
|
impl WasmBridge {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
plugins: PluginsConfig,
|
|
||||||
senders: ThreadSenders,
|
senders: ThreadSenders,
|
||||||
store: Arc<Mutex<Store>>,
|
store: Arc<Mutex<Store>>,
|
||||||
plugin_dir: PathBuf,
|
plugin_dir: PathBuf,
|
||||||
|
|
@ -124,7 +122,6 @@ impl WasmBridge {
|
||||||
let watcher = None;
|
let watcher = None;
|
||||||
WasmBridge {
|
WasmBridge {
|
||||||
connected_clients,
|
connected_clients,
|
||||||
plugins,
|
|
||||||
senders,
|
senders,
|
||||||
store,
|
store,
|
||||||
plugin_dir,
|
plugin_dir,
|
||||||
|
|
@ -150,7 +147,7 @@ impl WasmBridge {
|
||||||
}
|
}
|
||||||
pub fn load_plugin(
|
pub fn load_plugin(
|
||||||
&mut self,
|
&mut self,
|
||||||
run: &RunPlugin,
|
run: &Option<RunPlugin>,
|
||||||
tab_index: Option<usize>,
|
tab_index: Option<usize>,
|
||||||
size: Size,
|
size: Size,
|
||||||
cwd: Option<PathBuf>,
|
cwd: Option<PathBuf>,
|
||||||
|
|
@ -176,95 +173,109 @@ impl WasmBridge {
|
||||||
|
|
||||||
let plugin_id = self.next_plugin_id;
|
let plugin_id = self.next_plugin_id;
|
||||||
|
|
||||||
let mut plugin = self
|
match run {
|
||||||
.plugins
|
Some(run) => {
|
||||||
.get(run)
|
let mut plugin = PluginConfig::from_run_plugin(run)
|
||||||
.with_context(|| format!("failed to resolve plugin {run:?}"))
|
.with_context(|| format!("failed to resolve plugin {run:?}"))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let plugin_name = run.location.to_string();
|
let plugin_name = run.location.to_string();
|
||||||
|
|
||||||
self.cached_events_for_pending_plugins
|
self.cached_events_for_pending_plugins
|
||||||
.insert(plugin_id, vec![]);
|
.insert(plugin_id, vec![]);
|
||||||
self.cached_resizes_for_pending_plugins
|
self.cached_resizes_for_pending_plugins
|
||||||
.insert(plugin_id, (size.rows, size.cols));
|
.insert(plugin_id, (size.rows, size.cols));
|
||||||
|
|
||||||
let load_plugin_task = task::spawn({
|
let load_plugin_task = task::spawn({
|
||||||
let plugin_dir = self.plugin_dir.clone();
|
let plugin_dir = self.plugin_dir.clone();
|
||||||
let plugin_cache = self.plugin_cache.clone();
|
let plugin_cache = self.plugin_cache.clone();
|
||||||
let senders = self.senders.clone();
|
let senders = self.senders.clone();
|
||||||
let store = self.store.clone();
|
let store = self.store.clone();
|
||||||
let plugin_map = self.plugin_map.clone();
|
let plugin_map = self.plugin_map.clone();
|
||||||
let connected_clients = self.connected_clients.clone();
|
let connected_clients = self.connected_clients.clone();
|
||||||
let path_to_default_shell = self.path_to_default_shell.clone();
|
let path_to_default_shell = self.path_to_default_shell.clone();
|
||||||
let zellij_cwd = cwd.unwrap_or_else(|| self.zellij_cwd.clone());
|
let zellij_cwd = cwd.unwrap_or_else(|| self.zellij_cwd.clone());
|
||||||
let capabilities = self.capabilities.clone();
|
let capabilities = self.capabilities.clone();
|
||||||
let client_attributes = self.client_attributes.clone();
|
let client_attributes = self.client_attributes.clone();
|
||||||
let default_shell = self.default_shell.clone();
|
let default_shell = self.default_shell.clone();
|
||||||
let default_layout = self.default_layout.clone();
|
let default_layout = self.default_layout.clone();
|
||||||
async move {
|
async move {
|
||||||
let _ =
|
let _ = senders.send_to_background_jobs(
|
||||||
senders.send_to_background_jobs(BackgroundJob::AnimatePluginLoading(plugin_id));
|
BackgroundJob::AnimatePluginLoading(plugin_id),
|
||||||
let mut loading_indication = LoadingIndication::new(plugin_name.clone());
|
);
|
||||||
|
let mut loading_indication = LoadingIndication::new(plugin_name.clone());
|
||||||
|
|
||||||
if let RunPluginLocation::Remote(url) = &plugin.location {
|
if let RunPluginLocation::Remote(url) = &plugin.location {
|
||||||
let file_name: String = PortableHash::default()
|
let file_name: String = PortableHash::default()
|
||||||
.hash128(url.as_bytes())
|
.hash128(url.as_bytes())
|
||||||
.iter()
|
.iter()
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let downloader = Downloader::new(ZELLIJ_CACHE_DIR.to_path_buf());
|
let downloader = Downloader::new(ZELLIJ_CACHE_DIR.to_path_buf());
|
||||||
match downloader.download(url, Some(&file_name)).await {
|
match downloader.download(url, Some(&file_name)).await {
|
||||||
Ok(_) => plugin.path = ZELLIJ_CACHE_DIR.join(&file_name),
|
Ok(_) => plugin.path = ZELLIJ_CACHE_DIR.join(&file_name),
|
||||||
Err(e) => handle_plugin_loading_failure(
|
Err(e) => handle_plugin_loading_failure(
|
||||||
&senders,
|
&senders,
|
||||||
|
plugin_id,
|
||||||
|
&mut loading_indication,
|
||||||
|
e,
|
||||||
|
cli_client_id,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match PluginLoader::start_plugin(
|
||||||
plugin_id,
|
plugin_id,
|
||||||
|
client_id,
|
||||||
|
&plugin,
|
||||||
|
tab_index,
|
||||||
|
plugin_dir,
|
||||||
|
plugin_cache,
|
||||||
|
senders.clone(),
|
||||||
|
store,
|
||||||
|
plugin_map,
|
||||||
|
size,
|
||||||
|
connected_clients.clone(),
|
||||||
&mut loading_indication,
|
&mut loading_indication,
|
||||||
e,
|
path_to_default_shell,
|
||||||
cli_client_id,
|
zellij_cwd.clone(),
|
||||||
),
|
capabilities,
|
||||||
|
client_attributes,
|
||||||
|
default_shell,
|
||||||
|
default_layout,
|
||||||
|
skip_cache,
|
||||||
|
) {
|
||||||
|
Ok(_) => handle_plugin_successful_loading(&senders, plugin_id),
|
||||||
|
Err(e) => handle_plugin_loading_failure(
|
||||||
|
&senders,
|
||||||
|
plugin_id,
|
||||||
|
&mut loading_indication,
|
||||||
|
e,
|
||||||
|
cli_client_id,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
let _ = senders.send_to_plugin(PluginInstruction::ApplyCachedEvents {
|
||||||
|
plugin_ids: vec![plugin_id],
|
||||||
|
done_receiving_permissions: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
match PluginLoader::start_plugin(
|
|
||||||
plugin_id,
|
|
||||||
client_id,
|
|
||||||
&plugin,
|
|
||||||
tab_index,
|
|
||||||
plugin_dir,
|
|
||||||
plugin_cache,
|
|
||||||
senders.clone(),
|
|
||||||
store,
|
|
||||||
plugin_map,
|
|
||||||
size,
|
|
||||||
connected_clients.clone(),
|
|
||||||
&mut loading_indication,
|
|
||||||
path_to_default_shell,
|
|
||||||
zellij_cwd.clone(),
|
|
||||||
capabilities,
|
|
||||||
client_attributes,
|
|
||||||
default_shell,
|
|
||||||
default_layout,
|
|
||||||
skip_cache,
|
|
||||||
) {
|
|
||||||
Ok(_) => handle_plugin_successful_loading(&senders, plugin_id),
|
|
||||||
Err(e) => handle_plugin_loading_failure(
|
|
||||||
&senders,
|
|
||||||
plugin_id,
|
|
||||||
&mut loading_indication,
|
|
||||||
e,
|
|
||||||
cli_client_id,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
let _ = senders.send_to_plugin(PluginInstruction::ApplyCachedEvents {
|
|
||||||
plugin_ids: vec![plugin_id],
|
|
||||||
done_receiving_permissions: false,
|
|
||||||
});
|
});
|
||||||
}
|
self.loading_plugins
|
||||||
});
|
.insert((plugin_id, run.clone()), load_plugin_task);
|
||||||
self.loading_plugins
|
self.next_plugin_id += 1;
|
||||||
.insert((plugin_id, run.clone()), load_plugin_task);
|
},
|
||||||
self.next_plugin_id += 1;
|
None => {
|
||||||
|
self.next_plugin_id += 1;
|
||||||
|
let mut loading_indication = LoadingIndication::new(format!("{}", plugin_id));
|
||||||
|
handle_plugin_loading_failure(
|
||||||
|
&self.senders,
|
||||||
|
plugin_id,
|
||||||
|
&mut loading_indication,
|
||||||
|
"Failed to resolve plugin alias",
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
Ok((plugin_id, client_id))
|
Ok((plugin_id, client_id))
|
||||||
}
|
}
|
||||||
pub fn unload_plugin(&mut self, pid: PluginId) -> Result<()> {
|
pub fn unload_plugin(&mut self, pid: PluginId) -> Result<()> {
|
||||||
|
|
@ -1076,7 +1087,7 @@ impl WasmBridge {
|
||||||
// returns its details
|
// returns its details
|
||||||
pub fn get_or_load_plugins(
|
pub fn get_or_load_plugins(
|
||||||
&mut self,
|
&mut self,
|
||||||
run_plugin: RunPlugin,
|
run_plugin_or_alias: RunPluginOrAlias,
|
||||||
size: Size,
|
size: Size,
|
||||||
cwd: Option<PathBuf>,
|
cwd: Option<PathBuf>,
|
||||||
skip_cache: bool,
|
skip_cache: bool,
|
||||||
|
|
@ -1086,52 +1097,62 @@ impl WasmBridge {
|
||||||
pane_id_to_replace: Option<PaneId>,
|
pane_id_to_replace: Option<PaneId>,
|
||||||
cli_client_id: Option<ClientId>,
|
cli_client_id: Option<ClientId>,
|
||||||
) -> Vec<(PluginId, Option<ClientId>)> {
|
) -> Vec<(PluginId, Option<ClientId>)> {
|
||||||
let all_plugin_ids = self.all_plugin_and_client_ids_for_plugin_location(
|
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
||||||
&run_plugin.location,
|
match run_plugin {
|
||||||
&run_plugin.configuration,
|
Some(run_plugin) => {
|
||||||
);
|
let all_plugin_ids = self.all_plugin_and_client_ids_for_plugin_location(
|
||||||
if all_plugin_ids.is_empty() {
|
&run_plugin.location,
|
||||||
if let Some(loading_plugin_id) =
|
&run_plugin.configuration,
|
||||||
self.plugin_id_of_loading_plugin(&run_plugin.location, &run_plugin.configuration)
|
);
|
||||||
{
|
if all_plugin_ids.is_empty() {
|
||||||
return vec![(loading_plugin_id, None)];
|
if let Some(loading_plugin_id) = self.plugin_id_of_loading_plugin(
|
||||||
}
|
&run_plugin.location,
|
||||||
match self.load_plugin(
|
&run_plugin.configuration,
|
||||||
&run_plugin,
|
) {
|
||||||
None,
|
return vec![(loading_plugin_id, None)];
|
||||||
size,
|
|
||||||
cwd.clone(),
|
|
||||||
skip_cache,
|
|
||||||
None,
|
|
||||||
cli_client_id,
|
|
||||||
) {
|
|
||||||
Ok((plugin_id, client_id)) => {
|
|
||||||
drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
|
||||||
Some(should_float),
|
|
||||||
should_be_open_in_place,
|
|
||||||
run_plugin,
|
|
||||||
pane_title,
|
|
||||||
None,
|
|
||||||
plugin_id,
|
|
||||||
pane_id_to_replace,
|
|
||||||
cwd,
|
|
||||||
Some(client_id),
|
|
||||||
)));
|
|
||||||
vec![(plugin_id, Some(client_id))]
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Failed to load plugin: {e}");
|
|
||||||
if let Some(cli_client_id) = cli_client_id {
|
|
||||||
let _ = self.senders.send_to_server(ServerInstruction::LogError(
|
|
||||||
vec![format!("Failed to log plugin: {e}")],
|
|
||||||
cli_client_id,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
vec![]
|
match self.load_plugin(
|
||||||
},
|
&Some(run_plugin),
|
||||||
}
|
None,
|
||||||
} else {
|
size,
|
||||||
all_plugin_ids
|
cwd.clone(),
|
||||||
|
skip_cache,
|
||||||
|
None,
|
||||||
|
cli_client_id,
|
||||||
|
) {
|
||||||
|
Ok((plugin_id, client_id)) => {
|
||||||
|
drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
||||||
|
Some(should_float),
|
||||||
|
should_be_open_in_place,
|
||||||
|
run_plugin_or_alias,
|
||||||
|
pane_title,
|
||||||
|
None,
|
||||||
|
plugin_id,
|
||||||
|
pane_id_to_replace,
|
||||||
|
cwd,
|
||||||
|
Some(client_id),
|
||||||
|
)));
|
||||||
|
vec![(plugin_id, Some(client_id))]
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to load plugin: {e}");
|
||||||
|
if let Some(cli_client_id) = cli_client_id {
|
||||||
|
let _ = self.senders.send_to_server(ServerInstruction::LogError(
|
||||||
|
vec![format!("Failed to log plugin: {e}")],
|
||||||
|
cli_client_id,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
all_plugin_ids
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
log::error!("Plugin not found for alias");
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn clear_plugin_map_cache(&mut self) {
|
pub fn clear_plugin_map_cache(&mut self) {
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@ use zellij_utils::{
|
||||||
ipc::{ClientToServerMsg, IpcSenderWithContext},
|
ipc::{ClientToServerMsg, IpcSenderWithContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::{panes::PaneId, screen::ScreenInstruction};
|
use crate::{panes::PaneId, screen::ScreenInstruction};
|
||||||
|
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
|
|
@ -41,7 +39,7 @@ use zellij_utils::{
|
||||||
input::{
|
input::{
|
||||||
actions::Action,
|
actions::Action,
|
||||||
command::{RunCommand, RunCommandAction, TerminalAction},
|
command::{RunCommand, RunCommandAction, TerminalAction},
|
||||||
layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation},
|
layout::{Layout, RunPluginOrAlias},
|
||||||
plugins::PluginType,
|
plugins::PluginType,
|
||||||
},
|
},
|
||||||
plugin_api::{
|
plugin_api::{
|
||||||
|
|
@ -1226,15 +1224,9 @@ fn start_or_reload_plugin(env: &ForeignFunctionEnv, url: &str) -> Result<()> {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
||||||
let url = Url::parse(&url).map_err(|e| anyhow!("Failed to parse url: {}", e))?;
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(url, &None, None, Some(cwd))
|
||||||
let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(cwd))
|
|
||||||
.map_err(|e| anyhow!("Failed to parse plugin location: {}", e))?;
|
.map_err(|e| anyhow!("Failed to parse plugin location: {}", e))?;
|
||||||
let run_plugin = RunPlugin {
|
let action = Action::StartOrReloadPlugin(run_plugin_or_alias);
|
||||||
location: run_plugin_location,
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
configuration: PluginUserConfiguration::new(BTreeMap::new()), // TODO: allow passing configuration
|
|
||||||
};
|
|
||||||
let action = Action::StartOrReloadPlugin(run_plugin);
|
|
||||||
apply_action!(action, error_msg, env);
|
apply_action!(action, error_msg, env);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ use zellij_utils::{
|
||||||
input::{
|
input::{
|
||||||
command::{RunCommand, TerminalAction},
|
command::{RunCommand, TerminalAction},
|
||||||
layout::{
|
layout::{
|
||||||
FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation,
|
FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPluginLocation,
|
||||||
TiledPaneLayout,
|
RunPluginOrAlias, TiledPaneLayout,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pane_size::Size,
|
pane_size::Size,
|
||||||
|
|
@ -62,8 +62,8 @@ pub enum PtyInstruction {
|
||||||
Option<TerminalAction>,
|
Option<TerminalAction>,
|
||||||
Option<TiledPaneLayout>,
|
Option<TiledPaneLayout>,
|
||||||
Vec<FloatingPaneLayout>,
|
Vec<FloatingPaneLayout>,
|
||||||
usize, // tab_index
|
usize, // tab_index
|
||||||
HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>, // plugin_ids
|
HashMap<RunPluginOrAlias, Vec<u32>>, // plugin_ids
|
||||||
ClientId,
|
ClientId,
|
||||||
), // the String is the tab name
|
), // the String is the tab name
|
||||||
ClosePane(PaneId),
|
ClosePane(PaneId),
|
||||||
|
|
@ -85,7 +85,7 @@ pub enum PtyInstruction {
|
||||||
Option<bool>, // should float
|
Option<bool>, // should float
|
||||||
bool, // should be opened in place
|
bool, // should be opened in place
|
||||||
Option<String>, // pane title
|
Option<String>, // pane title
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
usize, // tab index
|
usize, // tab index
|
||||||
Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
||||||
ClientId,
|
ClientId,
|
||||||
|
|
@ -874,7 +874,7 @@ impl Pty {
|
||||||
layout: TiledPaneLayout,
|
layout: TiledPaneLayout,
|
||||||
floating_panes_layout: Vec<FloatingPaneLayout>,
|
floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
default_shell: Option<TerminalAction>,
|
default_shell: Option<TerminalAction>,
|
||||||
plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
tab_index: usize,
|
tab_index: usize,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
@ -1337,7 +1337,7 @@ impl Pty {
|
||||||
should_float: Option<bool>,
|
should_float: Option<bool>,
|
||||||
should_open_in_place: bool, // should be opened in place
|
should_open_in_place: bool, // should be opened in place
|
||||||
pane_title: Option<String>, // pane title
|
pane_title: Option<String>, // pane title
|
||||||
run: RunPlugin,
|
run: RunPluginOrAlias,
|
||||||
tab_index: usize, // tab index
|
tab_index: usize, // tab index
|
||||||
pane_id_to_replace: Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
pane_id_to_replace: Option<PaneId>, // pane id to replace if this is to be opened "in-place"
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
|
|
||||||
|
|
@ -1023,15 +1023,15 @@ pub(crate) fn route_thread_main(
|
||||||
cli_args,
|
cli_args,
|
||||||
opts,
|
opts,
|
||||||
layout,
|
layout,
|
||||||
plugin_config,
|
plugin_aliases,
|
||||||
) => {
|
) => {
|
||||||
let new_client_instruction = ServerInstruction::NewClient(
|
let new_client_instruction = ServerInstruction::NewClient(
|
||||||
client_attributes,
|
client_attributes,
|
||||||
cli_args,
|
cli_args,
|
||||||
opts,
|
opts,
|
||||||
layout,
|
layout,
|
||||||
|
plugin_aliases,
|
||||||
client_id,
|
client_id,
|
||||||
plugin_config,
|
|
||||||
);
|
);
|
||||||
to_server
|
to_server
|
||||||
.send(new_client_instruction)
|
.send(new_client_instruction)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use zellij_utils::{
|
||||||
envs::set_session_name,
|
envs::set_session_name,
|
||||||
input::command::TerminalAction,
|
input::command::TerminalAction,
|
||||||
input::layout::{
|
input::layout::{
|
||||||
FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation,
|
FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||||
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
},
|
},
|
||||||
position::Position,
|
position::Position,
|
||||||
|
|
@ -220,7 +220,7 @@ pub enum ScreenInstruction {
|
||||||
Vec<FloatingPaneLayout>,
|
Vec<FloatingPaneLayout>,
|
||||||
Vec<(u32, HoldForCommand)>, // new pane pids
|
Vec<(u32, HoldForCommand)>, // new pane pids
|
||||||
Vec<(u32, HoldForCommand)>, // new floating pane pids
|
Vec<(u32, HoldForCommand)>, // new floating pane pids
|
||||||
HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
usize, // tab_index
|
usize, // tab_index
|
||||||
ClientId,
|
ClientId,
|
||||||
),
|
),
|
||||||
|
|
@ -279,10 +279,16 @@ pub enum ScreenInstruction {
|
||||||
PreviousSwapLayout(ClientId),
|
PreviousSwapLayout(ClientId),
|
||||||
NextSwapLayout(ClientId),
|
NextSwapLayout(ClientId),
|
||||||
QueryTabNames(ClientId),
|
QueryTabNames(ClientId),
|
||||||
NewTiledPluginPane(RunPlugin, Option<String>, bool, Option<PathBuf>, ClientId), // Option<String> is
|
NewTiledPluginPane(
|
||||||
|
RunPluginOrAlias,
|
||||||
|
Option<String>,
|
||||||
|
bool,
|
||||||
|
Option<PathBuf>,
|
||||||
|
ClientId,
|
||||||
|
), // Option<String> is
|
||||||
// optional pane title, bool is skip cache, Option<PathBuf> is an optional cwd
|
// optional pane title, bool is skip cache, Option<PathBuf> is an optional cwd
|
||||||
NewFloatingPluginPane(
|
NewFloatingPluginPane(
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
Option<String>,
|
Option<String>,
|
||||||
bool,
|
bool,
|
||||||
Option<PathBuf>,
|
Option<PathBuf>,
|
||||||
|
|
@ -291,13 +297,13 @@ pub enum ScreenInstruction {
|
||||||
), // Option<String> is an
|
), // Option<String> is an
|
||||||
// optional pane title, bool
|
// optional pane title, bool
|
||||||
// is skip cache, Option<PathBuf> is an optional cwd
|
// is skip cache, Option<PathBuf> is an optional cwd
|
||||||
NewInPlacePluginPane(RunPlugin, Option<String>, PaneId, bool, ClientId), // Option<String> is an
|
NewInPlacePluginPane(RunPluginOrAlias, Option<String>, PaneId, bool, ClientId), // Option<String> is an
|
||||||
// optional pane title, bool is skip cache
|
// optional pane title, bool is skip cache
|
||||||
StartOrReloadPluginPane(RunPlugin, Option<String>),
|
StartOrReloadPluginPane(RunPluginOrAlias, Option<String>),
|
||||||
AddPlugin(
|
AddPlugin(
|
||||||
Option<bool>, // should_float
|
Option<bool>, // should_float
|
||||||
bool, // should be opened in place
|
bool, // should be opened in place
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
Option<String>, // pane title
|
Option<String>, // pane title
|
||||||
Option<usize>, // tab index
|
Option<usize>, // tab index
|
||||||
u32, // plugin id
|
u32, // plugin id
|
||||||
|
|
@ -309,9 +315,17 @@ pub enum ScreenInstruction {
|
||||||
StartPluginLoadingIndication(u32, LoadingIndication), // u32 - plugin_id
|
StartPluginLoadingIndication(u32, LoadingIndication), // u32 - plugin_id
|
||||||
ProgressPluginLoadingOffset(u32), // u32 - plugin id
|
ProgressPluginLoadingOffset(u32), // u32 - plugin id
|
||||||
RequestStateUpdateForPlugins,
|
RequestStateUpdateForPlugins,
|
||||||
LaunchOrFocusPlugin(RunPlugin, bool, bool, bool, Option<PaneId>, bool, ClientId), // bools are: should_float, move_to_focused_tab, should_open_in_place, Option<PaneId> is the pane id to replace, bool following it is skip_cache
|
LaunchOrFocusPlugin(
|
||||||
|
RunPluginOrAlias,
|
||||||
|
bool,
|
||||||
|
bool,
|
||||||
|
bool,
|
||||||
|
Option<PaneId>,
|
||||||
|
bool,
|
||||||
|
ClientId,
|
||||||
|
), // bools are: should_float, move_to_focused_tab, should_open_in_place, Option<PaneId> is the pane id to replace, bool following it is skip_cache
|
||||||
LaunchPlugin(
|
LaunchPlugin(
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
bool,
|
bool,
|
||||||
bool,
|
bool,
|
||||||
Option<PaneId>,
|
Option<PaneId>,
|
||||||
|
|
@ -1224,7 +1238,7 @@ impl Screen {
|
||||||
floating_panes_layout: Vec<FloatingPaneLayout>,
|
floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
new_plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
tab_index: usize,
|
tab_index: usize,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
@ -1830,7 +1844,7 @@ impl Screen {
|
||||||
|
|
||||||
pub fn focus_plugin_pane(
|
pub fn focus_plugin_pane(
|
||||||
&mut self,
|
&mut self,
|
||||||
run_plugin: &RunPlugin,
|
run_plugin: &RunPluginOrAlias,
|
||||||
should_float: bool,
|
should_float: bool,
|
||||||
move_to_focused_tab: bool,
|
move_to_focused_tab: bool,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
|
@ -3452,7 +3466,7 @@ pub(crate) fn screen_thread_main(
|
||||||
ScreenInstruction::AddPlugin(
|
ScreenInstruction::AddPlugin(
|
||||||
should_float,
|
should_float,
|
||||||
should_be_in_place,
|
should_be_in_place,
|
||||||
run_plugin_location,
|
run_plugin_or_alias,
|
||||||
pane_title,
|
pane_title,
|
||||||
tab_index,
|
tab_index,
|
||||||
plugin_id,
|
plugin_id,
|
||||||
|
|
@ -3465,10 +3479,10 @@ pub(crate) fn screen_thread_main(
|
||||||
"({}) - {}",
|
"({}) - {}",
|
||||||
cwd.map(|cwd| cwd.display().to_string())
|
cwd.map(|cwd| cwd.display().to_string())
|
||||||
.unwrap_or(".".to_owned()),
|
.unwrap_or(".".to_owned()),
|
||||||
run_plugin_location.location
|
run_plugin_or_alias.location_string()
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let run_plugin = Run::Plugin(run_plugin_location);
|
let run_plugin = Run::Plugin(run_plugin_or_alias);
|
||||||
|
|
||||||
if should_be_in_place {
|
if should_be_in_place {
|
||||||
if let Some(pane_id_to_replace) = pane_id_to_replace {
|
if let Some(pane_id_to_replace) = pane_id_to_replace {
|
||||||
|
|
@ -3571,33 +3585,35 @@ pub(crate) fn screen_thread_main(
|
||||||
skip_cache,
|
skip_cache,
|
||||||
client_id,
|
client_id,
|
||||||
) => match pane_id_to_replace {
|
) => match pane_id_to_replace {
|
||||||
Some(pane_id_to_replace) => match screen.active_tab_indices.values().next() {
|
Some(pane_id_to_replace) if should_open_in_place => {
|
||||||
Some(tab_index) => {
|
match screen.active_tab_indices.values().next() {
|
||||||
let size = Size::default();
|
Some(tab_index) => {
|
||||||
screen
|
let size = Size::default();
|
||||||
.bus
|
screen
|
||||||
.senders
|
.bus
|
||||||
.send_to_pty(PtyInstruction::FillPluginCwd(
|
.senders
|
||||||
Some(should_float),
|
.send_to_pty(PtyInstruction::FillPluginCwd(
|
||||||
should_open_in_place,
|
Some(should_float),
|
||||||
None,
|
should_open_in_place,
|
||||||
run_plugin,
|
None,
|
||||||
*tab_index,
|
run_plugin,
|
||||||
Some(pane_id_to_replace),
|
*tab_index,
|
||||||
client_id,
|
Some(pane_id_to_replace),
|
||||||
size,
|
client_id,
|
||||||
skip_cache,
|
size,
|
||||||
None,
|
skip_cache,
|
||||||
None,
|
None,
|
||||||
))?;
|
None,
|
||||||
},
|
))?;
|
||||||
None => {
|
},
|
||||||
log::error!(
|
None => {
|
||||||
|
log::error!(
|
||||||
"Could not find an active tab - is there at least 1 connected user?"
|
"Could not find an active tab - is there at least 1 connected user?"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
None => {
|
_ => {
|
||||||
let client_id = if screen.active_tab_indices.contains_key(&client_id) {
|
let client_id = if screen.active_tab_indices.contains_key(&client_id) {
|
||||||
Some(client_id)
|
Some(client_id)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use zellij_utils::common_path::common_path_all;
|
||||||
use zellij_utils::pane_size::PaneGeom;
|
use zellij_utils::pane_size::PaneGeom;
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
input::command::RunCommand,
|
input::command::RunCommand,
|
||||||
input::layout::{Layout, Run, RunPlugin},
|
input::layout::{Layout, Run, RunPlugin, RunPluginOrAlias},
|
||||||
session_serialization::{GlobalLayoutManifest, PaneLayoutManifest, TabLayoutManifest},
|
session_serialization::{GlobalLayoutManifest, PaneLayoutManifest, TabLayoutManifest},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -178,7 +178,8 @@ impl SessionLayoutMetadata {
|
||||||
let mut update_cmd_in_pane_metadata = |pane_layout_metadata: &mut PaneLayoutMetadata| {
|
let mut update_cmd_in_pane_metadata = |pane_layout_metadata: &mut PaneLayoutMetadata| {
|
||||||
if let PaneId::Plugin(id) = pane_layout_metadata.id {
|
if let PaneId::Plugin(id) = pane_layout_metadata.id {
|
||||||
if let Some(run_plugin) = plugin_ids_to_run_plugins.remove(&id) {
|
if let Some(run_plugin) = plugin_ids_to_run_plugins.remove(&id) {
|
||||||
pane_layout_metadata.run = Some(Run::Plugin(run_plugin));
|
pane_layout_metadata.run =
|
||||||
|
Some(Run::Plugin(RunPluginOrAlias::RunPlugin(run_plugin)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
data::{Palette, Style},
|
data::{Palette, Style},
|
||||||
input::layout::{
|
input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias, TiledPaneLayout},
|
||||||
FloatingPaneLayout, PluginUserConfiguration, Run, RunPluginLocation, TiledPaneLayout,
|
|
||||||
},
|
|
||||||
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -104,7 +102,7 @@ impl<'a> LayoutApplier<'a> {
|
||||||
floating_panes_layout: Vec<FloatingPaneLayout>,
|
floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
mut new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
mut new_plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
// true => should_show_floating_panes
|
// true => should_show_floating_panes
|
||||||
|
|
@ -208,7 +206,7 @@ impl<'a> LayoutApplier<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: TiledPaneLayout,
|
layout: TiledPaneLayout,
|
||||||
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_plugin_ids: &mut HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
new_plugin_ids: &mut HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let err_context = || format!("failed to apply tiled panes layout");
|
let err_context = || format!("failed to apply tiled panes layout");
|
||||||
|
|
@ -263,9 +261,9 @@ impl<'a> LayoutApplier<'a> {
|
||||||
let positions_and_size = positions_in_layout.iter();
|
let positions_and_size = positions_in_layout.iter();
|
||||||
for (layout, position_and_size) in positions_and_size {
|
for (layout, position_and_size) in positions_and_size {
|
||||||
if let Some(Run::Plugin(run)) = layout.run.clone() {
|
if let Some(Run::Plugin(run)) = layout.run.clone() {
|
||||||
let pane_title = run.location.to_string();
|
let pane_title = run.location_string();
|
||||||
let pid = new_plugin_ids
|
let pid = new_plugin_ids
|
||||||
.get_mut(&(run.location, run.configuration))
|
.get_mut(&run)
|
||||||
.and_then(|ids| ids.pop())
|
.and_then(|ids| ids.pop())
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let mut new_plugin = PluginPane::new(
|
let mut new_plugin = PluginPane::new(
|
||||||
|
|
@ -372,7 +370,7 @@ impl<'a> LayoutApplier<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
floating_panes_layout: Vec<FloatingPaneLayout>,
|
floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_plugin_ids: &mut HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
new_plugin_ids: &mut HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
layout_name: Option<String>,
|
layout_name: Option<String>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
// true => has floating panes
|
// true => has floating panes
|
||||||
|
|
@ -392,9 +390,9 @@ impl<'a> LayoutApplier<'a> {
|
||||||
position_and_size,
|
position_and_size,
|
||||||
);
|
);
|
||||||
} else if let Some(Run::Plugin(run)) = floating_pane_layout.run.clone() {
|
} else if let Some(Run::Plugin(run)) = floating_pane_layout.run.clone() {
|
||||||
let pane_title = run.location.to_string();
|
let pane_title = run.location_string();
|
||||||
let pid = new_plugin_ids
|
let pid = new_plugin_ids
|
||||||
.get_mut(&(run.location, run.configuration))
|
.get_mut(&run)
|
||||||
.and_then(|ids| ids.pop())
|
.and_then(|ids| ids.pop())
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let mut new_pane = PluginPane::new(
|
let mut new_pane = PluginPane::new(
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ use zellij_utils::{
|
||||||
command::TerminalAction,
|
command::TerminalAction,
|
||||||
layout::{
|
layout::{
|
||||||
FloatingPaneLayout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation,
|
FloatingPaneLayout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation,
|
||||||
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
RunPluginOrAlias, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
},
|
},
|
||||||
parse_keys,
|
parse_keys,
|
||||||
},
|
},
|
||||||
|
|
@ -636,7 +636,7 @@ impl Tab {
|
||||||
floating_panes_layout: Vec<FloatingPaneLayout>,
|
floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||||
new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
new_plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.swap_layouts
|
self.swap_layouts
|
||||||
|
|
@ -3587,15 +3587,16 @@ impl Tab {
|
||||||
self.set_force_render();
|
self.set_force_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_plugin(&self, run_plugin: &RunPlugin) -> Option<PaneId> {
|
pub fn find_plugin(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option<PaneId> {
|
||||||
self.tiled_panes
|
self.tiled_panes
|
||||||
.get_plugin_pane_id(run_plugin)
|
.get_plugin_pane_id(run_plugin_or_alias)
|
||||||
.or_else(|| self.floating_panes.get_plugin_pane_id(run_plugin))
|
.or_else(|| self.floating_panes.get_plugin_pane_id(run_plugin_or_alias))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
let run = Some(Run::Plugin(run_plugin.clone()));
|
|
||||||
self.suppressed_panes
|
self.suppressed_panes
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_id, s_p)| s_p.1.invoked_with() == &run)
|
.find(|(_id, (_, pane))| {
|
||||||
|
run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with())
|
||||||
|
})
|
||||||
.map(|(id, _)| *id)
|
.map(|(id, _)| *id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -3769,7 +3770,7 @@ pub fn pane_info_for_pane(pane_id: &PaneId, pane: &Box<dyn Pane>) -> PaneInfo {
|
||||||
pane_info.id = *plugin_id;
|
pane_info.id = *plugin_id;
|
||||||
pane_info.is_plugin = true;
|
pane_info.is_plugin = true;
|
||||||
pane_info.plugin_url = pane.invoked_with().as_ref().and_then(|c| match c {
|
pane_info.plugin_url = pane.invoked_with().as_ref().and_then(|c| match c {
|
||||||
Run::Plugin(run_plugin) => Some(run_plugin.location.to_string()),
|
Run::Plugin(run_plugin_or_alias) => Some(run_plugin_or_alias.location_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 6071
|
assertion_line: 6089
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ tab-bar ────────────────────────────────────────┌ status-bar ──────────────────────────────────────────────┐──────────┐
|
00 (C): ┌ zellij:tab-bar ─────────────────────────────────┌ zellij:status-bar ───────────────────────────────────────┐──────────┐
|
||||||
01 (C): │I am a tab bar │I am a │ │
|
01 (C): │I am a tab bar │I am a │ │
|
||||||
02 (C): │ │status bar │ │
|
02 (C): │ │status bar │ │
|
||||||
03 (C): │ │ │ │
|
03 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 5971
|
assertion_line: 5995
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ status-bar ──────────────────────────────────────────────┐─────────────────────────────────────────────────┐──────────┐
|
00 (C): ┌ zellij:status-bar ───────────────────────────────────────┐ab-bar ──────────────────────────────────────────┐──────────┐
|
||||||
01 (C): │I am a │b bar │ │
|
01 (C): │I am a │b bar │ │
|
||||||
02 (C): │status bar │ │ │
|
02 (C): │status bar │ │ │
|
||||||
03 (C): │ │ │ │
|
03 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 5541
|
assertion_line: 6180
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────┐────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────┐────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -8,7 +8,7 @@ expression: snapshot
|
||||||
02 (C): │ │ │
|
02 (C): │ │ │
|
||||||
03 (C): │ │ │
|
03 (C): │ │ │
|
||||||
04 (C): │ │ │
|
04 (C): │ │ │
|
||||||
05 (C): │ ┌ status-bar ──────────────────────────────────────────────┐ │
|
05 (C): │ ┌ zellij:status-bar ───────────────────────────────────────┐ │
|
||||||
06 (C): │ │I am a │ │
|
06 (C): │ │I am a │ │
|
||||||
07 (C): │ │status bar │─┐ │
|
07 (C): │ │status bar │─┐ │
|
||||||
08 (C): │ │ │ │ │
|
08 (C): │ │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 6269
|
assertion_line: 6275
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
01 (C): │ │
|
01 (C): │ │
|
||||||
02 (C): │ ┌ command2 ────────────── SCROLL: 0/1 ┐ │
|
02 (C): │ ┌ command2 ────────────── SCROLL: 0/1 ┐ │
|
||||||
03 (C): │ │ Waiting to run: command2 │ │
|
03 (C): │ │ Waiting to run: command2 │ │
|
||||||
04 (C): │ │ ┌ tab-bar ─────────────────────────────┐ │
|
04 (C): │ │ ┌ zellij:tab-bar ──────────────────────┐ │
|
||||||
05 (C): │ │<│I am a tab bar ┌ status-bar ──────────────────────────────────────────────┐ │
|
05 (C): │ │<│I am a tab bar ┌ zellij:status-bar ───────────────────────────────────────┐ │
|
||||||
06 (C): │ │l│ │I am a │ │
|
06 (C): │ │l│ │I am a │ │
|
||||||
07 (C): │ └─│ │status bar │─┐ │
|
07 (C): │ └─│ │status bar │─┐ │
|
||||||
08 (C): │ │ │ │ │ │
|
08 (C): │ │ │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 6363
|
assertion_line: 6432
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -8,11 +8,11 @@ expression: snapshot
|
||||||
02 (C): │ │
|
02 (C): │ │
|
||||||
03 (C): │ │
|
03 (C): │ │
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ ┌ tab-bar ─────────────────────────────────────────────────┐ │
|
05 (C): │ ┌ zellij:tab-bar ──────────────────────────────────────────┐ │
|
||||||
06 (C): │ │I am a tab bar │ │
|
06 (C): │ │I am a tab bar │ │
|
||||||
07 (C): │ │ ┌ Pane #2 ─────────────────────────────────────────────────┐ │
|
07 (C): │ │ ┌ Pane #2 ─────────────────────────────────────────────────┐ │
|
||||||
08 (C): │ │ │ │ │
|
08 (C): │ │ │ │ │
|
||||||
09 (C): │ │ │ ┌ status-bar ──────────────────────────────────────────────┐ │
|
09 (C): │ │ │ ┌ zellij:status-bar ───────────────────────────────────────┐ │
|
||||||
10 (C): │ │ │ │I am a │ │
|
10 (C): │ │ │ │I am a │ │
|
||||||
11 (C): │ │ │ │status bar │ │
|
11 (C): │ │ │ │status bar │ │
|
||||||
12 (C): │ │ │ │ │ │
|
12 (C): │ │ │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||||
assertion_line: 5481
|
assertion_line: 5510
|
||||||
expression: snapshot
|
expression: snapshot
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -17,10 +17,10 @@ expression: snapshot
|
||||||
11 (C): │ │
|
11 (C): │ │
|
||||||
12 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
|
12 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
|
||||||
13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
14 (C): ┌ status-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
14 (C): ┌ zellij:status-bar ────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
15 (C): │I am a │
|
15 (C): │I am a │
|
||||||
16 (C): │status bar │
|
16 (C): │status bar │
|
||||||
17 (C): │ │
|
17 (C): │ │
|
||||||
18 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
18 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
19 (C): ┌ tab-bar ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
19 (C): ┌ zellij:tab-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ use zellij_utils::data::ResizeStrategy;
|
||||||
use zellij_utils::envs::set_session_name;
|
use zellij_utils::envs::set_session_name;
|
||||||
use zellij_utils::errors::{prelude::*, ErrorContext};
|
use zellij_utils::errors::{prelude::*, ErrorContext};
|
||||||
use zellij_utils::input::layout::{
|
use zellij_utils::input::layout::{
|
||||||
FloatingPaneLayout, Layout, PluginUserConfiguration, RunPluginLocation, SwapFloatingLayout,
|
FloatingPaneLayout, Layout, PluginUserConfiguration, RunPluginLocation, RunPluginOrAlias,
|
||||||
SwapTiledLayout, TiledPaneLayout,
|
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
};
|
};
|
||||||
use zellij_utils::input::plugins::PluginTag;
|
use zellij_utils::input::plugins::PluginTag;
|
||||||
use zellij_utils::ipc::IpcReceiverWithContext;
|
use zellij_utils::ipc::IpcReceiverWithContext;
|
||||||
|
|
@ -273,7 +273,7 @@ fn create_new_tab_with_swap_layouts(
|
||||||
Vec<FloatingPaneLayout>,
|
Vec<FloatingPaneLayout>,
|
||||||
Vec<(u32, Option<RunCommand>)>,
|
Vec<(u32, Option<RunCommand>)>,
|
||||||
Vec<(u32, Option<RunCommand>)>,
|
Vec<(u32, Option<RunCommand>)>,
|
||||||
HashMap<(RunPluginLocation, PluginUserConfiguration), Vec<u32>>,
|
HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||||
)>,
|
)>,
|
||||||
draw_pane_frames: bool,
|
draw_pane_frames: bool,
|
||||||
) -> Tab {
|
) -> Tab {
|
||||||
|
|
@ -5022,17 +5022,11 @@ fn layout_with_plugins_and_commands_swaped_properly() {
|
||||||
let new_floating_terminal_ids = vec![];
|
let new_floating_terminal_ids = vec![];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -5123,17 +5117,11 @@ fn base_layout_is_included_in_swap_layouts() {
|
||||||
let new_floating_terminal_ids = vec![];
|
let new_floating_terminal_ids = vec![];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -5221,17 +5209,11 @@ fn swap_layouts_including_command_panes_absent_from_existing_layout() {
|
||||||
let new_floating_terminal_ids = vec![];
|
let new_floating_terminal_ids = vec![];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -5322,17 +5304,11 @@ fn swap_layouts_not_including_command_panes_present_in_existing_layout() {
|
||||||
let new_floating_terminal_ids = vec![];
|
let new_floating_terminal_ids = vec![];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -5496,17 +5472,11 @@ fn swap_layouts_not_including_plugin_panes_present_in_existing_layout() {
|
||||||
let new_floating_terminal_ids = vec![];
|
let new_floating_terminal_ids = vec![];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -5987,17 +5957,11 @@ fn floating_layout_with_plugins_and_commands_swaped_properly() {
|
||||||
let new_terminal_ids = vec![(4, None)];
|
let new_terminal_ids = vec![(4, None)];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -6086,17 +6050,11 @@ fn base_floating_layout_is_included_in_swap_layouts() {
|
||||||
let new_terminal_ids = vec![(4, None)];
|
let new_terminal_ids = vec![(4, None)];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -6184,17 +6142,11 @@ fn swap_floating_layouts_including_command_panes_absent_from_existing_layout() {
|
||||||
let new_terminal_ids = vec![(4, None)];
|
let new_terminal_ids = vec![(4, None)];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -6285,17 +6237,11 @@ fn swap_floating_layouts_not_including_command_panes_present_in_existing_layout(
|
||||||
let new_terminal_ids = vec![(4, None)];
|
let new_terminal_ids = vec![(4, None)];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -6448,17 +6394,11 @@ fn swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout()
|
||||||
let new_terminal_ids = vec![(4, None)];
|
let new_terminal_ids = vec![(4, None)];
|
||||||
let mut new_plugin_ids = HashMap::new();
|
let mut new_plugin_ids = HashMap::new();
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
new_plugin_ids.insert(
|
new_plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
vec![2],
|
vec![2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ use zellij_utils::errors::{prelude::*, ErrorContext};
|
||||||
use zellij_utils::input::actions::Action;
|
use zellij_utils::input::actions::Action;
|
||||||
use zellij_utils::input::command::{RunCommand, TerminalAction};
|
use zellij_utils::input::command::{RunCommand, TerminalAction};
|
||||||
use zellij_utils::input::layout::{
|
use zellij_utils::input::layout::{
|
||||||
FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, SplitDirection, SplitSize,
|
FloatingPaneLayout, Layout, PluginAlias, PluginUserConfiguration, Run, RunPlugin,
|
||||||
TiledPaneLayout,
|
RunPluginLocation, RunPluginOrAlias, SplitDirection, SplitSize, TiledPaneLayout,
|
||||||
};
|
};
|
||||||
use zellij_utils::input::options::Options;
|
use zellij_utils::input::options::Options;
|
||||||
use zellij_utils::ipc::IpcReceiverWithContext;
|
use zellij_utils::ipc::IpcReceiverWithContext;
|
||||||
|
|
@ -338,10 +338,91 @@ impl MockScreen {
|
||||||
let mut floating_pane_ids = vec![];
|
let mut floating_pane_ids = vec![];
|
||||||
let mut plugin_ids = HashMap::new();
|
let mut plugin_ids = HashMap::new();
|
||||||
plugin_ids.insert(
|
plugin_ids.insert(
|
||||||
(
|
RunPluginOrAlias::from_url("file:/path/to/fake/plugin", &None, None, None).unwrap(),
|
||||||
RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
vec![1],
|
||||||
Default::default(),
|
);
|
||||||
),
|
for i in 0..pane_count {
|
||||||
|
pane_ids.push((i as u32, None));
|
||||||
|
}
|
||||||
|
for i in 0..floating_pane_count {
|
||||||
|
floating_pane_ids.push((i as u32, None));
|
||||||
|
}
|
||||||
|
let default_shell = None;
|
||||||
|
let tab_name = None;
|
||||||
|
let tab_index = self.last_opened_tab_index.map(|l| l + 1).unwrap_or(0);
|
||||||
|
let _ = self.to_screen.send(ScreenInstruction::NewTab(
|
||||||
|
None,
|
||||||
|
default_shell,
|
||||||
|
Some(pane_layout.clone()),
|
||||||
|
initial_floating_panes_layout.clone(),
|
||||||
|
tab_name,
|
||||||
|
(vec![], vec![]), // swap layouts
|
||||||
|
self.main_client_id,
|
||||||
|
));
|
||||||
|
let _ = self.to_screen.send(ScreenInstruction::ApplyLayout(
|
||||||
|
pane_layout,
|
||||||
|
initial_floating_panes_layout,
|
||||||
|
pane_ids,
|
||||||
|
floating_pane_ids,
|
||||||
|
plugin_ids,
|
||||||
|
tab_index,
|
||||||
|
self.main_client_id,
|
||||||
|
));
|
||||||
|
self.last_opened_tab_index = Some(tab_index);
|
||||||
|
screen_thread
|
||||||
|
}
|
||||||
|
// same as the above function, but starts a plugin with a plugin alias
|
||||||
|
pub fn run_with_alias(
|
||||||
|
&mut self,
|
||||||
|
initial_layout: Option<TiledPaneLayout>,
|
||||||
|
initial_floating_panes_layout: Vec<FloatingPaneLayout>,
|
||||||
|
) -> std::thread::JoinHandle<()> {
|
||||||
|
let config_options = self.config_options.clone();
|
||||||
|
let client_attributes = self.client_attributes.clone();
|
||||||
|
let screen_bus = Bus::new(
|
||||||
|
vec![self.screen_receiver.take().unwrap()],
|
||||||
|
None,
|
||||||
|
Some(&self.to_pty.clone()),
|
||||||
|
Some(&self.to_plugin.clone()),
|
||||||
|
Some(&self.to_server.clone()),
|
||||||
|
Some(&self.to_pty_writer.clone()),
|
||||||
|
Some(&self.to_background_jobs.clone()),
|
||||||
|
Some(Box::new(self.os_input.clone())),
|
||||||
|
)
|
||||||
|
.should_silently_fail();
|
||||||
|
let debug = false;
|
||||||
|
let screen_thread = std::thread::Builder::new()
|
||||||
|
.name("screen_thread".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
set_var("ZELLIJ_SESSION_NAME", "zellij-test");
|
||||||
|
screen_thread_main(
|
||||||
|
screen_bus,
|
||||||
|
None,
|
||||||
|
client_attributes,
|
||||||
|
Box::new(config_options),
|
||||||
|
debug,
|
||||||
|
Box::new(Layout::default()),
|
||||||
|
)
|
||||||
|
.expect("TEST")
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let pane_layout = initial_layout.unwrap_or_default();
|
||||||
|
let pane_count = pane_layout.extract_run_instructions().len();
|
||||||
|
let floating_pane_count = initial_floating_panes_layout.len();
|
||||||
|
let mut pane_ids = vec![];
|
||||||
|
let mut floating_pane_ids = vec![];
|
||||||
|
let mut plugin_ids = HashMap::new();
|
||||||
|
plugin_ids.insert(
|
||||||
|
RunPluginOrAlias::Alias(PluginAlias {
|
||||||
|
name: "fixture_plugin_for_tests".to_owned(),
|
||||||
|
configuration: Some(Default::default()),
|
||||||
|
run_plugin: Some(RunPlugin {
|
||||||
|
location: RunPluginLocation::parse("file:/path/to/fake/plugin", None).unwrap(),
|
||||||
|
configuration: PluginUserConfiguration::default(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
vec![1],
|
vec![1],
|
||||||
);
|
);
|
||||||
for i in 0..pane_count {
|
for i in 0..pane_count {
|
||||||
|
|
@ -358,7 +439,6 @@ impl MockScreen {
|
||||||
default_shell,
|
default_shell,
|
||||||
Some(pane_layout.clone()),
|
Some(pane_layout.clone()),
|
||||||
initial_floating_panes_layout.clone(),
|
initial_floating_panes_layout.clone(),
|
||||||
// vec![], // floating_panes_layout
|
|
||||||
tab_name,
|
tab_name,
|
||||||
(vec![], vec![]), // swap layouts
|
(vec![], vec![]), // swap layouts
|
||||||
self.main_client_id,
|
self.main_client_id,
|
||||||
|
|
@ -366,10 +446,8 @@ impl MockScreen {
|
||||||
let _ = self.to_screen.send(ScreenInstruction::ApplyLayout(
|
let _ = self.to_screen.send(ScreenInstruction::ApplyLayout(
|
||||||
pane_layout,
|
pane_layout,
|
||||||
initial_floating_panes_layout,
|
initial_floating_panes_layout,
|
||||||
// vec![], // floating panes layout
|
|
||||||
pane_ids,
|
pane_ids,
|
||||||
floating_pane_ids,
|
floating_pane_ids,
|
||||||
// vec![], // floating pane ids
|
|
||||||
plugin_ids,
|
plugin_ids,
|
||||||
tab_index,
|
tab_index,
|
||||||
self.main_client_id,
|
self.main_client_id,
|
||||||
|
|
@ -2884,7 +2962,7 @@ pub fn send_cli_launch_or_focus_plugin_action() {
|
||||||
floating: true,
|
floating: true,
|
||||||
in_place: false,
|
in_place: false,
|
||||||
move_to_focused_tab: true,
|
move_to_focused_tab: true,
|
||||||
url: url::Url::parse("file:/path/to/fake/plugin").unwrap(),
|
url: "file:/path/to/fake/plugin".to_owned(),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
skip_plugin_cache: false,
|
skip_plugin_cache: false,
|
||||||
};
|
};
|
||||||
|
|
@ -2917,11 +2995,11 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() {
|
||||||
let session_metadata = mock_screen.clone_session_metadata();
|
let session_metadata = mock_screen.clone_session_metadata();
|
||||||
let mut initial_layout = TiledPaneLayout::default();
|
let mut initial_layout = TiledPaneLayout::default();
|
||||||
let existing_plugin_pane = TiledPaneLayout {
|
let existing_plugin_pane = TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
initial_layout.children_split_direction = SplitDirection::Vertical;
|
initial_layout.children_split_direction = SplitDirection::Vertical;
|
||||||
|
|
@ -2944,7 +3022,89 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() {
|
||||||
floating: true,
|
floating: true,
|
||||||
in_place: false,
|
in_place: false,
|
||||||
move_to_focused_tab: true,
|
move_to_focused_tab: true,
|
||||||
url: url::Url::parse("file:/path/to/fake/plugin").unwrap(),
|
url: "file:/path/to/fake/plugin".to_owned(),
|
||||||
|
configuration: Default::default(),
|
||||||
|
skip_plugin_cache: false,
|
||||||
|
};
|
||||||
|
send_cli_action_to_server(&session_metadata, cli_action, client_id);
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be
|
||||||
|
mock_screen.teardown(vec![plugin_thread, server_thread, screen_thread]);
|
||||||
|
|
||||||
|
let plugin_load_instruction_sent = received_plugin_instructions
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find(|instruction| match instruction {
|
||||||
|
PluginInstruction::Load(..) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.is_some();
|
||||||
|
assert!(
|
||||||
|
!plugin_load_instruction_sent,
|
||||||
|
"Plugin Load instruction should not be sent for an already loaded plugin"
|
||||||
|
);
|
||||||
|
let snapshots = take_snapshots_and_cursor_coordinates_from_render_events(
|
||||||
|
received_server_instructions.lock().unwrap().iter(),
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
let snapshot_count = snapshots.len();
|
||||||
|
assert_eq!(
|
||||||
|
snapshot_count, 2,
|
||||||
|
"Another render was sent for focusing the already loaded plugin"
|
||||||
|
);
|
||||||
|
for (cursor_coordinates, _snapshot) in snapshots.iter().skip(1) {
|
||||||
|
assert!(
|
||||||
|
cursor_coordinates.is_none(),
|
||||||
|
"Cursor moved to existing plugin in final snapshot indicating focus changed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded_for_plugin_alias() {
|
||||||
|
let size = Size {
|
||||||
|
cols: 121,
|
||||||
|
rows: 20,
|
||||||
|
};
|
||||||
|
let client_id = 10; // fake client id should not appear in the screen's state
|
||||||
|
let mut mock_screen = MockScreen::new(size);
|
||||||
|
let plugin_receiver = mock_screen.plugin_receiver.take().unwrap();
|
||||||
|
let session_metadata = mock_screen.clone_session_metadata();
|
||||||
|
let mut initial_layout = TiledPaneLayout::default();
|
||||||
|
let existing_plugin_pane = TiledPaneLayout {
|
||||||
|
run: Some(Run::Plugin(RunPluginOrAlias::Alias(PluginAlias {
|
||||||
|
name: "fixture_plugin_for_tests".to_owned(),
|
||||||
|
configuration: Some(Default::default()),
|
||||||
|
run_plugin: Some(RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
||||||
|
configuration: Default::default(),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}))),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
initial_layout.children_split_direction = SplitDirection::Vertical;
|
||||||
|
initial_layout.children = vec![TiledPaneLayout::default(), existing_plugin_pane];
|
||||||
|
let screen_thread = mock_screen.run_with_alias(Some(initial_layout), vec![]);
|
||||||
|
let received_plugin_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let plugin_thread = log_actions_in_thread!(
|
||||||
|
received_plugin_instructions,
|
||||||
|
PluginInstruction::Exit,
|
||||||
|
plugin_receiver
|
||||||
|
);
|
||||||
|
let received_server_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let server_receiver = mock_screen.server_receiver.take().unwrap();
|
||||||
|
let server_thread = log_actions_in_thread!(
|
||||||
|
received_server_instructions,
|
||||||
|
ServerInstruction::KillSession,
|
||||||
|
server_receiver
|
||||||
|
);
|
||||||
|
let cli_action = CliAction::LaunchOrFocusPlugin {
|
||||||
|
floating: true,
|
||||||
|
in_place: false,
|
||||||
|
move_to_focused_tab: true,
|
||||||
|
url: "fixture_plugin_for_tests".to_owned(),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
skip_plugin_cache: false,
|
skip_plugin_cache: false,
|
||||||
};
|
};
|
||||||
|
|
@ -3184,11 +3344,11 @@ pub fn screen_can_break_plugin_pane_to_a_new_tab() {
|
||||||
let mut initial_layout = TiledPaneLayout::default();
|
let mut initial_layout = TiledPaneLayout::default();
|
||||||
let mut pane_to_break_free = TiledPaneLayout::default();
|
let mut pane_to_break_free = TiledPaneLayout::default();
|
||||||
pane_to_break_free.name = Some("plugin_pane_to_break_free".to_owned());
|
pane_to_break_free.name = Some("plugin_pane_to_break_free".to_owned());
|
||||||
pane_to_break_free.run = Some(Run::Plugin(RunPlugin {
|
pane_to_break_free.run = Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
}));
|
})));
|
||||||
let mut pane_to_stay = TiledPaneLayout::default();
|
let mut pane_to_stay = TiledPaneLayout::default();
|
||||||
pane_to_stay.name = Some("pane_to_stay".to_owned());
|
pane_to_stay.name = Some("pane_to_stay".to_owned());
|
||||||
initial_layout.children_split_direction = SplitDirection::Vertical;
|
initial_layout.children_split_direction = SplitDirection::Vertical;
|
||||||
|
|
@ -3254,11 +3414,11 @@ pub fn screen_can_break_floating_plugin_pane_to_a_new_tab() {
|
||||||
pane_to_break_free.name = Some("tiled_pane".to_owned());
|
pane_to_break_free.name = Some("tiled_pane".to_owned());
|
||||||
let mut floating_pane = FloatingPaneLayout::default();
|
let mut floating_pane = FloatingPaneLayout::default();
|
||||||
floating_pane.name = Some("floating_plugin_pane_to_eject".to_owned());
|
floating_pane.name = Some("floating_plugin_pane_to_eject".to_owned());
|
||||||
floating_pane.run = Some(Run::Plugin(RunPlugin {
|
floating_pane.run = Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
}));
|
})));
|
||||||
let mut floating_panes_layout = vec![floating_pane];
|
let mut floating_panes_layout = vec![floating_pane];
|
||||||
initial_layout.children_split_direction = SplitDirection::Vertical;
|
initial_layout.children_split_direction = SplitDirection::Vertical;
|
||||||
initial_layout.children = vec![pane_to_break_free];
|
initial_layout.children = vec![pane_to_break_free];
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -8,8 +8,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
02 (C): │ │
|
02 (C): │ │
|
||||||
03 (C): │ │
|
03 (C): │ │
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
06 (C): │ │Loading /path/to/fake/plugin │ │
|
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
07 (C): │ │ │ │
|
07 (C): │ │ │ │
|
||||||
08 (C): │ │ │ │
|
08 (C): │ │ │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ │
|
05 (C): │ │
|
||||||
06 (C): │ │
|
06 (C): │ │
|
||||||
07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
08 (C): │ │Loading /path/to/fake/plugin │ │
|
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
10 (C): │ │ │ │
|
10 (C): │ │ │ │
|
||||||
11 (C): │ │ │ │
|
11 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ │
|
05 (C): │ │
|
||||||
06 (C): │ │
|
06 (C): │ │
|
||||||
07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
08 (C): │ │Loading /path/to/fake/plugin │ │
|
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
10 (C): │ │ │ │
|
10 (C): │ │ │ │
|
||||||
11 (C): │ │ │ │
|
11 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ │
|
05 (C): │ │
|
||||||
06 (C): │ │
|
06 (C): │ │
|
||||||
07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
08 (C): │ │Loading /path/to/fake/plugin │ │
|
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
10 (C): │ │ │ │
|
10 (C): │ │ │ │
|
||||||
11 (C): │ │ │ │
|
11 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ │
|
05 (C): │ │
|
||||||
06 (C): │ │
|
06 (C): │ │
|
||||||
07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
08 (C): │ │Loading /path/to/fake/plugin │ │
|
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
10 (C): │ │ │ │
|
10 (C): │ │ │ │
|
||||||
11 (C): │ │ │ │
|
11 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2986
|
assertion_line: 3171
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
|
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -8,8 +8,8 @@ expression: "format!(\"{}\", snapshot)"
|
||||||
02 (C): │ │
|
02 (C): │ │
|
||||||
03 (C): │ │
|
03 (C): │ │
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
05 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │
|
05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │
|
||||||
06 (C): │ │Loading /path/to/fake/plugin │ │
|
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||||
07 (C): │ │ │ │
|
07 (C): │ │ │ │
|
||||||
08 (C): │ │ │ │
|
08 (C): │ │ │ │
|
||||||
09 (C): │ │ │ │
|
09 (C): │ │ │ │
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2914
|
assertion_line: 3097
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐
|
00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐
|
||||||
01 (C): │Loading /path/to/fake/plugin │
|
01 (C): │Loading file:/path/to/fake/plugin │
|
||||||
02 (C): │ │
|
02 (C): │ │
|
||||||
03 (C): │ │
|
03 (C): │ │
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2914
|
assertion_line: 3097
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐
|
00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐
|
||||||
01 (C): │Loading /path/to/fake/plugin │
|
01 (C): │Loading file:/path/to/fake/plugin │
|
||||||
02 (C): │ │
|
02 (C): │ │
|
||||||
03 (C): │ │
|
03 (C): │ │
|
||||||
04 (C): │ │
|
04 (C): │ │
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2914
|
assertion_line: 3097
|
||||||
expression: "format!(\"{}\", snapshot)"
|
expression: "format!(\"{}\", snapshot)"
|
||||||
---
|
---
|
||||||
00 (C): ┌ plugin_pane_to_break_free ───────────┐┌ pane_to_stay ────────────────────────┐
|
00 (C): ┌ plugin_pane_to_break_free ───────────┐┌ pane_to_stay ────────────────────────┐
|
||||||
01 (C): │Loading /path/to/fake/plugin ││ │
|
01 (C): │Loading file:/path/to/fake/plugin ││ │
|
||||||
02 (C): │ ││ │
|
02 (C): │ ││ │
|
||||||
03 (C): │ ││ │
|
03 (C): │ ││ │
|
||||||
04 (C): │ ││ │
|
04 (C): │ ││ │
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2639
|
assertion_line: 2758
|
||||||
expression: "format!(\"{:#?}\", pty_fill_plugin_cwd_instruction)"
|
expression: "format!(\"{:#?}\", pty_fill_plugin_cwd_instruction)"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -10,15 +10,17 @@ Some(
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: File(
|
_allow_exec_host_cmd: false,
|
||||||
"/path/to/fake/plugin",
|
location: File(
|
||||||
),
|
"/path/to/fake/plugin",
|
||||||
configuration: PluginUserConfiguration(
|
),
|
||||||
{},
|
configuration: PluginUserConfiguration(
|
||||||
),
|
{},
|
||||||
},
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
1,
|
1,
|
||||||
|
|
|
||||||
|
|
@ -186,11 +186,15 @@ keybinds {
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
tab-bar { path "tab-bar"; }
|
tab-bar location="zellij:tab-bar"
|
||||||
status-bar { path "status-bar"; }
|
status-bar location="zellij:status-bar"
|
||||||
strider { path "strider"; }
|
strider location="zellij:strider"
|
||||||
compact-bar { path "compact-bar"; }
|
compact-bar location="zellij:compact-bar"
|
||||||
session-manager { path "session-manager"; }
|
session-manager location="zellij:session-manager"
|
||||||
|
welcome-screen location="zellij:session-manager" {
|
||||||
|
welcome_screen true
|
||||||
|
}
|
||||||
|
filepicker location="zellij:strider"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose what to do when zellij receives SIGTERM, SIGINT, SIGQUIT or SIGHUP
|
// Choose what to do when zellij receives SIGTERM, SIGINT, SIGQUIT or SIGHUP
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
layout {
|
layout {
|
||||||
pane
|
pane
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:compact-bar"
|
plugin location="compact-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
tab_template name="ui" {
|
tab_template name="ui" {
|
||||||
children
|
children
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:compact-bar"
|
plugin location="compact-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
layout {
|
layout {
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:tab-bar"
|
plugin location="tab-bar"
|
||||||
}
|
}
|
||||||
pane
|
pane
|
||||||
pane size=2 borderless=true {
|
pane size=2 borderless=true {
|
||||||
plugin location="zellij:status-bar"
|
plugin location="status-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
tab_template name="ui" {
|
tab_template name="ui" {
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:tab-bar"
|
plugin location="tab-bar"
|
||||||
}
|
}
|
||||||
children
|
children
|
||||||
pane size=2 borderless=true {
|
pane size=2 borderless=true {
|
||||||
plugin location="zellij:status-bar"
|
plugin location="status-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
layout {
|
layout {
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:tab-bar"
|
plugin location="tab-bar"
|
||||||
}
|
}
|
||||||
pane
|
pane
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
layout {
|
layout {
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:tab-bar"
|
plugin location="tab-bar"
|
||||||
}
|
}
|
||||||
pane split_direction="Vertical" {
|
pane split_direction="Vertical" {
|
||||||
pane size="20%" {
|
pane size="20%" {
|
||||||
plugin location="zellij:strider"
|
plugin location="strider"
|
||||||
}
|
}
|
||||||
pane
|
pane
|
||||||
}
|
}
|
||||||
pane size=2 borderless=true {
|
pane size=2 borderless=true {
|
||||||
plugin location="zellij:status-bar"
|
plugin location="status-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
tab_template name="ui" {
|
tab_template name="ui" {
|
||||||
pane size=1 borderless=true {
|
pane size=1 borderless=true {
|
||||||
plugin location="zellij:tab-bar"
|
plugin location="tab-bar"
|
||||||
}
|
}
|
||||||
pane split_direction="Vertical" {
|
pane split_direction="Vertical" {
|
||||||
pane size="20%" {
|
pane size="20%" {
|
||||||
plugin location="zellij:strider"
|
plugin location="strider"
|
||||||
}
|
}
|
||||||
pane {
|
pane {
|
||||||
children
|
children
|
||||||
|
|
@ -12,7 +12,7 @@ tab_template name="ui" {
|
||||||
|
|
||||||
}
|
}
|
||||||
pane size=2 borderless=true {
|
pane size=2 borderless=true {
|
||||||
plugin location="zellij:status-bar"
|
plugin location="status-bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
layout {
|
layout {
|
||||||
pane borderless=true {
|
pane borderless=true {
|
||||||
plugin location="zellij:session-manager" {
|
plugin location="welcome-screen"
|
||||||
welcome_screen true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
session_serialization false // this will apply only to the initial welcome screen layout, and is intended to prevent lots of garbage sessions left around
|
session_serialization false // this will apply only to the initial welcome screen layout, and is intended to prevent lots of garbage sessions left around
|
||||||
|
|
|
||||||
|
|
@ -627,7 +627,7 @@ pub enum CliAction {
|
||||||
in_place: bool,
|
in_place: bool,
|
||||||
#[clap(short, long, value_parser)]
|
#[clap(short, long, value_parser)]
|
||||||
move_to_focused_tab: bool,
|
move_to_focused_tab: bool,
|
||||||
url: Url,
|
url: String,
|
||||||
#[clap(short, long, value_parser)]
|
#[clap(short, long, value_parser)]
|
||||||
configuration: Option<PluginUserConfiguration>,
|
configuration: Option<PluginUserConfiguration>,
|
||||||
#[clap(short, long, value_parser)]
|
#[clap(short, long, value_parser)]
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use super::command::RunCommandAction;
|
use super::command::RunCommandAction;
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
FloatingPaneLayout, Layout, RunPlugin, RunPluginLocation, SwapFloatingLayout, SwapTiledLayout,
|
FloatingPaneLayout, Layout, PluginAlias, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||||
TiledPaneLayout,
|
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
};
|
};
|
||||||
use crate::cli::CliAction;
|
use crate::cli::CliAction;
|
||||||
use crate::data::{Direction, Resize};
|
use crate::data::{Direction, Resize};
|
||||||
|
|
@ -217,9 +217,9 @@ pub enum Action {
|
||||||
LeftClick(Position),
|
LeftClick(Position),
|
||||||
RightClick(Position),
|
RightClick(Position),
|
||||||
MiddleClick(Position),
|
MiddleClick(Position),
|
||||||
LaunchOrFocusPlugin(RunPlugin, bool, bool, bool, bool), // bools => should float,
|
LaunchOrFocusPlugin(RunPluginOrAlias, bool, bool, bool, bool), // bools => should float,
|
||||||
// move_to_focused_tab, should_open_in_place, skip_cache
|
// move_to_focused_tab, should_open_in_place, skip_cache
|
||||||
LaunchPlugin(RunPlugin, bool, bool, bool, Option<PathBuf>), // bools => should float,
|
LaunchPlugin(RunPluginOrAlias, bool, bool, bool, Option<PathBuf>), // bools => should float,
|
||||||
// should_open_in_place, skip_cache, Option<PathBuf> is cwd
|
// should_open_in_place, skip_cache, Option<PathBuf> is cwd
|
||||||
LeftMouseRelease(Position),
|
LeftMouseRelease(Position),
|
||||||
RightMouseRelease(Position),
|
RightMouseRelease(Position),
|
||||||
|
|
@ -246,19 +246,19 @@ pub enum Action {
|
||||||
/// Query all tab names
|
/// Query all tab names
|
||||||
QueryTabNames,
|
QueryTabNames,
|
||||||
/// Open a new tiled (embedded, non-floating) plugin pane
|
/// Open a new tiled (embedded, non-floating) plugin pane
|
||||||
NewTiledPluginPane(RunPlugin, Option<String>, bool, Option<PathBuf>), // String is an optional name, bool is
|
NewTiledPluginPane(RunPluginOrAlias, Option<String>, bool, Option<PathBuf>), // String is an optional name, bool is
|
||||||
// skip_cache, Option<PathBuf> is cwd
|
// skip_cache, Option<PathBuf> is cwd
|
||||||
NewFloatingPluginPane(
|
NewFloatingPluginPane(
|
||||||
RunPlugin,
|
RunPluginOrAlias,
|
||||||
Option<String>,
|
Option<String>,
|
||||||
bool,
|
bool,
|
||||||
Option<PathBuf>,
|
Option<PathBuf>,
|
||||||
Option<FloatingPaneCoordinates>,
|
Option<FloatingPaneCoordinates>,
|
||||||
), // String is an optional name, bool is
|
), // String is an optional name, bool is
|
||||||
// skip_cache, Option<PathBuf> is cwd
|
// skip_cache, Option<PathBuf> is cwd
|
||||||
NewInPlacePluginPane(RunPlugin, Option<String>, bool), // String is an optional name, bool is
|
NewInPlacePluginPane(RunPluginOrAlias, Option<String>, bool), // String is an optional name, bool is
|
||||||
// skip_cache
|
// skip_cache
|
||||||
StartOrReloadPlugin(RunPlugin),
|
StartOrReloadPlugin(RunPluginOrAlias),
|
||||||
CloseTerminalPane(u32),
|
CloseTerminalPane(u32),
|
||||||
ClosePluginPane(u32),
|
ClosePluginPane(u32),
|
||||||
FocusTerminalPaneWithId(u32, bool), // bool is should_float_if_hidden
|
FocusTerminalPaneWithId(u32, bool), // bool is should_float_if_hidden
|
||||||
|
|
@ -351,14 +351,20 @@ impl Action {
|
||||||
let cwd = cwd
|
let cwd = cwd
|
||||||
.map(|cwd| current_dir.join(cwd))
|
.map(|cwd| current_dir.join(cwd))
|
||||||
.or_else(|| Some(current_dir));
|
.or_else(|| Some(current_dir));
|
||||||
let user_configuration = configuration.unwrap_or_default();
|
|
||||||
if let Some(plugin) = plugin {
|
if let Some(plugin) = plugin {
|
||||||
let location = RunPluginLocation::parse(&plugin, cwd.clone())
|
let plugin = match RunPluginLocation::parse(&plugin, cwd.clone()) {
|
||||||
.map_err(|e| format!("Failed to parse plugin loction {plugin}: {}", e))?;
|
Ok(location) => {
|
||||||
let plugin = RunPlugin {
|
let user_configuration = configuration.unwrap_or_default();
|
||||||
_allow_exec_host_cmd: false,
|
RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: user_configuration,
|
location,
|
||||||
|
configuration: user_configuration,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Err(_) => RunPluginOrAlias::Alias(PluginAlias::new(
|
||||||
|
&plugin,
|
||||||
|
&configuration.map(|c| c.inner().clone()),
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
if floating {
|
if floating {
|
||||||
Ok(vec![Action::NewFloatingPluginPane(
|
Ok(vec![Action::NewFloatingPluginPane(
|
||||||
|
|
@ -571,14 +577,13 @@ impl Action {
|
||||||
CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]),
|
CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]),
|
||||||
CliAction::StartOrReloadPlugin { url, configuration } => {
|
CliAction::StartOrReloadPlugin { url, configuration } => {
|
||||||
let current_dir = get_current_dir();
|
let current_dir = get_current_dir();
|
||||||
let run_plugin_location = RunPluginLocation::parse(&url, Some(current_dir))
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
|
&url,
|
||||||
let run_plugin = RunPlugin {
|
&configuration.map(|c| c.inner().clone()),
|
||||||
location: run_plugin_location,
|
None,
|
||||||
_allow_exec_host_cmd: false,
|
Some(current_dir),
|
||||||
configuration: configuration.unwrap_or_default(),
|
)?;
|
||||||
};
|
Ok(vec![Action::StartOrReloadPlugin(run_plugin_or_alias)])
|
||||||
Ok(vec![Action::StartOrReloadPlugin(run_plugin)])
|
|
||||||
},
|
},
|
||||||
CliAction::LaunchOrFocusPlugin {
|
CliAction::LaunchOrFocusPlugin {
|
||||||
url,
|
url,
|
||||||
|
|
@ -589,15 +594,14 @@ impl Action {
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
} => {
|
} => {
|
||||||
let current_dir = get_current_dir();
|
let current_dir = get_current_dir();
|
||||||
let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(current_dir))
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
|
url.as_str(),
|
||||||
let run_plugin = RunPlugin {
|
&configuration.map(|c| c.inner().clone()),
|
||||||
location: run_plugin_location,
|
None,
|
||||||
_allow_exec_host_cmd: false,
|
Some(current_dir),
|
||||||
configuration: configuration.unwrap_or_default(),
|
)?;
|
||||||
};
|
|
||||||
Ok(vec![Action::LaunchOrFocusPlugin(
|
Ok(vec![Action::LaunchOrFocusPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
floating,
|
floating,
|
||||||
move_to_focused_tab,
|
move_to_focused_tab,
|
||||||
in_place,
|
in_place,
|
||||||
|
|
@ -612,16 +616,14 @@ impl Action {
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
} => {
|
} => {
|
||||||
let current_dir = get_current_dir();
|
let current_dir = get_current_dir();
|
||||||
let run_plugin_location =
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
RunPluginLocation::parse(url.as_str(), Some(current_dir.clone()))
|
&url.as_str(),
|
||||||
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
|
&configuration.map(|c| c.inner().clone()),
|
||||||
let run_plugin = RunPlugin {
|
None,
|
||||||
location: run_plugin_location,
|
Some(current_dir.clone()),
|
||||||
_allow_exec_host_cmd: false,
|
)?;
|
||||||
configuration: configuration.unwrap_or_default(),
|
|
||||||
};
|
|
||||||
Ok(vec![Action::LaunchPlugin(
|
Ok(vec![Action::LaunchPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
floating,
|
floating,
|
||||||
in_place,
|
in_place,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use std::convert::TryFrom;
|
||||||
|
|
||||||
use super::keybinds::Keybinds;
|
use super::keybinds::Keybinds;
|
||||||
use super::options::Options;
|
use super::options::Options;
|
||||||
use super::plugins::{PluginsConfig, PluginsConfigError};
|
use super::plugins::{PluginAliases, PluginsConfigError};
|
||||||
use super::theme::{Themes, UiConfig};
|
use super::theme::{Themes, UiConfig};
|
||||||
use crate::cli::{CliArgs, Command};
|
use crate::cli::{CliArgs, Command};
|
||||||
use crate::envs::EnvironmentVariables;
|
use crate::envs::EnvironmentVariables;
|
||||||
|
|
@ -25,7 +25,7 @@ pub struct Config {
|
||||||
pub keybinds: Keybinds,
|
pub keybinds: Keybinds,
|
||||||
pub options: Options,
|
pub options: Options,
|
||||||
pub themes: Themes,
|
pub themes: Themes,
|
||||||
pub plugins: PluginsConfig,
|
pub plugins: PluginAliases,
|
||||||
pub ui: UiConfig,
|
pub ui: UiConfig,
|
||||||
pub env: EnvironmentVariables,
|
pub env: EnvironmentVariables,
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +226,7 @@ impl Config {
|
||||||
self.options = self.options.merge(other.options);
|
self.options = self.options.merge(other.options);
|
||||||
self.keybinds.merge(other.keybinds.clone());
|
self.keybinds.merge(other.keybinds.clone());
|
||||||
self.themes = self.themes.merge(other.themes);
|
self.themes = self.themes.merge(other.themes);
|
||||||
self.plugins = self.plugins.merge(other.plugins);
|
self.plugins.merge(other.plugins);
|
||||||
self.ui = self.ui.merge(other.ui);
|
self.ui = self.ui.merge(other.ui);
|
||||||
self.env = self.env.merge(other.env);
|
self.env = self.env.merge(other.env);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -237,11 +237,11 @@ impl Config {
|
||||||
mod config_test {
|
mod config_test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::data::{InputMode, Palette, PaletteColor, PluginTag};
|
use crate::data::{InputMode, Palette, PaletteColor, PluginTag};
|
||||||
use crate::input::layout::RunPluginLocation;
|
use crate::input::layout::{RunPlugin, RunPluginLocation};
|
||||||
use crate::input::options::{Clipboard, OnForceClose};
|
use crate::input::options::{Clipboard, OnForceClose};
|
||||||
use crate::input::plugins::{PluginConfig, PluginType, PluginsConfig};
|
use crate::input::plugins::{PluginConfig, PluginType};
|
||||||
use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
|
use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
|
||||||
use std::collections::HashMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
|
@ -591,60 +591,54 @@ mod config_test {
|
||||||
fn can_define_plugin_configuration_in_configfile() {
|
fn can_define_plugin_configuration_in_configfile() {
|
||||||
let config_contents = r#"
|
let config_contents = r#"
|
||||||
plugins {
|
plugins {
|
||||||
tab-bar { path "tab-bar"; }
|
tab-bar location="zellij:tab-bar"
|
||||||
status-bar { path "status-bar"; }
|
status-bar location="zellij:status-bar"
|
||||||
strider {
|
strider location="zellij:strider"
|
||||||
path "strider"
|
compact-bar location="zellij:compact-bar"
|
||||||
_allow_exec_host_cmd true
|
session-manager location="zellij:session-manager"
|
||||||
|
welcome-screen location="zellij:session-manager" {
|
||||||
|
welcome_screen true
|
||||||
}
|
}
|
||||||
compact-bar { path "compact-bar"; }
|
filepicker location="zellij:strider"
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
let config = Config::from_kdl(config_contents, None).unwrap();
|
let config = Config::from_kdl(config_contents, None).unwrap();
|
||||||
let mut expected_plugin_configuration = HashMap::new();
|
let mut expected_plugin_configuration = BTreeMap::new();
|
||||||
expected_plugin_configuration.insert(
|
expected_plugin_configuration.insert(
|
||||||
PluginTag::new("tab-bar"),
|
"tab-bar".to_owned(),
|
||||||
PluginConfig {
|
RunPlugin::from_url("zellij:tab-bar").unwrap(),
|
||||||
path: PathBuf::from("tab-bar"),
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
userspace_configuration: Default::default(),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expected_plugin_configuration.insert(
|
expected_plugin_configuration.insert(
|
||||||
PluginTag::new("status-bar"),
|
"status-bar".to_owned(),
|
||||||
PluginConfig {
|
RunPlugin::from_url("zellij:status-bar").unwrap(),
|
||||||
path: PathBuf::from("status-bar"),
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
userspace_configuration: Default::default(),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expected_plugin_configuration.insert(
|
expected_plugin_configuration.insert(
|
||||||
PluginTag::new("strider"),
|
"strider".to_owned(),
|
||||||
PluginConfig {
|
RunPlugin::from_url("zellij:strider").unwrap(),
|
||||||
path: PathBuf::from("strider"),
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("strider")),
|
|
||||||
_allow_exec_host_cmd: true,
|
|
||||||
userspace_configuration: Default::default(),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expected_plugin_configuration.insert(
|
expected_plugin_configuration.insert(
|
||||||
PluginTag::new("compact-bar"),
|
"compact-bar".to_owned(),
|
||||||
PluginConfig {
|
RunPlugin::from_url("zellij:compact-bar").unwrap(),
|
||||||
path: PathBuf::from("compact-bar"),
|
);
|
||||||
run: PluginType::Pane(None),
|
expected_plugin_configuration.insert(
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("compact-bar")),
|
"session-manager".to_owned(),
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin::from_url("zellij:session-manager").unwrap(),
|
||||||
userspace_configuration: Default::default(),
|
);
|
||||||
},
|
let mut welcome_screen_configuration = BTreeMap::new();
|
||||||
|
welcome_screen_configuration.insert("welcome_screen".to_owned(), "true".to_owned());
|
||||||
|
expected_plugin_configuration.insert(
|
||||||
|
"welcome-screen".to_owned(),
|
||||||
|
RunPlugin::from_url("zellij:session-manager")
|
||||||
|
.unwrap()
|
||||||
|
.with_configuration(welcome_screen_configuration),
|
||||||
|
);
|
||||||
|
expected_plugin_configuration.insert(
|
||||||
|
"filepicker".to_owned(),
|
||||||
|
RunPlugin::from_url("zellij:strider").unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.plugins,
|
config.plugins,
|
||||||
PluginsConfig::from_data(expected_plugin_configuration),
|
PluginAliases::from_data(expected_plugin_configuration),
|
||||||
"Plugins defined in config"
|
"Plugins defined in config"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ use std::cmp::Ordering;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::plugins::{PluginTag, PluginsConfigError};
|
use super::plugins::{PluginAliases, PluginTag, PluginsConfigError};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
@ -80,10 +80,122 @@ impl SplitSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum RunPluginOrAlias {
|
||||||
|
RunPlugin(RunPlugin),
|
||||||
|
Alias(PluginAlias),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RunPluginOrAlias {
|
||||||
|
fn default() -> Self {
|
||||||
|
RunPluginOrAlias::RunPlugin(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RunPluginOrAlias {
|
||||||
|
pub fn location_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
RunPluginOrAlias::RunPlugin(run_plugin) => run_plugin.location.display(),
|
||||||
|
RunPluginOrAlias::Alias(plugin_alias) => plugin_alias.name.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn populate_run_plugin_if_needed(&mut self, plugin_aliases: &PluginAliases) {
|
||||||
|
if let RunPluginOrAlias::Alias(run_plugin_alias) = self {
|
||||||
|
if run_plugin_alias.run_plugin.is_some() {
|
||||||
|
log::warn!("Overriding plugin alias");
|
||||||
|
}
|
||||||
|
let merged_run_plugin = plugin_aliases
|
||||||
|
.aliases
|
||||||
|
.get(run_plugin_alias.name.as_str())
|
||||||
|
.map(|r| {
|
||||||
|
r.clone().merge_configuration(
|
||||||
|
&run_plugin_alias
|
||||||
|
.configuration
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c.inner().clone()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
run_plugin_alias.run_plugin = merged_run_plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_run_plugin(&self) -> Option<RunPlugin> {
|
||||||
|
match self {
|
||||||
|
RunPluginOrAlias::RunPlugin(run_plugin) => Some(run_plugin.clone()),
|
||||||
|
RunPluginOrAlias::Alias(plugin_alias) => plugin_alias.run_plugin.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_configuration(&self) -> Option<PluginUserConfiguration> {
|
||||||
|
self.get_run_plugin().map(|r| r.configuration.clone())
|
||||||
|
}
|
||||||
|
pub fn from_url(
|
||||||
|
url: &str,
|
||||||
|
configuration: &Option<BTreeMap<String, String>>,
|
||||||
|
alias_dict: Option<&PluginAliases>,
|
||||||
|
cwd: Option<PathBuf>,
|
||||||
|
) -> Result<Self, String> {
|
||||||
|
match RunPluginLocation::parse(&url, cwd) {
|
||||||
|
Ok(location) => Ok(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location,
|
||||||
|
configuration: configuration
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| PluginUserConfiguration::new(c.clone()))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
})),
|
||||||
|
Err(PluginsConfigError::InvalidUrlScheme(_))
|
||||||
|
| Err(PluginsConfigError::InvalidUrl(..)) => {
|
||||||
|
let mut plugin_alias = PluginAlias::new(&url, configuration);
|
||||||
|
if let Some(alias_dict) = alias_dict {
|
||||||
|
plugin_alias.run_plugin = alias_dict
|
||||||
|
.aliases
|
||||||
|
.get(url)
|
||||||
|
.map(|r| r.clone().merge_configuration(configuration));
|
||||||
|
}
|
||||||
|
Ok(RunPluginOrAlias::Alias(plugin_alias))
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!("Failed to parse plugin location {url}: {}", e));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_equivalent_to_run(&self, run: &Option<Run>) -> bool {
|
||||||
|
match (self, run) {
|
||||||
|
(
|
||||||
|
RunPluginOrAlias::Alias(self_alias),
|
||||||
|
Some(Run::Plugin(RunPluginOrAlias::Alias(run_alias))),
|
||||||
|
) => {
|
||||||
|
self_alias.name == run_alias.name
|
||||||
|
&& self_alias
|
||||||
|
.configuration
|
||||||
|
.as_ref()
|
||||||
|
// we do the is_empty() checks because an empty configuration is the same as no
|
||||||
|
// configuration (i.e. None)
|
||||||
|
.and_then(|c| if c.inner().is_empty() { None } else { Some(c) })
|
||||||
|
== run_alias.configuration.as_ref().and_then(|c| {
|
||||||
|
if c.inner().is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(
|
||||||
|
RunPluginOrAlias::Alias(self_alias),
|
||||||
|
Some(Run::Plugin(RunPluginOrAlias::RunPlugin(other_run_plugin))),
|
||||||
|
) => self_alias.run_plugin.as_ref() == Some(other_run_plugin),
|
||||||
|
(
|
||||||
|
RunPluginOrAlias::RunPlugin(self_run_plugin),
|
||||||
|
Some(Run::Plugin(RunPluginOrAlias::RunPlugin(other_run_plugin))),
|
||||||
|
) => self_run_plugin == other_run_plugin,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
pub enum Run {
|
pub enum Run {
|
||||||
#[serde(rename = "plugin")]
|
#[serde(rename = "plugin")]
|
||||||
Plugin(RunPlugin),
|
Plugin(RunPluginOrAlias),
|
||||||
#[serde(rename = "command")]
|
#[serde(rename = "command")]
|
||||||
Command(RunCommand),
|
Command(RunCommand),
|
||||||
EditFile(PathBuf, Option<usize>, Option<PathBuf>), // TODO: merge this with TerminalAction::OpenFile
|
EditFile(PathBuf, Option<usize>, Option<PathBuf>), // TODO: merge this with TerminalAction::OpenFile
|
||||||
|
|
@ -227,6 +339,23 @@ impl Run {
|
||||||
Run::Cwd(cwd) => Some(cwd.clone()),
|
Run::Cwd(cwd) => Some(cwd.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn get_run_plugin(&self) -> Option<RunPlugin> {
|
||||||
|
match self {
|
||||||
|
Run::Plugin(RunPluginOrAlias::RunPlugin(run_plugin)) => Some(run_plugin.clone()),
|
||||||
|
Run::Plugin(RunPluginOrAlias::Alias(plugin_alias)) => {
|
||||||
|
plugin_alias.run_plugin.as_ref().map(|r| r.clone())
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn populate_run_plugin_if_needed(&mut self, alias_dict: &PluginAliases) {
|
||||||
|
match self {
|
||||||
|
Run::Plugin(run_plugin_alias) => {
|
||||||
|
run_plugin_alias.populate_run_plugin_if_needed(alias_dict)
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derive_hash_xor_eq)]
|
#[allow(clippy::derive_hash_xor_eq)]
|
||||||
|
|
@ -246,6 +375,35 @@ impl RunPlugin {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn with_configuration(mut self, configuration: BTreeMap<String, String>) -> Self {
|
||||||
|
self.configuration = PluginUserConfiguration::new(configuration);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn merge_configuration(mut self, configuration: &Option<BTreeMap<String, String>>) -> Self {
|
||||||
|
if let Some(configuration) = configuration {
|
||||||
|
self.configuration.merge(configuration);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Hash, Default, PartialEq, Eq)]
|
||||||
|
pub struct PluginAlias {
|
||||||
|
pub name: String,
|
||||||
|
pub configuration: Option<PluginUserConfiguration>,
|
||||||
|
pub run_plugin: Option<RunPlugin>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginAlias {
|
||||||
|
pub fn new(name: &str, configuration: &Option<BTreeMap<String, String>>) -> Self {
|
||||||
|
PluginAlias {
|
||||||
|
name: name.to_owned(),
|
||||||
|
configuration: configuration
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| PluginUserConfiguration::new(c.clone())),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derive_hash_xor_eq)]
|
#[allow(clippy::derive_hash_xor_eq)]
|
||||||
|
|
@ -280,6 +438,11 @@ impl PluginUserConfiguration {
|
||||||
pub fn insert(&mut self, config_key: impl Into<String>, config_value: impl Into<String>) {
|
pub fn insert(&mut self, config_key: impl Into<String>, config_value: impl Into<String>) {
|
||||||
self.0.insert(config_key.into(), config_value.into());
|
self.0.insert(config_key.into(), config_value.into());
|
||||||
}
|
}
|
||||||
|
pub fn merge(&mut self, other_config: &BTreeMap<String, String>) {
|
||||||
|
for (key, value) in other_config {
|
||||||
|
self.0.insert(key.to_owned(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for PluginUserConfiguration {
|
impl FromStr for PluginUserConfiguration {
|
||||||
|
|
@ -706,6 +869,15 @@ impl TiledPaneLayout {
|
||||||
child.add_cwd_to_layout(cwd);
|
child.add_cwd_to_layout(cwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn populate_plugin_aliases_in_layout(&mut self, plugin_aliases: &PluginAliases) {
|
||||||
|
match self.run.as_mut() {
|
||||||
|
Some(run) => run.populate_run_plugin_if_needed(plugin_aliases),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
for child in self.children.iter_mut() {
|
||||||
|
child.populate_plugin_aliases_in_layout(plugin_aliases);
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn deepest_depth(&self) -> usize {
|
pub fn deepest_depth(&self) -> usize {
|
||||||
let mut deepest_child_depth = 0;
|
let mut deepest_child_depth = 0;
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
|
|
@ -1141,6 +1313,26 @@ impl Layout {
|
||||||
Err(_e) => None,
|
Err(_e) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn populate_plugin_aliases_in_layout(&mut self, plugin_aliases: &PluginAliases) {
|
||||||
|
for tab in self.tabs.iter_mut() {
|
||||||
|
tab.1.populate_plugin_aliases_in_layout(plugin_aliases);
|
||||||
|
for floating_pane_layout in tab.2.iter_mut() {
|
||||||
|
floating_pane_layout
|
||||||
|
.run
|
||||||
|
.as_mut()
|
||||||
|
.map(|f| f.populate_run_plugin_if_needed(&plugin_aliases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(template) = self.template.as_mut() {
|
||||||
|
template.0.populate_plugin_aliases_in_layout(plugin_aliases);
|
||||||
|
for floating_pane_layout in template.1.iter_mut() {
|
||||||
|
floating_pane_layout
|
||||||
|
.run
|
||||||
|
.as_mut()
|
||||||
|
.map(|f| f.populate_run_plugin_if_needed(&plugin_aliases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_space(
|
fn split_space(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
//! Plugins configuration metadata
|
//! Plugins configuration metadata
|
||||||
use std::borrow::Borrow;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -14,73 +13,17 @@ use crate::consts::ASSET_MAP;
|
||||||
pub use crate::data::PluginTag;
|
pub use crate::data::PluginTag;
|
||||||
use crate::errors::prelude::*;
|
use crate::errors::prelude::*;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
use std::fmt;
|
pub struct PluginAliases {
|
||||||
|
pub aliases: BTreeMap<String, RunPlugin>,
|
||||||
/// Used in the config struct for plugin metadata
|
|
||||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
|
||||||
pub struct PluginsConfig(pub HashMap<PluginTag, PluginConfig>);
|
|
||||||
|
|
||||||
impl fmt::Debug for PluginsConfig {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let mut stable_sorted = BTreeMap::new();
|
|
||||||
for (plugin_tag, plugin_config) in self.0.iter() {
|
|
||||||
stable_sorted.insert(plugin_tag, plugin_config);
|
|
||||||
}
|
|
||||||
write!(f, "{:#?}", stable_sorted)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginsConfig {
|
impl PluginAliases {
|
||||||
pub fn new() -> Self {
|
pub fn merge(&mut self, other: Self) {
|
||||||
Self(HashMap::new())
|
self.aliases.extend(other.aliases);
|
||||||
}
|
}
|
||||||
pub fn from_data(data: HashMap<PluginTag, PluginConfig>) -> Self {
|
pub fn from_data(aliases: BTreeMap<String, RunPlugin>) -> Self {
|
||||||
PluginsConfig(data)
|
PluginAliases { aliases }
|
||||||
}
|
|
||||||
|
|
||||||
/// Get plugin config from run configuration specified in layout files.
|
|
||||||
pub fn get(&self, run: impl Borrow<RunPlugin>) -> Option<PluginConfig> {
|
|
||||||
let run = run.borrow();
|
|
||||||
match &run.location {
|
|
||||||
RunPluginLocation::File(path) => Some(PluginConfig {
|
|
||||||
path: path.clone(),
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
_allow_exec_host_cmd: run._allow_exec_host_cmd,
|
|
||||||
location: run.location.clone(),
|
|
||||||
userspace_configuration: run.configuration.clone(),
|
|
||||||
}),
|
|
||||||
RunPluginLocation::Zellij(tag) => self.0.get(tag).cloned().map(|plugin| PluginConfig {
|
|
||||||
_allow_exec_host_cmd: run._allow_exec_host_cmd,
|
|
||||||
userspace_configuration: run.configuration.clone(),
|
|
||||||
..plugin
|
|
||||||
}),
|
|
||||||
RunPluginLocation::Remote(_) => Some(PluginConfig {
|
|
||||||
path: PathBuf::new(),
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
_allow_exec_host_cmd: run._allow_exec_host_cmd,
|
|
||||||
location: run.location.clone(),
|
|
||||||
userspace_configuration: run.configuration.clone(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &PluginConfig> {
|
|
||||||
self.0.values()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merges two PluginConfig structs into one PluginConfig struct
|
|
||||||
/// `other` overrides the PluginConfig of `self`.
|
|
||||||
pub fn merge(&self, other: Self) -> Self {
|
|
||||||
let mut plugin_config = self.0.clone();
|
|
||||||
plugin_config.extend(other.0);
|
|
||||||
Self(plugin_config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PluginsConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
PluginsConfig(HashMap::new())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +43,44 @@ pub struct PluginConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginConfig {
|
impl PluginConfig {
|
||||||
|
pub fn from_run_plugin(run_plugin: &RunPlugin) -> Option<PluginConfig> {
|
||||||
|
match &run_plugin.location {
|
||||||
|
RunPluginLocation::File(path) => Some(PluginConfig {
|
||||||
|
path: path.clone(),
|
||||||
|
run: PluginType::Pane(None),
|
||||||
|
_allow_exec_host_cmd: run_plugin._allow_exec_host_cmd,
|
||||||
|
location: run_plugin.location.clone(),
|
||||||
|
userspace_configuration: run_plugin.configuration.clone(),
|
||||||
|
}),
|
||||||
|
RunPluginLocation::Zellij(tag) => {
|
||||||
|
let tag = tag.to_string();
|
||||||
|
if tag == "status-bar"
|
||||||
|
|| tag == "tab-bar"
|
||||||
|
|| tag == "compact-bar"
|
||||||
|
|| tag == "strider"
|
||||||
|
|| tag == "session-manager"
|
||||||
|
{
|
||||||
|
Some(PluginConfig {
|
||||||
|
path: PathBuf::from(&tag),
|
||||||
|
run: PluginType::Pane(None),
|
||||||
|
_allow_exec_host_cmd: run_plugin._allow_exec_host_cmd,
|
||||||
|
location: RunPluginLocation::parse(&format!("zellij:{}", tag), None)
|
||||||
|
.ok()?,
|
||||||
|
userspace_configuration: run_plugin.configuration.clone(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RunPluginLocation::Remote(_) => Some(PluginConfig {
|
||||||
|
path: PathBuf::new(),
|
||||||
|
run: PluginType::Pane(None),
|
||||||
|
_allow_exec_host_cmd: run_plugin._allow_exec_host_cmd,
|
||||||
|
location: run_plugin.location.clone(),
|
||||||
|
userspace_configuration: run_plugin.configuration.clone(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Resolve wasm plugin bytes for the plugin path and given plugin directory.
|
/// Resolve wasm plugin bytes for the plugin path and given plugin directory.
|
||||||
///
|
///
|
||||||
/// If zellij was built without the 'disable_automatic_asset_installation' feature, builtin
|
/// If zellij was built without the 'disable_automatic_asset_installation' feature, builtin
|
||||||
|
|
|
||||||
|
|
@ -551,29 +551,29 @@ fn layout_with_plugin_panes() {
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
children: vec![
|
children: vec![
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location: RunPluginLocation::File(PathBuf::from(
|
location: RunPluginLocation::File(PathBuf::from(
|
||||||
"/path/to/my/plugin.wasm",
|
"/path/to/my/plugin.wasm",
|
||||||
)),
|
)),
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
location: RunPluginLocation::Zellij(PluginTag::new("status-bar")),
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: PluginUserConfiguration(expected_plugin_configuration),
|
configuration: PluginUserConfiguration(expected_plugin_configuration),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -2079,6 +2079,9 @@ fn run_plugin_location_parsing() {
|
||||||
pane {
|
pane {
|
||||||
plugin location="file:c:/absolute/windows/plugin.wasm"
|
plugin location="file:c:/absolute/windows/plugin.wasm"
|
||||||
}
|
}
|
||||||
|
pane {
|
||||||
|
plugin location="filepicker"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap();
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap();
|
||||||
|
|
@ -2087,59 +2090,67 @@ fn run_plugin_location_parsing() {
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
children: vec![
|
children: vec![
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from(
|
location: RunPluginLocation::File(PathBuf::from(
|
||||||
"/path/to/my/plugin.wasm",
|
"/path/to/my/plugin.wasm",
|
||||||
)),
|
)),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from("plugin.wasm")),
|
location: RunPluginLocation::File(PathBuf::from("plugin.wasm")),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from(
|
location: RunPluginLocation::File(PathBuf::from(
|
||||||
"relative/with space/plugin.wasm",
|
"relative/with space/plugin.wasm",
|
||||||
)),
|
)),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from(
|
location: RunPluginLocation::File(PathBuf::from(
|
||||||
"/absolute/with space/plugin.wasm",
|
"/absolute/with space/plugin.wasm",
|
||||||
)),
|
)),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TiledPaneLayout {
|
TiledPaneLayout {
|
||||||
run: Some(Run::Plugin(RunPlugin {
|
run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
location: RunPluginLocation::File(PathBuf::from(
|
location: RunPluginLocation::File(PathBuf::from(
|
||||||
"c:/absolute/windows/plugin.wasm",
|
"c:/absolute/windows/plugin.wasm",
|
||||||
)),
|
)),
|
||||||
configuration: Default::default(),
|
configuration: Default::default(),
|
||||||
})),
|
}))),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TiledPaneLayout {
|
||||||
|
run: Some(Run::Plugin(RunPluginOrAlias::Alias(PluginAlias {
|
||||||
|
name: "filepicker".to_owned(),
|
||||||
|
configuration: Some(PluginUserConfiguration::default()),
|
||||||
|
..Default::default()
|
||||||
|
}))),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/input/./unit/layout_test.rs
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
assertion_line: 1880
|
assertion_line: 1935
|
||||||
expression: "format!(\"{:#?}\", layout)"
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
---
|
---
|
||||||
Layout {
|
Layout {
|
||||||
|
|
@ -65,17 +65,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"tab-bar",
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -167,17 +169,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"status-bar",
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -220,17 +224,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"tab-bar",
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -387,17 +393,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"status-bar",
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -440,17 +448,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"tab-bar",
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -688,17 +698,19 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"status-bar",
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
data::{ClientId, ConnectToSession, InputMode, Style},
|
data::{ClientId, ConnectToSession, InputMode, Style},
|
||||||
errors::{get_current_ctx, prelude::*, ErrorContext},
|
errors::{get_current_ctx, prelude::*, ErrorContext},
|
||||||
input::keybinds::Keybinds,
|
input::keybinds::Keybinds,
|
||||||
input::{actions::Action, layout::Layout, options::Options, plugins::PluginsConfig},
|
input::{actions::Action, layout::Layout, options::Options, plugins::PluginAliases},
|
||||||
pane_size::{Size, SizeInPixels},
|
pane_size::{Size, SizeInPixels},
|
||||||
};
|
};
|
||||||
use interprocess::local_socket::LocalSocketStream;
|
use interprocess::local_socket::LocalSocketStream;
|
||||||
|
|
@ -76,7 +76,7 @@ pub enum ClientToServerMsg {
|
||||||
Box<CliArgs>,
|
Box<CliArgs>,
|
||||||
Box<Options>,
|
Box<Options>,
|
||||||
Box<Layout>,
|
Box<Layout>,
|
||||||
Option<PluginsConfig>,
|
Box<PluginAliases>,
|
||||||
),
|
),
|
||||||
AttachClient(
|
AttachClient(
|
||||||
ClientAttributes,
|
ClientAttributes,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use crate::input::{
|
||||||
config::ConfigError,
|
config::ConfigError,
|
||||||
layout::{
|
layout::{
|
||||||
FloatingPaneLayout, Layout, LayoutConstraint, PercentOrFixed, PluginUserConfiguration, Run,
|
FloatingPaneLayout, Layout, LayoutConstraint, PercentOrFixed, PluginUserConfiguration, Run,
|
||||||
RunPlugin, RunPluginLocation, SplitDirection, SplitSize, SwapFloatingLayout,
|
RunPluginOrAlias, SplitDirection, SplitSize, SwapFloatingLayout, SwapTiledLayout,
|
||||||
SwapTiledLayout, TiledPaneLayout,
|
TiledPaneLayout,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -313,20 +313,21 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
plugin_block.span().len(),
|
plugin_block.span().len(),
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
let location =
|
|
||||||
RunPluginLocation::parse(&string_url, self.cwd_prefix(None)?).map_err(|e| {
|
|
||||||
ConfigError::new_layout_kdl_error(
|
|
||||||
e.to_string(),
|
|
||||||
url_node.span().offset(),
|
|
||||||
url_node.span().len(),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&plugin_block)?;
|
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&plugin_block)?;
|
||||||
Ok(Some(Run::Plugin(RunPlugin {
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
_allow_exec_host_cmd,
|
&string_url,
|
||||||
location,
|
&Some(configuration.inner().clone()),
|
||||||
configuration,
|
None,
|
||||||
})))
|
self.cwd_prefix(None)?,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
ConfigError::new_kdl_error(
|
||||||
|
format!("Failed to parse plugin: {}", e),
|
||||||
|
url_node.span().offset(),
|
||||||
|
url_node.span().len(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(Some(Run::Plugin(run_plugin_or_alias)))
|
||||||
}
|
}
|
||||||
pub fn parse_plugin_user_configuration(
|
pub fn parse_plugin_user_configuration(
|
||||||
plugin_block: &KdlNode,
|
plugin_block: &KdlNode,
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ use crate::envs::EnvironmentVariables;
|
||||||
use crate::home::{find_default_config_dir, get_layout_dir};
|
use crate::home::{find_default_config_dir, get_layout_dir};
|
||||||
use crate::input::config::{Config, ConfigError, KdlError};
|
use crate::input::config::{Config, ConfigError, KdlError};
|
||||||
use crate::input::keybinds::Keybinds;
|
use crate::input::keybinds::Keybinds;
|
||||||
use crate::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation};
|
use crate::input::layout::{Layout, RunPlugin, RunPluginOrAlias};
|
||||||
use crate::input::options::{Clipboard, OnForceClose, Options};
|
use crate::input::options::{Clipboard, OnForceClose, Options};
|
||||||
use crate::input::permission::{GrantedPermission, PermissionCache};
|
use crate::input::permission::{GrantedPermission, PermissionCache};
|
||||||
use crate::input::plugins::{PluginConfig, PluginTag, PluginType, PluginsConfig};
|
use crate::input::plugins::PluginAliases;
|
||||||
use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
|
use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
|
||||||
use kdl_layout_parser::KdlLayoutParser;
|
use kdl_layout_parser::KdlLayoutParser;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
|
|
@ -981,15 +981,22 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
|
||||||
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache"))
|
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache"))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
||||||
let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?;
|
|
||||||
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?;
|
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?;
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
location,
|
&plugin_path,
|
||||||
_allow_exec_host_cmd: false,
|
&Some(configuration.inner().clone()),
|
||||||
configuration,
|
None,
|
||||||
};
|
Some(current_dir),
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
ConfigError::new_kdl_error(
|
||||||
|
format!("Failed to parse plugin: {}", e),
|
||||||
|
kdl_action.span().offset(),
|
||||||
|
kdl_action.span().len(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
Ok(Action::LaunchOrFocusPlugin(
|
Ok(Action::LaunchOrFocusPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
move_to_focused_tab,
|
move_to_focused_tab,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
|
|
@ -1019,15 +1026,22 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
|
||||||
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache"))
|
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache"))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
||||||
let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?;
|
|
||||||
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?;
|
let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?;
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
location,
|
&plugin_path,
|
||||||
_allow_exec_host_cmd: false,
|
&Some(configuration.inner().clone()),
|
||||||
configuration,
|
None,
|
||||||
};
|
Some(current_dir),
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
ConfigError::new_kdl_error(
|
||||||
|
format!("Failed to parse plugin: {}", e),
|
||||||
|
kdl_action.span().offset(),
|
||||||
|
kdl_action.span().len(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
Ok(Action::LaunchPlugin(
|
Ok(Action::LaunchPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
|
|
@ -1810,9 +1824,9 @@ impl Config {
|
||||||
let config_themes = Themes::from_kdl(kdl_themes)?;
|
let config_themes = Themes::from_kdl(kdl_themes)?;
|
||||||
config.themes = config.themes.merge(config_themes);
|
config.themes = config.themes.merge(config_themes);
|
||||||
}
|
}
|
||||||
if let Some(kdl_plugin_config) = kdl_config.get("plugins") {
|
if let Some(kdl_plugin_aliases) = kdl_config.get("plugins") {
|
||||||
let config_plugins = PluginsConfig::from_kdl(kdl_plugin_config)?;
|
let config_plugins = PluginAliases::from_kdl(kdl_plugin_aliases)?;
|
||||||
config.plugins = config.plugins.merge(config_plugins);
|
config.plugins.merge(config_plugins);
|
||||||
}
|
}
|
||||||
if let Some(kdl_ui_config) = kdl_config.get("ui") {
|
if let Some(kdl_ui_config) = kdl_config.get("ui") {
|
||||||
let config_ui = UiConfig::from_kdl(&kdl_ui_config)?;
|
let config_ui = UiConfig::from_kdl(&kdl_ui_config)?;
|
||||||
|
|
@ -1826,38 +1840,27 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginsConfig {
|
impl PluginAliases {
|
||||||
pub fn from_kdl(kdl_plugin_config: &KdlNode) -> Result<Self, ConfigError> {
|
pub fn from_kdl(kdl_plugin_aliases: &KdlNode) -> Result<PluginAliases, ConfigError> {
|
||||||
let mut plugins: HashMap<PluginTag, PluginConfig> = HashMap::new();
|
let mut aliases: BTreeMap<String, RunPlugin> = BTreeMap::new();
|
||||||
for plugin_config in
|
if let Some(kdl_plugin_aliases) = kdl_children_nodes!(kdl_plugin_aliases) {
|
||||||
kdl_children_nodes_or_error!(kdl_plugin_config, "no plugin config found")
|
for alias_definition in kdl_plugin_aliases {
|
||||||
{
|
let alias_name = kdl_name!(alias_definition);
|
||||||
let plugin_name = kdl_name!(plugin_config);
|
if let Some(string_url) =
|
||||||
let plugin_tag = PluginTag::new(plugin_name);
|
kdl_get_string_property_or_child_value!(alias_definition, "location")
|
||||||
let path = kdl_children_property_first_arg_as_string!(plugin_config, "path")
|
{
|
||||||
.map(|path| PathBuf::from(path))
|
let configuration =
|
||||||
.ok_or(ConfigError::new_kdl_error(
|
KdlLayoutParser::parse_plugin_user_configuration(&alias_definition)?;
|
||||||
"Plugin path not found or invalid".into(),
|
let run_plugin = RunPlugin::from_url(string_url)?
|
||||||
plugin_config.span().offset(),
|
.with_configuration(configuration.inner().clone());
|
||||||
plugin_config.span().len(),
|
aliases.insert(alias_name.to_owned(), run_plugin);
|
||||||
))?;
|
}
|
||||||
let allow_exec_host_cmd =
|
}
|
||||||
kdl_children_property_first_arg_as_bool!(plugin_config, "_allow_exec_host_cmd")
|
|
||||||
.unwrap_or(false);
|
|
||||||
let plugin_config = PluginConfig {
|
|
||||||
path,
|
|
||||||
run: PluginType::Pane(None),
|
|
||||||
location: RunPluginLocation::Zellij(plugin_tag.clone()),
|
|
||||||
_allow_exec_host_cmd: allow_exec_host_cmd,
|
|
||||||
userspace_configuration: PluginUserConfiguration::new(BTreeMap::new()), // TODO: consider removing the whole
|
|
||||||
// "plugins" section in the config
|
|
||||||
// because it's not used???
|
|
||||||
};
|
|
||||||
plugins.insert(plugin_tag, plugin_config);
|
|
||||||
}
|
}
|
||||||
Ok(PluginsConfig(plugins))
|
Ok(PluginAliases { aliases })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiConfig {
|
impl UiConfig {
|
||||||
pub fn from_kdl(kdl_ui_config: &KdlNode) -> Result<UiConfig, ConfigError> {
|
pub fn from_kdl(kdl_ui_config: &KdlNode) -> Result<UiConfig, ConfigError> {
|
||||||
let mut ui_config = UiConfig::default();
|
let mut ui_config = UiConfig::default();
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,10 @@ use crate::errors::prelude::*;
|
||||||
use crate::input::actions::Action;
|
use crate::input::actions::Action;
|
||||||
use crate::input::actions::{SearchDirection, SearchOption};
|
use crate::input::actions::{SearchDirection, SearchOption};
|
||||||
use crate::input::command::RunCommandAction;
|
use crate::input::command::RunCommandAction;
|
||||||
use crate::input::layout::{PluginUserConfiguration, RunPlugin, RunPluginLocation};
|
use crate::input::layout::{
|
||||||
|
PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||||
|
};
|
||||||
use crate::position::Position;
|
use crate::position::Position;
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
@ -403,24 +404,23 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
Some(ProtobufActionName::LaunchOrFocusPlugin) => {
|
Some(ProtobufActionName::LaunchOrFocusPlugin) => {
|
||||||
match protobuf_action.optional_payload {
|
match protobuf_action.optional_payload {
|
||||||
Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => {
|
Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => {
|
||||||
let run_plugin_location =
|
|
||||||
RunPluginLocation::parse(&payload.plugin_url, None)
|
|
||||||
.map_err(|_| "Malformed LaunchOrFocusPlugin payload")?;
|
|
||||||
let configuration: PluginUserConfiguration = payload
|
let configuration: PluginUserConfiguration = payload
|
||||||
.plugin_configuration
|
.plugin_configuration
|
||||||
.and_then(|p| PluginUserConfiguration::try_from(p).ok())
|
.and_then(|p| PluginUserConfiguration::try_from(p).ok())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
_allow_exec_host_cmd: false,
|
&payload.plugin_url.as_str(),
|
||||||
location: run_plugin_location,
|
&Some(configuration.inner().clone()),
|
||||||
configuration,
|
None,
|
||||||
};
|
None,
|
||||||
|
)
|
||||||
|
.map_err(|_| "Malformed LaunchOrFocusPlugin payload")?;
|
||||||
let should_float = payload.should_float;
|
let should_float = payload.should_float;
|
||||||
let move_to_focused_tab = payload.move_to_focused_tab;
|
let move_to_focused_tab = payload.move_to_focused_tab;
|
||||||
let should_open_in_place = payload.should_open_in_place;
|
let should_open_in_place = payload.should_open_in_place;
|
||||||
let skip_plugin_cache = payload.skip_plugin_cache;
|
let skip_plugin_cache = payload.skip_plugin_cache;
|
||||||
Ok(Action::LaunchOrFocusPlugin(
|
Ok(Action::LaunchOrFocusPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
move_to_focused_tab,
|
move_to_focused_tab,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
|
|
@ -432,25 +432,24 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
},
|
},
|
||||||
Some(ProtobufActionName::LaunchPlugin) => match protobuf_action.optional_payload {
|
Some(ProtobufActionName::LaunchPlugin) => match protobuf_action.optional_payload {
|
||||||
Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => {
|
Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => {
|
||||||
let run_plugin_location =
|
|
||||||
RunPluginLocation::parse(&payload.plugin_url, None)
|
|
||||||
.map_err(|_| "Malformed LaunchOrFocusPlugin payload")?;
|
|
||||||
let configuration: PluginUserConfiguration = payload
|
let configuration: PluginUserConfiguration = payload
|
||||||
.plugin_configuration
|
.plugin_configuration
|
||||||
.and_then(|p| PluginUserConfiguration::try_from(p).ok())
|
.and_then(|p| PluginUserConfiguration::try_from(p).ok())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin_or_alias = RunPluginOrAlias::from_url(
|
||||||
_allow_exec_host_cmd: false,
|
&payload.plugin_url.as_str(),
|
||||||
location: run_plugin_location,
|
&Some(configuration.inner().clone()),
|
||||||
configuration,
|
None,
|
||||||
};
|
None,
|
||||||
|
)
|
||||||
|
.map_err(|_| "Malformed LaunchOrFocusPlugin payload")?;
|
||||||
let should_float = payload.should_float;
|
let should_float = payload.should_float;
|
||||||
let _move_to_focused_tab = payload.move_to_focused_tab; // not actually used in
|
let _move_to_focused_tab = payload.move_to_focused_tab; // not actually used in
|
||||||
// this action
|
// this action
|
||||||
let should_open_in_place = payload.should_open_in_place;
|
let should_open_in_place = payload.should_open_in_place;
|
||||||
let skip_plugin_cache = payload.skip_plugin_cache;
|
let skip_plugin_cache = payload.skip_plugin_cache;
|
||||||
Ok(Action::LaunchPlugin(
|
Ok(Action::LaunchPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
|
|
@ -553,11 +552,11 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
let run_plugin_location =
|
let run_plugin_location =
|
||||||
RunPluginLocation::parse(&payload.plugin_url, None)
|
RunPluginLocation::parse(&payload.plugin_url, None)
|
||||||
.map_err(|_| "Malformed NewTiledPluginPane payload")?;
|
.map_err(|_| "Malformed NewTiledPluginPane payload")?;
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location: run_plugin_location,
|
location: run_plugin_location,
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: PluginUserConfiguration::default(),
|
configuration: PluginUserConfiguration::default(),
|
||||||
};
|
});
|
||||||
let pane_name = payload.pane_name;
|
let pane_name = payload.pane_name;
|
||||||
let skip_plugin_cache = payload.skip_plugin_cache;
|
let skip_plugin_cache = payload.skip_plugin_cache;
|
||||||
Ok(Action::NewTiledPluginPane(
|
Ok(Action::NewTiledPluginPane(
|
||||||
|
|
@ -576,11 +575,11 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
let run_plugin_location =
|
let run_plugin_location =
|
||||||
RunPluginLocation::parse(&payload.plugin_url, None)
|
RunPluginLocation::parse(&payload.plugin_url, None)
|
||||||
.map_err(|_| "Malformed NewTiledPluginPane payload")?;
|
.map_err(|_| "Malformed NewTiledPluginPane payload")?;
|
||||||
let run_plugin = RunPlugin {
|
let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
location: run_plugin_location,
|
location: run_plugin_location,
|
||||||
_allow_exec_host_cmd: false,
|
_allow_exec_host_cmd: false,
|
||||||
configuration: PluginUserConfiguration::default(),
|
configuration: PluginUserConfiguration::default(),
|
||||||
};
|
});
|
||||||
let pane_name = payload.pane_name;
|
let pane_name = payload.pane_name;
|
||||||
let skip_plugin_cache = payload.skip_plugin_cache;
|
let skip_plugin_cache = payload.skip_plugin_cache;
|
||||||
Ok(Action::NewFloatingPluginPane(
|
Ok(Action::NewFloatingPluginPane(
|
||||||
|
|
@ -597,14 +596,11 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
Some(ProtobufActionName::StartOrReloadPlugin) => {
|
Some(ProtobufActionName::StartOrReloadPlugin) => {
|
||||||
match protobuf_action.optional_payload {
|
match protobuf_action.optional_payload {
|
||||||
Some(OptionalPayload::StartOrReloadPluginPayload(payload)) => {
|
Some(OptionalPayload::StartOrReloadPluginPayload(payload)) => {
|
||||||
let run_plugin_location = RunPluginLocation::parse(&payload, None)
|
let run_plugin_or_alias =
|
||||||
.map_err(|_| "Malformed StartOrReloadPluginPayload payload")?;
|
RunPluginOrAlias::from_url(&payload.as_str(), &None, None, None)
|
||||||
let run_plugin = RunPlugin {
|
.map_err(|_| "Malformed LaunchOrFocusPlugin payload")?;
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: run_plugin_location,
|
Ok(Action::StartOrReloadPlugin(run_plugin_or_alias))
|
||||||
configuration: PluginUserConfiguration::default(),
|
|
||||||
};
|
|
||||||
Ok(Action::StartOrReloadPlugin(run_plugin))
|
|
||||||
},
|
},
|
||||||
_ => Err("Wrong payload for Action::StartOrReloadPlugin"),
|
_ => Err("Wrong payload for Action::StartOrReloadPlugin"),
|
||||||
}
|
}
|
||||||
|
|
@ -1044,44 +1040,44 @@ impl TryFrom<Action> for ProtobufAction {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Action::LaunchOrFocusPlugin(
|
Action::LaunchOrFocusPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
move_to_focused_tab,
|
move_to_focused_tab,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
) => {
|
) => {
|
||||||
let url: Url = Url::from(&run_plugin.location);
|
let configuration = run_plugin_or_alias.get_configuration().unwrap_or_default();
|
||||||
Ok(ProtobufAction {
|
Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::LaunchOrFocusPlugin as i32,
|
name: ProtobufActionName::LaunchOrFocusPlugin as i32,
|
||||||
optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload(
|
optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload(
|
||||||
LaunchOrFocusPluginPayload {
|
LaunchOrFocusPluginPayload {
|
||||||
plugin_url: url.into(),
|
plugin_url: run_plugin_or_alias.location_string(),
|
||||||
should_float,
|
should_float,
|
||||||
move_to_focused_tab,
|
move_to_focused_tab,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
plugin_configuration: Some(run_plugin.configuration.try_into()?),
|
plugin_configuration: Some(configuration.try_into()?),
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Action::LaunchPlugin(
|
Action::LaunchPlugin(
|
||||||
run_plugin,
|
run_plugin_or_alias,
|
||||||
should_float,
|
should_float,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
_cwd,
|
_cwd,
|
||||||
) => {
|
) => {
|
||||||
let url: Url = Url::from(&run_plugin.location);
|
let configuration = run_plugin_or_alias.get_configuration().unwrap_or_default();
|
||||||
Ok(ProtobufAction {
|
Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::LaunchPlugin as i32,
|
name: ProtobufActionName::LaunchPlugin as i32,
|
||||||
optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload(
|
optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload(
|
||||||
LaunchOrFocusPluginPayload {
|
LaunchOrFocusPluginPayload {
|
||||||
plugin_url: url.into(),
|
plugin_url: run_plugin_or_alias.location_string(),
|
||||||
should_float,
|
should_float,
|
||||||
move_to_focused_tab: false,
|
move_to_focused_tab: false,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
plugin_configuration: Some(run_plugin.configuration.try_into()?),
|
plugin_configuration: Some(configuration.try_into()?),
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
|
@ -1166,12 +1162,11 @@ impl TryFrom<Action> for ProtobufAction {
|
||||||
optional_payload: None,
|
optional_payload: None,
|
||||||
}),
|
}),
|
||||||
Action::NewTiledPluginPane(run_plugin, pane_name, skip_plugin_cache, _cwd) => {
|
Action::NewTiledPluginPane(run_plugin, pane_name, skip_plugin_cache, _cwd) => {
|
||||||
let plugin_url: Url = Url::from(&run_plugin.location);
|
|
||||||
Ok(ProtobufAction {
|
Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::NewTiledPluginPane as i32,
|
name: ProtobufActionName::NewTiledPluginPane as i32,
|
||||||
optional_payload: Some(OptionalPayload::NewTiledPluginPanePayload(
|
optional_payload: Some(OptionalPayload::NewTiledPluginPanePayload(
|
||||||
NewPluginPanePayload {
|
NewPluginPanePayload {
|
||||||
plugin_url: plugin_url.into(),
|
plugin_url: run_plugin.location_string(),
|
||||||
pane_name,
|
pane_name,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
},
|
},
|
||||||
|
|
@ -1185,27 +1180,30 @@ impl TryFrom<Action> for ProtobufAction {
|
||||||
_cwd,
|
_cwd,
|
||||||
_coordinates,
|
_coordinates,
|
||||||
) => {
|
) => {
|
||||||
let plugin_url: Url = Url::from(&run_plugin.location);
|
// let plugin_url: Url = match run_plugin {
|
||||||
|
// RunPluginOrAlias::RunPlugin(run_plugin) => Url::from(&run_plugin.location),
|
||||||
|
// RunPluginOrAlias::Alias(plugin_alias) => {
|
||||||
|
// // TODO: support plugin alias
|
||||||
|
// unimplemented!()
|
||||||
|
// }
|
||||||
|
// };
|
||||||
Ok(ProtobufAction {
|
Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::NewFloatingPluginPane as i32,
|
name: ProtobufActionName::NewFloatingPluginPane as i32,
|
||||||
optional_payload: Some(OptionalPayload::NewFloatingPluginPanePayload(
|
optional_payload: Some(OptionalPayload::NewFloatingPluginPanePayload(
|
||||||
NewPluginPanePayload {
|
NewPluginPanePayload {
|
||||||
plugin_url: plugin_url.into(),
|
plugin_url: run_plugin.location_string(),
|
||||||
pane_name,
|
pane_name,
|
||||||
skip_plugin_cache,
|
skip_plugin_cache,
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Action::StartOrReloadPlugin(run_plugin) => {
|
Action::StartOrReloadPlugin(run_plugin) => Ok(ProtobufAction {
|
||||||
let plugin_url: Url = Url::from(&run_plugin.location);
|
name: ProtobufActionName::StartOrReloadPlugin as i32,
|
||||||
Ok(ProtobufAction {
|
optional_payload: Some(OptionalPayload::StartOrReloadPluginPayload(
|
||||||
name: ProtobufActionName::StartOrReloadPlugin as i32,
|
run_plugin.location_string(),
|
||||||
optional_payload: Some(OptionalPayload::StartOrReloadPluginPayload(
|
)),
|
||||||
plugin_url.into(),
|
}),
|
||||||
)),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
Action::CloseTerminalPane(terminal_pane_id) => Ok(ProtobufAction {
|
Action::CloseTerminalPane(terminal_pane_id) => Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::CloseTerminalPane as i32,
|
name: ProtobufActionName::CloseTerminalPane as i32,
|
||||||
optional_payload: Some(OptionalPayload::CloseTerminalPanePayload(terminal_pane_id)),
|
optional_payload: Some(OptionalPayload::CloseTerminalPanePayload(terminal_pane_id)),
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,11 @@
|
||||||
//! # Persistence module
|
|
||||||
//! !WIP! This module is holding the logic for all persistence sessions need
|
|
||||||
//!
|
|
||||||
//! # Examples
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! fn main() {
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
input::layout::PluginUserConfiguration,
|
input::layout::PluginUserConfiguration,
|
||||||
input::layout::{
|
input::layout::{
|
||||||
FloatingPaneLayout, Layout, PercentOrFixed, Run, SplitDirection, SplitSize,
|
FloatingPaneLayout, Layout, PercentOrFixed, Run, RunPluginOrAlias, SplitDirection,
|
||||||
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
SplitSize, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
},
|
},
|
||||||
pane_size::{Constraint, PaneGeom},
|
pane_size::{Constraint, PaneGeom},
|
||||||
};
|
};
|
||||||
|
|
@ -238,10 +229,20 @@ fn extract_plugin_and_config(
|
||||||
layout_run: &Option<Run>,
|
layout_run: &Option<Run>,
|
||||||
) -> (Option<String>, Option<PluginUserConfiguration>) {
|
) -> (Option<String>, Option<PluginUserConfiguration>) {
|
||||||
match &layout_run {
|
match &layout_run {
|
||||||
Some(Run::Plugin(run_plugin)) => (
|
Some(Run::Plugin(run_plugin_or_alias)) => match run_plugin_or_alias {
|
||||||
Some(run_plugin.location.display()),
|
RunPluginOrAlias::RunPlugin(run_plugin) => (
|
||||||
Some(run_plugin.configuration.clone()),
|
Some(run_plugin.location.display()),
|
||||||
),
|
Some(run_plugin.configuration.clone()),
|
||||||
|
),
|
||||||
|
RunPluginOrAlias::Alias(plugin_alias) => {
|
||||||
|
let name = plugin_alias.name.clone();
|
||||||
|
let configuration = plugin_alias
|
||||||
|
.run_plugin
|
||||||
|
.as_ref()
|
||||||
|
.map(|run_plugin| run_plugin.configuration.clone());
|
||||||
|
(Some(name), configuration)
|
||||||
|
},
|
||||||
|
},
|
||||||
_ => (None, None),
|
_ => (None, None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -770,20 +770,6 @@ mod setup_test {
|
||||||
assert_snapshot!(format!("{:#?}", config));
|
assert_snapshot!(format!("{:#?}", config));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn layout_plugins_override_config_plugins() {
|
|
||||||
let mut cli_args = CliArgs::default();
|
|
||||||
cli_args.config = Some(PathBuf::from(format!(
|
|
||||||
"{}/src/test-fixtures/config-with-plugins-config.kdl",
|
|
||||||
env!("CARGO_MANIFEST_DIR")
|
|
||||||
)));
|
|
||||||
cli_args.layout = Some(PathBuf::from(format!(
|
|
||||||
"{}/src/test-fixtures/layout-with-plugins-config.kdl",
|
|
||||||
env!("CARGO_MANIFEST_DIR")
|
|
||||||
)));
|
|
||||||
let (config, _layout, _options, _, _) = Setup::from_cli_args(&cli_args).unwrap();
|
|
||||||
assert_snapshot!(format!("{:#?}", config));
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn layout_themes_override_config_themes() {
|
fn layout_themes_override_config_themes() {
|
||||||
let mut cli_args = CliArgs::default();
|
let mut cli_args = CliArgs::default();
|
||||||
cli_args.config = Some(PathBuf::from(format!(
|
cli_args.config = Some(PathBuf::from(format!(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 672
|
assertion_line: 699
|
||||||
expression: "format!(\"{:#?}\", layout)"
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
---
|
---
|
||||||
Layout {
|
Layout {
|
||||||
|
|
@ -23,17 +23,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -73,17 +73,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -133,17 +133,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -235,17 +235,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -288,17 +288,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -455,17 +455,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -508,17 +508,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -756,17 +756,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -816,17 +816,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -899,17 +899,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -952,17 +952,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -1119,17 +1119,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -1172,17 +1172,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -1420,17 +1420,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -1480,17 +1480,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "tab-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"tab-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
@ -1582,17 +1582,17 @@ Layout {
|
||||||
),
|
),
|
||||||
run: Some(
|
run: Some(
|
||||||
Plugin(
|
Plugin(
|
||||||
RunPlugin {
|
Alias(
|
||||||
_allow_exec_host_cmd: false,
|
PluginAlias {
|
||||||
location: Zellij(
|
name: "status-bar",
|
||||||
PluginTag(
|
configuration: Some(
|
||||||
"status-bar",
|
PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
run_plugin: None,
|
||||||
configuration: PluginUserConfiguration(
|
},
|
||||||
{},
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
borderless: true,
|
borderless: true,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 671
|
assertion_line: 698
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -2655,17 +2655,19 @@ Config {
|
||||||
'w',
|
'w',
|
||||||
): [
|
): [
|
||||||
LaunchOrFocusPlugin(
|
LaunchOrFocusPlugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"session-manager",
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
@ -3831,91 +3833,87 @@ Config {
|
||||||
serialization_interval: None,
|
serialization_interval: None,
|
||||||
},
|
},
|
||||||
themes: {},
|
themes: {},
|
||||||
plugins: {
|
plugins: PluginAliases {
|
||||||
PluginTag(
|
aliases: {
|
||||||
"compact-bar",
|
"compact-bar": RunPlugin {
|
||||||
): PluginConfig {
|
_allow_exec_host_cmd: false,
|
||||||
path: "compact-bar",
|
location: Zellij(
|
||||||
run: Pane(
|
PluginTag(
|
||||||
None,
|
"compact-bar",
|
||||||
),
|
),
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"compact-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "session-manager",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"filepicker": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"strider",
|
||||||
"status-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "status-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"status-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "strider",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"session-manager": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"session-manager",
|
||||||
"tab-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "tab-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"tab-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
|
"status-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"strider": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"strider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"tab-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"welcome-screen": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{
|
||||||
|
"welcome_screen": "true",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: UiConfig {
|
ui: UiConfig {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 729
|
assertion_line: 756
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -2655,17 +2655,19 @@ Config {
|
||||||
'w',
|
'w',
|
||||||
): [
|
): [
|
||||||
LaunchOrFocusPlugin(
|
LaunchOrFocusPlugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"session-manager",
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
@ -3831,91 +3833,87 @@ Config {
|
||||||
serialization_interval: None,
|
serialization_interval: None,
|
||||||
},
|
},
|
||||||
themes: {},
|
themes: {},
|
||||||
plugins: {
|
plugins: PluginAliases {
|
||||||
PluginTag(
|
aliases: {
|
||||||
"compact-bar",
|
"compact-bar": RunPlugin {
|
||||||
): PluginConfig {
|
_allow_exec_host_cmd: false,
|
||||||
path: "compact-bar",
|
location: Zellij(
|
||||||
run: Pane(
|
PluginTag(
|
||||||
None,
|
"compact-bar",
|
||||||
),
|
),
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"compact-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "session-manager",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"filepicker": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"strider",
|
||||||
"status-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "status-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"status-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "strider",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"session-manager": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"session-manager",
|
||||||
"tab-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "tab-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"tab-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
|
"status-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"strider": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"strider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"tab-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"welcome-screen": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{
|
||||||
|
"welcome_screen": "true",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: UiConfig {
|
ui: UiConfig {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 785
|
assertion_line: 813
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -89,91 +89,87 @@ Config {
|
||||||
serialization_interval: None,
|
serialization_interval: None,
|
||||||
},
|
},
|
||||||
themes: {},
|
themes: {},
|
||||||
plugins: {
|
plugins: PluginAliases {
|
||||||
PluginTag(
|
aliases: {
|
||||||
"compact-bar",
|
"compact-bar": RunPlugin {
|
||||||
): PluginConfig {
|
_allow_exec_host_cmd: false,
|
||||||
path: "compact-bar",
|
location: Zellij(
|
||||||
run: Pane(
|
PluginTag(
|
||||||
None,
|
"compact-bar",
|
||||||
),
|
),
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"compact-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "session-manager",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"filepicker": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"strider",
|
||||||
"status-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "status-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"status-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "strider",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"session-manager": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"session-manager",
|
||||||
"tab-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "tab-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"tab-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
|
"status-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"strider": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"strider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"tab-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"welcome-screen": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{
|
||||||
|
"welcome_screen": "true",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: UiConfig {
|
ui: UiConfig {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 757
|
assertion_line: 784
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -2655,17 +2655,19 @@ Config {
|
||||||
'w',
|
'w',
|
||||||
): [
|
): [
|
||||||
LaunchOrFocusPlugin(
|
LaunchOrFocusPlugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"session-manager",
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 771
|
assertion_line: 799
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -2655,17 +2655,19 @@ Config {
|
||||||
'w',
|
'w',
|
||||||
): [
|
): [
|
||||||
LaunchOrFocusPlugin(
|
LaunchOrFocusPlugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"session-manager",
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
@ -4135,91 +4137,87 @@ Config {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: PluginAliases {
|
||||||
PluginTag(
|
aliases: {
|
||||||
"compact-bar",
|
"compact-bar": RunPlugin {
|
||||||
): PluginConfig {
|
_allow_exec_host_cmd: false,
|
||||||
path: "compact-bar",
|
location: Zellij(
|
||||||
run: Pane(
|
PluginTag(
|
||||||
None,
|
"compact-bar",
|
||||||
),
|
),
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"compact-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "session-manager",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"filepicker": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"strider",
|
||||||
"status-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "status-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"status-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "strider",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"session-manager": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"session-manager",
|
||||||
"tab-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "tab-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"tab-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
|
"status-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"strider": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"strider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"tab-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"welcome-screen": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{
|
||||||
|
"welcome_screen": "true",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: UiConfig {
|
ui: UiConfig {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-utils/src/setup.rs
|
source: zellij-utils/src/setup.rs
|
||||||
assertion_line: 743
|
assertion_line: 770
|
||||||
expression: "format!(\"{:#?}\", config)"
|
expression: "format!(\"{:#?}\", config)"
|
||||||
---
|
---
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -2655,17 +2655,19 @@ Config {
|
||||||
'w',
|
'w',
|
||||||
): [
|
): [
|
||||||
LaunchOrFocusPlugin(
|
LaunchOrFocusPlugin(
|
||||||
RunPlugin {
|
RunPlugin(
|
||||||
_allow_exec_host_cmd: false,
|
RunPlugin {
|
||||||
location: Zellij(
|
_allow_exec_host_cmd: false,
|
||||||
PluginTag(
|
location: Zellij(
|
||||||
"session-manager",
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
},
|
),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
@ -3831,91 +3833,87 @@ Config {
|
||||||
serialization_interval: None,
|
serialization_interval: None,
|
||||||
},
|
},
|
||||||
themes: {},
|
themes: {},
|
||||||
plugins: {
|
plugins: PluginAliases {
|
||||||
PluginTag(
|
aliases: {
|
||||||
"compact-bar",
|
"compact-bar": RunPlugin {
|
||||||
): PluginConfig {
|
_allow_exec_host_cmd: false,
|
||||||
path: "compact-bar",
|
location: Zellij(
|
||||||
run: Pane(
|
PluginTag(
|
||||||
None,
|
"compact-bar",
|
||||||
),
|
),
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"compact-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "session-manager",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"session-manager",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"filepicker": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"strider",
|
||||||
"status-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "status-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"status-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
): PluginConfig {
|
|
||||||
path: "strider",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"strider",
|
|
||||||
),
|
),
|
||||||
),
|
},
|
||||||
userspace_configuration: PluginUserConfiguration(
|
"session-manager": RunPlugin {
|
||||||
{},
|
_allow_exec_host_cmd: false,
|
||||||
),
|
location: Zellij(
|
||||||
},
|
PluginTag(
|
||||||
PluginTag(
|
"session-manager",
|
||||||
"tab-bar",
|
),
|
||||||
): PluginConfig {
|
|
||||||
path: "tab-bar",
|
|
||||||
run: Pane(
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_allow_exec_host_cmd: false,
|
|
||||||
location: Zellij(
|
|
||||||
PluginTag(
|
|
||||||
"tab-bar",
|
|
||||||
),
|
),
|
||||||
),
|
configuration: PluginUserConfiguration(
|
||||||
userspace_configuration: PluginUserConfiguration(
|
{},
|
||||||
{},
|
),
|
||||||
),
|
},
|
||||||
|
"status-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"status-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"strider": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"strider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"tab-bar": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"tab-bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"welcome-screen": RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: Zellij(
|
||||||
|
PluginTag(
|
||||||
|
"session-manager",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
configuration: PluginUserConfiguration(
|
||||||
|
{
|
||||||
|
"welcome_screen": "true",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: UiConfig {
|
ui: UiConfig {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue