Attachment 'pythonoutline.py'

Download

   1 #!/usr/bin/env python
   2 # -*- coding: utf-8 -*-
   3 #
   4 # This file is part of the Python Outline Plugin for Gedit
   5 # Copyright (C) 2007 Dieter Verfaillie <dieterv@optionexplicit.be>
   6 #
   7 # This program is free software; you can redistribute it and/or modify
   8 # it under the terms of the GNU General Public License as published by
   9 # the Free Software Foundation; either version 2 of the License, or
  10 # (at your option) any later version.
  11 #
  12 # This program is distributed in the hope that it will be useful,
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 # GNU General Public License for more details.
  16 #
  17 # You should have received a copy of the GNU General Public License
  18 # along with this program; if not, write to the Free Software
  19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20 
  21 
  22 import os
  23 
  24 import gtk
  25 import gedit
  26 
  27 import compiler
  28 import gc
  29 import glob
  30 import time
  31 
  32 
  33 class TreeModelASTVisitor(compiler.visitor.ASTVisitor):
  34     defaulticon = None
  35 
  36     moduleicon = gtk.Window().render_icon(gtk.STOCK_COPY, gtk.ICON_SIZE_MENU)
  37     importicon = gtk.Window().render_icon(gtk.STOCK_JUMP_TO, gtk.ICON_SIZE_MENU)
  38     classicon = gtk.Window().render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_MENU)
  39     functionicon = gtk.Window().render_icon(gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
  40 
  41     def __init__(self, treemodel):
  42         compiler.visitor.ASTVisitor.__init__(self)
  43 
  44         self.treemodel = treemodel
  45 
  46     def walkChildren(self, node, parent=None):
  47         for child in node.getChildNodes():
  48             child.parent = node
  49             self.dispatch(child, parent)
  50 
  51     def default(self, node, parent=None):
  52         self.walkChildren(node, parent)
  53 
  54 
  55 class OutlineTreeModelASTVisitor(TreeModelASTVisitor):
  56     def __init__(self, treemodel):
  57         TreeModelASTVisitor.__init__(self, treemodel)
  58 
  59     def visitAssAttr(self, node, parent=None):
  60         if hasattr(node.expr, 'name'):
  61             if node.expr.name == 'self':
  62                 iter = self.treemodel.append(parent, (self.defaulticon, 'self.' + node.attrname, node.__class__.__name__, node.lineno, None))
  63 
  64     def visitAssName(self, node, parent=None):
  65         if hasattr(node.parent, 'parent'):
  66             if not hasattr(node.parent.parent, 'parent'):
  67                 iter = self.treemodel.append(parent, (self.defaulticon, node.name, node.__class__.__name__, node.lineno, None))
  68 
  69     def visitClass(self, node, parent=None):
  70         iter = self.treemodel.append(parent, (self.classicon, node.name, node.__class__.__name__, node.lineno, node.doc))
  71         self.walkChildren(node.code, iter)
  72 
  73     def visitDecorators(self, node, parent=None):
  74         iter = self.treemodel.append(parent, (self.defaulticon, None, node.__class__.__name__, node.lineno, None))
  75         self.walkChildren(node, iter)
  76 
  77     def visitFrom(self, node, parent=None):
  78         for name in node.names:
  79             if name[1] is None:
  80                 self.treemodel.append(parent, (self.importicon, name[0] + ' (' + node.modname + ')', node.__class__.__name__, node.lineno, None))
  81             else:
  82                 self.treemodel.append(parent, (self.importicon, name[1] + ' = ' + name[0] + ' (' + node.modname + ')', node.__class__.__name__, node.lineno, None))
  83 
  84     def visitFunction(self, node, parent=None):
  85         iter = self.treemodel.append(parent, (self.functionicon, node.name, node.__class__.__name__, node.lineno, node.doc))
  86         self.walkChildren(node, iter)
  87 
  88     def visitImport(self, node, parent=None):
  89         for name in node.names:
  90             if name[1] is None:
  91                 self.treemodel.append(parent, (self.importicon, name[0], node.__class__.__name__, node.lineno, None))
  92             else:
  93                 self.treemodel.append(parent, (self.importicon, name[1] + ' = ' + name[0], node.__class__.__name__, node.lineno, None))
  94 
  95     def visitName(self, node, parent=None):
  96         if node.parent.__class__.__name__ in ['Class', 'Function']:
  97             self.treemodel.append(parent, (self.defaulticon, node.name, node.__class__.__name__, node.lineno, None))
  98 
  99 
 100 class OutlineBox(gtk.VBox):
 101     def __init__(self):
 102         gtk.VBox.__init__(self)
 103 
 104         scrolledwindow = gtk.ScrolledWindow()
 105         scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 106         scrolledwindow.show()
 107         self.pack_start(scrolledwindow, True, True, 0)
 108 
 109         self.treeview = gtk.TreeView()
 110         self.treeview.set_rules_hint(True)
 111         self.treeview.set_headers_visible(False)
 112         self.treeview.set_enable_search(True)
 113         self.treeview.set_reorderable(False)
 114         self.treeselection = self.treeview.get_selection()
 115         self.treeselection.connect('changed', self.on_selection_changed)
 116         scrolledwindow.add(self.treeview)
 117 
 118         col = gtk.TreeViewColumn()
 119         col.set_title('name')
 120         col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
 121         col.set_expand(True)
 122         render_pixbuf = gtk.CellRendererPixbuf()
 123         render_pixbuf.set_property('xalign', 0.5)
 124         render_pixbuf.set_property('yalign', 0.5)
 125         render_pixbuf.set_property('xpad', 2)
 126         render_pixbuf.set_property('ypad', 2)
 127         col.pack_start(render_pixbuf, expand=False)
 128         col.add_attribute(render_pixbuf, 'pixbuf', 0)
 129         render_text = gtk.CellRendererText()
 130         render_text.set_property('xalign', 0)
 131         render_text.set_property('yalign', 0.5)
 132         col.pack_start(render_text, expand=True)
 133         col.add_attribute(render_text, 'text', 1)
 134         self.treeview.append_column(col)
 135         self.treeview.set_search_column(1)
 136 
 137         self.label = gtk.Label()
 138         self.pack_end(self.label, False)
 139 
 140         self.expand_classes = False
 141         self.expand_functions = False
 142 
 143         self.show_all()
 144 
 145     def on_toggle_expand_classes(self, action):
 146         self.expand_classes = action.get_active()
 147 
 148     def on_toggle_expand_functions(self, action):
 149         self.expand_functions = action.get_active()
 150 
 151     def on_row_has_child_toggled(self, treemodel, path, iter):
 152         if self.expand_classes and treemodel.get_value(iter, 2) == 'Class':
 153             self.treeview.expand_row(path, False)
 154         elif self.expand_functions and treemodel.get_value(iter, 2) == 'Function':
 155             self.treeview.expand_row(path, False)
 156 
 157     def on_selection_changed(self, selection):
 158         model, iter = selection.get_selected()
 159         if iter:
 160             lineno = model.get_value(iter, 3)
 161             if lineno:
 162                 lineno = int(lineno) -1
 163                 linestartiter = self.buffer.get_iter_at_line(lineno)
 164                 lineenditer = self.buffer.get_iter_at_line(lineno)
 165                 lineenditer.forward_line()
 166                 line = self.buffer.get_text(linestartiter, lineenditer)
 167                 name = model.get_value(iter, 1)
 168                 start = line.find(name)
 169                 if start > -1:
 170                     end = start + len(name)
 171                     self.buffer.select_range(
 172                         self.buffer.get_iter_at_line_offset(lineno, start),
 173                         self.buffer.get_iter_at_line_offset(lineno, end))
 174                     self.view.scroll_to_cursor()
 175                 else:
 176                     #Todo: scroll view to lineno
 177                     pass
 178 
 179     def create_treemodel(self):
 180         treemodel = gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, str)
 181         handler = treemodel.connect('row-has-child-toggled', self.on_row_has_child_toggled)
 182         return treemodel, handler
 183 
 184     def parse(self, view, buffer):
 185         self.view = view
 186         self.buffer = buffer
 187 
 188         startTime = time.time()
 189 
 190         treemodel, handler = self.create_treemodel()
 191         self.treeview.set_model(treemodel)
 192         self.treeview.freeze_child_notify()
 193 
 194         visitor = OutlineTreeModelASTVisitor(treemodel)
 195  
 196         try:
 197             bounds = self.buffer.get_bounds()
 198             mod = compiler.parse(self.buffer.get_text(bounds[0], bounds[1]).replace('\r', '\n') + '\n')
 199             visitor.preorder(mod, visitor, None)
 200             del bounds, mod, visitor
 201         except SyntaxError:
 202             pass
 203         finally:
 204             gc.collect()
 205 
 206         treemodel.disconnect(handler)
 207         self.treeview.thaw_child_notify()
 208 
 209         stopTime = time.time()
 210         self.label.set_text('Outline created in ' + str(float(stopTime - startTime)) + ' s')
 211 
 212 
 213 class PythonOutlinePluginInstance(object):
 214     def __init__(self, plugin, window):
 215         self._window = window
 216         self._plugin = plugin
 217 
 218         self._insert_panel()
 219 
 220     def deactivate(self):
 221         self._remove_panel
 222 
 223         self._window = None
 224         self._plugin = None
 225 
 226     def update_ui(self):
 227         document = self._window.get_active_document()
 228         if document:
 229             uri = str(document.get_uri())
 230             if document.get_mime_type() == 'text/x-python' or uri.endswith('.py') or uri.endswith('.pyw'):
 231                 self.outlinebox.parse(self._window.get_active_view(), document)
 232             else:
 233                 treemodel, handler = self.outlinebox.create_treemodel()
 234                 self.outlinebox.treeview.set_model(treemodel)
 235 
 236     def _insert_panel(self):
 237         self.panel = self._window.get_side_panel()
 238         self.outlinebox = OutlineBox()
 239         self.panel.add_item(self.outlinebox, "Python Outline", gtk.STOCK_REFRESH)
 240 
 241     def _remove_panel(self):
 242         self.panel.destroy()
 243 
 244 
 245 class PythonOutlinePlugin(gedit.Plugin):
 246     def __init__(self):
 247         gedit.Plugin.__init__(self)
 248         self._instances = {}
 249 
 250     def activate(self, window):
 251         self._instances[window] = PythonOutlinePluginInstance(self, window)
 252 
 253     def deactivate(self, window):
 254         self._instances[window].deactivate()
 255         del self._instances[window]
 256 
 257     def update_ui(self, window):
 258         self._instances[window].update_ui()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2021-02-25 09:43:45, 0.2 KB) [[attachment:pythonoutline.gedit-plugin]]
  • [get | view] (2021-02-25 09:43:45, 80.1 KB) [[attachment:pythonoutline.png]]
  • [get | view] (2021-02-25 09:43:45, 9.6 KB) [[attachment:pythonoutline.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.