diff options
author | James Campos <james.r.campos@gmail.com> | 2020-07-16 04:19:58 -0700 |
---|---|---|
committer | James Campos <james.r.campos@gmail.com> | 2020-07-16 04:19:58 -0700 |
commit | 3b0838a611990bead1544a6660b07b15d6fe2024 (patch) | |
tree | d7e2ea4eaebdfb09b9b1f9b55daa96a40d3a2f96 /src/main.rs | |
parent | 51860063f810513973c379b1bed0bcc34db6139c (diff) | |
download | bk-3b0838a611990bead1544a6660b07b15d6fe2024.tar.gz |
fix #2, start links
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 88 |
1 files changed, 42 insertions, 46 deletions
diff --git a/src/main.rs b/src/main.rs index 1b7269f..b46defc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use crossterm::{ }; use serde::{Deserialize, Serialize}; use std::{ - cmp::{max, min}, + cmp::min, collections::HashMap, env, fs, io::{stdout, Write}, @@ -17,6 +17,7 @@ use std::{ }; mod epub; +use epub::Chapter; // XXX assumes a char is i unit wide fn wrap(text: &str, width: usize) -> Vec<(usize, usize)> { @@ -304,7 +305,6 @@ impl View for Page { let c = bk.chap(); let line_end = min(bk.line + bk.rows, c.lines.len()); - // XXX does not pick up combined bold italic state if both attributes start above screen let attrs = { let text_start = c.lines[bk.line].0; let text_end = c.lines[line_end - 1].1; @@ -319,25 +319,34 @@ impl View for Page { } let mut search_iter = search.into_iter().peekable(); - let attr_end = match c.attrs.binary_search_by_key(&text_end, |&(pos, _)| pos) { + let mut merged = Vec::new(); + let attr_start = match c + .attrs + .binary_search_by_key(&text_start, |&(pos, _, _)| pos) + { Ok(n) => n, - Err(n) => n, + Err(n) => n - 1, }; - let attr_start = c.attrs[..attr_end] - .iter() - .rposition(|&(pos, _)| pos <= text_start) - .unwrap(); - // keep attr pos >= line start - let (pos, attr) = c.attrs[attr_start]; - let head = (max(pos, text_start), attr); - let tail = &c.attrs[attr_start + 1..attr_end]; - let mut attrs_iter = iter::once(&head).chain(tail.iter()).peekable(); - - // seems like this should be simpler. use itertools? - let mut merged = Vec::new(); + let mut attrs_iter = c.attrs[attr_start..].iter(); + let (_, _, attr) = attrs_iter.next().unwrap(); + if attr.has(Attribute::Bold) { + merged.push((text_start, Attribute::Bold)); + } + if attr.has(Attribute::Italic) { + merged.push((text_start, Attribute::Italic)); + } + if attr.has(Attribute::Underlined) { + merged.push((text_start, Attribute::Underlined)); + } + let mut attrs_iter = attrs_iter + .map(|&(pos, a, _)| (pos, a)) + .take_while(|(pos, _)| pos <= &text_end) + .peekable(); + + // use itertools? loop { match (search_iter.peek(), attrs_iter.peek()) { - (None, None) => panic!("double none wtf"), + (None, None) => break, (Some(_), None) => { merged.extend(search_iter); break; @@ -346,7 +355,7 @@ impl View for Page { merged.extend(attrs_iter); break; } - (Some(&s), Some(&&a)) => { + (Some(&s), Some(&a)) => { if s.0 < a.0 { merged.push(s); search_iter.next(); @@ -357,6 +366,7 @@ impl View for Page { } } } + merged }; @@ -380,7 +390,6 @@ impl View for Page { } } - struct Search; impl View for Search { fn run(&self, bk: &mut Bk, kc: KeyCode) { @@ -431,17 +440,8 @@ impl View for Search { } } -struct Chapter { - title: String, - // a single string for searching - text: String, - // byte indexes - lines: Vec<(usize, usize)>, - attrs: Vec<(usize, Attribute)>, -} - struct Bk<'a> { - chapters: Vec<Chapter>, + chapters: Vec<epub::Chapter>, // position in the book chapter: usize, line: usize, @@ -468,24 +468,17 @@ impl Bk<'_> { .map(|(a, b)| String::from(&epub.meta[a..b])) .collect(); - let mut chapters = Vec::with_capacity(epub.chapters.len()); - for (title, text, attrs) in epub.chapters { - let title = if title.chars().count() > width { - title + let mut chapters = epub.chapters; + for c in &mut chapters { + c.lines = wrap(&c.text, width); + if c.title.chars().count() > width { + c.title = c + .title .chars() .take(width - 1) .chain(iter::once('…')) - .collect() - } else { - title - }; - let lines = wrap(&text, width); - chapters.push(Chapter { - title, - text, - lines, - attrs, - }); + .collect(); + } } let line = match chapters[args.chapter] @@ -528,8 +521,11 @@ impl Bk<'_> { while let Some(view) = self.view { let pad = self.cols.saturating_sub(self.max_width) / 2; - // clearing the screen doesn't reset attributes wtf - queue!(stdout, terminal::Clear(terminal::ClearType::All), Print(Attribute::Reset))?; + queue!( + stdout, + terminal::Clear(terminal::ClearType::All), + Print(Attribute::Reset) + )?; for (i, line) in view.render(self).iter().enumerate() { queue!(stdout, cursor::MoveTo(pad, i as u16), Print(line))?; } |