Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b175445

Browse files
committed
Merge IDLE-syntax-branch r39668:41449 into trunk
A idlelib/AutoCompleteWindow.py A idlelib/AutoComplete.py A idlelib/HyperParser.py M idlelib/PyShell.py M idlelib/ParenMatch.py M idlelib/configDialog.py M idlelib/EditorWindow.py M idlelib/PyParse.py M idlelib/CallTips.py M idlelib/CallTipWindow.py M idlelib/run.py M idlelib/config-extensions.def A idlelib/MultiCall.py
1 parent c85c74c commit b175445

13 files changed

Lines changed: 1592 additions & 201 deletions

Lib/idlelib/AutoComplete.py

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

0 commit comments

Comments
 (0)