Skip to content

Commit 54aa1c9

Browse files
committed
Add interactive search to jump-to dialog
This implements real-time search that updates results as the user types, eliminating the need to press Enter after each query modification. - Interactive search with 150ms debouncing for optimal responsiveness - Visual "Searching..." indicator during search operations The 150ms debounce delay balances UI responsiveness with performance, preventing excessive updates during rapid typing while maintaining the feel of instant feedback.
1 parent 1fa9757 commit 54aa1c9

File tree

1 file changed

+39
-9
lines changed

1 file changed

+39
-9
lines changed

guiconfig.py

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@
104104

105105
# Help text for the jump-to dialog
106106
_JUMP_TO_HELP = """\
107-
Type one or more strings/regexes and press Enter to list items that match all
108-
of them. Python's regex flavor is used (see the 're' module). Double-clicking
109-
an item will jump to it. Item values can be toggled directly within the dialog.\
107+
Type to search - results update as you type. Supports multiple strings/regexes
108+
(space-separated) that must all match. Python's regex flavor is used (see 're'
109+
module). Double-click an item to jump to it. Values can be toggled within the dialog.\
110110
"""
111111

112112

@@ -186,11 +186,13 @@ def menuconfig(kconf):
186186
global _jump_to_tree
187187
global _cur_menu
188188
global _tree_row_index
189+
global _search_after_id
189190

190191
_kconf = kconf
191192

192193
_jump_to_tree = None
193194
_tree_row_index = 0
195+
_search_after_id = None
194196

195197
_create_id_to_node()
196198

@@ -2061,18 +2063,35 @@ def _try_load(filename):
20612063
def _jump_to_dialog(_=None):
20622064
# Pops up a dialog for jumping directly to a particular node. Symbol values
20632065
# can also be changed within the dialog.
2064-
#
2065-
# Note: There's nothing preventing this from doing an incremental search
2066-
# like menuconfig.py does, but currently it's a bit jerky for large Kconfig
2067-
# trees, at least when inputting the beginning of the search string. We'd
2068-
# need to somehow only update the tree items that are shown in the Treeview
2069-
# to fix it.
20702066

20712067
global _jump_to_tree
2068+
global _search_after_id
2069+
2070+
_search_after_id = None
20722071

20732072
def search(_=None):
2073+
# Clear "Searching..." message
2074+
if msglabel["text"] == "Searching...":
2075+
msglabel["text"] = ""
20742076
_update_jump_to_matches(msglabel, entry.get())
20752077

2078+
def interactive_search(_=None):
2079+
# Performs incremental search with debouncing to avoid excessive updates
2080+
global _search_after_id
2081+
2082+
# Cancel any pending search
2083+
if _search_after_id:
2084+
dialog.after_cancel(_search_after_id)
2085+
2086+
# Show searching indicator for non-empty queries
2087+
search_text = entry.get()
2088+
if search_text:
2089+
msglabel["text"] = "Searching..."
2090+
2091+
# Schedule a new search after a short delay (150ms)
2092+
# This provides responsive feedback while avoiding excessive updates
2093+
_search_after_id = dialog.after(150, lambda: search())
2094+
20762095
def jump_to_selected(event=None):
20772096
# Jumps to the selected node and closes the dialog
20782097

@@ -2115,6 +2134,9 @@ def tree_select(_):
21152134
entry.grid(column=0, row=1, sticky="ew", padx=".1c", pady=".1c")
21162135
entry.focus_set()
21172136

2137+
# Bind KeyRelease for interactive search
2138+
entry.bind("<KeyRelease>", interactive_search)
2139+
# Still allow immediate search with Enter
21182140
entry.bind("<Return>", search)
21192141
entry.bind("<KP_Enter>", search)
21202142

@@ -2156,7 +2178,15 @@ def tree_select(_):
21562178
# add=True to avoid overriding the description text update
21572179
tree.bind("<<TreeviewSelect>>", tree_select, add=True)
21582180

2181+
def on_dialog_destroy():
2182+
# Clean up any pending search callbacks
2183+
global _search_after_id
2184+
if _search_after_id:
2185+
dialog.after_cancel(_search_after_id)
2186+
_search_after_id = None
2187+
21592188
dialog.bind("<Escape>", lambda _: dialog.destroy())
2189+
dialog.protocol("WM_DELETE_WINDOW", lambda: (on_dialog_destroy(), dialog.destroy()))
21602190

21612191
# Wait for the user to be done with the dialog
21622192
_root.wait_window(dialog)

0 commit comments

Comments
 (0)