[Python-checkins] r65572 - in sandbox/trunk/ttk-gsoc/src/idlelib: EditorWindow.py OutputWindow.py PyShell.py editorpage.py

guilherme.polo python-checkins at python.org
Thu Aug 7 15:55:28 CEST 2008


Author: guilherme.polo
Date: Thu Aug  7 15:55:27 2008
New Revision: 65572

Log:
Added a new method in EditorWindow to remove tab controls from its window (the
code was in PyShell before this);

rmenu is controlled by EditorPage instance now;

ispythonsource coded moved from EditorWindow to EditorPage, but PyShell still
has its own ispythonsource due to not having a dedicated Page class for it;

When a new tab is created, it gets selected now;

Moved great part of OutputWindow's code to a new class named OutputPage living
in the editorpage module now;


Modified:
   sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py
   sandbox/trunk/ttk-gsoc/src/idlelib/OutputWindow.py
   sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py
   sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py

Modified: sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py	Thu Aug  7 15:55:27 2008
@@ -20,7 +20,7 @@
 
 TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
 if TTK:
-    from ttk import Scrollbar
+    from ttk import Style, Scrollbar
 
 # The default tab setting for a Text widget, in average-width characters.
 TK_TABWIDTH_DEFAULT = 8
@@ -30,11 +30,6 @@
     from UndoDelegator import UndoDelegator   # overridden by PyShell
 
     help_url = None
