From 5c57fafbcc72dbeb0ca3a6bc0a3d745b666db60b Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 29 Jun 2017 15:11:01 -0500 Subject: [PATCH 01/47] parenmatch highlighting options adds fg color, bg color, font, and underline options for parens highlighting --- Lib/idlelib/config-extensions.def | 4 ++++ Lib/idlelib/configdialog.py | 4 +++- Lib/idlelib/parenmatch.py | 18 ++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index a24b8c9316ba07..f8abd38d9aa49d 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -73,6 +73,10 @@ format-paragraph= [ParenMatch] enable=True style= expression +font=courier 10 +fgcolor=Black +bgcolor=White +underline=False flash-delay= 500 bell=True [ParenMatch_cfgBindings] diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 4a25846238f6e1..c9f72ca37dab0a 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1419,7 +1419,9 @@ def save_all_changed_extensions(self): ParenMatch: Style indicates what is highlighted when closer is entered: 'opener' - opener '({[' corresponding to closer; 'parens' - both chars; -'expression' (default) - also everything in between. Flash-delay is how +'expression' (default) - also everything in between. Bgcolor and fgcolor +are the matched background and foreground colors, respectively, and accept +named colors and hex values preceeded by a # sign. Flash-delay is how long to highlight if cursor is not moved (0 means forever). ''' } diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index c15cb818cd8fbd..41986d35e801e5 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -41,7 +41,14 @@ class ParenMatch: 'extensions','ParenMatch','flash-delay', type='int',default=500) BELL = idleConf.GetOption( 'extensions','ParenMatch','bell', type='bool',default=1) - HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(),'hilite') + BG_COLOR = idleConf.GetOption("extensions", "ParenMatch", + "bgcolor", type="str", default="LightGray") + FG_COLOR = idleConf.GetOption("extensions", "ParenMatch", + "fgcolor", type="str", default="Black") + P_FONT = idleConf.GetOption("extensions", "ParenMatch", + "font", type="str", default="courier 10 italic") + P_UNDERLINE = idleConf.GetOption("extensions", "ParenMatch", + "underline", type="bool", default=1) RESTORE_VIRTUAL_EVENT_NAME = "<>" # We want the restore event be called before the usual return and @@ -133,7 +140,8 @@ def handle_restore_timer(self, timer_count): def create_tag_opener(self, indices): """Highlight the single paren that matches""" self.text.tag_add("paren", indices[0]) - self.text.tag_config("paren", self.HILITE_CONFIG) + self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, + font=self.P_FONT,underline=self.P_UNDERLINE) def create_tag_parens(self, indices): """Highlight the left and right parens""" @@ -142,7 +150,8 @@ def create_tag_parens(self, indices): else: rightindex = indices[1] self.text.tag_add("paren", indices[0], indices[0]+"+1c", rightindex+"-1c", rightindex) - self.text.tag_config("paren", self.HILITE_CONFIG) + self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, + font=self.P_FONT,underline=self.P_UNDERLINE) def create_tag_expression(self, indices): """Highlight the entire expression""" @@ -151,7 +160,8 @@ def create_tag_expression(self, indices): else: rightindex = indices[1] self.text.tag_add("paren", indices[0], rightindex) - self.text.tag_config("paren", self.HILITE_CONFIG) + self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, + font=self.P_FONT,underline=self.P_UNDERLINE) # any one of the set_timeout_XXX methods can be used depending on # the style From d49170f8b19e30fb5283ff3e2cec131fff1f133e Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 29 Jun 2017 15:46:53 -0500 Subject: [PATCH 02/47] fixed whitespace issue --- Lib/idlelib/parenmatch.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 41986d35e801e5..15e01a3e57ab1c 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -141,7 +141,7 @@ def create_tag_opener(self, indices): """Highlight the single paren that matches""" self.text.tag_add("paren", indices[0]) self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + font=self.P_FONT,underline=self.P_UNDERLINE) def create_tag_parens(self, indices): """Highlight the left and right parens""" @@ -151,7 +151,7 @@ def create_tag_parens(self, indices): rightindex = indices[1] self.text.tag_add("paren", indices[0], indices[0]+"+1c", rightindex+"-1c", rightindex) self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + font=self.P_FONT,underline=self.P_UNDERLINE) def create_tag_expression(self, indices): """Highlight the entire expression""" @@ -161,7 +161,7 @@ def create_tag_expression(self, indices): rightindex = indices[1] self.text.tag_add("paren", indices[0], rightindex) self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + font=self.P_FONT,underline=self.P_UNDERLINE) # any one of the set_timeout_XXX methods can be used depending on # the style From 8c3a9662bcd5c8617a0383a420536d46b472f341 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 30 Jun 2017 08:18:50 -0500 Subject: [PATCH 03/47] only select from highlighting options --- Lib/idlelib/config-extensions.def | 5 +---- Lib/idlelib/configdialog.py | 7 +++---- Lib/idlelib/parenmatch.py | 21 +++++++-------------- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index f8abd38d9aa49d..6f1ec03981b7bd 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -73,10 +73,7 @@ format-paragraph= [ParenMatch] enable=True style= expression -font=courier 10 -fgcolor=Black -bgcolor=White -underline=False +hilite=hilite flash-delay= 500 bell=True [ParenMatch_cfgBindings] diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index c9f72ca37dab0a..cfcf6f49b9acdc 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1419,10 +1419,9 @@ def save_all_changed_extensions(self): ParenMatch: Style indicates what is highlighted when closer is entered: 'opener' - opener '({[' corresponding to closer; 'parens' - both chars; -'expression' (default) - also everything in between. Bgcolor and fgcolor -are the matched background and foreground colors, respectively, and accept -named colors and hex values preceeded by a # sign. Flash-delay is how -long to highlight if cursor is not moved (0 means forever). +'expression' (default) - also everything in between. Hilite determines +what highlighting is used. Flash-delay is how long to highlight if cursor +is not moved (0 means forever). ''' } diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 15e01a3e57ab1c..8f22cb70c34100 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -41,14 +41,10 @@ class ParenMatch: 'extensions','ParenMatch','flash-delay', type='int',default=500) BELL = idleConf.GetOption( 'extensions','ParenMatch','bell', type='bool',default=1) - BG_COLOR = idleConf.GetOption("extensions", "ParenMatch", - "bgcolor", type="str", default="LightGray") - FG_COLOR = idleConf.GetOption("extensions", "ParenMatch", - "fgcolor", type="str", default="Black") - P_FONT = idleConf.GetOption("extensions", "ParenMatch", - "font", type="str", default="courier 10 italic") - P_UNDERLINE = idleConf.GetOption("extensions", "ParenMatch", - "underline", type="bool", default=1) + HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), + idleConf.GetOption( + 'extensions','ParenMatch','hilite', default='expression')) + RESTORE_VIRTUAL_EVENT_NAME = "<>" # We want the restore event be called before the usual return and @@ -140,8 +136,7 @@ def handle_restore_timer(self, timer_count): def create_tag_opener(self, indices): """Highlight the single paren that matches""" self.text.tag_add("paren", indices[0]) - self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + self.text.tag_config("paren", self.HILITE_CONFIG) def create_tag_parens(self, indices): """Highlight the left and right parens""" @@ -150,8 +145,7 @@ def create_tag_parens(self, indices): else: rightindex = indices[1] self.text.tag_add("paren", indices[0], indices[0]+"+1c", rightindex+"-1c", rightindex) - self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + self.text.tag_config("paren", self.HILITE_CONFIG) def create_tag_expression(self, indices): """Highlight the entire expression""" @@ -160,8 +154,7 @@ def create_tag_expression(self, indices): else: rightindex = indices[1] self.text.tag_add("paren", indices[0], rightindex) - self.text.tag_config("paren", background=self.BG_COLOR,foreground=self.FG_COLOR, - font=self.P_FONT,underline=self.P_UNDERLINE) + self.text.tag_config("paren", self.HILITE_CONFIG) # any one of the set_timeout_XXX methods can be used depending on # the style From 757bb38c457956b3b37c234ee2b10b80a5aa7b62 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 30 Jun 2017 08:27:29 -0500 Subject: [PATCH 04/47] fixed whitespace --- Lib/idlelib/parenmatch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 8f22cb70c34100..48f699ac676b0b 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -41,8 +41,8 @@ class ParenMatch: 'extensions','ParenMatch','flash-delay', type='int',default=500) BELL = idleConf.GetOption( 'extensions','ParenMatch','bell', type='bool',default=1) - HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), - idleConf.GetOption( + HILITE_CONFIG = idleConf.GetHighlight( + idleConf.CurrentTheme(), idleConf.GetOption( 'extensions','ParenMatch','hilite', default='expression')) From d7e136c91b1d5d7e5f3e476b3bdc3887e95ed074 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 30 Jun 2017 08:39:03 -0500 Subject: [PATCH 05/47] whitespace --- Lib/idlelib/parenmatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 48f699ac676b0b..2dcd68ebcc1ce1 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -44,7 +44,7 @@ class ParenMatch: HILITE_CONFIG = idleConf.GetHighlight( idleConf.CurrentTheme(), idleConf.GetOption( 'extensions','ParenMatch','hilite', default='expression')) - + RESTORE_VIRTUAL_EVENT_NAME = "<>" # We want the restore event be called before the usual return and From 2adebb95c5706f7f9d530787e76a210f6541945f Mon Sep 17 00:00:00 2001 From: wohlganger Date: Mon, 10 Jul 2017 16:12:37 -0500 Subject: [PATCH 06/47] #27099 - turn builtin extensions to reg modules --- Lib/idlelib/autocomplete.py | 19 ++-- Lib/idlelib/autoexpand.py | 8 -- Lib/idlelib/calltips.py | 8 +- Lib/idlelib/codecontext.py | 31 ++++--- Lib/idlelib/colorizer.py | 1 + Lib/idlelib/config-extensions.def | 67 -------------- Lib/idlelib/config-highlight.def | 12 +++ Lib/idlelib/config-keys.def | 66 ++++++++++++- Lib/idlelib/config-main.def | 53 +++++++++++ Lib/idlelib/config.py | 23 ++++- Lib/idlelib/configdialog.py | 148 +++++++++++++++++++++++------- Lib/idlelib/editor.py | 49 +++++++--- Lib/idlelib/mainmenu.py | 11 ++- Lib/idlelib/paragraph.py | 10 +- Lib/idlelib/parenmatch.py | 31 +++---- Lib/idlelib/rstrip.py | 3 - Lib/idlelib/runscript.py | 2 +- Lib/idlelib/zoomheight.py | 8 +- 18 files changed, 362 insertions(+), 188 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index cd212ccb143a3c..87706c19eae543 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -1,6 +1,5 @@ -"""autocomplete.py - An IDLE extension for automatically completing names. - -This extension can complete either attribute names or file names. It can pop +""" +This can complete either attribute names or file names. It can pop a window with all available names, for the user to select from. """ import os @@ -27,18 +26,10 @@ class AutoComplete: - menudefs = [ - ('edit', [ - ("Show Completions", "<>"), - ]) - ] - - popupwait = idleConf.GetOption("extensions", "AutoComplete", - "popupwait", type="int", default=0) - def __init__(self, editwin=None): self.editwin = editwin if editwin is not None: # not in subprocess or test + self.reset() self.text = editwin.text self.autocompletewindow = None # id of delayed call, and the index of the text insert when @@ -47,6 +38,10 @@ def __init__(self, editwin=None): self._delayed_completion_id = None self._delayed_completion_index = None + def reset(self): + self.popupwait = idleConf.GetOption("main", "EditorWindow", + "autocomplete_wait", type="int", default=0) + def _make_autocomplete_window(self): return autocomplete_w.AutoCompleteWindow(self.text) diff --git a/Lib/idlelib/autoexpand.py b/Lib/idlelib/autoexpand.py index 6b46bee69c95f5..10064c1f6e289b 100644 --- a/Lib/idlelib/autoexpand.py +++ b/Lib/idlelib/autoexpand.py @@ -10,7 +10,6 @@ place before requesting the next selection causes AutoExpand to reset its state. -This is an extension file and there is only one instance of AutoExpand. ''' import re import string @@ -20,13 +19,6 @@ ###$ unix class AutoExpand: - - menudefs = [ - ('edit', [ - ('E_xpand Word', '<>'), - ]), - ] - wordchars = string.ascii_letters + string.digits + "_" def __init__(self, editwin): diff --git a/Lib/idlelib/calltips.py b/Lib/idlelib/calltips.py index a8a3abe6c6982a..6e59a43f40cf72 100644 --- a/Lib/idlelib/calltips.py +++ b/Lib/idlelib/calltips.py @@ -1,4 +1,4 @@ -"""calltips.py - An IDLE Extension to Jog Your Memory +""" Call Tips are floating windows which display function, class, and method parameter and docstring information when you type an opening parenthesis, and @@ -17,12 +17,6 @@ class CallTips: - menudefs = [ - ('edit', [ - ("Show call tip", "<>"), - ]) - ] - def __init__(self, editwin=None): if editwin is None: # subprocess and test self.editwin = None diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 09dc078d63f191..5de187a82584d5 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -1,4 +1,4 @@ -"""codecontext - Extension to display the block context above the edit window +"""codecontext - display the block context above the edit window Once code has scrolled off the top of a window, it can be difficult to determine which block you are in. This extension implements a pane at the top @@ -26,13 +26,7 @@ lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() class CodeContext: - menudefs = [('options', [('!Code Conte_xt', '<>')])] - context_depth = idleConf.GetOption("extensions", "CodeContext", - "numlines", type="int", default=3) - bgcolor = idleConf.GetOption("extensions", "CodeContext", - "bgcolor", type="str", default="LightGray") - fgcolor = idleConf.GetOption("extensions", "CodeContext", - "fgcolor", type="str", default="Black") + def __init__(self, editwin): self.editwin = editwin self.text = editwin.text @@ -45,15 +39,28 @@ def __init__(self, editwin): # starts the toplevel 'block' of the module. self.info = [(0, -1, "", False)] self.topvisible = 1 - visible = idleConf.GetOption("extensions", "CodeContext", - "visible", type="bool", default=False) + visible = idleConf.GetOption("main", "Theme", + "contexton", type="bool", default=False) + self.reset() if visible: self.toggle_code_context_event() - self.editwin.setvar('<>', True) + # Start two update cycles, one for context lines, one for font changes. self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) + def reset(self): + self.menudefs = [('options', [('!Code Conte_xt', '<>')])] + self.context_depth = idleConf.GetOption("main", "Theme", + "numlines", type="int", default=3) + highlight=idleConf.GetHighlight(idleConf.CurrentTheme(),'codecontext') + self.fgcolor = highlight['foreground'] + self.bgcolor = highlight['background'] + if self.topvisible: + #need to rebuild widget to change color + self.toggle_code_context_event() + self.toggle_code_context_event() + def toggle_code_context_event(self, event=None): if not self.label: # Calculate the border width and horizontal padding required to @@ -86,7 +93,7 @@ def toggle_code_context_event(self, event=None): else: self.label.destroy() self.label = None - idleConf.SetOption("extensions", "CodeContext", "visible", + idleConf.SetOption("main", "Theme", "contexton", str(self.label is not None)) idleConf.SaveUserCfgFiles() return "break" diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index ff4084528804bd..89d81a0aefc556 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -92,6 +92,7 @@ def LoadTagDefs(self): "ERROR": idleConf.GetHighlight(theme, "error"), # The following is used by ReplaceDialog: "hit": idleConf.GetHighlight(theme, "hit"), + "paren": idleConf.GetHighlight(theme, "parenmatch"), } if DEBUG: print('tagdefs',self.tagdefs) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 6f1ec03981b7bd..649a2efa3e478b 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -31,70 +31,3 @@ # # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. - -[AutoComplete] -enable=True -popupwait=2000 -[AutoComplete_cfgBindings] -force-open-completions= -[AutoComplete_bindings] -autocomplete= -try-open-completions= - -[AutoExpand] -enable=True -[AutoExpand_cfgBindings] -expand-word= - -[CallTips] -enable=True -[CallTips_cfgBindings] -force-open-calltip= -[CallTips_bindings] -try-open-calltip= -refresh-calltip= - -[CodeContext] -enable=True -enable_shell=False -numlines=3 -visible=False -bgcolor=LightGray -fgcolor=Black -[CodeContext_bindings] -toggle-code-context= - -[FormatParagraph] -enable=True -max-width=72 -[FormatParagraph_cfgBindings] -format-paragraph= - -[ParenMatch] -enable=True -style= expression -hilite=hilite -flash-delay= 500 -bell=True -[ParenMatch_cfgBindings] -flash-paren= -[ParenMatch_bindings] -paren-closed= - -[RstripExtension] -enable=True -enable_shell=False -enable_editor=True - -[ScriptBinding] -enable=True -enable_shell=False -enable_editor=True -[ScriptBinding_cfgBindings] -run-module= -check-module= - -[ZoomHeight] -enable=True -[ZoomHeight_cfgBindings] -zoom-height= diff --git a/Lib/idlelib/config-highlight.def b/Lib/idlelib/config-highlight.def index 4146e28c4eda1f..531708e9c11fa3 100644 --- a/Lib/idlelib/config-highlight.def +++ b/Lib/idlelib/config-highlight.def @@ -22,6 +22,10 @@ hit-foreground= #ffffff hit-background= #000000 error-foreground= #000000 error-background= #ff7777 +codecontext-foreground = black +codecontext-background = LightGray +parenmatch-foreground = black +parenmatch-background = gray #cursor (only foreground can be set, restart IDLE) cursor-foreground= black #shell window @@ -53,6 +57,10 @@ hit-foreground= #ffffff hit-background= #000000 error-foreground= #000000 error-background= #ff7777 +codecontext-foreground = black +codecontext-background = LightGray +parenmatch-foreground = #aaaaaa +parenmatch-background = #ffffff #cursor (only foreground can be set, restart IDLE) cursor-foreground= black #shell window @@ -91,3 +99,7 @@ stdout-background = #002240 hit-foreground = #002240 comment-background = #002240 break-foreground = #FFFFFF +codecontext-foreground = #aaaaaa +codecontext-background = #000000 +parenmatch-foreground = #00dddd +parenmatch-background = #002240 diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 64788f9adf015c..6b7e202c9ccab1 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -57,6 +57,19 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= +autocomplete= +try-open-completions= +expand-word= +try-open-calltip= +refresh-calltip= +force-open-calltip= +toggle-code-context= +format-paragraph= +flash-paren= +paren-closed= +run-module= +check-module= +zoom-height= [IDLE Classic Unix] copy= @@ -108,6 +121,19 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= +autocomplete= +try-open-completions= +expand-word= +try-open-calltip= +refresh-calltip= +force-open-calltip= +toggle-code-context= +format-paragraph= +flash-paren= +paren-closed= +run-module= +check-module= +zoom-height= [IDLE Modern Unix] copy = @@ -159,6 +185,19 @@ toggle-tabs = change-indentwidth = del-word-left = del-word-right = +autocomplete= +try-open-completions= +expand-word= +try-open-calltip= +refresh-calltip= +force-open-calltip= +toggle-code-context= +format-paragraph= +flash-paren= +paren-closed= +run-module= +check-module= +zoom-height= [IDLE Classic Mac] copy= @@ -210,6 +249,19 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= +autocomplete= +try-open-completions= +expand-word= +try-open-calltip= +refresh-calltip= +force-open-calltip= +toggle-code-context= +format-paragraph= +flash-paren= +paren-closed= +run-module= +check-module= +zoom-height= [IDLE Classic OSX] toggle-tabs = @@ -262,4 +314,16 @@ python-context-help = save-copy-of-window-as-file = open-window-from-file = python-docs = - +autocomplete= +try-open-completions= +expand-word= +try-open-calltip= +refresh-calltip= +force-open-calltip= +toggle-code-context= +format-paragraph= +flash-paren= +paren-closed= +run-module= +check-module= +zoom-height= diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 16f4b0959cf13c..20ef3687dc1682 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -82,6 +82,59 @@ name= name2= # name2 set in user config-main.cfg for keys added after 2016 July 1 +[AutoComplete] +enable=True +popupwait=2000 +[AutoComplete_cfgBindings] +force-open-completions= +[AutoComplete_bindings] +autocomplete= +try-open-completions= + +[AutoExpand] +enable=True + +[CallTips] +enable=True +[CallTips_cfgBindings] +force-open-calltip= + + +[CodeContext] +enable=True +enable_shell=False +numlines=3 +visible=False +bgcolor=LightGray +fgcolor=Black + + +[FormatParagraph] +enable=True +max-width=72 + + +[ParenMatch] +enable=True +style= expression +hilite=hilite +flash-delay= 500 +bell=True + +[RstripExtension] +enable=True +enable_shell=False +enable_editor=True + +[ScriptBinding] +enable=True +enable_shell=False +enable_editor=True + +[ZoomHeight] +enable=True + + [History] cyclic=1 diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index ed37f11a9cb8e0..fb6c5f3a2a7389 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -356,7 +356,12 @@ def GetThemeDict(self, type, themeName): 'stderr-foreground':'#000000', 'stderr-background':'#ffffff', 'console-foreground':'#000000', - 'console-background':'#ffffff' } + 'console-background':'#ffffff', + 'codecontext-foreground':'#000000', + 'codecontext-background':'#ffffff', + 'parenmatch-foreground':'000000', + 'parenmatch-background':'#ffffff', + } for element in theme: if not cfgParser.has_option(themeName, element): # Print warning that will return a default color @@ -660,7 +665,21 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>': [''] + '<>': [''], + '<>':['>':['', '', ''], + '<>':[''], + '<>':[''], + '<>':['', ''], + '<>':[''], + '<>':[''], + '<>':[''], + '<>':[''], + '<>':[''], + '<>':['', '', ''], + '<>':[''], + '<>':[''], + '<>':[''] } if keySetName: if not (self.userCfg['keys'].has_section(keySetName) or diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index f58299c769da7b..d8603c2894aa22 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -11,7 +11,7 @@ """ from tkinter import (Toplevel, Frame, LabelFrame, Listbox, Label, Button, Entry, Text, Scale, Radiobutton, Checkbutton, Canvas, - StringVar, BooleanVar, IntVar, TRUE, FALSE, + OptionMenu, StringVar, BooleanVar, IntVar, TRUE, FALSE, TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE, NORMAL, DISABLED, NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW, HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END) @@ -72,6 +72,8 @@ def __init__(self, parent, title='', _htest=False, _utest=False): 'Shell Error Text': ('error', '11'), 'Shell Stdout Text': ('stdout', '12'), 'Shell Stderr Text': ('stderr', '13'), + 'Code Context Text': ('codecontext', '14'), + 'Matched Parenthetics': ('parenmatch', '15'), } self.create_widgets() self.resizable(height=FALSE, width=FALSE) @@ -218,8 +220,23 @@ def create_page_highlight(self): self.custom_theme = StringVar(parent) self.fg_bg_toggle = BooleanVar(parent) self.colour = StringVar(parent) + self.font_name = StringVar(parent) self.is_builtin_theme = BooleanVar(parent) self.highlight_target = StringVar(parent) + + self.parenstyle = StringVar(parent) + self.parenstyle.set(idleConf.GetOption( + 'main','Theme','parenstyle', default='opener')) + self.bell = BooleanVar(parent) + self.bell.set(idleConf.GetOption( + 'main','Theme','bell', default=True)) + + self.flash_delay = IntVar(parent) + self.flash_delay.set(idleConf.GetOption( + 'main','Theme','flash-delay', default=500)) + self.num_lines = IntVar(parent) + self.num_lines.set(idleConf.GetOption( + 'main','Theme','numlines', default=3)) ##widget creation #body frame @@ -229,6 +246,10 @@ def create_page_highlight(self): text=' Custom Highlighting ') frame_theme = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' Highlighting Theme ') + frame_paren = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Matched Parenthetics ') + frame_code = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Code Context ') #frame_custom self.text_highlight_sample=Text( frame_custom, relief=SOLID, borderwidth=1, @@ -238,10 +259,12 @@ def create_page_highlight(self): text.bind('', lambda e: 'break') text.bind('', lambda e: 'break') text_and_tags=( + ('Class CodeContext\n', 'codecontext'), ('#you can click here', 'comment'), ('\n', 'normal'), ('#to choose items', 'comment'), ('\n', 'normal'), ('def', 'keyword'), (' ', 'normal'), ('func', 'definition'), ('(param):\n ', 'normal'), + ('(parenthetics)','parenmatch'), ('"""string"""', 'string'), ('\n var0 = ', 'normal'), ("'string'", 'string'), ('\n var1 = ', 'normal'), ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), @@ -297,10 +320,28 @@ def tem(event, elem=element): command=self.delete_custom_theme) self.new_custom_theme = Label(frame_theme, bd=2) + #frame_paren + self.opt_menu_pstyle = OptionMenu( + frame_paren, self.parenstyle, "opener","parens","expression")#todo: figure out how to make it work + + flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') + + self.entry_flash = Entry( + frame_paren, textvariable=self.flash_delay, width=4) + self.check_bell = Checkbutton( + frame_paren, text="Bell", variable=self.bell) + #frame_code + lines_label = Label(frame_code, text='Lines : ') + self.entry_num_lines = Entry( + frame_code, textvariable=self.num_lines, width=3) + ##widget packing #body frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_theme.pack(side=LEFT, padx=5, pady=5, fill=Y) + frame_theme.pack(side=TOP, padx=5, pady=5, fill=X) + frame_paren.pack(side=TOP, padx=5, pady=5, fill=X) + frame_code.pack(side=TOP, padx=5, pady=5, fill=X) + #frame_custom self.frame_colour_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0) @@ -320,6 +361,17 @@ def tem(event, elem=element): self.opt_menu_theme_custom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) self.button_delete_custom_theme.pack(side=TOP, fill=X, padx=5, pady=5) self.new_custom_theme.pack(side=TOP, fill=X, pady=5) + + #frame_paren + self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) + self.check_bell.pack(side=TOP, anchor=W,padx=5) + flash_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) + #frame_code + lines_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) + + return frame def create_page_keys(self): @@ -422,6 +474,12 @@ def create_page_general(self): self.win_height = StringVar(parent) self.startup_edit = IntVar(parent) self.autosave = IntVar(parent) + self.autocomplete_wait = IntVar(parent) + self.autocomplete_wait.set(idleConf.GetOption( + 'main','General','autocomplete_wait', default=2000)) + self.formatp_maxw = IntVar(parent) + self.formatp_maxw.set(idleConf.GetOption( + 'main','General','formatp_maxw', default=72)) #widget creation #body @@ -432,6 +490,7 @@ def create_page_general(self): frame_save = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' autosave Preferences ') frame_win_size = Frame(frame, borderwidth=2, relief=GROOVE) + frame_extras = Frame(frame, borderwidth=2, relief=GROOVE) frame_help = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' Additional Help Sources ') #frame_run @@ -459,6 +518,13 @@ def create_page_general(self): win_height_title = Label(frame_win_size, text='Height') self.entry_win_height = Entry( frame_win_size, textvariable=self.win_height, width=3) + #frame extras + autocomplete_wait_title = Label(frame_extras, text='AutoComplete Popup Wait') + self.entry_autocomplete_wait = Entry( + frame_extras, textvariable=self.autocomplete_wait, width=6) + formatp_maxw_title = Label(frame_extras, text='Format Paragraph Max Width') + self.entry_formatp_maxw = Entry( + frame_extras, textvariable=self.formatp_maxw, width=3) #frame_help frame_helplist = Frame(frame_help) frame_helplist_buttons = Frame(frame_helplist) @@ -484,6 +550,7 @@ def create_page_general(self): frame_run.pack(side=TOP, padx=5, pady=5, fill=X) frame_save.pack(side=TOP, padx=5, pady=5, fill=X) frame_win_size.pack(side=TOP, padx=5, pady=5, fill=X) + frame_extras.pack(side=TOP, padx=5, pady=5, fill=X) frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) #frame_run startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5) @@ -499,6 +566,11 @@ def create_page_general(self): win_height_title.pack(side=RIGHT, anchor=E, pady=5) self.entry_win_width.pack(side=RIGHT, anchor=E, padx=10, pady=5) win_width_title.pack(side=RIGHT, anchor=E, pady=5) + #frame extras + self.entry_autocomplete_wait.pack(side=RIGHT, anchor=E, padx=10, pady=5) + autocomplete_wait_title.pack(side=RIGHT, anchor=E, pady=5) + self.entry_formatp_maxw.pack(side=RIGHT, anchor=E, padx=10, pady=5) + formatp_maxw_title.pack(side=RIGHT, anchor=E, pady=5) #frame_help frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y) frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) @@ -529,6 +601,13 @@ def attach_var_callbacks(self): self.startup_edit.trace_add('write', self.var_changed_startup_edit) self.autosave.trace_add('write', self.var_changed_autosave) + self.parenstyle.trace_add('write', self.var_changed_parenstyle) + self.bell.trace_add('write', self.var_changed_bell) + self.flash_delay.trace_add('write', self.var_changed_flash_delay) + self.num_lines.trace_add('write', self.var_changed_num_lines) + self.formatp_maxw.trace_add('write', self.var_changed_formatp_maxw) + self.autocomplete_wait.trace_add('write',self.var_changed_autocomplete_wait) + def remove_var_callbacks(self): "Remove callbacks to prevent memory leaks." for var in ( @@ -537,7 +616,8 @@ def remove_var_callbacks(self): self.custom_theme, self.is_builtin_theme, self.highlight_target, self.keybinding, self.builtin_keys, self.custom_keys, self.are_keys_builtin, self.win_width, self.win_height, - self.startup_edit, self.autosave,): + self.startup_edit, self.autosave, + self.parenstyle, self.bell, self.flash_delay, self.num_lines): var.trace_remove('write', var.trace_info()[0][1]) def var_changed_font(self, *params): @@ -670,6 +750,16 @@ def var_changed_win_height(self, *params): value = self.win_height.get() changes.add_option('main', 'EditorWindow', 'height', value) + def var_changed_formatp_maxw(self, *params): + "Store change to format paragraph max width." + value = self.formatp_maxw.get() + changes.add_option('main', 'General', 'formatp_maxw', value) + + def var_changed_autocomplete_wait(self, *params): + "Store change to autocomplete popup wait time." + value = self.autocomplete_wait.get() + changes.add_option('main', 'General', 'autocomplete_wait', value) + def var_changed_startup_edit(self, *params): "Store change to toggle for starting IDLE in the editor or shell." value = self.startup_edit.get() @@ -680,6 +770,26 @@ def var_changed_autosave(self, *params): value = self.autosave.get() changes.add_option('main', 'General', 'autosave', value) + def var_changed_parenstyle(self, *params): + "Store change to parenthetics display style." + value=self.parenstyle.get() + self.add_changed_item('main', 'Theme', 'parenstyle', value) + + def var_changed_bell(self, *params): + "Store change to parenthtics bell (on/off)." + value=self.bell.get() + self.add_changed_item('main', 'Theme', 'bell', value) + + def var_changed_flash_delay(self, *params): + "Store change to parenthetics flash delay." + value=self.flash_delay.get() + self.add_changed_item('main', 'Theme', 'flash-delay', value) + + def var_changed_num_lines(self, *params): + "Store change to code context - number of lines displayed." + value=self.num_lines.get() + self.add_changed_item('main', 'Theme', 'numlines', value) + def set_theme_type(self): "Set available screen options based on builtin or custom theme." if self.is_builtin_theme.get(): @@ -1276,6 +1386,9 @@ def activate_config_changes(self): instance.set_notabs_indentwidth() instance.ApplyKeybindings() instance.reset_help_menu_entries() + instance.insParenMatch.reset() + instance.insCodeContext.reset() + instance.insAutoComplete.reset() def cancel(self): "Dismiss config dialog." @@ -1476,34 +1589,7 @@ def save_all_changed_extensions(self): [Cancel] only cancels changes made since the last save. ''' help_pages = { - 'Highlighting': ''' -Highlighting: -The IDLE Dark color theme is new in October 2015. It can only -be used with older IDLE releases if it is saved as a custom -theme, with a different name. -''', - 'Keys': ''' -Keys: -The IDLE Modern Unix key set is new in June 2016. It can only -be used with older IDLE releases if it is saved as a custom -key set, with a different name. -''', - 'Extensions': ''' -Extensions: - -Autocomplete: Popupwait is milleseconds to wait after key char, without -cursor movement, before popping up completion box. Key char is '.' after -identifier or a '/' (or '\\' on Windows) within a string. - -FormatParagraph: Max-width is max chars in lines after re-formatting. -Use with paragraphs in both strings and comment blocks. - -ParenMatch: Style indicates what is highlighted when closer is entered: -'opener' - opener '({[' corresponding to closer; 'parens' - both chars; -'expression' (default) - also everything in between. Hilite determines -what highlighting is used. Flash-delay is how long to highlight if cursor -is not moved (0 means forever). -''' + } diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 43b105f726573d..4b575fa7c8e8cd 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -26,6 +26,15 @@ from idlelib import replace from idlelib import search from idlelib import windows +from idlelib.autocomplete import AutoComplete +from idlelib.autoexpand import AutoExpand +from idlelib.calltips import CallTips +from idlelib.codecontext import CodeContext +from idlelib.paragraph import FormatParagraph +from idlelib.parenmatch import ParenMatch +from idlelib.rstrip import RstripExtension +from idlelib.runscript import ScriptBinding +from idlelib.zoomheight import ZoomHeight # The default tab setting for a Text widget, in average-width characters. TK_TABWIDTH_DEFAULT = 8 @@ -270,6 +279,34 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.askinteger = tkSimpleDialog.askinteger self.showerror = tkMessageBox.showerror + + #init merged extentions binds - needs to be done after color is set + self.insAutoComplete=AutoComplete(self) + self.insAutoExpand=AutoExpand(self) + self.insCallTips=CallTips(self) + self.insCodeContext=CodeContext(self) + self.insFormatParagraph=FormatParagraph(self) + self.insParenMatch=ParenMatch(self) + self.insRstripExtension=RstripExtension(self) + self.insScriptBinding=ScriptBinding(self) + self.insZoomHeight=ZoomHeight(self) + + text.bind("<>",self.insAutoComplete.autocomplete_event) + text.bind("<>", self.insAutoComplete.try_open_completions_event) + text.bind("<>",self.insAutoComplete.force_open_completions_event) + text.bind("<>",self.insAutoExpand.expand_word_event) + text.bind("<>",self.insCodeContext.toggle_code_context_event) + text.bind("<>",self.insFormatParagraph.format_paragraph_event) + text.bind("<>",self.insParenMatch.flash_paren_event) + text.bind("<>",self.insParenMatch.paren_closed_event) + text.bind("<>",self.insScriptBinding.run_module_event) + text.bind("<>",self.insScriptBinding.check_module_event) + text.bind("<>",self.insZoomHeight.zoom_height_event) + text.bind("<>",self.insRstripExtension.do_rstrip) + text.bind("<>",self.insCallTips.try_open_calltip_event) + text.bind("<>",self.insCallTips.refresh_calltip_event) #must come after paren-closed to work right + text.bind("<>",self.insCallTips.force_open_calltip_event) + def _filename_to_unicode(self, filename): """Return filename as BMP unicode so diplayable in Tk.""" # Decode bytes to unicode. @@ -981,17 +1018,7 @@ def load_standard_extensions(self): def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) - extfiles = { # map config-extension section names to new file names - 'AutoComplete': 'autocomplete', - 'AutoExpand': 'autoexpand', - 'CallTips': 'calltips', - 'CodeContext': 'codecontext', - 'FormatParagraph': 'paragraph', - 'ParenMatch': 'parenmatch', - 'RstripExtension': 'rstrip', - 'ScriptBinding': 'runscript', - 'ZoomHeight': 'zoomheight', - } + extfiles = { } def load_extension(self, name): fname = self.extfiles.get(name, name) diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index 65345cd1f16188..14c283e4901af5 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -52,6 +52,11 @@ ('Find in Files...', '<>'), ('R_eplace...', '<>'), ('Go to _Line', '<>'), + ('S_how Completions', '<>'), + ('E_xpand Word', '<>'), + ('Show C_all Tip', '<>'), + ('Show Surrounding P_arens', '<>'), + ]), ('format', [ ('_Indent Region', '<>'), @@ -62,9 +67,13 @@ ('Untabify Region', '<>'), ('Toggle Tabs', '<>'), ('New Indent Width', '<>'), + ('F_ormat Paragraph', '<>'), + ('S_trip Trailing Whitespace', '<>'), ]), ('run', [ ('Python Shell', '<>'), + ('C_heck Module', '<>'), + ('R_un Module', '<>'), ]), ('shell', [ ('_View Last Restart', '<>'), @@ -80,7 +89,7 @@ ]), ('options', [ ('Configure _IDLE', '<>'), - None, + ('_Code Context', '<>'), ]), ('help', [ ('_About IDLE', '<>'), diff --git a/Lib/idlelib/paragraph.py b/Lib/idlelib/paragraph.py index f11bdaeb77ac38..b64b4a8690ef42 100644 --- a/Lib/idlelib/paragraph.py +++ b/Lib/idlelib/paragraph.py @@ -1,4 +1,4 @@ -"""Extension to format a paragraph or selection to a max width. +"""format a paragraph or selection to a max width. Does basic, standard text formatting, and also understands Python comment blocks. Thus, for editing Python source code, this @@ -21,12 +21,6 @@ class FormatParagraph: - menudefs = [ - ('format', [ # /s/edit/format dscherer@cmu.edu - ('Format Paragraph', '<>'), - ]) - ] - def __init__(self, editwin): self.editwin = editwin @@ -48,7 +42,7 @@ def format_paragraph_event(self, event, limit=None): if limit is None: # The default length limit is that defined by pep8 limit = idleConf.GetOption( - 'extensions', 'FormatParagraph', 'max-width', + 'main', 'General', 'formatp_maxw', type='int', default=72) text = self.editwin.text first, last = self.editwin.get_selection_indices() diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 2dcd68ebcc1ce1..b47d63bad4237c 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -1,4 +1,4 @@ -"""ParenMatch -- An IDLE extension for parenthesis matching. +"""ParenMatch -- for parenthesis matching. When you hit a right paren, the cursor should move briefly to the left paren. Paren here is used generically; the matching applies to @@ -30,21 +30,6 @@ class ParenMatch: - Highlight when cursor is moved to the right of a closer. This might be too expensive to check. """ - menudefs = [ - ('edit', [ - ("Show surrounding parens", "<>"), - ]) - ] - STYLE = idleConf.GetOption( - 'extensions','ParenMatch','style', default='expression') - FLASH_DELAY = idleConf.GetOption( - 'extensions','ParenMatch','flash-delay', type='int',default=500) - BELL = idleConf.GetOption( - 'extensions','ParenMatch','bell', type='bool',default=1) - HILITE_CONFIG = idleConf.GetHighlight( - idleConf.CurrentTheme(), idleConf.GetOption( - 'extensions','ParenMatch','hilite', default='expression')) - RESTORE_VIRTUAL_EVENT_NAME = "<>" # We want the restore event be called before the usual return and @@ -60,9 +45,21 @@ def __init__(self, editwin): # and deactivate_restore (which calls event_delete). editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME, self.restore_event) - self.bell = self.text.bell if self.BELL else lambda: None self.counter = 0 self.is_restore_active = 0 + self.reset() + + def reset(self): + self.STYLE = idleConf.GetOption( + 'main','Theme','parenstyle', default='opener') + self.FLASH_DELAY = idleConf.GetOption( + 'main','Theme','flash-delay', type='int',default=500) + if idleConf.GetOption( + 'main','Theme','bell', type='bool',default=1): + self.bell=self.text.bell + else: + self.bell=lambda:None + self.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), 'parenmatch') self.set_style(self.STYLE) def activate_restore(self): diff --git a/Lib/idlelib/rstrip.py b/Lib/idlelib/rstrip.py index 2ce3c7eafe5a81..82c7f7e8d8c8ab 100644 --- a/Lib/idlelib/rstrip.py +++ b/Lib/idlelib/rstrip.py @@ -2,9 +2,6 @@ class RstripExtension: - menudefs = [ - ('format', [None, ('Strip trailing whitespace', '<>'), ] ), ] - def __init__(self, editwin): self.editwin = editwin self.editwin.text.bind("<>", self.do_rstrip) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 3355f17d90bdb7..97c02fc83b5f66 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -1,4 +1,4 @@ -"""Extension to execute code outside the Python shell window. +"""execute code outside the Python shell window. This adds the following commands: diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index d01c9e964aa60f..fc062c2cdf409f 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -1,4 +1,4 @@ -# Sample extension: zoom a window to maximum height +# zoom a window to maximum height import re import sys @@ -8,12 +8,6 @@ class ZoomHeight: - menudefs = [ - ('windows', [ - ('_Zoom Height', '<>'), - ]) - ] - def __init__(self, editwin): self.editwin = editwin From 86c3d4c26cddaa7be013918447d52fb89ad4259c Mon Sep 17 00:00:00 2001 From: wohlganger Date: Mon, 10 Jul 2017 16:25:46 -0500 Subject: [PATCH 07/47] whitespace + fix I thought I already committed. --- Lib/idlelib/codecontext.py | 6 +++--- Lib/idlelib/configdialog.py | 38 ++++++++++++++++++------------------- Lib/idlelib/mainmenu.py | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 5de187a82584d5..36703dd3316cc0 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -26,7 +26,7 @@ lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() class CodeContext: - + def __init__(self, editwin): self.editwin = editwin self.text = editwin.text @@ -44,7 +44,7 @@ def __init__(self, editwin): self.reset() if visible: self.toggle_code_context_event() - + # Start two update cycles, one for context lines, one for font changes. self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) @@ -60,7 +60,7 @@ def reset(self): #need to rebuild widget to change color self.toggle_code_context_event() self.toggle_code_context_event() - + def toggle_code_context_event(self, event=None): if not self.label: # Calculate the border width and horizontal padding required to diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index d8603c2894aa22..f85943b2b5af54 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -223,14 +223,14 @@ def create_page_highlight(self): self.font_name = StringVar(parent) self.is_builtin_theme = BooleanVar(parent) self.highlight_target = StringVar(parent) - + self.parenstyle = StringVar(parent) self.parenstyle.set(idleConf.GetOption( 'main','Theme','parenstyle', default='opener')) self.bell = BooleanVar(parent) self.bell.set(idleConf.GetOption( 'main','Theme','bell', default=True)) - + self.flash_delay = IntVar(parent) self.flash_delay.set(idleConf.GetOption( 'main','Theme','flash-delay', default=500)) @@ -323,9 +323,9 @@ def tem(event, elem=element): #frame_paren self.opt_menu_pstyle = OptionMenu( frame_paren, self.parenstyle, "opener","parens","expression")#todo: figure out how to make it work - + flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') - + self.entry_flash = Entry( frame_paren, textvariable=self.flash_delay, width=4) self.check_bell = Checkbutton( @@ -334,14 +334,14 @@ def tem(event, elem=element): lines_label = Label(frame_code, text='Lines : ') self.entry_num_lines = Entry( frame_code, textvariable=self.num_lines, width=3) - + ##widget packing #body frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) frame_theme.pack(side=TOP, padx=5, pady=5, fill=X) frame_paren.pack(side=TOP, padx=5, pady=5, fill=X) frame_code.pack(side=TOP, padx=5, pady=5, fill=X) - + #frame_custom self.frame_colour_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0) @@ -366,12 +366,12 @@ def tem(event, elem=element): self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) self.check_bell.pack(side=TOP, anchor=W,padx=5) flash_label.pack(side=LEFT, anchor=W, padx=5) - self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) + self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) #frame_code lines_label.pack(side=LEFT, anchor=W, padx=5) self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) - - + + return frame def create_page_keys(self): @@ -521,10 +521,10 @@ def create_page_general(self): #frame extras autocomplete_wait_title = Label(frame_extras, text='AutoComplete Popup Wait') self.entry_autocomplete_wait = Entry( - frame_extras, textvariable=self.autocomplete_wait, width=6) - formatp_maxw_title = Label(frame_extras, text='Format Paragraph Max Width') + frame_extras, textvariable=self.autocomplete_wait, width=6) + formatp_maxw_title = Label(frame_extras, text='Format Paragraph Max Width') self.entry_formatp_maxw = Entry( - frame_extras, textvariable=self.formatp_maxw, width=3) + frame_extras, textvariable=self.formatp_maxw, width=3) #frame_help frame_helplist = Frame(frame_help) frame_helplist_buttons = Frame(frame_helplist) @@ -607,7 +607,7 @@ def attach_var_callbacks(self): self.num_lines.trace_add('write', self.var_changed_num_lines) self.formatp_maxw.trace_add('write', self.var_changed_formatp_maxw) self.autocomplete_wait.trace_add('write',self.var_changed_autocomplete_wait) - + def remove_var_callbacks(self): "Remove callbacks to prevent memory leaks." for var in ( @@ -773,23 +773,23 @@ def var_changed_autosave(self, *params): def var_changed_parenstyle(self, *params): "Store change to parenthetics display style." value=self.parenstyle.get() - self.add_changed_item('main', 'Theme', 'parenstyle', value) + changes.add_option('main', 'Theme', 'parenstyle', value) def var_changed_bell(self, *params): "Store change to parenthtics bell (on/off)." value=self.bell.get() - self.add_changed_item('main', 'Theme', 'bell', value) + changes.add_option('main', 'Theme', 'bell', value) def var_changed_flash_delay(self, *params): "Store change to parenthetics flash delay." value=self.flash_delay.get() - self.add_changed_item('main', 'Theme', 'flash-delay', value) + changes.add_option('main', 'Theme', 'flash-delay', value) def var_changed_num_lines(self, *params): "Store change to code context - number of lines displayed." value=self.num_lines.get() - self.add_changed_item('main', 'Theme', 'numlines', value) - + changes.add_option('main', 'Theme', 'numlines', value) + def set_theme_type(self): "Set available screen options based on builtin or custom theme." if self.is_builtin_theme.get(): @@ -1589,7 +1589,7 @@ def save_all_changed_extensions(self): [Cancel] only cancels changes made since the last save. ''' help_pages = { - + } diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index 14c283e4901af5..cd649cf5285be6 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -56,7 +56,7 @@ ('E_xpand Word', '<>'), ('Show C_all Tip', '<>'), ('Show Surrounding P_arens', '<>'), - + ]), ('format', [ ('_Indent Region', '<>'), From 1c246fcf1f3e4df13f4caba599c813efa0cdb4eb Mon Sep 17 00:00:00 2001 From: wohlganger Date: Tue, 11 Jul 2017 08:13:14 -0500 Subject: [PATCH 08/47] warning fixes, removed old config entries --- Lib/idlelib/autocomplete.py | 2 +- Lib/idlelib/config-keys.def | 10 +++---- Lib/idlelib/config-main.def | 53 ------------------------------------- 3 files changed, 6 insertions(+), 59 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index 87706c19eae543..33eef9ae63e19f 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -39,7 +39,7 @@ def __init__(self, editwin=None): self._delayed_completion_index = None def reset(self): - self.popupwait = idleConf.GetOption("main", "EditorWindow", + self.popupwait = idleConf.GetOption("main", "General", "autocomplete_wait", type="int", default=0) def _make_autocomplete_window(self): diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 6b7e202c9ccab1..ad110b50024a6d 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -63,7 +63,7 @@ expand-word= try-open-calltip= refresh-calltip= force-open-calltip= -toggle-code-context= +toggle-code-context= format-paragraph= flash-paren= paren-closed= @@ -127,7 +127,7 @@ expand-word= try-open-calltip= refresh-calltip= force-open-calltip= -toggle-code-context= +toggle-code-context= format-paragraph= flash-paren= paren-closed= @@ -191,7 +191,7 @@ expand-word= try-open-calltip= refresh-calltip= force-open-calltip= -toggle-code-context= +toggle-code-context= format-paragraph= flash-paren= paren-closed= @@ -255,7 +255,7 @@ expand-word= try-open-calltip= refresh-calltip= force-open-calltip= -toggle-code-context= +toggle-code-context= format-paragraph= flash-paren= paren-closed= @@ -320,7 +320,7 @@ expand-word= try-open-calltip= refresh-calltip= force-open-calltip= -toggle-code-context= +toggle-code-context= format-paragraph= flash-paren= paren-closed= diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 20ef3687dc1682..16f4b0959cf13c 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -82,59 +82,6 @@ name= name2= # name2 set in user config-main.cfg for keys added after 2016 July 1 -[AutoComplete] -enable=True -popupwait=2000 -[AutoComplete_cfgBindings] -force-open-completions= -[AutoComplete_bindings] -autocomplete= -try-open-completions= - -[AutoExpand] -enable=True - -[CallTips] -enable=True -[CallTips_cfgBindings] -force-open-calltip= - - -[CodeContext] -enable=True -enable_shell=False -numlines=3 -visible=False -bgcolor=LightGray -fgcolor=Black - - -[FormatParagraph] -enable=True -max-width=72 - - -[ParenMatch] -enable=True -style= expression -hilite=hilite -flash-delay= 500 -bell=True - -[RstripExtension] -enable=True -enable_shell=False -enable_editor=True - -[ScriptBinding] -enable=True -enable_shell=False -enable_editor=True - -[ZoomHeight] -enable=True - - [History] cyclic=1 From 0418ad0a94f215ad9b5894b9e5b71474670f5c44 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Tue, 11 Jul 2017 16:46:26 -0500 Subject: [PATCH 09/47] calltip append doc fix, default paren-fore fix, help update How did the change to the __doc__ of append not get fixed in the tests earlier? --- Lib/idlelib/config.py | 2 +- Lib/idlelib/help.html | 15 ++------------- Lib/idlelib/idle_test/test_calltips.py | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index fb6c5f3a2a7389..c5690c8729e960 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -359,7 +359,7 @@ def GetThemeDict(self, type, themeName): 'console-background':'#ffffff', 'codecontext-foreground':'#000000', 'codecontext-background':'#ffffff', - 'parenmatch-foreground':'000000', + 'parenmatch-foreground':'#000000', 'parenmatch-background':'#ffffff', } for element in theme: diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 0a3062e156421c..60a1035ece6538 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -636,19 +636,8 @@

