From ce2e48d7a39fecf0e5c3ea0e16a4fa2de535518b Mon Sep 17 00:00:00 2001
From: James Campos <james.r.campos@gmail.com>
Date: Mon, 13 Jul 2020 21:37:05 -0700
Subject: inline styles

---
 src/epub.rs |  16 ++++++-
 src/main.rs | 157 ++++++++++++++++++++++++++++--------------------------------
 2 files changed, 88 insertions(+), 85 deletions(-)

(limited to 'src')

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 => '/',
-- 
cgit v1.2.3