-    rmenu = None
-    rmenu_specs = [
-        # ("Label", "<<virtual-event>>"), ...
-        ("Close", "<<close-window>>"), # Example
-    ]
     menu_specs = [
         ("file", "_File"),
         ("edit", "_Edit"),
@@ -49,7 +44,8 @@
         del menu_specs[-3]
         menu_specs[-2] = ("windows", "_Window")
 
-    def __init__(self, flist=None, filename=None, key=None, root=None):
+    def __init__(self, flist=None, filename=None, key=None, root=None,
+       start_page=EditorPage):
         if EditorWindow.help_url is None:
             dochome =  os.path.join(sys.prefix, 'Doc', 'index.html')
             if sys.platform.count('linux'):
@@ -114,7 +110,7 @@
         self.text_notebook = TabbedPageSet(self.top)
         self.text_notebook.pack(fill=BOTH, expand=True)
         self.text_notebook.bind('<<NotebookTabChanged>>', self._update_controls)
-        self.new_tab(filename=filename, load_ext=False)
+        self.new_tab(filename=filename, load_ext=False, ptype=start_page)
         self.text = self.current_page.text # XXX
         self.top.focused_widget = self.text
         self.top.bind('<<tab-closed>>', self._post_tab_close)
@@ -165,7 +161,11 @@
         # Making the initial values larger slows things down more often.
         self.num_context_lines = 50, 500, 5000000
 
-        self.set_indentation_params(self.ispythonsource(filename))
+        if hasattr(self, 'ispythonsource'): # PyShell
+            self.set_indentation_params(self.ispythonsource(filename))
+        else:
+            self.set_indentation_params(
+                self.current_page.ispythonsource(filename))
 
         self.extensions = {}
         self._load_extensions()
@@ -200,9 +200,37 @@
             page = self.text_notebook.pages[curr_tab].editpage
         return page
 
+    def remove_tab_controls(self):
+        """Remove tab area and most tab bindings from this window."""
+        if TTK:
+            self.text_notebook['style'] = 'PyShell.TNotebook'
+            style = Style(self.top)
+            style.layout('PyShell.TNotebook.Tab', [('null', '')])
+        else:
+            self.text_notebook._tab_set.grid_forget()
+
+        # remove commands related to tab
+        if 'file' in self.menudict:
+            menu = self.menudict['file']
+            curr_entry = None
+            i = 0
+            while True:
+                last_entry, curr_entry = curr_entry, menu.entryconfigure(i)
+                if last_entry == curr_entry:
+                    # no more menu entries
+                    break
+
+                if 'label' in curr_entry and 'Tab' in curr_entry['label'][-1]:
+                    if 'Close' not in ' '.join(curr_entry['label'][-1]):
+                        menu.delete(i)
+                i += 1
+
+        self.current_page.text.unbind('<<new-tab>>')
+        # close-tab is still available!
+
     def short_title(self):
         # overriden by PyShell
-        self.current_page.short_title()
+        return self.current_page.short_title()
 
     def next_tab(self, event):
         """Show next tab if not in the last tab already."""
@@ -218,13 +246,14 @@
             return
         self.text_notebook.select(index - 1)
 
-    def new_tab(self, event=None, filename=None, load_ext=True):
+    def new_tab(self, event=None, filename=None, load_ext=True, ptype=None):
         """Create a new EditorPage and insert it into the notebook."""
         page_title = "#%d" % (len(self.text_notebook.pages) + 1)
         page = self.text_notebook.add_page(page_title)
 
         vbar = Scrollbar(page.frame, name='vbar')
-        page.editpage = EditorPage(page.frame, self, title=page_title,
+        ptype = ptype or EditorPage
+        page.editpage = ptype(page.frame, self, title=page_title,
             name='text', padx=5, wrap='none')
 
         firstpage = False # don't update window's title
@@ -240,8 +269,7 @@
                 underline=0, menu=self.recent_files_menu)
             self.update_recent_files_list()
 
-        page.editpage.post_init(filename=filename, update_window_title=firstpage)
-
+        # pack widgets
         text = page.editpage.text
         vbar['command'] = text.yview
         vbar.pack(side=RIGHT, fill=Y)
@@ -258,6 +286,13 @@
         self.apply_bindings(tab=page)
         if load_ext:
             self._load_extensions()
+
+        # select the just created page
+        self.text_notebook.select(len(self.text_notebook.pages) - 1)
+
+        page.editpage.post_init(filename=filename,
+            update_window_title=firstpage)
+
         self.top.event_generate('<<tab-created>>')
         return "break"
 
@@ -308,20 +343,6 @@
             text.tag_add("sel", "insert", "insert +1l")
             page.center()
 
-    def ispythonsource(self, filename):
-        if not filename or os.path.isdir(filename):
-            return True
-        base, ext = os.path.splitext(os.path.basename(filename))
-        if os.path.normcase(ext) in (".py", ".pyw"):
-            return True
-        try:
-            f = open(filename)
-            line = f.readline()
-            f.close()
-        except IOError:
-            return False
-        return line.startswith('#!') and line.find('python') >= 0
-
     def close_hook(self):
         if self.flist:
             self.flist.unregister_maybe_terminate(self)
@@ -605,7 +626,7 @@
         self.extensions = {}
 
     def _load_extension(self, name, tab):
-        ext_loaded = self.extensions.get(name, None)
+        ext_loaded = self.extensions.get(name)
 
         try:
             mod = __import__(name, globals(), locals(), [])

Modified: sandbox/trunk/ttk-gsoc/src/idlelib/OutputWindow.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/OutputWindow.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/OutputWindow.py	Thu Aug  7 15:55:27 2008
@@ -3,10 +3,10 @@
 
 import utils
 import IOBinding
+from editorpage import OutputPage
 from EditorWindow import EditorWindow
 
 class OutputWindow(EditorWindow):
-
     """An editor window that can serve as an output file.
 
     Also the future base class for the Python shell window.
@@ -14,36 +14,14 @@
     """
 
     def __init__(self, *args):
-        EditorWindow.__init__(self, *args)
-        self.top.bind("<<tab-created>>", self.__configure_new_tab)
-        # configure the tab created in EditorWindow.__init__
-        self.__configure_new_tab() 
-
-    def __configure_new_tab(self, event=None):
-        page = self.text_notebook.last_page().editpage
-        page.text.bind("<<goto-file-line>>", utils.callback(self.goto_file_line,
-            page.text))
-
-    # Customize EditorWindow
-
-    def ispythonsource(self, filename):
-        # No colorization needed
-        return 0
-
-    def short_title(self):
-        return "Output"
-
-    def maybesave(self):
-        # Override base class method -- don't ask any questions
-        if self.get_saved():
-            return "yes"
-        else:
-            return "no"
+        EditorWindow.__init__(self, start_page=OutputPage, *args)
+        self.remove_tab_controls()
 
     # Act as output file
 
     def write(self, s, tags=(), mark="insert", text=None):
-        assert text is not None
+        if text is None:
+            text = self.current_page.text
         # Tk assumes that byte strings are Latin-1;
         # we assume that they are in the locale's encoding
         if isinstance(s, str):
@@ -61,60 +39,3 @@
 
     def flush(self):
         pass
-
-    # Our own right-button menu
-
-    rmenu_specs = [
-        ("Go to file/line", "<<goto-file-line>>"),
-    ]
-
-    file_line_pats = [
-        r'file "([^"]*)", line (\d+)',
-        r'([^\s]+)\((\d+)\)',
-        r'([^\s]+):\s*(\d+):',
-    ]
-
-    file_line_progs = None
-
-    def goto_file_line(self, event, text):
-        if self.file_line_progs is None:
-            l = []
-            for pat in self.file_line_pats:
-                l.append(re.compile(pat, re.IGNORECASE))
-            self.file_line_progs = l
-        
-        line = text.get("insert linestart", "insert lineend")
-        result = self._file_line_helper(line)
-        if not result:
-            # Try the previous line.  This is handy e.g. in tracebacks,
-            # where you tend to right-click on the displayed source line
-            line = text.get("insert -1line linestart", "insert -1line ineend")
-            result = self._file_line_helper(line)
-            if not result:
-                tkMessageBox.showerror(
-                    "No special line",
-                    "The line you point at doesn't look like "
-                    "a valid file name followed by a line number.",
-                    master=text)
-                return
-        filename, lineno = result
-        edit = self.flist.open(filename)
-        edit.gotoline(lineno)
-
-    def _file_line_helper(self, line):
-        for prog in self.file_line_progs:
-            m = prog.search(line)
-            if m:
-                break
-        else:
-            return None
-        filename, lineno = m.group(1, 2)
-        try:
-            f = open(filename, "r")
-            f.close()
-        except IOError:
-            return None
-        try:
-            return filename, int(lineno)
-        except TypeError:
-            return None

Modified: sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py	Thu Aug  7 15:55:27 2008
@@ -112,9 +112,6 @@
 class PyShellEditorWindow(EditorWindow):
     "Regular text edit window in IDLE, supports breakpoints"
 
-    rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
-                   ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
-
     def __init__(self, *args):
         EditorWindow.__init__(self, *args)
 
@@ -833,31 +830,7 @@
         OutputWindow.__init__(self, flist, None, None)
         # remove things related to tabs. The window running the shell is
         # considered special enough to have a single window for it.
-
-        # remove tabs area
-        if TTK:
-            self.text_notebook['style'] = 'PyShell.TNotebook'
-            style = Style(self.top)
-            style.layout('PyShell.TNotebook.Tab', [('null', '')])
-        else:
-            self.text_notebook._tab_set.grid_forget()
-
-        # remove commands related to tab
-        if 'file' in self.menudict:
-            menu = self.menudict['file']
-            curr_entry = None
-            i = 0
-            while True:
-                last_entry, curr_entry = curr_entry, menu.entryconfigure(i)
-                if last_entry == curr_entry:
-                    break
-
-                if 'label' in curr_entry and 'Tab' in curr_entry['label'][-1]:
-                    if 'New' in ' '.join(curr_entry['label'][-1]):
-                        menu.delete(i)
-                i += 1
-        self.text.unbind('<<new-tab>>')
-        #self.text.unbind('<<close-tab>>')
+        self.remove_tab_controls()
 
         #
         self.usetabs = True

Modified: sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py	Thu Aug  7 15:55:27 2008
@@ -73,6 +73,12 @@
     return file, filename, descr
 
 class EditorPage(object):
+    rmenu = None
+    rmenu_specs = [
+        ("Set Breakpoint", "<<set-breakpoint-here>>"),
+        ("Clear Breakpoint", "<<clear-breakpoint-here>>")
+    ]
+
     def __init__(self, parent_frame, editwin, title=None, **kwargs):
         self.editwin = editwin
         self.title = title
@@ -228,6 +234,20 @@
         newtop = max(1, lineno - height//2)
         text.yview(float(newtop))
 
+    def ispythonsource(self, filename):
+        if not filename or os.path.isdir(filename):
+            return True
+        base, ext = os.path.splitext(os.path.basename(filename))
+        if os.path.normcase(ext) in (".py", ".pyw"):
+            return True
+        try:
+            f = open(filename)
+            line = f.readline()
+            f.close()
+        except IOError:
+            return False
+        return line.startswith('#!') and line.find('python') >= 0
+
     def newline_and_indent_event(self, event):
         # Used by EditorWindow.newline_and_indent_event which is used by PyShell
         text = self.text
@@ -474,15 +494,8 @@
             f.close()
         if self.editwin.flist:
             if idleConf.GetOption('main', 'EditorWindow', 'file-in-tab',
-                default=1, type='bool'):
-                if hasattr(self.editwin, 'interp'):
-                    # PyShell window must open a module in a new window
-                    action = None
-                else:
-                    action = self.editwin.new_tab
-            else:
-                action = None
-            self.editwin.flist.open(file, action)
+               default=1, type='bool'):
+                self.editwin.flist.open(file)
         else:
             self.io.loadfile(file)
 
@@ -499,8 +512,7 @@
         return "break"
 
     def _find_in_files_event(self, event):
-        # XXX not expected to work correctly for now
-        GrepDialog.grep(self.text, self.editwin.io, self.editwin.flist)
+        GrepDialog.grep(self.text, self.io, self.editwin.flist)
         return "break"
 
     def _replace_event(self, event):
@@ -810,10 +822,10 @@
         self.text.tag_remove("sel", "1.0", "end")
         self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
 
-        if not self.editwin.rmenu:
+        if not self.rmenu:
             self.__make_rmenu()
 
-        rmenu = self.editwin.rmenu
+        rmenu = self.rmenu
         self.event = event
         iswin = sys.platform[:3] == 'win'
         if iswin:
@@ -825,12 +837,12 @@
     def __make_rmenu(self):
         rmenu = Menu(self.text, tearoff=False)
 
-        for label, eventname in self.editwin.rmenu_specs:
+        for label, eventname in self.rmenu_specs:
             def command(text=self.text, eventname=eventname):
                 text.event_generate(eventname)
             rmenu.add_command(label=label, command=command)
 
-        self.editwin.rmenu = rmenu
+        self.rmenu = rmenu
 
     def __rmcolorizer(self):
         if not self.color:
@@ -842,7 +854,12 @@
     def __addcolorizer(self):
         if self.color:
             return
-        if self.editwin.ispythonsource(self.io.filename):
+
+        if hasattr(self.editwin, 'ispythonsource'): # PyShell window
+            pychecker = self.editwin.ispythonsource
+        else:
+            pychecker = self.ispythonsource
+        if pychecker(self.io.filename):
             self.color = self.editwin.ColorDelegator()
 
         # can add more colorizers here...
@@ -923,3 +940,84 @@
         else:
             # The colorizer is missing: assume the worst
             return 1
+
+
+import re
+
+class OutputPage(EditorPage):
+    rmenu_specs = [
+        ("Go to file/line", "<<goto-file-line>>"),
+    ]
+
+    file_line_pats = [
+        r'file "([^"]*)", line (\d+)',
+        r'([^\s]+)\((\d+)\)',
+        r'([^\s]+):\s*(\d+):',
+    ]
+
+    file_line_progs = None
+
+    def __init__(self, parent_frame, editwin, title=None, **kwargs):
+        EditorPage.__init__(self, parent_frame, editwin, title, **kwargs)
+        self.text.bind("<<goto-file-line>>", self.goto_file_line)
+
+    def ispythonsource(self, filename):
+        # No colorization needed
+        return 0
+
+    def short_title(self):
+        return "Output"
+
+    def maybesave(self):
+        # Override base class method -- don't ask any questions
+        if self.get_saved():
+            return "yes"
+        else:
+            return "no"
+
+    def goto_file_line(self, event):
+        text = self.text
+        if self.file_line_progs is None:
+            l = []
+            for pat in self.file_line_pats:
+                l.append(re.compile(pat, re.IGNORECASE))
+            self.file_line_progs = l
+
+        line = text.get("insert linestart", "insert lineend")
+        result = self._file_line_helper(line)
+        if not result:
+            # Try the previous line.  This is handy e.g. in tracebacks,
+            # where you tend to right-click on the displayed source line
+            line = text.get("insert -1line linestart", "insert -1line ineend")
+            result = self._file_line_helper(line)
+            if not result:
+                tkMessageBox.showerror("No special line",
+                    "The line you point at doesn't look like "
+                    "a valid file name followed by a line number.",
+                    master=text)
+                return
+        filename, lineno = result
+        self._open_file_at_line(filename, lineno)
+
+    def _file_line_helper(self, line):
+        for prog in self.file_line_progs:
+            m = prog.search(line)
+            if m:
+                break
+        else:
+            return None
+
+        filename, lineno = m.group(1, 2)
+        try:
+            f = open(filename, "r")
+            f.close()
+        except IOError:
+            return None
+        try:
+            return filename, int(lineno)
+        except TypeError:
+            return None
+
+    def _open_file_at_line(self, filename, lineno):
+        edit = self.editwin.flist.open(filename)
+        edit.gotoline(lineno)


More information about the Python-checkins mailing list