chiark / gitweb /
Track the latest read item within File's lifetime.
authorSimon Tatham <anakin@pobox.com>
Sat, 6 Jan 2024 11:32:09 +0000 (11:32 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 6 Jan 2024 14:06:13 +0000 (14:06 +0000)
Nothing actually uses it yet.

src/file.rs

index 22680b357642dccfe42fcf1367646e2776cc87ce..07614c4af4af06e2ab2727b6697f05de5b1827cf 100644 (file)
@@ -321,6 +321,7 @@ struct File<Type: FileType, Source: FileDataSource> {
     file_desc: Type,
     search_direction: Option<SearchDirection>,
     last_search: Option<Regex>,
+    latest_read_index: Option<isize>,
 }
 
 impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
@@ -364,6 +365,7 @@ impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
             file_desc,
             search_direction: None,
             last_search: None,
+            latest_read_index: None,
         };
         Ok(ff)
     }
@@ -452,6 +454,30 @@ impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
         }
     }
 
+    fn update_latest_read_index(&mut self) {
+        let pos_item_shown_in_full = match self.pos.width {
+            None => self.pos.line > 0,
+            Some(pw) => match self.last_size {
+                None => false, // if in doubt don't mark things as read
+                Some((sw, _sh)) => if pw == sw {
+                    self.rendered.get(&self.pos.item)
+                        .map_or(false, |lines| self.pos.line == lines.len())
+                } else {
+                    false // similarly, if in doubt
+                }
+            }
+        };
+
+        let latest_read_index = if pos_item_shown_in_full {
+            self.pos.item
+        } else {
+            self.pos.item - 1
+        };
+
+        self.latest_read_index = max(
+            self.latest_read_index, Some(latest_read_index));
+    }
+
     fn update_pos_for_size(&mut self, w: usize, h: usize) {
         if self.pos.width.is_none() && self.pos.line == 0 {
             // Special case: look at the _top_ of the item
@@ -1023,7 +1049,14 @@ impl<Type: FileType, Source: FileDataSource>
             None => panic!("handle_keypress before resize"),
         };
 
-        match self.ui_mode {
+        self.update_latest_read_index();
+
+        // This whole match is in a lambda which we immediately call,
+        // so that if any clause needs to do an early return, it will
+        // only return from this lambda and not the whole function.
+        // That way we never miss the update_latest_read_index at the
+        // end.
+        let action = (|| match self.ui_mode {
             UIMode::Normal => match key {
                 Pr('q') | Pr('Q') => LogicalAction::Pop,
                 Up => {
@@ -1229,7 +1262,11 @@ impl<Type: FileType, Source: FileDataSource>
                 Pr('q') | Pr('Q') => self.abort_selection(),
                 _ => LogicalAction::Nothing,
             }
-        }
+        })();
+
+        self.update_latest_read_index();
+
+        action
     }
 
     fn handle_feed_updates(&mut self, feeds_updated: &HashSet<FeedId>,