add local searching

This commit is contained in:
Crispy 2023-08-17 13:00:30 +02:00
parent cc0dfa4c06
commit a553050f91

View file

@ -1,6 +1,7 @@
use std::fs::{read_link, DirEntry}; use std::fs::{read_link, DirEntry};
use std::path::PathBuf; use std::path::PathBuf;
use eframe::egui::{Id, Key};
use eframe::{egui, Frame, NativeOptions}; use eframe::{egui, Frame, NativeOptions};
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
@ -14,11 +15,14 @@ fn main() {
} }
struct FileGui { struct FileGui {
home: String,
current_dir: PathBuf, current_dir: PathBuf,
loaded_dir: PathBuf, loaded_dir: PathBuf,
path_input: String,
home: String,
entries: Vec<Entry>, entries: Vec<Entry>,
path_input: String,
path_input_id: Id,
search_input: String,
search_input_id: Id,
} }
struct Entry { struct Entry {
@ -42,11 +46,14 @@ impl FileGui {
let home = std::env::var("HOME").unwrap(); let home = std::env::var("HOME").unwrap();
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();
let mut s = Self { let mut s = Self {
home,
current_dir, current_dir,
loaded_dir: PathBuf::new(), loaded_dir: PathBuf::new(),
path_input: String::new(),
home,
entries: Vec::new(), entries: Vec::new(),
path_input: String::new(),
path_input_id: Id::null(),
search_input: String::new(),
search_input_id: Id::null(),
}; };
s.override_input(); s.override_input();
s.refresh_entries(); s.refresh_entries();
@ -62,7 +69,7 @@ impl FileGui {
.replace(&self.home, "~"); .replace(&self.home, "~");
} }
fn enter_input(&mut self) { fn apply_input(&mut self) {
let path = self.path_input.replace('~', &self.home).replace('\\', "/"); let path = self.path_input.replace('~', &self.home).replace('\\', "/");
self.current_dir = PathBuf::from(path); self.current_dir = PathBuf::from(path);
} }
@ -80,6 +87,7 @@ impl FileGui {
.unwrap() .unwrap()
.filter_map(|dir_entry| dir_entry.ok().map(Entry::new)) .filter_map(|dir_entry| dir_entry.ok().map(Entry::new))
.flatten() .flatten()
.filter(|e| e.name.contains(&self.search_input))
.collect(); .collect();
self.entries self.entries
.sort_by(|a, b| b.is_dir().cmp(&a.is_dir()).then(a.name.cmp(&b.name))); .sort_by(|a, b| b.is_dir().cmp(&a.is_dir()).then(a.name.cmp(&b.name)));
@ -110,7 +118,16 @@ impl FileGui {
} }
impl eframe::App for FileGui { impl eframe::App for FileGui {
fn update(&mut self, ctx: &egui::Context, _frame: &mut Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
if ctx.input(|i| i.key_pressed(Key::F) && i.modifiers.ctrl) {
ctx.memory_mut(|m| m.request_focus(self.search_input_id));
}
if ctx.input(|i| i.key_pressed(Key::L) && i.modifiers.ctrl) {
ctx.memory_mut(|m| m.request_focus(self.path_input_id));
}
if ctx.input(|i| i.key_pressed(Key::R) && i.modifiers.ctrl) {
self.refresh_entries();
}
egui::TopBottomPanel::top("top_bar").show(ctx, |ui| { egui::TopBottomPanel::top("top_bar").show(ctx, |ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
if ui.button("").clicked() { if ui.button("").clicked() {
@ -120,14 +137,21 @@ impl eframe::App for FileGui {
self.refresh_entries(); self.refresh_entries();
} }
let path_bar = ui.text_edit_singleline(&mut self.path_input); let path_bar = ui.text_edit_singleline(&mut self.path_input);
self.path_input_id = path_bar.id;
if path_bar.lost_focus() { if path_bar.lost_focus() {
if ui.input(|i| i.key_pressed(egui::Key::Enter)) { if ui.input(|i| i.key_pressed(egui::Key::Enter)) {
self.enter_input(); self.apply_input();
self.refresh_entries(); self.refresh_entries();
} else if ui.input(|i| i.key_pressed(egui::Key::Escape)) { } else if ui.input(|i| i.key_pressed(egui::Key::Escape)) {
self.override_input(); self.override_input();
} }
} }
let filter_input = ui.text_edit_singleline(&mut self.search_input);
self.search_input_id = filter_input.id;
if filter_input.changed() {
self.refresh_entries();
}
if let Some(filename) = self.loaded_dir.file_name() { if let Some(filename) = self.loaded_dir.file_name() {
ui.label(filename.to_str().unwrap()); ui.label(filename.to_str().unwrap());
} }
@ -136,7 +160,7 @@ impl eframe::App for FileGui {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
TableBuilder::new(ui) TableBuilder::new(ui)
.striped(true) .striped(true)
.max_scroll_height(1200.0) .max_scroll_height(frame.info().window_info.size.y)
.column(Column::auto()) .column(Column::auto())
.column(Column::remainder()) .column(Column::remainder())
.body(|body| { .body(|body| {
@ -144,14 +168,7 @@ impl eframe::App for FileGui {
body.rows(18.0, self.entries.len(), |row_index, mut row| { body.rows(18.0, self.entries.len(), |row_index, mut row| {
let entry = &self.entries[row_index]; let entry = &self.entries[row_index];
row.col(|ui| { row.col(|ui| {
ui.label(match entry.filetype { ui.label(entry.filetype.icon());
FileType::Dir => "🗁",
FileType::File => "🗋",
FileType::SymLinkFile => "",
FileType::SymLinkDir => "",
FileType::SymLinkMissing => "",
FileType::Unknown => "",
});
}); });
row.col(|ui| { row.col(|ui| {
if ui.button(&entry.name).clicked() { if ui.button(&entry.name).clicked() {
@ -200,3 +217,16 @@ impl Entry {
self.filetype == FileType::Dir || self.filetype == FileType::SymLinkDir self.filetype == FileType::Dir || self.filetype == FileType::SymLinkDir
} }
} }
impl FileType {
fn icon(&self) -> &str {
match self {
FileType::Dir => "🗁",
FileType::File => "🗋",
FileType::SymLinkFile => "",
FileType::SymLinkDir => "",
FileType::SymLinkMissing => "",
FileType::Unknown => "",
}
}
}