big performance improvement

This commit is contained in:
rabite 2019-03-16 22:49:27 +01:00
parent 33a9562379
commit 8b1c4db9cf
10 changed files with 139 additions and 55 deletions

35
src/dirty.rs Normal file
View File

@ -0,0 +1,35 @@
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct DirtyBit(bool);
pub trait Dirtyable {
fn get_bit(&self) -> &DirtyBit;
fn get_bit_mut(&mut self) -> &mut DirtyBit;
fn is_dirty(&self) -> bool {
self.get_bit().0
}
fn set_dirty(&mut self) {
self.get_bit_mut().0 = true;
}
fn set_clean(&mut self) {
self.get_bit_mut().0 = false;
}
}
impl DirtyBit {
pub fn new() -> DirtyBit {
DirtyBit(false)
}
}
impl Dirtyable for DirtyBit {
fn get_bit(&self) -> &DirtyBit {
self
}
fn get_bit_mut(&mut self) -> &mut DirtyBit {
self
}
}

View File

@ -13,6 +13,7 @@ use failure::Error;
use notify::DebouncedEvent;
use crate::fail::{HResult, HError};
use crate::dirty::{DirtyBit, Dirtyable};
@ -54,7 +55,8 @@ pub struct Files {
pub sort: SortBy,
pub dirs_first: bool,
pub reverse: bool,
pub show_hidden: bool
pub show_hidden: bool,
pub dirty: DirtyBit
}
impl Index<usize> for Files {
@ -65,7 +67,15 @@ impl Index<usize> for Files {
}
impl Dirtyable for Files {
fn get_bit(&self) -> &DirtyBit {
&self.dirty
}
fn get_bit_mut(&mut self) -> &mut DirtyBit {
&mut self.dirty
}
}
impl Files {
@ -88,7 +98,8 @@ impl Files {
sort: SortBy::Name,
dirs_first: true,
reverse: false,
show_hidden: true
show_hidden: true,
dirty: DirtyBit::new()
};
files.sort();
@ -131,7 +142,8 @@ impl Files {
sort: SortBy::Name,
dirs_first: true,
reverse: false,
show_hidden: true
show_hidden: true,
dirty: DirtyBit::new()
};
files.sort();
@ -188,6 +200,7 @@ impl Files {
if self.reverse {
self.files.reverse();
}
self.set_dirty();
}
pub fn cycle_sort(&mut self) {
@ -216,6 +229,7 @@ impl Files {
.collect();
self.files = files;
self.set_dirty();
}
pub fn handle_event(&mut self, event: &DebouncedEvent) -> HResult<()> {
@ -247,6 +261,7 @@ impl Files {
},
_ => {},
}
self.set_dirty();
Ok(())
}

View File

@ -1,11 +1,12 @@
use termion::event::Key;
use failure::Fail;
use chrono::{DateTime, TimeZone, Local};
use chrono::{DateTime, Local};
use crate::term;
use crate::widget::Widget;
use crate::listview::{ListView, Listable};
use crate::fail::{HResult, HError};
use crate::dirty::Dirtyable;
pub type LogView = ListView<Vec<LogEntry>>;
@ -82,25 +83,30 @@ pub trait FoldableWidgetExt {
impl FoldableWidgetExt for ListView<Vec<LogEntry>> {
fn on_refresh(&mut self) -> HResult<()> {
self.content.refresh_logs()
if self.content.refresh_logs()? > 0 {
self.core.set_dirty();
}
Ok(())
}
}
trait LogList {
fn refresh_logs(&mut self) -> HResult<()>;
fn refresh_logs(&mut self) -> HResult<usize>;
}
impl LogList for Vec<LogEntry> {
fn refresh_logs(&mut self) -> HResult<()> {
fn refresh_logs(&mut self) -> HResult<usize> {
let logs = crate::fail::get_logs()?;
let mut logentries = logs.into_iter().map(|log| {
LogEntry::from(log)
}).collect();
}).collect::<Vec<_>>();
let n = logentries.len();
self.append(&mut logentries);
//self.truncate(10);
Ok(())
Ok(n)
}
}
@ -154,7 +160,8 @@ where
self.set_selection(fold_pos);
}
self.refresh()
self.core.set_dirty();
Ok(())
}
fn fold_start_pos(&self, fold: usize) -> usize {
@ -201,11 +208,9 @@ where
}
fn render(&self) -> Vec<String> {
let (xsize, ysize) = self.core.coordinates.size_u();
let offset = self.offset;
let (xsize, _) = self.core.coordinates.size_u();
self.content
.iter()
//.skip(offset)
.map(|foldable|
foldable
.render()
@ -213,8 +218,6 @@ where
.map(|line| term::sized_string_u(line, xsize))
.collect::<Vec<_>>())
.flatten()
.skip(offset)
.take(ysize+1)
.collect()
}
fn on_refresh(&mut self) -> HResult<()> {
@ -223,18 +226,12 @@ where
fn on_key(&mut self, key: Key) -> HResult<()> {
match key {
Key::Up | Key::Char('p') => {
self.move_up();
self.refresh()?;
}
Key::Char('P') => { for _ in 0..10 { self.move_up() } self.refresh()?; }
Key::Char('N') => { for _ in 0..10 { self.move_down() } self.refresh()?; }
Key::Down | Key::Char('n') => {
self.move_down();
self.refresh()?;
},
Key::Char('t') => { self.toggle_fold()?; }
Key::Char('l') => { self.popup_finnished()?; }
Key::Up | Key::Char('p') => self.move_up(),
Key::Char('P') => for _ in 0..10 { self.move_up() },
Key::Char('N') => for _ in 0..10 { self.move_down() },
Key::Down | Key::Char('n') => self.move_down(),
Key::Char('t') => self.toggle_fold()?,
Key::Char('l') => self.popup_finnished()?,
_ => {}
}
Ok(())

View File

@ -7,6 +7,7 @@ use crate::files::{File, Files};
use crate::fail::{HResult, ErrorLog};
use crate::term;
use crate::widget::{Widget, WidgetCore};
use crate::dirty::Dirtyable;
pub trait Listable {
fn len(&self) -> usize;
@ -27,6 +28,11 @@ impl Listable for ListView<Files> {
fn on_refresh(&mut self) -> HResult<()> {
let visible_file_num = self.selection + self.get_coordinates()?.ysize() as usize;
self.content.meta_upto(visible_file_num);
if self.content.is_dirty() {
self.core.set_dirty();
self.content.set_clean();
}
Ok(())
}
@ -366,13 +372,9 @@ impl ListView<Files>
}
fn render(&self) -> Vec<String> {
let ysize = self.get_coordinates().unwrap().ysize() as usize;
let offset = self.offset;
self.content
.files
.iter()
.skip(offset)
.take(ysize)
.map(|file| self.render_line(&file))
.collect()
}
@ -389,10 +391,15 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
fn refresh(&mut self) -> HResult<()> {
self.on_refresh().log();
self.lines = self.len();
if self.selection >= self.lines && self.selection != 0 {
self.selection -= 1;
}
self.buffer = self.render();
if self.core.is_dirty() || self.buffer.len() != self.len() {
self.buffer = self.render();
self.core.set_clean();
}
Ok(())
}
@ -400,10 +407,13 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
fn get_drawlist(&self) -> HResult<String> {
let mut output = term::reset();
let (xpos, ypos) = self.get_coordinates().unwrap().position().position();
let ysize = self.get_coordinates().unwrap().ysize() as usize;
output += &self
.buffer
.iter()
.skip(self.offset)
.take(ysize)
.enumerate()
.map(|(i, item)| {
let mut output = term::normal_color();
@ -425,9 +435,6 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
Ok(output)
}
fn render_header(&self) -> HResult<String> {
Ok(format!("{} files", self.len()))
}
fn on_key(&mut self, key: Key) -> HResult<()> {
Listable::on_key(self, key)

View File

@ -45,6 +45,8 @@ mod proclist;
mod bookmarks;
mod paths;
mod foldview;
mod dirty;

View File

@ -28,7 +28,7 @@ fn kill_proc() -> HResult<()> {
}
pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> {
let stale = *(stale.try_lock().unwrap());
let stale = *(stale.lock().unwrap());
Ok(stale)
}
@ -405,7 +405,6 @@ impl Previewer {
.to_string();
let mut textview = TextView {
lines: output.lines().map(|s| s.to_string()).collect(),
buffer: String::new(),
core: core.clone(),
follow: false,
offset: 0};

View File

@ -150,6 +150,6 @@ impl<T> Widget for TabView<T> where T: Widget, TabView<T>: Tabbable {
fn on_key(&mut self, key: Key) -> HResult<()> {
Tabbable::on_key(self, key)?;
self.refresh()
Ok(())
}
}

View File

@ -51,7 +51,6 @@ pub trait ScreenExt: Write {
}
fn reset(&mut self) -> HResult<()> {
write!(self, "{}", termion::style::Reset)?;
self.flush()?;
Ok(())
}
fn clear(&mut self) -> HResult<()> {
@ -60,7 +59,6 @@ pub trait ScreenExt: Write {
}
fn write_str(&mut self, str: &str) -> HResult<()> {
write!(self, "{}", str)?;
self.flush()?;
Ok(())
}
fn goto_xy(&mut self, x: usize, y: usize) -> HResult<()> {
@ -149,6 +147,9 @@ pub fn sized_string_u(string: &str, xsize: usize) -> String {
// Do these as constants
pub fn highlight_color() -> String {
format!(
"{}",

View File

@ -4,11 +4,11 @@ use crate::files::File;
use crate::term::sized_string;
use crate::widget::{Widget, WidgetCore};
use crate::fail::HResult;
use crate::dirty::Dirtyable;
#[derive(PartialEq)]
pub struct TextView {
pub lines: Vec<String>,
pub buffer: String,
pub core: WidgetCore,
pub follow: bool,
pub offset: usize,
@ -18,7 +18,6 @@ impl TextView {
pub fn new_blank(core: &WidgetCore) -> TextView {
TextView {
lines: vec![],
buffer: String::new(),
core: core.clone(),
follow: false,
offset: 0,
@ -35,7 +34,6 @@ impl TextView {
Ok(TextView {
lines: lines,
buffer: String::new(),
core: core.clone(),
follow: false,
offset: 0,
@ -56,7 +54,6 @@ impl TextView {
Ok(TextView {
lines: lines,
buffer: String::new(),
core: core.clone(),
follow: false,
offset: 0,
@ -66,6 +63,7 @@ impl TextView {
pub fn set_text(&mut self, text: &str) -> HResult<()> {
let lines = text.lines().map(|l| l.to_string()).collect();
self.lines = lines;
self.core.set_dirty();
self.refresh()
}
@ -94,6 +92,10 @@ impl TextView {
self.offset = 0;
}
}
if offset != self.offset as isize {
self.core.set_dirty();
}
}
pub fn scroll_up(&mut self) {
@ -140,8 +142,17 @@ impl Widget for TextView {
self.scroll_bottom();
}
if self.core.is_dirty() {
self.core.set_clean();
}
Ok(())
}
self.buffer = self.get_clearlist()? +
fn get_drawlist(&self) -> HResult<String> {
let (xsize, ysize) = self.get_coordinates()?.size().size();
let (xpos, ypos) = self.get_coordinates()?.position().position();
let output = self.get_clearlist()? +
&self
.lines
.iter()
@ -156,10 +167,6 @@ impl Widget for TextView {
sized_string(&line, xsize))
})
.collect::<String>();
Ok(())
}
fn get_drawlist(&self) -> HResult<String> {
Ok(self.buffer.clone())
Ok(output)
}
}

View File

@ -1,5 +1,6 @@
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::io::Write;
use termion::event::{Event, Key, MouseEvent};
use termion::input::TermRead;
@ -9,6 +10,7 @@ use crate::fail::{HResult, HError, ErrorLog};
use crate::minibuffer::MiniBuffer;
use crate::term;
use crate::term::{Screen, ScreenExt};
use crate::dirty::{Dirtyable, DirtyBit};
use std::io::stdin;
@ -47,7 +49,8 @@ pub struct WidgetCore {
pub minibuffer: Arc<Mutex<Option<MiniBuffer>>>,
pub event_sender: Sender<Events>,
event_receiver: Arc<Mutex<Option<Receiver<Events>>>>,
pub status_bar_content: Arc<Mutex<Option<String>>>
pub status_bar_content: Arc<Mutex<Option<String>>>,
dirty: DirtyBit
}
impl WidgetCore {
@ -66,7 +69,8 @@ impl WidgetCore {
minibuffer: Arc::new(Mutex::new(None)),
event_sender: sender,
event_receiver: Arc::new(Mutex::new(Some(receiver))),
status_bar_content: status_bar_content };
status_bar_content: status_bar_content,
dirty: DirtyBit::new() };
let minibuffer = MiniBuffer::new(&core);
*core.minibuffer.lock().unwrap() = Some(minibuffer);
@ -78,6 +82,17 @@ impl WidgetCore {
}
}
impl Dirtyable for WidgetCore {
fn get_bit(&self) -> &DirtyBit {
&self.dirty
}
fn get_bit_mut(&mut self) -> &mut DirtyBit {
&mut self.dirty
}
}
pub trait Widget {
fn get_core(&self) -> HResult<&WidgetCore>; // {
// Err(HError::NoWidgetCoreError(Backtrace::new()))
@ -89,8 +104,12 @@ pub trait Widget {
Ok(&self.get_core()?.coordinates)
}
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
self.get_core_mut()?.coordinates = coordinates.clone();
self.refresh()?;
let widget_coords = &mut self.get_core_mut()?.coordinates;
if widget_coords != coordinates {
*widget_coords = coordinates.clone();
self.get_core_mut()?.set_dirty();
self.refresh()?;
}
Ok(())
}
fn render_header(&self) -> HResult<String> {
@ -235,8 +254,10 @@ pub trait Widget {
}
_ => {}
}
self.refresh().log();
self.draw().log();
self.after_draw().log();
self.get_core_mut()?.screen.flush().ok();
}
Ok(())
}