mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	svn+ssh://pythondev@svn.python.org/python/trunk
........
  r53624 | peter.astrand | 2007-02-02 20:06:36 +0100 (Fri, 02 Feb 2007) | 1 line
  We had several if statements checking the value of a fd. This is unsafe, since valid fds might be zero. We should check for not None instead.
........
  r53635 | kurt.kaiser | 2007-02-05 07:03:18 +0100 (Mon, 05 Feb 2007) | 2 lines
  Add 'raw' support to configHandler. Patch 1650174 Tal Einat.
........
  r53641 | kurt.kaiser | 2007-02-06 00:02:16 +0100 (Tue, 06 Feb 2007) | 5 lines
  1. Calltips now 'handle' tuples in the argument list (display '<tuple>' :)
     Suggested solution by Christos Georgiou, Bug 791968.
  2. Clean up tests, were not failing when they should have been.
  4. Remove some camelcase and an unneeded try/except block.
........
  r53644 | kurt.kaiser | 2007-02-06 04:21:40 +0100 (Tue, 06 Feb 2007) | 2 lines
  Clean up ModifiedInterpreter.runcode() structure
........
  r53646 | peter.astrand | 2007-02-06 16:37:50 +0100 (Tue, 06 Feb 2007) | 1 line
  Applied patch 1124861.3.patch to solve bug #1124861: Automatically create pipes on Windows, if GetStdHandle fails. Will backport.
........
  r53648 | lars.gustaebel | 2007-02-06 19:38:13 +0100 (Tue, 06 Feb 2007) | 4 lines
  Patch #1652681: create nonexistent files in append mode and
  allow appending to empty files.
........
  r53649 | kurt.kaiser | 2007-02-06 20:09:43 +0100 (Tue, 06 Feb 2007) | 4 lines
  Updated patch (CodeContext.061217.patch) to
  [ 1362975 ] CodeContext - Improved text indentation
  Tal Einat 16Dec06
........
  r53650 | kurt.kaiser | 2007-02-06 20:21:19 +0100 (Tue, 06 Feb 2007) | 2 lines
  narrow exception per [ 1540849 ] except too broad
........
  r53653 | kurt.kaiser | 2007-02-07 04:39:41 +0100 (Wed, 07 Feb 2007) | 4 lines
  [ 1621265 ] Auto-completion list placement
  Move AC window below input line unless not enough space, then put it above.
  Patch: Tal Einat
........
  r53654 | kurt.kaiser | 2007-02-07 09:07:13 +0100 (Wed, 07 Feb 2007) | 2 lines
  Handle AttributeError during calltip lookup
........
  r53656 | raymond.hettinger | 2007-02-07 21:08:22 +0100 (Wed, 07 Feb 2007) | 3 lines
  SF #1615701:  make d.update(m) honor __getitem__() and keys() in dict subclasses
........
  r53658 | raymond.hettinger | 2007-02-07 22:04:20 +0100 (Wed, 07 Feb 2007) | 1 line
  SF: 1397711 Set docs conflated immutable and hashable
........
  r53660 | raymond.hettinger | 2007-02-07 22:42:17 +0100 (Wed, 07 Feb 2007) | 1 line
  Check for a common user error with defaultdict().
........
  r53662 | raymond.hettinger | 2007-02-07 23:24:07 +0100 (Wed, 07 Feb 2007) | 1 line
  Bug #1575169: operator.isSequenceType() now returns False for subclasses of dict.
........
  r53664 | raymond.hettinger | 2007-02-08 00:49:03 +0100 (Thu, 08 Feb 2007) | 1 line
  Silence compiler warning
........
  r53666 | raymond.hettinger | 2007-02-08 01:07:32 +0100 (Thu, 08 Feb 2007) | 1 line
  Do not let overflows in enumerate() and count() pass silently.
........
  r53668 | raymond.hettinger | 2007-02-08 01:50:39 +0100 (Thu, 08 Feb 2007) | 1 line
  Bypass set specific optimizations for set and frozenset subclasses.
........
  r53670 | raymond.hettinger | 2007-02-08 02:42:35 +0100 (Thu, 08 Feb 2007) | 1 line
  Fix docstring bug
........
  r53671 | martin.v.loewis | 2007-02-08 10:13:36 +0100 (Thu, 08 Feb 2007) | 3 lines
  Bug #1653736: Complain about keyword arguments to time.isoformat.
  Will backport to 2.5.
