diff --git a/Lib/idlelib/News3.txt b/Lib/idlelib/News3.txt index 68702ac8fb9157..a3f5b7fb6e1410 100644 --- a/Lib/idlelib/News3.txt +++ b/Lib/idlelib/News3.txt @@ -1,3 +1,12 @@ +What's New in IDLE 3.14.0 +(since 3.13.0) +Released on 2025-10-xx +========================= + + +gh-67407: Improve the Find, Replace and Find in Files dialogs. + + What's New in IDLE 3.13.0 (since 3.12.0) Released on 2024-10-xx diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py index 42048ff2395fe1..216002c4fbd4bf 100644 --- a/Lib/idlelib/grep.py +++ b/Lib/idlelib/grep.py @@ -8,7 +8,7 @@ import sys from tkinter import StringVar, BooleanVar -from tkinter.ttk import Checkbutton # Frame imported in ...Base +from tkinter.ttk import Checkbutton, Frame from idlelib.searchbase import SearchDialogBase from idlelib import searchengine @@ -64,7 +64,7 @@ def findfiles(folder, pattern, recursive): class GrepDialog(SearchDialogBase): "Dialog for searching multiple files." - title = "Find in Files Dialog" + title = "Find in Files" icon = "Grep" needwrapbutton = 0 @@ -112,7 +112,7 @@ def open(self, text, searchphrase, io=None): def create_entries(self): "Create base entry widgets and add widget for search path." SearchDialogBase.create_entries(self) - self.globent = self.make_entry("In files:", self.globvar)[0] + self.globent = self.make_entry("In files", self.globvar)[0] def create_other_buttons(self): "Add check button to recurse down subdirectories." @@ -122,9 +122,10 @@ def create_other_buttons(self): btn.pack(side="top", fill="both") def create_command_buttons(self): - "Create base command buttons and add button for Search Files." - SearchDialogBase.create_command_buttons(self) - self.make_button("Search Files", self.default_command, isdef=True) + """Create base command buttons and add button for Search Files.""" + f = self.buttonframe = Frame(self.frame) + f.grid(row=3, column=2, padx=4, pady=4) + self.make_button("Search", self.default_command, isdef=True) def default_command(self, event=None): """Grep for search pattern in file path. The default command is bound diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index a7293774eecaeb..c3698d331e4deb 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -264,8 +264,7 @@ 'file': 'replace', 'kwds': {}, 'msg': "Click the 'Replace' button.\n" - "Test various replace options in the 'Replace dialog'.\n" - "Click [Close] or [X] to close the 'Replace Dialog'." + "Test various replace options in the 'Replace dialog'." } _scrolled_list_spec = { @@ -281,15 +280,13 @@ 'file': 'search', 'kwds': {}, 'msg': "Click the 'Search' button.\n" - "Test various search options in the 'Search dialog'.\n" - "Click [Close] or [X] to close the 'Search Dialog'." + "Test various search options in the 'Search dialog'." } _searchbase_spec = { 'file': 'searchbase', 'kwds': {}, - 'msg': "Check the appearance of the base search dialog\n" - "Its only action is to close." + 'msg': "Check the appearance of the base search dialog" } show_idlehelp_spec = { diff --git a/Lib/idlelib/idle_test/test_searchbase.py b/Lib/idlelib/idle_test/test_searchbase.py index 8c9c410ebaf47c..0aaa84e2638f8f 100644 --- a/Lib/idlelib/idle_test/test_searchbase.py +++ b/Lib/idlelib/idle_test/test_searchbase.py @@ -85,7 +85,7 @@ def test_make_entry(self): equal(int(egi['row']), 0) equal(int(egi['column']), 1) equal(int(egi['rowspan']), 1) - equal(int(egi['columnspan']), 1) + equal(int(egi['columnspan']), 2) equal(self.dialog.row, 1) def test_create_entries(self): @@ -148,12 +148,6 @@ def test_make_button(self): def test_create_command_buttons(self): self.dialog.frame = Frame(self.root) self.dialog.create_command_buttons() - # Look for close button command in buttonframe - closebuttoncommand = '' - for child in self.dialog.buttonframe.winfo_children(): - if child['text'] == 'Close': - closebuttoncommand = child['command'] - self.assertIn('close', closebuttoncommand) if __name__ == '__main__': diff --git a/Lib/idlelib/replace.py b/Lib/idlelib/replace.py index 3716d841568d30..9f8077d3a8bf85 100644 --- a/Lib/idlelib/replace.py +++ b/Lib/idlelib/replace.py @@ -32,7 +32,7 @@ def replace(text, insert_tags=None): class ReplaceDialog(SearchDialogBase): "Dialog for finding and replacing a pattern in text." - title = "Replace Dialog" + title = "Replace" icon = "Replace" def __init__(self, root, engine): @@ -69,7 +69,7 @@ def open(self, text, searchphrase=None, *, insert_tags=None): def create_entries(self): "Create base and additional label and text entry widgets." SearchDialogBase.create_entries(self) - self.replent = self.make_entry("Replace with:", self.replvar)[0] + self.replent = self.make_entry("Replace with", self.replvar)[0] def create_command_buttons(self): """Create base and additional command buttons. @@ -78,9 +78,8 @@ def create_command_buttons(self): Replace+Find, and Replace All. """ SearchDialogBase.create_command_buttons(self) - self.make_button("Find", self.find_it) - self.make_button("Replace", self.replace_it) - self.make_button("Replace+Find", self.default_command, isdef=True) + self.make_button("Find Next", self.find_it) + self.make_button("Replace", self.default_command, isdef=True) self.make_button("Replace All", self.replace_all) def find_it(self, event=None): @@ -88,7 +87,7 @@ def find_it(self, event=None): self.do_find(False) def replace_it(self, event=None): - """Handle the Replace button. + """Only used in test case If the find is successful, then perform replace. """ diff --git a/Lib/idlelib/searchbase.py b/Lib/idlelib/searchbase.py index 64ed50c7364be3..08b64853e813ff 100644 --- a/Lib/idlelib/searchbase.py +++ b/Lib/idlelib/searchbase.py @@ -26,7 +26,7 @@ class SearchDialogBase: add widgets. ''' - title = "Search Dialog" # replace in subclasses + title = "Find" # replace in subclasses icon = "Search" needwrapbutton = 1 # not in Find in Files @@ -92,8 +92,6 @@ def create_widgets(self): top.grid_rowconfigure(0, weight=100) self.row = 0 - self.frame.grid_columnconfigure(0, pad=2, weight=0) - self.frame.grid_columnconfigure(1, pad=2, minsize=100, weight=100) self.create_entries() # row 0 (and maybe 1), cols 0, 1 self.create_option_buttons() # next row, cols 0, 1 @@ -109,13 +107,13 @@ def make_entry(self, label_text, var): label = Label(self.frame, text=label_text) label.grid(row=self.row, column=0, sticky="nw") entry = Entry(self.frame, textvariable=var, exportselection=0) - entry.grid(row=self.row, column=1, sticky="nwe") - self.row = self.row + 1 + entry.grid(row=self.row, column=1, columnspan=2, padx=4, pady=4, sticky="nwe") + self.row += 1 return entry, label def create_entries(self): "Create one or more entry lines with make_entry." - self.ent = self.make_entry("Find:", self.engine.patvar)[0] + self.ent = self.make_entry("Find", self.engine.patvar)[0] def make_frame(self,labeltext=None): '''Return (frame, label). @@ -179,10 +177,7 @@ def make_button(self, label, command, isdef=0): def create_command_buttons(self): "Place buttons in vertical command frame gridded on right." f = self.buttonframe = Frame(self.frame) - f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2) - - b = self.make_button("Close", self.close) - b.lower() + f.grid(row=2, column=2, padx=4, pady=4) class _searchbase(SearchDialogBase): # htest # diff --git a/Misc/NEWS.d/next/Library/2024-07-29-20-11-27.gh-issue-67407.nhILB2.rst b/Misc/NEWS.d/next/Library/2024-07-29-20-11-27.gh-issue-67407.nhILB2.rst new file mode 100644 index 00000000000000..1e6f2f96c4dead --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-29-20-11-27.gh-issue-67407.nhILB2.rst @@ -0,0 +1,2 @@ +Improve IDLE Find, Replace and Find in Files dialogs. Patch by Wulian233 and +AlSweigart.