[gedit] Added filename detection to output panel and implemented click-open



commit 275f6305cec1e59583bce5a07768e51824ab25ff
Author: Jesse van den Kieboom <jesse icecrew nl>
Date:   Fri May 22 21:03:06 2009 +0200

    Added filename detection to output panel and implemented click-open
    
    Patch original from Mathias Hasselmann, modified to to be less gcc specific.
    Fixes bug #407368.
---
 plugins/externaltools/tools/functions.py   |    2 +-
 plugins/externaltools/tools/outputpanel.py |  127 +++++++++++++++++++++++++++-
 plugins/externaltools/tools/outputpanel.ui |    3 +
 3 files changed, 127 insertions(+), 5 deletions(-)

diff --git a/plugins/externaltools/tools/functions.py b/plugins/externaltools/tools/functions.py
index 8d09c7f..18bd2fa 100644
--- a/plugins/externaltools/tools/functions.py
+++ b/plugins/externaltools/tools/functions.py
@@ -85,7 +85,7 @@ def run_external_tool(window, node):
         panel.show()
 
     # Assign the error output to the output panel
-    panel.process = capture
+    panel.set_process(capture)
 
     if input_type != 'nothing' and view is not None:
         if input_type == 'document':
diff --git a/plugins/externaltools/tools/outputpanel.py b/plugins/externaltools/tools/outputpanel.py
index c085b5f..6820cf2 100644
--- a/plugins/externaltools/tools/outputpanel.py
+++ b/plugins/externaltools/tools/outputpanel.py
@@ -24,6 +24,9 @@ import gobject
 import os
 from weakref import WeakKeyDictionary
 from capture import *
+from gtk import gdk
+import re
+import gio
 
 class UniqueById:
     __shared_state = WeakKeyDictionary()
@@ -45,7 +48,10 @@ class OutputPanel(UniqueById):
             return
 
         callbacks = {
-            'on_stop_clicked' : self.on_stop_clicked
+            'on_stop_clicked' : self.on_stop_clicked,
+            'on_view_visibility_notify_event': self.on_view_visibility_notify_event,
+            'on_view_motion_notify_event': self.on_view_motion_notify_event,
+            'on_view_button_press_event': self.on_view_button_press_event
         }
 
         self.window = window
@@ -57,16 +63,34 @@ class OutputPanel(UniqueById):
         self['view'].modify_font(pango.FontDescription('Monospace'))
 
         buffer = self['view'].get_buffer()
+        
         self.normal_tag = buffer.create_tag("normal")
-        self.error_tag  = buffer.create_tag("error")
+        
+        self.error_tag = buffer.create_tag("error")
         self.error_tag.set_property("foreground", "red")
+        
         self.italic_tag = buffer.create_tag('italic')
         self.italic_tag.set_property('style', pango.STYLE_OBLIQUE)
+        
         self.bold_tag = buffer.create_tag('bold')
         self.bold_tag.set_property('weight', pango.WEIGHT_BOLD)
+        
+        self.link_tag = buffer.create_tag('link')
+        self.link_tag.set_property('underline', pango.UNDERLINE_LOW)
+        
+        self.line_tag = buffer.create_tag('line')
+        
+        self.link_cursor = gdk.Cursor(gdk.HAND2)
+        self.normal_cursor = gdk.Cursor(gdk.XTERM)
+        
+        self.link_regex = re.compile('((\\./|\\.\\./|/)[^\s:]+|[^\s:]+\\.[^\s:]+)(:([0-9]+))?')
 
         self.process = None
 
+    def set_process(self, process):
+        self.process = process
+        self.cwd = process.cwd
+
     def __getitem__(self, key):
         # Convenience function to get an object from its name
         return self.ui.get_object(key)
@@ -91,15 +115,110 @@ class OutputPanel(UniqueById):
 
     def write(self, text, tag = None):
         buffer = self['view'].get_buffer()
+        
+        end_iter = buffer.get_end_iter()
+        insert = buffer.create_mark(None, end_iter, True)
+
         if tag is None:
-            buffer.insert(buffer.get_end_iter(), text)
+            buffer.insert(end_iter, text)
         else:
