public
Description: My Gedit plugins ;)
Homepage:
Clone URL: git://github.com/caironoleto/my-gedit-plugins.git
my-gedit-plugins / FindInFiles.py
100644 285 lines (221 sloc) 11.967 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
import gedit
import gtk
import os
import gconf
 
class ResultsView(gtk.VBox):
    def __init__(self, geditwindow):
        gtk.VBox.__init__(self)
        
        # We have to use .geditwindow specifically here (self.window won't work)
        self.geditwindow = geditwindow
        
        # Save the document's encoding in a variable for later use (when opening new tabs)
        try: self.encoding = gedit.encoding_get_current()
        except: self.encoding = gedit.gedit_encoding_get_current()
        
        # Preferences (we'll control them with toggled checkboxes)
        self.ignore_comments = False
        self.case_sensitive = False
        
        # We save the grep search result data in a ListStore
        # Format: ID (COUNT) | FILE (without path) | LINE | FILE (with path)
        # Note: We use the full-path version when opening new tabs (when necessary)
        self.search_data = gtk.ListStore(str, str, str, str)
 
        # Create a list (a "tree view" without children) to display the results
        self.results_list = gtk.TreeView(self.search_data)
 
        # Get the selection attribute of the results_list and assign a couple of properties
        tree_selection = self.results_list.get_selection()
        
        # Properties...
        tree_selection.set_mode(gtk.SELECTION_SINGLE)
        tree_selection.connect("changed", self.view_result)
        
        # Create the cells for our results list treeview
        # Note: We don't need to create a cell or text renderer
        # for the full-path filename variable because we
        # won't actually be displaying that information.
        cell_id = gtk.TreeViewColumn("#")
        cell_line_number = gtk.TreeViewColumn("Line")
        cell_filename = gtk.TreeViewColumn("File")
        
        # Now add the cell objects to the results_list treeview object
        self.results_list.append_column(cell_id)
        self.results_list.append_column(cell_line_number)
        self.results_list.append_column(cell_filename)
        
        # Create text-rendering objects so that we can actually
        # see the data that we'll put into the objects
        text_renderer_id = gtk.CellRendererText()
        text_renderer_filename = gtk.CellRendererText()
        text_renderer_line_number = gtk.CellRendererText()
        
        # Pack the text renderer objects into the cell objects we created
        cell_id.pack_start(text_renderer_id, True)
        cell_filename.pack_start(text_renderer_filename, True)
        cell_line_number.pack_start(text_renderer_line_number, True)
        
        # Now set the IDs to each of the text renderer objects and set them to "text" mode
        cell_id.add_attribute(text_renderer_id, "text", 0)
        cell_filename.add_attribute(text_renderer_filename, "text", 1)
        cell_line_number.add_attribute(text_renderer_line_number, "text", 2)
 
        # Create a scrolling window object and add our results_list treeview object to it
        scrolled_window = gtk.ScrolledWindow()
        scrolled_window.add(self.results_list)
        
        # Pack in the scrolled window object
        self.pack_start(scrolled_window)
        
        # Create a "Find" button; we'll pack it into an HBox in a moment...
        button_find = gtk.Button("Find")
        button_find.connect("clicked", self.button_press)
        # Create a "search bar" to type the search string into; we'll pack it
        # into the HBox as well...
        self.search_form = gtk.Entry()
        self.search_form.connect("activate", self.button_press)
 
        # Here's the HBox I mentioned...
        search_box = gtk.HBox(False, 0)
        search_box.pack_start(self.search_form, False, False)
        search_box.pack_start(button_find, False, False)
        
        # Pack the search box (search bar + Find button) into the side panel
        self.pack_start(search_box, False, False)
        
        # Create a check box to decide whether or not to ignore comments
        self.check_ignore = gtk.CheckButton("Ignore comments")
        self.check_ignore.connect("toggled", self.toggle_ignore)
        # Pack it in...
        self.pack_start(self.check_ignore, False, False)
        
        # Create a check box to determine whether to pay attention to case
        self.check_case = gtk.CheckButton("Case Sensitive")
        self.check_case.connect("toggled", self.toggle_case)
        # Pack it in...
        self.pack_start(self.check_case, False, False)
        
        # Show all UI elements
        self.show_all()
 
    # A click of the "Ignore comments" check box calls to this function
    def toggle_ignore(self, widget):
        self.ignore_comments = not self.ignore_comments
        
    # A click of the "Case sensitive" check box calls to this function
    def toggle_case(self, widget):
        self.case_sensitive = not self.case_sensitive
        
    # A call goes to view_result whenever the user clicks on
    # one of the results after a search. In response to the
    # click, we'll go to that file's tab (or open it in a
    # new tab if they since closed that tab) and scroll to
    # the line that the result appears in.
    def view_result(self, widget):
        # Get the selection object
        tree_selection = self.results_list.get_selection()
        
        # Get the model and iterator for the row selected
        (model, iterator) = tree_selection.get_selected()
        
        if (iterator):
            # Get the absolute path of the file
            absolute_path = model.get_value(iterator, 3)
            
            # Get the line number
            line_number = int(model.get_value(iterator, 2)) - 1
            
            # Get all open tabs
            documents = self.geditwindow.get_documents()
            
            # Loop through the tabs until we find which one matches the file
            # If we don't find it, we'll create it in a new tab afterwards.
            for each in documents:
            
                if (each.get_uri().replace("file://", "") == absolute_path):
                    # This sets the active tab to "each"
                    self.geditwindow.set_active_tab(gedit.tab_get_from_document(each))
                    each.goto_line(line_number)
 
                    # Get the bounds of the document
                    (start, end) = each.get_bounds()
                    
                    self.geditwindow.get_active_view().scroll_to_iter(end, 0.0)
                    
                    x = each.get_iter_at_line_offset(line_number, 0)
                    self.geditwindow.get_active_view().scroll_to_iter(x, 0.0)
                    
                    return
                    
            # If we got this far, then we didn't find the file open in a tab.
            # Thus, we'll want to go ahead and open it...
            self.geditwindow.create_tab_from_uri("file://" + absolute_path, self.encoding, int(model.get_value(iterator, 2)), False, True)
        
    # Clicking the "Find" button or hitting return in the search area calls button_press.
    # This function, of course, searches each open document for the search query and
    # displays the results in the side panel.
    def button_press(self, widget):
        # Get all open tabs
        documents = self.geditwindow.get_documents()
        
        # Make sure there are documents to search...
        if (len(documents) == 0):
            return # Can't search nothing. :P
            
        # Let's also make sure the user entered a search string
        if (len(self.search_form.get_text()) <= 0):
            return
        
        # Create a string that will hold all of the filenames;
        # we'll append it to the grep command string.
        string = ""
        
        fbroot = self.get_filebrowser_root()
        if fbroot != "" and fbroot is not None:
          location = fbroot.replace("file://", "")
        else:
          return
 
        hooray = os.popen ("find " + location + " -type f -not -regex '.*/.svn.*'").readlines()
        for hip in hooray:
          string += " '%s'" % hip[:-1]
        
        # str_case_operator will hold the "case insensitive" command if necessary
        str_case_operator = ""
        if (not self.case_sensitive):
            str_case_operator = " -i"
 
        # Create a pipe and call the grep command, then read it
        pipe = os.popen("grep -n -H" + str_case_operator + " %s %s" % (self.search_form.get_text(), string))
        data = pipe.read()
        results = data.split("\n")
        
        # Clear any current results from the side panel
        self.search_data.clear()
 
        # Process each result...
        for each in results:
            # Each result will look like this:
            # FILE (absolute path):Line number:string
            #
            # ... where string is the line that the search data was found in.
            pieces = each.split(":", 2)
            
            if (len(pieces) == 3):
                line_number = pieces[1]
                filename = os.path.basename(pieces[0]) # We just want the filename, not the path
                string = pieces[2].lstrip(" ") # Remove leading whitespace
 
                # If we want to ignore comments, then we'll make sure it doesn't start with # or //
                if (self.ignore_comments):
                    if (not string.startswith("#") and not string.startswith("//")):
                        self.search_data.append( ("%d" % (len(self.search_data) + 1), filename, line_number, pieces[0]) )
                else:
                    self.search_data.append( ("%d" % (len(self.search_data) + 1), filename, line_number, pieces[0]) )
                    
    def get_filebrowser_root(self):
        base = u'/apps/gedit-2/plugins/filebrowser/on_load'
        client = gconf.client_get_default()
        client.add_dir(base, gconf.CLIENT_PRELOAD_NONE)
        path = os.path.join(base, u'virtual_root')
        val = client.get(path)
        if val is not None:
          #also read hidden files setting
          base = u'/apps/gedit-2/plugins/filebrowser'
          client = gconf.client_get_default()
          client.add_dir(base, gconf.CLIENT_PRELOAD_NONE)
          path = os.path.join(base, u'filter_mode')
          try:
            fbfilter = client.get(path).get_string()
          except AttributeError:
            fbfilter = "hidden"
          if fbfilter.find("hidden") == -1:
            self._show_hidden = True
          else:
            self._show_hidden = False
          return val.get_string()
 
class PluginHelper:
    def __init__(self, plugin, window):
        self.window = window
        self.plugin = plugin
        
        self.ui_id = None
        
        self.add_panel(window)
        
    def deactivate(self):
        self.remove_menu_item()
        
        self.window = None
        self.plugin = None
        
    def update_ui(self):
        pass
        
    def add_panel(self, window):
        panel = self.window.get_side_panel()
        
        self.results_view = ResultsView(window)
        
        image = gtk.Image()
        image.set_from_stock(gtk.STOCK_DND_MULTIPLE, gtk.ICON_SIZE_BUTTON)
        self.ui_id = panel.add_item(self.results_view, "Find in Open Documents", image)
        
    def remove_menu_item(self):
        panel = self.window.get_side_panel()
        
        panel.remove_item(self.results_view)
 
class FindInDocumentsPlugin(gedit.Plugin):
    def __init__(self):
        gedit.Plugin.__init__(self)
        self.instances = {}
        
    def activate(self, window):
        self.instances[window] = PluginHelper(self, window)
        
    def deactivate(self, window):
        self.instances[window].deactivate()
        
    def update_ui(self, window):
        self.instances[window].update_ui()