Commit 4d5bc603 authored by Kurt B. Kaiser's avatar Kurt B. Kaiser

Noam Raphel: Further developemt of CodeContext feature.

The visibility state of the code context pane is now persistent between
sessions and the pane does not appear in the shell window.

M CodeContext.py
M EditorWindow.py
M NEWS.txt
M PyShell.py
M config-extensions.def
M configHandler.py
parent cfa157d8
"""CodeContext - Display the block context of code at top of edit window """CodeContext - Display the block context of code at top of edit window
Once code has scolled off the top of the screen, it can be difficult Once code has scrolled off the top of the screen, it can be difficult
to determine which block you are in. This extension implements a pane to determine which block you are in. This extension implements a pane
at the top of each IDLE edit window which provides block structure at the top of each IDLE edit window which provides block structure
hints. These hints are the lines which contain the block opening hints. These hints are the lines which contain the block opening
...@@ -12,12 +12,11 @@ the context hints pane. ...@@ -12,12 +12,11 @@ the context hints pane.
""" """
import Tkinter import Tkinter
from configHandler import idleConf from configHandler import idleConf
from PyShell import PyShell from sets import Set
import re import re
BLOCKOPENERS = dict([(x, None) for x in ("class", "def", "elif", "else", BLOCKOPENERS = Set(["class", "def", "elif", "else", "except", "finally", "for",
"except", "finally", "for", "if", "if", "try", "while"])
"try", "while")])
INFINITY = 1 << 30 INFINITY = 1 << 30
UPDATEINTERVAL = 100 # millisec UPDATEINTERVAL = 100 # millisec
FONTUPDATEINTERVAL = 1000 # millisec FONTUPDATEINTERVAL = 1000 # millisec
...@@ -33,11 +32,7 @@ class CodeContext: ...@@ -33,11 +32,7 @@ class CodeContext:
"bgcolor", type="str", default="LightGray") "bgcolor", type="str", default="LightGray")
fgcolor = idleConf.GetOption("extensions", "CodeContext", fgcolor = idleConf.GetOption("extensions", "CodeContext",
"fgcolor", type="str", default="Black") "fgcolor", type="str", default="Black")
default_on = idleConf.GetOption("extensions", "CodeContext",
"default_on", type="int", default=0)
def __init__(self, editwin): def __init__(self, editwin):
if isinstance(editwin, PyShell):
return
self.editwin = editwin self.editwin = editwin
self.text = editwin.text self.text = editwin.text
self.textfont = self.text["font"] self.textfont = self.text["font"]
...@@ -45,7 +40,9 @@ class CodeContext: ...@@ -45,7 +40,9 @@ class CodeContext:
# Dummy line, which starts the "block" of the whole document: # Dummy line, which starts the "block" of the whole document:
self.info = list(self.interesting_lines(1)) self.info = list(self.interesting_lines(1))
self.lastfirstline = 1 self.lastfirstline = 1
if self.default_on: visible = idleConf.GetOption("extensions", "CodeContext",
"visible", type="bool", default=False)
if visible:
self.toggle_code_context_event() self.toggle_code_context_event()
self.editwin.setvar('<<toggle-code-context>>', True) 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.
...@@ -67,6 +64,9 @@ class CodeContext: ...@@ -67,6 +64,9 @@ class CodeContext:
else: else:
self.label.destroy() self.label.destroy()
self.label = None self.label = None
idleConf.SetOption("extensions", "CodeContext", "visible",
str(self.label is not None))
idleConf.SaveUserCfgFiles()
def get_line_info(self, linenum): def get_line_info(self, linenum):
"""Get the line indent value, text, and any block start keyword """Get the line indent value, text, and any block start keyword
......
...@@ -751,14 +751,16 @@ class EditorWindow: ...@@ -751,14 +751,16 @@ class EditorWindow:
traceback.print_exc() traceback.print_exc()
def get_standard_extension_names(self): def get_standard_extension_names(self):
return idleConf.GetExtensions() return idleConf.GetExtensions(editor_only=True)
def load_extension(self, name): def load_extension(self, name):
mod = __import__(name, globals(), locals(), []) mod = __import__(name, globals(), locals(), [])
cls = getattr(mod, name) cls = getattr(mod, name)
keydefs = idleConf.GetExtensionBindings(name)
if hasattr(cls, "menudefs"):
self.fill_menus(cls.menudefs, keydefs)
ins = cls(self) ins = cls(self)
self.extensions[name] = ins self.extensions[name] = ins
keydefs=idleConf.GetExtensionBindings(name)
if keydefs: if keydefs:
self.apply_bindings(keydefs) self.apply_bindings(keydefs)
for vevent in keydefs.keys(): for vevent in keydefs.keys():
...@@ -770,8 +772,6 @@ class EditorWindow: ...@@ -770,8 +772,6 @@ class EditorWindow:
methodname = methodname + "_event" methodname = methodname + "_event"
if hasattr(ins, methodname): if hasattr(ins, methodname):
self.text.bind(vevent, getattr(ins, methodname)) self.text.bind(vevent, getattr(ins, methodname))
if hasattr(ins, "menudefs"):
self.fill_menus(ins.menudefs, keydefs)
return ins return ins
def apply_bindings(self, keydefs=None): def apply_bindings(self, keydefs=None):
......
What's New in IDLE 1.1a0? What's New in IDLE 1.1a0?
=================================== =========================
*Release date: XX-XXX-2004* *Release date: XX-XXX-2004*
- CodeContext hint pane visibility state is now persistent across sessions.
The pane no longer appears in the shell window. Added capability to limit
extensions to shell window or editor windows. Noam Raphael addition
to Patch 936169.
- Paragraph reformat width is now a configurable parameter in the
Options GUI.
- New Extension: CodeContext. Provides block structuring hints for code - New Extension: CodeContext. Provides block structuring hints for code
which has scrolled above an edit window. Patch 936169 Noam Raphael. which has scrolled above an edit window. Patch 936169 Noam Raphael.
...@@ -52,7 +60,7 @@ What's New in IDLE 1.1a0? ...@@ -52,7 +60,7 @@ What's New in IDLE 1.1a0?
What's New in IDLE 1.0? What's New in IDLE 1.0?
=================================== =======================
*Release date: 29-Jul-2003* *Release date: 29-Jul-2003*
...@@ -61,7 +69,7 @@ What's New in IDLE 1.0? ...@@ -61,7 +69,7 @@ What's New in IDLE 1.0?
What's New in IDLE 1.0 release candidate 2? What's New in IDLE 1.0 release candidate 2?
=================================== ===========================================
*Release date: 24-Jul-2003* *Release date: 24-Jul-2003*
...@@ -69,7 +77,7 @@ What's New in IDLE 1.0 release candidate 2? ...@@ -69,7 +77,7 @@ What's New in IDLE 1.0 release candidate 2?
What's New in IDLE 1.0 release candidate 1? What's New in IDLE 1.0 release candidate 1?
=================================== ===========================================
*Release date: 18-Jul-2003* *Release date: 18-Jul-2003*
...@@ -90,7 +98,7 @@ What's New in IDLE 1.0 release candidate 1? ...@@ -90,7 +98,7 @@ What's New in IDLE 1.0 release candidate 1?
What's New in IDLE 1.0b2? What's New in IDLE 1.0b2?
=================================== =========================
*Release date: 29-Jun-2003* *Release date: 29-Jun-2003*
...@@ -131,7 +139,7 @@ What's New in IDLE 1.0b2? ...@@ -131,7 +139,7 @@ What's New in IDLE 1.0b2?
What's New in IDLEfork 0.9b1? What's New in IDLEfork 0.9b1?
=================================== =============================
*Release date: 02-Jun-2003* *Release date: 02-Jun-2003*
......
...@@ -806,6 +806,9 @@ class PyShell(OutputWindow): ...@@ -806,6 +806,9 @@ class PyShell(OutputWindow):
# #
self.pollinterval = 50 # millisec self.pollinterval = 50 # millisec
def get_standard_extension_names(self):
return idleConf.GetExtensions(shell_only=True)
reading = False reading = False
executing = False executing = False
canceled = False canceled = False
......
# config-extensions.def
#
# 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.
# #
# Each extension must have at least one section, named after the extension # Each extension must have at least one section, named after the extension
# module. This section must contain an 'enable' item (=1 to enable the # module. This section must contain an 'enable' item (=1 to enable the
# extension, =0 to disable it) and also contain any other general configuration # extension, =0 to disable it), it may contain 'enable_editor' or 'enable_shell'
# items for the extension. Each extension must define at least one section # items, to apply it only to editor/shell windows, and may also contain any
# named ExtensionName_bindings or ExtensionName_cfgBindings. If present, # other general configuration items for the extension.
# ExtensionName_bindings defines virtual event bindings for the extension that #
# are not user re-configurable. If present, ExtensionName_cfgBindings # Each extension must define at least one section named ExtensionName_bindings
# defines virtual event bindings for the extension that may be sensibly # or ExtensionName_cfgBindings. If present, ExtensionName_bindings defines
# re-configured. If there are no keybindings for a menus' virtual events, # virtual event bindings for the extension that are not user re-configurable.
# include lines like <<toggle-code-context>>= (See [CodeContext], below.) # If present, ExtensionName_cfgBindings defines virtual event bindings for the
# extension that may be sensibly re-configured.
#
# If there are no keybindings for a menus' virtual events, include lines like
# <<toggle-code-context>>= (See [CodeContext], below.)
#
# Currently it is necessary to manually modify this file to change extension # Currently it is necessary to manually modify this file to change extension
# key bindings and default values. To customize, create # key bindings and default values. To customize, create
# ~/.idlerc/config-extensions.cfg and append the appropriate customized # ~/.idlerc/config-extensions.cfg and append the appropriate customized
# section(s). Those sections will override the defaults in this file. # section(s). Those sections will override the defaults in this file.
#
# Note: If a keybinding is already in use when the extension is # Note: If a keybinding is already in use when the extension is
# loaded, the extension's virtual event's keybinding will be set to ''. # loaded, the extension's virtual event's keybinding will be set to ''.
#
# 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.
...@@ -65,8 +71,9 @@ check-restore=<KeyPress> ...@@ -65,8 +71,9 @@ check-restore=<KeyPress>
[CodeContext] [CodeContext]
enable=1 enable=1
enable_shell=0
numlines=3 numlines=3
default_on=0 visible=0
bgcolor=LightGray bgcolor=LightGray
fgcolor=Black fgcolor=Black
[CodeContext_bindings] [CodeContext_bindings]
......
...@@ -215,7 +215,8 @@ class IdleConf: ...@@ -215,7 +215,8 @@ class IdleConf:
sys.stderr.write(warn) sys.stderr.write(warn)
return userDir return userDir
def GetOption(self, configType, section, option, default=None, type=None): def GetOption(self, configType, section, option, default=None, type=None,
warn_on_default=True):
""" """
Get an option value for given config type and given general Get an option value for given config type and given general
configuration section/option or return a default. If type is specified, configuration section/option or return a default. If type is specified,
...@@ -224,14 +225,17 @@ class IdleConf: ...@@ -224,14 +225,17 @@ class IdleConf:
fallback to a useable passed-in default if the option isn't present in fallback to a useable passed-in default if the option isn't present in
either the user or the default configuration. either the user or the default configuration.
configType must be one of ('main','extensions','highlight','keys') configType must be one of ('main','extensions','highlight','keys')
If a default is returned a warning is printed to stderr. If a default is returned, and warn_on_default is True, a warning is
printed to stderr.
""" """
if self.userCfg[configType].has_option(section,option): if self.userCfg[configType].has_option(section,option):
return self.userCfg[configType].Get(section, option, type=type) return self.userCfg[configType].Get(section, option, type=type)
elif self.defaultCfg[configType].has_option(section,option): elif self.defaultCfg[configType].has_option(section,option):
return self.defaultCfg[configType].Get(section, option, type=type) return self.defaultCfg[configType].Get(section, option, type=type)
else: #returning default, print warning else: #returning default, print warning
warning=('\n Warning: configHandler.py - IdleConf.GetOption -\n' if warn_on_default:
warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n'
' problem retrieving configration option %r\n' ' problem retrieving configration option %r\n'
' from section %r.\n' ' from section %r.\n'
' returning default value: %r\n' % ' returning default value: %r\n' %
...@@ -239,6 +243,12 @@ class IdleConf: ...@@ -239,6 +243,12 @@ class IdleConf:
sys.stderr.write(warning) sys.stderr.write(warning)
return default return default
def SetOption(self, configType, section, option, value):
"""In user's config file, set section's option to value.
"""
self.userCfg[configType].SetOption(section, option, value)
def GetSectionList(self, configSet, configType): def GetSectionList(self, configSet, configType):
""" """
Get a list of sections from either the user or default config for Get a list of sections from either the user or default config for
...@@ -356,10 +366,10 @@ class IdleConf: ...@@ -356,10 +366,10 @@ class IdleConf:
""" """
return self.GetOption('main','Keys','name',default='') return self.GetOption('main','Keys','name',default='')
def GetExtensions(self, activeOnly=1): def GetExtensions(self, active_only=True, editor_only=False, shell_only=False):
""" """
Gets a list of all idle extensions declared in the config files. Gets a list of all idle extensions declared in the config files.
activeOnly - boolean, if true only return active (enabled) extensions active_only - boolean, if true only return active (enabled) extensions
""" """
extns=self.RemoveKeyBindNames( extns=self.RemoveKeyBindNames(
self.GetSectionList('default','extensions')) self.GetSectionList('default','extensions'))
...@@ -368,12 +378,22 @@ class IdleConf: ...@@ -368,12 +378,22 @@ 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)
if activeOnly: if active_only:
activeExtns=[] activeExtns=[]
for extn in extns: for extn in extns:
if self.GetOption('extensions',extn,'enable',default=1, if self.GetOption('extensions', extn, 'enable', default=True,
type='bool'): type='bool'):
#the extension is enabled #the extension is enabled
if editor_only or shell_only:
if editor_only:
option = "enable_editor"
else:
option = "enable_shell"
if self.GetOption('extensions', extn,option,
default=True, type='bool',
warn_on_default=False):
activeExtns.append(extn)
else:
activeExtns.append(extn) activeExtns.append(extn)
return activeExtns return activeExtns
else: else:
...@@ -401,7 +421,7 @@ class IdleConf: ...@@ -401,7 +421,7 @@ class IdleConf:
""" """
extName=None extName=None
vEvent='<<'+virtualEvent+'>>' vEvent='<<'+virtualEvent+'>>'
for extn in self.GetExtensions(activeOnly=0): for extn in self.GetExtensions(active_only=0):
for event in self.GetExtensionKeys(extn).keys(): for event in self.GetExtensionKeys(extn).keys():
if event == vEvent: if event == vEvent:
extName=extn extName=extn
...@@ -482,7 +502,7 @@ class IdleConf: ...@@ -482,7 +502,7 @@ class IdleConf:
in an extension is already in use, that binding is disabled. in an extension is already in use, that binding is disabled.
""" """
keySet=self.GetCoreKeys(keySetName) keySet=self.GetCoreKeys(keySetName)
activeExtns=self.GetExtensions(activeOnly=1) activeExtns=self.GetExtensions(active_only=1)
for extn in activeExtns: for extn in activeExtns:
extKeys=self.__GetRawExtensionKeys(extn) extKeys=self.__GetRawExtensionKeys(extn)
if extKeys: #the extension defines keybindings if extKeys: #the extension defines keybindings
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment