mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
speedup: make hunter handle directories with 1M files
This commit is contained in:
parent
cd773727eb
commit
8fc070b71b
@ -87,9 +87,12 @@ pub struct FileBrowser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tabbable for TabView<FileBrowser> {
|
impl Tabbable for TabView<FileBrowser> {
|
||||||
fn new_tab(&mut self) -> HResult<()> {
|
type Tab = FileBrowser;
|
||||||
let cur_tab = self.active_tab_();
|
|
||||||
|
|
||||||
|
fn new_tab(&mut self) -> HResult<()> {
|
||||||
|
self.active_tab_mut().save_tab_settings().log();
|
||||||
|
|
||||||
|
let cur_tab = self.active_tab();
|
||||||
let settings = cur_tab.fs_cache.tab_settings.read()?.clone();
|
let settings = cur_tab.fs_cache.tab_settings.read()?.clone();
|
||||||
let cache = cur_tab.fs_cache.new_client(settings).ok();
|
let cache = cur_tab.fs_cache.new_client(settings).ok();
|
||||||
|
|
||||||
@ -136,11 +139,11 @@ impl Tabbable for TabView<FileBrowser> {
|
|||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_tab(& self) -> & dyn Widget {
|
fn active_tab(& self) -> &Self::Tab {
|
||||||
self.active_tab_()
|
self.active_tab_()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_tab_mut(&mut self) -> &mut dyn Widget {
|
fn active_tab_mut(&mut self) -> &mut Self::Tab {
|
||||||
self.active_tab_mut_()
|
self.active_tab_mut_()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +277,7 @@ impl FileBrowser {
|
|||||||
|
|
||||||
let mut list = ListView::new(&core_m.clone(),
|
let mut list = ListView::new(&core_m.clone(),
|
||||||
files);
|
files);
|
||||||
|
|
||||||
selected_file.map(|f| list.select_file(&f));
|
selected_file.map(|f| list.select_file(&f));
|
||||||
|
|
||||||
|
|
||||||
@ -342,8 +346,7 @@ impl FileBrowser {
|
|||||||
bookmarks: Arc::new(Mutex::new(bookmarks)),
|
bookmarks: Arc::new(Mutex::new(bookmarks)),
|
||||||
log_view: Arc::new(Mutex::new(log_view)),
|
log_view: Arc::new(Mutex::new(log_view)),
|
||||||
fs_cache: fs_cache,
|
fs_cache: fs_cache,
|
||||||
fs_stat: Arc::new(RwLock::new(fs_stat))
|
fs_stat: Arc::new(RwLock::new(fs_stat)) })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter_dir(&mut self) -> HResult<()> {
|
pub fn enter_dir(&mut self) -> HResult<()> {
|
||||||
@ -486,8 +489,6 @@ impl FileBrowser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
|
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
|
||||||
self.save_tab_settings().log();
|
|
||||||
|
|
||||||
let dir = dir.clone();
|
let dir = dir.clone();
|
||||||
let cache = self.fs_cache.clone();
|
let cache = self.fs_cache.clone();
|
||||||
|
|
||||||
@ -730,6 +731,12 @@ impl FileBrowser {
|
|||||||
Ok(&self.left_widget()?.content)
|
Ok(&self.left_widget()?.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn save_selected_file(&self) -> HResult<()> {
|
||||||
|
self.selected_file()
|
||||||
|
.map(|f| self.fs_cache.set_selection(self.cwd.clone(),
|
||||||
|
f))?
|
||||||
|
}
|
||||||
|
|
||||||
pub fn save_tab_settings(&mut self) -> HResult<()> {
|
pub fn save_tab_settings(&mut self) -> HResult<()> {
|
||||||
if !self.main_async_widget_mut()?.ready() { return Ok(()) }
|
if !self.main_async_widget_mut()?.ready() { return Ok(()) }
|
||||||
|
|
||||||
@ -1144,11 +1151,8 @@ impl FileBrowser {
|
|||||||
pub fn get_footer(&self) -> HResult<String> {
|
pub fn get_footer(&self) -> HResult<String> {
|
||||||
let xsize = self.get_coordinates()?.xsize();
|
let xsize = self.get_coordinates()?.xsize();
|
||||||
let ypos = self.get_coordinates()?.position().y();
|
let ypos = self.get_coordinates()?.position().y();
|
||||||
let pos = self.main_widget()?.get_selection();
|
let file = self.selected_file()?;
|
||||||
let file = self.main_widget()?
|
|
||||||
.content
|
|
||||||
.iter_files()
|
|
||||||
.nth(pos)?;
|
|
||||||
|
|
||||||
let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into());
|
let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into());
|
||||||
let user = file.pretty_user().unwrap_or("NOUSER".into());
|
let user = file.pretty_user().unwrap_or("NOUSER".into());
|
||||||
@ -1262,7 +1266,6 @@ impl Widget for FileBrowser {
|
|||||||
self.set_cwd().log();
|
self.set_cwd().log();
|
||||||
if !self.columns.zoom_active { self.update_preview().log(); }
|
if !self.columns.zoom_active { self.update_preview().log(); }
|
||||||
self.columns.refresh().log();
|
self.columns.refresh().log();
|
||||||
self.save_tab_settings().log();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,6 +1277,9 @@ impl Widget for FileBrowser {
|
|||||||
match self.do_key(key) {
|
match self.do_key(key) {
|
||||||
Err(HError::WidgetUndefinedKeyError{..}) => {
|
Err(HError::WidgetUndefinedKeyError{..}) => {
|
||||||
match self.main_widget_mut()?.on_key(key) {
|
match self.main_widget_mut()?.on_key(key) {
|
||||||
|
Ok(_) => {
|
||||||
|
self.save_tab_settings()?;
|
||||||
|
}
|
||||||
Err(HError::WidgetUndefinedKeyError{..}) => {
|
Err(HError::WidgetUndefinedKeyError{..}) => {
|
||||||
self.preview_widget_mut()?.on_key(key)?
|
self.preview_widget_mut()?.on_key(key)?
|
||||||
}
|
}
|
||||||
@ -1303,7 +1309,11 @@ impl Acting for FileBrowser {
|
|||||||
match movement {
|
match movement {
|
||||||
Left => self.go_back(),
|
Left => self.go_back(),
|
||||||
Right => self.enter_dir(),
|
Right => self.enter_dir(),
|
||||||
_ => self.main_widget_mut()?.movement(movement)
|
_ => {
|
||||||
|
self.main_widget_mut()?.movement(movement)?;
|
||||||
|
self.save_selected_file()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/files.rs
14
src/files.rs
@ -401,7 +401,7 @@ impl Files {
|
|||||||
!(filter.is_some() &&
|
!(filter.is_some() &&
|
||||||
!f.name.contains(filter.as_ref().unwrap())) &&
|
!f.name.contains(filter.as_ref().unwrap())) &&
|
||||||
(!filter_selected || f.selected))
|
(!filter_selected || f.selected))
|
||||||
.filter(move |f| !(!show_hidden && f.name.starts_with(".")))
|
.filter(move |f| !(!show_hidden && f.hidden))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_files_mut(&mut self) -> impl Iterator<Item=&mut File> {
|
pub fn iter_files_mut(&mut self) -> impl Iterator<Item=&mut File> {
|
||||||
@ -416,7 +416,7 @@ impl Files {
|
|||||||
!(filter.is_some() &&
|
!(filter.is_some() &&
|
||||||
!f.name.contains(filter.as_ref().unwrap())) &&
|
!f.name.contains(filter.as_ref().unwrap())) &&
|
||||||
(!filter_selected || f.selected))
|
(!filter_selected || f.selected))
|
||||||
.filter(move |f| !(!show_hidden && f.name.starts_with(".")))
|
.filter(move |f| !(!show_hidden && f.hidden))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(trivial_bounds)]
|
#[allow(trivial_bounds)]
|
||||||
@ -750,12 +750,18 @@ impl std::fmt::Debug for File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for File {
|
||||||
|
fn default() -> File {
|
||||||
|
File::new_placeholder(Path::new("")).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
|
pub hidden: bool,
|
||||||
pub kind: Kind,
|
pub kind: Kind,
|
||||||
pub dirsize: Option<Async<usize>>,
|
pub dirsize: Option<Async<usize>>,
|
||||||
pub target: Option<PathBuf>,
|
pub target: Option<PathBuf>,
|
||||||
@ -772,6 +778,7 @@ impl File {
|
|||||||
name: &str,
|
name: &str,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
||||||
|
let hidden = name.starts_with(".");
|
||||||
let tag = check_tag(&path).ok();
|
let tag = check_tag(&path).ok();
|
||||||
let meta = File::make_async_meta(&path, dirty_meta.clone(), None);
|
let meta = File::make_async_meta(&path, dirty_meta.clone(), None);
|
||||||
let dirsize = if path.is_dir() {
|
let dirsize = if path.is_dir() {
|
||||||
@ -780,6 +787,7 @@ impl File {
|
|||||||
|
|
||||||
File {
|
File {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
hidden: hidden,
|
||||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||||
path: path,
|
path: path,
|
||||||
dirsize: dirsize,
|
dirsize: dirsize,
|
||||||
@ -797,6 +805,7 @@ impl File {
|
|||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
dirty_meta: Option<AsyncDirtyBit>,
|
dirty_meta: Option<AsyncDirtyBit>,
|
||||||
stale: Stale) -> File {
|
stale: Stale) -> File {
|
||||||
|
let hidden = name.starts_with(".");
|
||||||
let tag = check_tag(&path).ok();
|
let tag = check_tag(&path).ok();
|
||||||
let meta = File::make_async_meta(&path,
|
let meta = File::make_async_meta(&path,
|
||||||
dirty_meta.clone(),
|
dirty_meta.clone(),
|
||||||
@ -809,6 +818,7 @@ impl File {
|
|||||||
|
|
||||||
File {
|
File {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
hidden: hidden,
|
||||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||||
path: path,
|
path: path,
|
||||||
dirsize: dirsize,
|
dirsize: dirsize,
|
||||||
|
@ -326,6 +326,7 @@ where
|
|||||||
ListView<Vec<F>>: FoldableWidgetExt,
|
ListView<Vec<F>>: FoldableWidgetExt,
|
||||||
Bindings<<ListView<Vec<F>> as ActingExt>::Action>: Default
|
Bindings<<ListView<Vec<F>> as ActingExt>::Action>: Default
|
||||||
{
|
{
|
||||||
|
type Item = ();
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.content.iter().map(|f| f.lines()).sum()
|
self.content.iter().map(|f| f.lines()).sum()
|
||||||
|
@ -191,7 +191,22 @@ impl FsCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_selection(&self, dir: &File) -> HResult<File> {
|
pub fn get_selection(&self, dir: &File) -> HResult<File> {
|
||||||
Ok(self.tab_settings.read()?.get(&dir).as_ref()?.selection.as_ref()?.clone())
|
Ok(self.tab_settings
|
||||||
|
.read()?
|
||||||
|
.get(&dir)
|
||||||
|
.as_ref()?
|
||||||
|
.selection
|
||||||
|
.as_ref()?
|
||||||
|
.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_selection(&self, dir: File, selection: File) -> HResult<()> {
|
||||||
|
self.tab_settings.write()
|
||||||
|
.map(|mut settings| {
|
||||||
|
let setting = settings.entry(dir).or_insert(TabSettings::new());
|
||||||
|
setting.selection = Some(selection);
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_settings(&self, files: &Files, selection: Option<File>) -> HResult<()> {
|
pub fn save_settings(&self, files: &Files, selection: Option<File>) -> HResult<()> {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ use crate::widget::{Widget, WidgetCore};
|
|||||||
use crate::dirty::Dirtyable;
|
use crate::dirty::Dirtyable;
|
||||||
|
|
||||||
pub trait Listable {
|
pub trait Listable {
|
||||||
|
type Item: Debug + PartialEq + Default;
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
fn render(&self) -> Vec<String>;
|
fn render(&self) -> Vec<String>;
|
||||||
fn render_header(&self) -> HResult<String> { Ok("".to_string()) }
|
fn render_header(&self) -> HResult<String> { Ok("".to_string()) }
|
||||||
@ -32,6 +34,8 @@ impl Acting for ListView<Files> {
|
|||||||
fn movement(&mut self, movement: &Movement) -> HResult<()> {
|
fn movement(&mut self, movement: &Movement) -> HResult<()> {
|
||||||
use Movement::*;
|
use Movement::*;
|
||||||
|
|
||||||
|
let pos = self.get_selection();
|
||||||
|
|
||||||
match movement {
|
match movement {
|
||||||
Up(n) => { for _ in 0..*n { self.move_up(); }; self.refresh()?; }
|
Up(n) => { for _ in 0..*n { self.move_up(); }; self.refresh()?; }
|
||||||
Down(n) => { for _ in 0..*n { self.move_down(); }; self.refresh()?; }
|
Down(n) => { for _ in 0..*n { self.move_down(); }; self.refresh()?; }
|
||||||
@ -42,12 +46,18 @@ impl Acting for ListView<Files> {
|
|||||||
Left | Right => {}
|
Left | Right => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pos != self.get_selection() {
|
||||||
|
self.update_selected_file();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_action(&mut self, action: &Self::Action) -> HResult<()> {
|
fn do_action(&mut self, action: &Self::Action) -> HResult<()> {
|
||||||
use FileListAction::*;
|
use FileListAction::*;
|
||||||
|
|
||||||
|
let pos = self.get_selection();
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Search => self.search_file()?,
|
Search => self.search_file()?,
|
||||||
SearchNext => self.search_next()?,
|
SearchNext => self.search_next()?,
|
||||||
@ -65,11 +75,18 @@ impl Acting for ListView<Files> {
|
|||||||
ToPrevMtime => self.select_prev_mtime(),
|
ToPrevMtime => self.select_prev_mtime(),
|
||||||
ToggleDirsFirst => self.toggle_dirs_first(),
|
ToggleDirsFirst => self.toggle_dirs_first(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pos != self.get_selection() {
|
||||||
|
self.update_selected_file();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Listable for ListView<Files> {
|
impl Listable for ListView<Files> {
|
||||||
|
type Item = File;
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.content.len()
|
self.content.len()
|
||||||
}
|
}
|
||||||
@ -81,6 +98,12 @@ impl Listable for ListView<Files> {
|
|||||||
fn on_new(&mut self) -> HResult<()> {
|
fn on_new(&mut self) -> HResult<()> {
|
||||||
let show_hidden = self.core.config().show_hidden();
|
let show_hidden = self.core.config().show_hidden();
|
||||||
self.content.show_hidden = show_hidden;
|
self.content.show_hidden = show_hidden;
|
||||||
|
let file = self.content
|
||||||
|
.iter_files()
|
||||||
|
.nth(0)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
|
self.current_item = Some(file);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,9 +140,12 @@ impl Listable for ListView<Files> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct ListView<T> where ListView<T>: Listable
|
pub struct ListView<T>
|
||||||
|
where
|
||||||
|
ListView<T>: Listable
|
||||||
{
|
{
|
||||||
pub content: T,
|
pub content: T,
|
||||||
|
pub current_item: Option<<ListView<T> as Listable>::Item>,
|
||||||
pub lines: usize,
|
pub lines: usize,
|
||||||
selection: usize,
|
selection: usize,
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
@ -137,6 +163,7 @@ where
|
|||||||
pub fn new(core: &WidgetCore, content: T) -> ListView<T> {
|
pub fn new(core: &WidgetCore, content: T) -> ListView<T> {
|
||||||
let mut view = ListView::<T> {
|
let mut view = ListView::<T> {
|
||||||
content: content,
|
content: content,
|
||||||
|
current_item: None,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
selection: 0,
|
selection: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
@ -222,13 +249,19 @@ where
|
|||||||
|
|
||||||
impl ListView<Files>
|
impl ListView<Files>
|
||||||
{
|
{
|
||||||
pub fn selected_file(&self) -> &File {
|
pub fn update_selected_file(&mut self) {
|
||||||
let selection = self.selection;
|
let pos = self.selection;
|
||||||
|
|
||||||
&self.content
|
let file = self.content
|
||||||
.iter_files()
|
.iter_files()
|
||||||
.nth(selection)
|
.nth(pos)
|
||||||
.unwrap_or(&self.content.directory)
|
.map(|f| f.clone());
|
||||||
|
|
||||||
|
self.current_item = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selected_file(&self) -> &File {
|
||||||
|
self.current_item.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selected_file_mut(&mut self) -> &mut File {
|
pub fn selected_file_mut(&mut self) -> &mut File {
|
||||||
@ -288,6 +321,8 @@ impl ListView<Files>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_file(&mut self, file: &File) {
|
pub fn select_file(&mut self, file: &File) {
|
||||||
|
self.current_item = Some(file.clone());
|
||||||
|
|
||||||
let pos = self
|
let pos = self
|
||||||
.content
|
.content
|
||||||
.iter_files()
|
.iter_files()
|
||||||
@ -375,6 +410,8 @@ impl ListView<Files>
|
|||||||
self.content.toggle_hidden();
|
self.content.toggle_hidden();
|
||||||
self.select_file(&file);
|
self.select_file(&file);
|
||||||
self.refresh().log();
|
self.refresh().log();
|
||||||
|
self.core.show_status(&format!("Showing hidden files: {}",
|
||||||
|
self.content.show_hidden)).log();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_dirs_first(&mut self) {
|
fn toggle_dirs_first(&mut self) {
|
||||||
@ -390,9 +427,13 @@ impl ListView<Files>
|
|||||||
fn multi_select_file(&mut self) {
|
fn multi_select_file(&mut self) {
|
||||||
self.selected_file_mut().toggle_selection();
|
self.selected_file_mut().toggle_selection();
|
||||||
|
|
||||||
|
// Create mutable clone to render change
|
||||||
|
let mut file = self.clone_selected_file();
|
||||||
|
file.toggle_selection();
|
||||||
|
|
||||||
if !self.content.filter_selected {
|
if !self.content.filter_selected {
|
||||||
let selection = self.get_selection();
|
let selection = self.get_selection();
|
||||||
let line = self.render_line(self.selected_file());
|
let line = self.render_line(&file);
|
||||||
self.buffer[selection] = line;
|
self.buffer[selection] = line;
|
||||||
|
|
||||||
self.move_down();
|
self.move_down();
|
||||||
@ -432,8 +473,12 @@ impl ListView<Files>
|
|||||||
fn toggle_tag(&mut self) -> HResult<()> {
|
fn toggle_tag(&mut self) -> HResult<()> {
|
||||||
self.selected_file_mut().toggle_tag()?;
|
self.selected_file_mut().toggle_tag()?;
|
||||||
|
|
||||||
|
// Create a mutable clone to render changes into buffer
|
||||||
|
let mut file = self.clone_selected_file();
|
||||||
|
file.toggle_tag()?;
|
||||||
|
|
||||||
|
let line = self.render_line(&file);
|
||||||
let selection = self.get_selection();
|
let selection = self.get_selection();
|
||||||
let line = self.render_line(self.selected_file());
|
|
||||||
self.buffer[selection] = line;
|
self.buffer[selection] = line;
|
||||||
|
|
||||||
self.move_down();
|
self.move_down();
|
||||||
@ -689,7 +734,10 @@ impl ListView<Files>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<T> Widget for ListView<T> where ListView<T>: Listable {
|
impl<T> Widget for ListView<T>
|
||||||
|
where
|
||||||
|
ListView<T>: Listable
|
||||||
|
{
|
||||||
fn get_core(&self) -> HResult<&WidgetCore> {
|
fn get_core(&self) -> HResult<&WidgetCore> {
|
||||||
Ok(&self.core)
|
Ok(&self.core)
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,7 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Listable for ListView<Vec<Process>> {
|
impl Listable for ListView<Vec<Process>> {
|
||||||
|
type Item = ();
|
||||||
fn len(&self) -> usize { self.content.len() }
|
fn len(&self) -> usize { self.content.len() }
|
||||||
fn render(&self) -> Vec<String> {
|
fn render(&self) -> Vec<String> {
|
||||||
self.content.iter().map(|proc| {
|
self.content.iter().map(|proc| {
|
||||||
|
@ -5,6 +5,7 @@ use crate::fail::{HResult, HError, ErrorLog};
|
|||||||
use crate::coordinates::Coordinates;
|
use crate::coordinates::Coordinates;
|
||||||
|
|
||||||
pub trait Tabbable {
|
pub trait Tabbable {
|
||||||
|
type Tab: Widget;
|
||||||
fn new_tab(&mut self) -> HResult<()>;
|
fn new_tab(&mut self) -> HResult<()>;
|
||||||
fn close_tab(&mut self) -> HResult<()>;
|
fn close_tab(&mut self) -> HResult<()>;
|
||||||
fn next_tab(&mut self) -> HResult<()>;
|
fn next_tab(&mut self) -> HResult<()>;
|
||||||
@ -14,8 +15,8 @@ pub trait Tabbable {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn get_tab_names(&self) -> Vec<Option<String>>;
|
fn get_tab_names(&self) -> Vec<Option<String>>;
|
||||||
fn active_tab(&self) -> &dyn Widget;
|
fn active_tab(&self) -> &Self::Tab;
|
||||||
fn active_tab_mut(&mut self) -> &mut dyn Widget;
|
fn active_tab_mut(&mut self) -> &mut Self::Tab;
|
||||||
fn on_key_sub(&mut self, key: Key) -> HResult<()>;
|
fn on_key_sub(&mut self, key: Key) -> HResult<()>;
|
||||||
fn on_key(&mut self, key: Key) -> HResult<()> {
|
fn on_key(&mut self, key: Key) -> HResult<()> {
|
||||||
self.on_key_sub(key)
|
self.on_key_sub(key)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user