25.5.4.2. Setting preferences¶

IDLE contains an extension facility. Preferences for extensions can be changed with Configure Extensions. See the beginning of config-extensions.def -in the idlelib directory for further information. The default extensions -are currently:

-
    -
  • FormatParagraph
  • -
  • AutoExpand
  • -
  • ZoomHeight
  • -
  • ScriptBinding
  • -
  • CallTips
  • -
  • ParenMatch
  • -
  • AutoComplete
  • -
  • CodeContext
  • -
  • RstripExtension
  • -
+in the idlelib directory for further information. There are currently no default extensions.

+ diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py index 29b9f06faf868b..cf7c650a074daa 100644 --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -58,7 +58,7 @@ def gtest(obj, out): 'Create and return a new object. See help(type) for accurate signature.') gtest(list.__init__, 'Initialize self. See help(type(self)) for accurate signature.') - append_doc = "Append object to the end of the list." + append_doc = "L.append(object) -> None -- append object to end" gtest(list.append, append_doc) gtest([].append, append_doc) gtest(List.append, append_doc) From 097a0d8be848fbf5b5be1e6af0ab8acd8fc77d19 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 12 Jul 2017 08:46:23 -0500 Subject: [PATCH 10/47] fix calltips Used incorrect / old python for testing. --- Lib/idlelib/idle_test/test_calltips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py index cf7c650a074daa..29b9f06faf868b 100644 --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -58,7 +58,7 @@ def gtest(obj, out): 'Create and return a new object. See help(type) for accurate signature.') gtest(list.__init__, 'Initialize self. See help(type(self)) for accurate signature.') - append_doc = "L.append(object) -> None -- append object to end" + append_doc = "Append object to the end of the list." gtest(list.append, append_doc) gtest([].append, append_doc) gtest(List.append, append_doc) From 4232e77176ddc39040e103c63aa6c492e05ea135 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 12 Jul 2017 09:17:55 -0500 Subject: [PATCH 11/47] removed circular import --- Lib/idlelib/editor.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 4b575fa7c8e8cd..83aeb6c7834b80 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -26,15 +26,7 @@ from idlelib import replace from idlelib import search from idlelib import windows -from idlelib.autocomplete import AutoComplete -from idlelib.autoexpand import AutoExpand -from idlelib.calltips import CallTips -from idlelib.codecontext import CodeContext -from idlelib.paragraph import FormatParagraph -from idlelib.parenmatch import ParenMatch -from idlelib.rstrip import RstripExtension -from idlelib.runscript import ScriptBinding -from idlelib.zoomheight import ZoomHeight + # The default tab setting for a Text widget, in average-width characters. TK_TABWIDTH_DEFAULT = 8 @@ -66,6 +58,16 @@ class EditorWindow(object): help_url = None def __init__(self, flist=None, filename=None, key=None, root=None): + from idlelib.autocomplete import AutoComplete + from idlelib.autoexpand import AutoExpand + from idlelib.calltips import CallTips + from idlelib.codecontext import CodeContext + from idlelib.paragraph import FormatParagraph + from idlelib.parenmatch import ParenMatch + from idlelib.rstrip import RstripExtension + from idlelib.runscript import ScriptBinding + from idlelib.zoomheight import ZoomHeight + if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') if sys.platform.count('linux'): From a7b29f5df03ce95a41ec26f081d326bdb55d9fb8 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 12 Jul 2017 09:49:06 -0500 Subject: [PATCH 12/47] fix warnings due to missing default config options in idlelib.config-main.def --- Lib/idlelib/config-main.def | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 16f4b0959cf13c..55e747f9d625d3 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -55,6 +55,7 @@ autosave= 0 print-command-posix=lpr %%s print-command-win=start /min notepad /p %%s delete-exitfunc= 1 +autocomplete_wait= 0 [EditorWindow] width= 80 @@ -74,6 +75,11 @@ num-spaces= 4 default= 1 name= IDLE Classic name2= +contexton= 0 +numlines= 3 +parenstyle= opener +flash-delay= 500 +bell= 1 # name2 set in user config-main.cfg for themes added after 2015 Oct 1 [Keys] From 252672b6d9d50a4f60f4c9a0cadc385f32401797 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 19 Jul 2017 11:06:28 -0500 Subject: [PATCH 13/47] added format_pmaxw to config-main --- Lib/idlelib/config-main.def | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 55e747f9d625d3..71ff1f927254ec 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -56,6 +56,7 @@ print-command-posix=lpr %%s print-command-win=start /min notepad /p %%s delete-exitfunc= 1 autocomplete_wait= 0 +formatp_maxw= 72 [EditorWindow] width= 80 From 1a745919a6a7d4ac015f7a02d60190af6e44151d Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 20 Jul 2017 09:08:44 -0500 Subject: [PATCH 14/47] replaced help.html edit with idle.rst edit per terryjreedy request. --- Doc/library/idle.rst | 22 ++-------------------- Lib/idlelib/help.html | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index a945b6d771225b..13f286d7e30ebb 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -672,23 +672,5 @@ Extensions IDLE contains an extension facility. Preferences for extensions can be changed with Configure Extensions. See the beginning of config-extensions.def -in the idlelib directory for further information. The default extensions -are currently: - -* FormatParagraph - -* AutoExpand - -* ZoomHeight - -* ScriptBinding - -* CallTips - -* ParenMatch - -* AutoComplete - -* CodeContext - -* RstripExtension +in the idlelib directory for further information. There are currently no +default extensions. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 60a1035ece6538..0a3062e156421c 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -636,8 +636,19 @@

