chiark / gitweb /
Implement searching in the file pager.
authorSimon Tatham <anakin@pobox.com>
Sat, 9 Dec 2023 18:31:26 +0000 (18:31 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 9 Dec 2023 18:35:34 +0000 (18:35 +0000)
cursesclient.py

index f6898524b87c7e0b02f337bba6c28b37bcad85bf..c5a9ed5013d871f74fb4c4be87b985d6b9c2f26e 100644 (file)
@@ -2,6 +2,7 @@ import collections
 import curses
 import itertools
 import os
+import re
 import select
 import signal
 import sys
@@ -434,6 +435,8 @@ class File(Activity):
     def __init__(self, cc):
         self.cc = cc
         self.mode = 'normal'
+        self.search_direction = None
+        self.search_re = None
 
     def handle_key(self, ch):
         backward_keys = {'-', 'b', 'B', curses.KEY_PPAGE, curses.KEY_LEFT}
@@ -468,6 +471,20 @@ class File(Activity):
                 self.thread_mode()
             elif ch in {'i', 'I'}:
                 self.info_mode()
+            elif ch in {'\\'}:
+                self.search_direction = -1
+                self.push_to(BottomLinePrompt(
+                    self.cc, self.got_search_text,
+                    "Search back (blank = last): "))
+            elif ch in {'/'}:
+                self.search_direction = +1
+                self.push_to(BottomLinePrompt(
+                    self.cc, self.got_search_text,
+                    "Search (blank = last): "))
+            elif ch in {'n', 'N'}:
+                if (self.search_direction is not None and
+                    self.search_re is not None):
+                    self.search(self.search_direction, self.search_re)
         elif self.mode == 'select':
             if ch in {'q', 'Q'}:
                 self.mode = 'normal'
@@ -500,6 +517,21 @@ class File(Activity):
                   ch in {' '}):
                 self.info_complete(False)
 
+    def got_search_text(self, text):
+        if len(text) != 0:
+            try:
+                self.search_re = re.compile(text, flags=re.IGNORECASE)
+            except re.error:
+                curses.beep()
+                # FIXME: real Mono reports an error in the status line
+                # (but still also beeps); waits for you to press Return;
+                # then returns to paging through the file
+                return
+
+        if (self.search_direction is not None and
+            self.search_re is not None):
+            self.search(self.search_direction, self.search_re)
+
     def unprime(self):
         pass # not supported
     def send_mode(self):
@@ -780,6 +812,16 @@ class ObjectFile(File):
     def unprime(self):
         self.primed_to_extend = False
 
+    def search(self, direction, re):
+        pos = self.linepos - 1
+        while True:
+            pos += direction
+            if not 0 <= pos < len(self.lines):
+                curses.beep()
+                return False
+            if re.search(str(self.lines[pos])):
+                return self.move_to(pos + 1)
+
 class StatusFile(ObjectFile):
     items_are_statuses = True
     items_have_authors = True