aboutsummaryrefslogtreecommitdiffstats
path: root/default-plugins/strider
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2024-02-26 15:30:15 +0100
committerGitHub <noreply@github.com>2024-02-26 15:30:15 +0100
commit21273ac95a2fed6b07d8550fe2d4f65993be7037 (patch)
treef5a7aa488ece8f21c17350bb3ec14ceaf15f60a7 /default-plugins/strider
parentdocs(changelog): add moving tab (diff)
downloadsl0ppij-21273ac95a2fed6b07d8550fe2d4f65993be7037.tar.gz
sl0ppij-21273ac95a2fed6b07d8550fe2d4f65993be7037.tar.xz
sl0ppij-21273ac95a2fed6b07d8550fe2d4f65993be7037.zip
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
Diffstat (limited to 'default-plugins/strider')
-rw-r--r--default-plugins/strider/src/main.rs138
-rw-r--r--default-plugins/strider/src/search/controls_line.rs353
-rw-r--r--default-plugins/strider/src/search/mod.rs317
-rw-r--r--default-plugins/strider/src/search/search_results.rs308
-rw-r--r--default-plugins/strider/src/search/search_state.rs264
-rw-r--r--default-plugins/strider/src/search/selection_controls_area.rs61
-rw-r--r--default-plugins/strider/src/search/ui.rs120
-rw-r--r--default-plugins/strider/src/state.rs22
8 files changed, 0 insertions, 1583 deletions
diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs
index 598bf61d..2e06240a 100644
--- a/default-plugins/strider/src/main.rs
+++ b/default-plugins/strider/src/main.rs
@@ -1,49 +1,22 @@
-mod search;
mod state;
use colored::*;
-use search::{FileContentsWorker, FileNameWorker, MessageToSearch, ResultsOfSearch};
-use serde::{Deserialize, Serialize};
-use serde_json;
use state::{refresh_directory, FsEntry, State};
use std::collections::BTreeMap;
use std::{cmp::min, time::Instant};
use zellij_tile::prelude::*;
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 {
fn load(&mut self, _configuration: BTreeMap<String, String>) {
refresh_directory(self);
- self.search_state.loading = true;
subscribe(&[
EventType::Key,
EventType::Mouse,
EventType::CustomMessage,
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 {
@@ -55,58 +28,8 @@ impl ZellijPlugin for State {
};
self.ev_history.push_back((event.clone(), Instant::now()));
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 {
- 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 => {
- self.stop_typing_search_term();
hide_self();
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);
},
@@ -246,12 +121,6 @@ impl ZellijPlugin for State {
}
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 {
if self.selected() < self.scroll() {
*self.scroll_mut() = self.selected();
@@ -288,10 +157,3 @@ impl ZellijPlugin for State {
}
}
}
-
-#[derive(Serialize, Deserialize)]
-pub enum MessageToPlugin {
- UpdateFileNameSearchResults,
- UpdateFileContentsSearchResults,
- DoneScanningFolder,
-}
diff --git a/default-plugins/strider/src/search/controls_line.rs b/default-plugins/strider/src/search/controls_line.rs
deleted file mode 100644
index a75715ef..00000000
--- a/default-plugins/strider/src/search/controls_line.rs
+++ /dev/null
@@ -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
- }
-}
diff --git a/default-plugins/strider/src/search/mod.rs b/default-plugins/strider/src/search/mod.rs
deleted file mode 100644
index 6ffa60cb..00000000
--- a/default-plugins/strider/src/search/mod.rs
+++ /dev/null
@@ -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(&current_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
- }
-}
diff --git a/default-plugins/strider/src/search/search_results.rs b/default-plugins/strider/src/search/search_results.rs
deleted file mode 100644
index b76200ae..00000000
--- a/default-plugins/strider/src/search/search_results.rs
+++ /dev/null
@@ -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))
- }
- }
-}
diff --git a/default-plugins/strider/src/search/search_state.rs b/default-plugins/strider/src/search/search_state.rs
deleted file mode 100644
index 60d03941..00000000
--- a/default-plugins/strider/src/search/search_state.rs
+++ /dev/null
@@ -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(&currently_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
- }
-}
diff --git a/default-plugins/strider/src/search/selection_controls_area.rs b/default-plugins/strider/src/search/selection_controls_area.rs
deleted file mode 100644
index 0805e1e4..00000000
--- a/default-plugins/strider/src/search/selection_controls_area.rs
+++ /dev/null
@@ -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)
- }
-}
diff --git a/default-plugins/strider/src/search/ui.rs b/default-plugins/strider/src/search/ui.rs
deleted file mode 100644
index 5ee5a3e8..00000000
--- a/default-plugins/strider/src/search/ui.rs
+++ /dev/null
@@ -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)
-}
diff --git a/default-plugins/strider/src/state.rs b/default-plugins/strider/src/state.rs
index 67e9b891..be4ede4b 100644
--- a/default-plugins/strider/src/state.rs
+++ b/default-plugins/strider/src/state.rs
@@ -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 std::{
collections::{HashMap, VecDeque},
@@ -11,7 +8,6 @@ use std::{
use zellij_tile::prelude::*;
pub const ROOT: &str = "/host";
-pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term";
#[derive(Default)]
pub struct State {
@@ -20,30 +16,12 @@ pub struct State {
pub cursor_hist: HashMap<PathBuf, (usize, usize)>,
pub hide_hidden_files: bool,
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_animation_offset: u8,
- pub typing_search_term: bool,
- pub selected_search_result: usize,
- pub processed_search_index: usize,
pub should_open_floating: bool,
- pub search_filter: SearchType,
}
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 {
&mut self.cursor_hist.entry(self.path.clone()).or_default().0
}