Attachment 'rstoutline.py'

Download

   1 #!/usr/bin/env python
   2 # -*- coding: utf-8 -*-
   3 #
   4 # This file is part of the ReST Outline Plugin for Gedit
   5 # based upon Python Outline Plugin for Gedit
   6 # Copyright (C) 2007 Dieter Verfaillie <dieterv@optionexplicit.be>
   7 # Copyright (C) 2011 Pablo Angulo <pangard@cancamusa.net>
   8 #
   9 # This program is free software; you can redistribute it and/or modify
  10 # it under the terms of the GNU General Public License as published by
  11 # the Free Software Foundation; either version 2 of the License, or
  12 # (at your option) any later version.
  13 #
  14 # This program is distributed in the hope that it will be useful,
  15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 # GNU General Public License for more details.
  18 #
  19 # You should have received a copy of the GNU General Public License
  20 # along with this program; if not, write to the Free Software
  21 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  22 
  23 import gtk
  24 import gedit
  25 
  26 import gc
  27 import time
  28 
  29 class ReSTParser (object):
  30     '''Updates a treemodel, adding entries for each header section
  31     '''
  32     header_chars = ['=', '-', '`', ':', "'", '"', '~', '^', '_', '*', '+', '#', '<', '>']
  33 
  34     def __init__(self, treemodel):
  35         self.treemodel = treemodel
  36         
  37     def parse(self, text):
  38         last = None
  39         parents = []
  40         levels  = []
  41         for j,line in enumerate(text.splitlines()):
  42             first = line[0] if line else ''
  43             line = line.strip()
  44             if (last and 
  45                 first in self.header_chars and 
  46                 len(line) > 1 and
  47                 all(c==first for c in line)):
  48                 if first not in levels:
  49                     levels.append(first)
  50                 i = levels.index(first)                
  51                 while i>len(parents):
  52                     parents.append(self.treemodel.append(parents[-1] if parents else None, 
  53                                          ('?', 'empty node', str(j-1)) ))
  54                 if i<len(parents):
  55                     parents = parents[:i]
  56                 parents.append(self.treemodel.append(parents[-1] if parents else None, 
  57                                   (first, last, str(j-1)) ))
  58             last = line
  59 
  60 
  61 class OutlineBox(gtk.VBox):
  62     def __init__(self):
  63         gtk.VBox.__init__(self)
  64 
  65         scrolledwindow = gtk.ScrolledWindow()
  66         scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  67         scrolledwindow.show()
  68         self.pack_start(scrolledwindow, True, True, 0)
  69 
  70         self.treeview = gtk.TreeView()
  71         self.treeview.set_rules_hint(True)
  72         self.treeview.set_headers_visible(False)
  73         self.treeview.set_enable_search(True)
  74         self.treeview.set_reorderable(False)
  75         self.treeselection = self.treeview.get_selection()
  76         self.treeselection.connect('changed', self.on_selection_changed)
  77         scrolledwindow.add(self.treeview)
  78 
  79         col = gtk.TreeViewColumn()
  80         col.set_title('name')
  81         col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
  82         col.set_expand(True)
  83         render_text = gtk.CellRendererText()
  84 #        render_text.set_property('cell-background', '#CCCCCC')
  85         render_text.set_property('xpad', 5)
  86         render_text.set_property('xalign', 0)
  87         render_text.set_property('yalign', 0.5)
  88         col.pack_start(render_text, expand=False)
  89         col.add_attribute(render_text, 'text', 0)
  90         render_text = gtk.CellRendererText()
  91         render_text.set_property('xalign', 0)
  92         render_text.set_property('yalign', 0.5)
  93         col.pack_start(render_text, expand=True)
  94         col.add_attribute(render_text, 'text', 1)
  95         self.treeview.append_column(col)
  96         self.treeview.set_search_column(1)
  97 
  98         self.label = gtk.Label()
  99         self.pack_end(self.label, False)
 100 
 101         self.expand_classes = False
 102         self.expand_functions = False
 103 
 104         self.show_all()
 105 
 106     def on_row_has_child_toggled(self, treemodel, path, iter):
 107         self.treeview.expand_row(path, False)
 108 
 109     def on_selection_changed(self, selection):
 110         model, iter = selection.get_selected()
 111         if iter:
 112             lineno = model.get_value(iter, 2)
 113             if not lineno: return
 114             lineno = int(lineno)
 115             name = model.get_value(iter, 1)
 116             linestartiter = self.buffer.get_iter_at_line(lineno)
 117             lineenditer = self.buffer.get_iter_at_line(lineno)
 118             lineenditer.forward_line()
 119             lineenditer.backward_char()
 120             line = self.buffer.get_text(linestartiter, lineenditer)
 121             self.buffer.select_range(linestartiter, lineenditer)
 122             self.view.scroll_to_cursor()
 123 
 124     def create_treemodel(self):
 125         #Header char, header, lineno
 126         treemodel = gtk.TreeStore(str, str, str)
 127         handler = treemodel.connect('row-has-child-toggled', self.on_row_has_child_toggled)
 128         return treemodel, handler
 129 
 130     def parse(self, view, buffer):
 131         self.view = view
 132         self.buffer = buffer
 133 
 134         startTime = time.time()
 135 
 136         treemodel, handler = self.create_treemodel()
 137         self.treeview.set_model(treemodel)
 138         self.treeview.freeze_child_notify()
 139 
 140         bounds = self.buffer.get_bounds()
 141         text   = self.buffer.get_text(bounds[0], bounds[1]).replace('\r', '\n') + '\n'
 142         rstparser = ReSTParser(treemodel)
 143         rstparser.parse(text)
 144         gc.collect()
 145 
 146         treemodel.disconnect(handler)
 147         self.treeview.thaw_child_notify()
 148 
 149         stopTime = time.time()
 150         self.label.set_text('Outline created in ' + str(float(stopTime - startTime)) + ' s')
 151 
 152         return treemodel
 153 
 154 class ReSTOutlinePluginInstance(object):
 155     def __init__(self, plugin, window):
 156         self._window = window
 157         self._plugin = plugin
 158 
 159         self._insert_panel()
 160         self._models = {}
 161 
 162     def deactivate(self):
 163         self._remove_panel
 164 
 165         self._window = None
 166         self._plugin = None
 167 
 168     def update_ui(self):
 169         document = self._window.get_active_document()
 170         if document:
 171             uri = str(document.get_uri())
 172             if document.get_mime_type() == 'text/restructured' or uri.endswith('.rst'):
 173                 self.outlinebox.parse(self._window.get_active_view(), document)
 174             else:
 175                 treemodel, handler = self.outlinebox.create_treemodel()
 176                 self.outlinebox.treeview.set_model(treemodel)
 177 
 178     def _insert_panel(self):
 179         self.panel = self._window.get_side_panel()
 180         self.outlinebox = OutlineBox()
 181         self.panel.add_item(self.outlinebox, "ReST Outline", gtk.STOCK_INDEX)
 182 
 183     def _remove_panel(self):
 184         self.panel.destroy()
 185 
 186 
 187 class ReSTOutlinePlugin(gedit.Plugin):
 188     def __init__(self):
 189         gedit.Plugin.__init__(self)
 190         self._instances = {}
 191 
 192     def activate(self, window):
 193         self._instances[window] = ReSTOutlinePluginInstance(self, window)
 194 
 195     def deactivate(self, window):
 196         self._instances[window].deactivate()
 197         del self._instances[window]
 198 
 199     def update_ui(self, window):
 200         self._instances[window].update_ui()
 201         
 202         

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:46, 0.3 KB) [[attachment:rstoutline.gedit-plugin]]
  • [get | view] (2021-02-25 09:43:46, 108.0 KB) [[attachment:rstoutline.png]]
  • [get | view] (2021-02-25 09:43:46, 7.0 KB) [[attachment:rstoutline.py]]
 All files | Selected Files: delete move to page copy to page

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