Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5)

Delta Between Two Patch Sets: Lib/idlelib/EditorWindow.py

Issue 13884: IDLE 2.6.5 Recent Files undocks
Left Patch Set: Created 4 years, 6 months ago
Right Patch Set: Created 4 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | Lib/idlelib/help.txt » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 import importlib 1 import sys
2 import importlib.abc
3 import importlib.util
4 import os 2 import os
5 import platform 3 import platform
6 import re 4 import re
7 import string 5 import imp
8 import sys 6 from Tkinter import *
9 from tkinter import * 7 import tkSimpleDialog
10 import tkinter.simpledialog as tkSimpleDialog 8 import tkMessageBox
11 import tkinter.messagebox as tkMessageBox
12 import traceback
13 import webbrowser 9 import webbrowser
14 10
15 from idlelib.MultiCall import MultiCallCreator 11 from idlelib.MultiCall import MultiCallCreator
16 from idlelib import WindowList 12 from idlelib import WindowList
17 from idlelib import SearchDialog 13 from idlelib import SearchDialog
18 from idlelib import GrepDialog 14 from idlelib import GrepDialog
19 from idlelib import ReplaceDialog 15 from idlelib import ReplaceDialog
20 from idlelib import PyParse 16 from idlelib import PyParse
21 from idlelib.configHandler import idleConf 17 from idlelib.configHandler import idleConf
22 from idlelib import aboutDialog, textView, configDialog 18 from idlelib import aboutDialog, textView, configDialog
23 from idlelib import macosxSupport 19 from idlelib import macosxSupport
24 20
25 # The default tab setting for a Text widget, in average-width characters. 21 # The default tab setting for a Text widget, in average-width characters.
26 TK_TABWIDTH_DEFAULT = 8 22 TK_TABWIDTH_DEFAULT = 8
27 23
28 _py_version = ' (%s)' % platform.python_version() 24 _py_version = ' (%s)' % platform.python_version()
29 25
30 def _sphinx_version(): 26 def _sphinx_version():
31 "Format sys.version_info to produce the Sphinx version string used to instal l the chm docs" 27 "Format sys.version_info to produce the Sphinx version string used to instal l the chm docs"
32 major, minor, micro, level, serial = sys.version_info 28 major, minor, micro, level, serial = sys.version_info
33 release = '%s%s' % (major, minor) 29 release = '%s%s' % (major, minor)
34 release += '%s' % (micro,) 30 if micro:
31 release += '%s' % (micro,)
35 if level == 'candidate': 32 if level == 'candidate':
36 release += 'rc%s' % (serial,) 33 release += 'rc%s' % (serial,)
37 elif level != 'final': 34 elif level != 'final':
38 release += '%s%s' % (level[0], serial) 35 release += '%s%s' % (level[0], serial)
39 return release 36 return release
37
38 def _find_module(fullname, path=None):
39 """Version of imp.find_module() that handles hierarchical module names"""
40
41 file = None
42 for tgt in fullname.split('.'):
43 if file is not None:
44 file.close() # close intermediate files
45 (file, filename, descr) = imp.find_module(tgt, path)
46 if descr[2] == imp.PY_SOURCE:
47 break # find but not load the source file
48 module = imp.load_module(tgt, file, filename, descr)
49 try:
50 path = module.__path__
51 except AttributeError:
52 raise ImportError, 'No source for module ' + module.__name__
53 if descr[2] != imp.PY_SOURCE:
54 # If all of the above fails and didn't raise an exception,fallback
55 # to a straight import which can find __init__.py in a package.
56 m = __import__(fullname)
57 try:
58 filename = m.__file__
59 except AttributeError:
60 pass
61 else:
62 file = None
63 base, ext = os.path.splitext(filename)
64 if ext == '.pyc':
65 ext = '.py'
66 filename = base + ext
67 descr = filename, None, imp.PY_SOURCE
68 return file, filename, descr
40 69
41 70
42 class HelpDialog(object): 71 class HelpDialog(object):
43 72
44 def __init__(self): 73 def __init__(self):
45 self.parent = None # parent of help window 74 self.parent = None # parent of help window
46 self.dlg = None # the help window iteself 75 self.dlg = None # the help window iteself
47 76
48 def display(self, parent, near=None): 77 def display(self, parent, near=None):
49 """ Display the help dialog. 78 """ Display the help dialog.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 def _help_dialog(parent): # wrapper for htest 112 def _help_dialog(parent): # wrapper for htest
84 helpDialog.show_dialog(parent) 113 helpDialog.show_dialog(parent)
85 114
86 115
87 class EditorWindow(object): 116 class EditorWindow(object):
88 from idlelib.Percolator import Percolator 117 from idlelib.Percolator import Percolator
89 from idlelib.ColorDelegator import ColorDelegator 118 from idlelib.ColorDelegator import ColorDelegator
90 from idlelib.UndoDelegator import UndoDelegator 119 from idlelib.UndoDelegator import UndoDelegator
91 from idlelib.IOBinding import IOBinding, filesystemencoding, encoding 120 from idlelib.IOBinding import IOBinding, filesystemencoding, encoding
92 from idlelib import Bindings 121 from idlelib import Bindings
93 from tkinter import Toplevel 122 from Tkinter import Toplevel
94 from idlelib.MultiStatusBar import MultiStatusBar 123 from idlelib.MultiStatusBar import MultiStatusBar
95 124
96 help_url = None 125 help_url = None
97 126
98 def __init__(self, flist=None, filename=None, key=None, root=None): 127 def __init__(self, flist=None, filename=None, key=None, root=None):
99 if EditorWindow.help_url is None: 128 if EditorWindow.help_url is None:
100 dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html') 129 dochome = os.path.join(sys.prefix, 'Doc', 'index.html')
101 if sys.platform.count('linux'): 130 if sys.platform.count('linux'):
102 # look for html docs in a couple of standard places 131 # look for html docs in a couple of standard places
103 pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] 132 pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3]
104 if os.path.isdir('/var/www/html/python/'): # "python2" rpm 133 if os.path.isdir('/var/www/html/python/'): # "python2" rpm
105 dochome = '/var/www/html/python/index.html' 134 dochome = '/var/www/html/python/index.html'
106 else: 135 else:
107 basepath = '/usr/share/doc/' # standard location 136 basepath = '/usr/share/doc/' # standard location
108 dochome = os.path.join(basepath, pyver, 137 dochome = os.path.join(basepath, pyver,
109 'Doc', 'index.html') 138 'Doc', 'index.html')
110 elif sys.platform[:3] == 'win': 139 elif sys.platform[:3] == 'win':
111 chmfile = os.path.join(sys.base_prefix, 'Doc', 140 chmfile = os.path.join(sys.prefix, 'Doc',
112 'Python%s.chm' % _sphinx_version()) 141 'Python%s.chm' % _sphinx_version())
113 if os.path.isfile(chmfile): 142 if os.path.isfile(chmfile):
114 dochome = chmfile 143 dochome = chmfile
115 elif sys.platform == 'darwin': 144 elif sys.platform == 'darwin':
116 # documentation may be stored inside a python framework 145 # documentation may be stored inside a python framework
117 dochome = os.path.join(sys.base_prefix, 146 dochome = os.path.join(sys.prefix,
118 'Resources/English.lproj/Documentation/index.html') 147 'Resources/English.lproj/Documentation/index.html')
119 dochome = os.path.normpath(dochome) 148 dochome = os.path.normpath(dochome)
120 if os.path.isfile(dochome): 149 if os.path.isfile(dochome):
121 EditorWindow.help_url = dochome 150 EditorWindow.help_url = dochome
122 if sys.platform == 'darwin': 151 if sys.platform == 'darwin':
123 # Safari requires real file:-URLs 152 # Safari requires real file:-URLs
124 EditorWindow.help_url = 'file://' + EditorWindow.help_url 153 EditorWindow.help_url = 'file://' + EditorWindow.help_url
125 else: 154 else:
126 EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.v ersion_info[:2] 155 EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.v ersion_info[:2]
127 self.flist = flist 156 self.flist = flist
(...skipping 11 matching lines...) Expand all
139 #configDialog.py so it can access all EditorWindow instances 168 #configDialog.py so it can access all EditorWindow instances
140 self.top.instance_dict = flist.inversedict 169 self.top.instance_dict = flist.inversedict
141 else: 170 else:
142 self.tkinter_vars = {} # keys: Tkinter event names 171 self.tkinter_vars = {} # keys: Tkinter event names
143 # values: Tkinter variable instances 172 # values: Tkinter variable instances
144 self.top.instance_dict = {} 173 self.top.instance_dict = {}
145 self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(), 174 self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(),
146 'recent-files.lst') 175 'recent-files.lst')
147 self.text_frame = text_frame = Frame(top) 176 self.text_frame = text_frame = Frame(top)
148 self.vbar = vbar = Scrollbar(text_frame, name='vbar') 177 self.vbar = vbar = Scrollbar(text_frame, name='vbar')
149 self.width = idleConf.GetOption('main', 'EditorWindow', 178 self.width = idleConf.GetOption('main','EditorWindow','width', type='int ')
150 'width', type='int')
151 text_options = { 179 text_options = {
152 'name': 'text', 180 'name': 'text',
153 'padx': 5, 181 'padx': 5,
154 'wrap': 'none', 182 'wrap': 'none',
155 'width': self.width, 183 'width': self.width,
156 'height': idleConf.GetOption('main', 'EditorWindow', 184 'height': idleConf.GetOption('main', 'EditorWindow', 'height', t ype='int')}
157 'height', type='int')}
158 if TkVersion >= 8.5: 185 if TkVersion >= 8.5:
159 # Starting with tk 8.5 we have to set the new tabstyle option 186 # Starting with tk 8.5 we have to set the new tabstyle option
160 # to 'wordprocessor' to achieve the same display of tabs as in 187 # to 'wordprocessor' to achieve the same display of tabs as in
161 # older tk versions. 188 # older tk versions.
162 text_options['tabstyle'] = 'wordprocessor' 189 text_options['tabstyle'] = 'wordprocessor'
163 self.text = text = MultiCallCreator(Text)(text_frame, **text_options) 190 self.text = text = MultiCallCreator(Text)(text_frame, **text_options)
164 self.top.focused_widget = self.text 191 self.top.focused_widget = self.text
165 192
166 self.createmenubar() 193 self.createmenubar()
167 self.apply_bindings() 194 self.apply_bindings()
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 text.bind("<<beginning-of-line>>", self.home_callback) 244 text.bind("<<beginning-of-line>>", self.home_callback)
218 245
219 if flist: 246 if flist:
220 flist.inversedict[self] = key 247 flist.inversedict[self] = key
221 if key: 248 if key:
222 flist.dict[key] = self 249 flist.dict[key] = self
223 text.bind("<<open-new-window>>", self.new_callback) 250 text.bind("<<open-new-window>>", self.new_callback)
224 text.bind("<<close-all-windows>>", self.flist.close_all_callback) 251 text.bind("<<close-all-windows>>", self.flist.close_all_callback)
225 text.bind("<<open-class-browser>>", self.open_class_browser) 252 text.bind("<<open-class-browser>>", self.open_class_browser)
226 text.bind("<<open-path-browser>>", self.open_path_browser) 253 text.bind("<<open-path-browser>>", self.open_path_browser)
227 text.bind("<<open-turtle-demo>>", self.open_turtle_demo)
228 254
229 self.set_status_bar() 255 self.set_status_bar()
230 vbar['command'] = text.yview 256 vbar['command'] = text.yview
231 vbar.pack(side=RIGHT, fill=Y) 257 vbar.pack(side=RIGHT, fill=Y)
232 text['yscrollcommand'] = vbar.set 258 text['yscrollcommand'] = vbar.set
233 fontWeight = 'normal' 259 fontWeight = 'normal'
234 if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): 260 if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'):
235 fontWeight='bold' 261 fontWeight='bold'
236 text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), 262 text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'),
237 idleConf.GetOption('main', 'EditorWindow', 263 idleConf.GetOption('main', 'EditorWindow',
238 'font-size', type='int'), 264 'font-size', type='int'),
239 fontWeight)) 265 fontWeight))
240 text_frame.pack(side=LEFT, fill=BOTH, expand=1) 266 text_frame.pack(side=LEFT, fill=BOTH, expand=1)
241 text.pack(side=TOP, fill=BOTH, expand=1) 267 text.pack(side=TOP, fill=BOTH, expand=1)
242 text.focus_set() 268 text.focus_set()
243 269
244 # usetabs true -> literal tab characters are used by indent and 270 # usetabs true -> literal tab characters are used by indent and
245 # dedent cmds, possibly mixed with spaces if 271 # dedent cmds, possibly mixed with spaces if
246 # indentwidth is not a multiple of tabwidth, 272 # indentwidth is not a multiple of tabwidth,
247 # which will cause Tabnanny to nag! 273 # which will cause Tabnanny to nag!
248 # false -> tab characters are converted to spaces by indent 274 # false -> tab characters are converted to spaces by indent
249 # and dedent cmds, and ditto TAB keystrokes 275 # and dedent cmds, and ditto TAB keystrokes
250 # Although use-spaces=0 can be configured manually in config-main.def, 276 # Although use-spaces=0 can be configured manually in config-main.def,
251 # configuration of tabs v. spaces is not supported in the configuration 277 # configuration of tabs v. spaces is not supported in the configuration
252 # dialog. IDLE promotes the preferred Python indentation: use spaces! 278 # dialog. IDLE promotes the preferred Python indentation: use spaces!
253 usespaces = idleConf.GetOption('main', 'Indent', 279 usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='boo l')
254 'use-spaces', type='bool')
255 self.usetabs = not usespaces 280 self.usetabs = not usespaces
256 281
257 # tabwidth is the display width of a literal tab character. 282 # tabwidth is the display width of a literal tab character.
258 # CAUTION: telling Tk to use anything other than its default 283 # CAUTION: telling Tk to use anything other than its default
259 # tab setting causes it to use an entirely different tabbing algorithm, 284 # tab setting causes it to use an entirely different tabbing algorithm,
260 # treating tab stops as fixed distances from the left margin. 285 # treating tab stops as fixed distances from the left margin.
261 # Nobody expects this, so for now tabwidth should never be changed. 286 # Nobody expects this, so for now tabwidth should never be changed.
262 self.tabwidth = 8 # must remain 8 until Tk is fixed. 287 self.tabwidth = 8 # must remain 8 until Tk is fixed.
263 288
264 # indentwidth is the number of screen characters per indent level. 289 # indentwidth is the number of screen characters per indent level.
265 # The recommended Python indentation is four spaces. 290 # The recommended Python indentation is four spaces.
266 self.indentwidth = self.tabwidth 291 self.indentwidth = self.tabwidth
267 self.set_notabs_indentwidth() 292 self.set_notabs_indentwidth()
268 293
269 # If context_use_ps1 is true, parsing searches back for a ps1 line; 294 # If context_use_ps1 is true, parsing searches back for a ps1 line;
270 # else searches for a popular (if, def, ...) Python stmt. 295 # else searches for a popular (if, def, ...) Python stmt.
271 self.context_use_ps1 = False 296 self.context_use_ps1 = False
272 297
273 # When searching backwards for a reliable place to begin parsing, 298 # When searching backwards for a reliable place to begin parsing,
274 # first start num_context_lines[0] lines back, then 299 # first start num_context_lines[0] lines back, then
275 # num_context_lines[1] lines back if that didn't work, and so on. 300 # num_context_lines[1] lines back if that didn't work, and so on.
276 # The last value should be huge (larger than the # of lines in a 301 # The last value should be huge (larger than the # of lines in a
277 # conceivable file). 302 # conceivable file).
278 # Making the initial values larger slows things down more often. 303 # Making the initial values larger slows things down more often.
279 self.num_context_lines = 50, 500, 5000000 304 self.num_context_lines = 50, 500, 5000000
305
280 self.per = per = self.Percolator(text) 306 self.per = per = self.Percolator(text)
307
281 self.undo = undo = self.UndoDelegator() 308 self.undo = undo = self.UndoDelegator()
282 per.insertfilter(undo) 309 per.insertfilter(undo)
283 text.undo_block_start = undo.undo_block_start 310 text.undo_block_start = undo.undo_block_start
284 text.undo_block_stop = undo.undo_block_stop 311 text.undo_block_stop = undo.undo_block_stop
285 undo.set_saved_change_hook(self.saved_change_hook) 312 undo.set_saved_change_hook(self.saved_change_hook)
313
286 # IOBinding implements file I/O and printing functionality 314 # IOBinding implements file I/O and printing functionality
287 self.io = io = self.IOBinding(self) 315 self.io = io = self.IOBinding(self)
288 io.set_filename_change_hook(self.filename_change_hook) 316 io.set_filename_change_hook(self.filename_change_hook)
289 self.good_load = False 317
290 self.set_indentation_params(False) 318 # Create the recent files submenu
319 self.recent_files_menu = Menu(self.menubar, tearoff=0)
320 self.menudict['file'].insert_cascade(3, label='Recent Files',
321 underline=0,
322 menu=self.recent_files_menu)
323 self.update_recent_files_list()
324
291 self.color = None # initialized below in self.ResetColorizer 325 self.color = None # initialized below in self.ResetColorizer
292 if filename: 326 if filename:
293 if os.path.exists(filename) and not os.path.isdir(filename): 327 if os.path.exists(filename) and not os.path.isdir(filename):
294 if io.loadfile(filename): 328 io.loadfile(filename)
295 self.good_load = True
296 is_py_src = self.ispythonsource(filename)
297 self.set_indentation_params(is_py_src)
298 else: 329 else:
299 io.set_filename(filename) 330 io.set_filename(filename)
300 self.good_load = True
301
302 self.ResetColorizer() 331 self.ResetColorizer()
303 self.saved_change_hook() 332 self.saved_change_hook()
304 self.update_recent_files_list() 333
334 self.set_indentation_params(self.ispythonsource(filename))
335
305 self.load_extensions() 336 self.load_extensions()
337
306 menu = self.menudict.get('windows') 338 menu = self.menudict.get('windows')
307 if menu: 339 if menu:
308 end = menu.index("end") 340 end = menu.index("end")
309 if end is None: 341 if end is None:
310 end = -1 342 end = -1
311 if end >= 0: 343 if end >= 0:
312 menu.add_separator() 344 menu.add_separator()
313 end = end + 1 345 end = end + 1
314 self.wmenu_end = end 346 self.wmenu_end = end
315 WindowList.register_callback(self.postwindowsmenu) 347 WindowList.register_callback(self.postwindowsmenu)
(...skipping 28 matching lines...) Expand all
344 text.tag_remove("sel_fix", "1.0", "end") 376 text.tag_remove("sel_fix", "1.0", "end")
345 377
346 text.bind("<<Highlight-FocusOut>>", 378 text.bind("<<Highlight-FocusOut>>",
347 lambda ev: highlight_fix("out")) 379 lambda ev: highlight_fix("out"))
348 text.bind("<<Highlight-FocusIn>>", 380 text.bind("<<Highlight-FocusIn>>",
349 lambda ev: highlight_fix("in")) 381 lambda ev: highlight_fix("in"))
350 382
351 383
352 def _filename_to_unicode(self, filename): 384 def _filename_to_unicode(self, filename):
353 """convert filename to unicode in order to display it in Tk""" 385 """convert filename to unicode in order to display it in Tk"""
354 if isinstance(filename, str) or not filename: 386 if isinstance(filename, unicode) or not filename:
355 return filename 387 return filename
356 else: 388 else:
357 try: 389 try:
358 return filename.decode(self.filesystemencoding) 390 return filename.decode(self.filesystemencoding)
359 except UnicodeDecodeError: 391 except UnicodeDecodeError:
360 # XXX 392 # XXX
361 try: 393 try:
362 return filename.decode(self.encoding) 394 return filename.decode(self.encoding)
363 except UnicodeDecodeError: 395 except UnicodeDecodeError:
364 # byte-to-byte conversion 396 # byte-to-byte conversion
365 return filename.decode('iso8859-1') 397 return filename.decode('iso8859-1')
366 398
367 def new_callback(self, event): 399 def new_callback(self, event):
368 dirname, basename = self.io.defaultfilename() 400 dirname, basename = self.io.defaultfilename()
369 self.flist.new(dirname) 401 self.flist.new(dirname)
370 return "break" 402 return "break"
371 403
372 def home_callback(self, event): 404 def home_callback(self, event):
373 if (event.state & 4) != 0 and event.keysym == "Home": 405 if (event.state & 4) != 0 and event.keysym == "Home":
374 # state&4==Control. If <Control-Home>, use the Tk binding. 406 # state&4==Control. If <Control-Home>, use the Tk binding.
375 return 407 return
376 if self.text.index("iomark") and \ 408 if self.text.index("iomark") and \
377 self.text.compare("iomark", "<=", "insert lineend") and \ 409 self.text.compare("iomark", "<=", "insert lineend") and \
378 self.text.compare("insert linestart", "<=", "iomark"): 410 self.text.compare("insert linestart", "<=", "iomark"):
379 # In Shell on input line, go to just after prompt 411 # In Shell on input line, go to just after prompt
380 insertpt = int(self.text.index("iomark").split(".")[1]) 412 insertpt = int(self.text.index("iomark").split(".")[1])
381 else: 413 else:
382 line = self.text.get("insert linestart", "insert lineend") 414 line = self.text.get("insert linestart", "insert lineend")
383 for insertpt in range(len(line)): 415 for insertpt in xrange(len(line)):
384 if line[insertpt] not in (' ','\t'): 416 if line[insertpt] not in (' ','\t'):
385 break 417 break
386 else: 418 else:
387 insertpt=len(line) 419 insertpt=len(line)
388 lineat = int(self.text.index("insert").split('.')[1]) 420 lineat = int(self.text.index("insert").split('.')[1])
389 if insertpt == lineat: 421 if insertpt == lineat:
390 insertpt = 0 422 insertpt = 0
391 dest = "insert linestart+"+str(insertpt)+"c" 423 dest = "insert linestart+"+str(insertpt)+"c"
392 if (event.state&1) == 0: 424 if (event.state&1) == 0:
393 # shift was not pressed 425 # shift was not pressed
394 self.text.tag_remove("sel", "1.0", "end") 426 self.text.tag_remove("sel", "1.0", "end")
395 else: 427 else:
396 if not self.text.index("sel.first"): 428 if not self.text.index("sel.first"):
397 # there was no previous selection 429 self.text.mark_set("my_anchor", "insert") # there was no previo us selection
398 self.text.mark_set("my_anchor", "insert")
399 else: 430 else:
400 if self.text.compare(self.text.index("sel.first"), "<", 431 if self.text.compare(self.text.index("sel.first"), "<", self.tex t.index("insert")):
401 self.text.index("insert")):
402 self.text.mark_set("my_anchor", "sel.first") # extend back 432 self.text.mark_set("my_anchor", "sel.first") # extend back
403 else: 433 else:
404 self.text.mark_set("my_anchor", "sel.last") # extend forward 434 self.text.mark_set("my_anchor", "sel.last") # extend forward
405 first = self.text.index(dest) 435 first = self.text.index(dest)
406 last = self.text.index("my_anchor") 436 last = self.text.index("my_anchor")
407 if self.text.compare(first,">",last): 437 if self.text.compare(first,">",last):
408 first,last = last,first 438 first,last = last,first
409 self.text.tag_remove("sel", "1.0", "end") 439 self.text.tag_remove("sel", "1.0", "end")
410 self.text.tag_add("sel", first, last) 440 self.text.tag_add("sel", first, last)
411 self.text.mark_set("insert", dest) 441 self.text.mark_set("insert", dest)
(...skipping 30 matching lines...) Expand all
442 ] 472 ]
443 473
444 474
445 def createmenubar(self): 475 def createmenubar(self):
446 mbar = self.menubar 476 mbar = self.menubar
447 self.menudict = menudict = {} 477 self.menudict = menudict = {}
448 for name, label in self.menu_specs: 478 for name, label in self.menu_specs:
449 underline, label = prepstr(label) 479 underline, label = prepstr(label)
450 menudict[name] = menu = Menu(mbar, name=name, tearoff=0) 480 menudict[name] = menu = Menu(mbar, name=name, tearoff=0)
451 mbar.add_cascade(label=label, menu=menu, underline=underline) 481 mbar.add_cascade(label=label, menu=menu, underline=underline)
482
452 if macosxSupport.isCarbonTk(): 483 if macosxSupport.isCarbonTk():
453 # Insert the application menu 484 # Insert the application menu
454 menudict['application'] = menu = Menu(mbar, name='apple', 485 menudict['application'] = menu = Menu(mbar, name='apple',
455 tearoff=0) 486 tearoff=0)
456 mbar.add_cascade(label='IDLE', menu=menu) 487 mbar.add_cascade(label='IDLE', menu=menu)
488
457 self.fill_menus() 489 self.fill_menus()
458 self.recent_files_menu = Menu(self.menubar, tearoff=0)
459 self.menudict['file'].insert_cascade(3, label='Recent Files',
460 underline=0,
461 menu=self.recent_files_menu)
462 self.base_helpmenu_length = self.menudict['help'].index(END) 490 self.base_helpmenu_length = self.menudict['help'].index(END)
463 self.reset_help_menu_entries() 491 self.reset_help_menu_entries()
464 492
465 def postwindowsmenu(self): 493 def postwindowsmenu(self):
466 # Only called when Windows menu exists 494 # Only called when Windows menu exists
467 menu = self.menudict['windows'] 495 menu = self.menudict['windows']
468 end = menu.index("end") 496 end = menu.index("end")
469 if end is None: 497 if end is None:
470 end = -1 498 end = -1
471 if end > self.wmenu_end: 499 if end > self.wmenu_end:
(...skipping 15 matching lines...) Expand all
487 for item in self.rmenu_specs: 515 for item in self.rmenu_specs:
488 try: 516 try:
489 label, eventname, verify_state = item 517 label, eventname, verify_state = item
490 except ValueError: # see issue1207589 518 except ValueError: # see issue1207589
491 continue 519 continue
492 520
493 if verify_state is None: 521 if verify_state is None:
494 continue 522 continue
495 state = getattr(self, verify_state)() 523 state = getattr(self, verify_state)()
496 rmenu.entryconfigure(label, state=state) 524 rmenu.entryconfigure(label, state=state)
497
498 525
499 rmenu.tk_popup(event.x_root, event.y_root) 526 rmenu.tk_popup(event.x_root, event.y_root)
500 if iswin: 527 if iswin:
501 self.text.config(cursor="ibeam") 528 self.text.config(cursor="ibeam")
502 529
503 rmenu_specs = [ 530 rmenu_specs = [
504 # ("Label", "<<virtual-event>>", "statefuncname"), ... 531 # ("Label", "<<virtual-event>>", "statefuncname"), ...
505 ("Close", "<<close-window>>", None), # Example 532 ("Close", "<<close-window>>", None), # Example
506 ] 533 ]
507 534
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 if self.root: 575 if self.root:
549 parent = self.root 576 parent = self.root
550 else: 577 else:
551 parent = self.top 578 parent = self.top
552 helpDialog.display(parent, near=self.top) 579 helpDialog.display(parent, near=self.top)
553 580
554 def python_docs(self, event=None): 581 def python_docs(self, event=None):
555 if sys.platform[:3] == 'win': 582 if sys.platform[:3] == 'win':
556 try: 583 try:
557 os.startfile(self.help_url) 584 os.startfile(self.help_url)
558 except OSError as why: 585 except WindowsError as why:
559 tkMessageBox.showerror(title='Document Start Failure', 586 tkMessageBox.showerror(title='Document Start Failure',
560 message=str(why), parent=self.text) 587 message=str(why), parent=self.text)
561 else: 588 else:
562 webbrowser.open(self.help_url) 589 webbrowser.open(self.help_url)
563 return "break" 590 return "break"
564 591
565 def cut(self,event): 592 def cut(self,event):
566 self.text.event_generate("<<Cut>>") 593 self.text.event_generate("<<Cut>>")
567 return "break" 594 return "break"
568 595
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 "Go to line number:",parent=text) 669 "Go to line number:",parent=text)
643 if lineno is None: 670 if lineno is None:
644 return "break" 671 return "break"
645 if lineno <= 0: 672 if lineno <= 0:
646 text.bell() 673 text.bell()
647 return "break" 674 return "break"
648 text.mark_set("insert", "%d.0" % lineno) 675 text.mark_set("insert", "%d.0" % lineno)
649 text.see("insert") 676 text.see("insert")
650 677
651 def open_module(self, event=None): 678 def open_module(self, event=None):
652 # XXX Shouldn't this be in IOBinding? 679 # XXX Shouldn't this be in IOBinding or in FileList?
653 try: 680 try:
654 name = self.text.get("sel.first", "sel.last") 681 name = self.text.get("sel.first", "sel.last")
655 except TclError: 682 except TclError:
656 name = "" 683 name = ""
657 else: 684 else:
658 name = name.strip() 685 name = name.strip()
659 name = tkSimpleDialog.askstring("Module", 686 name = tkSimpleDialog.askstring("Module",
660 "Enter the name of a Python module\n" 687 "Enter the name of a Python module\n"
661 "to search on sys.path and open:", 688 "to search on sys.path and open:",
662 parent=self.text, initialvalue=name) 689 parent=self.text, initialvalue=name)
663 if name: 690 if name:
664 name = name.strip() 691 name = name.strip()
665 if not name: 692 if not name:
666 return 693 return
667 # XXX Ought to insert current file's directory in front of path 694 # XXX Ought to insert current file's directory in front of path
668 try: 695 try:
669 spec = importlib.util.find_spec(name) 696 (f, file_path, (suffix, mode, mtype)) = _find_module(name)
670 except (ValueError, ImportError) as msg: 697 except (NameError, ImportError) as msg:
671 tkMessageBox.showerror("Import error", str(msg), parent=self.text) 698 tkMessageBox.showerror("Import error", str(msg), parent=self.text)
672 return 699 return
673 if spec is None: 700 if mtype != imp.PY_SOURCE:
674 tkMessageBox.showerror("Import error", "module not found", 701 tkMessageBox.showerror("Unsupported type",
675 parent=self.text) 702 "%s is not a source module" % name, parent=self.text)
676 return 703 return
677 if not isinstance(spec.loader, importlib.abc.SourceLoader): 704 if f:
678 tkMessageBox.showerror("Import error", "not a source-based module", 705 f.close()
679 parent=self.text)
680 return
681 try:
682 file_path = spec.loader.get_filename(name)
683 except AttributeError:
684 tkMessageBox.showerror("Import error",
685 "loader does not support get_filename",
686 parent=self.text)
687 return
688 if self.flist: 706 if self.flist:
689 self.flist.open(file_path) 707 self.flist.open(file_path)
690 else: 708 else:
691 self.io.loadfile(file_path) 709 self.io.loadfile(file_path)
692 return file_path 710 return file_path
693 711
694 def open_class_browser(self, event=None): 712 def open_class_browser(self, event=None):
695 filename = self.io.filename 713 filename = self.io.filename
696 if not (self.__class__.__name__ == 'PyShellEditorWindow' 714 if not (self.__class__.__name__ == 'PyShellEditorWindow'
697 and filename): 715 and filename):
698 filename = self.open_module() 716 filename = self.open_module()
699 if filename is None: 717 if filename is None:
700 return 718 return
701 head, tail = os.path.split(filename) 719 head, tail = os.path.split(filename)
702 base, ext = os.path.splitext(tail) 720 base, ext = os.path.splitext(tail)
703 from idlelib import ClassBrowser 721 from idlelib import ClassBrowser
704 ClassBrowser.ClassBrowser(self.flist, base, [head]) 722 ClassBrowser.ClassBrowser(self.flist, base, [head])
705 723
706 def open_path_browser(self, event=None): 724 def open_path_browser(self, event=None):
707 from idlelib import PathBrowser 725 from idlelib import PathBrowser
708 PathBrowser.PathBrowser(self.flist) 726 PathBrowser.PathBrowser(self.flist)
709 727
710 def open_turtle_demo(self, event = None):
711 import subprocess
712
713 cmd = [sys.executable,
714 '-c',
715 'from turtledemo.__main__ import main; main()']
716 subprocess.Popen(cmd, shell=False)
717
718 def gotoline(self, lineno): 728 def gotoline(self, lineno):
719 if lineno is not None and lineno > 0: 729 if lineno is not None and lineno > 0:
720 self.text.mark_set("insert", "%d.0" % lineno) 730 self.text.mark_set("insert", "%d.0" % lineno)
721 self.text.tag_remove("sel", "1.0", "end") 731 self.text.tag_remove("sel", "1.0", "end")
722 self.text.tag_add("sel", "insert", "insert +1l") 732 self.text.tag_add("sel", "insert", "insert +1l")
723 self.center() 733 self.center()
724 734
725 def ispythonsource(self, filename): 735 def ispythonsource(self, filename):
726 if not filename or os.path.isdir(filename): 736 if not filename or os.path.isdir(filename):
727 return True 737 return True
728 base, ext = os.path.splitext(os.path.basename(filename)) 738 base, ext = os.path.splitext(os.path.basename(filename))
729 if os.path.normcase(ext) in (".py", ".pyw"): 739 if os.path.normcase(ext) in (".py", ".pyw"):
730 return True 740 return True
731 line = self.text.get('1.0', '1.0 lineend') 741 try:
732 return line.startswith('#!') and 'python' in line 742 f = open(filename)
743 line = f.readline()
744 f.close()
745 except IOError:
746 return False
747 return line.startswith('#!') and line.find('python') >= 0
733 748
734 def close_hook(self): 749 def close_hook(self):
735 if self.flist: 750 if self.flist:
736 self.flist.unregister_maybe_terminate(self) 751 self.flist.unregister_maybe_terminate(self)
737 self.flist = None 752 self.flist = None
738 753
739 def set_close_hook(self, close_hook): 754 def set_close_hook(self, close_hook):
740 self.close_hook = close_hook 755 self.close_hook = close_hook
741 756
742 def filename_change_hook(self): 757 def filename_change_hook(self):
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') 789 cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
775 select_colors = idleConf.GetHighlight(theme, 'hilite') 790 select_colors = idleConf.GetHighlight(theme, 'hilite')
776 self.text.config( 791 self.text.config(
777 foreground=normal_colors['foreground'], 792 foreground=normal_colors['foreground'],
778 background=normal_colors['background'], 793 background=normal_colors['background'],
779 insertbackground=cursor_color, 794 insertbackground=cursor_color,
780 selectforeground=select_colors['foreground'], 795 selectforeground=select_colors['foreground'],
781 selectbackground=select_colors['background'], 796 selectbackground=select_colors['background'],
782 ) 797 )
783 798
784 IDENTCHARS = string.ascii_letters + string.digits + "_"
785
786 def colorize_syntax_error(self, text, pos):
787 text.tag_add("ERROR", pos)
788 char = text.get(pos)
789 if char and char in self.IDENTCHARS:
790 text.tag_add("ERROR", pos + " wordstart", pos)
791 if '\n' == text.get(pos): # error at line end
792 text.mark_set("insert", pos)
793 else:
794 text.mark_set("insert", pos + "+1c")
795 text.see(pos)
796
797 def ResetFont(self): 799 def ResetFont(self):
798 "Update the text widgets' font if it is changed" 800 "Update the text widgets' font if it is changed"
799 # Called from configDialog.py 801 # Called from configDialog.py
800 fontWeight='normal' 802 fontWeight='normal'
801 if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): 803 if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'):
802 fontWeight='bold' 804 fontWeight='bold'
803 self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 805 self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'),
804 idleConf.GetOption('main','EditorWindow','font-size', 806 idleConf.GetOption('main','EditorWindow','font-size',
805 type='int'), 807 type='int'),
806 fontWeight)) 808 fontWeight))
(...skipping 19 matching lines...) Expand all
826 xkeydefs = idleConf.GetExtensionBindings(extensionName) 828 xkeydefs = idleConf.GetExtensionBindings(extensionName)
827 if xkeydefs: 829 if xkeydefs:
828 self.apply_bindings(xkeydefs) 830 self.apply_bindings(xkeydefs)
829 #update menu accelerators 831 #update menu accelerators
830 menuEventDict = {} 832 menuEventDict = {}
831 for menu in self.Bindings.menudefs: 833 for menu in self.Bindings.menudefs:
832 menuEventDict[menu[0]] = {} 834 menuEventDict[menu[0]] = {}
833 for item in menu[1]: 835 for item in menu[1]:
834 if item: 836 if item:
835 menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1] 837 menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1]
836 for menubarItem in self.menudict: 838 for menubarItem in self.menudict.keys():
837 menu = self.menudict[menubarItem] 839 menu = self.menudict[menubarItem]
838 end = menu.index(END) 840 end = menu.index(END)
839 if end is None: 841 if end is None:
840 # Skip empty menus 842 # Skip empty menus
841 continue 843 continue
842 end += 1 844 end += 1
843 for index in range(0, end): 845 for index in range(0, end):
844 if menu.type(index) == 'command': 846 if menu.type(index) == 'command':
845 accel = menu.entrycget(index, 'accelerator') 847 accel = menu.entrycget(index, 'accelerator')
846 if accel: 848 if accel:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 self.menudict['help'] = helpmenu 880 self.menudict['help'] = helpmenu
879 881
880 def __extra_help_callback(self, helpfile): 882 def __extra_help_callback(self, helpfile):
881 "Create a callback with the helpfile value frozen at definition time" 883 "Create a callback with the helpfile value frozen at definition time"
882 def display_extra_help(helpfile=helpfile): 884 def display_extra_help(helpfile=helpfile):
883 if not helpfile.startswith(('www', 'http')): 885 if not helpfile.startswith(('www', 'http')):
884 helpfile = os.path.normpath(helpfile) 886 helpfile = os.path.normpath(helpfile)
885 if sys.platform[:3] == 'win': 887 if sys.platform[:3] == 'win':
886 try: 888 try:
887 os.startfile(helpfile) 889 os.startfile(helpfile)
888 except OSError as why: 890 except WindowsError as why:
889 tkMessageBox.showerror(title='Document Start Failure', 891 tkMessageBox.showerror(title='Document Start Failure',
890 message=str(why), parent=self.text) 892 message=str(why), parent=self.text)
891 else: 893 else:
892 webbrowser.open(helpfile) 894 webbrowser.open(helpfile)
893 return display_extra_help 895 return display_extra_help
894 896
895 def update_recent_files_list(self, new_file=None): 897 def update_recent_files_list(self, new_file=None):
896 "Load and update the recent files list and menus" 898 "Load and update the recent files list and menus"
897 rf_list = [] 899 rf_list = []
898 if os.path.exists(self.recent_files_path): 900 if os.path.exists(self.recent_files_path):
899 with open(self.recent_files_path, 'r', 901 with open(self.recent_files_path, 'r') as rf_list_file:
900 encoding='utf_8', errors='replace') as rf_list_file:
901 rf_list = rf_list_file.readlines() 902 rf_list = rf_list_file.readlines()
902 if new_file: 903 if new_file:
903 new_file = os.path.abspath(new_file) + '\n' 904 new_file = os.path.abspath(new_file) + '\n'
904 if new_file in rf_list: 905 if new_file in rf_list:
905 rf_list.remove(new_file) # move to top 906 rf_list.remove(new_file) # move to top
906 rf_list.insert(0, new_file) 907 rf_list.insert(0, new_file)
907 # clean and save the recent files list 908 # clean and save the recent files list
908 bad_paths = [] 909 bad_paths = []
909 for path in rf_list: 910 for path in rf_list:
910 if '\0' in path or not os.path.exists(path[0:-1]): 911 if '\0' in path or not os.path.exists(path[0:-1]):
911 bad_paths.append(path) 912 bad_paths.append(path)
912 rf_list = [path for path in rf_list if path not in bad_paths] 913 rf_list = [path for path in rf_list if path not in bad_paths]
913 ulchars = "1234567890ABCDEFGHIJK" 914 ulchars = "1234567890ABCDEFGHIJK"
914 rf_list = rf_list[0:len(ulchars)] 915 rf_list = rf_list[0:len(ulchars)]
915 try: 916 try:
916 with open(self.recent_files_path, 'w', 917 with open(self.recent_files_path, 'w') as rf_file:
917 encoding='utf_8', errors='replace') as rf_file:
918 rf_file.writelines(rf_list) 918 rf_file.writelines(rf_list)
919 except OSError as err: 919 except IOError as err:
920 if not getattr(self.root, "recentfilelist_error_displayed", False): 920 if not getattr(self.root, "recentfilelist_error_displayed", False):
921 self.root.recentfilelist_error_displayed = True 921 self.root.recentfilelist_error_displayed = True
922 tkMessageBox.showerror(title='IDLE Error', 922 tkMessageBox.showerror(title='IDLE Error',
923 message='Unable to update Recent Files list:\n%s' 923 message='Unable to update Recent Files list:\n%s'
924 % str(err), 924 % str(err),
925 parent=self.text) 925 parent=self.text)
926 # for each edit window instance, construct the recent files menu 926 # for each edit window instance, construct the recent files menu
927 for instance in self.top.instance_dict: 927 for instance in self.top.instance_dict.keys():
928 menu = instance.recent_files_menu 928 menu = instance.recent_files_menu
929 menu.delete(0, END) # clear, and rebuild: 929 menu.delete(0, END) # clear, and rebuild:
930 for i, file_name in enumerate(rf_list): 930 for i, file_name in enumerate(rf_list):
931 file_name = file_name.rstrip() # zap \n 931 file_name = file_name.rstrip() # zap \n
932 # make unicode string to display non-ASCII chars correctly 932 # make unicode string to display non-ASCII chars correctly
933 ufile_name = self._filename_to_unicode(file_name) 933 ufile_name = self._filename_to_unicode(file_name)
934 callback = instance.__recent_file_callback(file_name) 934 callback = instance.__recent_file_callback(file_name)
935 menu.add_command(label=ulchars[i] + " " + ufile_name, 935 menu.add_command(label=ulchars[i] + " " + ufile_name,
936 command=callback, 936 command=callback,
937 underline=0) 937 underline=0)
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 return top, bot 1003 return top, bot
1004 1004
1005 def getlineno(self, mark="insert"): 1005 def getlineno(self, mark="insert"):
1006 text = self.text 1006 text = self.text
1007 return int(float(text.index(mark))) 1007 return int(float(text.index(mark)))
1008 1008
1009 def get_geometry(self): 1009 def get_geometry(self):
1010 "Return (width, height, x, y)" 1010 "Return (width, height, x, y)"
1011 geom = self.top.wm_geometry() 1011 geom = self.top.wm_geometry()
1012 m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) 1012 m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom)
1013 return list(map(int, m.groups())) 1013 tuple = (map(int, m.groups()))
1014 return tuple
1014 1015
1015 def close_event(self, event): 1016 def close_event(self, event):
1016 self.close() 1017 self.close()
1017 1018
1018 def maybesave(self): 1019 def maybesave(self):
1019 if self.io: 1020 if self.io:
1020 if not self.get_saved(): 1021 if not self.get_saved():
1021 if self.top.state()!='normal': 1022 if self.top.state()!='normal':
1022 self.top.deiconify() 1023 self.top.deiconify()
1023 self.top.lower() 1024 self.top.lower()
(...skipping 24 matching lines...) Expand all
1048 self.top.destroy() 1049 self.top.destroy()
1049 if self.close_hook: 1050 if self.close_hook:
1050 # unless override: unregister from flist, terminate if last window 1051 # unless override: unregister from flist, terminate if last window
1051 self.close_hook() 1052 self.close_hook()
1052 1053
1053 def load_extensions(self): 1054 def load_extensions(self):
1054 self.extensions = {} 1055 self.extensions = {}
1055 self.load_standard_extensions() 1056 self.load_standard_extensions()
1056 1057
1057 def unload_extensions(self): 1058 def unload_extensions(self):
1058 for ins in list(self.extensions.values()): 1059 for ins in self.extensions.values():
1059 if hasattr(ins, "close"): 1060 if hasattr(ins, "close"):
1060 ins.close() 1061 ins.close()
1061 self.extensions = {} 1062 self.extensions = {}
1062 1063
1063 def load_standard_extensions(self): 1064 def load_standard_extensions(self):
1064 for name in self.get_standard_extension_names(): 1065 for name in self.get_standard_extension_names():
1065 try: 1066 try:
1066 self.load_extension(name) 1067 self.load_extension(name)
1067 except: 1068 except:
1068 print("Failed to load extension", repr(name)) 1069 print "Failed to load extension", repr(name)
1070 import traceback
1069 traceback.print_exc() 1071 traceback.print_exc()
1070 1072
1071 def get_standard_extension_names(self): 1073 def get_standard_extension_names(self):
1072 return idleConf.GetExtensions(editor_only=True) 1074 return idleConf.GetExtensions(editor_only=True)
1073 1075
1074 def load_extension(self, name): 1076 def load_extension(self, name):
1075 try: 1077 try:
1076 try: 1078 mod = __import__(name, globals(), locals(), [])
1077 mod = importlib.import_module('.' + name, package=__package__)
1078 except (ImportError, TypeError):
1079 mod = importlib.import_module(name)
1080 except ImportError: 1079 except ImportError:
1081 print("\nFailed to import extension: ", name) 1080 print "\nFailed to import extension: ", name
1082 raise 1081 return
1083 cls = getattr(mod, name) 1082 cls = getattr(mod, name)
1084 keydefs = idleConf.GetExtensionBindings(name) 1083 keydefs = idleConf.GetExtensionBindings(name)
1085 if hasattr(cls, "menudefs"): 1084 if hasattr(cls, "menudefs"):
1086 self.fill_menus(cls.menudefs, keydefs) 1085 self.fill_menus(cls.menudefs, keydefs)
1087 ins = cls(self) 1086 ins = cls(self)
1088 self.extensions[name] = ins 1087 self.extensions[name] = ins
1089 if keydefs: 1088 if keydefs:
1090 self.apply_bindings(keydefs) 1089 self.apply_bindings(keydefs)
1091 for vevent in keydefs: 1090 for vevent in keydefs.keys():
1092 methodname = vevent.replace("-", "_") 1091 methodname = vevent.replace("-", "_")
1093 while methodname[:1] == '<': 1092 while methodname[:1] == '<':
1094 methodname = methodname[1:] 1093 methodname = methodname[1:]
1095 while methodname[-1:] == '>': 1094 while methodname[-1:] == '>':
1096 methodname = methodname[:-1] 1095 methodname = methodname[:-1]
1097 methodname = methodname + "_event" 1096 methodname = methodname + "_event"
1098 if hasattr(ins, methodname): 1097 if hasattr(ins, methodname):
1099 self.text.bind(vevent, getattr(ins, methodname)) 1098 self.text.bind(vevent, getattr(ins, methodname))
1100 1099
1101 def apply_bindings(self, keydefs=None): 1100 def apply_bindings(self, keydefs=None):
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 menu.add_command(label=label, underline=underline, 1142 menu.add_command(label=label, underline=underline,
1144 command=command, 1143 command=command,
1145 accelerator=accelerator) 1144 accelerator=accelerator)
1146 1145
1147 def getvar(self, name): 1146 def getvar(self, name):
1148 var = self.get_var_obj(name) 1147 var = self.get_var_obj(name)
1149 if var: 1148 if var:
1150 value = var.get() 1149 value = var.get()
1151 return value 1150 return value
1152 else: 1151 else:
1153 raise NameError(name) 1152 raise NameError, name
1154 1153
1155 def setvar(self, name, value, vartype=None): 1154 def setvar(self, name, value, vartype=None):
1156 var = self.get_var_obj(name, vartype) 1155 var = self.get_var_obj(name, vartype)
1157 if var: 1156 if var:
1158 var.set(value) 1157 var.set(value)
1159 else: 1158 else:
1160 raise NameError(name) 1159 raise NameError, name
1161 1160
1162 def get_var_obj(self, name, vartype=None): 1161 def get_var_obj(self, name, vartype=None):
1163 var = self.tkinter_vars.get(name) 1162 var = self.tkinter_vars.get(name)
1164 if not var and vartype: 1163 if not var and vartype:
1165 # create a Tkinter variable object with self.text as master: 1164 # create a Tkinter variable object with self.text as master:
1166 self.tkinter_vars[name] = var = vartype(self.text) 1165 self.tkinter_vars[name] = var = vartype(self.text)
1167 return var 1166 return var
1168 1167
1169 # Tk implementations of "virtual text methods" -- each platform 1168 # Tk implementations of "virtual text methods" -- each platform
1170 # reusing IDLE's support code needs to define these for its GUI's 1169 # reusing IDLE's support code needs to define these for its GUI's
(...skipping 20 matching lines...) Expand all
1191 try: 1190 try:
1192 first = self.text.index("sel.first") 1191 first = self.text.index("sel.first")
1193 last = self.text.index("sel.last") 1192 last = self.text.index("sel.last")
1194 return first, last 1193 return first, last
1195 except TclError: 1194 except TclError:
1196 return None, None 1195 return None, None
1197 1196
1198 # Return the text widget's current view of what a tab stop means 1197 # Return the text widget's current view of what a tab stop means
1199 # (equivalent width in spaces). 1198 # (equivalent width in spaces).
1200 1199
1201 def get_tk_tabwidth(self): 1200 def get_tabwidth(self):
1202 current = self.text['tabs'] or TK_TABWIDTH_DEFAULT 1201 current = self.text['tabs'] or TK_TABWIDTH_DEFAULT
1203 return int(current) 1202 return int(current)
1204 1203
1205 # Set the text widget's current view of what a tab stop means. 1204 # Set the text widget's current view of what a tab stop means.
1206 1205
1207 def set_tk_tabwidth(self, newtabwidth): 1206 def set_tabwidth(self, newtabwidth):
1208 text = self.text 1207 text = self.text
1209 if self.get_tk_tabwidth() != newtabwidth: 1208 if self.get_tabwidth() != newtabwidth:
1210 # Set text widget tab width
1211 pixels = text.tk.call("font", "measure", text["font"], 1209 pixels = text.tk.call("font", "measure", text["font"],
1212 "-displayof", text.master, 1210 "-displayof", text.master,
1213 "n" * newtabwidth) 1211 "n" * newtabwidth)
1214 text.configure(tabs=pixels) 1212 text.configure(tabs=pixels)
1215 1213
1216 ### begin autoindent code ### (configuration was moved to beginning of class) 1214 # If ispythonsource and guess are true, guess a good value for
1217 1215 # indentwidth based on file content (if possible), and if
1218 def set_indentation_params(self, is_py_src, guess=True): 1216 # indentwidth != tabwidth set usetabs false.
1219 if is_py_src and guess: 1217 # In any case, adjust the Text widget's view of what a tab
1218 # character means.
1219
1220 def set_indentation_params(self, ispythonsource, guess=True):
1221 if guess and ispythonsource:
1220 i = self.guess_indent() 1222 i = self.guess_indent()
1221 if 2 <= i <= 8: 1223 if 2 <= i <= 8:
1222 self.indentwidth = i 1224 self.indentwidth = i
1223 if self.indentwidth != self.tabwidth: 1225 if self.indentwidth != self.tabwidth:
1224 self.usetabs = False 1226 self.usetabs = False
1225 self.set_tk_tabwidth(self.tabwidth) 1227 self.set_tabwidth(self.tabwidth)
1226 1228
1227 def smart_backspace_event(self, event): 1229 def smart_backspace_event(self, event):
1228 text = self.text 1230 text = self.text
1229 first, last = self.get_selection_indices() 1231 first, last = self.get_selection_indices()
1230 if first and last: 1232 if first and last:
1231 text.delete(first, last) 1233 text.delete(first, last)
1232 text.mark_set("insert", first) 1234 text.mark_set("insert", first)
1233 return "break" 1235 return "break"
1234 # Delete whitespace left, until hitting a real char or closest 1236 # Delete whitespace left, until hitting a real char or closest
1235 # preceding virtual tab stop. 1237 # preceding virtual tab stop.
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1645 self.blkopenline = line 1647 self.blkopenline = line
1646 elif type == INDENT and self.blkopenline: 1648 elif type == INDENT and self.blkopenline:
1647 self.indentedline = line 1649 self.indentedline = line
1648 self.finished = 1 1650 self.finished = 1
1649 1651
1650 def run(self): 1652 def run(self):
1651 save_tabsize = _tokenize.tabsize 1653 save_tabsize = _tokenize.tabsize
1652 _tokenize.tabsize = self.tabwidth 1654 _tokenize.tabsize = self.tabwidth
1653 try: 1655 try:
1654 try: 1656 try:
1655 tokens = _tokenize.generate_tokens(self.readline) 1657 _tokenize.tokenize(self.readline, self.tokeneater)
1656 for token in tokens:
1657 self.tokeneater(*token)
1658 except (_tokenize.TokenError, SyntaxError): 1658 except (_tokenize.TokenError, SyntaxError):
1659 # since we cut off the tokenizer early, we can trigger 1659 # since we cut off the tokenizer early, we can trigger
1660 # spurious errors 1660 # spurious errors
1661 pass 1661 pass
1662 finally: 1662 finally:
1663 _tokenize.tabsize = save_tabsize 1663 _tokenize.tabsize = save_tabsize
1664 return self.blkopenline, self.indentedline 1664 return self.blkopenline, self.indentedline
1665 1665
1666 ### end autoindent code ### 1666 ### end autoindent code ###
1667 1667
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1718 if sys.argv[1:]: 1718 if sys.argv[1:]:
1719 filename = sys.argv[1] 1719 filename = sys.argv[1]
1720 else: 1720 else:
1721 filename = None 1721 filename = None
1722 macosxSupport.setupApp(root, None) 1722 macosxSupport.setupApp(root, None)
1723 edit = EditorWindow(root=root, filename=filename) 1723 edit = EditorWindow(root=root, filename=filename)
1724 edit.text.bind("<<close-all-windows>>", edit.close_event) 1724 edit.text.bind("<<close-all-windows>>", edit.close_event)
1725 # Does not stop error, neither does following 1725 # Does not stop error, neither does following
1726 # edit.text.bind("<<close-window>>", edit.close_event) 1726 # edit.text.bind("<<close-window>>", edit.close_event)
1727 1727
1728
1728 if __name__ == '__main__': 1729 if __name__ == '__main__':
1729 from idlelib.idle_test.htest import run 1730 from idlelib.idle_test.htest import run
1730 run(_help_dialog, _editor_window) 1731 run(_help_dialog, _editor_window)
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+