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.You are not allowed to attach a file to this page.