bpo-27099: IDLE - Convert built-in extensions to regular features (#2494)
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 '<<force-open-completions>>', '<<expand-word>>', '<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', '<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. 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, revised by Terry Jan Reedy.
This commit is contained in:
parent
d39dbf4cf1
commit
58fc71c447
|
@ -672,23 +672,6 @@ Extensions
|
||||||
|
|
||||||
IDLE contains an extension facility. Preferences for extensions can be
|
IDLE contains an extension facility. Preferences for extensions can be
|
||||||
changed with Configure Extensions. See the beginning of config-extensions.def
|
changed with Configure Extensions. See the beginning of config-extensions.def
|
||||||
in the idlelib directory for further information. The default extensions
|
in the idlelib directory for further information. The only current default
|
||||||
are currently:
|
extension is zoomheight. It exists as an extension primarily to be an example
|
||||||
|
and for testing purposes.
|
||||||
* FormatParagraph
|
|
||||||
|
|
||||||
* AutoExpand
|
|
||||||
|
|
||||||
* ZoomHeight
|
|
||||||
|
|
||||||
* ScriptBinding
|
|
||||||
|
|
||||||
* CallTips
|
|
||||||
|
|
||||||
* ParenMatch
|
|
||||||
|
|
||||||
* AutoComplete
|
|
||||||
|
|
||||||
* CodeContext
|
|
||||||
|
|
||||||
* RstripExtension
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""autocomplete.py - An IDLE extension for automatically completing names.
|
"""Complete either attribute names or file names.
|
||||||
|
|
||||||
This extension can complete either attribute names or file names. It can pop
|
Either on demand or after a user-selected delay after a key character,
|
||||||
a window with all available names, for the user to select from.
|
pop up a list of candidates.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
@ -27,15 +27,6 @@ if os.altsep: # e.g. '/' on Windows...
|
||||||
|
|
||||||
class AutoComplete:
|
class AutoComplete:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('edit', [
|
|
||||||
("Show Completions", "<<force-open-completions>>"),
|
|
||||||
])
|
|
||||||
]
|
|
||||||
|
|
||||||
popupwait = idleConf.GetOption("extensions", "AutoComplete",
|
|
||||||
"popupwait", type="int", default=0)
|
|
||||||
|
|
||||||
def __init__(self, editwin=None):
|
def __init__(self, editwin=None):
|
||||||
self.editwin = editwin
|
self.editwin = editwin
|
||||||
if editwin is not None: # not in subprocess or test
|
if editwin is not None: # not in subprocess or test
|
||||||
|
@ -47,6 +38,11 @@ class AutoComplete:
|
||||||
self._delayed_completion_id = None
|
self._delayed_completion_id = None
|
||||||
self._delayed_completion_index = None
|
self._delayed_completion_index = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reload(cls):
|
||||||
|
cls.popupwait = idleConf.GetOption(
|
||||||
|
"extensions", "AutoComplete", "popupwait", type="int", default=0)
|
||||||
|
|
||||||
def _make_autocomplete_window(self):
|
def _make_autocomplete_window(self):
|
||||||
return autocomplete_w.AutoCompleteWindow(self.text)
|
return autocomplete_w.AutoCompleteWindow(self.text)
|
||||||
|
|
||||||
|
@ -228,6 +224,9 @@ class AutoComplete:
|
||||||
return eval(name, namespace)
|
return eval(name, namespace)
|
||||||
|
|
||||||
|
|
||||||
|
AutoComplete.reload()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from unittest import main
|
from unittest import main
|
||||||
main('idlelib.idle_test.test_autocomplete', verbosity=2)
|
main('idlelib.idle_test.test_autocomplete', verbosity=2)
|
||||||
|
|
|
@ -10,23 +10,13 @@ Changing the current text line or leaving the cursor in a different
|
||||||
place before requesting the next selection causes AutoExpand to reset
|
place before requesting the next selection causes AutoExpand to reset
|
||||||
its state.
|
its state.
|
||||||
|
|
||||||
This is an extension file and there is only one instance of AutoExpand.
|
There is only one instance of Autoexpand.
|
||||||
'''
|
'''
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
|
|
||||||
###$ event <<expand-word>>
|
|
||||||
###$ win <Alt-slash>
|
|
||||||
###$ unix <Alt-slash>
|
|
||||||
|
|
||||||
class AutoExpand:
|
class AutoExpand:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('edit', [
|
|
||||||
('E_xpand Word', '<<expand-word>>'),
|
|
||||||
]),
|
|
||||||
]
|
|
||||||
|
|
||||||
wordchars = string.ascii_letters + string.digits + "_"
|
wordchars = string.ascii_letters + string.digits + "_"
|
||||||
|
|
||||||
def __init__(self, editwin):
|
def __init__(self, editwin):
|
||||||
|
@ -100,6 +90,7 @@ class AutoExpand:
|
||||||
i = i-1
|
i = i-1
|
||||||
return line[i:]
|
return line[i:]
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import unittest
|
import unittest
|
||||||
unittest.main('idlelib.idle_test.test_autoexpand', verbosity=2)
|
unittest.main('idlelib.idle_test.test_autoexpand', verbosity=2)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
"""calltips.py - An IDLE Extension to Jog Your Memory
|
"""Pop up a reminder of how to call a function.
|
||||||
|
|
||||||
Call Tips are floating windows which display function, class, and method
|
Call Tips are floating windows which display function, class, and method
|
||||||
parameter and docstring information when you type an opening parenthesis, and
|
parameter and docstring information when you type an opening parenthesis, and
|
||||||
which disappear when you type a closing parenthesis.
|
which disappear when you type a closing parenthesis.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
|
@ -15,13 +14,8 @@ from idlelib import calltip_w
|
||||||
from idlelib.hyperparser import HyperParser
|
from idlelib.hyperparser import HyperParser
|
||||||
import __main__
|
import __main__
|
||||||
|
|
||||||
class CallTips:
|
|
||||||
|
|
||||||
menudefs = [
|
class CallTips:
|
||||||
('edit', [
|
|
||||||
("Show call tip", "<<force-open-calltip>>"),
|
|
||||||
])
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, editwin=None):
|
def __init__(self, editwin=None):
|
||||||
if editwin is None: # subprocess and test
|
if editwin is None: # subprocess and test
|
||||||
|
@ -103,6 +97,7 @@ class CallTips:
|
||||||
else:
|
else:
|
||||||
return get_argspec(get_entity(expression))
|
return get_argspec(get_entity(expression))
|
||||||
|
|
||||||
|
|
||||||
def get_entity(expression):
|
def get_entity(expression):
|
||||||
"""Return the object corresponding to expression evaluated
|
"""Return the object corresponding to expression evaluated
|
||||||
in a namespace spanning sys.modules and __main.dict__.
|
in a namespace spanning sys.modules and __main.dict__.
|
||||||
|
@ -126,7 +121,6 @@ _default_callable_argspec = "See source or doc"
|
||||||
_invalid_method = "invalid method signature"
|
_invalid_method = "invalid method signature"
|
||||||
_argument_positional = "\n['/' marks preceding arguments as positional-only]\n"
|
_argument_positional = "\n['/' marks preceding arguments as positional-only]\n"
|
||||||
|
|
||||||
|
|
||||||
def get_argspec(ob):
|
def get_argspec(ob):
|
||||||
'''Return a string describing the signature of a callable object, or ''.
|
'''Return a string describing the signature of a callable object, or ''.
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
determine which block you are in. This extension implements a pane at the top
|
||||||
|
@ -25,10 +25,8 @@ FONTUPDATEINTERVAL = 1000 # millisec
|
||||||
getspacesfirstword =\
|
getspacesfirstword =\
|
||||||
lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups()
|
lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups()
|
||||||
|
|
||||||
|
|
||||||
class CodeContext:
|
class CodeContext:
|
||||||
menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])]
|
|
||||||
context_depth = idleConf.GetOption("extensions", "CodeContext",
|
|
||||||
"numlines", type="int", default=3)
|
|
||||||
bgcolor = idleConf.GetOption("extensions", "CodeContext",
|
bgcolor = idleConf.GetOption("extensions", "CodeContext",
|
||||||
"bgcolor", type="str", default="LightGray")
|
"bgcolor", type="str", default="LightGray")
|
||||||
fgcolor = idleConf.GetOption("extensions", "CodeContext",
|
fgcolor = idleConf.GetOption("extensions", "CodeContext",
|
||||||
|
@ -45,15 +43,20 @@ class CodeContext:
|
||||||
# starts the toplevel 'block' of the module.
|
# starts the toplevel 'block' of the module.
|
||||||
self.info = [(0, -1, "", False)]
|
self.info = [(0, -1, "", False)]
|
||||||
self.topvisible = 1
|
self.topvisible = 1
|
||||||
visible = idleConf.GetOption("extensions", "CodeContext",
|
self.reload()
|
||||||
"visible", type="bool", default=False)
|
|
||||||
if visible:
|
|
||||||
self.toggle_code_context_event()
|
|
||||||
self.editwin.setvar('<<toggle-code-context>>', True)
|
|
||||||
# Start two update cycles, one for context lines, one for font changes.
|
# Start two update cycles, one for context lines, one for font changes.
|
||||||
self.text.after(UPDATEINTERVAL, self.timer_event)
|
self.text.after(UPDATEINTERVAL, self.timer_event)
|
||||||
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
|
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reload(cls):
|
||||||
|
cls.context_depth = idleConf.GetOption("extensions", "CodeContext",
|
||||||
|
"numlines", type="int", default=3)
|
||||||
|
cls.bgcolor = idleConf.GetOption("extensions", "CodeContext",
|
||||||
|
"bgcolor", type="str", default="LightGray")
|
||||||
|
cls.fgcolor = idleConf.GetOption("extensions", "CodeContext",
|
||||||
|
"fgcolor", type="str", default="Black")
|
||||||
|
|
||||||
def toggle_code_context_event(self, event=None):
|
def toggle_code_context_event(self, event=None):
|
||||||
if not self.label:
|
if not self.label:
|
||||||
# Calculate the border width and horizontal padding required to
|
# Calculate the border width and horizontal padding required to
|
||||||
|
@ -86,7 +89,7 @@ class CodeContext:
|
||||||
else:
|
else:
|
||||||
self.label.destroy()
|
self.label.destroy()
|
||||||
self.label = None
|
self.label = None
|
||||||
idleConf.SetOption("extensions", "CodeContext", "visible",
|
idleConf.SetOption("main", "Theme", "contexton",
|
||||||
str(self.label is not None))
|
str(self.label is not None))
|
||||||
idleConf.SaveUserCfgFiles()
|
idleConf.SaveUserCfgFiles()
|
||||||
return "break"
|
return "break"
|
||||||
|
@ -177,3 +180,6 @@ class CodeContext:
|
||||||
self.textfont = newtextfont
|
self.textfont = newtextfont
|
||||||
self.label["font"] = self.textfont
|
self.label["font"] = self.textfont
|
||||||
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
|
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
|
||||||
|
|
||||||
|
|
||||||
|
CodeContext.reload()
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
# config-extensions.def
|
# 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
|
||||||
|
|
||||||
|
[ParenMatch]
|
||||||
|
style= expression
|
||||||
|
flash-delay= 500
|
||||||
|
bell= True
|
||||||
|
|
||||||
# IDLE reads several config files to determine user preferences. This
|
# IDLE reads several config files to determine user preferences. This
|
||||||
# file is the default configuration file for IDLE extensions settings.
|
# file is the default configuration file for IDLE extensions settings.
|
||||||
#
|
#
|
||||||
|
@ -19,7 +39,7 @@
|
||||||
# extension that may be sensibly re-configured.
|
# extension that may be sensibly re-configured.
|
||||||
#
|
#
|
||||||
# If there are no keybindings for a menus' virtual events, include lines
|
# If there are no keybindings for a menus' virtual events, include lines
|
||||||
# like <<toggle-code-context>>= (See [CodeContext], below.)
|
# like <<toggle-code-context>>=.
|
||||||
#
|
#
|
||||||
# Currently it is necessary to manually modify this file to change
|
# Currently it is necessary to manually modify this file to change
|
||||||
# extension key bindings and default values. To customize, create
|
# extension key bindings and default values. To customize, create
|
||||||
|
@ -32,68 +52,14 @@
|
||||||
# See config-keys.def for notes on specifying keys and extend.txt for
|
# See config-keys.def for notes on specifying keys and extend.txt for
|
||||||
# information on creating IDLE extensions.
|
# information on creating IDLE extensions.
|
||||||
|
|
||||||
[AutoComplete]
|
# A fake extension for testing and example purposes. When enabled and
|
||||||
enable=True
|
# invoked, inserts or deletes z-text at beginning of every line.
|
||||||
popupwait=2000
|
[ZzDummy]
|
||||||
[AutoComplete_cfgBindings]
|
enable= True
|
||||||
force-open-completions=<Control-Key-space>
|
enable_shell = False
|
||||||
[AutoComplete_bindings]
|
enable_editor = True
|
||||||
autocomplete=<Key-Tab>
|
z-text= Z
|
||||||
try-open-completions=<KeyRelease-period> <KeyRelease-slash> <KeyRelease-backslash>
|
[ZzDummy_cfgBindings]
|
||||||
|
z-in= <Control-Shift-KeyRelease-Insert>
|
||||||
[AutoExpand]
|
[ZzDummy_bindings]
|
||||||
enable=True
|
z-out= <Control-Shift-KeyRelease-Delete>
|
||||||
[AutoExpand_cfgBindings]
|
|
||||||
expand-word=<Alt-Key-slash>
|
|
||||||
|
|
||||||
[CallTips]
|
|
||||||
enable=True
|
|
||||||
[CallTips_cfgBindings]
|
|
||||||
force-open-calltip=<Control-Key-backslash>
|
|
||||||
[CallTips_bindings]
|
|
||||||
try-open-calltip=<KeyRelease-parenleft>
|
|
||||||
refresh-calltip=<KeyRelease-parenright> <KeyRelease-0>
|
|
||||||
|
|
||||||
[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=<Alt-Key-q>
|
|
||||||
|
|
||||||
[ParenMatch]
|
|
||||||
enable=True
|
|
||||||
style= expression
|
|
||||||
flash-delay= 500
|
|
||||||
bell=True
|
|
||||||
[ParenMatch_cfgBindings]
|
|
||||||
flash-paren=<Control-Key-0>
|
|
||||||
[ParenMatch_bindings]
|
|
||||||
paren-closed=<KeyRelease-parenright> <KeyRelease-bracketright> <KeyRelease-braceright>
|
|
||||||
|
|
||||||
[RstripExtension]
|
|
||||||
enable=True
|
|
||||||
enable_shell=False
|
|
||||||
enable_editor=True
|
|
||||||
|
|
||||||
[ScriptBinding]
|
|
||||||
enable=True
|
|
||||||
enable_shell=False
|
|
||||||
enable_editor=True
|
|
||||||
[ScriptBinding_cfgBindings]
|
|
||||||
run-module=<Key-F5>
|
|
||||||
check-module=<Alt-Key-x>
|
|
||||||
|
|
||||||
[ZoomHeight]
|
|
||||||
enable=True
|
|
||||||
[ZoomHeight_cfgBindings]
|
|
||||||
zoom-height=<Alt-Key-2>
|
|
||||||
|
|
|
@ -57,6 +57,14 @@ toggle-tabs=<Alt-Key-t> <Meta-Key-t> <Alt-Key-T> <Meta-Key-T>
|
||||||
change-indentwidth=<Alt-Key-u> <Meta-Key-u> <Alt-Key-U> <Meta-Key-U>
|
change-indentwidth=<Alt-Key-u> <Meta-Key-u> <Alt-Key-U> <Meta-Key-U>
|
||||||
del-word-left=<Control-Key-BackSpace>
|
del-word-left=<Control-Key-BackSpace>
|
||||||
del-word-right=<Control-Key-Delete>
|
del-word-right=<Control-Key-Delete>
|
||||||
|
force-open-completions= <Control-Key-space>
|
||||||
|
expand-word= <Alt-Key-slash>
|
||||||
|
force-open-calltip= <Control-Key-backslash>
|
||||||
|
format-paragraph= <Alt-Key-q>
|
||||||
|
flash-paren= <Control-Key-0>
|
||||||
|
run-module= <Key-F5>
|
||||||
|
check-module= <Alt-Key-x>
|
||||||
|
zoom-height= <Alt-Key-2>
|
||||||
|
|
||||||
[IDLE Classic Unix]
|
[IDLE Classic Unix]
|
||||||
copy=<Alt-Key-w> <Meta-Key-w>
|
copy=<Alt-Key-w> <Meta-Key-w>
|
||||||
|
@ -108,6 +116,14 @@ toggle-tabs=<Alt-Key-t>
|
||||||
change-indentwidth=<Alt-Key-u>
|
change-indentwidth=<Alt-Key-u>
|
||||||
del-word-left=<Alt-Key-BackSpace>
|
del-word-left=<Alt-Key-BackSpace>
|
||||||
del-word-right=<Alt-Key-d>
|
del-word-right=<Alt-Key-d>
|
||||||
|
force-open-completions= <Control-Key-space>
|
||||||
|
expand-word= <Alt-Key-slash>
|
||||||
|
force-open-calltip= <Control-Key-backslash>
|
||||||
|
format-paragraph= <Alt-Key-q>
|
||||||
|
flash-paren= <Control-Key-0>
|
||||||
|
run-module= <Key-F5>
|
||||||
|
check-module= <Alt-Key-x>
|
||||||
|
zoom-height= <Alt-Key-2>
|
||||||
|
|
||||||
[IDLE Modern Unix]
|
[IDLE Modern Unix]
|
||||||
copy = <Control-Shift-Key-C> <Control-Key-Insert>
|
copy = <Control-Shift-Key-C> <Control-Key-Insert>
|
||||||
|
@ -159,6 +175,14 @@ toggle-tabs = <Control-Key-T>
|
||||||
change-indentwidth = <Alt-Key-u>
|
change-indentwidth = <Alt-Key-u>
|
||||||
del-word-left = <Control-Key-BackSpace>
|
del-word-left = <Control-Key-BackSpace>
|
||||||
del-word-right = <Control-Key-Delete>
|
del-word-right = <Control-Key-Delete>
|
||||||
|
force-open-completions= <Control-Key-space>
|
||||||
|
expand-word= <Alt-Key-slash>
|
||||||
|
force-open-calltip= <Control-Key-backslash>
|
||||||
|
format-paragraph= <Alt-Key-q>
|
||||||
|
flash-paren= <Control-Key-0>
|
||||||
|
run-module= <Key-F5>
|
||||||
|
check-module= <Alt-Key-x>
|
||||||
|
zoom-height= <Alt-Key-2>
|
||||||
|
|
||||||
[IDLE Classic Mac]
|
[IDLE Classic Mac]
|
||||||
copy=<Command-Key-c>
|
copy=<Command-Key-c>
|
||||||
|
@ -210,6 +234,14 @@ toggle-tabs=<Control-Key-t>
|
||||||
change-indentwidth=<Control-Key-u>
|
change-indentwidth=<Control-Key-u>
|
||||||
del-word-left=<Control-Key-BackSpace>
|
del-word-left=<Control-Key-BackSpace>
|
||||||
del-word-right=<Control-Key-Delete>
|
del-word-right=<Control-Key-Delete>
|
||||||
|
force-open-completions= <Control-Key-space>
|
||||||
|
expand-word= <Option-Key-slash>
|
||||||
|
force-open-calltip= <Control-Key-backslash>
|
||||||
|
format-paragraph= <Option-Key-q>
|
||||||
|
flash-paren= <Control-Key-0>
|
||||||
|
run-module= <Key-F5>
|
||||||
|
check-module= <Option-Key-x>
|
||||||
|
zoom-height= <Option-Key-0>
|
||||||
|
|
||||||
[IDLE Classic OSX]
|
[IDLE Classic OSX]
|
||||||
toggle-tabs = <Control-Key-t>
|
toggle-tabs = <Control-Key-t>
|
||||||
|
@ -262,4 +294,11 @@ python-context-help = <Shift-Key-F1>
|
||||||
save-copy-of-window-as-file = <Option-Command-Key-s>
|
save-copy-of-window-as-file = <Option-Command-Key-s>
|
||||||
open-window-from-file = <Command-Key-o>
|
open-window-from-file = <Command-Key-o>
|
||||||
python-docs = <Key-F1>
|
python-docs = <Key-F1>
|
||||||
|
force-open-completions= <Control-Key-space>
|
||||||
|
expand-word= <Option-Key-slash>
|
||||||
|
force-open-calltip= <Control-Key-backslash>
|
||||||
|
format-paragraph= <Option-Key-q>
|
||||||
|
flash-paren= <Control-Key-0>
|
||||||
|
run-module= <Key-F5>
|
||||||
|
check-module= <Option-Key-x>
|
||||||
|
zoom-height= <Option-Key-0>
|
||||||
|
|
|
@ -359,7 +359,8 @@ class IdleConf:
|
||||||
'stderr-foreground':'#000000',
|
'stderr-foreground':'#000000',
|
||||||
'stderr-background':'#ffffff',
|
'stderr-background':'#ffffff',
|
||||||
'console-foreground':'#000000',
|
'console-foreground':'#000000',
|
||||||
'console-background':'#ffffff' }
|
'console-background':'#ffffff',
|
||||||
|
}
|
||||||
for element in theme:
|
for element in theme:
|
||||||
if not cfgParser.has_option(themeName, element):
|
if not cfgParser.has_option(themeName, element):
|
||||||
# Print warning that will return a default color
|
# Print warning that will return a default color
|
||||||
|
@ -443,6 +444,11 @@ class IdleConf:
|
||||||
for extn in userExtns:
|
for extn in userExtns:
|
||||||
if extn not in extns: #user has added own extension
|
if extn not in extns: #user has added own extension
|
||||||
extns.append(extn)
|
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:
|
if active_only:
|
||||||
activeExtns = []
|
activeExtns = []
|
||||||
for extn in extns:
|
for extn in extns:
|
||||||
|
@ -594,7 +600,12 @@ class IdleConf:
|
||||||
return ('<<'+virtualEvent+'>>') in self.GetCoreKeys()
|
return ('<<'+virtualEvent+'>>') in self.GetCoreKeys()
|
||||||
|
|
||||||
# TODO make keyBindins a file or class attribute used for test above
|
# 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.
|
||||||
|
'<<force-open-completions>>', '<<expand-word>>',
|
||||||
|
'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>',
|
||||||
|
'<<run-module>>', '<<check-module>>', '<<zoom-height>>'}
|
||||||
|
|
||||||
def GetCoreKeys(self, keySetName=None):
|
def GetCoreKeys(self, keySetName=None):
|
||||||
"""Return dict of core virtual-key keybindings for keySetName.
|
"""Return dict of core virtual-key keybindings for keySetName.
|
||||||
|
@ -654,8 +665,17 @@ class IdleConf:
|
||||||
'<<toggle-tabs>>': ['<Alt-Key-t>'],
|
'<<toggle-tabs>>': ['<Alt-Key-t>'],
|
||||||
'<<change-indentwidth>>': ['<Alt-Key-u>'],
|
'<<change-indentwidth>>': ['<Alt-Key-u>'],
|
||||||
'<<del-word-left>>': ['<Control-Key-BackSpace>'],
|
'<<del-word-left>>': ['<Control-Key-BackSpace>'],
|
||||||
'<<del-word-right>>': ['<Control-Key-Delete>']
|
'<<del-word-right>>': ['<Control-Key-Delete>'],
|
||||||
|
'<<force-open-completions>>': ['<Control-Key-space>'],
|
||||||
|
'<<expand-word>>': ['<Alt-Key-slash>'],
|
||||||
|
'<<force-open-calltip>>': ['<Control-Key-backslash>'],
|
||||||
|
'<<flash-paren>>': ['<Control-Key-0>'],
|
||||||
|
'<<format-paragraph>>': ['<Alt-Key-q>'],
|
||||||
|
'<<run-module>>': ['<Key-F5>'],
|
||||||
|
'<<check-module>>': ['<Alt-Key-x>'],
|
||||||
|
'<<zoom-height>>': ['<Alt-Key-2>'],
|
||||||
}
|
}
|
||||||
|
|
||||||
if keySetName:
|
if keySetName:
|
||||||
if not (self.userCfg['keys'].has_section(keySetName) or
|
if not (self.userCfg['keys'].has_section(keySetName) or
|
||||||
self.defaultCfg['keys'].has_section(keySetName)):
|
self.defaultCfg['keys'].has_section(keySetName)):
|
||||||
|
@ -670,7 +690,8 @@ class IdleConf:
|
||||||
binding = self.GetKeyBinding(keySetName, event)
|
binding = self.GetKeyBinding(keySetName, event)
|
||||||
if binding:
|
if binding:
|
||||||
keyBindings[event] = binding
|
keyBindings[event] = binding
|
||||||
else: #we are going to return a default, print warning
|
# Otherwise return default in keyBindings.
|
||||||
|
elif event not in self.former_extension_events:
|
||||||
warning = (
|
warning = (
|
||||||
'\n Warning: config.py - IdleConf.GetCoreKeys -\n'
|
'\n Warning: config.py - IdleConf.GetCoreKeys -\n'
|
||||||
' problem retrieving key binding for event %r\n'
|
' problem retrieving key binding for event %r\n'
|
||||||
|
|
|
@ -15,7 +15,7 @@ from tkinter import (Toplevel, Listbox, Text, Scale, Canvas,
|
||||||
NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
|
NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
|
||||||
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
|
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
|
||||||
from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame,
|
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.colorchooser as tkColorChooser
|
||||||
import tkinter.font as tkFont
|
import tkinter.font as tkFont
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
|
@ -198,7 +198,6 @@ class ConfigDialog(Toplevel):
|
||||||
|
|
||||||
def deactivate_current_config(self):
|
def deactivate_current_config(self):
|
||||||
"""Remove current key bindings.
|
"""Remove current key bindings.
|
||||||
|
|
||||||
Iterate over window instances defined in parent and remove
|
Iterate over window instances defined in parent and remove
|
||||||
the keybindings.
|
the keybindings.
|
||||||
"""
|
"""
|
||||||
|
@ -288,6 +287,7 @@ class ConfigDialog(Toplevel):
|
||||||
"Fill self.extensions with data from the default and user configs."
|
"Fill self.extensions with data from the default and user configs."
|
||||||
self.extensions = {}
|
self.extensions = {}
|
||||||
for ext_name in idleConf.GetExtensions(active_only=False):
|
for ext_name in idleConf.GetExtensions(active_only=False):
|
||||||
|
# Former built-in extensions are already filtered out.
|
||||||
self.extensions[ext_name] = []
|
self.extensions[ext_name] = []
|
||||||
|
|
||||||
for ext_name in self.extensions:
|
for ext_name in self.extensions:
|
||||||
|
@ -796,7 +796,8 @@ class HighPage(Frame):
|
||||||
takefocus=FALSE, highlightthickness=0, wrap=NONE)
|
takefocus=FALSE, highlightthickness=0, wrap=NONE)
|
||||||
text.bind('<Double-Button-1>', lambda e: 'break')
|
text.bind('<Double-Button-1>', lambda e: 'break')
|
||||||
text.bind('<B1-Motion>', lambda e: 'break')
|
text.bind('<B1-Motion>', lambda e: 'break')
|
||||||
text_and_tags=(('\n', 'normal'),
|
text_and_tags=(
|
||||||
|
('\n', 'normal'),
|
||||||
('#you can click here', 'comment'), ('\n', 'normal'),
|
('#you can click here', 'comment'), ('\n', 'normal'),
|
||||||
('#to choose items', 'comment'), ('\n', 'normal'),
|
('#to choose items', 'comment'), ('\n', 'normal'),
|
||||||
('def', 'keyword'), (' ', 'normal'),
|
('def', 'keyword'), (' ', 'normal'),
|
||||||
|
@ -858,11 +859,10 @@ class HighPage(Frame):
|
||||||
frame_theme, text='Delete Custom Theme',
|
frame_theme, text='Delete Custom Theme',
|
||||||
command=self.delete_custom)
|
command=self.delete_custom)
|
||||||
self.theme_message = Label(frame_theme, borderwidth=2)
|
self.theme_message = Label(frame_theme, borderwidth=2)
|
||||||
|
|
||||||
# Pack widgets:
|
# Pack widgets:
|
||||||
# body.
|
# body.
|
||||||
frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
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_custom.
|
# frame_custom.
|
||||||
self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
|
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)
|
frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0)
|
||||||
|
@ -1764,15 +1764,30 @@ class GenPage(Frame):
|
||||||
(*)helplist: ListBox
|
(*)helplist: ListBox
|
||||||
scroll_helplist: Scrollbar
|
scroll_helplist: Scrollbar
|
||||||
"""
|
"""
|
||||||
|
# Integer values need StringVar because int('') raises.
|
||||||
self.startup_edit = tracers.add(
|
self.startup_edit = tracers.add(
|
||||||
IntVar(self), ('main', 'General', 'editor-on-startup'))
|
IntVar(self), ('main', 'General', 'editor-on-startup'))
|
||||||
self.autosave = tracers.add(
|
|
||||||
IntVar(self), ('main', 'General', 'autosave'))
|
|
||||||
self.win_width = tracers.add(
|
self.win_width = tracers.add(
|
||||||
StringVar(self), ('main', 'EditorWindow', 'width'))
|
StringVar(self), ('main', 'EditorWindow', 'width'))
|
||||||
self.win_height = tracers.add(
|
self.win_height = tracers.add(
|
||||||
StringVar(self), ('main', 'EditorWindow', 'height'))
|
StringVar(self), ('main', 'EditorWindow', 'height'))
|
||||||
|
self.autocomplete_wait = tracers.add(
|
||||||
|
StringVar(self), ('extensions', 'AutoComplete', 'popupwait'))
|
||||||
|
self.paren_style = tracers.add(
|
||||||
|
StringVar(self), ('extensions', 'ParenMatch', 'style'))
|
||||||
|
self.flash_delay = tracers.add(
|
||||||
|
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(
|
||||||
|
StringVar(self), ('extensions', 'FormatParagraph', 'max-width'))
|
||||||
|
self.context_lines = tracers.add(
|
||||||
|
StringVar(self), ('extensions', 'CodeContext', 'numlines'))
|
||||||
|
|
||||||
|
# Create widgets:
|
||||||
# Section frames.
|
# Section frames.
|
||||||
frame_window = LabelFrame(self, borderwidth=2, relief=GROOVE,
|
frame_window = LabelFrame(self, borderwidth=2, relief=GROOVE,
|
||||||
text=' Window Preferences')
|
text=' Window Preferences')
|
||||||
|
@ -1790,7 +1805,7 @@ class GenPage(Frame):
|
||||||
frame_run, variable=self.startup_edit, value=0,
|
frame_run, variable=self.startup_edit, value=0,
|
||||||
text='Open Shell Window')
|
text='Open Shell Window')
|
||||||
|
|
||||||
frame_win_size = Frame(frame_window, borderwidth=0,)
|
frame_win_size = Frame(frame_window, borderwidth=0)
|
||||||
win_size_title = Label(
|
win_size_title = Label(
|
||||||
frame_win_size, text='Initial Window Size (in characters)')
|
frame_win_size, text='Initial Window Size (in characters)')
|
||||||
win_width_title = Label(frame_win_size, text='Width')
|
win_width_title = Label(frame_win_size, text='Width')
|
||||||
|
@ -1800,6 +1815,26 @@ class GenPage(Frame):
|
||||||
self.win_height_int = Entry(
|
self.win_height_int = Entry(
|
||||||
frame_win_size, textvariable=self.win_height, width=3)
|
frame_win_size, textvariable=self.win_height, 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_editor.
|
||||||
frame_save = Frame(frame_editor, borderwidth=0)
|
frame_save = Frame(frame_editor, borderwidth=0)
|
||||||
run_save_title = Label(frame_save, text='At Start of Run (F5) ')
|
run_save_title = Label(frame_save, text='At Start of Run (F5) ')
|
||||||
|
@ -1810,6 +1845,18 @@ class GenPage(Frame):
|
||||||
frame_save, variable=self.autosave, value=1,
|
frame_save, variable=self.autosave, value=1,
|
||||||
text='No Prompt')
|
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_help.
|
||||||
frame_helplist = Frame(frame_help)
|
frame_helplist = Frame(frame_help)
|
||||||
frame_helplist_buttons = Frame(frame_helplist)
|
frame_helplist_buttons = Frame(frame_helplist)
|
||||||
|
@ -1847,11 +1894,33 @@ class GenPage(Frame):
|
||||||
win_height_title.pack(side=RIGHT, anchor=E, pady=5)
|
win_height_title.pack(side=RIGHT, anchor=E, pady=5)
|
||||||
self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, 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)
|
win_width_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.
|
||||||
frame_save.pack(side=TOP, padx=5, pady=0, fill=X)
|
frame_save.pack(side=TOP, padx=5, pady=0, fill=X)
|
||||||
run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
|
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_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
|
||||||
self.save_ask_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_help.
|
||||||
frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
|
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)
|
frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
||||||
|
@ -1863,17 +1932,30 @@ class GenPage(Frame):
|
||||||
|
|
||||||
def load_general_cfg(self):
|
def load_general_cfg(self):
|
||||||
"Load current configuration settings for the general options."
|
"Load current configuration settings for the general options."
|
||||||
# Set startup state.
|
# Set variables for all windows.
|
||||||
self.startup_edit.set(idleConf.GetOption(
|
self.startup_edit.set(idleConf.GetOption(
|
||||||
'main', 'General', 'editor-on-startup', default=0, type='bool'))
|
'main', 'General', 'editor-on-startup', type='bool'))
|
||||||
# Set autosave state.
|
|
||||||
self.autosave.set(idleConf.GetOption(
|
|
||||||
'main', 'General', 'autosave', default=0, type='bool'))
|
|
||||||
# Set initial window size.
|
|
||||||
self.win_width.set(idleConf.GetOption(
|
self.win_width.set(idleConf.GetOption(
|
||||||
'main', 'EditorWindow', 'width', type='int'))
|
'main', 'EditorWindow', 'width', type='int'))
|
||||||
self.win_height.set(idleConf.GetOption(
|
self.win_height.set(idleConf.GetOption(
|
||||||
'main', 'EditorWindow', 'height', type='int'))
|
'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.
|
# Set additional help sources.
|
||||||
self.user_helplist = idleConf.GetAllExtraHelpSourcesList()
|
self.user_helplist = idleConf.GetAllExtraHelpSourcesList()
|
||||||
self.helplist.delete(0, 'end')
|
self.helplist.delete(0, 'end')
|
||||||
|
@ -2034,10 +2116,10 @@ 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
|
be used with older IDLE releases if it is saved as a custom
|
||||||
key set, with a different name.
|
key set, with a different name.
|
||||||
''',
|
''',
|
||||||
'Extensions': '''
|
'General': '''
|
||||||
Extensions:
|
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
|
cursor movement, before popping up completion box. Key char is '.' after
|
||||||
identifier or a '/' (or '\\' on Windows) within a string.
|
identifier or a '/' (or '\\' on Windows) within a string.
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ from idlelib import windows
|
||||||
TK_TABWIDTH_DEFAULT = 8
|
TK_TABWIDTH_DEFAULT = 8
|
||||||
_py_version = ' (%s)' % platform.python_version()
|
_py_version = ' (%s)' % platform.python_version()
|
||||||
|
|
||||||
|
|
||||||
def _sphinx_version():
|
def _sphinx_version():
|
||||||
"Format sys.version_info to produce the Sphinx version string used to install the chm docs"
|
"Format sys.version_info to produce the Sphinx version string used to install the chm docs"
|
||||||
major, minor, micro, level, serial = sys.version_info
|
major, minor, micro, level, serial = sys.version_info
|
||||||
|
@ -52,11 +51,22 @@ class EditorWindow(object):
|
||||||
from idlelib import mainmenu
|
from idlelib import mainmenu
|
||||||
from tkinter import Toplevel
|
from tkinter import Toplevel
|
||||||
from idlelib.statusbar import MultiStatusBar
|
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.zoomheight import ZoomHeight
|
||||||
|
|
||||||
filesystemencoding = sys.getfilesystemencoding() # for file names
|
filesystemencoding = sys.getfilesystemencoding() # for file names
|
||||||
help_url = None
|
help_url = None
|
||||||
|
|
||||||
def __init__(self, flist=None, filename=None, key=None, root=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:
|
if EditorWindow.help_url is None:
|
||||||
dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html')
|
dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html')
|
||||||
if sys.platform.count('linux'):
|
if sys.platform.count('linux'):
|
||||||
|
@ -84,7 +94,8 @@ class EditorWindow(object):
|
||||||
# Safari requires real file:-URLs
|
# Safari requires real file:-URLs
|
||||||
EditorWindow.help_url = 'file://' + EditorWindow.help_url
|
EditorWindow.help_url = 'file://' + EditorWindow.help_url
|
||||||
else:
|
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
|
self.flist = flist
|
||||||
root = root or flist.root
|
root = root or flist.root
|
||||||
self.root = root
|
self.root = root
|
||||||
|
@ -270,6 +281,43 @@ class EditorWindow(object):
|
||||||
self.askinteger = tkSimpleDialog.askinteger
|
self.askinteger = tkSimpleDialog.askinteger
|
||||||
self.showerror = tkMessageBox.showerror
|
self.showerror = tkMessageBox.showerror
|
||||||
|
|
||||||
|
# Add pseudoevents for former extension fixed keys.
|
||||||
|
# (This probably needs to be done once in the process.)
|
||||||
|
text.event_add('<<autocomplete>>', '<Key-Tab>')
|
||||||
|
text.event_add('<<try-open-completions>>', '<KeyRelease-period>',
|
||||||
|
'<KeyRelease-slash>', '<KeyRelease-backslash>')
|
||||||
|
text.event_add('<<try-open-calltip>>', '<KeyRelease-parenleft>')
|
||||||
|
text.event_add('<<refresh-calltip>>', '<KeyRelease-parenright>')
|
||||||
|
text.event_add('<<paren-closed>>', '<KeyRelease-parenright>',
|
||||||
|
'<KeyRelease-bracketright>', '<KeyRelease-braceright>')
|
||||||
|
|
||||||
|
# Former extension bindings depends on frame.text being packed
|
||||||
|
# (called from self.ResetColorizer()).
|
||||||
|
autocomplete = self.AutoComplete(self)
|
||||||
|
text.bind("<<autocomplete>>", autocomplete.autocomplete_event)
|
||||||
|
text.bind("<<try-open-completions>>",
|
||||||
|
autocomplete.try_open_completions_event)
|
||||||
|
text.bind("<<force-open-completions>>",
|
||||||
|
autocomplete.force_open_completions_event)
|
||||||
|
text.bind("<<expand-word>>", self.AutoExpand(self).expand_word_event)
|
||||||
|
text.bind("<<format-paragraph>>",
|
||||||
|
self.FormatParagraph(self).format_paragraph_event)
|
||||||
|
parenmatch = self.ParenMatch(self)
|
||||||
|
text.bind("<<flash-paren>>", parenmatch.flash_paren_event)
|
||||||
|
text.bind("<<paren-closed>>", parenmatch.paren_closed_event)
|
||||||
|
scriptbinding = ScriptBinding(self)
|
||||||
|
text.bind("<<check-module>>", scriptbinding.check_module_event)
|
||||||
|
text.bind("<<run-module>>", scriptbinding.run_module_event)
|
||||||
|
text.bind("<<do-rstrip>>", self.RstripExtension(self).do_rstrip)
|
||||||
|
calltips = self.CallTips(self)
|
||||||
|
text.bind("<<try-open-calltip>>", calltips.try_open_calltip_event)
|
||||||
|
#refresh-calltips must come after paren-closed to work right
|
||||||
|
text.bind("<<refresh-calltip>>", calltips.refresh_calltip_event)
|
||||||
|
text.bind("<<force-open-calltip>>", calltips.force_open_calltip_event)
|
||||||
|
text.bind("<<zoom-height>>", self.ZoomHeight(self).zoom_height_event)
|
||||||
|
text.bind("<<toggle-code-context>>",
|
||||||
|
self.CodeContext(self).toggle_code_context_event)
|
||||||
|
|
||||||
def _filename_to_unicode(self, filename):
|
def _filename_to_unicode(self, filename):
|
||||||
"""Return filename as BMP unicode so diplayable in Tk."""
|
"""Return filename as BMP unicode so diplayable in Tk."""
|
||||||
# Decode bytes to unicode.
|
# Decode bytes to unicode.
|
||||||
|
@ -981,16 +1029,8 @@ class EditorWindow(object):
|
||||||
def get_standard_extension_names(self):
|
def get_standard_extension_names(self):
|
||||||
return idleConf.GetExtensions(editor_only=True)
|
return idleConf.GetExtensions(editor_only=True)
|
||||||
|
|
||||||
extfiles = { # map config-extension section names to new file names
|
extfiles = { # Map built-in config-extension section names to file names.
|
||||||
'AutoComplete': 'autocomplete',
|
'ZzDummy': 'zzdummy',
|
||||||
'AutoExpand': 'autoexpand',
|
|
||||||
'CallTips': 'calltips',
|
|
||||||
'CodeContext': 'codecontext',
|
|
||||||
'FormatParagraph': 'paragraph',
|
|
||||||
'ParenMatch': 'parenmatch',
|
|
||||||
'RstripExtension': 'rstrip',
|
|
||||||
'ScriptBinding': 'runscript',
|
|
||||||
'ZoomHeight': 'zoomheight',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def load_extension(self, name):
|
def load_extension(self, name):
|
||||||
|
|
|
@ -437,78 +437,57 @@ class IdleConfTest(unittest.TestCase):
|
||||||
|
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
eq(conf.GetExtensions(),
|
eq(conf.GetExtensions(),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy'])
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding',
|
|
||||||
'ZoomHeight'])
|
|
||||||
eq(conf.GetExtensions(active_only=False),
|
eq(conf.GetExtensions(active_only=False),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy', 'DISABLE'])
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding',
|
|
||||||
'ZoomHeight', 'DISABLE'])
|
|
||||||
eq(conf.GetExtensions(editor_only=True),
|
eq(conf.GetExtensions(editor_only=True),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy'])
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding',
|
|
||||||
'ZoomHeight'])
|
|
||||||
eq(conf.GetExtensions(shell_only=True),
|
eq(conf.GetExtensions(shell_only=True),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'FormatParagraph',
|
[])
|
||||||
'ParenMatch', 'ZoomHeight'])
|
|
||||||
eq(conf.GetExtensions(active_only=False, editor_only=True),
|
eq(conf.GetExtensions(active_only=False, editor_only=True),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy', 'DISABLE'])
|
||||||
'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'])
|
|
||||||
|
|
||||||
# Add user extensions
|
# Add user extensions
|
||||||
conf.SetOption('extensions', 'Foobar', 'enable', 'True')
|
conf.SetOption('extensions', 'Foobar', 'enable', 'True')
|
||||||
eq(conf.GetExtensions(),
|
eq(conf.GetExtensions(),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy', 'Foobar']) # User extensions didn't sort
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension',
|
|
||||||
'ScriptBinding', 'ZoomHeight', 'Foobar']) # User extensions didn't sort
|
|
||||||
eq(conf.GetExtensions(active_only=False),
|
eq(conf.GetExtensions(active_only=False),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['ZzDummy', 'DISABLE', 'Foobar'])
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension',
|
|
||||||
'ScriptBinding', 'ZoomHeight', 'DISABLE', 'Foobar'])
|
|
||||||
|
|
||||||
def test_remove_key_bind_names(self):
|
def test_remove_key_bind_names(self):
|
||||||
conf = self.mock_config()
|
conf = self.mock_config()
|
||||||
|
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
conf.RemoveKeyBindNames(conf.GetSectionList('default', 'extensions')),
|
conf.RemoveKeyBindNames(conf.GetSectionList('default', 'extensions')),
|
||||||
['AutoComplete', 'AutoExpand', 'CallTips', 'CodeContext',
|
['AutoComplete', 'CodeContext', 'FormatParagraph', 'ParenMatch','ZzDummy'])
|
||||||
'FormatParagraph', 'ParenMatch', 'RstripExtension', 'ScriptBinding',
|
|
||||||
'ZoomHeight'])
|
|
||||||
|
|
||||||
def test_get_extn_name_for_event(self):
|
def test_get_extn_name_for_event(self):
|
||||||
conf = self.mock_config()
|
conf = self.mock_config()
|
||||||
|
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
eq(conf.GetExtnNameForEvent('force-open-completions'), 'AutoComplete')
|
eq(conf.GetExtnNameForEvent('z-in'), 'ZzDummy')
|
||||||
eq(conf.GetExtnNameForEvent('expand-word'), 'AutoExpand')
|
eq(conf.GetExtnNameForEvent('z-out'), None)
|
||||||
eq(conf.GetExtnNameForEvent('force-open-calltip'), 'CallTips')
|
|
||||||
eq(conf.GetExtnNameForEvent('zoom-height'), 'ZoomHeight')
|
|
||||||
|
|
||||||
def test_get_extension_keys(self):
|
def test_get_extension_keys(self):
|
||||||
conf = self.mock_config()
|
conf = self.mock_config()
|
||||||
|
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
eq(conf.GetExtensionKeys('AutoComplete'),
|
eq(conf.GetExtensionKeys('ZzDummy'),
|
||||||
{'<<force-open-completions>>': ['<Control-Key-space>']})
|
{'<<z-in>>': ['<Control-Shift-KeyRelease-Insert>']})
|
||||||
eq(conf.GetExtensionKeys('ParenMatch'),
|
# need option key test
|
||||||
{'<<flash-paren>>': ['<Control-Key-0>']})
|
## key = ['<Option-Key-2>'] if sys.platform == 'darwin' else ['<Alt-Key-2>']
|
||||||
|
## eq(conf.GetExtensionKeys('ZoomHeight'), {'<<zoom-height>>': key})
|
||||||
key = ['<Option-Key-2>'] if sys.platform == 'darwin' else ['<Alt-Key-2>']
|
|
||||||
eq(conf.GetExtensionKeys('ZoomHeight'), {'<<zoom-height>>': key})
|
|
||||||
|
|
||||||
def test_get_extension_bindings(self):
|
def test_get_extension_bindings(self):
|
||||||
conf = self.mock_config()
|
conf = self.mock_config()
|
||||||
|
|
||||||
self.assertEqual(conf.GetExtensionBindings('NotExists'), {})
|
self.assertEqual(conf.GetExtensionBindings('NotExists'), {})
|
||||||
|
|
||||||
key = ['<Option-Key-2>'] if sys.platform == 'darwin' else ['<Alt-Key-2>']
|
#key = ['<Option-Key-2>'] if sys.platform == 'darwin' else ['<Alt-Key-2>']
|
||||||
|
expect = {'<<z-in>>': ['<Control-Shift-KeyRelease-Insert>'],
|
||||||
|
'<<z-out>>': ['<Control-Shift-KeyRelease-Delete>']}
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
conf.GetExtensionBindings('ZoomHeight'), {'<<zoom-height>>': key})
|
conf.GetExtensionBindings('ZzDummy'), expect)
|
||||||
|
|
||||||
# Add non-configuarable bindings
|
# Add non-configuarable bindings
|
||||||
conf.defaultCfg['extensions'].add_section('Foobar')
|
conf.defaultCfg['extensions'].add_section('Foobar')
|
||||||
|
@ -542,9 +521,11 @@ class IdleConfTest(unittest.TestCase):
|
||||||
sys.platform = 'some-linux'
|
sys.platform = 'some-linux'
|
||||||
self.assertEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
|
self.assertEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
|
||||||
|
|
||||||
# This should not be the same, sicne replace <Alt- to <Option-
|
# This should not be the same, since replace <Alt- to <Option-.
|
||||||
sys.platform = 'darwin'
|
# Above depended on config-extensions.def having Alt keys,
|
||||||
self.assertNotEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
|
# which is no longer true.
|
||||||
|
# sys.platform = 'darwin'
|
||||||
|
# self.assertNotEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
|
||||||
|
|
||||||
# Restore platform
|
# Restore platform
|
||||||
sys.platform = current_platform
|
sys.platform = current_platform
|
||||||
|
|
|
@ -824,19 +824,20 @@ class KeysPageTest(unittest.TestCase):
|
||||||
d.custom_name.set('my custom keys')
|
d.custom_name.set('my custom keys')
|
||||||
d.bindingslist.delete(0, 'end')
|
d.bindingslist.delete(0, 'end')
|
||||||
d.bindingslist.insert(0, 'copy')
|
d.bindingslist.insert(0, 'copy')
|
||||||
d.bindingslist.insert(1, 'expand-word')
|
d.bindingslist.insert(1, 'z-in')
|
||||||
d.bindingslist.selection_set(0)
|
d.bindingslist.selection_set(0)
|
||||||
d.bindingslist.selection_anchor(0)
|
d.bindingslist.selection_anchor(0)
|
||||||
# Core binding - adds to keys.
|
# Core binding - adds to keys.
|
||||||
d.keybinding.set('<Key-F11>')
|
d.keybinding.set('<Key-F11>')
|
||||||
self.assertEqual(keyspage,
|
self.assertEqual(keyspage,
|
||||||
{'my custom keys': {'copy': '<Key-F11>'}})
|
{'my custom keys': {'copy': '<Key-F11>'}})
|
||||||
|
|
||||||
# Not a core binding - adds to extensions.
|
# Not a core binding - adds to extensions.
|
||||||
d.bindingslist.selection_set(1)
|
d.bindingslist.selection_set(1)
|
||||||
d.bindingslist.selection_anchor(1)
|
d.bindingslist.selection_anchor(1)
|
||||||
d.keybinding.set('<Key-F11>')
|
d.keybinding.set('<Key-F11>')
|
||||||
self.assertEqual(extpage,
|
self.assertEqual(extpage,
|
||||||
{'AutoExpand_cfgBindings': {'expand-word': '<Key-F11>'}})
|
{'ZzDummy_cfgBindings': {'z-in': '<Key-F11>'}})
|
||||||
|
|
||||||
def test_set_keys_type(self):
|
def test_set_keys_type(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
|
@ -1125,13 +1126,6 @@ class GenPageTest(unittest.TestCase):
|
||||||
self.assertEqual(mainpage,
|
self.assertEqual(mainpage,
|
||||||
{'General': {'editor-on-startup': '0'}})
|
{'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):
|
def test_editor_size(self):
|
||||||
d = self.page
|
d = self.page
|
||||||
d.win_height_int.insert(0, '1')
|
d.win_height_int.insert(0, '1')
|
||||||
|
@ -1140,6 +1134,37 @@ class GenPageTest(unittest.TestCase):
|
||||||
d.win_width_int.insert(0, '1')
|
d.win_width_int.insert(0, '1')
|
||||||
self.assertEqual(mainpage, {'EditorWindow': {'width': '180'}})
|
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):
|
def test_source_selected(self):
|
||||||
d = self.page
|
d = self.page
|
||||||
d.set = d.set_add_delete_state
|
d.set = d.set_add_delete_state
|
||||||
|
|
|
@ -52,6 +52,11 @@ menudefs = [
|
||||||
('Find in Files...', '<<find-in-files>>'),
|
('Find in Files...', '<<find-in-files>>'),
|
||||||
('R_eplace...', '<<replace>>'),
|
('R_eplace...', '<<replace>>'),
|
||||||
('Go to _Line', '<<goto-line>>'),
|
('Go to _Line', '<<goto-line>>'),
|
||||||
|
('S_how Completions', '<<force-open-completions>>'),
|
||||||
|
('E_xpand Word', '<<expand-word>>'),
|
||||||
|
('Show C_all Tip', '<<force-open-calltip>>'),
|
||||||
|
('Show Surrounding P_arens', '<<flash-paren>>'),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
('format', [
|
('format', [
|
||||||
('_Indent Region', '<<indent-region>>'),
|
('_Indent Region', '<<indent-region>>'),
|
||||||
|
@ -62,9 +67,13 @@ menudefs = [
|
||||||
('Untabify Region', '<<untabify-region>>'),
|
('Untabify Region', '<<untabify-region>>'),
|
||||||
('Toggle Tabs', '<<toggle-tabs>>'),
|
('Toggle Tabs', '<<toggle-tabs>>'),
|
||||||
('New Indent Width', '<<change-indentwidth>>'),
|
('New Indent Width', '<<change-indentwidth>>'),
|
||||||
|
('F_ormat Paragraph', '<<format-paragraph>>'),
|
||||||
|
('S_trip Trailing Whitespace', '<<do-rstrip>>'),
|
||||||
]),
|
]),
|
||||||
('run', [
|
('run', [
|
||||||
('Python Shell', '<<open-python-shell>>'),
|
('Python Shell', '<<open-python-shell>>'),
|
||||||
|
('C_heck Module', '<<check-module>>'),
|
||||||
|
('R_un Module', '<<run-module>>'),
|
||||||
]),
|
]),
|
||||||
('shell', [
|
('shell', [
|
||||||
('_View Last Restart', '<<view-restart>>'),
|
('_View Last Restart', '<<view-restart>>'),
|
||||||
|
@ -80,7 +89,10 @@ menudefs = [
|
||||||
]),
|
]),
|
||||||
('options', [
|
('options', [
|
||||||
('Configure _IDLE', '<<open-config-dialog>>'),
|
('Configure _IDLE', '<<open-config-dialog>>'),
|
||||||
None,
|
('_Code Context', '<<toggle-code-context>>'),
|
||||||
|
]),
|
||||||
|
('windows', [
|
||||||
|
('Zoom Height', '<<zoom-height>>'),
|
||||||
]),
|
]),
|
||||||
('help', [
|
('help', [
|
||||||
('_About IDLE', '<<about-idle>>'),
|
('_About IDLE', '<<about-idle>>'),
|
||||||
|
|
|
@ -77,6 +77,7 @@ class OutputWindow(EditorWindow):
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
EditorWindow.__init__(self, *args)
|
EditorWindow.__init__(self, *args)
|
||||||
self.text.bind("<<goto-file-line>>", self.goto_file_line)
|
self.text.bind("<<goto-file-line>>", self.goto_file_line)
|
||||||
|
self.text.unbind("<<toggle-code-context>>")
|
||||||
|
|
||||||
# Customize EditorWindow
|
# Customize EditorWindow
|
||||||
def ispythonsource(self, filename):
|
def ispythonsource(self, filename):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""Extension to 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
|
Does basic, standard text formatting, and also understands Python
|
||||||
comment blocks. Thus, for editing Python source code, this
|
comment blocks. Thus, for editing Python source code, this
|
||||||
|
@ -21,15 +21,14 @@ from idlelib.config import idleConf
|
||||||
|
|
||||||
class FormatParagraph:
|
class FormatParagraph:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('format', [ # /s/edit/format dscherer@cmu.edu
|
|
||||||
('Format Paragraph', '<<format-paragraph>>'),
|
|
||||||
])
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, editwin):
|
def __init__(self, editwin):
|
||||||
self.editwin = editwin
|
self.editwin = editwin
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reload(cls):
|
||||||
|
cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph',
|
||||||
|
'max-width', type='int', default=72)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.editwin = None
|
self.editwin = None
|
||||||
|
|
||||||
|
@ -45,11 +44,7 @@ class FormatParagraph:
|
||||||
|
|
||||||
The length limit parameter is for testing with a known value.
|
The length limit parameter is for testing with a known value.
|
||||||
"""
|
"""
|
||||||
if limit is None:
|
limit = self.max_width if limit is None else limit
|
||||||
# The default length limit is that defined by pep8
|
|
||||||
limit = idleConf.GetOption(
|
|
||||||
'extensions', 'FormatParagraph', 'max-width',
|
|
||||||
type='int', default=72)
|
|
||||||
text = self.editwin.text
|
text = self.editwin.text
|
||||||
first, last = self.editwin.get_selection_indices()
|
first, last = self.editwin.get_selection_indices()
|
||||||
if first and last:
|
if first and last:
|
||||||
|
@ -75,6 +70,9 @@ class FormatParagraph:
|
||||||
text.see("insert")
|
text.see("insert")
|
||||||
return "break"
|
return "break"
|
||||||
|
|
||||||
|
|
||||||
|
FormatParagraph.reload()
|
||||||
|
|
||||||
def find_paragraph(text, mark):
|
def find_paragraph(text, mark):
|
||||||
"""Returns the start/stop indices enclosing the paragraph that mark is in.
|
"""Returns the start/stop indices enclosing the paragraph that mark is in.
|
||||||
|
|
||||||
|
|
|
@ -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
|
When you hit a right paren, the cursor should move briefly to the left
|
||||||
paren. Paren here is used generically; the matching applies to
|
paren. Paren here is used generically; the matching applies to
|
||||||
|
@ -30,18 +30,6 @@ class ParenMatch:
|
||||||
- Highlight when cursor is moved to the right of a closer.
|
- Highlight when cursor is moved to the right of a closer.
|
||||||
This might be too expensive to check.
|
This might be too expensive to check.
|
||||||
"""
|
"""
|
||||||
menudefs = [
|
|
||||||
('edit', [
|
|
||||||
("Show surrounding parens", "<<flash-paren>>"),
|
|
||||||
])
|
|
||||||
]
|
|
||||||
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(),'hilite')
|
|
||||||
|
|
||||||
RESTORE_VIRTUAL_EVENT_NAME = "<<parenmatch-check-restore>>"
|
RESTORE_VIRTUAL_EVENT_NAME = "<<parenmatch-check-restore>>"
|
||||||
# We want the restore event be called before the usual return and
|
# We want the restore event be called before the usual return and
|
||||||
|
@ -62,6 +50,17 @@ class ParenMatch:
|
||||||
self.is_restore_active = 0
|
self.is_restore_active = 0
|
||||||
self.set_style(self.STYLE)
|
self.set_style(self.STYLE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reload(cls):
|
||||||
|
cls.STYLE = idleConf.GetOption(
|
||||||
|
'extensions','ParenMatch','style', default='opener')
|
||||||
|
cls.FLASH_DELAY = idleConf.GetOption(
|
||||||
|
'extensions','ParenMatch','flash-delay', type='int',default=500)
|
||||||
|
cls.BELL = idleConf.GetOption(
|
||||||
|
'extensions','ParenMatch','bell', type='bool', default=1)
|
||||||
|
cls.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(),
|
||||||
|
'hilite')
|
||||||
|
|
||||||
def activate_restore(self):
|
def activate_restore(self):
|
||||||
"Activate mechanism to restore text from highlighting."
|
"Activate mechanism to restore text from highlighting."
|
||||||
if not self.is_restore_active:
|
if not self.is_restore_active:
|
||||||
|
@ -181,6 +180,9 @@ class ParenMatch:
|
||||||
lambda self=self, c=self.counter: self.handle_restore_timer(c))
|
lambda self=self, c=self.counter: self.handle_restore_timer(c))
|
||||||
|
|
||||||
|
|
||||||
|
ParenMatch.reload()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import unittest
|
import unittest
|
||||||
unittest.main('idlelib.idle_test.test_parenmatch', verbosity=2)
|
unittest.main('idlelib.idle_test.test_parenmatch', verbosity=2)
|
||||||
|
|
|
@ -2,12 +2,8 @@
|
||||||
|
|
||||||
class RstripExtension:
|
class RstripExtension:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('format', [None, ('Strip trailing whitespace', '<<do-rstrip>>'), ] ), ]
|
|
||||||
|
|
||||||
def __init__(self, editwin):
|
def __init__(self, editwin):
|
||||||
self.editwin = editwin
|
self.editwin = editwin
|
||||||
self.editwin.text.bind("<<do-rstrip>>", self.do_rstrip)
|
|
||||||
|
|
||||||
def do_rstrip(self, event=None):
|
def do_rstrip(self, event=None):
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
"""Extension to 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.
|
Run module: also execute the module's code in the __main__ namespace.
|
||||||
It also runs the tabnanny to catch any inconsistent tabs.
|
The window must have been saved previously. The module is added to
|
||||||
|
sys.modules, and is also added to the __main__ namespace.
|
||||||
- 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
|
|
||||||
|
|
||||||
|
TODO: Specify command line arguments in a dialog box.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import tabnanny
|
import tabnanny
|
||||||
import tokenize
|
import tokenize
|
||||||
|
@ -40,11 +32,6 @@ by Format->Untabify Region and specify the number of columns used by each tab.
|
||||||
|
|
||||||
class ScriptBinding:
|
class ScriptBinding:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('run', [None,
|
|
||||||
('Check Module', '<<check-module>>'),
|
|
||||||
('Run Module', '<<run-module>>'), ]), ]
|
|
||||||
|
|
||||||
def __init__(self, editwin):
|
def __init__(self, editwin):
|
||||||
self.editwin = editwin
|
self.editwin = editwin
|
||||||
# Provide instance variables referenced by debugger
|
# Provide instance variables referenced by debugger
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Sample extension: zoom a window to maximum height
|
"Zoom a window to maximum height."
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -8,12 +8,6 @@ from idlelib import macosx
|
||||||
|
|
||||||
class ZoomHeight:
|
class ZoomHeight:
|
||||||
|
|
||||||
menudefs = [
|
|
||||||
('windows', [
|
|
||||||
('_Zoom Height', '<<zoom-height>>'),
|
|
||||||
])
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, editwin):
|
def __init__(self, editwin):
|
||||||
self.editwin = editwin
|
self.editwin = editwin
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
"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-in>>'),
|
||||||
|
## ('Z out', '<<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"
|
||||||
|
|
||||||
|
def z_out_event(self, event): pass
|
||||||
|
|
||||||
|
ZzDummy.reload()
|
||||||
|
|
||||||
|
##if __name__ == "__main__":
|
||||||
|
## import unittest
|
||||||
|
## unittest.main('idlelib.idle_test.test_zzdummy',
|
||||||
|
## verbosity=2, exit=False)
|
|
@ -0,0 +1,20 @@
|
||||||
|
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 '<<force-open-completions>>', '<<expand-word>>',
|
||||||
|
'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>',
|
||||||
|
'<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. 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.
|
Loading…
Reference in New Issue