Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/idlelib/EditorWindow.py

    r2 r391  
    33import re
    44import imp
    5 from itertools import count
    65from Tkinter import *
    76import tkSimpleDialog
    87import tkMessageBox
    9 from MultiCall import MultiCallCreator
    10 
    118import 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
     10from idlelib.MultiCall import MultiCallCreator
     11from idlelib import idlever
     12from idlelib import WindowList
     13from idlelib import SearchDialog
     14from idlelib import GrepDialog
     15from idlelib import ReplaceDialog
     16from idlelib import PyParse
     17from idlelib.configHandler import idleConf
     18from idlelib import aboutDialog, textView, configDialog
     19from idlelib import macosxSupport
    2120
    2221# The default tab setting for a Text widget, in average-width characters.
     
    2827    release = '%s%s' % (major, minor)
    2928    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':
    3233        release += '%s%s' % (level[0], serial)
    3334    return release
     
    4849        except AttributeError:
    4950            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
    5066    return file, filename, descr
    5167
     68
     69class 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
     109helpDialog = HelpDialog()  # singleton instance
     110
     111
    52112class EditorWindow(object):
    53     from Percolator import Percolator
    54     from ColorDelegator import ColorDelegator
    55     from UndoDelegator import UndoDelegator
    56     from IOBinding import IOBinding, filesystemencoding, encoding
    57     import Bindings
     113    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
    58118    from Tkinter import Toplevel
    59     from MultiStatusBar import MultiStatusBar
     119    from idlelib.MultiStatusBar import MultiStatusBar
    60120
    61121    help_url = None
     
    102162        if flist:
    103163            self.tkinter_vars = flist.vars
    104             #self.top.instance_dict makes flist.inversedict avalable to
    105             #configDialog.py so it can access all EditorWindow instaces
     164            #self.top.instance_dict makes flist.inversedict available to
     165            #configDialog.py so it can access all EditorWindow instances
    106166            self.top.instance_dict = flist.inversedict
    107167        else:
     
    113173        self.text_frame = text_frame = Frame(top)
    114174        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')
    116176        text_options = {
    117177                'name': 'text',
     
    119179                'wrap': 'none',
    120180                'width': self.width,
    121                 'height': idleConf.GetOption('main', 'EditorWindow', 'height')}
     181                'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')}
    122182        if TkVersion >= 8.5:
    123183            # Starting with tk 8.5 we have to set the new tabstyle option
     
    136196            # Command-W on editorwindows doesn't work without this.
    137197            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)
    138206        text.bind("<<cut>>", self.cut)
    139207        text.bind("<<copy>>", self.copy)
     
    154222        text.bind("<<replace>>", self.replace_event)
    155223        text.bind("<<goto-line>>", self.goto_line_event)
    156         text.bind("<3>", self.right_menu_event)
    157224        text.bind("<<smart-backspace>>",self.smart_backspace_event)
    158225        text.bind("<<newline-and-indent>>",self.newline_and_indent_event)
     
    189256            fontWeight='bold'
    190257        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'),
    192260                          fontWeight))
    193261        text_frame.pack(side=LEFT, fill=BOTH, expand=1)
     
    279347        self.showerror = tkMessageBox.showerror
    280348
     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
    281379    def _filename_to_unicode(self, filename):
    282380        """convert filename to unicode in order to display it in Tk"""
     
    300398
    301399    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
    306403        if self.text.index("iomark") and \
    307404           self.text.compare("iomark", "<=", "insert lineend") and \
    308405           self.text.compare("insert linestart", "<=", "iomark"):
     406            # In Shell on input line, go to just after prompt
    309407            insertpt = int(self.text.index("iomark").split(".")[1])
    310408        else:
     
    315413            else:
    316414                insertpt=len(line)
    317 
    318415        lineat = int(self.text.index("insert").split('.')[1])
    319 
    320416        if insertpt == lineat:
    321417            insertpt = 0
    322 
    323418        dest = "insert linestart+"+str(insertpt)+"c"
    324 
    325419        if (event.state&1) == 0:
    326             # shift not pressed
     420            # shift was not pressed
    327421            self.text.tag_remove("sel", "1.0", "end")
    328422        else:
    329423            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
    332430            first = self.text.index(dest)
    333             last = self.text.index("anchor")
    334 
     431            last = self.text.index("my_anchor")
    335432            if self.text.compare(first,">",last):
    336433                first,last = last,first
    337 
    338434            self.text.tag_remove("sel", "1.0", "end")
    339435            self.text.tag_add("sel", first, last)
    340 
    341436        self.text.mark_set("insert", dest)
    342437        self.text.see("insert")
     
    373468
    374469    if macosxSupport.runningAsOSXApp():
    375         del menu_specs[-3]
    376470        menu_specs[-2] = ("windows", "_Window")
    377471
     
    385479            mbar.add_cascade(label=label, menu=menu, underline=underline)
    386480
    387         if macosxSupport.runningAsOSXApp():
     481        if macosxSupport.isCarbonAquaTk(self.root):
    388482            # Insert the application menu
    389483            menudict['application'] = menu = Menu(mbar, name='apple')
     
    407501
    408502    def right_menu_event(self, event):
    409         self.text.tag_remove("sel", "1.0", "end")
    410503        self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
    411504        if not self.rmenu:
     
    416509        if iswin:
    417510            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
    418523        rmenu.tk_popup(event.x_root, event.y_root)
    419524        if iswin:
     
    421526
    422527    rmenu_specs = [
    423         # ("Label", "<<virtual-event>>"), ...
    424         ("Close", "<<close-window>>"), # Example
     528        # ("Label", "<<virtual-event>>", "statefuncname"), ...
     529        ("Close", "<<close-window>>", None), # Example
    425530    ]
    426531
    427532    def make_rmenu(self):
    428533        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()
    433542        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'
    434562
    435563    def about_dialog(self, event=None):
     
    440568
    441569    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)
    444575
    445576    def python_docs(self, event=None):
    446577        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)
    448583        else:
    449584            webbrowser.open(self.help_url)
     
    555690        try:
    556691            (f, file, (suffix, mode, type)) = _find_module(name)
    557         except (NameError, ImportError), msg:
     692        except (NameError, ImportError) as msg:
    558693            tkMessageBox.showerror("Import error", str(msg), parent=self.text)
    559694            return
     
    580715        head, tail = os.path.split(filename)
    581716        base, ext = os.path.splitext(tail)
    582         import ClassBrowser
     717        from idlelib import ClassBrowser
    583718        ClassBrowser.ClassBrowser(self.flist, base, [head])
    584719
    585720    def open_path_browser(self, event=None):
    586         import PathBrowser
     721        from idlelib import PathBrowser
    587722        PathBrowser.PathBrowser(self.flist)
    588723
     
    665800            fontWeight='bold'
    666801        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'),
    668804                fontWeight))
    669805
     
    698834        for menubarItem in self.menudict.keys():
    699835            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
    701841            for index in range(0, end):
    702842                if menu.type(index) == 'command':
     
    705845                        itemName = menu.entrycget(index, 'label')
    706846                        event = ''
    707                         if menuEventDict.has_key(menubarItem):
    708                             if menuEventDict[menubarItem].has_key(itemName):
     847                        if menubarItem in menuEventDict:
     848                            if itemName in menuEventDict[menubarItem]:
    709849                                event = menuEventDict[menubarItem][itemName]
    710850                        if event:
     
    740880        def display_extra_help(helpfile=helpfile):
    741881            if not helpfile.startswith(('www', 'http')):
    742                 url = os.path.normpath(helpfile)
     882                helpfile = os.path.normpath(helpfile)
    743883            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)
    745889            else:
    746890                webbrowser.open(helpfile)
     
    751895        rf_list = []
    752896        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:
    755898                rf_list = rf_list_file.readlines()
    756             finally:
    757                 rf_list_file.close()
    758899        if new_file:
    759900            new_file = os.path.abspath(new_file) + '\n'
     
    769910        ulchars = "1234567890ABCDEFGHIJK"
    770911        rf_list = rf_list[0:len(ulchars)]
    771         rf_file = open(self.recent_files_path, 'w')
    772912        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)
    776922        # for each edit window instance, construct the recent files menu
    777923        for instance in self.top.instance_dict.keys():
    778924            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 \n
     925            menu.delete(0, END)  # clear, and rebuild:
     926            for i, file_name in enumerate(rf_list):
     927                file_name = file_name.rstrip()  # zap \n
    782928                # make unicode string to display non-ASCII chars correctly
    783929                ufile_name = self._filename_to_unicode(file_name)
     
    11031249        want = ((have - 1) // self.indentwidth) * self.indentwidth
    11041250        # 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 = ''
    11061255        ncharsdeleted = 0
    11071256        while 1:
     
    11941343                for context in self.num_context_lines:
    11951344                    startat = max(lno - context, 1)
    1196                     startatindex = `startat` + ".0"
     1345                    startatindex = repr(startat) + ".0"
    11971346                    rawtext = text.get(startatindex, "insert")
    11981347                    y.set_str(rawtext)
     
    13131462        head, tail, chars, lines = self.get_region()
    13141463        tabwidth = self._asktabwidth()
     1464        if tabwidth is None: return
    13151465        for pos in range(len(lines)):
    13161466            line = lines[pos]
     
    13241474        head, tail, chars, lines = self.get_region()
    13251475        tabwidth = self._asktabwidth()
     1476        if tabwidth is None: return
    13261477        for pos in range(len(lines)):
    13271478            lines[pos] = lines[pos].expandtabs(tabwidth)
     
    14171568            initialvalue=self.indentwidth,
    14181569            minvalue=2,
    1419             maxvalue=16) or self.tabwidth
     1570            maxvalue=16)
    14201571
    14211572    # Guess indentwidth from text content.
     
    14991650            try:
    15001651                _tokenize.tokenize(self.readline, self.tokeneater)
    1501             except _tokenize.TokenError:
     1652            except (_tokenize.TokenError, SyntaxError):
    15021653                # since we cut off the tokenizer early, we can trigger
    15031654                # spurious errors
     
    15261677def get_accelerator(keydefs, eventname):
    15271678    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>>"}):
    15291685        return ""
    15301686    s = keylist[0]
Note: See TracChangeset for help on using the changeset viewer.