........
  r53679 | kurt.kaiser | 2007-02-08 23:58:18 +0100 (Thu, 08 Feb 2007) | 6 lines
  Corrected some bugs in AutoComplete.  Also, Page Up/Down in ACW implemented;
  mouse and cursor selection in ACWindow implemented; double Tab inserts current
  selection and closes ACW (similar to double-click and Return); scroll wheel now
  works in ACW.  Added AutoComplete instructions to IDLE Help.
........
  r53689 | martin.v.loewis | 2007-02-09 13:19:32 +0100 (Fri, 09 Feb 2007) | 3 lines
  Bug #1653736: Properly discard third argument to slot_nb_inplace_power.
  Will backport.
........
  r53691 | martin.v.loewis | 2007-02-09 13:36:48 +0100 (Fri, 09 Feb 2007) | 4 lines
  Bug #1600860: Search for shared python library in LIBDIR, not
  lib/python/config, on "linux" and "gnu" systems.
  Will backport.
........
  r53693 | martin.v.loewis | 2007-02-09 13:58:49 +0100 (Fri, 09 Feb 2007) | 2 lines
  Update broken link. Will backport to 2.5.
........
  r53697 | georg.brandl | 2007-02-09 19:48:41 +0100 (Fri, 09 Feb 2007) | 2 lines
  Bug #1656078: typo in in profile docs.
........
  r53731 | brett.cannon | 2007-02-11 06:36:00 +0100 (Sun, 11 Feb 2007) | 3 lines
  Change a very minor inconsistency (that is purely cosmetic) in the AST
  definition.
........
  r53735 | skip.montanaro | 2007-02-11 19:24:37 +0100 (Sun, 11 Feb 2007) | 1 line
  fix trace.py --ignore-dir
........
  r53741 | brett.cannon | 2007-02-11 20:44:41 +0100 (Sun, 11 Feb 2007) | 3 lines
  Check in changed Python-ast.c from a cosmetic change to Python.asdl (in
  r53731).
........
  r53751 | brett.cannon | 2007-02-12 04:51:02 +0100 (Mon, 12 Feb 2007) | 5 lines
  Modify Parser/asdl_c.py so that the __version__ number for Python/Python-ast.c
  is specified at the top of the file.  Also add a note that Python/Python-ast.c
  needs to be committed separately after a change to the AST grammar to capture
  the revision number of the change (which is what __version__ is set to).
........
  r53752 | lars.gustaebel | 2007-02-12 10:25:53 +0100 (Mon, 12 Feb 2007) | 3 lines
  Bug #1656581: Point out that external file objects are supposed to be
  at position 0.
........
  r53754 | martin.v.loewis | 2007-02-12 13:21:10 +0100 (Mon, 12 Feb 2007) | 3 lines
  Patch 1463026: Support default namespace in XMLGenerator.
  Fixes #847665. Will backport.
........
  r53757 | armin.rigo | 2007-02-12 17:23:24 +0100 (Mon, 12 Feb 2007) | 4 lines
  Fix the line to what is my guess at the original author's meaning.
  (The line has no effect anyway, but is present because it's
  customary call the base class __init__).
........
  r53763 | martin.v.loewis | 2007-02-13 09:34:45 +0100 (Tue, 13 Feb 2007) | 3 lines
  Patch #685268: Consider a package's __path__ in imputil.
  Will backport.
........
  r53765 | martin.v.loewis | 2007-02-13 10:49:38 +0100 (Tue, 13 Feb 2007) | 2 lines
  Patch #698833: Support file decryption in zipfile.
........
  r53766 | martin.v.loewis | 2007-02-13 11:10:39 +0100 (Tue, 13 Feb 2007) | 3 lines
  Patch #1517891: Make 'a' create the file if it doesn't exist.
  Fixes #1514451.
........
  r53767 | martin.v.loewis | 2007-02-13 13:08:24 +0100 (Tue, 13 Feb 2007) | 3 lines
  Bug #1658794: Remove extraneous 'this'.
  Will backport to 2.5.
........
  r53769 | martin.v.loewis | 2007-02-13 13:14:19 +0100 (Tue, 13 Feb 2007) | 3 lines
  Patch #1657276: Make NETLINK_DNRTMSG conditional.
  Will backport.
