diff --git a/src/search.rs b/src/search.rs
index 2a70a9ae..c62f96d3 100644
--- a/src/search.rs
+++ b/src/search.rs
@@ -66,7 +66,8 @@ pub struct Searcher<'a, R, W: 'a> {
     match_count: u64,
     line_count: Option<u64>,
     last_match: Match,
-    last_printed: Option<(usize, usize)>,
+    last_printed: usize,
+    last_line: usize,
     after_context_remaining: usize,
     count: bool,
     invert_match: bool,
@@ -104,7 +105,8 @@ impl<'a, R: io::Read, W: io::Write> Searcher<'a, R, W> {
             match_count: 0,
             line_count: None,
             last_match: Match::default(),
-            last_printed: None,
+            last_printed: 0,
+            last_line: 0,
             after_context_remaining: 0,
             count: false,
             invert_match: false,
@@ -158,85 +160,41 @@ impl<'a, R: io::Read, W: io::Write> Searcher<'a, R, W> {
         self.match_count = 0;
         self.line_count = if self.line_number { Some(0) } else { None };
         self.last_match = Match::default();
-        self.last_printed = None;
         self.after_context_remaining = 0;
         loop {
-            let mut keep_from = self.inp.lastnl;
-            if self.before_context > 0 {
-                let start_of_keep = cmp::min(
-                    self.inp.lastnl,
-                    self.last_printed.map(|(_, end)| end).unwrap_or(0));
-                keep_from = start_of_keep + start_of_previous_lines(
-                    &self.inp.buf[start_of_keep..],
-                    (self.inp.lastnl - start_of_keep).saturating_sub(1),
-                    self.before_context);
-                // println!("start_of_keep: {}, lastnl: {}, last_printed: {:?}",
-                         // start_of_keep, self.inp.lastnl, self.last_printed);
-                // println!("keep_from: {}", keep_from);
-                // println!(
-                    // "KEEPING: {}",
-                    // show(&self.inp.buf[keep_from..self.inp.lastnl]));
-            }
-            let ok = try!(self.inp.fill(&mut self.haystack, keep_from).map_err(|err| {
-                Error::from_io(err, &self.path)
-            }));
-            if !ok {
+            if !try!(self.fill()) {
                 break;
             }
-            self.last_printed = None;
             while self.inp.pos < self.inp.lastnl {
-                let ok = self.grep.read_match(
+                let matched = self.grep.read_match(
                     &mut self.last_match,
                     &mut self.inp.buf[..self.inp.lastnl],
                     self.inp.pos);
-                if !ok {
-                    let upto = self.inp.lastnl;
-                    if self.invert_match {
-                        self.find_inverted_matches(upto);
-                    } else {
-                        self.count_lines(upto);
-                    }
-                    self.inp.pos = upto;
-                    break;
-                }
-                if self.before_context > 0 {
-                    let start = self.last_printed.map(|(_, e)| e).unwrap_or(0);
-                    let end = self.last_match.start().saturating_sub(1);
-                    if end > start {
-                        let before_context_start =
-                            start + start_of_previous_lines(
-                                &self.inp.buf[start..],
-                                end - start,
-                                self.before_context);
-                        let mut it = IterLines::new(before_context_start);
-                        while let Some((s, e)) = it.next(&self.inp.buf[..end]) {
-                            self.print_context(s, e);
-                        }
-                    }
-                }
                 if self.invert_match {
-                    let inverted_upto = self.last_match.start();
-                    self.find_inverted_matches(inverted_upto);
-                    // Add a line to account for the match...
-                    if let Some(ref mut line_count) = self.line_count {
-                        *line_count += 1;
+                    let upto =
+                        if matched {
+                            self.last_match.start()
+                        } else {
+                            self.inp.lastnl
+                        };
+                    if upto > self.inp.pos {
+                        let upto_context = self.inp.pos;
+                        self.print_before_context(upto_context);
+                        self.print_inverted_matches(upto);
                     }
-                    // ... and skip over the match.
-                    self.inp.pos = self.last_match.end() + 1;
-                } else {
+                } else if matched {
                     self.match_count += 1;
                     if !self.count {
-                        let upto = cmp::min(
-                            self.inp.lastnl, self.last_match.end() + 1);
-                        self.count_lines(upto);
                         let start = self.last_match.start();
                         let end = self.last_match.end();
+                        self.print_before_context(start);
                         self.print_match(start, end);
                     }
-                    // Move the position one past the end of the match so that
-                    // the next search starts after the nl. If we're at EOF,
-                    // then pos will be past EOF.
+                }
+                if matched {
                     self.inp.pos = self.last_match.end() + 1;
+                } else {
+                    self.inp.pos = self.inp.lastnl;
                 }
             }
         }
@@ -246,15 +204,37 @@ impl<'a, R: io::Read, W: io::Write> Searcher<'a, R, W> {
         Ok(self.match_count)
     }
 
+    fn fill(&mut self) -> Result<bool, Error> {
+        let mut keep_from = self.inp.lastnl;
+        if self.before_context > 0 {
+            keep_from = start_of_previous_lines(
+                &self.inp.buf,
+                self.inp.lastnl.saturating_sub(1),
+                self.before_context + 1);
+        }
+        if keep_from < self.last_printed {
+            self.last_printed = self.last_printed - keep_from;
+        } else {
+            self.last_printed = 0;
+        }
+        if keep_from < self.last_line {
+            self.last_line = self.last_line - keep_from;
+        } else {
+            self.count_lines(keep_from);
+            self.last_line = 0;
+        }
+        let ok = try!(self.inp.fill(&mut self.haystack, keep_from).map_err(|err| {
+            Error::from_io(err, &self.path)
+        }));
+        Ok(ok)
+    }
+
     #[inline(always)]
-    fn find_inverted_matches(&mut self, upto: usize) {
+    fn print_inverted_matches(&mut self, upto: usize) {
         debug_assert!(self.invert_match);
         let mut it = IterLines::new(self.inp.pos);
         while let Some((start, end)) = it.next(&self.inp.buf[..upto]) {
             if !self.count {
-                if let Some(ref mut line_count) = self.line_count {
-                    *line_count += 1;
-                }
                 self.print_match(start, end);
             }
             self.inp.pos = end + 1;
@@ -263,33 +243,67 @@ impl<'a, R: io::Read, W: io::Write> Searcher<'a, R, W> {
     }
 
     #[inline(always)]
-    fn count_lines(&mut self, upto: usize) {
-        if let Some(ref mut line_count) = self.line_count {
-            *line_count += count_lines(&self.inp.buf[self.inp.pos..upto]);
+    fn print_before_context(&mut self, upto: usize) {
+        // Never print contexts if we're only counting.
+        if self.count {
+            return;
+        }
+        if self.before_context > 0 {
+            let start = self.last_printed;
+            let end = upto.saturating_sub(1);
+            if end > start {
+                let before_context_start =
+                    start + start_of_previous_lines(
+                        &self.inp.buf[start..],
+                        end - start,
+                        self.before_context);
+                let mut it = IterLines::new(before_context_start);
+                while let Some((s, e)) = it.next(&self.inp.buf[..end]) {
+                    self.print_context(s, e);
+                }
+            }
         }
     }
 
     #[inline(always)]
     fn print_match(&mut self, start: usize, end: usize) {
+        let last_printed = cmp::min(end + 1, self.inp.lastnl);
+        self.count_lines(start);
+        self.add_line(last_printed);
         self.printer.matched(
             &self.path, &self.inp.buf, start, end, self.line_count);
-        self.last_printed = Some((start, cmp::min(end + 1, self.inp.lastnl)));
+        self.last_printed = last_printed;
         self.after_context_remaining = self.after_context;
     }
 
     #[inline(always)]
     fn print_context(&mut self, start: usize, end: usize) {
-        // println!("has_printed: {}, last_printed: {:?}, this: {:?}",
-                 // self.printer.has_printed(),
-                 // self.last_printed,
-                 // (start, end));
         if self.printer.has_printed()
-            && self.last_printed.map(|(_, end)| start > end).unwrap_or(true) {
+            && (self.last_printed == 0 || self.last_printed < start) {
             self.printer.context_separator();
         }
+        let last_printed = cmp::min(end + 1, self.inp.lastnl);
+        self.count_lines(start);
+        self.add_line(last_printed);
         self.printer.context(
             &self.path, &self.inp.buf, start, end, self.line_count);
-        self.last_printed = Some((start, cmp::min(end + 1, self.inp.lastnl)));
+        self.last_printed = last_printed;
+    }
+
+    #[inline(always)]
+    fn count_lines(&mut self, upto: usize) {
+        if let Some(ref mut line_count) = self.line_count {
+            *line_count += count_lines(&self.inp.buf[self.last_line..upto]);
+            self.last_line = upto;
+        }
+    }
+
+    #[inline(always)]
+    fn add_line(&mut self, line_end: usize) {
+        if let Some(ref mut line_count) = self.line_count {
+            *line_count += 1;
+            self.last_line = line_end;
+        }
     }
 }
 
@@ -499,6 +513,9 @@ fn start_of_previous_lines(
         end -= 1;
     }
     if buf[end] == b'\n' {
+        if end == 0 {
+            return end + 1;
+        }
         end -= 1;
     }
     while count > 0 {
@@ -783,7 +800,10 @@ and exhibited clearly, with a label attached.\
     }
 
     macro_rules! before_context {
-        ($name:ident, $query:expr, $num:expr, $expected:expr) => {
+        ($name:ident, $query:expr, $num:expr, $expect:expr) => {
+            before_context!($name, $query, $num, $expect, false);
+        };
+        ($name:ident, $query:expr, $num:expr, $expect:expr, $invert:expr) => {
             #[test]
             fn $name() {
                 let text = hay("\
@@ -798,46 +818,66 @@ and exhibited clearly, with a label attached.\
                 let mut pp = Printer::new(vec![]);
                 let grep = matcher($query);
                 let count = {
-                    let searcher = Searcher::new(
+                    let mut searcher = Searcher::new(
                         &mut inp, &mut pp, &grep, test_path(), text);
-                    searcher.before_context($num).run().unwrap()
+                    searcher = searcher.line_number(true);
+                    searcher = searcher.before_context($num);
+                    searcher = searcher.invert_match($invert);
+                    searcher.run().unwrap()
                 };
                 let out = String::from_utf8(pp.into_inner()).unwrap();
-                assert_eq!(out, $expected);
+                assert_eq!(out, $expect);
             }
-        }
+        };
     }
 
     before_context!(before_context_one, "Sherlock", 1, "\
-/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
-/baz.rs-Holmeses, success in the province of detective work must always
-/baz.rs:be, to a very large extent, the result of luck. Sherlock Holmes
+/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs-2-Holmeses, success in the province of detective work must always
+/baz.rs:3:be, to a very large extent, the result of luck. Sherlock Holmes
 ");
 
+    before_context!(before_context_invert_one1, "Sherlock", 1, "\
+/baz.rs-1-For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs:2:Holmeses, success in the province of detective work must always
+/baz.rs-3-be, to a very large extent, the result of luck. Sherlock Holmes
+/baz.rs:4:can extract a clew from a wisp of straw or a flake of cigar ash;
+/baz.rs:5:but Doctor Watson has to have it taken out for him and dusted,
+/baz.rs:6:and exhibited clearly, with a label attached.
+", true);
+
+    before_context!(before_context_invert_one2, " a ", 1, "\
+/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs:2:Holmeses, success in the province of detective work must always
+--
+/baz.rs-4-can extract a clew from a wisp of straw or a flake of cigar ash;
+/baz.rs:5:but Doctor Watson has to have it taken out for him and dusted,
+", true);
+
     before_context!(before_context_two1, "Sherlock", 2, "\
-/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
-/baz.rs-Holmeses, success in the province of detective work must always
-/baz.rs:be, to a very large extent, the result of luck. Sherlock Holmes
+/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs-2-Holmeses, success in the province of detective work must always
+/baz.rs:3:be, to a very large extent, the result of luck. Sherlock Holmes
 ");
 
     before_context!(before_context_two2, "dusted", 2, "\
-/baz.rs-be, to a very large extent, the result of luck. Sherlock Holmes
-/baz.rs-can extract a clew from a wisp of straw or a flake of cigar ash;
-/baz.rs:but Doctor Watson has to have it taken out for him and dusted,
+/baz.rs-3-be, to a very large extent, the result of luck. Sherlock Holmes
+/baz.rs-4-can extract a clew from a wisp of straw or a flake of cigar ash;
+/baz.rs:5:but Doctor Watson has to have it taken out for him and dusted,
 ");
 
     before_context!(before_context_two3, "success|attached", 2, "\
-/baz.rs-For the Doctor Watsons of this world, as opposed to the Sherlock
-/baz.rs:Holmeses, success in the province of detective work must always
+/baz.rs-1-For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs:2:Holmeses, success in the province of detective work must always
 --
-/baz.rs-can extract a clew from a wisp of straw or a flake of cigar ash;
-/baz.rs-but Doctor Watson has to have it taken out for him and dusted,
-/baz.rs:and exhibited clearly, with a label attached.
+/baz.rs-4-can extract a clew from a wisp of straw or a flake of cigar ash;
+/baz.rs-5-but Doctor Watson has to have it taken out for him and dusted,
+/baz.rs:6:and exhibited clearly, with a label attached.
 ");
 
     before_context!(before_context_three, "Sherlock", 3, "\
-/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
-/baz.rs-Holmeses, success in the province of detective work must always
-/baz.rs:be, to a very large extent, the result of luck. Sherlock Holmes
+/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
+/baz.rs-2-Holmeses, success in the province of detective work must always
+/baz.rs:3:be, to a very large extent, the result of luck. Sherlock Holmes
 ");
 }