diff options
-rw-r--r-- | Lib/idlelib/configdialog.py | 275 | ||||
-rw-r--r-- | Lib/idlelib/idle_test/test_configdialog.py | 44 | ||||
-rw-r--r-- | Misc/NEWS.d/next/IDLE/2021-06-08-03-04-51.bpo-40468.tUCGUb.rst | 6 |
3 files changed, 184 insertions, 141 deletions
diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 9c0153b..e3fa34f 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -116,11 +116,14 @@ class ConfigDialog(Toplevel): self.highpage = HighPage(note, self.extpage) self.fontpage = FontPage(note, self.highpage) self.keyspage = KeysPage(note, self.extpage) - self.genpage = GenPage(note) + self.winpage = WinPage(note) + self.shedpage = ShedPage(note) + note.add(self.fontpage, text='Fonts/Tabs') note.add(self.highpage, text='Highlights') note.add(self.keyspage, text=' Keys ') - note.add(self.genpage, text=' General ') + note.add(self.winpage, text=' Windows ') + note.add(self.shedpage, text=' Shell/Ed ') note.add(self.extpage, text='Extensions') note.enable_traversal() note.pack(side=TOP, expand=TRUE, fill=BOTH) @@ -1594,14 +1597,14 @@ class KeysPage(Frame): self.set_keys_type() -class GenPage(Frame): +class WinPage(Frame): def __init__(self, master): super().__init__(master) self.init_validators() - self.create_page_general() - self.load_general_cfg() + self.create_page_windows() + self.load_windows_cfg() def init_validators(self): digits_or_empty_re = re.compile(r'[0-9]*') @@ -1610,26 +1613,17 @@ class GenPage(Frame): return digits_or_empty_re.fullmatch(s) is not None self.digits_only = (self.register(is_digits_or_empty), '%P',) - def create_page_general(self): - """Return frame of widgets for General tab. - - Enable users to provisionally change general options. Function - load_general_cfg initializes tk variables and helplist using - idleConf. Radiobuttons startup_shell_on and startup_editor_on - set var startup_edit. Radiobuttons save_ask_on and save_auto_on - set var autosave. Entry boxes win_width_int and win_height_int - set var win_width and win_height. Setting var_name invokes the - default callback that adds option to changes. + def create_page_windows(self): + """Return frame of widgets for Windows tab. - Helplist: load_general_cfg loads list user_helplist with - name, position pairs and copies names to listbox helplist. - Clicking a name invokes help_source selected. Clicking - button_helplist_name invokes helplist_item_name, which also - changes user_helplist. These functions all call - set_add_delete_state. All but load call update_help_changes to - rewrite changes['main']['HelpFiles']. + Enable users to provisionally change general window options. + Function load_windows_cfg initializes tk variables idleConf. + Radiobuttons startup_shell_on and startup_editor_on set var + startup_edit. Entry boxes win_width_int and win_height_int set var + win_width and win_height. Setting var_name invokes the default + callback that adds option to changes. - Widgets for GenPage(Frame): (*) widgets bound to self + Widgets for WinPage(Frame): (*) widgets bound to self frame_window: LabelFrame frame_run: Frame startup_title: Label @@ -1654,24 +1648,9 @@ class GenPage(Frame): paren_time_title: Label (*)paren_flash_time: Entry - flash_delay (*)bell_on: Checkbutton - paren_bell - frame_editor: LabelFrame - frame_save: Frame - run_save_title: Label - (*)save_ask_on: Radiobutton - autosave - (*)save_auto_on: Radiobutton - autosave frame_format: Frame format_width_title: Label (*)format_width_int: Entry - format_width - frame_line_numbers_default: Frame - line_numbers_default_title: Label - (*)line_numbers_default_bool: Checkbutton - line_numbers_default - frame_context: Frame - context_title: Label - (*)context_int: Entry - context_lines - frame_shell: LabelFrame - frame_auto_squeeze_min_lines: Frame - auto_squeeze_min_lines_title: Label - (*)auto_squeeze_min_lines_int: Entry - auto_squeeze_min_lines """ # Integer values need StringVar because int('') raises. self.startup_edit = tracers.add( @@ -1690,29 +1669,13 @@ class GenPage(Frame): StringVar(self), ('extensions', 'ParenMatch', 'flash-delay')) self.paren_bell = tracers.add( BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) - - self.auto_squeeze_min_lines = tracers.add( - StringVar(self), ('main', 'PyShell', 'auto-squeeze-min-lines')) - - self.autosave = tracers.add( - IntVar(self), ('main', 'General', 'autosave')) self.format_width = tracers.add( StringVar(self), ('extensions', 'FormatParagraph', 'max-width')) - self.line_numbers_default = tracers.add( - BooleanVar(self), - ('main', 'EditorWindow', 'line-numbers-default')) - self.context_lines = tracers.add( - StringVar(self), ('extensions', 'CodeContext', 'maxlines')) # Create widgets: - # Section frames. frame_window = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Window Preferences') - frame_editor = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Editor Preferences') - frame_shell = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Shell Preferences') - # Frame_window. + frame_run = Frame(frame_window, borderwidth=0) startup_title = Label(frame_run, text='At Startup') self.startup_editor_on = Radiobutton( @@ -1747,8 +1710,7 @@ class GenPage(Frame): self.auto_wait_int = Entry(frame_autocomplete, width=6, textvariable=self.autocomplete_wait, validatecommand=self.digits_only, - validate='key', - ) + validate='key') frame_paren1 = Frame(frame_window, borderwidth=0) paren_style_title = Label(frame_paren1, text='Paren Match Style') @@ -1763,55 +1725,16 @@ class GenPage(Frame): frame_paren2, textvariable=self.flash_delay, width=6) self.bell_on = Checkbutton( frame_paren2, text="Bell on Mismatch", variable=self.paren_bell) - - # Frame_editor. - frame_save = Frame(frame_editor, borderwidth=0) - run_save_title = Label(frame_save, text='At Start of Run (F5) ') - self.save_ask_on = Radiobutton( - frame_save, variable=self.autosave, value=0, - text="Prompt to Save") - self.save_auto_on = Radiobutton( - frame_save, variable=self.autosave, value=1, - text='No Prompt') - - frame_format = Frame(frame_editor, borderwidth=0) + frame_format = Frame(frame_window, borderwidth=0) format_width_title = Label(frame_format, text='Format Paragraph Max Width') self.format_width_int = Entry( frame_format, textvariable=self.format_width, width=4, validatecommand=self.digits_only, validate='key', - ) - - frame_line_numbers_default = Frame(frame_editor, borderwidth=0) - line_numbers_default_title = Label( - frame_line_numbers_default, text='Show line numbers in new windows') - self.line_numbers_default_bool = Checkbutton( - frame_line_numbers_default, - variable=self.line_numbers_default, - width=1) - - frame_context = Frame(frame_editor, borderwidth=0) - context_title = Label(frame_context, text='Max Context Lines :') - self.context_int = Entry( - frame_context, textvariable=self.context_lines, width=3, - validatecommand=self.digits_only, validate='key', - ) - - # Frame_shell. - frame_auto_squeeze_min_lines = Frame(frame_shell, borderwidth=0) - auto_squeeze_min_lines_title = Label(frame_auto_squeeze_min_lines, - text='Auto-Squeeze Min. Lines:') - self.auto_squeeze_min_lines_int = Entry( - frame_auto_squeeze_min_lines, width=4, - textvariable=self.auto_squeeze_min_lines, - validatecommand=self.digits_only, validate='key', - ) + ) # Pack widgets: - # Body. frame_window.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_editor.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_shell.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) # frame_run. frame_run.pack(side=TOP, padx=5, pady=0, fill=X) startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5) @@ -1840,34 +1763,10 @@ class GenPage(Frame): paren_time_title.pack(side=LEFT, anchor=W, padx=5) self.bell_on.pack(side=RIGHT, anchor=E, padx=15, pady=5) self.paren_flash_time.pack(side=TOP, anchor=W, padx=15, pady=5) - - # frame_save. - frame_save.pack(side=TOP, padx=5, pady=0, fill=X) - run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) - self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) # frame_format. frame_format.pack(side=TOP, padx=5, pady=0, fill=X) format_width_title.pack(side=LEFT, anchor=W, padx=5, pady=5) self.format_width_int.pack(side=TOP, padx=10, pady=5) - # frame_line_numbers_default. - frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X) - line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5) - # frame_context. - frame_context.pack(side=TOP, padx=5, pady=0, fill=X) - context_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.context_int.pack(side=TOP, padx=5, pady=5) - - # frame_auto_squeeze_min_lines - frame_auto_squeeze_min_lines.pack(side=TOP, padx=5, pady=0, fill=X) - auto_squeeze_min_lines_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.auto_squeeze_min_lines_int.pack(side=TOP, padx=5, pady=5) - - def load_general_cfg(self): - "Load current configuration settings for the general options." - self.load_windows_cfg() - self.load_shelled_cfg() def load_windows_cfg(self): # Set variables for all windows. @@ -1887,22 +1786,142 @@ class GenPage(Frame): 'extensions', 'ParenMatch', 'flash-delay', type='int')) self.paren_bell.set(idleConf.GetOption( 'extensions', 'ParenMatch', 'bell')) + self.format_width.set(idleConf.GetOption( + 'extensions', 'FormatParagraph', 'max-width', type='int')) + + +class ShedPage(Frame): + + def __init__(self, master): + super().__init__(master) + + self.init_validators() + self.create_page_shed() + self.load_shelled_cfg() + + def init_validators(self): + digits_or_empty_re = re.compile(r'[0-9]*') + def is_digits_or_empty(s): + "Return 's is blank or contains only digits'" + return digits_or_empty_re.fullmatch(s) is not None + self.digits_only = (self.register(is_digits_or_empty), '%P',) + + def create_page_shed(self): + """Return frame of widgets for Shell/Ed tab. + + Enable users to provisionally change shell and editor options. + Function load_shed_cfg initializes tk variables using idleConf. + Entry box auto_squeeze_min_lines_int sets + auto_squeeze_min_lines_int. Setting var_name invokes the + default callback that adds option to changes. + + Widgets for ShedPage(Frame): (*) widgets bound to self + frame_shell: LabelFrame + frame_auto_squeeze_min_lines: Frame + auto_squeeze_min_lines_title: Label + (*)auto_squeeze_min_lines_int: Entry - + auto_squeeze_min_lines + frame_editor: LabelFrame + frame_save: Frame + run_save_title: Label + (*)save_ask_on: Radiobutton - autosave + (*)save_auto_on: Radiobutton - autosave + frame_format: Frame + format_width_title: Label + (*)format_width_int: Entry - format_width + frame_line_numbers_default: Frame + line_numbers_default_title: Label + (*)line_numbers_default_bool: Checkbutton - line_numbers_default + frame_context: Frame + context_title: Label + (*)context_int: Entry - context_lines + """ + # Integer values need StringVar because int('') raises. + self.auto_squeeze_min_lines = tracers.add( + StringVar(self), ('main', 'PyShell', 'auto-squeeze-min-lines')) + + self.autosave = tracers.add( + IntVar(self), ('main', 'General', 'autosave')) + self.line_numbers_default = tracers.add( + BooleanVar(self), + ('main', 'EditorWindow', 'line-numbers-default')) + self.context_lines = tracers.add( + StringVar(self), ('extensions', 'CodeContext', 'maxlines')) + + # Create widgets: + frame_shell = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Shell Preferences') + frame_editor = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Editor Preferences') + # Frame_shell. + frame_auto_squeeze_min_lines = Frame(frame_shell, borderwidth=0) + auto_squeeze_min_lines_title = Label(frame_auto_squeeze_min_lines, + text='Auto-Squeeze Min. Lines:') + self.auto_squeeze_min_lines_int = Entry( + frame_auto_squeeze_min_lines, width=4, + textvariable=self.auto_squeeze_min_lines, + validatecommand=self.digits_only, validate='key', + ) + # Frame_editor. + frame_save = Frame(frame_editor, borderwidth=0) + run_save_title = Label(frame_save, text='At Start of Run (F5) ') + + self.save_ask_on = Radiobutton( + frame_save, variable=self.autosave, value=0, + text="Prompt to Save") + self.save_auto_on = Radiobutton( + frame_save, variable=self.autosave, value=1, + text='No Prompt') + + frame_line_numbers_default = Frame(frame_editor, borderwidth=0) + line_numbers_default_title = Label( + frame_line_numbers_default, text='Show line numbers in new windows') + self.line_numbers_default_bool = Checkbutton( + frame_line_numbers_default, + variable=self.line_numbers_default, + width=1) + + frame_context = Frame(frame_editor, borderwidth=0) + context_title = Label(frame_context, text='Max Context Lines :') + self.context_int = Entry( + frame_context, textvariable=self.context_lines, width=3, + validatecommand=self.digits_only, validate='key', + ) + + # Pack widgets: + frame_shell.pack(side=TOP, padx=5, pady=5, fill=BOTH) + Label(self).pack() # Spacer -- better solution? + frame_editor.pack(side=TOP, padx=5, pady=5, fill=BOTH) + # frame_auto_squeeze_min_lines + frame_auto_squeeze_min_lines.pack(side=TOP, padx=5, pady=0, fill=X) + auto_squeeze_min_lines_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.auto_squeeze_min_lines_int.pack(side=TOP, padx=5, pady=5) + # frame_save. + frame_save.pack(side=TOP, padx=5, pady=0, fill=X) + run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) + self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) + # frame_line_numbers_default. + frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X) + line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5) + # frame_context. + frame_context.pack(side=TOP, padx=5, pady=0, fill=X) + context_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.context_int.pack(side=TOP, padx=5, pady=5) def load_shelled_cfg(self): + # Set variables for shell windows. + self.auto_squeeze_min_lines.set(idleConf.GetOption( + 'main', 'PyShell', 'auto-squeeze-min-lines', type='int')) # Set variables for editor windows. self.autosave.set(idleConf.GetOption( 'main', 'General', 'autosave', default=0, type='bool')) - self.format_width.set(idleConf.GetOption( - 'extensions', 'FormatParagraph', 'max-width', type='int')) self.line_numbers_default.set(idleConf.GetOption( 'main', 'EditorWindow', 'line-numbers-default', type='bool')) self.context_lines.set(idleConf.GetOption( 'extensions', 'CodeContext', 'maxlines', type='int')) - # Set variables for shell windows. - self.auto_squeeze_min_lines.set(idleConf.GetOption( - 'main', 'PyShell', 'auto-squeeze-min-lines', type='int')) - class ExtPage(Frame): def __init__(self, master): diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index e01aa63..f71d1b1 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -1203,7 +1203,7 @@ class KeysPageTest(unittest.TestCase): del d.askyesno -class GenPageTest(unittest.TestCase): +class WinPageTest(unittest.TestCase): """Test that general tab widgets enable users to make changes. Test that widget actions set vars, that var changes add @@ -1211,24 +1211,22 @@ class GenPageTest(unittest.TestCase): """ @classmethod def setUpClass(cls): - page = cls.page = dialog.genpage + page = cls.page = dialog.winpage dialog.note.select(page) page.update() def setUp(self): changes.clear() - def test_load_general_cfg(self): + def test_load_windows_cfg(self): # Set to wrong values, load, check right values. eq = self.assertEqual d = self.page d.startup_edit.set(1) - d.autosave.set(1) d.win_width.set(1) d.win_height.set(1) - d.load_general_cfg() + d.load_windows_cfg() eq(d.startup_edit.get(), 0) - eq(d.autosave.get(), 0) eq(d.win_width.get(), '80') eq(d.win_height.get(), '40') @@ -1274,6 +1272,35 @@ class GenPageTest(unittest.TestCase): d.bell_on.invoke() eq(extpage, {'ParenMatch': {'bell': 'False'}}) + def test_paragraph(self): + self.page.format_width_int.delete(0, 'end') + self.page.format_width_int.insert(0, '11') + self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}}) + + +class GenPageTest(unittest.TestCase): + """Test that shed tab widgets enable users to make changes. + + Test that widget actions set vars, that var changes add + options to changes. + """ + @classmethod + def setUpClass(cls): + page = cls.page = dialog.shedpage + dialog.note.select(page) + page.update() + + def setUp(self): + changes.clear() + + def test_load_shelled_cfg(self): + # Set to wrong values, load, check right values. + eq = self.assertEqual + d = self.page + d.autosave.set(1) + d.load_shelled_cfg() + eq(d.autosave.get(), 0) + def test_autosave(self): d = self.page d.save_auto_on.invoke() @@ -1281,11 +1308,6 @@ class GenPageTest(unittest.TestCase): d.save_ask_on.invoke() self.assertEqual(mainpage, {'General': {'autosave': '0'}}) - def test_paragraph(self): - self.page.format_width_int.delete(0, 'end') - self.page.format_width_int.insert(0, '11') - self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}}) - def test_context(self): self.page.context_int.delete(0, 'end') self.page.context_int.insert(0, '1') diff --git a/Misc/NEWS.d/next/IDLE/2021-06-08-03-04-51.bpo-40468.tUCGUb.rst b/Misc/NEWS.d/next/IDLE/2021-06-08-03-04-51.bpo-40468.tUCGUb.rst index 79cb1cc..526036c 100644 --- a/Misc/NEWS.d/next/IDLE/2021-06-08-03-04-51.bpo-40468.tUCGUb.rst +++ b/Misc/NEWS.d/next/IDLE/2021-06-08-03-04-51.bpo-40468.tUCGUb.rst @@ -1,2 +1,4 @@ -Shorten settings dialog by moving help sources to extensions tab. This will -improve issues with dialog being too tall for some screens. +Split the settings dialog General tab into Windows and Shell/ED tabs. +Move help sources, which extend the Help menu, to the Extensions tab. +Make space for new options and shorten the dialog. +The latter makes the dialog better fit small screens. |