25.5.4.2. Setting preferences¶

IDLE contains an extension facility. Preferences for extensions can be changed with Configure Extensions. See the beginning of config-extensions.def -in the idlelib directory for further information. There are currently no default extensions.

- +in the idlelib directory for further information. The default extensions +are currently:

+
    +
  • FormatParagraph
  • +
  • AutoExpand
  • +
  • ZoomHeight
  • +
  • ScriptBinding
  • +
  • CallTips
  • +
  • ParenMatch
  • +
  • AutoComplete
  • +
  • CodeContext
  • +
  • RstripExtension
  • +
From f095c53d3dfffb716885db0b48b1c4a89d63b7a4 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 4 Aug 2017 10:11:19 -0500 Subject: [PATCH 15/47] added conflict resolved var descriptions to docstring in create_page_highlight. --- Lib/idlelib/configdialog.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 1441b431aa364a..7518748f3d86db 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -230,6 +230,12 @@ def create_page_highlight(self): Note: this has no callback. is_builtin_theme: Selector for built-in or custom theme. highlight_target: Menu variable for the highlight tag target. + parenstyle: Menu option for style of paren highlight used. + bell: Menu variable for whether parens bells on error. + flash_delay: Menu variable for length of time paren + highlights display. + num_lines: Menu variable for number of lines Code Context + displays. Instance Data Attributes: theme_elements: Dictionary of tags for text highlighting. From a661bfaa2a95cd10194e45da0617c146cf7f11bb Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 4 Aug 2017 11:03:37 -0500 Subject: [PATCH 16/47] strip trailing whitespace --- Lib/idlelib/configdialog.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 7518748f3d86db..7703556f8ce486 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -309,7 +309,7 @@ def create_page_highlight(self): self.highlight_target = tracers.add( StringVar(parent), self.var_changed_highlight_target) - + self.parenstyle = tracers.add( StringVar(parent), self.var_changed_parenstyle) self.bell = tracers.add( @@ -327,7 +327,7 @@ def create_page_highlight(self): 'main','Theme','flash-delay', default=500)) self.num_lines.set(idleConf.GetOption( 'main','Theme','numlines', default=3)) - + # Widget creation: # body frame and section frames frame = Frame(self.note) @@ -336,12 +336,12 @@ def create_page_highlight(self): text=' Custom Highlighting ') frame_theme = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' Highlighting Theme ') - + frame_paren = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' Matched Parenthetics ') frame_code = LabelFrame(frame, borderwidth=2, relief=GROOVE, text=' Code Context ') - + #frame_custom text = self.highlight_sample = frame.highlight_sample = Text( frame_custom, relief=SOLID, borderwidth=1, @@ -580,7 +580,7 @@ def var_changed_color(self, *params): self.num_lines = tracers.add( StringVar(parent), self.var_changed_num_lines) - + def var_changed_highlight_target(self, *params): "Process selection of new target tag for highlighting." self.set_highlight_target() From 5a6a007c88b6b070cdff2f78f84ec8422f26736a Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 11:09:10 -0500 Subject: [PATCH 17/47] re-introduced highlight options. Fixing code conflict ate highlighting options. Needed to be re-introduced. --- Lib/idlelib/configdialog.py | 81 +++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index dedf4deee849e3..caa64d33a3faad 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -207,7 +207,7 @@ def deactivate_current_config(self): for instance in win_instances: instance.RemoveKeybindings() - + def activate_config_changes(self): @@ -291,7 +291,7 @@ def load_extensions(self): for ext_name in self.extensions: opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) - + # Bring 'enable' options to the beginning of the list. enables = [opt_name for opt_name in opt_list if opt_name.startswith('enable')] @@ -769,6 +769,8 @@ def create_page_highlight(self): 'Shell Error Text': ('error', '11'), 'Shell Stdout Text': ('stdout', '12'), 'Shell Stderr Text': ('stderr', '13'), + 'Code Context Text': ('codecontext', '14'), + 'Matched Parenthetics': ('parenmatch', '15'), } self.builtin_name = tracers.add( StringVar(self), self.var_changed_builtin_name) @@ -781,6 +783,23 @@ def create_page_highlight(self): BooleanVar(self), self.var_changed_theme_source) self.highlight_target = tracers.add( StringVar(self), self.var_changed_highlight_target) + self.parenstyle = tracers.add( + StringVar(self), self.var_changed_parenstyle) + self.bell = tracers.add( + StringVar(self), self.var_changed_bell) + self.flash_delay = tracers.add( + StringVar(self), self.var_changed_flash_delay) + self.num_lines = tracers.add( + StringVar(self), self.var_changed_num_lines) + + self.parenstyle.set(idleConf.GetOption( + 'main','Theme','parenstyle', default='opener')) + self.bell.set(idleConf.GetOption( + 'main','Theme','bell', default=True)) + self.flash_delay.set(idleConf.GetOption( + 'main','Theme','flash-delay', default=500)) + self.num_lines.set(idleConf.GetOption( + 'main','Theme','numlines', default=3)) # Create widgets: # body frame and section frames. @@ -788,6 +807,10 @@ def create_page_highlight(self): text=' Custom Highlighting ') frame_theme = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Highlighting Theme ') + frame_paren = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Matched Parenthetics ') + frame_code = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Code Context ') # frame_custom. text = self.highlight_sample = Text( frame_custom, relief=SOLID, borderwidth=1, @@ -795,12 +818,15 @@ def create_page_highlight(self): takefocus=FALSE, highlightthickness=0, wrap=NONE) text.bind('', lambda e: 'break') text.bind('', lambda e: 'break') - text_and_tags=(('\n', 'normal'), + text_and_tags=( + ('Class CodeContext\n', 'codecontext'), ('#you can click here', 'comment'), ('\n', 'normal'), ('#to choose items', 'comment'), ('\n', 'normal'), ('def', 'keyword'), (' ', 'normal'), - ('func', 'definition'), ('(param):\n ', 'normal'), - ('"""string"""', 'string'), ('\n var0 = ', 'normal'), + ('func', 'definition'), + ('(parenthetics)','parenmatch'), + (':\n','normal'), + (' """string"""', 'string'), ('\n var0 = ', 'normal'), ("'string'", 'string'), ('\n var1 = ', 'normal'), ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), ("'found'", 'hit'), ('\n var3 = ', 'normal'), @@ -855,11 +881,24 @@ def tem(event, elem=element): frame_theme, text='Delete Custom Theme', command=self.delete_custom) self.theme_message = Label(frame_theme, bd=2) - + #frame_paren + self.opt_menu_pstyle = OptionMenu( + frame_paren, self.parenstyle, "opener","parens","expression") + flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') + self.entry_flash = Entry( + frame_paren, textvariable=self.flash_delay, width=4) + self.check_bell = Checkbutton( + frame_paren, text="Bell", variable=self.bell) + #frame_code + lines_label = Label(frame_code, text='Lines : ') + self.entry_num_lines = Entry( + frame_code, textvariable=self.num_lines, width=3) # Pack widgets: # body. frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_theme.pack(side=LEFT, padx=5, pady=5, fill=Y) + frame_theme.pack(side=TOP, padx=5, pady=5, fill=X) + frame_paren.pack(side=TOP, padx=5, pady=5, fill=X) + frame_code.pack(side=TOP, padx=5, pady=5, fill=X) # frame_custom. self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0) @@ -878,6 +917,14 @@ def tem(event, elem=element): self.customlist.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) self.button_delete_custom.pack(side=TOP, fill=X, padx=5, pady=5) self.theme_message.pack(side=TOP, fill=X, pady=5) + #frame_paren + self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) + self.check_bell.pack(side=TOP, anchor=W,padx=5) + flash_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) + #frame_code + lines_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) def load_theme_cfg(self): """Load current configuration settings for the theme options. @@ -984,6 +1031,26 @@ def var_changed_highlight_target(self, *params): "Process selection of new target tag for highlighting." self.set_highlight_target() + def var_changed_parenstyle(self, *params): + "Store change to parenthetics display style." + value=self.parenstyle.get() + changes.add_option('main', 'Theme', 'parenstyle', value) + + def var_changed_bell(self, *params): + "Store change to parenthtics bell (on/off)." + value=self.bell.get() + changes.add_option('main', 'Theme', 'bell', value) + + def var_changed_flash_delay(self, *params): + "Store change to parenthetics flash delay." + value=self.flash_delay.get() + changes.add_option('main', 'Theme', 'flash-delay', value) + + def var_changed_num_lines(self, *params): + "Store change to code context - number of lines displayed." + value=self.num_lines.get() + changes.add_option('main', 'Theme', 'numlines', value) + def set_theme_type(self): """Set available screen options based on builtin or custom theme. From 709b43470a70c33aab9146b4a911feb26efdbf7a Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 24 Aug 2017 13:49:24 -0400 Subject: [PATCH 18/47] News blurb. --- Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst diff --git a/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst b/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst new file mode 100644 index 00000000000000..539f06eb63b446 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst @@ -0,0 +1,2 @@ +Convert IDLE's built-in 'extensions' to regular features. Inital patch by +Charles Wohlganger. From b9b1f9a85ca105fc03cd624f0016b360885d8acf Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 13:47:53 -0500 Subject: [PATCH 19/47] Reinstated zoomheight as an extension. Replaced autoexpand with zoomheight as non-core keybinding test example. --- Lib/idlelib/config-extensions.def | 5 +++++ Lib/idlelib/config-keys.def | 5 ----- Lib/idlelib/config.py | 3 +-- Lib/idlelib/idle_test/test_configdialog.py | 5 +++-- Lib/idlelib/zoomheight.py | 11 ++++++++--- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 649a2efa3e478b..973c28f540ea93 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -31,3 +31,8 @@ # # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. + +[ZoomHeight] +enable = True +[ZoomHeight_cfgBindings] +zoom-height= \ No newline at end of file diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index ad110b50024a6d..8ea04538edd49c 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -69,7 +69,6 @@ flash-paren= paren-closed= run-module= check-module= -zoom-height= [IDLE Classic Unix] copy= @@ -133,7 +132,6 @@ flash-paren= paren-closed= run-module= check-module= -zoom-height= [IDLE Modern Unix] copy = @@ -197,7 +195,6 @@ flash-paren= paren-closed= run-module= check-module= -zoom-height= [IDLE Classic Mac] copy= @@ -261,7 +258,6 @@ flash-paren= paren-closed= run-module= check-module= -zoom-height= [IDLE Classic OSX] toggle-tabs = @@ -326,4 +322,3 @@ flash-paren= paren-closed= run-module= check-module= -zoom-height= diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index b806a481b555cf..9c2ca2e460828d 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -672,8 +672,7 @@ def GetCoreKeys(self, keySetName=None): '<>':[''], '<>':['', '', ''], '<>':[''], - '<>':[''], - '<>':[''] + '<>':[''] } if keySetName: if not (self.userCfg['keys'].has_section(keySetName) or diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index df801c32b73a4b..1ce92412571384 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -823,19 +823,20 @@ def test_keybinding(self): d.custom_name.set('my custom keys') d.bindingslist.delete(0, 'end') d.bindingslist.insert(0, 'copy') - d.bindingslist.insert(1, 'expand-word') + d.bindingslist.insert(1, 'zoom-height') d.bindingslist.selection_set(0) d.bindingslist.selection_anchor(0) # Core binding - adds to keys. d.keybinding.set('') self.assertEqual(keyspage, {'my custom keys': {'copy': ''}}) + # Not a core binding - adds to extensions. d.bindingslist.selection_set(1) d.bindingslist.selection_anchor(1) d.keybinding.set('') self.assertEqual(extpage, - {'AutoExpand_cfgBindings': {'expand-word': ''}}) + {'zoomheight_cfgBindings': {'zoom-height': ''}}) def test_set_keys_type(self): eq = self.assertEqual diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index fc062c2cdf409f..cc8299bd73fec0 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -1,4 +1,4 @@ -# zoom a window to maximum height +# Sample extension - zoom a window to maximum height import re import sys @@ -6,8 +6,13 @@ from idlelib import macosx -class ZoomHeight: - +class zoomheight: + menudefs = [ + ('windows', [ + ('_Zoom Height', '<>'), + ]) + ] + def __init__(self, editwin): self.editwin = editwin From 8b76ccb2240e403317cbf37bdb9a04347b518aa6 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 14:08:57 -0500 Subject: [PATCH 20/47] fixed configdialog test (wrong cases), fixed whitespace --- Lib/idlelib/config-extensions.def | 4 ++-- Lib/idlelib/idle_test/test_configdialog.py | 2 +- Lib/idlelib/tree.py | 2 +- Lib/idlelib/zoomheight.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 973c28f540ea93..d4e106329a95ce 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -32,7 +32,7 @@ # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. -[ZoomHeight] +[zoomheight] enable = True -[ZoomHeight_cfgBindings] +[zoomheight_cfgBindings] zoom-height= \ No newline at end of file diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 1ce92412571384..d7bcd040e58e8c 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -830,7 +830,7 @@ def test_keybinding(self): d.keybinding.set('') self.assertEqual(keyspage, {'my custom keys': {'copy': ''}}) - + # Not a core binding - adds to extensions. d.bindingslist.selection_set(1) d.bindingslist.selection_anchor(1) diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py index 292ce36184c76d..907e52d1a992a1 100644 --- a/Lib/idlelib/tree.py +++ b/Lib/idlelib/tree.py @@ -20,7 +20,7 @@ from tkinter.ttk import Scrollbar from idlelib.config import idleConf -from idlelib import zoomheight +from idlelib import ZoomHeight ICONDIR = "Icons" diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index cc8299bd73fec0..18d42608c98cf3 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -12,7 +12,7 @@ class zoomheight: ('_Zoom Height', '<>'), ]) ] - + def __init__(self, editwin): self.editwin = editwin From b986c1232a4eb717b82c3b3d84df1bffdae4d276 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 14:12:59 -0500 Subject: [PATCH 21/47] update idle.rst: zoomheight is an extension. --- Doc/library/idle.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 13f286d7e30ebb..4f51f3f0ac2eaa 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -672,5 +672,6 @@ Extensions IDLE contains an extension facility. Preferences for extensions can be changed with Configure Extensions. See the beginning of config-extensions.def -in the idlelib directory for further information. There are currently no -default extensions. +in the idlelib directory for further information. The only current default +extension is zoomheight. It exists as an extension primarily to be an example +and for testing purposes. \ No newline at end of file From f86acaa61b35afe19f4edae1e91e13933fefed10 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 14:42:32 -0500 Subject: [PATCH 22/47] more fixes for zoomheight - trying to minimize changes from master --- Lib/idlelib/config-extensions.def | 4 ++-- Lib/idlelib/configdialog.py | 6 +++++- Lib/idlelib/editor.py | 9 ++++----- Lib/idlelib/tree.py | 2 +- Lib/idlelib/zoomheight.py | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index d4e106329a95ce..973c28f540ea93 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -32,7 +32,7 @@ # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. -[zoomheight] +[ZoomHeight] enable = True -[zoomheight_cfgBindings] +[ZoomHeight_cfgBindings] zoom-height= \ No newline at end of file diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index caa64d33a3faad..ecb75f1fa9f7c2 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -243,7 +243,11 @@ def create_page_extensions(self): which are boolean, and can be toggled with a True/False button. Methods: - + load_extensions: + extension_selected: Handle selection from list. + create_extension_frame: Hold widgets for one extension. + set_extension_value: Set in userCfg['extensions']. + save_all_changed_extensions: Call extension page Save(). """ parent = self.parent frame = Frame(self.note) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 83aeb6c7834b80..34024ea94c9af6 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -65,8 +65,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): from idlelib.paragraph import FormatParagraph from idlelib.parenmatch import ParenMatch from idlelib.rstrip import RstripExtension - from idlelib.runscript import ScriptBinding - from idlelib.zoomheight import ZoomHeight + from idlelib.runscript import ScriptBinding if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') @@ -291,7 +290,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.insParenMatch=ParenMatch(self) self.insRstripExtension=RstripExtension(self) self.insScriptBinding=ScriptBinding(self) - self.insZoomHeight=ZoomHeight(self) text.bind("<>",self.insAutoComplete.autocomplete_event) text.bind("<>", self.insAutoComplete.try_open_completions_event) @@ -303,7 +301,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>",self.insParenMatch.paren_closed_event) text.bind("<>",self.insScriptBinding.run_module_event) text.bind("<>",self.insScriptBinding.check_module_event) - text.bind("<>",self.insZoomHeight.zoom_height_event) text.bind("<>",self.insRstripExtension.do_rstrip) text.bind("<>",self.insCallTips.try_open_calltip_event) text.bind("<>",self.insCallTips.refresh_calltip_event) #must come after paren-closed to work right @@ -1020,7 +1017,9 @@ def load_standard_extensions(self): def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) - extfiles = { } + extfiles = { + 'ZoomHeight': 'zoomheight', + } def load_extension(self, name): fname = self.extfiles.get(name, name) diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py index 907e52d1a992a1..292ce36184c76d 100644 --- a/Lib/idlelib/tree.py +++ b/Lib/idlelib/tree.py @@ -20,7 +20,7 @@ from tkinter.ttk import Scrollbar from idlelib.config import idleConf -from idlelib import ZoomHeight +from idlelib import zoomheight ICONDIR = "Icons" diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index 18d42608c98cf3..ea1230a1f2454a 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -1,4 +1,4 @@ -# Sample extension - zoom a window to maximum height +# Sample extension: zoom a window to maximum height import re import sys @@ -6,7 +6,7 @@ from idlelib import macosx -class zoomheight: +class ZoomHeight: menudefs = [ ('windows', [ ('_Zoom Height', '<>'), From 5805462040b6a84182e0c5f7cc6f8355be399495 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 14:47:53 -0500 Subject: [PATCH 23/47] zoomheight config fix, zoomheight should be fully back to the way it was before. --- Lib/idlelib/config-extensions.def | 4 ++-- Lib/idlelib/zoomheight.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 973c28f540ea93..5ee60649923c8c 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -33,6 +33,6 @@ # information on creating IDLE extensions. [ZoomHeight] -enable = True +enable=True [ZoomHeight_cfgBindings] -zoom-height= \ No newline at end of file +zoom-height= diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index ea1230a1f2454a..d01c9e964aa60f 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -7,6 +7,7 @@ class ZoomHeight: + menudefs = [ ('windows', [ ('_Zoom Height', '<>'), From 165b548c3acdd338cac305ee52da467a0efbbae5 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 14:54:19 -0500 Subject: [PATCH 24/47] whitespace --- Lib/idlelib/editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 34024ea94c9af6..9ee3e9e16688cc 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -65,7 +65,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): from idlelib.paragraph import FormatParagraph from idlelib.parenmatch import ParenMatch from idlelib.rstrip import RstripExtension - from idlelib.runscript import ScriptBinding + from idlelib.runscript import ScriptBinding if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') From aee5d02c305001c15d41997c1b6b29dff5cf245a Mon Sep 17 00:00:00 2001 From: wohlganger Date: Thu, 24 Aug 2017 15:35:14 -0500 Subject: [PATCH 25/47] fixed force-open completions missing from config-keys and config. Fixed zoomheight configdialog test. --- Lib/idlelib/config-keys.def | 5 +++++ Lib/idlelib/config.py | 1 + Lib/idlelib/idle_test/test_configdialog.py | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 8ea04538edd49c..1a1b67f98e26d7 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -59,6 +59,7 @@ del-word-left= del-word-right= autocomplete= try-open-completions= +force-open-completions= expand-word= try-open-calltip= refresh-calltip= @@ -122,6 +123,7 @@ del-word-left= del-word-right= autocomplete= try-open-completions= +force-open-completions= expand-word= try-open-calltip= refresh-calltip= @@ -185,6 +187,7 @@ del-word-left = del-word-right = autocomplete= try-open-completions= +force-open-completions= expand-word= try-open-calltip= refresh-calltip= @@ -248,6 +251,7 @@ del-word-left= del-word-right= autocomplete= try-open-completions= +force-open-completions= expand-word= try-open-calltip= refresh-calltip= @@ -312,6 +316,7 @@ open-window-from-file = python-docs = autocomplete= try-open-completions= +force-open-completions= expand-word= try-open-calltip= refresh-calltip= diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 9c2ca2e460828d..0dcf5c9439b848 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -662,6 +662,7 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>':['>':['', '', ''], + '<>':[''], '<>':[''], '<>':[''], '<>':['', ''], diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index d7bcd040e58e8c..f1b7d5b308276a 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -836,7 +836,7 @@ def test_keybinding(self): d.bindingslist.selection_anchor(1) d.keybinding.set('') self.assertEqual(extpage, - {'zoomheight_cfgBindings': {'zoom-height': ''}}) + {'ZoomHeight_cfgBindings': {'zoom-height': ''}}) def test_set_keys_type(self): eq = self.assertEqual From cb161bd96dc5039f7ff85af5834d3e24d4fe2775 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 25 Aug 2017 08:17:17 -0500 Subject: [PATCH 26/47] Changes made per terryjreedy request. Sorry about the formatting; I think that happened when I was trying to fix for the conflicts. --- Lib/idlelib/configdialog.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index ecb75f1fa9f7c2..fab8b137652ad6 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -207,16 +207,12 @@ def deactivate_current_config(self): for instance in win_instances: instance.RemoveKeybindings() - - - def activate_config_changes(self): """Apply configuration changes to current windows. Dynamically update the current parent window instances with some of the configuration changes. """ - win_instances = self.parent.instance_dict.keys() for instance in win_instances: instance.ResetColorizer() @@ -1169,7 +1165,6 @@ def create_new(self, new_theme_name): save_new set_theme_type """ - if self.theme_source.get(): theme_type = 'default' theme_name = self.builtin_name.get() @@ -2079,7 +2074,33 @@ def detach(self): [Cancel] only cancels changes made since the last save. ''' help_pages = { - + 'Highlighting': ''' +Highlighting: +The IDLE Dark color theme is new in October 2015. It can only +be used with older IDLE releases if it is saved as a custom +theme, with a different name. +''', + 'Keys': ''' +Keys: +The IDLE Modern Unix key set is new in June 2016. It can only +be used with older IDLE releases if it is saved as a custom +key set, with a different name. +''', + 'Extensions': ''' +Extensions: + +Autocomplete: Popupwait is milleseconds to wait after key char, without +cursor movement, before popping up completion box. Key char is '.' after +identifier or a '/' (or '\\' on Windows) within a string. + +FormatParagraph: Max-width is max chars in lines after re-formatting. +Use with paragraphs in both strings and comment blocks. + +ParenMatch: Style indicates what is highlighted when closer is entered: +'opener' - opener '({[' corresponding to closer; 'parens' - both chars; +'expression' (default) - also everything in between. Flash-delay is how +long to highlight if cursor is not moved (0 means forever). +''' } From dc09a2b2edb137cbd95d3f680956c9fb18c43e40 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Fri, 25 Aug 2017 08:51:16 -0500 Subject: [PATCH 27/47] re-added autocomplete wait and format paragraph max width options to general tab --- Lib/idlelib/configdialog.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index fab8b137652ad6..80e0eaff86e159 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -791,7 +791,6 @@ def create_page_highlight(self): StringVar(self), self.var_changed_flash_delay) self.num_lines = tracers.add( StringVar(self), self.var_changed_num_lines) - self.parenstyle.set(idleConf.GetOption( 'main','Theme','parenstyle', default='opener')) self.bell.set(idleConf.GetOption( @@ -800,7 +799,6 @@ def create_page_highlight(self): 'main','Theme','flash-delay', default=500)) self.num_lines.set(idleConf.GetOption( 'main','Theme','numlines', default=3)) - # Create widgets: # body frame and section frames. frame_custom = LabelFrame(self, borderwidth=2, relief=GROOVE, @@ -1830,6 +1828,11 @@ def create_page_general(self): self.win_height = tracers.add( StringVar(self), ('main', 'EditorWindow', 'height')) + self.formatp_maxw = tracers.add( + IntVar(self), ('main', 'General', 'formatp_maxw')) + self.autocomplete_wait = tracers.add( + IntVar(self), ('write', 'General', 'autocomplete_wait')) + # Create widgets: # Section frames. frame_run = LabelFrame(self, borderwidth=2, relief=GROOVE, @@ -1837,6 +1840,7 @@ def create_page_general(self): frame_save = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' autosave Preferences ') frame_win_size = Frame(self, borderwidth=2, relief=GROOVE) + frame_extras = Frame(self, borderwidth=2, relief=GROOVE) frame_help = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Additional Help Sources ') # frame_run. @@ -1864,6 +1868,13 @@ def create_page_general(self): win_height_title = Label(frame_win_size, text='Height') self.win_height_int = Entry( frame_win_size, textvariable=self.win_height, width=3) + #frame extras + autocomplete_wait_title = Label(frame_extras, text='AutoComplete Popup Wait') + self.entry_autocomplete_wait = Entry( + frame_extras, textvariable=self.autocomplete_wait, width=6) + formatp_maxw_title = Label(frame_extras, text='Format Paragraph Max Width') + self.entry_formatp_maxw = Entry( + frame_extras, textvariable=self.formatp_maxw, width=3) # frame_help. frame_helplist = Frame(frame_help) frame_helplist_buttons = Frame(frame_helplist) @@ -1889,6 +1900,7 @@ def create_page_general(self): frame_run.pack(side=TOP, padx=5, pady=5, fill=X) frame_save.pack(side=TOP, padx=5, pady=5, fill=X) frame_win_size.pack(side=TOP, padx=5, pady=5, fill=X) + frame_extras.pack(side=TOP, padx=5, pady=5, fill=X) frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) # frame_run. startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5) @@ -1904,6 +1916,11 @@ def create_page_general(self): win_height_title.pack(side=RIGHT, anchor=E, pady=5) self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5) win_width_title.pack(side=RIGHT, anchor=E, pady=5) + #frame extras + self.entry_autocomplete_wait.pack(side=RIGHT, anchor=E, padx=10, pady=5) + autocomplete_wait_title.pack(side=RIGHT, anchor=E, pady=5) + self.entry_formatp_maxw.pack(side=RIGHT, anchor=E, padx=10, pady=5) + formatp_maxw_title.pack(side=RIGHT, anchor=E, pady=5) # frame_help. frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y) frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) From 60ff82f253be57c0e125addf7b9afa18e47be5bb Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 30 Aug 2017 09:21:42 -0500 Subject: [PATCH 28/47] changes per terryjreedy still need to move the imports --- Lib/idlelib/autocomplete.py | 27 ++++--- Lib/idlelib/autoexpand.py | 1 + Lib/idlelib/codecontext.py | 32 ++++----- Lib/idlelib/colorizer.py | 1 - Lib/idlelib/config-extensions.def | 20 ++++-- Lib/idlelib/config-highlight.def | 12 ---- Lib/idlelib/config-keys.def | 105 +++++++++++---------------- Lib/idlelib/config-main.def | 5 -- Lib/idlelib/config.py | 15 +--- Lib/idlelib/configdialog.py | 115 +++++++++++------------------- Lib/idlelib/editor.py | 33 +++++---- Lib/idlelib/mainmenu.py | 3 + Lib/idlelib/parenmatch.py | 8 +-- Lib/idlelib/zoomheight.py | 8 +-- 14 files changed, 156 insertions(+), 229 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index 33eef9ae63e19f..02b7564b8888fd 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -1,6 +1,6 @@ -""" -This can complete either attribute names or file names. It can pop -a window with all available names, for the user to select from. +"""Complete either attribute names or file names. +Either on demand or after a user-selected delay after a key character, +pop up a list of candidates. """ import os import string @@ -26,19 +26,18 @@ class AutoComplete: - def __init__(self, editwin=None): + def __init__(self, editwin): self.editwin = editwin - if editwin is not None: # not in subprocess or test - self.reset() - self.text = editwin.text - self.autocompletewindow = None - # id of delayed call, and the index of the text insert when - # the delayed call was issued. If _delayed_completion_id is - # None, there is no delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None + self.reload() + self.text = editwin.text + self.autocompletewindow = None + # id of delayed call, and the index of the text insert when + # the delayed call was issued. If _delayed_completion_id is + # None, there is no delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None - def reset(self): + def reload(self): self.popupwait = idleConf.GetOption("main", "General", "autocomplete_wait", type="int", default=0) diff --git a/Lib/idlelib/autoexpand.py b/Lib/idlelib/autoexpand.py index 10064c1f6e289b..0b0e8454939663 100644 --- a/Lib/idlelib/autoexpand.py +++ b/Lib/idlelib/autoexpand.py @@ -10,6 +10,7 @@ place before requesting the next selection causes AutoExpand to reset its state. +There is only one instance of Autoexpand. ''' import re import string diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 36703dd3316cc0..5fab5101c88bb7 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -26,7 +26,10 @@ lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() class CodeContext: - + bgcolor = idleConf.GetOption("extensions", "CodeContext", + "bgcolor", type="str", default="LightGray") + fgcolor = idleConf.GetOption("extensions", "CodeContext", + "fgcolor", type="str", default="Black") def __init__(self, editwin): self.editwin = editwin self.text = editwin.text @@ -39,27 +42,20 @@ def __init__(self, editwin): # starts the toplevel 'block' of the module. self.info = [(0, -1, "", False)] self.topvisible = 1 - visible = idleConf.GetOption("main", "Theme", - "contexton", type="bool", default=False) - self.reset() - if visible: - self.toggle_code_context_event() - + self.reload() # Start two update cycles, one for context lines, one for font changes. self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) - def reset(self): - self.menudefs = [('options', [('!Code Conte_xt', '<>')])] - self.context_depth = idleConf.GetOption("main", "Theme", - "numlines", type="int", default=3) - highlight=idleConf.GetHighlight(idleConf.CurrentTheme(),'codecontext') - self.fgcolor = highlight['foreground'] - self.bgcolor = highlight['background'] - if self.topvisible: - #need to rebuild widget to change color - self.toggle_code_context_event() - self.toggle_code_context_event() + def reload(self): + self.context_depth = idleConf.GetOption("extensions", "CodeContext", + "numlines", type="int", default=3) + self.bgcolor = idleConf.GetOption("extensions", "CodeContext", + "bgcolor", type="str", default="LightGray") + self.fgcolor = idleConf.GetOption("extensions", "CodeContext", + "fgcolor", type="str", default="Black") + + def toggle_code_context_event(self, event=None): if not self.label: diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 89d81a0aefc556..ff4084528804bd 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -92,7 +92,6 @@ def LoadTagDefs(self): "ERROR": idleConf.GetHighlight(theme, "error"), # The following is used by ReplaceDialog: "hit": idleConf.GetHighlight(theme, "hit"), - "paren": idleConf.GetHighlight(theme, "parenmatch"), } if DEBUG: print('tagdefs',self.tagdefs) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 5ee60649923c8c..4c53eadea551a8 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -32,7 +32,19 @@ # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. -[ZoomHeight] -enable=True -[ZoomHeight_cfgBindings] -zoom-height= +[AutoComplete] +popupwait=2000 + +[CodeContext] +numlines=3 +visible=False +bgcolor=LightGray +fgcolor=Black + +[FormatParagraph] +max-width=72 + +[ParenMatch] +style=expression +flash-delay=500 +bell=True diff --git a/Lib/idlelib/config-highlight.def b/Lib/idlelib/config-highlight.def index 531708e9c11fa3..4146e28c4eda1f 100644 --- a/Lib/idlelib/config-highlight.def +++ b/Lib/idlelib/config-highlight.def @@ -22,10 +22,6 @@ hit-foreground= #ffffff hit-background= #000000 error-foreground= #000000 error-background= #ff7777 -codecontext-foreground = black -codecontext-background = LightGray -parenmatch-foreground = black -parenmatch-background = gray #cursor (only foreground can be set, restart IDLE) cursor-foreground= black #shell window @@ -57,10 +53,6 @@ hit-foreground= #ffffff hit-background= #000000 error-foreground= #000000 error-background= #ff7777 -codecontext-foreground = black -codecontext-background = LightGray -parenmatch-foreground = #aaaaaa -parenmatch-background = #ffffff #cursor (only foreground can be set, restart IDLE) cursor-foreground= black #shell window @@ -99,7 +91,3 @@ stdout-background = #002240 hit-foreground = #002240 comment-background = #002240 break-foreground = #FFFFFF -codecontext-foreground = #aaaaaa -codecontext-background = #000000 -parenmatch-foreground = #00dddd -parenmatch-background = #002240 diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 1a1b67f98e26d7..935ef06a37a884 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -57,19 +57,14 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= -autocomplete= -try-open-completions= -force-open-completions= -expand-word= -try-open-calltip= -refresh-calltip= -force-open-calltip= -toggle-code-context= -format-paragraph= -flash-paren= -paren-closed= -run-module= -check-module= +force-open-completions= +expand-word= +force-open-calltip= +format-paragraph= +flash-paren= +run-module= +check-module= +zoom-height= [IDLE Classic Unix] copy= @@ -121,19 +116,14 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= -autocomplete= -try-open-completions= -force-open-completions= -expand-word= -try-open-calltip= -refresh-calltip= -force-open-calltip= -toggle-code-context= -format-paragraph= -flash-paren= -paren-closed= -run-module= -check-module= +force-open-completions= +expand-word= +force-open-calltip= +format-paragraph= +flash-paren= +run-module= +check-module= +zoom-height= [IDLE Modern Unix] copy = @@ -185,19 +175,14 @@ toggle-tabs = change-indentwidth = del-word-left = del-word-right = -autocomplete= -try-open-completions= -force-open-completions= -expand-word= -try-open-calltip= -refresh-calltip= -force-open-calltip= -toggle-code-context= -format-paragraph= -flash-paren= -paren-closed= -run-module= -check-module= +force-open-completions= +expand-word= +force-open-calltip= +format-paragraph= +flash-paren= +run-module= +check-module= +zoom-height= [IDLE Classic Mac] copy= @@ -249,19 +234,14 @@ toggle-tabs= change-indentwidth= del-word-left= del-word-right= -autocomplete= -try-open-completions= -force-open-completions= -expand-word= -try-open-calltip= -refresh-calltip= -force-open-calltip= -toggle-code-context= -format-paragraph= -flash-paren= -paren-closed= -run-module= -check-module= +force-open-completions= +expand-word= +force-open-calltip= +format-paragraph= +flash-paren= +run-module= +check-module= +zoom-height= [IDLE Classic OSX] toggle-tabs = @@ -314,16 +294,11 @@ python-context-help = save-copy-of-window-as-file = open-window-from-file = python-docs = -autocomplete= -try-open-completions= -force-open-completions= -expand-word= -try-open-calltip= -refresh-calltip= -force-open-calltip= -toggle-code-context= -format-paragraph= -flash-paren= -paren-closed= -run-module= -check-module= +force-open-completions= +expand-word= +force-open-calltip= +format-paragraph= +flash-paren= +run-module= +check-module= +zoom-height= diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 71ff1f927254ec..24ec7af16b4c37 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -76,11 +76,6 @@ num-spaces= 4 default= 1 name= IDLE Classic name2= -contexton= 0 -numlines= 3 -parenstyle= opener -flash-delay= 500 -bell= 1 # name2 set in user config-main.cfg for themes added after 2015 Oct 1 [Keys] diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 0dcf5c9439b848..758e3be5c029d5 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -360,10 +360,6 @@ def GetThemeDict(self, type, themeName): 'stderr-background':'#ffffff', 'console-foreground':'#000000', 'console-background':'#ffffff', - 'codecontext-foreground':'#000000', - 'codecontext-background':'#ffffff', - 'parenmatch-foreground':'#000000', - 'parenmatch-background':'#ffffff', } for element in theme: if not cfgParser.has_option(themeName, element): @@ -660,20 +656,13 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>':['>':['', '', ''], '<>':[''], '<>':[''], - '<>':[''], - '<>':['', ''], '<>':[''], - '<>':[''], - '<>':[''], - '<>':[''], '<>':[''], - '<>':['', '', ''], '<>':[''], - '<>':[''] + '<>':[''], + '<>':[''] } if keySetName: if not (self.userCfg['keys'].has_section(keySetName) or diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 6883ebbdee89ca..ed0fc8e3fff743 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -769,8 +769,6 @@ def create_page_highlight(self): 'Shell Error Text': ('error', '11'), 'Shell Stdout Text': ('stdout', '12'), 'Shell Stderr Text': ('stderr', '13'), - 'Code Context Text': ('codecontext', '14'), - 'Matched Parenthetics': ('parenmatch', '15'), } self.builtin_name = tracers.add( StringVar(self), self.var_changed_builtin_name) @@ -783,32 +781,13 @@ def create_page_highlight(self): BooleanVar(self), self.var_changed_theme_source) self.highlight_target = tracers.add( StringVar(self), self.var_changed_highlight_target) - self.parenstyle = tracers.add( - StringVar(self), self.var_changed_parenstyle) - self.bell = tracers.add( - StringVar(self), self.var_changed_bell) - self.flash_delay = tracers.add( - StringVar(self), self.var_changed_flash_delay) - self.num_lines = tracers.add( - StringVar(self), self.var_changed_num_lines) - self.parenstyle.set(idleConf.GetOption( - 'main','Theme','parenstyle', default='opener')) - self.bell.set(idleConf.GetOption( - 'main','Theme','bell', default=True)) - self.flash_delay.set(idleConf.GetOption( - 'main','Theme','flash-delay', default=500)) - self.num_lines.set(idleConf.GetOption( - 'main','Theme','numlines', default=3)) + # Create widgets: # body frame and section frames. frame_custom = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Custom Highlighting ') frame_theme = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Highlighting Theme ') - frame_paren = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Matched Parenthetics ') - frame_code = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Code Context ') # frame_custom. text = self.highlight_sample = Text( frame_custom, relief=SOLID, borderwidth=1, @@ -816,13 +795,13 @@ def create_page_highlight(self): takefocus=FALSE, highlightthickness=0, wrap=NONE) text.bind('', lambda e: 'break') text.bind('', lambda e: 'break') - text_and_tags=( - ('Class CodeContext\n', 'codecontext'), + text_and_tags=(('\n', 'normal'), + ('#you can click here', 'comment'), ('\n', 'normal'), ('#to choose items', 'comment'), ('\n', 'normal'), ('def', 'keyword'), (' ', 'normal'), - ('func', 'definition'), - ('(parenthetics)','parenmatch'), + ('func', 'definition'), ('(param):\n ', 'normal'), + ('"""string"""', 'string'), ('\n var0 = ', 'normal'), (':\n','normal'), (' """string"""', 'string'), ('\n var0 = ', 'normal'), ("'string'", 'string'), ('\n var1 = ', 'normal'), @@ -881,24 +860,10 @@ def tem(event, elem=element): frame_theme, text='Delete Custom Theme', command=self.delete_custom) self.theme_message = Label(frame_theme, borderwidth=2) - #frame_paren - self.opt_menu_pstyle = OptionMenu( - frame_paren, self.parenstyle, "opener","parens","expression") - flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') - self.entry_flash = Entry( - frame_paren, textvariable=self.flash_delay, width=4) - self.check_bell = Checkbutton( - frame_paren, text="Bell", variable=self.bell) - #frame_code - lines_label = Label(frame_code, text='Lines : ') - self.entry_num_lines = Entry( - frame_code, textvariable=self.num_lines, width=3) # Pack widgets: # body. frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) frame_theme.pack(side=TOP, padx=5, pady=5, fill=X) - frame_paren.pack(side=TOP, padx=5, pady=5, fill=X) - frame_code.pack(side=TOP, padx=5, pady=5, fill=X) # frame_custom. self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0) @@ -917,14 +882,6 @@ def tem(event, elem=element): self.customlist.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) self.button_delete_custom.pack(side=TOP, fill=X, padx=5, pady=5) self.theme_message.pack(side=TOP, fill=X, pady=5) - #frame_paren - self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) - self.check_bell.pack(side=TOP, anchor=W,padx=5) - flash_label.pack(side=LEFT, anchor=W, padx=5) - self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) - #frame_code - lines_label.pack(side=LEFT, anchor=W, padx=5) - self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) def load_theme_cfg(self): """Load current configuration settings for the theme options. @@ -1029,26 +986,6 @@ def var_changed_highlight_target(self, *params): "Process selection of new target tag for highlighting." self.set_highlight_target() - def var_changed_parenstyle(self, *params): - "Store change to parenthetics display style." - value=self.parenstyle.get() - changes.add_option('main', 'Theme', 'parenstyle', value) - - def var_changed_bell(self, *params): - "Store change to parenthtics bell (on/off)." - value=self.bell.get() - changes.add_option('main', 'Theme', 'bell', value) - - def var_changed_flash_delay(self, *params): - "Store change to parenthetics flash delay." - value=self.flash_delay.get() - changes.add_option('main', 'Theme', 'flash-delay', value) - - def var_changed_num_lines(self, *params): - "Store change to code context - number of lines displayed." - value=self.num_lines.get() - changes.add_option('main', 'Theme', 'numlines', value) - def set_theme_type(self): """Set available screen options based on builtin or custom theme. @@ -1836,19 +1773,32 @@ def create_page_general(self): StringVar(self), ('main', 'EditorWindow', 'width')) self.win_height = tracers.add( StringVar(self), ('main', 'EditorWindow', 'height')) + self.parenstyle = tracers.add( + StringVar(self), ('extensions', 'ParenMatch', 'style')) + self.bell = tracers.add( + BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) + self.flash_delay = tracers.add( + IntVar(self), ('extensions', 'ParenMatch', 'flash-delay')) + self.num_lines = tracers.add( + IntVar(self), ('extensions', 'CodeContext', 'numlines')) self.formatp_maxw = tracers.add( - IntVar(self), ('main', 'General', 'formatp_maxw')) + IntVar(self), ('extensions', 'FormatParagraph', 'max-width')) self.autocomplete_wait = tracers.add( - IntVar(self), ('write', 'General', 'autocomplete_wait')) + IntVar(self), ('extensions', 'Autocomplete', 'popupwait')) + # 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_extras = Frame(self, borderwidth=2, relief=GROOVE) + frame_paren = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Matched Parenthetics ') + frame_code = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Code Context ') frame_help = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Additional Help Sources ') - frame_extras = Frame(self, borderwidth=2, relief=GROOVE) # Frame_window. frame_run = Frame(frame_window, borderwidth=0) startup_title = Label(frame_run, text='At Startup') @@ -1868,6 +1818,18 @@ def create_page_general(self): win_height_title = Label(frame_win_size, text='Height') self.win_height_int = Entry( frame_win_size, textvariable=self.win_height, width=3) + #frame_paren + self.opt_menu_pstyle = OptionMenu( + frame_paren, self.parenstyle, "opener","parens","expression") + flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') + self.entry_flash = Entry( + frame_paren, textvariable=self.flash_delay, width=4) + self.check_bell = Checkbutton( + frame_paren, text="Bell", variable=self.bell) + #frame_code + lines_label = Label(frame_code, text='Lines : ') + self.entry_num_lines = Entry( + frame_code, textvariable=self.num_lines, width=3) #frame extras autocomplete_wait_title = Label(frame_extras, text='AutoComplete Popup Wait') self.entry_autocomplete_wait = Entry( @@ -1908,7 +1870,8 @@ def create_page_general(self): # 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_paren.pack(side=TOP, padx=5, pady=5, fill=X) + frame_code.pack(side=TOP, padx=5, pady=5, fill=X) frame_extras.pack(side=TOP, padx=5, pady=5, fill=X) frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) # frame_run. @@ -1923,6 +1886,14 @@ def create_page_general(self): win_height_title.pack(side=RIGHT, anchor=E, pady=5) self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5) win_width_title.pack(side=RIGHT, anchor=E, pady=5) + #frame_paren + self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) + self.check_bell.pack(side=TOP, anchor=W,padx=5) + flash_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) + #frame_code + lines_label.pack(side=LEFT, anchor=W, padx=5) + self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) #frame extras self.entry_autocomplete_wait.pack(side=RIGHT, anchor=E, padx=10, pady=5) autocomplete_wait_title.pack(side=RIGHT, anchor=E, pady=5) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 9ee3e9e16688cc..e605d2da52fcfc 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -66,6 +66,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): from idlelib.parenmatch import ParenMatch from idlelib.rstrip import RstripExtension from idlelib.runscript import ScriptBinding + from idlelib.zoomheight import ZoomHeight if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') @@ -282,14 +283,15 @@ def __init__(self, flist=None, filename=None, key=None, root=None): #init merged extentions binds - needs to be done after color is set - self.insAutoComplete=AutoComplete(self) - self.insAutoExpand=AutoExpand(self) - self.insCallTips=CallTips(self) - self.insCodeContext=CodeContext(self) - self.insFormatParagraph=FormatParagraph(self) - self.insParenMatch=ParenMatch(self) - self.insRstripExtension=RstripExtension(self) - self.insScriptBinding=ScriptBinding(self) + self.insAutoComplete = AutoComplete(self) + self.insAutoExpand = AutoExpand(self) + self.insCallTips = CallTips(self) + self.insCodeContext = CodeContext(self) + self.insFormatParagraph = FormatParagraph(self) + self.insParenMatch = ParenMatch(self) + self.insRstripExtension = RstripExtension(self) + self.insScriptBinding = ScriptBinding(self) + self.insZoomHeight = ZoomHeight(self) text.bind("<>",self.insAutoComplete.autocomplete_event) text.bind("<>", self.insAutoComplete.try_open_completions_event) @@ -305,6 +307,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>",self.insCallTips.try_open_calltip_event) text.bind("<>",self.insCallTips.refresh_calltip_event) #must come after paren-closed to work right text.bind("<>",self.insCallTips.force_open_calltip_event) + text.bind("<>",self.insZoomHeight.zoom_height_event) def _filename_to_unicode(self, filename): """Return filename as BMP unicode so diplayable in Tk.""" @@ -1008,17 +1011,19 @@ def unload_extensions(self): def load_standard_extensions(self): for name in self.get_standard_extension_names(): - try: - self.load_extension(name) - except: - print("Failed to load extension", repr(name)) - traceback.print_exc() + if name not in {'CodeContext','FormatParagraph','ParenMatch','AutoComplete'}: + # specific exclusions because we are storing config for mainlined old + # extensions in config-extensions.def for backward compatibility + try: + self.load_extension(name) + except: + print("Failed to load extension", repr(name)) + traceback.print_exc() def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) extfiles = { - 'ZoomHeight': 'zoomheight', } def load_extension(self, name): diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index cd649cf5285be6..d1dcb83d9324f4 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -91,6 +91,9 @@ ('Configure _IDLE', '<>'), ('_Code Context', '<>'), ]), + ('windows', [ + ('Zoom Height', '<>'), + ]), ('help', [ ('_About IDLE', '<>'), None, diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 04dca0e0ee8b2d..d4dbc2f26eae56 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -51,15 +51,15 @@ def __init__(self, editwin): def reset(self): self.STYLE = idleConf.GetOption( - 'main','Theme','parenstyle', default='opener') + 'extensions','ParenMatch','style', default='opener') self.FLASH_DELAY = idleConf.GetOption( - 'main','Theme','flash-delay', type='int',default=500) + 'extensions','ParenMatch','flash-delay', type='int',default=500) if idleConf.GetOption( - 'main','Theme','bell', type='bool',default=1): + 'extensions','ParenMatch','bell', type='bool',default=1): self.bell=self.text.bell else: self.bell=lambda:None - self.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), 'parenmatch') + self.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), 'hilite') self.set_style(self.STYLE) def activate_restore(self): diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index d01c9e964aa60f..6f3c577b95dcb7 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -1,4 +1,4 @@ -# Sample extension: zoom a window to maximum height +# Zoom a window to maximum height import re import sys @@ -8,12 +8,6 @@ class ZoomHeight: - menudefs = [ - ('windows', [ - ('_Zoom Height', '<>'), - ]) - ] - def __init__(self, editwin): self.editwin = editwin From e3f6f169d7808a2ddd7725c6ac67b3fcd30f7ade Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 30 Aug 2017 13:52:22 -0500 Subject: [PATCH 29/47] fix warnings, errors, bugs AutoComplete, CodeContext, FormatParagraph, ParenMatch needed special exclusions to have settings read from config-extensions.def . Special exclusions needed for calltips, completions, paren-closed events to prevent them being configurable. --- Lib/idlelib/config.py | 33 ++++++++++++++-------- Lib/idlelib/configdialog.py | 3 ++ Lib/idlelib/editor.py | 55 ++++++++++++++++++------------------- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 758e3be5c029d5..07a138d413f898 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -439,6 +439,10 @@ def GetExtensions(self, active_only=True, """ extns = self.RemoveKeyBindNames( self.GetSectionList('default', 'extensions')) + for extn in ['AutoComplete','CodeContext','FormatParagraph','ParenMatch']: + extns.remove(extn) + # specific exclusions because we are storing config for mainlined old + # extensions in config-extensions.def for backward compatibility userExtns = self.RemoveKeyBindNames( self.GetSectionList('user', 'extensions')) for extn in userExtns: @@ -656,10 +660,13 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], + '<>':[''], + '<>':['', '', ''], '<>':[''], '<>':[''], '<>':[''], '<>':[''], + '<>':['', '', ''], '<>':[''], '<>':[''], '<>':[''] @@ -675,18 +682,20 @@ def GetCoreKeys(self, keySetName=None): _warn(warning, 'keys', keySetName) else: for event in keyBindings: - binding = self.GetKeyBinding(keySetName, event) - if binding: - keyBindings[event] = binding - else: #we are going to return a default, print warning - warning = ( - '\n Warning: config.py - IdleConf.GetCoreKeys -\n' - ' problem retrieving key binding for event %r\n' - ' from key set %r.\n' - ' returning default value: %r' % - (event, keySetName, keyBindings[event]) - ) - _warn(warning, 'keys', keySetName, event) + if event not in {'<>','<>','<>'}: + # do not allow calltips, etc. events/keys to be configured. + binding = self.GetKeyBinding(keySetName, event) + if binding: + keyBindings[event] = binding + else: #we are going to return a default, print warning + warning = ( + '\n Warning: config.py - IdleConf.GetCoreKeys -\n' + ' problem retrieving key binding for event %r\n' + ' from key set %r.\n' + ' returning default value: %r' % + (event, keySetName, keyBindings[event]) + ) + _warn(warning, 'keys', keySetName, event) return keyBindings def GetExtraHelpSourceList(self, configSet): diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index ed0fc8e3fff743..df24fd82631765 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1643,6 +1643,9 @@ def load_keys_list(self, keyset_name): keyset = idleConf.GetKeySet(keyset_name) bind_names = list(keyset.keys()) bind_names.sort() + for key in ('<>','<>','<>'): + #do not allow these event keys to be configured + bind_names.remove(key) self.bindingslist.delete(0, END) for bind_name in bind_names: key = ' '.join(keyset[bind_name]) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index e605d2da52fcfc..f40e29881077b8 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -53,21 +53,20 @@ class EditorWindow(object): from idlelib import mainmenu from tkinter import Toplevel from idlelib.statusbar import MultiStatusBar + from idlelib.autocomplete import AutoComplete + from idlelib.autoexpand import AutoExpand + from idlelib.calltips import CallTips + from idlelib.codecontext import CodeContext + from idlelib.paragraph import FormatParagraph + from idlelib.parenmatch import ParenMatch + from idlelib.rstrip import RstripExtension + from idlelib.runscript import ScriptBinding + from idlelib.zoomheight import ZoomHeight filesystemencoding = sys.getfilesystemencoding() # for file names help_url = None def __init__(self, flist=None, filename=None, key=None, root=None): - from idlelib.autocomplete import AutoComplete - from idlelib.autoexpand import AutoExpand - from idlelib.calltips import CallTips - from idlelib.codecontext import CodeContext - from idlelib.paragraph import FormatParagraph - from idlelib.parenmatch import ParenMatch - from idlelib.rstrip import RstripExtension - from idlelib.runscript import ScriptBinding - from idlelib.zoomheight import ZoomHeight - if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') if sys.platform.count('linux'): @@ -282,16 +281,16 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.showerror = tkMessageBox.showerror - #init merged extentions binds - needs to be done after color is set - self.insAutoComplete = AutoComplete(self) - self.insAutoExpand = AutoExpand(self) - self.insCallTips = CallTips(self) - self.insCodeContext = CodeContext(self) - self.insFormatParagraph = FormatParagraph(self) - self.insParenMatch = ParenMatch(self) - self.insRstripExtension = RstripExtension(self) - self.insScriptBinding = ScriptBinding(self) - self.insZoomHeight = ZoomHeight(self) + # merged extentions binds - depends on frame.text being packed (called from self.ResetColorizer()) + self.insAutoComplete = self.AutoComplete(self) + self.insAutoExpand = self.AutoExpand(self) + self.insCallTips = self.CallTips(self) + self.insCodeContext = self.CodeContext(self) + self.insFormatParagraph = self.FormatParagraph(self) + self.insParenMatch = self.ParenMatch(self) + self.insRstripExtension = self.RstripExtension(self) + self.insScriptBinding = self.ScriptBinding(self) + self.insZoomHeight = self.ZoomHeight(self) text.bind("<>",self.insAutoComplete.autocomplete_event) text.bind("<>", self.insAutoComplete.try_open_completions_event) @@ -305,7 +304,8 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>",self.insScriptBinding.check_module_event) text.bind("<>",self.insRstripExtension.do_rstrip) text.bind("<>",self.insCallTips.try_open_calltip_event) - text.bind("<>",self.insCallTips.refresh_calltip_event) #must come after paren-closed to work right + #refresh-calltips must come after paren-closed to work right + text.bind("<>",self.insCallTips.refresh_calltip_event) text.bind("<>",self.insCallTips.force_open_calltip_event) text.bind("<>",self.insZoomHeight.zoom_height_event) @@ -1011,14 +1011,11 @@ def unload_extensions(self): def load_standard_extensions(self): for name in self.get_standard_extension_names(): - if name not in {'CodeContext','FormatParagraph','ParenMatch','AutoComplete'}: - # specific exclusions because we are storing config for mainlined old - # extensions in config-extensions.def for backward compatibility - try: - self.load_extension(name) - except: - print("Failed to load extension", repr(name)) - traceback.print_exc() + try: + self.load_extension(name) + except: + print("Failed to load extension", repr(name)) + traceback.print_exc() def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) From a253f0cfdb32a4fbc65705c288c0f1a4d92a4816 Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 30 Aug 2017 15:20:11 -0500 Subject: [PATCH 30/47] whitespace --- Lib/idlelib/autocomplete.py | 2 +- Lib/idlelib/config.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index 02b7564b8888fd..bc67e55079e4ca 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -1,4 +1,4 @@ -"""Complete either attribute names or file names. +"""Complete either attribute names or file names. Either on demand or after a user-selected delay after a key character, pop up a list of candidates. """ diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 07a138d413f898..7da9fcaa6d7616 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -440,9 +440,9 @@ def GetExtensions(self, active_only=True, extns = self.RemoveKeyBindNames( self.GetSectionList('default', 'extensions')) for extn in ['AutoComplete','CodeContext','FormatParagraph','ParenMatch']: - extns.remove(extn) + extns.remove(extn) # specific exclusions because we are storing config for mainlined old - # extensions in config-extensions.def for backward compatibility + # extensions in config-extensions.def for backward compatibility userExtns = self.RemoveKeyBindNames( self.GetSectionList('user', 'extensions')) for extn in userExtns: @@ -683,7 +683,7 @@ def GetCoreKeys(self, keySetName=None): else: for event in keyBindings: if event not in {'<>','<>','<>'}: - # do not allow calltips, etc. events/keys to be configured. + # do not allow calltips, etc. events/keys to be configured. binding = self.GetKeyBinding(keySetName, event) if binding: keyBindings[event] = binding From fe8eb7a06bb3515db2c00d78e80fa998f3ec18ca Mon Sep 17 00:00:00 2001 From: wohlganger Date: Wed, 30 Aug 2017 15:41:37 -0500 Subject: [PATCH 31/47] bugfix if the cfg file had one of the old extensions in it, it was showing up in the extensions tab. This fixes that. --- Lib/idlelib/configdialog.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index df24fd82631765..34c7ea06503f79 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -287,7 +287,11 @@ def load_extensions(self): "Fill self.extensions with data from the default and user configs." self.extensions = {} for ext_name in idleConf.GetExtensions(active_only=False): - self.extensions[ext_name] = [] + if ext_name not in {'AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', 'FormatParagraph', + 'ParenMatch', 'RStripExtension', 'ScriptBinding', 'ZoomHeight'}: + # These extensions were converted to built-ins, and need to be filtered out so they don't + # appear in the Extensions tab. + self.extensions[ext_name] = [] for ext_name in self.extensions: opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) From caa777403acf09e010c742d6904fee7974faa4a4 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 31 Aug 2017 12:27:56 -0400 Subject: [PATCH 32/47] Make changes need to get IDLE to run --- Lib/idlelib/autocomplete.py | 28 ++++++++++++++++------------ Lib/idlelib/config.py | 8 ++++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index bc67e55079e4ca..ed0b45cd1fa675 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -26,20 +26,21 @@ class AutoComplete: - def __init__(self, editwin): + def __init__(self, editwin=None): self.editwin = editwin - self.reload() - self.text = editwin.text - self.autocompletewindow = None - # id of delayed call, and the index of the text insert when - # the delayed call was issued. If _delayed_completion_id is - # None, there is no delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None + if editwin is not None: # not in subprocess or test + self.text = editwin.text + self.autocompletewindow = None + # id of delayed call, and the index of the text insert when + # the delayed call was issued. If _delayed_completion_id is + # None, there is no delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None - def reload(self): - self.popupwait = idleConf.GetOption("main", "General", - "autocomplete_wait", type="int", default=0) + @classmethod + def reload(cls): + cls.popupwait = idleConf.GetOption( + "extensions", "AutoComplete", "popupwait", type="int", default=0) def _make_autocomplete_window(self): return autocomplete_w.AutoCompleteWindow(self.text) @@ -222,6 +223,9 @@ def get_entity(self, name): return eval(name, namespace) +AutoComplete.reload() + + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_autocomplete', verbosity=2) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 7da9fcaa6d7616..0c35953a15e11e 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -439,15 +439,15 @@ def GetExtensions(self, active_only=True, """ extns = self.RemoveKeyBindNames( self.GetSectionList('default', 'extensions')) - for extn in ['AutoComplete','CodeContext','FormatParagraph','ParenMatch']: - extns.remove(extn) - # specific exclusions because we are storing config for mainlined old - # extensions in config-extensions.def for backward compatibility userExtns = self.RemoveKeyBindNames( self.GetSectionList('user', 'extensions')) for extn in userExtns: if extn not in extns: #user has added own extension extns.append(extn) + for extn in ['AutoComplete','CodeContext','FormatParagraph','ParenMatch']: + extns.remove(extn) + # specific exclusions because we are storing config for mainlined old + # extensions in config-extensions.def for backward compatibility if active_only: activeExtns = [] for extn in extns: From c29184e935cf2a37894f55246de02d8c03fef138 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 31 Aug 2017 14:02:45 -0400 Subject: [PATCH 33/47] Edit extension/feature files, making existing tests pass. --- Lib/idlelib/autocomplete.py | 1 + Lib/idlelib/autoexpand.py | 4 +--- Lib/idlelib/calltips.py | 6 +++--- Lib/idlelib/codecontext.py | 15 +++++++++------ Lib/idlelib/config-main.def | 2 -- Lib/idlelib/editor.py | 4 +++- Lib/idlelib/paragraph.py | 16 ++++++++++------ Lib/idlelib/parenmatch.py | 24 +++++++++++++----------- Lib/idlelib/runscript.py | 27 +++++++-------------------- Lib/idlelib/zoomheight.py | 2 +- 10 files changed, 48 insertions(+), 53 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index ed0b45cd1fa675..edf445f08b5869 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -1,4 +1,5 @@ """Complete either attribute names or file names. + Either on demand or after a user-selected delay after a key character, pop up a list of candidates. """ diff --git a/Lib/idlelib/autoexpand.py b/Lib/idlelib/autoexpand.py index 0b0e8454939663..42e733a1a9e735 100644 --- a/Lib/idlelib/autoexpand.py +++ b/Lib/idlelib/autoexpand.py @@ -15,9 +15,6 @@ import re import string -###$ event <> -###$ win -###$ unix class AutoExpand: wordchars = string.ascii_letters + string.digits + "_" @@ -93,6 +90,7 @@ def getprevword(self): i = i-1 return line[i:] + if __name__ == '__main__': import unittest unittest.main('idlelib.idle_test.test_autoexpand', verbosity=2) diff --git a/Lib/idlelib/calltips.py b/Lib/idlelib/calltips.py index cbbe546df99e5d..ec8f6169895b88 100644 --- a/Lib/idlelib/calltips.py +++ b/Lib/idlelib/calltips.py @@ -1,9 +1,8 @@ -""" +"""Pop up a reminder of how to call a function. Call Tips are floating windows which display function, class, and method parameter and docstring information when you type an opening parenthesis, and which disappear when you type a closing parenthesis. - """ import inspect import re @@ -15,6 +14,7 @@ from idlelib.hyperparser import HyperParser import __main__ + class CallTips: def __init__(self, editwin=None): @@ -97,6 +97,7 @@ def fetch_tip(self, expression): else: return get_argspec(get_entity(expression)) + def get_entity(expression): """Return the object corresponding to expression evaluated in a namespace spanning sys.modules and __main.dict__. @@ -120,7 +121,6 @@ def get_entity(expression): _invalid_method = "invalid method signature" _argument_positional = "\n['/' marks preceding arguments as positional-only]\n" - def get_argspec(ob): '''Return a string describing the signature of a callable object, or ''. diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 5fab5101c88bb7..779b5b88cf35fa 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -25,6 +25,7 @@ getspacesfirstword =\ lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() + class CodeContext: bgcolor = idleConf.GetOption("extensions", "CodeContext", "bgcolor", type="str", default="LightGray") @@ -47,16 +48,15 @@ def __init__(self, editwin): self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) - def reload(self): - self.context_depth = idleConf.GetOption("extensions", "CodeContext", + @classmethod + def reload(cls): + cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "numlines", type="int", default=3) - self.bgcolor = idleConf.GetOption("extensions", "CodeContext", + cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", "bgcolor", type="str", default="LightGray") - self.fgcolor = idleConf.GetOption("extensions", "CodeContext", + cls.fgcolor = idleConf.GetOption("extensions", "CodeContext", "fgcolor", type="str", default="Black") - - def toggle_code_context_event(self, event=None): if not self.label: # Calculate the border width and horizontal padding required to @@ -180,3 +180,6 @@ def font_timer_event(self): self.textfont = newtextfont self.label["font"] = self.textfont self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) + + +CodeContext.reload() diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index 24ec7af16b4c37..16f4b0959cf13c 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -55,8 +55,6 @@ autosave= 0 print-command-posix=lpr %%s print-command-win=start /min notepad /p %%s delete-exitfunc= 1 -autocomplete_wait= 0 -formatp_maxw= 72 [EditorWindow] width= 80 diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index f40e29881077b8..4f4554c0f0bdb4 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -60,13 +60,15 @@ class EditorWindow(object): from idlelib.paragraph import FormatParagraph from idlelib.parenmatch import ParenMatch from idlelib.rstrip import RstripExtension - from idlelib.runscript import ScriptBinding from idlelib.zoomheight import ZoomHeight filesystemencoding = sys.getfilesystemencoding() # for file names help_url = None def __init__(self, flist=None, filename=None, key=None, root=None): + # Delay import: runscript imports pyshell imports EditorWindow. + from idlelib.runscript import ScriptBinding + if EditorWindow.help_url is None: dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') if sys.platform.count('linux'): diff --git a/Lib/idlelib/paragraph.py b/Lib/idlelib/paragraph.py index b64b4a8690ef42..cf8dfdb641f69d 100644 --- a/Lib/idlelib/paragraph.py +++ b/Lib/idlelib/paragraph.py @@ -1,4 +1,4 @@ -"""format a paragraph or selection to a max width. +"""Format a paragraph, comment block, or selection to a max width. Does basic, standard text formatting, and also understands Python comment blocks. Thus, for editing Python source code, this @@ -24,6 +24,11 @@ class FormatParagraph: def __init__(self, editwin): self.editwin = editwin + @classmethod + def reload(cls): + cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph', + 'max-width', type='int', default=72) + def close(self): self.editwin = None @@ -39,11 +44,7 @@ def format_paragraph_event(self, event, limit=None): The length limit parameter is for testing with a known value. """ - if limit is None: - # The default length limit is that defined by pep8 - limit = idleConf.GetOption( - 'main', 'General', 'formatp_maxw', - type='int', default=72) + limit = self.max_width if limit is None else limit text = self.editwin.text first, last = self.editwin.get_selection_indices() if first and last: @@ -69,6 +70,9 @@ def format_paragraph_event(self, event, limit=None): text.see("insert") return "break" + +FormatParagraph.reload() + def find_paragraph(text, mark): """Returns the start/stop indices enclosing the paragraph that mark is in. diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index d4dbc2f26eae56..12212150c6dc8e 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -45,22 +45,21 @@ def __init__(self, editwin): # and deactivate_restore (which calls event_delete). editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME, self.restore_event) + self.bell = self.text.bell if self.BELL else lambda: None self.counter = 0 self.is_restore_active = 0 - self.reset() + self.set_style(self.STYLE) - def reset(self): - self.STYLE = idleConf.GetOption( + @classmethod + def reload(cls): + cls.STYLE = idleConf.GetOption( 'extensions','ParenMatch','style', default='opener') - self.FLASH_DELAY = idleConf.GetOption( + cls.FLASH_DELAY = idleConf.GetOption( 'extensions','ParenMatch','flash-delay', type='int',default=500) - if idleConf.GetOption( - 'extensions','ParenMatch','bell', type='bool',default=1): - self.bell=self.text.bell - else: - self.bell=lambda:None - self.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), 'hilite') - self.set_style(self.STYLE) + cls.BELL = idleConf.GetOption( + 'extensions','ParenMatch','bell', type='bool', default=1) + cls.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), + 'hilite') def activate_restore(self): "Activate mechanism to restore text from highlighting." @@ -181,6 +180,9 @@ def set_timeout_last(self): lambda self=self, c=self.counter: self.handle_restore_timer(c)) +ParenMatch.reload() + + if __name__ == '__main__': import unittest unittest.main('idlelib.idle_test.test_parenmatch', verbosity=2) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 97c02fc83b5f66..45bf56345825a1 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -1,22 +1,14 @@ -"""execute code outside the Python shell window. +"""Execute code from an editor. -This adds the following commands: +Check module: do a full syntax check of the current module. +Also run the tabnanny to catch any inconsistent tabs. -- Check module does a full syntax check of the current module. - It also runs the tabnanny to catch any inconsistent tabs. - -- Run module executes the module's code in the __main__ namespace. The window - must have been saved previously. The module is added to sys.modules, and is - also added to the __main__ namespace. - -XXX GvR Redesign this interface (yet again) as follows: - -- Present a dialog box for ``Run Module'' - -- Allow specify command line arguments in the dialog box +Run module: also execute the module's code in the __main__ namespace. +The window must have been saved previously. The module is added to +sys.modules, and is also added to the __main__ namespace. +TODO: Specify command line arguments in a dialog box. """ - import os import tabnanny import tokenize @@ -40,11 +32,6 @@ class ScriptBinding: - menudefs = [ - ('run', [None, - ('Check Module', '<>'), - ('Run Module', '<>'), ]), ] - def __init__(self, editwin): self.editwin = editwin # Provide instance variables referenced by debugger diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index 6f3c577b95dcb7..74fbc888a80d3f 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -1,4 +1,4 @@ -# Zoom a window to maximum height +"Zoom a window to maximum height." import re import sys From c62f72629be55484fade5feb685bd3cf36c96d54 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 31 Aug 2017 14:26:11 -0400 Subject: [PATCH 34/47] Redo feature bindings. --- Lib/idlelib/editor.py | 54 +++++++++++++++++++++---------------------- Lib/idlelib/rstrip.py | 1 - 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 4f4554c0f0bdb4..d87f3076c04055 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -96,7 +96,8 @@ def __init__(self, flist=None, filename=None, key=None, root=None): # Safari requires real file:-URLs EditorWindow.help_url = 'file://' + EditorWindow.help_url else: - EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2] + EditorWindow.help_url = ("https://docs.python.org/%d.%d/" + % sys.version_info[:2]) self.flist = flist root = root or flist.root self.root = root @@ -283,33 +284,32 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.showerror = tkMessageBox.showerror - # merged extentions binds - depends on frame.text being packed (called from self.ResetColorizer()) - self.insAutoComplete = self.AutoComplete(self) - self.insAutoExpand = self.AutoExpand(self) - self.insCallTips = self.CallTips(self) - self.insCodeContext = self.CodeContext(self) - self.insFormatParagraph = self.FormatParagraph(self) - self.insParenMatch = self.ParenMatch(self) - self.insRstripExtension = self.RstripExtension(self) - self.insScriptBinding = self.ScriptBinding(self) - self.insZoomHeight = self.ZoomHeight(self) - - text.bind("<>",self.insAutoComplete.autocomplete_event) - text.bind("<>", self.insAutoComplete.try_open_completions_event) - text.bind("<>",self.insAutoComplete.force_open_completions_event) - text.bind("<>",self.insAutoExpand.expand_word_event) - text.bind("<>",self.insCodeContext.toggle_code_context_event) - text.bind("<>",self.insFormatParagraph.format_paragraph_event) - text.bind("<>",self.insParenMatch.flash_paren_event) - text.bind("<>",self.insParenMatch.paren_closed_event) - text.bind("<>",self.insScriptBinding.run_module_event) - text.bind("<>",self.insScriptBinding.check_module_event) - text.bind("<>",self.insRstripExtension.do_rstrip) - text.bind("<>",self.insCallTips.try_open_calltip_event) + # Former extension bindings depends on frame.text being packed + # (called from self.ResetColorizer()). + autocomplete = self.AutoComplete(self) + text.bind("<>", autocomplete.autocomplete_event) + text.bind("<>", + autocomplete.try_open_completions_event) + text.bind("<>", + autocomplete.force_open_completions_event) + text.bind("<>", self.AutoExpand(self).expand_word_event) + text.bind("<>", + self.CodeContext(self).toggle_code_context_event) + text.bind("<>", + self.FormatParagraph(self).format_paragraph_event) + parenmath = self.ParenMatch(self) + text.bind("<>", parenmatch.flash_paren_event) + text.bind("<>", parenmatch.paren_closed_event) + scriptbinding = self.ScriptBinding(self) + text.bind("<>", scriptbinding.check_module_event) + text.bind("<>", scriptbinding.run_module_event) + text.bind("<>", self.RstripExtension().do_rstrip) + calltips = self.CallTips(self) + text.bind("<>", calltips.try_open_calltip_event) #refresh-calltips must come after paren-closed to work right - text.bind("<>",self.insCallTips.refresh_calltip_event) - text.bind("<>",self.insCallTips.force_open_calltip_event) - text.bind("<>",self.insZoomHeight.zoom_height_event) + text.bind("<>", calltips.refresh_calltip_event) + text.bind("<>", calltips.force_open_calltip_event) + text.bind("<>", self.ZoomHeight(self).zoom_height_event) def _filename_to_unicode(self, filename): """Return filename as BMP unicode so diplayable in Tk.""" diff --git a/Lib/idlelib/rstrip.py b/Lib/idlelib/rstrip.py index 82c7f7e8d8c8ab..18c86f9b2c8896 100644 --- a/Lib/idlelib/rstrip.py +++ b/Lib/idlelib/rstrip.py @@ -4,7 +4,6 @@ class RstripExtension: def __init__(self, editwin): self.editwin = editwin - self.editwin.text.bind("<>", self.do_rstrip) def do_rstrip(self, event=None): From d0e009f3dc4bca30ac167208ba8f3f8982edac0a Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 31 Aug 2017 15:50:18 -0400 Subject: [PATCH 35/47] First draft of dummy extension. --- Lib/idlelib/config-extensions.def | 48 ++++++++++++++++++++----------- Lib/idlelib/editor.py | 3 +- Lib/idlelib/zzdummy.py | 41 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 Lib/idlelib/zzdummy.py diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 4c53eadea551a8..0643ac395f465e 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -1,5 +1,25 @@ # config-extensions.def # +# The following sections are for features that are no longer extensions. +# Their options values are left here for back-compatibility. + +[AutoComplete] +popupwait= 2000 + +[CodeContext] +numlines= 3 +visible= False +bgcolor= LightGray +fgcolor= Black + +[FormatParagraph] +max-width= 72 # PEP8 standard + +[ParenMatch] +style= expression +flash-delay= 500 +bell= True + # IDLE reads several config files to determine user preferences. This # file is the default configuration file for IDLE extensions settings. # @@ -19,7 +39,7 @@ # extension that may be sensibly re-configured. # # If there are no keybindings for a menus' virtual events, include lines -# like <>= (See [CodeContext], below.) +# like <>=. # # Currently it is necessary to manually modify this file to change # extension key bindings and default values. To customize, create @@ -32,19 +52,13 @@ # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. -[AutoComplete] -popupwait=2000 - -[CodeContext] -numlines=3 -visible=False -bgcolor=LightGray -fgcolor=Black - -[FormatParagraph] -max-width=72 - -[ParenMatch] -style=expression -flash-delay=500 -bell=True +# A fake extension for testing and example purposes. +# When enabled and invoked, inserts or deletes z-text at beginning of +# every line. +[ZzDummy] +enable= False +enable_shell = False +enable_editor = True +z-text= Z +[ZzDummy_bindings] +z-in= diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index d87f3076c04055..9d98962f5bcc90 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1022,7 +1022,8 @@ def load_standard_extensions(self): def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) - extfiles = { + extfiles = { # Use for experimental features implemented as extension. + 'ZzDummy': 'zzdummy', } def load_extension(self, name): diff --git a/Lib/idlelib/zzdummy.py b/Lib/idlelib/zzdummy.py new file mode 100644 index 00000000000000..c814b80edc2900 --- /dev/null +++ b/Lib/idlelib/zzdummy.py @@ -0,0 +1,41 @@ +"Example extension, also used for testing." + +from idlelib.config import idleConf + +ztext = idleConf.GetOption('extensions', 'ZzDummy', 'z-text') + + +class ZzDummy: + + menudefs = [ + ('format', [ + ('Z in', '<>'), + ('Z out', '<>'), + ] ) + ] + + def __init__(self, editwin): + self.text = editwin.text + z_in = False + + @classmethod + def reload(cls): + cls.ztext = idleConf.GetOption('extensions', 'ZzDummy', 'z-text') + + def z_in_event(self, event): + """ + """ + text = self.text + text.undo_block_start() + for line in range(1, text.index('end')): + text.insert('%d.0', ztest) + text.undo_block_stop() + return "break" + + +ZzDummy.reload() + +##if __name__ == "__main__": +## import unittest +## unittest.main('idlelib.idle_test.test_zzdummy', +## verbosity=2, exit=False) From 9e889c22738305781b99c85368f7d8f1801f2583 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 31 Aug 2017 16:42:52 -0400 Subject: [PATCH 36/47] Fix that eliminate startup error and all but 2 test_idle errors. --- Lib/idlelib/config-extensions.def | 15 ++++++++------- Lib/idlelib/configdialog.py | 3 --- Lib/idlelib/editor.py | 6 +++--- Lib/idlelib/idle_test/test_configdialog.py | 4 ++-- Lib/idlelib/zzdummy.py | 13 +++++++------ 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 0643ac395f465e..0fdb92b37f4396 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -13,7 +13,7 @@ bgcolor= LightGray fgcolor= Black [FormatParagraph] -max-width= 72 # PEP8 standard +max-width= 72 [ParenMatch] style= expression @@ -52,13 +52,14 @@ bell= True # See config-keys.def for notes on specifying keys and extend.txt for # information on creating IDLE extensions. -# A fake extension for testing and example purposes. -# When enabled and invoked, inserts or deletes z-text at beginning of -# every line. -[ZzDummy] -enable= False +# A fake extension for testing and example purposes. When enabled and +# invoked, inserts or deletes z-text at beginning of every line. +[ZzDummy] +enable= True enable_shell = False enable_editor = True z-text= Z [ZzDummy_bindings] -z-in= +z-in= +[ZzDummy_cfgBindings] +z-out= diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 34c7ea06503f79..ebcfeaae2931d7 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1647,9 +1647,6 @@ def load_keys_list(self, keyset_name): keyset = idleConf.GetKeySet(keyset_name) bind_names = list(keyset.keys()) bind_names.sort() - for key in ('<>','<>','<>'): - #do not allow these event keys to be configured - bind_names.remove(key) self.bindingslist.delete(0, END) for bind_name in bind_names: key = ' '.join(keyset[bind_name]) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 9d98962f5bcc90..ad69cbdb3d9fd1 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -297,13 +297,13 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.CodeContext(self).toggle_code_context_event) text.bind("<>", self.FormatParagraph(self).format_paragraph_event) - parenmath = self.ParenMatch(self) + parenmatch = self.ParenMatch(self) text.bind("<>", parenmatch.flash_paren_event) text.bind("<>", parenmatch.paren_closed_event) - scriptbinding = self.ScriptBinding(self) + scriptbinding = ScriptBinding(self) text.bind("<>", scriptbinding.check_module_event) text.bind("<>", scriptbinding.run_module_event) - text.bind("<>", self.RstripExtension().do_rstrip) + text.bind("<>", self.RstripExtension(self).do_rstrip) calltips = self.CallTips(self) text.bind("<>", calltips.try_open_calltip_event) #refresh-calltips must come after paren-closed to work right diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 695f0d7afc2526..7925c6d5148ec9 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -824,7 +824,7 @@ def test_keybinding(self): d.custom_name.set('my custom keys') d.bindingslist.delete(0, 'end') d.bindingslist.insert(0, 'copy') - d.bindingslist.insert(1, 'zoom-height') + d.bindingslist.insert(1, 'z-out') d.bindingslist.selection_set(0) d.bindingslist.selection_anchor(0) # Core binding - adds to keys. @@ -837,7 +837,7 @@ def test_keybinding(self): d.bindingslist.selection_anchor(1) d.keybinding.set('') self.assertEqual(extpage, - {'ZoomHeight_cfgBindings': {'zoom-height': ''}}) + {'ZzDummy_cfgBindings': {'z-out': ''}}) def test_set_keys_type(self): eq = self.assertEqual diff --git a/Lib/idlelib/zzdummy.py b/Lib/idlelib/zzdummy.py index c814b80edc2900..8084499646653d 100644 --- a/Lib/idlelib/zzdummy.py +++ b/Lib/idlelib/zzdummy.py @@ -7,12 +7,12 @@ class ZzDummy: - menudefs = [ - ('format', [ - ('Z in', '<>'), - ('Z out', '<>'), - ] ) - ] +## menudefs = [ +## ('format', [ +## ('Z in', '<>'), +## ('Z out', '<>'), +## ] ) +## ] def __init__(self, editwin): self.text = editwin.text @@ -32,6 +32,7 @@ def z_in_event(self, event): text.undo_block_stop() return "break" + def z_out_event(self, event): pass ZzDummy.reload() From 6afdea3c254c1d8d247f5125f4ca5e85351f68e3 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 1 Sep 2017 23:21:14 -0400 Subject: [PATCH 37/47] Move widgets, load widgets, add tests, make previous tests pass. --- Lib/idlelib/config-extensions.def | 4 +- Lib/idlelib/configdialog.py | 158 ++++++++++++--------- Lib/idlelib/idle_test/test_config.py | 59 +++----- Lib/idlelib/idle_test/test_configdialog.py | 42 ++++-- 4 files changed, 148 insertions(+), 115 deletions(-) diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def index 0fdb92b37f4396..e8d417bac0d497 100644 --- a/Lib/idlelib/config-extensions.def +++ b/Lib/idlelib/config-extensions.def @@ -59,7 +59,7 @@ enable= True enable_shell = False enable_editor = True z-text= Z -[ZzDummy_bindings] -z-in= [ZzDummy_cfgBindings] +z-in= +[ZzDummy_bindings] z-out= diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index ebcfeaae2931d7..fd26b780abb811 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -10,12 +10,12 @@ """ from tkinter import (Toplevel, Listbox, Text, Scale, Canvas, - OptionMenu, StringVar, BooleanVar, IntVar, TRUE, FALSE, + StringVar, BooleanVar, IntVar, TRUE, FALSE, TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE, NORMAL, DISABLED, NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW, HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END) from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame, - Notebook, Radiobutton, Scrollbar, Style) + OptionMenu, Notebook, Radiobutton, Scrollbar, Style) import tkinter.colorchooser as tkColorChooser import tkinter.font as tkFont from tkinter import messagebox @@ -287,8 +287,8 @@ def load_extensions(self): "Fill self.extensions with data from the default and user configs." self.extensions = {} for ext_name in idleConf.GetExtensions(active_only=False): - if ext_name not in {'AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', 'FormatParagraph', - 'ParenMatch', 'RStripExtension', 'ScriptBinding', 'ZoomHeight'}: + if ext_name not in {'AutoComplete', 'CodeContext', + 'FormatParagraph', 'ParenMatch'}: # These extensions were converted to built-ins, and need to be filtered out so they don't # appear in the Extensions tab. self.extensions[ext_name] = [] @@ -1771,24 +1771,25 @@ def create_page_general(self): """ self.startup_edit = tracers.add( IntVar(self), ('main', 'General', 'editor-on-startup')) - self.autosave = tracers.add( - IntVar(self), ('main', 'General', 'autosave')) self.win_width = tracers.add( StringVar(self), ('main', 'EditorWindow', 'width')) self.win_height = tracers.add( StringVar(self), ('main', 'EditorWindow', 'height')) - self.parenstyle = tracers.add( + self.autocomplete_wait = tracers.add( + IntVar(self), ('extensions', 'AutoComplete', 'popupwait')) + self.paren_style = tracers.add( StringVar(self), ('extensions', 'ParenMatch', 'style')) - self.bell = tracers.add( - BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) self.flash_delay = tracers.add( IntVar(self), ('extensions', 'ParenMatch', 'flash-delay')) - self.num_lines = tracers.add( + self.paren_bell = tracers.add( + BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) + + self.autosave = tracers.add( + IntVar(self), ('main', 'General', 'autosave')) + self.format_width = tracers.add( + IntVar(self), ('extensions', 'FormatParagraph', 'max-width')) + self.context_lines = tracers.add( IntVar(self), ('extensions', 'CodeContext', 'numlines')) - self.formatp_maxw = tracers.add( - IntVar(self), ('extensions', 'FormatParagraph', 'max-width')) - self.autocomplete_wait = tracers.add( - IntVar(self), ('extensions', 'Autocomplete', 'popupwait')) # Create widgets: # Section frames. @@ -1796,11 +1797,6 @@ def create_page_general(self): text=' Window Preferences') frame_editor = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Editor Preferences') - frame_extras = Frame(self, borderwidth=2, relief=GROOVE) - frame_paren = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Matched Parenthetics ') - frame_code = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Code Context ') frame_help = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Additional Help Sources ') # Frame_window. @@ -1813,7 +1809,7 @@ def create_page_general(self): frame_run, variable=self.startup_edit, value=0, text='Open Shell Window') - frame_win_size = Frame(frame_window, borderwidth=0,) + frame_win_size = Frame(frame_window, borderwidth=0) win_size_title = Label( frame_win_size, text='Initial Window Size (in characters)') win_width_title = Label(frame_win_size, text='Width') @@ -1822,25 +1818,27 @@ def create_page_general(self): win_height_title = Label(frame_win_size, text='Height') self.win_height_int = Entry( frame_win_size, textvariable=self.win_height, width=3) - #frame_paren - self.opt_menu_pstyle = OptionMenu( - frame_paren, self.parenstyle, "opener","parens","expression") - flash_label = Label(frame_paren, text='Time Displayed : \n(0 is until given input)') - self.entry_flash = Entry( - frame_paren, textvariable=self.flash_delay, width=4) - self.check_bell = Checkbutton( - frame_paren, text="Bell", variable=self.bell) - #frame_code - lines_label = Label(frame_code, text='Lines : ') - self.entry_num_lines = Entry( - frame_code, textvariable=self.num_lines, width=3) - #frame extras - autocomplete_wait_title = Label(frame_extras, text='AutoComplete Popup Wait') - self.entry_autocomplete_wait = Entry( - frame_extras, textvariable=self.autocomplete_wait, width=6) - formatp_maxw_title = Label(frame_extras, text='Format Paragraph Max Width') - self.entry_formatp_maxw = Entry( - frame_extras, textvariable=self.formatp_maxw, width=3) + + frame_autocomplete = Frame(frame_window, borderwidth=0,) + auto_wait_title = Label(frame_autocomplete, + text='Completions Popup Wait (milliseconds)') + self.auto_wait_int = Entry(frame_autocomplete, width=6, + textvariable=self.autocomplete_wait) + + frame_paren1 = Frame(frame_window, borderwidth=0) + paren_style_title = Label(frame_paren1, text='Paren Match Style') + self.paren_style_type = OptionMenu( + frame_paren1, self.paren_style, 'expression', + "opener","parens","expression") + frame_paren2 = Frame(frame_window, borderwidth=0) + paren_time_title = Label( + frame_paren2, text='Time Match Displayed (milliseconds)\n' + '(0 is until next input)') + self.paren_flash_time = Entry( + 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) ') @@ -1850,6 +1848,19 @@ def create_page_general(self): self.save_auto_on = Radiobutton( frame_save, variable=self.autosave, value=1, text='No Prompt') + + frame_format = Frame(frame_editor, 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) + + frame_context = Frame(frame_editor, borderwidth=0) + context_title = Label(frame_context, text='Context Lines :') + self.context_int = Entry( + frame_context, textvariable=self.context_lines, width=3) + + # frame_help. frame_helplist = Frame(frame_help) frame_helplist_buttons = Frame(frame_helplist) @@ -1874,9 +1885,6 @@ def create_page_general(self): # 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_paren.pack(side=TOP, padx=5, pady=5, fill=X) - frame_code.pack(side=TOP, padx=5, pady=5, fill=X) - frame_extras.pack(side=TOP, padx=5, pady=5, fill=X) frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) # frame_run. frame_run.pack(side=TOP, padx=5, pady=0, fill=X) @@ -1890,24 +1898,33 @@ def create_page_general(self): win_height_title.pack(side=RIGHT, anchor=E, pady=5) self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5) win_width_title.pack(side=RIGHT, anchor=E, pady=5) - #frame_paren - self.opt_menu_pstyle.pack(side=TOP,anchor=W,padx=5, fill=X) - self.check_bell.pack(side=TOP, anchor=W,padx=5) - flash_label.pack(side=LEFT, anchor=W, padx=5) - self.entry_flash.pack(side=LEFT, fill=X,anchor=W,padx=5) - #frame_code - lines_label.pack(side=LEFT, anchor=W, padx=5) - self.entry_num_lines.pack(side=LEFT,anchor=W,padx=5) - #frame extras - self.entry_autocomplete_wait.pack(side=RIGHT, anchor=E, padx=10, pady=5) - autocomplete_wait_title.pack(side=RIGHT, anchor=E, pady=5) - self.entry_formatp_maxw.pack(side=RIGHT, anchor=E, padx=10, pady=5) - formatp_maxw_title.pack(side=RIGHT, anchor=E, pady=5) + # frame_autocomplete. + frame_autocomplete.pack(side=TOP, padx=5, pady=0, fill=X) + auto_wait_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.auto_wait_int.pack(side=TOP, padx=10, pady=5) + # frame_paren. + frame_paren1.pack(side=TOP, padx=5, pady=0, fill=X) + paren_style_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.paren_style_type.pack(side=TOP, padx=10, pady=5) + frame_paren2.pack(side=TOP, padx=5, pady=0, fill=X) + 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_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_help. frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y) frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) @@ -1919,17 +1936,30 @@ def create_page_general(self): def load_general_cfg(self): "Load current configuration settings for the general options." - # Set startup state. + # Set variables for all windows. self.startup_edit.set(idleConf.GetOption( - 'main', 'General', 'editor-on-startup', default=0, type='bool')) - # Set autosave state. - self.autosave.set(idleConf.GetOption( - 'main', 'General', 'autosave', default=0, type='bool')) - # Set initial window size. + 'main', 'General', 'editor-on-startup', type='bool')) self.win_width.set(idleConf.GetOption( 'main', 'EditorWindow', 'width', type='int')) self.win_height.set(idleConf.GetOption( 'main', 'EditorWindow', 'height', type='int')) + self.autocomplete_wait.set(idleConf.GetOption( + 'extensions', 'AutoComplete', 'popupwait', type='int')) + self.paren_style.set(idleConf.GetOption( + 'extensions', 'ParenMatch', 'style')) + self.flash_delay.set(idleConf.GetOption( + 'extensions', 'ParenMatch', 'flash-delay', type='int')) + self.paren_bell.set(idleConf.GetOption( + 'extensions', 'ParenMatch', 'bell')) + + # 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.context_lines.set(idleConf.GetOption( + 'extensions', 'CodeContext', 'numlines', type='int')) + # Set additional help sources. self.user_helplist = idleConf.GetAllExtraHelpSourcesList() self.helplist.delete(0, 'end') @@ -2090,10 +2120,10 @@ def detach(self): be used with older IDLE releases if it is saved as a custom key set, with a different name. ''', - 'Extensions': ''' -Extensions: + 'General': ''' +General: -Autocomplete: Popupwait is milleseconds to wait after key char, without +AutoComplete: Popupwait is milleseconds to wait after key char, without cursor movement, before popping up completion box. Key char is '.' after identifier or a '/' (or '\\' on Windows) within a string. diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index bbf06504fc2552..aa33a0f642fdcb 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -437,78 +437,57 @@ def test_get_extensions(self): eq = self.assertEqual eq(conf.GetExtensions(), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding', - 'ZoomHeight']) + ['ZzDummy']) eq(conf.GetExtensions(active_only=False), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding', - 'ZoomHeight', 'DISABLE']) + ['ZzDummy', 'DISABLE']) eq(conf.GetExtensions(editor_only=True), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding', - 'ZoomHeight']) + ['ZzDummy']) eq(conf.GetExtensions(shell_only=True), - ['AutoComplete', 'AutoExpand', 'CallTips', 'FormatParagraph', - 'ParenMatch', 'ZoomHeight']) + []) eq(conf.GetExtensions(active_only=False, editor_only=True), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', - 'ScriptBinding', 'ZoomHeight', 'DISABLE']) - eq(conf.GetExtensions(active_only=False, shell_only=True), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding', - 'ZoomHeight', 'DISABLE']) + ['ZzDummy', 'DISABLE']) # Add user extensions conf.SetOption('extensions', 'Foobar', 'enable', 'True') eq(conf.GetExtensions(), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', - 'ScriptBinding', 'ZoomHeight', 'Foobar']) # User extensions didn't sort + ['ZzDummy', 'Foobar']) # User extensions didn't sort eq(conf.GetExtensions(active_only=False), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', - 'ScriptBinding', 'ZoomHeight', 'DISABLE', 'Foobar']) + ['ZzDummy', 'DISABLE', 'Foobar']) def test_remove_key_bind_names(self): conf = self.mock_config() self.assertCountEqual( conf.RemoveKeyBindNames(conf.GetSectionList('default', 'extensions')), - ['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext', - 'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding', - 'ZoomHeight']) + ['AutoComplete', 'CodeContext', 'FormatParagraph', 'ParenMatch','ZzDummy']) def test_get_extn_name_for_event(self): conf = self.mock_config() eq = self.assertEqual - eq(conf.GetExtnNameForEvent('force-open-completions'), 'AutoComplete') - eq(conf.GetExtnNameForEvent('expand-word'), 'AutoExpand') - eq(conf.GetExtnNameForEvent('force-open-calltip'), 'CallTips') - eq(conf.GetExtnNameForEvent('zoom-height'), 'ZoomHeight') + eq(conf.GetExtnNameForEvent('z-in'), 'ZzDummy') + eq(conf.GetExtnNameForEvent('z-out'), None) def test_get_extension_keys(self): conf = self.mock_config() eq = self.assertEqual - eq(conf.GetExtensionKeys('AutoComplete'), - {'<>': ['']}) - eq(conf.GetExtensionKeys('ParenMatch'), - {'<>': ['']}) - - key = [''] if sys.platform == 'darwin' else [''] - eq(conf.GetExtensionKeys('ZoomHeight'), {'<>': key}) + eq(conf.GetExtensionKeys('ZzDummy'), + {'<>': ['']}) +# need option key test +## key = [''] if sys.platform == 'darwin' else [''] +## eq(conf.GetExtensionKeys('ZoomHeight'), {'<>': key}) def test_get_extension_bindings(self): conf = self.mock_config() self.assertEqual(conf.GetExtensionBindings('NotExists'), {}) - key = [''] if sys.platform == 'darwin' else [''] + #key = [''] if sys.platform == 'darwin' else [''] + expect = {'<>': [''], + '<>': ['']} self.assertEqual( - conf.GetExtensionBindings('ZoomHeight'), {'<>': key}) + conf.GetExtensionBindings('ZzDummy'), expect) # Add non-configuarable bindings conf.defaultCfg['extensions'].add_section('Foobar') diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 7925c6d5148ec9..3d6a858e6fd2b9 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -824,7 +824,7 @@ def test_keybinding(self): d.custom_name.set('my custom keys') d.bindingslist.delete(0, 'end') d.bindingslist.insert(0, 'copy') - d.bindingslist.insert(1, 'z-out') + d.bindingslist.insert(1, 'z-in') d.bindingslist.selection_set(0) d.bindingslist.selection_anchor(0) # Core binding - adds to keys. @@ -837,7 +837,7 @@ def test_keybinding(self): d.bindingslist.selection_anchor(1) d.keybinding.set('') self.assertEqual(extpage, - {'ZzDummy_cfgBindings': {'z-out': ''}}) + {'ZzDummy_cfgBindings': {'z-in': ''}}) def test_set_keys_type(self): eq = self.assertEqual @@ -1126,13 +1126,6 @@ def test_startup(self): self.assertEqual(mainpage, {'General': {'editor-on-startup': '0'}}) - def test_autosave(self): - d = self.page - d.save_auto_on.invoke() - self.assertEqual(mainpage, {'General': {'autosave': '1'}}) - d.save_ask_on.invoke() - self.assertEqual(mainpage, {'General': {'autosave': '0'}}) - def test_editor_size(self): d = self.page d.win_height_int.insert(0, '1') @@ -1141,6 +1134,37 @@ def test_editor_size(self): d.win_width_int.insert(0, '1') self.assertEqual(mainpage, {'EditorWindow': {'width': '180'}}) + def test_autocomplete_wait(self): + self.page.auto_wait_int.insert(0, '1') + self.assertEqual(extpage, {'AutoComplete': {'popupwait': '12000'}}) + + def test_parenmatch(self): + d = self.page + eq = self.assertEqual + d.paren_style_type['menu'].invoke(0) + eq(extpage, {'ParenMatch': {'style': 'opener'}}) + changes.clear() + d.paren_flash_time.insert(0, '2') + eq(extpage, {'ParenMatch': {'flash-delay': '2500'}}) + changes.clear() + d.bell_on.invoke() + eq(extpage, {'ParenMatch': {'bell': 'False'}}) + + def test_autosave(self): + d = self.page + d.save_auto_on.invoke() + self.assertEqual(mainpage, {'General': {'autosave': '1'}}) + d.save_ask_on.invoke() + self.assertEqual(mainpage, {'General': {'autosave': '0'}}) + + def test_paragraph(self): + self.page.format_width_int.insert(0, '1') + self.assertEqual(extpage, {'FormatParagraph': {'max-width': '172'}}) + + def test_context(self): + self.page.context_int.insert(0, '1') + self.assertEqual(extpage, {'CodeContext': {'numlines': '13'}}) + def test_source_selected(self): d = self.page d.set = d.set_add_delete_state From 7de27db56b352bc87f682b2507243200fc15da99 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 5 Sep 2017 00:49:47 -0400 Subject: [PATCH 38/47] Add format-paragraph to core keys. --- Lib/idlelib/config.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 0c35953a15e11e..e44818024ef63a 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -660,16 +660,17 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>':[''], - '<>':['', '', ''], - '<>':[''], - '<>':[''], - '<>':[''], - '<>':[''], - '<>':['', '', ''], - '<>':[''], - '<>':[''], - '<>':[''] + '<>': [''], + '<>': ['', '', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', '', ''], + '<>': [''], + '<>': [''], + '<>': [''], } if keySetName: if not (self.userCfg['keys'].has_section(keySetName) or From 2265b53e1ba2f53aca8c0820ed02ecef15a3000e Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 5 Sep 2017 02:05:12 -0400 Subject: [PATCH 39/47] Fix autocomplete and long lines. --- Lib/idlelib/autocomplete.py | 1 + Lib/idlelib/config.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index edf445f08b5869..06c771cc08e1f1 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -31,6 +31,7 @@ def __init__(self, editwin=None): self.editwin = editwin if editwin is not None: # not in subprocess or test self.text = editwin.text + self.text.event_add('<>', '') self.autocompletewindow = None # id of delayed call, and the index of the text insert when # the delayed call was issued. If _delayed_completion_id is diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index e44818024ef63a..105a177c46b505 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -661,13 +661,17 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>': ['', '', ''], + '<>': ['', + '', + ''], '<>': [''], '<>': [''], '<>': [''], '<>': [''], '<>': [''], - '<>': ['', '', ''], + '<>': ['', + '', + ''], '<>': [''], '<>': [''], '<>': [''], @@ -683,7 +687,9 @@ def GetCoreKeys(self, keySetName=None): _warn(warning, 'keys', keySetName) else: for event in keyBindings: - if event not in {'<>','<>','<>'}: + if event not in {'<>', + '<>', + '<>'}: # do not allow calltips, etc. events/keys to be configured. binding = self.GetKeyBinding(keySetName, event) if binding: From 03eed248bc51e59abdf6409e07b9264198e69312 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 8 Sep 2017 21:23:36 -0400 Subject: [PATCH 40/47] Put fixed-key event-adds in EditorWindow.__init__ for now. --- Lib/idlelib/autocomplete.py | 1 - Lib/idlelib/config.py | 7 ------- Lib/idlelib/editor.py | 10 ++++++++++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index 06c771cc08e1f1..edf445f08b5869 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -31,7 +31,6 @@ def __init__(self, editwin=None): self.editwin = editwin if editwin is not None: # not in subprocess or test self.text = editwin.text - self.text.event_add('<>', '') self.autocompletewindow = None # id of delayed call, and the index of the text insert when # the delayed call was issued. If _delayed_completion_id is diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 105a177c46b505..d37fd9afce37c3 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -660,18 +660,11 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>': [''], - '<>': ['', - '', - ''], '<>': [''], '<>': [''], '<>': [''], '<>': [''], '<>': [''], - '<>': ['', - '', - ''], '<>': [''], '<>': [''], '<>': [''], diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index ad69cbdb3d9fd1..ea738999638919 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -284,6 +284,16 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.showerror = tkMessageBox.showerror + # Add pseudoevents for former extension fixed keys. + # (This probably needs to be done once in the process.) + text.event_add('<>', '') + text.event_add('<>', '' + '', '') + text.event_add('<>', '') + text.event_add('<>', '') + text.event_add('<>', '', + '', '') + # Former extension bindings depends on frame.text being packed # (called from self.ResetColorizer()). autocomplete = self.AutoComplete(self) From 207b0cac586371559e0db55e0f40485e9f837e00 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 8 Sep 2017 22:01:56 -0400 Subject: [PATCH 41/47] Don't warn if new core keys not in user key config. --- Lib/idlelib/config.py | 37 ++++++++++++++++++++----------------- Lib/idlelib/editor.py | 7 +++---- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index d37fd9afce37c3..2233b54228a336 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -599,7 +599,12 @@ def IsCoreBinding(self, virtualEvent): return ('<<'+virtualEvent+'>>') in self.GetCoreKeys() # TODO make keyBindins a file or class attribute used for test above -# and copied in function below +# and copied in function below. + + former_extension_events = { # Those with user-configurable keys. + '<>', '<>', + '<>', '<>', '<>', + '<>', '<>', '<>'} def GetCoreKeys(self, keySetName=None): """Return dict of core virtual-key keybindings for keySetName. @@ -669,6 +674,7 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], } + if keySetName: if not (self.userCfg['keys'].has_section(keySetName) or self.defaultCfg['keys'].has_section(keySetName)): @@ -680,22 +686,19 @@ def GetCoreKeys(self, keySetName=None): _warn(warning, 'keys', keySetName) else: for event in keyBindings: - if event not in {'<>', - '<>', - '<>'}: - # do not allow calltips, etc. events/keys to be configured. - binding = self.GetKeyBinding(keySetName, event) - if binding: - keyBindings[event] = binding - else: #we are going to return a default, print warning - warning = ( - '\n Warning: config.py - IdleConf.GetCoreKeys -\n' - ' problem retrieving key binding for event %r\n' - ' from key set %r.\n' - ' returning default value: %r' % - (event, keySetName, keyBindings[event]) - ) - _warn(warning, 'keys', keySetName, event) + binding = self.GetKeyBinding(keySetName, event) + if binding: + keyBindings[event] = binding + # Otherwise return default in keyBindings. + elif event not in self.former_extension_events: + warning = ( + '\n Warning: config.py - IdleConf.GetCoreKeys -\n' + ' problem retrieving key binding for event %r\n' + ' from key set %r.\n' + ' returning default value: %r' % + (event, keySetName, keyBindings[event]) + ) + _warn(warning, 'keys', keySetName, event) return keyBindings def GetExtraHelpSourceList(self, configSet): diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index ea738999638919..03ee1128636820 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -283,11 +283,10 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.askinteger = tkSimpleDialog.askinteger self.showerror = tkMessageBox.showerror - # Add pseudoevents for former extension fixed keys. # (This probably needs to be done once in the process.) text.event_add('<>', '') - text.event_add('<>', '' + text.event_add('<>', '', '', '') text.event_add('<>', '') text.event_add('<>', '') @@ -303,8 +302,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>", autocomplete.force_open_completions_event) text.bind("<>", self.AutoExpand(self).expand_word_event) - text.bind("<>", - self.CodeContext(self).toggle_code_context_event) text.bind("<>", self.FormatParagraph(self).format_paragraph_event) parenmatch = self.ParenMatch(self) @@ -320,6 +317,8 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind("<>", calltips.refresh_calltip_event) text.bind("<>", calltips.force_open_calltip_event) text.bind("<>", self.ZoomHeight(self).zoom_height_event) + text.bind("<>", + self.CodeContext(self).toggle_code_context_event) def _filename_to_unicode(self, filename): """Return filename as BMP unicode so diplayable in Tk.""" From 00acd22b068560e0d7cea1d8cddca0dadc371f6c Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 8 Sep 2017 22:16:29 -0400 Subject: [PATCH 42/47] Make code context inoperative in outwin, shell. --- Lib/idlelib/outwin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/idlelib/outwin.py b/Lib/idlelib/outwin.py index 5f7c09fb92cdad..6c2a792d86b99a 100644 --- a/Lib/idlelib/outwin.py +++ b/Lib/idlelib/outwin.py @@ -77,6 +77,7 @@ class OutputWindow(EditorWindow): def __init__(self, *args): EditorWindow.__init__(self, *args) self.text.bind("<>", self.goto_file_line) + self.text.unbind("<>") # Customize EditorWindow def ispythonsource(self, filename): From 2d2bfbd5e765c8badeaa214f9a456fb06a5d225d Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 8 Sep 2017 23:19:13 -0400 Subject: [PATCH 43/47] Change new bindings for MacOsx. --- Lib/idlelib/config-keys.def | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 935ef06a37a884..fd235194dfc950 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -235,13 +235,13 @@ change-indentwidth= del-word-left= del-word-right= force-open-completions= -expand-word= +expand-word= force-open-calltip= -format-paragraph= +format-paragraph= flash-paren= run-module= -check-module= -zoom-height= +check-module= +zoom-height= [IDLE Classic OSX] toggle-tabs = @@ -295,10 +295,10 @@ save-copy-of-window-as-file = open-window-from-file = python-docs = force-open-completions= -expand-word= +expand-word= force-open-calltip= -format-paragraph= +format-paragraph= flash-paren= run-module= -check-module= -zoom-height= +check-module= +zoom-height= From fe76cd32f89ec5df485a5313664a3a884916e67c Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 9 Sep 2017 16:51:15 -0400 Subject: [PATCH 44/47] Disable test dependent on extension Alt keys. --- Lib/idlelib/idle_test/test_config.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index aa33a0f642fdcb..84b45a6376749d 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -521,9 +521,11 @@ def test_get_current_keyset(self): sys.platform = 'some-linux' self.assertEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys())) - # This should not be the same, sicne replace Date: Sat, 9 Sep 2017 18:43:02 -0400 Subject: [PATCH 45/47] Minor edits. --- Lib/idlelib/config.py | 3 ++- Lib/idlelib/configdialog.py | 13 ++++--------- Lib/idlelib/editor.py | 4 +--- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 2233b54228a336..c3e57bc692d801 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -444,7 +444,8 @@ def GetExtensions(self, active_only=True, for extn in userExtns: if extn not in extns: #user has added own extension extns.append(extn) - for extn in ['AutoComplete','CodeContext','FormatParagraph','ParenMatch']: + for extn in ('AutoComplete','CodeContext', + 'FormatParagraph','ParenMatch'): extns.remove(extn) # specific exclusions because we are storing config for mainlined old # extensions in config-extensions.def for backward compatibility diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index fd26b780abb811..8260da6c990ef1 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -287,11 +287,8 @@ def load_extensions(self): "Fill self.extensions with data from the default and user configs." self.extensions = {} for ext_name in idleConf.GetExtensions(active_only=False): - if ext_name not in {'AutoComplete', 'CodeContext', - 'FormatParagraph', 'ParenMatch'}: - # These extensions were converted to built-ins, and need to be filtered out so they don't - # appear in the Extensions tab. - self.extensions[ext_name] = [] + # Former built-in extensions are already filtered out. + self.extensions[ext_name] = [] for ext_name in self.extensions: opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) @@ -799,15 +796,13 @@ def create_page_highlight(self): takefocus=FALSE, highlightthickness=0, wrap=NONE) text.bind('', lambda e: 'break') text.bind('', lambda e: 'break') - text_and_tags=(('\n', 'normal'), - + text_and_tags=( + ('\n', 'normal'), ('#you can click here', 'comment'), ('\n', 'normal'), ('#to choose items', 'comment'), ('\n', 'normal'), ('def', 'keyword'), (' ', 'normal'), ('func', 'definition'), ('(param):\n ', 'normal'), ('"""string"""', 'string'), ('\n var0 = ', 'normal'), - (':\n','normal'), - (' """string"""', 'string'), ('\n var0 = ', 'normal'), ("'string'", 'string'), ('\n var1 = ', 'normal'), ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), ("'found'", 'hit'), ('\n var3 = ', 'normal'), diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 03ee1128636820..855d375055653a 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -27,12 +27,10 @@ from idlelib import search from idlelib import windows - # The default tab setting for a Text widget, in average-width characters. TK_TABWIDTH_DEFAULT = 8 _py_version = ' (%s)' % platform.python_version() - def _sphinx_version(): "Format sys.version_info to produce the Sphinx version string used to install the chm docs" major, minor, micro, level, serial = sys.version_info @@ -1031,7 +1029,7 @@ def load_standard_extensions(self): def get_standard_extension_names(self): return idleConf.GetExtensions(editor_only=True) - extfiles = { # Use for experimental features implemented as extension. + extfiles = { # Map built-in config-extension section names to file names. 'ZzDummy': 'zzdummy', } From 6845bb0a53ad34c1625a4d85373250eb9175041b Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 9 Sep 2017 22:40:31 -0400 Subject: [PATCH 46/47] File out news blurb explaining effect for users. --- .../2017-08-24-13-48-16.bpo-27099.rENefC.rst | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst b/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst index 539f06eb63b446..9b59fbabe531b0 100644 --- a/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst +++ b/Misc/NEWS.d/next/IDLE/2017-08-24-13-48-16.bpo-27099.rENefC.rst @@ -1,2 +1,20 @@ -Convert IDLE's built-in 'extensions' to regular features. Inital patch by -Charles Wohlganger. +Convert IDLE's built-in 'extensions' to regular features. + +About 10 IDLE features were implemented as supposedly optional +extensions. Their different behavior could be confusing or worse for +users and not good for maintenance. Hence the conversion. + +The main difference for users is that user configurable key bindings +for builtin features are now handled uniformly. Now, editing a binding +in a keyset only affects its value in the keyset. All bindings are +defined together in the system-specific default keysets in config- +extensions.def. All custom keysets are saved as a whole in config- +extension.cfg. All take effect as soon as one clicks Apply or Ok. + +The affected events are '<>', '<>', +'<>', '<>', '<>', +'<>', '<>', and '<>'. Any +(global) customizations made before 3.6.3 will not affect their keyset- +specific customization after 3.6.3. and vice versa. + +Inital patch by Charles Wohlganger. From b7afebb2523d4bd712f1037b4ed6a0bda7e913b4 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 10 Sep 2017 16:47:33 -0400 Subject: [PATCH 47/47] Don't compute ('') during integer input in entry box. --- Lib/idlelib/configdialog.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 8260da6c990ef1..604719f0453b5c 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1764,6 +1764,7 @@ def create_page_general(self): (*)helplist: ListBox scroll_helplist: Scrollbar """ + # Integer values need StringVar because int('') raises. self.startup_edit = tracers.add( IntVar(self), ('main', 'General', 'editor-on-startup')) self.win_width = tracers.add( @@ -1771,20 +1772,20 @@ def create_page_general(self): self.win_height = tracers.add( StringVar(self), ('main', 'EditorWindow', 'height')) self.autocomplete_wait = tracers.add( - IntVar(self), ('extensions', 'AutoComplete', 'popupwait')) + StringVar(self), ('extensions', 'AutoComplete', 'popupwait')) self.paren_style = tracers.add( StringVar(self), ('extensions', 'ParenMatch', 'style')) self.flash_delay = tracers.add( - IntVar(self), ('extensions', 'ParenMatch', 'flash-delay')) + StringVar(self), ('extensions', 'ParenMatch', 'flash-delay')) self.paren_bell = tracers.add( BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) self.autosave = tracers.add( IntVar(self), ('main', 'General', 'autosave')) self.format_width = tracers.add( - IntVar(self), ('extensions', 'FormatParagraph', 'max-width')) + StringVar(self), ('extensions', 'FormatParagraph', 'max-width')) self.context_lines = tracers.add( - IntVar(self), ('extensions', 'CodeContext', 'numlines')) + StringVar(self), ('extensions', 'CodeContext', 'numlines')) # Create widgets: # Section frames.