Word Wrap toolbar button.
[rox-edit/bju.git] / diff.py
blob5f62c342835e41a1f3b2c0a75a52e4b6ce3d9ad6
1 import rox
2 import os
3 from rox import processes, g
4 from rox.options import Option
6 try:
7 processes.PipeThroughCommand
8 except:
9 rox.croak('Edit requires ROX-Lib 1.9.11 or later. Sorry!\n'
10 '\nhttp://rox.sourceforge.net/rox_lib.html')
12 header_fg = Option('headers_fg', '#000')
13 header_bg = Option('headers_bg', '#ddd')
15 static_fg = Option('static_fg', '#000')
16 static_bg = Option('static_bg', '#fff')
18 additions_fg = Option('additions_fg', '#000')
19 additions_bg = Option('additions_bg', '#8f8')
21 deletions_fg = Option('deletions_fg', '#000')
22 deletions_bg = Option('deletions_bg', '#f88')
24 tags = g.TextTagTable()
26 header = g.TextTag('header')
27 tags.add(header)
29 static = g.TextTag('static')
30 tags.add(static)
32 add = g.TextTag('add')
33 tags.add(add)
34 remove = g.TextTag('remove')
35 tags.add(remove)
37 def options_changed():
38 header.set_property('foreground', header_fg.value)
39 header.set_property('background', header_bg.value)
40 static.set_property('foreground', static_fg.value)
41 static.set_property('background', static_bg.value)
42 add.set_property('foreground', additions_fg.value)
43 add.set_property('background', additions_bg.value)
44 remove.set_property('foreground', deletions_fg.value)
45 remove.set_property('background', deletions_bg.value)
47 rox.app_options.add_notify(options_changed)
49 class Diff(processes.PipeThroughCommand):
50 def __init__(self, uri, src, dst):
51 processes.PipeThroughCommand.__init__(self, ('diff', '-u', '--', uri, '-'), src, dst)
52 self.wait()
54 def check_errors(self, errors, status):
55 if errors:
56 raise Exception(errors)
58 def Tmp(mode = 'w+b', suffix = '-tmp'):
59 "Create a seekable, randomly named temp file (deleted automatically after use)."
60 import tempfile
61 try:
62 return tempfile.NamedTemporaryFile(mode, suffix = suffix)
63 except:
64 # python2.2 doesn't have NamedTemporaryFile...
65 pass
67 import random
68 name = tempfile.mktemp(`random.randint(1, 1000000)` + suffix)
70 fd = os.open(name, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
71 tmp = tempfile.TemporaryFileWrapper(os.fdopen(fd, mode), name)
72 tmp.name = name
73 return tmp
75 class DiffWindow(rox.Dialog):
76 def __init__(self, uri, diff):
77 rox.Dialog.__init__(self)
78 self.set_title(_('Changes to %s') % uri)
79 self.set_has_separator(False)
81 buffer = g.TextBuffer(tags)
82 text = g.TextView(buffer)
83 text.set_editable(False)
84 text.set_cursor_visible(False)
85 text.modify_base(g.STATE_NORMAL, g.gdk.color_parse(static_bg.value))
87 swin = g.ScrolledWindow()
88 swin.set_shadow_type(g.SHADOW_IN)
89 swin.set_policy(g.POLICY_AUTOMATIC, g.POLICY_ALWAYS)
90 self.vbox.pack_start(swin)
91 swin.add(text)
92 self.vbox.show_all()
94 self.add_button(g.STOCK_CLOSE, g.RESPONSE_OK)
95 self.connect('response', lambda b, r: self.destroy())
97 iter = buffer.get_start_iter()
98 for line in diff.split('\n'):
99 line += '\n'
100 line = line.replace('\t', ' ')
101 if line[:4] in ('--- ', '+++ ', '@@ -'):
102 tag = header
103 elif line.startswith('-'):
104 tag = remove
105 if len(line) < 3: line = ' \n'
106 elif line.startswith('+'):
107 tag = add
108 if len(line) < 3: line = ' \n'
109 else:
110 tag = static
111 buffer.insert_with_tags(iter, line[1:], tag)
113 width = g.gdk.screen_width() * 3 / 4
114 height = g.gdk.screen_height() * 1 / 2
115 self.set_default_size(width, height)
118 def show_diff(uri, writer):
119 from cStringIO import StringIO
120 src = Tmp(suffix = '-diff')
121 dst = StringIO()
122 writer(src)
123 src.seek(0)
124 Diff(uri, src, dst)
125 del src
126 diff = dst.getvalue()
127 del dst
128 if not diff:
129 rox.info(_('There is no difference between this version and the saved one.'))
130 else:
131 DiffWindow(uri, diff).show()