........
  r53771 | lars.gustaebel | 2007-02-13 17:09:24 +0100 (Tue, 13 Feb 2007) | 4 lines
  Patch #1647484: Renamed GzipFile's filename attribute to name. The
  filename attribute is still accessible as a property that emits a
  DeprecationWarning.
........
  r53772 | lars.gustaebel | 2007-02-13 17:24:00 +0100 (Tue, 13 Feb 2007) | 3 lines
  Strip the '.gz' extension from the filename that is written to the
  gzip header.
........
  r53774 | martin.v.loewis | 2007-02-14 11:07:37 +0100 (Wed, 14 Feb 2007) | 2 lines
  Patch #1432399: Add HCI sockets.
........
  r53775 | martin.v.loewis | 2007-02-14 12:30:07 +0100 (Wed, 14 Feb 2007) | 2 lines
  Update 1432399 to removal of _BT_SOCKADDR_MEMB.
........
  r53776 | martin.v.loewis | 2007-02-14 12:30:56 +0100 (Wed, 14 Feb 2007) | 3 lines
  Ignore directory time stamps when considering
  whether to rerun libffi configure.
........
  r53778 | lars.gustaebel | 2007-02-14 15:45:12 +0100 (Wed, 14 Feb 2007) | 4 lines
  A missing binary mode in AppendTest caused failures in Windows
  Buildbot.
........
  r53782 | martin.v.loewis | 2007-02-15 10:51:35 +0100 (Thu, 15 Feb 2007) | 2 lines
  Patch #1397848: add the reasoning behind no-resize-on-shrinkage.
........
  r53783 | georg.brandl | 2007-02-15 11:37:59 +0100 (Thu, 15 Feb 2007) | 2 lines
  Make functools.wraps() docs a bit clearer.
........
  r53785 | georg.brandl | 2007-02-15 12:29:04 +0100 (Thu, 15 Feb 2007) | 2 lines
  Patch #1494140: Add documentation for the new struct.Struct object.
........
  r53787 | georg.brandl | 2007-02-15 12:29:55 +0100 (Thu, 15 Feb 2007) | 2 lines
  Add missing \versionadded.
........
  r53800 | brett.cannon | 2007-02-15 23:54:39 +0100 (Thu, 15 Feb 2007) | 11 lines
  Update the encoding package's search function to use absolute imports when
  calling __import__.  This helps make the expected search locations for encoding
  modules be more explicit.
  One could use an explicit value for __path__ when making the call to __import__
  to force the exact location searched for encodings.  This would give the most
  strict search path possible if one is worried about malicious code being
  imported.  The unfortunate side-effect of that is that if __path__ was modified
  on 'encodings' on purpose in a safe way it would not be picked up in future
  __import__ calls.
........
  r53801 | brett.cannon | 2007-02-16 20:33:01 +0100 (Fri, 16 Feb 2007) | 2 lines
  Make the __import__ call in encodings.__init__ absolute with a level 0 call.
