summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-03-16 22:49:27 +0100
committerrabite <rabite@posteo.de>2019-03-17 00:19:58 +0100
commit8b1c4db9cfa2ea0bf02e9e96c29b2510bbc391af (patch)
treef3c2b0e857691ae968d54269a0cd3b8067d36dbc
parent33a9562379b9d6fdd7be19ce20b3a5ac1fa7e1c7 (diff)
big performance improvement
-rw-r--r--src/dirty.rs35
-rw-r--r--src/files.rs21
-rw-r--r--src/foldview.rs47
-rw-r--r--src/listview.rs23
-rw-r--r--src/main.rs2
-rw-r--r--src/preview.rs3
-rw-r--r--src/tabview.rs2
-rw-r--r--src/term.rs5
-rw-r--r--src/textview.rs27
-rw-r--r--src/widget.rs29
10 files changed, 139 insertions, 55 deletions
diff --git a/src/dirty.rs b/src/dirty.rs
new file mode 100644
index 0000000..fe6e4d1
--- /dev/null
+++ b/src/dirty.rs
@@ -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
+ }
+}
diff --git a/src/files.rs b/src/files.rs
index e2a5aab..5cc7dd8 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -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(())
}
diff --git a/src/foldview.rs b/src/foldview.rs
index ffe5281..32d98e1 100644
--- a/src/foldview.rs
+++ b/src/foldview.rs
@@ -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(())
diff --git a/src/listview.rs b/src/listview.rs
index e41eb8e..416191b 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -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)
diff --git a/src/main.rs b/src/main.rs
index 80029fd..0659a09 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -45,6 +45,8 @@ mod proclist;
mod bookmarks;
mod paths;
mod foldview;
+mod dirty;
+
diff --git a/src/preview.rs b/src/preview.rs
index 832f136..17663b2 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -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};
diff --git a/src/tabview.rs b/src/tabview.rs
index 53bed38..e8dc748 100644
--- a/src/tabview.rs
+++ b/src/tabview.rs
@@ -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(())
}
}
diff --git a/src/term.rs b/src/term.rs
index 2cfd70e..6b19c1b 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -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!(
"{}",
diff --git a/src/textview.rs b/src/textview.rs
index 25dc63e..870bb4b 100644
--- a/src/textview.rs
+++ b/src/textview.rs
@@ -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)
}
}
diff --git a/src/widget.rs b/src/widget.rs
index f4b18b9..8c9942b 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -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(())
}