[Python-checkins] python/dist/src/Lib/idlelib CallTipWindow.py, 1.7, 1.7.14.1 CallTips.py, 1.12, 1.12.6.1 EditorWindow.py, 1.69, 1.69.2.1 ParenMatch.py, 1.8, 1.8.6.1 PyParse.py, 1.5, 1.5.14.1 PyShell.py, 1.99, 1.99.2.1 config-extensions.def, 1.15, 1.15.6.1 configDialog.py, 1.62, 1.62.2.1 run.py, 1.32, 1.32.2.1
kbk@users.sourceforge.net
kbk at users.sourceforge.net
Mon Oct 10 02:05:36 CEST 2005
Update of /cvsroot/python/python/dist/src/Lib/idlelib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22453
Modified Files:
Tag: IDLE-syntax-branch
CallTipWindow.py CallTips.py EditorWindow.py ParenMatch.py
PyParse.py PyShell.py config-extensions.def configDialog.py
run.py
Log Message:
Noam Raphael 'syntax' patch 10Jul05
Index: CallTipWindow.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/CallTipWindow.py,v
retrieving revision 1.7
retrieving revision 1.7.14.1
diff -u -d -r1.7 -r1.7.14.1
--- CallTipWindow.py 31 Dec 2002 15:59:14 -0000 1.7
+++ CallTipWindow.py 10 Oct 2005 00:05:30 -0000 1.7.14.1
@@ -6,33 +6,65 @@
"""
from Tkinter import *
+HIDE_VIRTUAL_EVENT_NAME = "<<caltipwindow-hide>>"
+HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>")
+CHECKHIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-checkhide>>"
+CHECKHIDE_SEQUENCES = ("<KeyRelease>", "<ButtonRelease>")
+CHECKHIDE_TIME = 100 # miliseconds
+
+MARK_RIGHT = "calltipwindowregion_right"
+
class CallTip:
def __init__(self, widget):
self.widget = widget
- self.tipwindow = None
- self.id = None
- self.x = self.y = 0
+ self.tipwindow = self.label = None
+ self.parenline = self.parencol = None
+ self.lastline = None
+ self.hideid = self.checkhideid = None
- def showtip(self, text):
- " Display text in calltip window"
+ def position_window(self):
+ """Check if needs to reposition the window, and if so - do it."""
+ curline = int(self.widget.index("insert").split('.')[0])
+ if curline == self.lastline:
+ return
+ self.lastline = curline
+ self.widget.see("insert")
+ if curline == self.parenline:
+ box = self.widget.bbox("%d.%d" % (self.parenline,
+ self.parencol))
+ else:
+ box = self.widget.bbox("%d.0" % curline)
+ if not box:
+ box = list(self.widget.bbox("insert"))
+ # align to left of window
+ box[0] = 0
+ box[2] = 0
+ x = box[0] + self.widget.winfo_rootx() + 2
+ y = box[1] + box[3] + self.widget.winfo_rooty()
+ self.tipwindow.wm_geometry("+%d+%d" % (x, y))
+
+ def showtip(self, text, parenleft, parenright):
+ """Show the calltip, bind events which will close it and reposition it.
+ """
# truncate overly long calltip
if len(text) >= 79:
text = text[:75] + ' ...'
self.text = text
if self.tipwindow or not self.text:
return
- self.widget.see("insert")
- x, y, cx, cy = self.widget.bbox("insert")
- x = x + self.widget.winfo_rootx() + 2
- y = y + cy + self.widget.winfo_rooty()
+
+ self.widget.mark_set(MARK_RIGHT, parenright)
+ self.parenline, self.parencol = map(
+ int, self.widget.index(parenleft).split("."))
+
self.tipwindow = tw = Toplevel(self.widget)
+ self.position_window()
# XXX 12 Dec 2002 KBK The following command has two effects: It removes
# the calltip window border (good) but also causes (at least on
# Linux) the calltip to show as a top level window, burning through
# any other window dragged over it. Also, shows on all viewports!
tw.wm_overrideredirect(1)
- tw.wm_geometry("+%d+%d" % (x, y))
try:
# This command is only needed and available on Tk >= 8.4.0 for OSX
# Without it, call tips intrude on the typing process by grabbing
@@ -41,16 +73,66 @@
"help", "noActivates")
except TclError:
pass
- label = Label(tw, text=self.text, justify=LEFT,
- background="#ffffe0", relief=SOLID, borderwidth=1,
- font = self.widget['font'])
- label.pack()
+ self.label = Label(tw, text=self.text, justify=LEFT,
+ background="#ffffe0", relief=SOLID, borderwidth=1,
+ font = self.widget['font'])
+ self.label.pack()
+
+ self.checkhideid = self.widget.bind(CHECKHIDE_VIRTUAL_EVENT_NAME,
+ self.checkhide_event)
+ for seq in CHECKHIDE_SEQUENCES:
+ self.widget.event_add(CHECKHIDE_VIRTUAL_EVENT_NAME, seq)
+ self.widget.after(CHECKHIDE_TIME, self.checkhide_event)
+ self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME,
+ self.hide_event)
+ for seq in HIDE_SEQUENCES:
+ self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq)
+
+ def checkhide_event(self, event=None):
+ if not self.tipwindow:
+ # If the event was triggered by the same event that unbinded
+ # this function, the function will be called nevertheless,
+ # so do nothing in this case.
+ return
+ curline, curcol = map(int, self.widget.index("insert").split('.'))
+ if curline < self.parenline or \
+ (curline == self.parenline and curcol <= self.parencol) or \
+ self.widget.compare("insert", ">", MARK_RIGHT):
+ self.hidetip()
+ else:
+ self.position_window()
+ self.widget.after(CHECKHIDE_TIME, self.checkhide_event)
+
+ def hide_event(self, event):
+ if not self.tipwindow:
+ # See the explanation in checkhide_event.
+ return
+ self.hidetip()
def hidetip(self):
- tw = self.tipwindow
+ if not self.tipwindow:
+ return
+
+ for seq in CHECKHIDE_SEQUENCES:
+ self.widget.event_delete(CHECKHIDE_VIRTUAL_EVENT_NAME, seq)
+ self.widget.unbind(CHECKHIDE_VIRTUAL_EVENT_NAME, self.checkhideid)
+ self.checkhideid = None
+ for seq in HIDE_SEQUENCES:
+ self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq)
+ self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid)
+ self.hideid = None
+
+ self.label.destroy()
+ self.label = None
+ self.tipwindow.destroy()
self.tipwindow = None
- if tw:
- tw.destroy()
+
+ self.widget.mark_unset(MARK_RIGHT)
+ self.parenline = self.parencol = self.lastline = None
+
+ def is_active(self):
+ return bool(self.tipwindow)
+
###############################
Index: CallTips.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/CallTips.py,v
retrieving revision 1.12
retrieving revision 1.12.6.1
diff -u -d -r1.12 -r1.12.6.1
--- CallTips.py 4 May 2004 08:34:56 -0000 1.12
+++ CallTips.py 10 Oct 2005 00:05:30 -0000 1.12.6.1
@@ -3,21 +3,21 @@
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.
-
-Future plans include extending the functionality to include class attributes.
-
"""
import sys
-import string
import types
import CallTipWindow
+from HyperParser import HyperParser
import __main__
class CallTips:
menudefs = [
+ ('edit', [
+ ("Show call tip", "<<force-open-calltip>>"),
+ ])
]
def __init__(self, editwin=None):
@@ -36,51 +36,47 @@
# See __init__ for usage
return CallTipWindow.CallTip(self.text)
- def _remove_calltip_window(self):
+ def _remove_calltip_window(self, event=None):
if self.calltip:
self.calltip.hidetip()
self.calltip = None
- def paren_open_event(self, event):
- self._remove_calltip_window()
- name = self.get_name_at_cursor()
- arg_text = self.fetch_tip(name)
- if arg_text:
- self.calltip_start = self.text.index("insert")
- self.calltip = self._make_calltip_window()
- self.calltip.showtip(arg_text)
- return "" #so the event is handled normally.
+ def force_open_calltip_event(self, event):
+ """Happens when the user really wants to open a CallTip, even if a
+ function call is needed.
+ """
+ self.open_calltip(True)
- def paren_close_event(self, event):
- # Now just hides, but later we should check if other
- # paren'd expressions remain open.
- self._remove_calltip_window()
- return "" #so the event is handled normally.
+ def try_open_calltip_event(self, event):
+ """Happens when it would be nice to open a CallTip, but not really
+ neccesary, for example after an opening bracket, so function calls
+ won't be made.
+ """
+ self.open_calltip(False)
- def check_calltip_cancel_event(self, event):
- if self.calltip:
- # If we have moved before the start of the calltip,
- # or off the calltip line, then cancel the tip.
- # (Later need to be smarter about multi-line, etc)
- if self.text.compare("insert", "<=", self.calltip_start) or \
- self.text.compare("insert", ">", self.calltip_start
- + " lineend"):
- self._remove_calltip_window()
- return "" #so the event is handled normally.
+ def refresh_calltip_event(self, event):
+ """If there is already a calltip window, check if it is still needed,
+ and if so, reload it.
+ """
+ if self.calltip and self.calltip.is_active():
+ self.open_calltip(False)
- def calltip_cancel_event(self, event):
+ def open_calltip(self, evalfuncs):
self._remove_calltip_window()
- return "" #so the event is handled normally.
-
- __IDCHARS = "._" + string.ascii_letters + string.digits
- def get_name_at_cursor(self):
- idchars = self.__IDCHARS
- str = self.text.get("insert linestart", "insert")
- i = len(str)
- while i and str[i-1] in idchars:
- i -= 1
- return str[i:]
+ hp = HyperParser(self.editwin, "insert")
+ sur_paren = hp.get_surrounding_brackets('(')
+ if not sur_paren:
+ return
+ hp.set_index(sur_paren[0])
+ name = hp.get_expression()
+ if not name or (not evalfuncs and name.find('(') != -1):
+ return
+ arg_text = self.fetch_tip(name)
+ if not arg_text:
+ return
+ self.calltip = self._make_calltip_window()
+ self.calltip.showtip(arg_text, sur_paren[0], sur_paren[1])
def fetch_tip(self, name):
"""Return the argument list and docstring of a function or class
@@ -127,7 +123,7 @@
return None
def get_arg_text(ob):
- "Get a string describing the arguments for the given object"
+ """Get a string describing the arguments for the given object"""
argText = ""
if ob is not None:
argOffset = 0
@@ -150,7 +146,7 @@
try:
realArgs = fob.func_code.co_varnames[argOffset:fob.func_code.co_argcount]
defaults = fob.func_defaults or []
- defaults = list(map(lambda name: "=%s" % name, defaults))
+ defaults = list(map(lambda name: "=%s" % repr(name), defaults))
defaults = [""] * (len(realArgs)-len(defaults)) + defaults
items = map(lambda arg, dflt: arg+dflt, realArgs, defaults)
if fob.func_code.co_flags & 0x4:
Index: EditorWindow.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/EditorWindow.py,v
retrieving revision 1.69
retrieving revision 1.69.2.1
diff -u -d -r1.69 -r1.69.2.1
--- EditorWindow.py 12 Jun 2005 05:19:23 -0000 1.69
+++ EditorWindow.py 10 Oct 2005 00:05:30 -0000 1.69.2.1
@@ -6,6 +6,7 @@
from Tkinter import *
import tkSimpleDialog
import tkMessageBox
+from MultiCall import MultiCallCreator
import webbrowser
import idlever
@@ -89,7 +90,8 @@
self.vbar = vbar = Scrollbar(top, name='vbar')
self.text_frame = text_frame = Frame(top)
self.width = idleConf.GetOption('main','EditorWindow','width')
- self.text = text = Text(text_frame, name='text', padx=5, wrap='none',
+ self.text = text = MultiCallCreator(Text)(
+ text_frame, name='text', padx=5, wrap='none',
foreground=idleConf.GetHighlight(currentTheme,
'normal',fgBg='fg'),
background=idleConf.GetHighlight(currentTheme,
@@ -264,8 +266,9 @@
self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
self.status_bar.pack(side=BOTTOM, fill=X)
- self.text.bind('<KeyRelease>', self.set_line_and_column)
- self.text.bind('<ButtonRelease>', self.set_line_and_column)
+ self.text.bind("<<set-line-and-column>>", self.set_line_and_column)
+ self.text.event_add("<<set-line-and-column>>",
+ "<KeyRelease>", "<ButtonRelease>")
self.text.after_idle(self.set_line_and_column)
def set_line_and_column(self, event=None):
@@ -355,6 +358,9 @@
return "break"
def copy(self,event):
+ if not self.text.tag_ranges("sel"):
+ # There is no selection, so do nothing and maybe interrupt.
+ return
self.text.event_generate("<<Copy>>")
return "break"
@@ -557,14 +563,28 @@
idleConf.GetOption('main','EditorWindow','font-size'),
fontWeight))
- def ResetKeybindings(self):
- "Update the keybindings if they are changed"
+ def RemoveKeybindings(self):
+ "Remove the keybindings before they are changed."
# Called from configDialog.py
self.Bindings.default_keydefs=idleConf.GetCurrentKeySet()
keydefs = self.Bindings.default_keydefs
for event, keylist in keydefs.items():
- self.text.event_delete(event)
+ self.text.event_delete(event, *keylist)
+ for extensionName in self.get_standard_extension_names():
+ keydefs = idleConf.GetExtensionBindings(extensionName)
+ if keydefs:
+ for event, keylist in keydefs.items():
+ self.text.event_delete(event, *keylist)
+
+ def ApplyKeybindings(self):
+ "Update the keybindings after they are changed"
+ # Called from configDialog.py
+ self.Bindings.default_keydefs=idleConf.GetCurrentKeySet()
self.apply_bindings()
+ for extensionName in self.get_standard_extension_names():
+ keydefs = idleConf.GetExtensionBindings(extensionName)
+ if keydefs:
+ self.apply_bindings(keydefs)
#update menu accelerators
menuEventDict={}
for menu in self.Bindings.menudefs:
@@ -1064,17 +1084,28 @@
# open/close first need to find the last stmt
lno = index2line(text.index('insert'))
y = PyParse.Parser(self.indentwidth, self.tabwidth)
- for context in self.num_context_lines:
- startat = max(lno - context, 1)
- startatindex = repr(startat) + ".0"
+ if not self.context_use_ps1:
+ for context in self.num_context_lines:
+ startat = max(lno - context, 1)
+ startatindex = `startat` + ".0"
+ rawtext = text.get(startatindex, "insert")
+ y.set_str(rawtext)
+ bod = y.find_good_parse_start(
+ self.context_use_ps1,
+ self._build_char_in_string_func(startatindex))
+ if bod is not None or startat == 1:
+ break
+ y.set_lo(bod or 0)
+ else:
+ r = text.tag_prevrange("console", "insert")
+ if r:
+ startatindex = r[1]
+ else:
+ startatindex = "1.0"
rawtext = text.get(startatindex, "insert")
y.set_str(rawtext)
- bod = y.find_good_parse_start(
- self.context_use_ps1,
- self._build_char_in_string_func(startatindex))
- if bod is not None or startat == 1:
- break
- y.set_lo(bod or 0)
+ y.set_lo(0)
+
c = y.get_continuation_type()
if c != PyParse.C_NONE:
# The current stmt hasn't ended yet.
Index: ParenMatch.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/ParenMatch.py,v
retrieving revision 1.8
retrieving revision 1.8.6.1
diff -u -d -r1.8 -r1.8.6.1
--- ParenMatch.py 12 Feb 2004 17:35:09 -0000 1.8
+++ ParenMatch.py 10 Oct 2005 00:05:30 -0000 1.8.6.1
@@ -3,17 +3,14 @@
When you hit a right paren, the cursor should move briefly to the left
paren. Paren here is used generically; the matching applies to
parentheses, square brackets, and curly braces.
-
-WARNING: This extension will fight with the CallTips extension,
-because they both are interested in the KeyRelease-parenright event.
-We'll have to fix IDLE to do something reasonable when two or more
-extensions what to capture the same event.
"""
-import PyParse
-from EditorWindow import EditorWindow, index2line
+from HyperParser import HyperParser
from configHandler import idleConf
+keysym_opener = {"parenright":'(', "bracketright":'[', "braceright":'{'}
+CHECK_DELAY = 100 # miliseconds
+
class ParenMatch:
"""Highlight matching parentheses
@@ -31,7 +28,6 @@
expression from the left paren to the right paren.
TODO:
- - fix interaction with CallTips
- extend IDLE with configuration dialog to change options
- implement rest of Emacs highlight styles (see below)
- print mismatch warning in IDLE status window
@@ -41,7 +37,11 @@
to the right of a right paren. I don't know how to do that in Tk,
so I haven't bothered.
"""
- menudefs = []
+ menudefs = [
+ ('edit', [
+ ("Show surrounding parens", "<<flash-paren>>"),
+ ])
+ ]
STYLE = idleConf.GetOption('extensions','ParenMatch','style',
default='expression')
FLASH_DELAY = idleConf.GetOption('extensions','ParenMatch','flash-delay',
@@ -50,14 +50,36 @@
BELL = idleConf.GetOption('extensions','ParenMatch','bell',
type='bool',default=1)
+ RESTORE_VIRTUAL_EVENT_NAME = "<<parenmatch-check-restore>>"
+ # We want the restore event be called before the usual return and
+ # backspace events.
+ RESTORE_SEQUENCES = ("<KeyPress>", "<ButtonPress>",
+ "<Key-Return>", "<Key-BackSpace>")
+
def __init__(self, editwin):
self.editwin = editwin
self.text = editwin.text
- self.finder = LastOpenBracketFinder(editwin)
+ # Bind the check-restore event to the function restore_event,
+ # so that we can then use activate_restore (which calls event_add)
+ # and deactivate_restore (which calls event_delete).
+ editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME,
+ self.restore_event)
self.counter = 0
- self._restore = None
+ self.is_restore_active = 0
self.set_style(self.STYLE)
+ def activate_restore(self):
+ if not self.is_restore_active:
+ for seq in self.RESTORE_SEQUENCES:
+ self.text.event_add(self.RESTORE_VIRTUAL_EVENT_NAME, seq)
+ self.is_restore_active = True
+
+ def deactivate_restore(self):
+ if self.is_restore_active:
+ for seq in self.RESTORE_SEQUENCES:
+ self.text.event_delete(self.RESTORE_VIRTUAL_EVENT_NAME, seq)
+ self.is_restore_active = False
+
def set_style(self, style):
self.STYLE = style
if style == "default":
@@ -67,23 +89,38 @@
self.create_tag = self.create_tag_expression
self.set_timeout = self.set_timeout_none
- def flash_open_paren_event(self, event):
- index = self.finder.find(keysym_type(event.keysym))
- if index is None:
+ def flash_paren_event(self, event):
+ indices = HyperParser(self.editwin, "insert").get_surrounding_brackets()
+ if indices is None:
self.warn_mismatched()
return
- self._restore = 1
- self.create_tag(index)
+ self.activate_restore()
+ self.create_tag(indices)
+ self.set_timeout_last()
+
+ def paren_closed_event(self, event):
+ # If it was a shortcut and not really a closing paren, quit.
+ if self.text.get("insert-1c") not in (')',']','}'):
+ return
+ hp = HyperParser(self.editwin, "insert-1c")
+ if not hp.is_in_code():
+ return
+ indices = hp.get_surrounding_brackets(keysym_opener[event.keysym], True)
+ if indices is None:
+ self.warn_mismatched()
+ return
+ self.activate_restore()
+ self.create_tag(indices)
self.set_timeout()
- def check_restore_event(self, event=None):
- if self._restore:
- self.text.tag_delete("paren")
- self._restore = None
+ def restore_event(self, event=None):
+ self.text.tag_delete("paren")
+ self.deactivate_restore()
+ self.counter += 1 # disable the last timer, if there is one.
def handle_restore_timer(self, timer_count):
- if timer_count + 1 == self.counter:
- self.check_restore_event()
+ if timer_count == self.counter:
+ self.restore_event()
def warn_mismatched(self):
if self.BELL:
@@ -92,87 +129,44 @@
# any one of the create_tag_XXX methods can be used depending on
# the style
- def create_tag_default(self, index):
+ def create_tag_default(self, indices):
"""Highlight the single paren that matches"""
- self.text.tag_add("paren", index)
+ self.text.tag_add("paren", indices[0])
self.text.tag_config("paren", self.HILITE_CONFIG)
- def create_tag_expression(self, index):
+ def create_tag_expression(self, indices):
"""Highlight the entire expression"""
- self.text.tag_add("paren", index, "insert")
+ if self.text.get(indices[1]) in (')', ']', '}'):
+ rightindex = indices[1]+"+1c"
+ else:
+ rightindex = indices[1]
+ self.text.tag_add("paren", indices[0], rightindex)
self.text.tag_config("paren", self.HILITE_CONFIG)
# any one of the set_timeout_XXX methods can be used depending on
# the style
def set_timeout_none(self):
- """Highlight will remain until user input turns it off"""
- pass
+ """Highlight will remain until user input turns it off
+ or the insert has moved"""
+ # After CHECK_DELAY, call a function which disables the "paren" tag
+ # if the event is for the most recent timer and the insert has changed,
+ # or schedules another call for itself.
+ self.counter += 1
+ def callme(callme, self=self, c=self.counter,
+ index=self.text.index("insert")):
+ if index != self.text.index("insert"):
+ self.handle_restore_timer(c)
+ else:
+ self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
+ self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
def set_timeout_last(self):
"""The last highlight created will be removed after .5 sec"""
# associate a counter with an event; only disable the "paren"
# tag if the event is for the most recent timer.
+ self.counter += 1
self.editwin.text_frame.after(self.FLASH_DELAY,
lambda self=self, c=self.counter: \
self.handle_restore_timer(c))
- self.counter = self.counter + 1
-
-def keysym_type(ks):
- # Not all possible chars or keysyms are checked because of the
- # limited context in which the function is used.
- if ks == "parenright" or ks == "(":
- return "paren"
- if ks == "bracketright" or ks == "[":
- return "bracket"
- if ks == "braceright" or ks == "{":
- return "brace"
-
-class LastOpenBracketFinder:
- num_context_lines = EditorWindow.num_context_lines
- indentwidth = EditorWindow.indentwidth
- tabwidth = EditorWindow.tabwidth
- context_use_ps1 = EditorWindow.context_use_ps1
- def __init__(self, editwin):
- self.editwin = editwin
- self.text = editwin.text
-
- def _find_offset_in_buf(self, lno):
- y = PyParse.Parser(self.indentwidth, self.tabwidth)
- for context in self.num_context_lines:
- startat = max(lno - context, 1)
- startatindex = repr(startat) + ".0"
- # rawtext needs to contain everything up to the last
- # character, which was the close paren. the parser also
- # requires that the last line ends with "\n"
- rawtext = self.text.get(startatindex, "insert")[:-1] + "\n"
- y.set_str(rawtext)
- bod = y.find_good_parse_start(
- self.context_use_ps1,
- self._build_char_in_string_func(startatindex))
- if bod is not None or startat == 1:
- break
- y.set_lo(bod or 0)
- i = y.get_last_open_bracket_pos()
- return i, y.str
-
- def find(self, right_keysym_type):
- """Return the location of the last open paren"""
- lno = index2line(self.text.index("insert"))
- i, buf = self._find_offset_in_buf(lno)
- if i is None \
- or keysym_type(buf[i]) != right_keysym_type:
- return None
- lines_back = buf[i:].count("\n") - 1
- # subtract one for the "\n" added to please the parser
- upto_open = buf[:i]
- j = upto_open.rfind("\n") + 1 # offset of column 0 of line
- offset = i - j
- return "%d.%d" % (lno - lines_back, offset)
-
- def _build_char_in_string_func(self, startindex):
- def inner(offset, startindex=startindex,
- icis=self.editwin.is_char_in_string):
- return icis(startindex + "%dc" % offset)
- return inner
Index: PyParse.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/PyParse.py,v
retrieving revision 1.5
retrieving revision 1.5.14.1
diff -u -d -r1.5 -r1.5.14.1
--- PyParse.py 17 Sep 2002 03:55:13 -0000 1.5
+++ PyParse.py 10 Oct 2005 00:05:30 -0000 1.5.14.1
@@ -13,9 +13,7 @@
_synchre = re.compile(r"""
^
[ \t]*
- (?: if
- | for
- | while
+ (?: while
| else
| def
| return
@@ -144,29 +142,11 @@
# This will be reliable iff given a reliable is_char_in_string
# function, meaning that when it says "no", it's absolutely
# guaranteed that the char is not in a string.
- #
- # Ack, hack: in the shell window this kills us, because there's
- # no way to tell the differences between output, >>> etc and
- # user input. Indeed, IDLE's first output line makes the rest
- # look like it's in an unclosed paren!:
- # Python 1.5.2 (#0, Apr 13 1999, ...
- def find_good_parse_start(self, use_ps1, is_char_in_string=None,
+ def find_good_parse_start(self, is_char_in_string=None,
_synchre=_synchre):
str, pos = self.str, None
- if use_ps1:
- # shell window
- ps1 = '\n' + sys.ps1
- i = str.rfind(ps1)
- if i >= 0:
- pos = i + len(ps1)
- # make it look like there's a newline instead
- # of ps1 at the start -- hacking here once avoids
- # repeated hackery later
- self.str = str[:pos-1] + '\n' + str[pos:]
- return pos
- # File window -- real work.
if not is_char_in_string:
# no clue -- make the caller pass everything
return None
@@ -355,6 +335,11 @@
# Creates:
# self.stmt_start, stmt_end
# slice indices of last interesting stmt
+ # self.stmt_bracketing
+ # the bracketing structure of the last interesting stmt;
+ # for example, for the statement "say(boo) or die", stmt_bracketing
+ # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are
+ # treated as brackets, for the matter.
# self.lastch
# last non-whitespace character before optional trailing
# comment
@@ -396,6 +381,7 @@
lastch = ""
stack = [] # stack of open bracket indices
push_stack = stack.append
+ bracketing = [(p, 0)]
while p < q:
# suck up all except ()[]{}'"#\\
m = _chew_ordinaryre(str, p, q)
@@ -416,6 +402,7 @@
if ch in "([{":
push_stack(p)
+ bracketing.append((p, len(stack)))
lastch = ch
p = p+1
continue
@@ -425,6 +412,7 @@
del stack[-1]
lastch = ch
p = p+1
+ bracketing.append((p, len(stack)))
continue
if ch == '"' or ch == "'":
@@ -435,14 +423,18 @@
# strings to a couple of characters per line. study1
# also needed to keep track of newlines, and we don't
# have to.
+ bracketing.append((p, len(stack)+1))
lastch = ch
p = _match_stringre(str, p, q).end()
+ bracketing.append((p, len(stack)))
continue
if ch == '#':
# consume comment and trailing newline
+ bracketing.append((p, len(stack)+1))
p = str.find('\n', p, q) + 1
assert p > 0
+ bracketing.append((p, len(stack)))
continue
assert ch == '\\'
@@ -458,6 +450,7 @@
self.lastch = lastch
if stack:
self.lastopenbracketpos = stack[-1]
+ self.stmt_bracketing = tuple(bracketing)
# Assuming continuation is C_BRACKET, return the number
# of spaces the next line should be indented.
@@ -582,3 +575,12 @@
def get_last_open_bracket_pos(self):
self._study2()
return self.lastopenbracketpos
+
+ # the structure of the bracketing of the last interesting statement,
+ # in the format defined in _study2, or None if the text didn't contain
+ # anything
+ stmt_bracketing = None
+
+ def get_last_stmt_bracketing(self):
+ self._study2()
+ return self.stmt_bracketing
Index: PyShell.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/PyShell.py,v
retrieving revision 1.99
retrieving revision 1.99.2.1
diff -u -d -r1.99 -r1.99.2.1
--- PyShell.py 1 Sep 2005 00:39:02 -0000 1.99
+++ PyShell.py 10 Oct 2005 00:05:30 -0000 1.99.2.1
@@ -1091,11 +1091,12 @@
self.recall(self.text.get(next[0], next[1]), event)
return "break"
# No stdin mark -- just get the current line, less any prompt
- line = self.text.get("insert linestart", "insert lineend")
- last_line_of_prompt = sys.ps1.split('\n')[-1]
- if line.startswith(last_line_of_prompt):
- line = line[len(last_line_of_prompt):]
- self.recall(line, event)
+ indices = self.text.tag_nextrange("console", "insert linestart")
+ if indices and \
+ self.text.compare(indices[0], "<=", "insert linestart"):
+ self.recall(self.text.get(indices[1], "insert lineend"), event)
+ else:
+ self.recall(self.text.get("insert linestart", "insert lineend"), event)
return "break"
# If we're between the beginning of the line and the iomark, i.e.
# in the prompt area, move to the end of the prompt
Index: config-extensions.def
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/config-extensions.def,v
retrieving revision 1.15
retrieving revision 1.15.6.1
diff -u -d -r1.15 -r1.15.6.1
--- config-extensions.def 6 Jun 2004 01:29:22 -0000 1.15
+++ config-extensions.def 10 Oct 2005 00:05:30 -0000 1.15.6.1
@@ -52,22 +52,30 @@
[CallTips]
enable=1
+[CallTips_cfgBindings]
+force-open-calltip=<Control-Key-backslash>
[CallTips_bindings]
-paren-open=<Key-parenleft>
-paren-close=<Key-parenright>
-check-calltip-cancel=<KeyRelease>
-calltip-cancel=<ButtonPress> <Key-Escape>
+try-open-calltip=<KeyRelease-parenleft>
+refresh-calltip=<KeyRelease-parenright> <KeyRelease-0>
[ParenMatch]
-enable=0
+enable=1
style= expression
flash-delay= 500
bell= 1
-hilite-foreground= black
-hilite-background= #43cd80
+[ParenMatch_cfgBindings]
+flash-paren=<Control-Key-0>
[ParenMatch_bindings]
-flash-open-paren=<KeyRelease-parenright> <KeyRelease-bracketright> <KeyRelease-braceright>
-check-restore=<KeyPress>
+paren-closed=<KeyRelease-parenright> <KeyRelease-bracketright> <KeyRelease-braceright>
+
+[AutoComplete]
+enable=1
+popupwait=0
+[AutoComplete_cfgBindings]
+force-open-completions=<Control-Key-space>
+[AutoComplete_bindings]
+autocomplete=<Key-Tab>
+try-open-completions=<KeyRelease-period> <KeyRelease-slash> <KeyRelease-backslash>
[CodeContext]
enable=1
Index: configDialog.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/configDialog.py,v
retrieving revision 1.62
retrieving revision 1.62.2.1
diff -u -d -r1.62 -r1.62.2.1
--- configDialog.py 22 Jul 2005 21:49:29 -0000 1.62
+++ configDialog.py 10 Oct 2005 00:05:30 -0000 1.62.2.1
@@ -1106,6 +1106,13 @@
idleConf.userCfg[configType].Save()
self.ResetChangedItems() #clear the changed items dict
+ def DeactivateCurrentConfig(self):
+ #Before a config is saved, some cleanup of current
+ #config must be done - remove the previous keybindings
+ winInstances=self.parent.instance_dict.keys()
+ for instance in winInstances:
+ instance.RemoveKeybindings()
+
def ActivateConfigChanges(self):
"Dynamically apply configuration changes"
winInstances=self.parent.instance_dict.keys()
@@ -1113,7 +1120,7 @@
instance.ResetColorizer()
instance.ResetFont()
instance.set_notabs_indentwidth()
- instance.ResetKeybindings()
+ instance.ApplyKeybindings()
instance.reset_help_menu_entries()
def Cancel(self):
@@ -1124,6 +1131,7 @@
self.destroy()
def Apply(self):
+ self.DeactivateCurrentConfig()
self.SaveAllChangedConfigs()
self.ActivateConfigChanges()
Index: run.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/run.py,v
retrieving revision 1.32
retrieving revision 1.32.2.1
diff -u -d -r1.32 -r1.32.2.1
--- run.py 5 May 2005 23:29:54 -0000 1.32
+++ run.py 10 Oct 2005 00:05:31 -0000 1.32.2.1
@@ -9,6 +9,8 @@
import Queue
import CallTips
+import AutoComplete
+
import RemoteDebugger
import RemoteObjectBrowser
import StackViewer
@@ -275,6 +277,7 @@
self.rpchandler = rpchandler
self.locals = __main__.__dict__
self.calltip = CallTips.CallTips()
+ self.autocomplete = AutoComplete.AutoComplete()
def runcode(self, code):
try:
@@ -305,6 +308,9 @@
def get_the_calltip(self, name):
return self.calltip.fetch_tip(name)
+ def get_the_completion_list(self, what, mode):
+ return self.autocomplete.fetch_completions(what, mode)
+
def stackviewer(self, flist_oid=None):
if self.usr_exc_info:
typ, val, tb = self.usr_exc_info
More information about the Python-checkins
mailing list