summaryrefslogtreecommitdiffstats
path: root/src/textview.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/textview.rs')
-rw-r--r--src/textview.rs169
1 files changed, 126 insertions, 43 deletions
diff --git a/src/textview.rs b/src/textview.rs
index cd9a815..b7dd0a9 100644
--- a/src/textview.rs
+++ b/src/textview.rs
@@ -1,6 +1,7 @@
-use std::io::{BufRead, BufReader};
+use std::io::BufRead;
use strip_ansi_escapes::strip;
+use termion::event::Key;
use crate::files::File;
use crate::term::sized_string_u;
@@ -15,6 +16,8 @@ pub struct TextView {
pub core: WidgetCore,
pub follow: bool,
pub offset: usize,
+ file: Option<File>,
+ limited: bool,
}
impl TextView {
@@ -24,56 +27,78 @@ impl TextView {
core: core.clone(),
follow: false,
offset: 0,
+ file: None,
+ limited: false
}
}
+
pub fn new_from_file(core: &WidgetCore, file: &File) -> HResult<TextView> {
- let file = std::fs::File::open(&file.path)?;
- let file = std::io::BufReader::new(file);
- let lines = file.lines()
- .map(|line| line
- .and_then(|l| strip(l))
- .map_err(HError::from)
- .and_then(|s| std::str::from_utf8(&s)
- .map(|s| s.to_string())
- .map_err(HError::from)))
- .collect::<HResult<_>>()?;
- Ok(TextView {
- lines: lines,
- core: core.clone(),
- follow: false,
- offset: 0,
- })
+ let mut view = TextView::new_from_file_limit_lines(core, file, 0)?;
+ view.limited = false;
+ Ok(view)
}
pub fn new_from_file_limit_lines(core: &WidgetCore,
file: &File,
num: usize) -> HResult<TextView> {
- let file = std::fs::File::open(&file.path)?;
- let file = BufReader::new(file);
- let lines = file.lines()
- .take(num)
- .map(|line| line
- .and_then(|l| strip(l))
- .map_err(HError::from)
- .and_then(|s| std::str::from_utf8(&s)
- .map(|s| s.to_string())
- .map_err(HError::from)))
- .collect::<HResult<_>>()?;
+ let buf = std::fs::File::open(&file.path)
+ .map(|f| std::io::BufReader::new(f))?;
+
+ let lines = buf.lines()
+ .enumerate()
+ .take_while(|(i, _)| num == 0 || i <= &num)
+ .map(|(_, l)| {
+ l.map_err(HError::from)
+ .and_then(|l| {
+ let l = strip(&l);
+ Ok(String::from_utf8_lossy(&l?).to_string())
+ })
+ .map_err(HError::from)
+
+ })
+ .collect::<HResult<_>>()?;
+
Ok(TextView {
lines: lines,
core: core.clone(),
follow: false,
offset: 0,
+ file: Some(file.clone()),
+ limited: true
})
}
pub fn set_text(&mut self, text: &str) -> HResult<()> {
let lines = text.lines().map(|l| l.to_string()).collect();
self.lines = lines;
+ self.limited = false;
+ self.file = None;
self.core.set_dirty();
self.refresh()
}
+ pub fn set_lines(&mut self, lines: Vec<String>) -> HResult<()> {
+ self.lines = lines;
+ self.limited = false;
+ self.file = None;
+ self.core.set_dirty();
+ self.refresh()
+ }
+
+ pub fn load_full(&mut self) {
+ if self.limited {
+ self.file
+ .as_ref()
+ .and_then(|f| {
+ TextView::new_from_file(&self.core, f).ok()
+ })
+ .map(|v| {
+ *self = v;
+ self.limited = false;
+ });
+ }
+ }
+
pub fn toggle_follow(&mut self) {
self.follow = !self.follow
}
@@ -159,21 +184,79 @@ impl Widget for TextView {
let (xsize, ysize) = self.get_coordinates()?.size().size();
let (xpos, ypos) = self.get_coordinates()?.position().position();
- let output = self.core.get_clearlist()? +
- &self
- .lines
- .iter()
- .skip(self.offset)
- .take(ysize as usize)
- .enumerate()
- .map(|(i, line)| {
- format!(
- "{}{}{}",
- crate::term::goto_xy(xpos, i as u16 + ypos),
- crate::term::reset(),
- sized_string_u(&line, (xsize-1) as usize))
- })
- .collect::<String>();
+ let mut output = crate::term::reset();
+
+ output += &self.lines
+ .iter()
+ .skip(self.offset)
+ .take(ysize as usize)
+ .enumerate()
+ .map(|(i, line)| {
+ format!(
+ "{}{}",
+ crate::term::goto_xy(xpos, i as u16 + ypos),
+ sized_string_u(&line, (xsize-1) as usize))
+ })
+ .collect::<String>();
Ok(output)
}
+
+ fn render_footer(&self) -> HResult<String> {
+ let (xsize, ysize) = self.core.coordinates.size_u();
+ let (_, ypos) = self.core.coordinates.position_u();
+ let lines = self.lines
+ .len()
+ .saturating_sub(1);
+ let current_line_top = self.offset;
+ let current_line_bot = std::cmp::min(current_line_top + ysize + 1,
+ lines);
+ let line_hint = format!("{} - {} / {}",
+ current_line_top,
+ current_line_bot,
+ lines);
+ let hint_xpos = xsize - line_hint.len();
+ let hint_ypos = ysize + ypos + 1;
+
+ let footer = format!("{}{}",
+ crate::term::goto_xy_u(hint_xpos, hint_ypos),
+ line_hint);
+
+ Ok(footer)
+ }
+
+ fn on_key(&mut self, key: Key) -> HResult<()> {
+ self.do_key(key)
+ }
+}
+
+use crate::keybind::{Acting, Bindings, Movement};
+
+impl Acting for TextView {
+ type Action=Movement;
+
+ fn search_in(&self) -> Bindings<Self::Action> {
+ Bindings::default()
+ }
+
+ fn movement(&mut self, movement: &Movement) -> HResult<()> {
+ use Movement::*;
+
+ self.load_full();
+
+ match movement {
+ Up(n) => { for _ in 0..*n { self.scroll_up(); }; self.refresh()?; }
+ Down(n) => { for _ in 0..*n { self.scroll_down(); }; self.refresh()?; }
+ PageUp => self.page_up(),
+ PageDown => self.page_down(),
+ Top => self.scroll_top(),
+ Bottom => self.scroll_bottom(),
+ Left | Right => {}
+ }
+
+ Ok(())
+ }
+
+ fn do_action(&mut self, _action: &Self::Action) -> HResult<()> {
+ Ok(())
+ }
}