aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Campos <james.r.campos@gmail.com>2020-07-13 21:37:05 -0700
committerJames Campos <james.r.campos@gmail.com>2020-07-13 21:37:05 -0700
commitce2e48d7a39fecf0e5c3ea0e16a4fa2de535518b (patch)
tree5f7f1b9f7d662b1bc9191056b4d5ace671732c56
parent2637f03c3b59909da9eb1e5b9b73ff4f2b06cddd (diff)
downloadbk-ce2e48d7a39fecf0e5c3ea0e16a4fa2de535518b.tar.gz
inline styles
-rw-r--r--src/epub.rs16
-rw-r--r--src/main.rs157
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 => '/',