symbian-qemu-0.9.1-12/python-2.6.1/Lib/idlelib/AutoComplete.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """AutoComplete.py - An IDLE extension for automatically completing names.
       
     2 
       
     3 This extension can complete either attribute names of file names. It can pop
       
     4 a window with all available names, for the user to select from.
       
     5 """
       
     6 import os
       
     7 import sys
       
     8 import string
       
     9 
       
    10 from configHandler import idleConf
       
    11 
       
    12 import AutoCompleteWindow
       
    13 from HyperParser import HyperParser
       
    14 
       
    15 import __main__
       
    16 
       
    17 # This string includes all chars that may be in a file name (without a path
       
    18 # separator)
       
    19 FILENAME_CHARS = string.ascii_letters + string.digits + os.curdir + "._~#$:-"
       
    20 # This string includes all chars that may be in an identifier
       
    21 ID_CHARS = string.ascii_letters + string.digits + "_"
       
    22 
       
    23 # These constants represent the two different types of completions
       
    24 COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1)
       
    25 
       
    26 SEPS = os.sep
       
    27 if os.altsep:  # e.g. '/' on Windows...
       
    28     SEPS += os.altsep
       
    29 
       
    30 class AutoComplete:
       
    31 
       
    32     menudefs = [
       
    33         ('edit', [
       
    34             ("Show Completions", "<<force-open-completions>>"),
       
    35         ])
       
    36     ]
       
    37 
       
    38     popupwait = idleConf.GetOption("extensions", "AutoComplete",
       
    39                                    "popupwait", type="int", default=0)
       
    40 
       
    41     def __init__(self, editwin=None):
       
    42         self.editwin = editwin
       
    43         if editwin is None:  # subprocess and test
       
    44             return
       
    45         self.text = editwin.text
       
    46         self.autocompletewindow = None
       
    47 
       
    48         # id of delayed call, and the index of the text insert when the delayed
       
    49         # call was issued. If _delayed_completion_id is None, there is no
       
    50         # delayed call.
       
    51         self._delayed_completion_id = None
       
    52         self._delayed_completion_index = None
       
    53 
       
    54     def _make_autocomplete_window(self):
       
    55         return AutoCompleteWindow.AutoCompleteWindow(self.text)
       
    56 
       
    57     def _remove_autocomplete_window(self, event=None):
       
    58         if self.autocompletewindow:
       
    59             self.autocompletewindow.hide_window()
       
    60             self.autocompletewindow = None
       
    61 
       
    62     def force_open_completions_event(self, event):
       
    63         """Happens when the user really wants to open a completion list, even
       
    64         if a function call is needed.
       
    65         """
       
    66         self.open_completions(True, False, True)
       
    67 
       
    68     def try_open_completions_event(self, event):
       
    69         """Happens when it would be nice to open a completion list, but not
       
    70         really neccesary, for example after an dot, so function
       
    71         calls won't be made.
       
    72         """
       
    73         lastchar = self.text.get("insert-1c")
       
    74         if lastchar == ".":
       
    75             self._open_completions_later(False, False, False,
       
    76                                          COMPLETE_ATTRIBUTES)
       
    77         elif lastchar in SEPS:
       
    78             self._open_completions_later(False, False, False,
       
    79                                          COMPLETE_FILES)
       
    80 
       
    81     def autocomplete_event(self, event):
       
    82         """Happens when the user wants to complete his word, and if neccesary,
       
    83         open a completion list after that (if there is more than one
       
    84         completion)
       
    85         """
       
    86         if hasattr(event, "mc_state") and event.mc_state:
       
    87             # A modifier was pressed along with the tab, continue as usual.
       
    88             return
       
    89         if self.autocompletewindow and self.autocompletewindow.is_active():
       
    90             self.autocompletewindow.complete()
       
    91             return "break"
       
    92         else:
       
    93             opened = self.open_completions(False, True, True)
       
    94             if opened:
       
    95                 return "break"
       
    96 
       
    97     def _open_completions_later(self, *args):
       
    98         self._delayed_completion_index = self.text.index("insert")
       
    99         if self._delayed_completion_id is not None:
       
   100             self.text.after_cancel(self._delayed_completion_id)
       
   101         self._delayed_completion_id = \
       
   102             self.text.after(self.popupwait, self._delayed_open_completions,
       
   103                             *args)
       
   104 
       
   105     def _delayed_open_completions(self, *args):
       
   106         self._delayed_completion_id = None
       
   107         if self.text.index("insert") != self._delayed_completion_index:
       
   108             return
       
   109         self.open_completions(*args)
       
   110 
       
   111     def open_completions(self, evalfuncs, complete, userWantsWin, mode=None):
       
   112         """Find the completions and create the AutoCompleteWindow.
       
   113         Return True if successful (no syntax error or so found).
       
   114         if complete is True, then if there's nothing to complete and no
       
   115         start of completion, won't open completions and return False.
       
   116         If mode is given, will open a completion list only in this mode.
       
   117         """
       
   118         # Cancel another delayed call, if it exists.
       
   119         if self._delayed_completion_id is not None:
       
   120             self.text.after_cancel(self._delayed_completion_id)
       
   121             self._delayed_completion_id = None
       
   122 
       
   123         hp = HyperParser(self.editwin, "insert")
       
   124         curline = self.text.get("insert linestart", "insert")
       
   125         i = j = len(curline)
       
   126         if hp.is_in_string() and (not mode or mode==COMPLETE_FILES):
       
   127             self._remove_autocomplete_window()
       
   128             mode = COMPLETE_FILES
       
   129             while i and curline[i-1] in FILENAME_CHARS:
       
   130                 i -= 1
       
   131             comp_start = curline[i:j]
       
   132             j = i
       
   133             while i and curline[i-1] in FILENAME_CHARS + SEPS:
       
   134                 i -= 1
       
   135             comp_what = curline[i:j]
       
   136         elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES):
       
   137             self._remove_autocomplete_window()
       
   138             mode = COMPLETE_ATTRIBUTES
       
   139             while i and curline[i-1] in ID_CHARS:
       
   140                 i -= 1
       
   141             comp_start = curline[i:j]
       
   142             if i and curline[i-1] == '.':
       
   143                 hp.set_index("insert-%dc" % (len(curline)-(i-1)))
       
   144                 comp_what = hp.get_expression()
       
   145                 if not comp_what or \
       
   146                    (not evalfuncs and comp_what.find('(') != -1):
       
   147                     return
       
   148             else:
       
   149                 comp_what = ""
       
   150         else:
       
   151             return
       
   152 
       
   153         if complete and not comp_what and not comp_start:
       
   154             return
       
   155         comp_lists = self.fetch_completions(comp_what, mode)
       
   156         if not comp_lists[0]:
       
   157             return
       
   158         self.autocompletewindow = self._make_autocomplete_window()
       
   159         self.autocompletewindow.show_window(comp_lists,
       
   160                                             "insert-%dc" % len(comp_start),
       
   161                                             complete,
       
   162                                             mode,
       
   163                                             userWantsWin)
       
   164         return True
       
   165 
       
   166     def fetch_completions(self, what, mode):
       
   167         """Return a pair of lists of completions for something. The first list
       
   168         is a sublist of the second. Both are sorted.
       
   169 
       
   170         If there is a Python subprocess, get the comp. list there.  Otherwise,
       
   171         either fetch_completions() is running in the subprocess itself or it
       
   172         was called in an IDLE EditorWindow before any script had been run.
       
   173 
       
   174         The subprocess environment is that of the most recently run script.  If
       
   175         two unrelated modules are being edited some calltips in the current
       
   176         module may be inoperative if the module was not the last to run.
       
   177         """
       
   178         try:
       
   179             rpcclt = self.editwin.flist.pyshell.interp.rpcclt
       
   180         except:
       
   181             rpcclt = None
       
   182         if rpcclt:
       
   183             return rpcclt.remotecall("exec", "get_the_completion_list",
       
   184                                      (what, mode), {})
       
   185         else:
       
   186             if mode == COMPLETE_ATTRIBUTES:
       
   187                 if what == "":
       
   188                     namespace = __main__.__dict__.copy()
       
   189                     namespace.update(__main__.__builtins__.__dict__)
       
   190                     bigl = eval("dir()", namespace)
       
   191                     bigl.sort()
       
   192                     if "__all__" in bigl:
       
   193                         smalll = eval("__all__", namespace)
       
   194                         smalll.sort()
       
   195                     else:
       
   196                         smalll = filter(lambda s: s[:1] != '_', bigl)
       
   197                 else:
       
   198                     try:
       
   199                         entity = self.get_entity(what)
       
   200                         bigl = dir(entity)
       
   201                         bigl.sort()
       
   202                         if "__all__" in bigl:
       
   203                             smalll = entity.__all__
       
   204                             smalll.sort()
       
   205                         else:
       
   206                             smalll = filter(lambda s: s[:1] != '_', bigl)
       
   207                     except:
       
   208                         return [], []
       
   209 
       
   210             elif mode == COMPLETE_FILES:
       
   211                 if what == "":
       
   212                     what = "."
       
   213                 try:
       
   214                     expandedpath = os.path.expanduser(what)
       
   215                     bigl = os.listdir(expandedpath)
       
   216                     bigl.sort()
       
   217                     smalll = filter(lambda s: s[:1] != '.', bigl)
       
   218                 except OSError:
       
   219                     return [], []
       
   220 
       
   221             if not smalll:
       
   222                 smalll = bigl
       
   223             return smalll, bigl
       
   224 
       
   225     def get_entity(self, name):
       
   226         """Lookup name in a namespace spanning sys.modules and __main.dict__"""
       
   227         namespace = sys.modules.copy()
       
   228         namespace.update(__main__.__dict__)
       
   229         return eval(name, namespace)