diff options
author | James Campos <james.r.campos@gmail.com> | 2020-07-13 21:37:05 -0700 |
---|---|---|
committer | James Campos <james.r.campos@gmail.com> | 2020-07-13 21:37:05 -0700 |
commit | ce2e48d7a39fecf0e5c3ea0e16a4fa2de535518b (patch) | |
tree | 5f7f1b9f7d662b1bc9191056b4d5ace671732c56 | |
parent | 2637f03c3b59909da9eb1e5b9b73ff4f2b06cddd (diff) | |
download | bk-ce2e48d7a39fecf0e5c3ea0e16a4fa2de535518b.tar.gz |
inline styles
-rw-r--r-- | src/epub.rs | 16 | ||||
-rw-r--r-- | src/main.rs | 157 |
2 files changed, 88 insertions, 85 deletions
diff --git a/src/epub.rs b/src/epub.rs index b5510c8..fb0445a 100644 --- a/src/epub.rs +++ b/src/epub.rs @@ -141,9 +141,23 @@ fn render(n: Node, buf: &mut String, attrs: &mut Attrs) { for c in n.children() { render(c, buf, attrs); } - attrs.push((buf.len(), Attribute::Reset)); + attrs.push((buf.len(), Attribute::NoBold)); buf.push('\n'); } + "em" => { + attrs.push((buf.len(), Attribute::Italic)); + for c in n.children() { + render(c, buf, attrs); + } + attrs.push((buf.len(), Attribute::NoItalic)); + } + "strong" => { + attrs.push((buf.len(), Attribute::Bold)); + for c in n.children() { + render(c, buf, attrs); + } + attrs.push((buf.len(), Attribute::NoBold)); + } "blockquote" | "p" | "tr" => { buf.push('\n'); for c in n.children() { diff --git a/src/main.rs b/src/main.rs index d977b12..d2c965f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -301,99 +301,85 @@ impl View for Page { } } fn render(&self, bk: &Bk) -> Vec<String> { - render_page(bk, 0) - } -} - -fn render_page(bk: &Bk, offset: usize) -> Vec<String> { - let c = bk.chap(); - let line_end = min(bk.line + bk.rows - offset, bk.chap().lines.len()); - - // TODO support inline tags (strong) - let attrs = { - let text_start = c.lines[bk.line].0; - let text_end = c.lines[line_end - 1].1; - - let mut search = Vec::new(); - let qlen = bk.query.len(); - if qlen > 0 { - for (pos, _) in c.text[text_start..text_end].match_indices(&bk.query) { - search.push(text_start + pos); + let c = bk.chap(); + let line_end = min(bk.line + bk.rows, c.lines.len()); + + let attrs = { + let text_start = c.lines[bk.line].0; + let text_end = c.lines[line_end - 1].1; + + let qlen = bk.query.len(); + let mut search = Vec::new(); + if qlen > 0 { + for (pos, _) in c.text[text_start..text_end].match_indices(&bk.query) { + search.push((text_start + pos, Attribute::Reverse)); + search.push((text_start + pos + qlen, Attribute::NoReverse)); + } } - } - let mut search_iter = search.into_iter(); + let mut search_iter = search.into_iter().peekable(); - let attr_end = match c.attrs.binary_search_by_key(&text_end, |&(pos, _)| pos) { - Ok(n) => n, - Err(n) => n, - }; - 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..]; - let mut attrs_iter = iter::once(&head).chain(tail.iter()); - - let mut merged = Vec::new(); - let mut sn = search_iter.next(); - let mut an = attrs_iter.next(); - loop { - match (sn, an) { - (None, None) => panic!("does this happen?"), - (Some(s), None) => { - merged.push((s, Attribute::Reverse)); - merged.push((s + qlen, Attribute::Reset)); - for s in search_iter { - merged.push((s, Attribute::Reverse)); - merged.push((s + qlen, Attribute::Reset)); + let attr_end = match c.attrs.binary_search_by_key(&text_end, |&(pos, _)| pos) { + Ok(n) => n, + Err(n) => n, + }; + 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..]; + let mut attrs_iter = iter::once(&head).chain(tail.iter()).peekable(); + + // seems like this should be simpler. use itertools? + let mut merged = Vec::new(); + loop { + match (search_iter.peek(), attrs_iter.peek()) { + (None, None) => panic!("double none wtf"), + (Some(_), None) => { + merged.extend(search_iter); + break; } - break; - } - (None, Some(&a)) => { - merged.push(a); - merged.extend(attrs_iter); - break; - } - (Some(s), Some(&a)) => { - if s < a.0 { - merged.push((s, Attribute::Reverse)); - merged.push((s + qlen, Attribute::Reset)); - // this match arm is inside a header tag - merged.push((s + qlen, Attribute::Bold)); - sn = search_iter.next(); - } else { - merged.push(a); - an = attrs_iter.next(); + (None, Some(_)) => { + merged.extend(attrs_iter); + break; + } + (Some(&s), Some(&&a)) => { + if s.0 < a.0 { + merged.push(s); + search_iter.next(); + } else { + merged.push(a); + attrs_iter.next(); + } } } } - } - merged - }; + merged + }; - let mut buf = Vec::new(); - let mut iter = attrs.into_iter().peekable(); - for &(mut start, end) in &c.lines[bk.line..line_end] { - let mut s = String::new(); - while let Some(a) = iter.peek() { - if a.0 <= end { - s.push_str(&c.text[start..a.0]); - s.push_str(&a.1.to_string()); - start = a.0; + let mut buf = Vec::new(); + let mut iter = attrs.into_iter().peekable(); + for &(mut start, end) in &c.lines[bk.line..line_end] { + let mut s = String::new(); + while let Some(&(pos, attr)) = iter.peek() { + if pos > end { + break; + } + s.push_str(&c.text[start..pos]); + s.push_str(&attr.to_string()); + start = pos; iter.next(); - } else { - break; } + s.push_str(&c.text[start..end]); + buf.push(s); } - s.push_str(&c.text[start..end]); - buf.push(s); + buf } - buf } + struct Search; impl View for Search { fn run(&self, bk: &mut Bk, kc: KeyCode) { @@ -427,10 +413,13 @@ impl View for Search { } } fn render(&self, bk: &Bk) -> Vec<String> { - let mut buf = render_page(bk, 1); - - for _ in buf.len()..bk.rows - 1 { - buf.push(String::new()); + let mut buf = Page::render(&Page, bk); + if buf.len() == bk.rows { + buf.pop(); + } else { + for _ in buf.len()..bk.rows - 1 { + buf.push(String::new()); + } } let prefix = match bk.dir { Direction::Next => '/', |