........
  r53809 | vinay.sajip | 2007-02-16 23:36:24 +0100 (Fri, 16 Feb 2007) | 1 line
  Minor fix for currentframe (SF #1652788).
........
  r53818 | raymond.hettinger | 2007-02-19 03:03:19 +0100 (Mon, 19 Feb 2007) | 3 lines
  Extend work on revision 52962:  Eliminate redundant calls to PyObject_Hash().
........
  r53820 | raymond.hettinger | 2007-02-19 05:08:43 +0100 (Mon, 19 Feb 2007) | 1 line
  Add merge() function to heapq.
........
  r53821 | raymond.hettinger | 2007-02-19 06:28:28 +0100 (Mon, 19 Feb 2007) | 1 line
  Add tie-breaker count to preserve sort stability.
........
  r53822 | raymond.hettinger | 2007-02-19 07:59:32 +0100 (Mon, 19 Feb 2007) | 1 line
  Use C heapreplace() instead of slower _siftup() in pure python.
........
  r53823 | raymond.hettinger | 2007-02-19 08:30:21 +0100 (Mon, 19 Feb 2007) | 1 line
  Add test for merge stability
........
  r53824 | raymond.hettinger | 2007-02-19 10:14:10 +0100 (Mon, 19 Feb 2007) | 1 line
  Provide an example of defaultdict with non-zero constant factory function.
........
  r53825 | lars.gustaebel | 2007-02-19 10:54:47 +0100 (Mon, 19 Feb 2007) | 2 lines
  Moved misplaced news item.
........
  r53826 | martin.v.loewis | 2007-02-19 11:55:19 +0100 (Mon, 19 Feb 2007) | 3 lines
  Patch #1490190: posixmodule now includes os.chflags() and os.lchflags()
  functions on platforms where the underlying system calls are available.
........
  r53827 | raymond.hettinger | 2007-02-19 19:15:04 +0100 (Mon, 19 Feb 2007) | 1 line
  Fixup docstrings for merge().
........
  r53829 | raymond.hettinger | 2007-02-19 21:44:04 +0100 (Mon, 19 Feb 2007) | 1 line
  Fixup set/dict interoperability.
........
  r53837 | raymond.hettinger | 2007-02-21 06:20:38 +0100 (Wed, 21 Feb 2007) | 1 line
  Add itertools.izip_longest().
........
  r53838 | raymond.hettinger | 2007-02-21 18:22:05 +0100 (Wed, 21 Feb 2007) | 1 line
  Remove filler struct item and fix leak.
........
		
	
			
		
			
				
	
	
		
			411 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
An auto-completion window for IDLE, used by the AutoComplete extension
 | 
						|
"""
 | 
						|
from Tkinter import *
 | 
						|
from MultiCall import MC_SHIFT
 | 
						|
import AutoComplete
 | 
						|
 | 
						|
HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>"
 | 
						|
HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>")
 | 
						|
KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
 | 
						|
# We need to bind event beyond <Key> so that the function will be called
 | 
						|
# before the default specific IDLE function
 | 
						|
KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
 | 
						|
                      "<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>",
 | 
						|
                      "<Key-Prior>", "<Key-Next>")
 | 
						|
KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>"
 | 
						|
KEYRELEASE_SEQUENCE = "<KeyRelease>"
 | 
						|
LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
 | 
						|
WINCONFIG_SEQUENCE = "<Configure>"
 | 
						|
DOUBLECLICK_SEQUENCE = "<B1-Double-ButtonRelease>"
 | 
						|
 | 
						|
class AutoCompleteWindow:
 | 
						|
 | 
						|
    def __init__(self, widget):
 | 
						|
        # The widget (Text) on which we place the AutoCompleteWindow
 | 
						|
        self.widget = widget
 | 
						|
        # The widgets we create
 | 
						|
        self.autocompletewindow = self.listbox = self.scrollbar = None
 | 
						|
        # The default foreground and background of a selection. Saved because
 | 
						|
        # they are changed to the regular colors of list items when the
 | 
						|
        # completion start is not a prefix of the selected completion
 | 
						|
        self.origselforeground = self.origselbackground = None
 | 
						|
        # The list of completions
 | 
						|
        self.completions = None
 | 
						|
        # A list with more completions, or None
 | 
						|
        self.morecompletions = None
 | 
						|
        # The completion mode. Either AutoComplete.COMPLETE_ATTRIBUTES or
 | 
						|
        # AutoComplete.COMPLETE_FILES
 | 
						|
        self.mode = None
 | 
						|
        # The current completion start, on the text box (a string)
 | 
						|
        self.start = None
 | 
						|
        # The index of the start of the completion
 | 
						|
        self.startindex = None
 | 
						|
        # The last typed start, used so that when the selection changes,
 | 
						|
        # the new start will be as close as possible to the last typed one.
 | 
						|
        self.lasttypedstart = None
 | 
						|
        # Do we have an indication that the user wants the completion window
 | 
						|
        # (for example, he clicked the list)
 | 
						|
        self.userwantswindow = None
 | 
						|
        # event ids
 | 
						|
        self.hideid = self.keypressid = self.listupdateid = self.winconfigid \
 | 
						|
        = self.keyreleaseid = self.doubleclickid                         = None
 | 
						|
        # Flag set if last keypress was a tab
 | 
						|
        self.lastkey_was_tab = False
 | 
						|
 | 
						|
    def _change_start(self, newstart):
 | 
						|
        i = 0
 | 
						|
        while i < len(self.start) and i < len(newstart) and \
 | 
						|
              self.start[i] == newstart[i]:
 | 
						|
            i += 1
 | 
						|
        if i < len(self.start):
 | 
						|
            self.widget.delete("%s+%dc" % (self.startindex, i),
 | 
						|
                               "%s+%dc" % (self.startindex, len(self.start)))
 | 
						|
        if i < len(newstart):
 | 
						|
            self.widget.insert("%s+%dc" % (self.startindex, i),
 | 
						|
                               newstart[i:])
 | 
						|
        self.start = newstart
 | 
						|
 | 
						|
    def _binary_search(self, s):
 | 
						|
        """Find the first index in self.completions where completions[i] is
 | 
						|
        greater or equal to s, or the last index if there is no such
 | 
						|
        one."""
 | 
						|
        i = 0; j = len(self.completions)
 | 
						|
        while j > i:
 | 
						|
            m = (i + j) // 2
 | 
						|
            if self.completions[m] >= s:
 | 
						|
                j = m
 | 
						|
            else:
 | 
						|
                i = m + 1
 | 
						|
        return min(i, len(self.completions)-1)
 | 
						|
 | 
						|
    def _complete_string(self, s):
 | 
						|
        """Assuming that s is the prefix of a string in self.completions,
 | 
						|
        return the longest string which is a prefix of all the strings which
 | 
						|
        s is a prefix of them. If s is not a prefix of a string, return s."""
 | 
						|
        first = self._binary_search(s)
 | 
						|
        if self.completions[first][:len(s)] != s:
 | 
						|
            # There is not even one completion which s is a prefix of.
 | 
						|
            return s
 | 
						|
        # Find the end of the range of completions where s is a prefix of.
 | 
						|
        i = first + 1
 | 
						|
        j = len(self.completions)
 | 
						|
        while j > i:
 | 
						|
            m = (i + j) // 2
 | 
						|
            if self.completions[m][:len(s)] != s:
 | 
						|
                j = m
 | 
						|
            else:
 | 
						|
                i = m + 1
 | 
						|
        last = i-1
 | 
						|
 | 
						|
        # We should return the maximum prefix of first and last
 | 
						|
        i = len(s)
 | 
						|
        while len(self.completions[first]) > i and \
 | 
						|
              len(self.completions[last]) > i and \
 | 
						|
              self.completions[first][i] == self.completions[last][i]:
 | 
						|
            i += 1
 | 
						|
        return self.completions[first][:i]
 | 
						|
 | 
						|
    def _selection_changed(self):
 | 
						|
        """Should be called when the selection of the Listbox has changed.
 | 
						|
        Updates the Listbox display and calls _change_start."""
 | 
						|
        cursel = int(self.listbox.curselection()[0])
 | 
						|
 | 
						|
        self.listbox.see(cursel)
 | 
						|
 | 
						|
        lts = self.lasttypedstart
 | 
						|
        selstart = self.completions[cursel]
 | 
						|
        if self._binary_search(lts) == cursel:
 | 
						|
            newstart = lts
 | 
						|
        else:
 | 
						|
            i = 0
 | 
						|
            while i < len(lts) and i < len(selstart) and lts[i] == selstart[i]:
 | 
						|
                i += 1
 | 
						|
            newstart = selstart[:i]
 | 
						|
        self._change_start(newstart)
 | 
						|
 | 
						|
        if self.completions[cursel][:len(self.start)] == self.start:
 | 
						|
            # start is a prefix of the selected completion
 | 
						|
            self.listbox.configure(selectbackground=self.origselbackground,
 | 
						|
                                   selectforeground=self.origselforeground)
 | 
						|
        else:
 | 
						|
            self.listbox.configure(selectbackground=self.listbox.cget("bg"),
 | 
						|
                                   selectforeground=self.listbox.cget("fg"))
 | 
						|
            # If there are more completions, show them, and call me again.
 | 
						|
            if self.morecompletions:
 | 
						|
                self.completions = self.morecompletions
 | 
						|
                self.morecompletions = None
 | 
						|
                self.listbox.delete(0, END)
 | 
						|
                for item in self.completions:
 | 
						|
                    self.listbox.insert(END, item)
 | 
						|
                self.listbox.select_set(self._binary_search(self.start))
 | 
						|
                self._selection_changed()
 | 
						|
 | 
						|
    def show_window(self, comp_lists, index, complete, mode, userWantsWin):
 | 
						|
        """Show the autocomplete list, bind events.
 | 
						|
        If complete is True, complete the text, and if there is exactly one
 | 
						|
        matching completion, don't open a list."""
 | 
						|
        # Handle the start we already have
 | 
						|
        self.completions, self.morecompletions = comp_lists
 | 
						|
        self.mode = mode
 | 
						|
        self.startindex = self.widget.index(index)
 | 
						|
        self.start = self.widget.get(self.startindex, "insert")
 | 
						|
        if complete:
 | 
						|
            completed = self._complete_string(self.start)
 | 
						|
            self._change_start(completed)
 | 
						|
            i = self._binary_search(completed)
 | 
						|
            if self.completions[i] == completed and \
 | 
						|
               (i == len(self.completions)-1 or
 | 
						|
                self.completions[i+1][:len(completed)] != completed):
 | 
						|
                # There is exactly one matching completion
 | 
						|
                return
 | 
						|
        self.userwantswindow = userWantsWin
 | 
						|
        self.lasttypedstart = self.start
 | 
						|
 | 
						|
        # Put widgets in place
 | 
						|
        self.autocompletewindow = acw = Toplevel(self.widget)
 | 
						|
        # Put it in a position so that it is not seen.
 | 
						|
        acw.wm_geometry("+10000+10000")
 | 
						|
        # Make it float
 | 
						|
        acw.wm_overrideredirect(1)
 | 
						|
        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
 | 
						|
            # the focus.
 | 
						|
            acw.tk.call("::tk::unsupported::MacWindowStyle", "style", acw._w,
 | 
						|
                        "help", "noActivates")
 | 
						|
        except TclError:
 | 
						|
            pass
 | 
						|
        self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL)
 | 
						|
        self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set,
 | 
						|
                                         exportselection=False, bg="white")
 | 
						|
        for item in self.completions:
 | 
						|
            listbox.insert(END, item)
 | 
						|
        self.origselforeground = listbox.cget("selectforeground")
 | 
						|
        self.origselbackground = listbox.cget("selectbackground")
 | 
						|
        scrollbar.config(command=listbox.yview)
 | 
						|
        scrollbar.pack(side=RIGHT, fill=Y)
 | 
						|
        listbox.pack(side=LEFT, fill=BOTH, expand=True)
 | 
						|
 | 
						|
        # Initialize the listbox selection
 | 
						|
        self.listbox.select_set(self._binary_search(self.start))
 | 
						|
        self._selection_changed()
 | 
						|
 | 
						|
        # bind events
 | 
						|
        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)
 | 
						|
        self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME,
 | 
						|
                                           self.keypress_event)
 | 
						|
        for seq in KEYPRESS_SEQUENCES:
 | 
						|
            self.widget.event_add(KEYPRESS_VIRTUAL_EVENT_NAME, seq)
 | 
						|
        self.keyreleaseid = self.widget.bind(KEYRELEASE_VIRTUAL_EVENT_NAME,
 | 
						|
                                             self.keyrelease_event)
 | 
						|
        self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE)
 | 
						|
        self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE,
 | 
						|
                                         self.listselect_event)
 | 
						|
        self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event)
 | 
						|
        self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE,
 | 
						|
                                          self.doubleclick_event)
 | 
						|
 | 
						|
    def winconfig_event(self, event):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
        # Position the completion list window
 | 
						|
        text = self.widget
 | 
						|
        text.see(self.startindex)
 | 
						|
        x, y, cx, cy = text.bbox(self.startindex)
 | 
						|
        acw = self.autocompletewindow
 | 
						|
        acw_width, acw_height = acw.winfo_width(), acw.winfo_height()
 | 
						|
        text_width, text_height = text.winfo_width(), text.winfo_height()
 | 
						|
        new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width))
 | 
						|
        new_y = text.winfo_rooty() + y
 | 
						|
        if (text_height - (y + cy) >= acw_height # enough height below
 | 
						|
            or y < acw_height): # not enough height above
 | 
						|
            # place acw below current line
 | 
						|
            new_y += cy
 | 
						|
        else:
 | 
						|
            # place acw above current line
 | 
						|
            new_y -= acw_height
 | 
						|
        acw.wm_geometry("+%d+%d" % (new_x, new_y))
 | 
						|
 | 
						|
    def hide_event(self, event):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
        self.hide_window()
 | 
						|
 | 
						|
    def listselect_event(self, event):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
        self.userwantswindow = True
 | 
						|
        cursel = int(self.listbox.curselection()[0])
 | 
						|
        self._change_start(self.completions[cursel])
 | 
						|
 | 
						|
    def doubleclick_event(self, event):
 | 
						|
        # Put the selected completion in the text, and close the list
 | 
						|
        cursel = int(self.listbox.curselection()[0])
 | 
						|
        self._change_start(self.completions[cursel])
 | 
						|
        self.hide_window()
 | 
						|
 | 
						|
    def keypress_event(self, event):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
        keysym = event.keysym
 | 
						|
        if hasattr(event, "mc_state"):
 | 
						|
            state = event.mc_state
 | 
						|
        else:
 | 
						|
            state = 0
 | 
						|
        if keysym != "Tab":
 | 
						|
            self.lastkey_was_tab = False
 | 
						|
        if (len(keysym) == 1 or keysym in ("underscore", "BackSpace")
 | 
						|
            or (self.mode==AutoComplete.COMPLETE_FILES and keysym in
 | 
						|
                ("period", "minus"))) \
 | 
						|
           and not (state & ~MC_SHIFT):
 | 
						|
            # Normal editing of text
 | 
						|
            if len(keysym) == 1:
 | 
						|
                self._change_start(self.start + keysym)
 | 
						|
            elif keysym == "underscore":
 | 
						|
                self._change_start(self.start + '_')
 | 
						|
            elif keysym == "period":
 | 
						|
                self._change_start(self.start + '.')
 | 
						|
            elif keysym == "minus":
 | 
						|
                self._change_start(self.start + '-')
 | 
						|
            else:
 | 
						|
                # keysym == "BackSpace"
 | 
						|
                if len(self.start) == 0:
 | 
						|
                    self.hide_window()
 | 
						|
                    return
 | 
						|
                self._change_start(self.start[:-1])
 | 
						|
            self.lasttypedstart = self.start
 | 
						|
            self.listbox.select_clear(0, int(self.listbox.curselection()[0]))
 | 
						|
            self.listbox.select_set(self._binary_search(self.start))
 | 
						|
            self._selection_changed()
 | 
						|
            return "break"
 | 
						|
 | 
						|
        elif keysym == "Return" and not state:
 | 
						|
            # If start is a prefix of the selection, or there was an indication
 | 
						|
            # that the user used the completion window, put the selected
 | 
						|
            # completion in the text, and close the list.
 | 
						|
            # Otherwise, close the window and let the event through.
 | 
						|
            cursel = int(self.listbox.curselection()[0])
 | 
						|
            if self.completions[cursel][:len(self.start)] == self.start or \
 | 
						|
               self.userwantswindow:
 | 
						|
                self._change_start(self.completions[cursel])
 | 
						|
                self.hide_window()
 | 
						|
                return "break"
 | 
						|
            else:
 | 
						|
                self.hide_window()
 | 
						|
                return
 | 
						|
 | 
						|
        elif (self.mode == AutoComplete.COMPLETE_ATTRIBUTES and keysym in
 | 
						|
              ("period", "space", "parenleft", "parenright", "bracketleft",
 | 
						|
               "bracketright")) or \
 | 
						|
             (self.mode == AutoComplete.COMPLETE_FILES and keysym in
 | 
						|
              ("slash", "backslash", "quotedbl", "apostrophe")) \
 | 
						|
             and not (state & ~MC_SHIFT):
 | 
						|
            # If start is a prefix of the selection, but is not '' when
 | 
						|
            # completing file names, put the whole
 | 
						|
            # selected completion. Anyway, close the list.
 | 
						|
            cursel = int(self.listbox.curselection()[0])
 | 
						|
            if self.completions[cursel][:len(self.start)] == self.start \
 | 
						|
               and (self.mode==AutoComplete.COMPLETE_ATTRIBUTES or self.start):
 | 
						|
                self._change_start(self.completions[cursel])
 | 
						|
            self.hide_window()
 | 
						|
            return
 | 
						|
 | 
						|
        elif keysym in ("Home", "End", "Prior", "Next", "Up", "Down") and \
 | 
						|
             not state:
 | 
						|
            # Move the selection in the listbox
 | 
						|
            self.userwantswindow = True
 | 
						|
            cursel = int(self.listbox.curselection()[0])
 | 
						|
            if keysym == "Home":
 | 
						|
                newsel = 0
 | 
						|
            elif keysym == "End":
 | 
						|
                newsel = len(self.completions)-1
 | 
						|
            elif keysym in ("Prior", "Next"):
 | 
						|
                jump = self.listbox.nearest(self.listbox.winfo_height()) - \
 | 
						|
                       self.listbox.nearest(0)
 | 
						|
                if keysym == "Prior":
 | 
						|
                    newsel = max(0, cursel-jump)
 | 
						|
                else:
 | 
						|
                    assert keysym == "Next"
 | 
						|
                    newsel = min(len(self.completions)-1, cursel+jump)
 | 
						|
            elif keysym == "Up":
 | 
						|
                newsel = max(0, cursel-1)
 | 
						|
            else:
 | 
						|
                assert keysym == "Down"
 | 
						|
                newsel = min(len(self.completions)-1, cursel+1)
 | 
						|
            self.listbox.select_clear(cursel)
 | 
						|
            self.listbox.select_set(newsel)
 | 
						|
            self._selection_changed()
 | 
						|
            self._change_start(self.completions[newsel])
 | 
						|
            return "break"
 | 
						|
 | 
						|
        elif (keysym == "Tab" and not state):
 | 
						|
            if self.lastkey_was_tab:
 | 
						|
                # two tabs in a row; insert current selection and close acw
 | 
						|
                cursel = int(self.listbox.curselection()[0])
 | 
						|
                self._change_start(self.completions[cursel])
 | 
						|
                self.hide_window()
 | 
						|
                return "break"
 | 
						|
            else:
 | 
						|
                # first tab; let AutoComplete handle the completion
 | 
						|
                self.userwantswindow = True
 | 
						|
                self.lastkey_was_tab = True
 | 
						|
                return
 | 
						|
 | 
						|
        elif any(s in keysym for s in ("Shift", "Control", "Alt",
 | 
						|
                                       "Meta", "Command", "Option")):
 | 
						|
            # A modifier key, so ignore
 | 
						|
            return
 | 
						|
 | 
						|
        else:
 | 
						|
            # Unknown event, close the window and let it through.
 | 
						|
            self.hide_window()
 | 
						|
            return
 | 
						|
 | 
						|
    def keyrelease_event(self, event):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
        if self.widget.index("insert") != \
 | 
						|
           self.widget.index("%s+%dc" % (self.startindex, len(self.start))):
 | 
						|
            # If we didn't catch an event which moved the insert, close window
 | 
						|
            self.hide_window()
 | 
						|
 | 
						|
    def is_active(self):
 | 
						|
        return self.autocompletewindow is not None
 | 
						|
 | 
						|
    def complete(self):
 | 
						|
        self._change_start(self._complete_string(self.start))
 | 
						|
        # The selection doesn't change.
 | 
						|
 | 
						|
    def hide_window(self):
 | 
						|
        if not self.is_active():
 | 
						|
            return
 | 
						|
 | 
						|
        # unbind events
 | 
						|
        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
 | 
						|
        for seq in KEYPRESS_SEQUENCES:
 | 
						|
            self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq)
 | 
						|
        self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid)
 | 
						|
        self.keypressid = None
 | 
						|
        self.widget.event_delete(KEYRELEASE_VIRTUAL_EVENT_NAME,
 | 
						|
                                 KEYRELEASE_SEQUENCE)
 | 
						|
        self.widget.unbind(KEYRELEASE_VIRTUAL_EVENT_NAME, self.keyreleaseid)
 | 
						|
        self.keyreleaseid = None
 | 
						|
        self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid)
 | 
						|
        self.listupdateid = None
 | 
						|
        self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
 | 
						|
        self.winconfigid = None
 | 
						|
 | 
						|
        # destroy widgets
 | 
						|
        self.scrollbar.destroy()
 | 
						|
        self.scrollbar = None
 | 
						|
        self.listbox.destroy()
 | 
						|
        self.listbox = None
 | 
						|
        self.autocompletewindow.destroy()
 | 
						|
        self.autocompletewindow = None
 |