diff options
Diffstat (limited to 'src/preview')
-rw-r--r-- | src/preview/mod.rs | 2 | ||||
-rw-r--r-- | src/preview/preview.rs | 10 | ||||
-rw-r--r-- | src/preview/zero_len_file_view.rs | 56 |
3 files changed, 66 insertions, 2 deletions
diff --git a/src/preview/mod.rs b/src/preview/mod.rs index ed49778..0eea813 100644 --- a/src/preview/mod.rs +++ b/src/preview/mod.rs @@ -1,9 +1,11 @@ mod preview; mod preview_state; +mod zero_len_file_view; pub use { preview::Preview, preview_state::PreviewState, + zero_len_file_view::ZeroLenFileView, }; #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/src/preview/preview.rs b/src/preview/preview.rs index ecf6850..19c444e 100644 --- a/src/preview/preview.rs +++ b/src/preview/preview.rs @@ -1,6 +1,5 @@ - use { - super::PreviewMode, + super::*, crate::{ app::{AppContext, LineNumber}, command::{ScrollCommand}, @@ -25,6 +24,7 @@ pub enum Preview { Image(ImageView), Syntactic(SyntacticView), Hex(HexView), + ZeroLen(ZeroLenFileView), IOError(io::Error), } @@ -87,6 +87,10 @@ impl Preview { ) -> Self { match SyntacticView::new(path, InputPattern::none(), &mut Dam::unlimited(), con) { Ok(Some(sv)) => Self::Syntactic(sv), + Err(ProgramError::ZeroLenFile) => { + debug!("zero len file - check if system file"); + Self::ZeroLen(ZeroLenFileView::new(path.to_path_buf())) + } // not previewable as UTF8 text // we'll try reading it as binary _ => Self::hex(path), @@ -136,6 +140,7 @@ impl Preview { match self { Self::Image(_) => Some(PreviewMode::Image), Self::Syntactic(_) => Some(PreviewMode::Text), + Self::ZeroLen(_) => Some(PreviewMode::Text), Self::Hex(_) => Some(PreviewMode::Hex), Self::IOError(_) => None, } @@ -226,6 +231,7 @@ impl Preview { match self { Self::Image(iv) => iv.display(w, screen, panel_skin, area, con), Self::Syntactic(sv) => sv.display(w, screen, panel_skin, area, con), + Self::ZeroLen(zlv) => zlv.display(w, screen, panel_skin, area), Self::Hex(hv) => hv.display(w, screen, panel_skin, area), Self::IOError(err) => { let mut y = area.top; diff --git a/src/preview/zero_len_file_view.rs b/src/preview/zero_len_file_view.rs new file mode 100644 index 0000000..5ec3045 --- /dev/null +++ b/src/preview/zero_len_file_view.rs @@ -0,0 +1,56 @@ +use { + crate::{ + display::{CropWriter, SPACE_FILLING, Screen, W}, + errors::ProgramError, + skin::PanelSkin, + }, + char_reader::CharReader, + crossterm::{ + cursor, + QueueableCommand, + }, + std::{ + fs::File, + path::PathBuf, + }, + termimad::{Area}, +}; + +/// a (light) display for a file declaring a size 0, +/// as happens for many system "files", for example in /proc +pub struct ZeroLenFileView { + path: PathBuf, +} + +impl ZeroLenFileView { + pub fn new(path: PathBuf) -> Self { + Self { + path, + } + } + pub fn display( + &mut self, + w: &mut W, + _screen: Screen, + panel_skin: &PanelSkin, + area: &Area, + ) -> Result<(), ProgramError> { + let styles = &panel_skin.styles; + let line_count = area.height as usize; + let file = File::open(&self.path)?; + let mut reader = CharReader::new(file); + // line_len here is in chars, and we crop in cols, but it's OK because both + // are usually identical for system files and we crop later anyway + let line_len = area.width as usize; + for y in 0..line_count { + w.queue(cursor::MoveTo(area.left, y as u16 + area.top))?; + let mut cw = CropWriter::new(w, area.width as usize); + let cw = &mut cw; + if let Some(line) = reader.next_line(line_len, 15_000)? { + cw.queue_str(&styles.default, &line)?; + } + cw.fill(&styles.default, &SPACE_FILLING)?; + } + Ok(()) + } +} |