Changeset 391 for python/trunk/Lib/idlelib/EditorWindow.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/idlelib/EditorWindow.py
r2 r391 3 3 import re 4 4 import imp 5 from itertools import count6 5 from Tkinter import * 7 6 import tkSimpleDialog 8 7 import tkMessageBox 9 from MultiCall import MultiCallCreator10 11 8 import webbrowser 12 import idlever 13 import WindowList 14 import SearchDialog 15 import GrepDialog 16 import ReplaceDialog 17 import PyParse 18 from configHandler import idleConf 19 import aboutDialog, textView, configDialog 20 import macosxSupport 9 10 from idlelib.MultiCall import MultiCallCreator 11 from idlelib import idlever 12 from idlelib import WindowList 13 from idlelib import SearchDialog 14 from idlelib import GrepDialog 15 from idlelib import ReplaceDialog 16 from idlelib import PyParse 17 from idlelib.configHandler import idleConf 18 from idlelib import aboutDialog, textView, configDialog 19 from idlelib import macosxSupport 21 20 22 21 # The default tab setting for a Text widget, in average-width characters. … … 28 27 release = '%s%s' % (major, minor) 29 28 if micro: 30 release += '%s' % micro 31 if level != 'final': 29 release += '%s' % (micro,) 30 if level == 'candidate': 31 release += 'rc%s' % (serial,) 32 elif level != 'final': 32 33 release += '%s%s' % (level[0], serial) 33 34 return release … … 48 49 except AttributeError: 49 50 raise ImportError, 'No source for module ' + module.__name__ 51 if descr[2] != imp.PY_SOURCE: 52 # If all of the above fails and didn't raise an exception,fallback 53 # to a straight import which can find __init__.py in a package. 54 m = __import__(fullname) 55 try: 56 filename = m.__file__ 57 except AttributeError: 58 pass 59 else: 60 file = None 61 base, ext = os.path.splitext(filename) 62 if ext == '.pyc': 63 ext = '.py' 64 filename = base + ext 65 descr = filename, None, imp.PY_SOURCE 50 66 return file, filename, descr 51 67 68 69 class HelpDialog(object): 70 71 def __init__(self): 72 self.parent = None # parent of help window 73 self.dlg = None # the help window iteself 74 75 def display(self, parent, near=None): 76 """ Display the help dialog. 77 78 parent - parent widget for the help window 79 80 near - a Toplevel widget (e.g. EditorWindow or PyShell) 81 to use as a reference for placing the help window 82 """ 83 if self.dlg is None: 84 self.show_dialog(parent) 85 if near: 86 self.nearwindow(near) 87 88 def show_dialog(self, parent): 89 self.parent = parent 90 fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') 91 self.dlg = dlg = textView.view_file(parent,'Help',fn, modal=False) 92 dlg.bind('<Destroy>', self.destroy, '+') 93 94 def nearwindow(self, near): 95 # Place the help dialog near the window specified by parent. 96 # Note - this may not reposition the window in Metacity 97 # if "/apps/metacity/general/disable_workarounds" is enabled 98 dlg = self.dlg 99 geom = (near.winfo_rootx() + 10, near.winfo_rooty() + 10) 100 dlg.withdraw() 101 dlg.geometry("=+%d+%d" % geom) 102 dlg.deiconify() 103 dlg.lift() 104 105 def destroy(self, ev=None): 106 self.dlg = None 107 self.parent = None 108 109 helpDialog = HelpDialog() # singleton instance 110 111 52 112 class EditorWindow(object): 53 from Percolator import Percolator54 from ColorDelegator import ColorDelegator55 from UndoDelegator import UndoDelegator56 from IOBinding import IOBinding, filesystemencoding, encoding57 import Bindings113 from idlelib.Percolator import Percolator 114 from idlelib.ColorDelegator import ColorDelegator 115 from idlelib.UndoDelegator import UndoDelegator 116 from idlelib.IOBinding import IOBinding, filesystemencoding, encoding 117 from idlelib import Bindings 58 118 from Tkinter import Toplevel 59 from MultiStatusBar import MultiStatusBar119 from idlelib.MultiStatusBar import MultiStatusBar 60 120 61 121 help_url = None … … 102 162 if flist: 103 163 self.tkinter_vars = flist.vars 104 #self.top.instance_dict makes flist.inversedict ava lable to105 #configDialog.py so it can access all EditorWindow insta ces164 #self.top.instance_dict makes flist.inversedict available to 165 #configDialog.py so it can access all EditorWindow instances 106 166 self.top.instance_dict = flist.inversedict 107 167 else: … … 113 173 self.text_frame = text_frame = Frame(top) 114 174 self.vbar = vbar = Scrollbar(text_frame, name='vbar') 115 self.width = idleConf.GetOption('main','EditorWindow','width' )175 self.width = idleConf.GetOption('main','EditorWindow','width', type='int') 116 176 text_options = { 117 177 'name': 'text', … … 119 179 'wrap': 'none', 120 180 'width': self.width, 121 'height': idleConf.GetOption('main', 'EditorWindow', 'height' )}181 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')} 122 182 if TkVersion >= 8.5: 123 183 # Starting with tk 8.5 we have to set the new tabstyle option … … 136 196 # Command-W on editorwindows doesn't work without this. 137 197 text.bind('<<close-window>>', self.close_event) 198 # Some OS X systems have only one mouse button, 199 # so use control-click for pulldown menus there. 200 # (Note, AquaTk defines <2> as the right button if 201 # present and the Tk Text widget already binds <2>.) 202 text.bind("<Control-Button-1>",self.right_menu_event) 203 else: 204 # Elsewhere, use right-click for pulldown menus. 205 text.bind("<3>",self.right_menu_event) 138 206 text.bind("<<cut>>", self.cut) 139 207 text.bind("<<copy>>", self.copy) … … 154 222 text.bind("<<replace>>", self.replace_event) 155 223 text.bind("<<goto-line>>", self.goto_line_event) 156 text.bind("<3>", self.right_menu_event)157 224 text.bind("<<smart-backspace>>",self.smart_backspace_event) 158 225 text.bind("<<newline-and-indent>>",self.newline_and_indent_event) … … 189 256 fontWeight='bold' 190 257 text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), 191 idleConf.GetOption('main', 'EditorWindow', 'font-size'), 258 idleConf.GetOption('main', 'EditorWindow', 259 'font-size', type='int'), 192 260 fontWeight)) 193 261 text_frame.pack(side=LEFT, fill=BOTH, expand=1) … … 279 347 self.showerror = tkMessageBox.showerror 280 348 349 self._highlight_workaround() # Fix selection tags on Windows 350 351 def _highlight_workaround(self): 352 # On Windows, Tk removes painting of the selection 353 # tags which is different behavior than on Linux and Mac. 354 # See issue14146 for more information. 355 if not sys.platform.startswith('win'): 356 return 357 358 text = self.text 359 text.event_add("<<Highlight-FocusOut>>", "<FocusOut>") 360 text.event_add("<<Highlight-FocusIn>>", "<FocusIn>") 361 def highlight_fix(focus): 362 sel_range = text.tag_ranges("sel") 363 if sel_range: 364 if focus == 'out': 365 HILITE_CONFIG = idleConf.GetHighlight( 366 idleConf.CurrentTheme(), 'hilite') 367 text.tag_config("sel_fix", HILITE_CONFIG) 368 text.tag_raise("sel_fix") 369 text.tag_add("sel_fix", *sel_range) 370 elif focus == 'in': 371 text.tag_remove("sel_fix", "1.0", "end") 372 373 text.bind("<<Highlight-FocusOut>>", 374 lambda ev: highlight_fix("out")) 375 text.bind("<<Highlight-FocusIn>>", 376 lambda ev: highlight_fix("in")) 377 378 281 379 def _filename_to_unicode(self, filename): 282 380 """convert filename to unicode in order to display it in Tk""" … … 300 398 301 399 def home_callback(self, event): 302 if (event.state & 12) != 0 and event.keysym == "Home": 303 # state&1==shift, state&4==control, state&8==alt 304 return # <Modifier-Home>; fall back to class binding 305 400 if (event.state & 4) != 0 and event.keysym == "Home": 401 # state&4==Control. If <Control-Home>, use the Tk binding. 402 return 306 403 if self.text.index("iomark") and \ 307 404 self.text.compare("iomark", "<=", "insert lineend") and \ 308 405 self.text.compare("insert linestart", "<=", "iomark"): 406 # In Shell on input line, go to just after prompt 309 407 insertpt = int(self.text.index("iomark").split(".")[1]) 310 408 else: … … 315 413 else: 316 414 insertpt=len(line) 317 318 415 lineat = int(self.text.index("insert").split('.')[1]) 319 320 416 if insertpt == lineat: 321 417 insertpt = 0 322 323 418 dest = "insert linestart+"+str(insertpt)+"c" 324 325 419 if (event.state&1) == 0: 326 # shift not pressed420 # shift was not pressed 327 421 self.text.tag_remove("sel", "1.0", "end") 328 422 else: 329 423 if not self.text.index("sel.first"): 330 self.text.mark_set("anchor","insert") 331 424 self.text.mark_set("my_anchor", "insert") # there was no previous selection 425 else: 426 if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")): 427 self.text.mark_set("my_anchor", "sel.first") # extend back 428 else: 429 self.text.mark_set("my_anchor", "sel.last") # extend forward 332 430 first = self.text.index(dest) 333 last = self.text.index("anchor") 334 431 last = self.text.index("my_anchor") 335 432 if self.text.compare(first,">",last): 336 433 first,last = last,first 337 338 434 self.text.tag_remove("sel", "1.0", "end") 339 435 self.text.tag_add("sel", first, last) 340 341 436 self.text.mark_set("insert", dest) 342 437 self.text.see("insert") … … 373 468 374 469 if macosxSupport.runningAsOSXApp(): 375 del menu_specs[-3]376 470 menu_specs[-2] = ("windows", "_Window") 377 471 … … 385 479 mbar.add_cascade(label=label, menu=menu, underline=underline) 386 480 387 if macosxSupport. runningAsOSXApp():481 if macosxSupport.isCarbonAquaTk(self.root): 388 482 # Insert the application menu 389 483 menudict['application'] = menu = Menu(mbar, name='apple') … … 407 501 408 502 def right_menu_event(self, event): 409 self.text.tag_remove("sel", "1.0", "end")410 503 self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) 411 504 if not self.rmenu: … … 416 509 if iswin: 417 510 self.text.config(cursor="arrow") 511 512 for item in self.rmenu_specs: 513 try: 514 label, eventname, verify_state = item 515 except ValueError: # see issue1207589 516 continue 517 518 if verify_state is None: 519 continue 520 state = getattr(self, verify_state)() 521 rmenu.entryconfigure(label, state=state) 522 418 523 rmenu.tk_popup(event.x_root, event.y_root) 419 524 if iswin: … … 421 526 422 527 rmenu_specs = [ 423 # ("Label", "<<virtual-event>>" ), ...424 ("Close", "<<close-window>>" ), # Example528 # ("Label", "<<virtual-event>>", "statefuncname"), ... 529 ("Close", "<<close-window>>", None), # Example 425 530 ] 426 531 427 532 def make_rmenu(self): 428 533 rmenu = Menu(self.text, tearoff=0) 429 for label, eventname in self.rmenu_specs: 430 def command(text=self.text, eventname=eventname): 431 text.event_generate(eventname) 432 rmenu.add_command(label=label, command=command) 534 for item in self.rmenu_specs: 535 label, eventname = item[0], item[1] 536 if label is not None: 537 def command(text=self.text, eventname=eventname): 538 text.event_generate(eventname) 539 rmenu.add_command(label=label, command=command) 540 else: 541 rmenu.add_separator() 433 542 self.rmenu = rmenu 543 544 def rmenu_check_cut(self): 545 return self.rmenu_check_copy() 546 547 def rmenu_check_copy(self): 548 try: 549 indx = self.text.index('sel.first') 550 except TclError: 551 return 'disabled' 552 else: 553 return 'normal' if indx else 'disabled' 554 555 def rmenu_check_paste(self): 556 try: 557 self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') 558 except TclError: 559 return 'disabled' 560 else: 561 return 'normal' 434 562 435 563 def about_dialog(self, event=None): … … 440 568 441 569 def help_dialog(self, event=None): 442 fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') 443 textView.view_file(self.top,'Help',fn) 570 if self.root: 571 parent = self.root 572 else: 573 parent = self.top 574 helpDialog.display(parent, near=self.top) 444 575 445 576 def python_docs(self, event=None): 446 577 if sys.platform[:3] == 'win': 447 os.startfile(self.help_url) 578 try: 579 os.startfile(self.help_url) 580 except WindowsError as why: 581 tkMessageBox.showerror(title='Document Start Failure', 582 message=str(why), parent=self.text) 448 583 else: 449 584 webbrowser.open(self.help_url) … … 555 690 try: 556 691 (f, file, (suffix, mode, type)) = _find_module(name) 557 except (NameError, ImportError) ,msg:692 except (NameError, ImportError) as msg: 558 693 tkMessageBox.showerror("Import error", str(msg), parent=self.text) 559 694 return … … 580 715 head, tail = os.path.split(filename) 581 716 base, ext = os.path.splitext(tail) 582 import ClassBrowser717 from idlelib import ClassBrowser 583 718 ClassBrowser.ClassBrowser(self.flist, base, [head]) 584 719 585 720 def open_path_browser(self, event=None): 586 import PathBrowser721 from idlelib import PathBrowser 587 722 PathBrowser.PathBrowser(self.flist) 588 723 … … 665 800 fontWeight='bold' 666 801 self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 667 idleConf.GetOption('main','EditorWindow','font-size'), 802 idleConf.GetOption('main','EditorWindow','font-size', 803 type='int'), 668 804 fontWeight)) 669 805 … … 698 834 for menubarItem in self.menudict.keys(): 699 835 menu = self.menudict[menubarItem] 700 end = menu.index(END) + 1 836 end = menu.index(END) 837 if end is None: 838 # Skip empty menus 839 continue 840 end += 1 701 841 for index in range(0, end): 702 842 if menu.type(index) == 'command': … … 705 845 itemName = menu.entrycget(index, 'label') 706 846 event = '' 707 if menu EventDict.has_key(menubarItem):708 if menuEventDict[menubarItem].has_key(itemName):847 if menubarItem in menuEventDict: 848 if itemName in menuEventDict[menubarItem]: 709 849 event = menuEventDict[menubarItem][itemName] 710 850 if event: … … 740 880 def display_extra_help(helpfile=helpfile): 741 881 if not helpfile.startswith(('www', 'http')): 742 url= os.path.normpath(helpfile)882 helpfile = os.path.normpath(helpfile) 743 883 if sys.platform[:3] == 'win': 744 os.startfile(helpfile) 884 try: 885 os.startfile(helpfile) 886 except WindowsError as why: 887 tkMessageBox.showerror(title='Document Start Failure', 888 message=str(why), parent=self.text) 745 889 else: 746 890 webbrowser.open(helpfile) … … 751 895 rf_list = [] 752 896 if os.path.exists(self.recent_files_path): 753 rf_list_file = open(self.recent_files_path,'r') 754 try: 897 with open(self.recent_files_path, 'r') as rf_list_file: 755 898 rf_list = rf_list_file.readlines() 756 finally:757 rf_list_file.close()758 899 if new_file: 759 900 new_file = os.path.abspath(new_file) + '\n' … … 769 910 ulchars = "1234567890ABCDEFGHIJK" 770 911 rf_list = rf_list[0:len(ulchars)] 771 rf_file = open(self.recent_files_path, 'w')772 912 try: 773 rf_file.writelines(rf_list) 774 finally: 775 rf_file.close() 913 with open(self.recent_files_path, 'w') as rf_file: 914 rf_file.writelines(rf_list) 915 except IOError as err: 916 if not getattr(self.root, "recentfilelist_error_displayed", False): 917 self.root.recentfilelist_error_displayed = True 918 tkMessageBox.showerror(title='IDLE Error', 919 message='Unable to update Recent Files list:\n%s' 920 % str(err), 921 parent=self.text) 776 922 # for each edit window instance, construct the recent files menu 777 923 for instance in self.top.instance_dict.keys(): 778 924 menu = instance.recent_files_menu 779 menu.delete( 1, END) # clear, and rebuild:780 for i, file in zip(count(),rf_list):781 file_name = file [0:-1]# zap \n925 menu.delete(0, END) # clear, and rebuild: 926 for i, file_name in enumerate(rf_list): 927 file_name = file_name.rstrip() # zap \n 782 928 # make unicode string to display non-ASCII chars correctly 783 929 ufile_name = self._filename_to_unicode(file_name) … … 1103 1249 want = ((have - 1) // self.indentwidth) * self.indentwidth 1104 1250 # Debug prompt is multilined.... 1105 last_line_of_prompt = sys.ps1.split('\n')[-1] 1251 if self.context_use_ps1: 1252 last_line_of_prompt = sys.ps1.split('\n')[-1] 1253 else: 1254 last_line_of_prompt = '' 1106 1255 ncharsdeleted = 0 1107 1256 while 1: … … 1194 1343 for context in self.num_context_lines: 1195 1344 startat = max(lno - context, 1) 1196 startatindex = `startat`+ ".0"1345 startatindex = repr(startat) + ".0" 1197 1346 rawtext = text.get(startatindex, "insert") 1198 1347 y.set_str(rawtext) … … 1313 1462 head, tail, chars, lines = self.get_region() 1314 1463 tabwidth = self._asktabwidth() 1464 if tabwidth is None: return 1315 1465 for pos in range(len(lines)): 1316 1466 line = lines[pos] … … 1324 1474 head, tail, chars, lines = self.get_region() 1325 1475 tabwidth = self._asktabwidth() 1476 if tabwidth is None: return 1326 1477 for pos in range(len(lines)): 1327 1478 lines[pos] = lines[pos].expandtabs(tabwidth) … … 1417 1568 initialvalue=self.indentwidth, 1418 1569 minvalue=2, 1419 maxvalue=16) or self.tabwidth1570 maxvalue=16) 1420 1571 1421 1572 # Guess indentwidth from text content. … … 1499 1650 try: 1500 1651 _tokenize.tokenize(self.readline, self.tokeneater) 1501 except _tokenize.TokenError:1652 except (_tokenize.TokenError, SyntaxError): 1502 1653 # since we cut off the tokenizer early, we can trigger 1503 1654 # spurious errors … … 1526 1677 def get_accelerator(keydefs, eventname): 1527 1678 keylist = keydefs.get(eventname) 1528 if not keylist: 1679 # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 1680 # if not keylist: 1681 if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in { 1682 "<<open-module>>", 1683 "<<goto-line>>", 1684 "<<change-indentwidth>>"}): 1529 1685 return "" 1530 1686 s = keylist[0]
Note:
See TracChangeset
for help on using the changeset viewer.