Fix the 'x lines selected' message (v3)
[rox-edit/bju.git] / diff.py
blobb49943a218eccd69d549663ef9d5e1c4b1e751e1
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 if line[:4] in ('--- ', '+++ ', '@@ -'):
101 tag = header
102 elif line.startswith('-'):
103 tag = remove
104 if len(line) < 3: line = ' \n'
105 elif line.startswith('+'):
106 tag = add
107 if len(line) < 3: line = ' \n'
108 else:
109 tag = static
110 buffer.insert_with_tags(iter, line, tag)
112 width = g.gdk.screen_width() * 3 / 4
113 height = g.gdk.screen_height() * 1 / 2
114 self.set_default_size(width, height)
117 def show_diff(uri, writer):
118 from cStringIO import StringIO
119 src = Tmp(suffix = '-diff')
120 dst = StringIO()
121 writer(src)
122 src.seek(0)
123 Diff(uri, src, dst)
124 del src
125 diff = dst.getvalue()
126 del dst
127 if not diff:
128 rox.info(_('There is no difference between this version and the saved one.'))
129 else:
130 DiffWindow(uri, diff).show()