-            buffer.insert_with_tags(buffer.get_end_iter(), text, tag)
+            buffer.insert_with_tags(end_iter, text, tag)
+        
+        for m in self.link_regex.finditer(text):
+            start = buffer.get_iter_at_mark(insert)
+            start.forward_chars(m.start(0))
+            end = start.copy()
+            end.forward_chars(m.end(0))
+            
+            filename = m.group(1)
+            
+            if (os.path.isabs(filename) and os.path.isfile(filename)) or \
+               (os.path.isfile(os.path.join(self.cwd, filename))):
+                buffer.apply_tag(self.link_tag, start, end)
+                
+                if m.group(4):
+                    start = buffer.get_iter_at_mark(insert)
+                    start.forward_chars(m.start(4))
+                    end = start.copy()
+                    end.forward_chars(m.end(4))
+            
+                    buffer.apply_tag(self.line_tag, start, end)
+        
+        buffer.delete_mark(insert)
         gobject.idle_add(self.scroll_to_end)
 
     def show(self):
         panel = self.window.get_bottom_panel()
         panel.show()
         panel.activate_item(self.panel)
+    
+    def update_cursor_style(self, view, x, y):
+        x, y = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, int(x), int(y))
+        piter = view.get_iter_at_location(x, y)
+        
+        if piter.has_tag(self.link_tag):
+            cursor = self.link_cursor
+        else:
+            cursor = self.normal_cursor
+
+        view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(cursor)
+    
+    def on_view_motion_notify_event(self, view, event):
+        if event.window == view.get_window(gtk.TEXT_WINDOW_TEXT):
+            self.update_cursor_style(view, event.x, event.y)
+
+        return False
+    
+    def on_view_visibility_notify_event(self, view, event):
+        if event.window == view.get_window(gtk.TEXT_WINDOW_TEXT):
+            x, y = event.window.get_pointer()
+            self.update_cursor_style(view, x, y)
+
+        return False
+    
+    def idle_grab_focus(self):
+        self.window.get_active_view().grab_focus()
+        return False
+    
+    def on_view_button_press_event(self, view, event):
+        if event.button != 1 or event.type != gdk.BUTTON_PRESS or \
+           event.window != view.get_window(gtk.TEXT_WINDOW_TEXT):
+            return False
+        
+        x, y = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, int(event.x), int(event.y))
+        
+        start = view.get_iter_at_location(x, y)
+
+        if not start.has_tag(self.link_tag):
+            return False
+        
+        end = start.copy()
+        start.backward_to_tag_toggle(self.link_tag)
+        line = start.copy()
+        
+        end.forward_to_tag_toggle(self.link_tag)
+        line.forward_to_tag_toggle(self.line_tag)
+
+        if line.compare(end) < 0:
+            tot = line.copy()
+            tot.backward_char()
+            
+            text = start.get_text(tot)
+            toline = int(line.get_text(end))
+        else:
+            text = start.get_text(end)
+            toline = 0
+
+        gfile = None
+        
+        if os.path.isabs(text) and os.path.isfile(text):
+            gfile = gio.File(text)
+        elif os.path.isfile(os.path.join(self.cwd, text)):
+            gfile = gio.File(os.path.join(self.cwd, text))
+            
+        if gfile:
+            gedit.commands.load_uri(self.window, gfile.get_uri(), None, toline)
+            
+            gobject.idle_add(self.idle_grab_focus)
 
 # ex:ts=4:et:
diff --git a/plugins/externaltools/tools/outputpanel.ui b/plugins/externaltools/tools/outputpanel.ui
index cea0609..f028179 100644
--- a/plugins/externaltools/tools/outputpanel.ui
+++ b/plugins/externaltools/tools/outputpanel.ui
@@ -21,6 +21,9 @@
         <property name="wrap_mode">GTK_WRAP_WORD</property>
         <property name="cursor_visible">False</property>
         <property name="accepts_tab">False</property>
+        <signal name="button_press_event" handler="on_view_button_press_event"/>
+        <signal name="motion_notify_event" handler="on_view_motion_notify_event"/>
+        <signal name="visibility_notify_event" handler="on_view_visibility_notify_event"/>
       </object>
     </child>
       </object>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]