From 30969bb6e6170dacf8cb3f54657801492a42640e Mon Sep 17 00:00:00 2001 From: Sören Tempel Date: Sun, 30 May 2021 06:16:27 +0200 Subject: Preliminary TextBuffer SearchBar support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still lacking some configuration options (highlight all, case insensitive search, …) and focus is not currently restored to the TermView on close currently. --- saneterm/keys.py | 2 ++ saneterm/search.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ saneterm/terminal.py | 20 +++++++++++++--- 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 saneterm/search.py diff --git a/saneterm/keys.py b/saneterm/keys.py index 6b85ede..ab471a2 100644 --- a/saneterm/keys.py +++ b/saneterm/keys.py @@ -17,7 +17,9 @@ class Bindings(): bind "a" { "move-input-start" () }; bind "e" { "move-input-end" () }; bind "j" { "insert-at-cursor" ("\\n") }; + bind "l" { "clear-view" () }; + bind "f" { "toggle-search" () }; bind "w" { "delete-from-cursor" (word-ends, -1) }; bind "h" { "backspace" () }; diff --git a/saneterm/search.py b/saneterm/search.py new file mode 100644 index 0000000..98cfb34 --- /dev/null +++ b/saneterm/search.py @@ -0,0 +1,64 @@ +from gi.repository import Gtk + +class SearchBar(Gtk.SearchBar): + "SearchBar implements Gtk.SearchBar on a Gtk.TextBuffer." + + BG_COLOR = "yellow" + FG_COLOR = "black" + + def __init__(self, buffer): + Gtk.SearchBar.__init__(self) + self.__buffer = buffer + + self.__match = None + self.__tag = buffer.create_tag("search-match", + background=self.BG_COLOR, + foreground=self.FG_COLOR) + + search_entry = Gtk.SearchEntry.new() + search_entry.connect("search-changed", self.__search_changed) + search_entry.connect("next-match", self.__next_match) + search_entry.connect("previous-match", self.__prev_match) + + self.set_show_close_button(True) + self.connect_entry(search_entry) + self.add(search_entry) + + def __find_match(self, entry, start, forward=True): + buf = self.__buffer + text = entry.get_text() + + # Remove old match. + buf.remove_tag(self.__tag, + buf.get_start_iter(), + buf.get_end_iter()) + + if forward: + self.__match = start.forward_search(text, 0, None) + else: + self.__match = start.backward_search(text, 0, None) + + if self.__match: + mstart, mend = self.__match + buf.apply_tag(self.__tag, mstart, mend) + + def __search_changed(self, entry): + self.__find_match(entry, self.__buffer.get_start_iter()) + + def __next_match(self, entry): + # Wrap around if no match was found previously. + if self.__match is None: + start = self.__buffer.get_start_iter() + else: + _, start = self.__match + + self.__find_match(entry, start) + + def __prev_match(self, entry): + # Wrap around if no match was found previously. + if self.__match is None: + start = self.__buffer.get_end_iter() + else: + start, _ = self.__match + + self.__find_match(entry, start, forward=False) diff --git a/saneterm/terminal.py b/saneterm/terminal.py index 2f71245..c25f596 100644 --- a/saneterm/terminal.py +++ b/saneterm/terminal.py @@ -7,6 +7,7 @@ import fcntl import struct from . import keys +from .search import SearchBar from .history import History from .termview import * @@ -86,13 +87,22 @@ class Terminal(Gtk.Window): for key, idx in keys.CTRL.items(): bindings.add_bind(key, "termios-ctrlkey", idx) + vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0) + self.add(vbox) + self.scroll = Gtk.ScrolledWindow().new(None, None) self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS) - self.scroll.add(self.termview) - self.add(self.scroll) - self.update_wrapmode() + vbox.pack_start(self.scroll, True, True, 0) + + self.search_bar = SearchBar(self.termview.get_buffer()) + vbox.pack_start(self.search_bar, False, True, 0) + + GObject.signal_new("toggle-search", self.termview, + GObject.SIGNAL_ACTION, GObject.TYPE_NONE, + ()) + self.termview.connect("toggle-search", self.toggle_search, self.search_bar) GObject.signal_new("history-entry", self.termview, GObject.SIGNAL_ACTION, GObject.TYPE_NONE, @@ -155,6 +165,10 @@ class Terminal(Gtk.Window): self.termview.insert_data(self.decoder.decode(data)) return GLib.SOURCE_CONTINUE + def toggle_search(self, termview, search_bar): + active = search_bar.get_search_mode() + search_bar.set_search_mode(not active) + def reset_history_index(self): self.hist_index = -1 -- cgit 1.4.1