On 11/2/06, Stephen Kennedy <[EMAIL PROTECTED]> wrote: > > > I really like meld for visual diffing, but I often have several files > > > diffed at the same time, so it would be very helpful to have new diffs > > > open in an existing meld window - something that for example gedit > > > currently does. To be precise, I would like meld to check, on startup, > > > if there's another instance open already and if it is, open the > > > requested diff in a new tab in the existing window. What's great is > > > that meld already has tabs - all we need to do is check for an > > > existing instance on startup, and pass it the arguments. > > > The most modern gnomish library for handling IPC is probably dbus, and > > appears to be what evince uses for this type of "successive concurrent > > executions open within the original parent process" functionality. See > > dbus is certainly the way to go here. The python binding are quite good too. > > It would also solve another tricky problem. Meld does not return a > useful exit code because of the tabbed interface, which confuses some > tools. It would be great to have a helper app which can open a single > tab and wait for its exit status.
What follows is a patch against meld-1.1.3 that implements open-in-existing-window functionality through dbus. The limitation is that the dbus bingings require python 2.4 for remote object instances. If dbus is not installed on the system, meld will silently ignore all the dbus stuff, but I could alternatively print a message informing the user. I haven't looked at returning a useful return code, but the dbus support is easily extendible if anyone's interested in doing that. I may have done things in a way not agreeable with the original creators. Comments, criticism, questions welcome and appreciated. In case the inline patch is frobbed by some mail system, you can also find the patch at: http://kacper.doesntexist.org/hacks/meld-dbus.patch diff -ru meld-1.1.3/meldapp.py meld-1.1.3-kw/meldapp.py --- meld-1.1.3/meldapp.py 2006-01-29 01:17:28.000000000 +0100 +++ meld-1.1.3-kw/meldapp.py 2006-11-18 13:05:23.584357970 +0100 @@ -34,6 +34,24 @@ import task # optional + +# dbus +dbus_available = 0 +try: + import dbus + import dbus.service + if getattr(dbus, 'version', (0,0,0)) >= (0,41,0): + import dbus.glib + dbus_available = 1 + else: + pass # dbus version too old +except ImportError: + pass + # FIXME: Do I print this error or give the silent treatement? + #print "Oops, no dbus. Please install the python-dbus package." + #print "Meld will not be able to launch new diffs in existing window." + +# sourceview sourceview_available = 0 for sourceview in "gtksourceview sourceview".split(): @@ -787,6 +805,30 @@ sys.exit(0) + def parseargs(self,args): + if len(args) == 0: + pass + + elif len(args) == 1: + a = args[0] + if os.path.isfile(a): + doc = vcview.VcView(self.prefs) + def cleanup(): + self.scheduler.remove_scheduler(doc.scheduler) + self.scheduler.add_task(cleanup) + self.scheduler.add_scheduler(doc.scheduler) + doc.set_location( os.path.dirname(a) ) + doc.connect("create-diff", + lambda obj,arg: self.append_diff(arg) ) + doc.run_diff([a]) + else: + self.append_vcview( [a] ) + + elif len(args) in (2,3): + self.append_diff(args) + else: + self.usage( _("Wrong number of arguments (Got %i)") % len(args)) + ################################################################################ # @@ -804,6 +846,7 @@ Options: -h, --help Show this help text and exit -v, --version Display the version and exit + -n, --new-window Open new window regardless For more information choose help -> contents. Report bugs at http://bugzilla.gnome.org/buglist.cgi?product=meld @@ -815,6 +858,56 @@ ################################################################################ # +# DBus stuff +# +# You either have dbus, or you don't. +# If you don't, I can't help yah, +# if you do, you either have meld running already or you don't. +# +# If you don't, I'll register the meld dbus interface, +# if you do, you either want a new window or not. +# +# If you don't, I'll pass those args along the bus, +# if you do, I'll just start a new window. +# +# -Kacper Wysocki ([EMAIL PROTECTED]) +# +################################################################################ + +class MeldDbus(dbus.service.Object): + def __init__(self, bus_name, app, object_path='/net/sf/meld'): + dbus.service.Object.__init__(self, bus_name, object_path) + self.app = app + + @dbus.service.method('net.sf.meld') + def diff(self, args): + self.app.parseargs(args) + +def register_dbus(app): + session_bus = dbus.SessionBus() + bus_name = dbus.service.BusName('net.sf.meld', bus=session_bus) + remotemeld = MeldDbus(bus_name, app) + +def try_dbus(): + bus = dbus.SessionBus() + proxy = bus.get_object('org.freedesktop.DBus', + '/org/freedesktop/DBus') + iface = dbus.Interface(proxy, 'org.freedesktop.DBus') + names = iface.ListNames() + if "net.sf.meld" in names: # does meld dbus interface exist? + return 1 # Found a running instance, passed things along + return 0 # didn't + +def pass_args_dbus(args): + bus = dbus.SessionBus() + proxy = bus.get_object('net.sf.meld','/net/sf/meld') + iface = dbus.Interface(proxy, 'net.sf.meld') + iface.diff(args) + + + +################################################################################ +# # Main # ################################################################################ @@ -829,6 +922,7 @@ return getattr(self.file, attr) sys.stdout = Unbuffered(sys.stdout) args = sys.argv[1:] + force_new_window = 0 if args: if "-h" in args or "--help" in args: @@ -837,30 +931,22 @@ if "-v" in args or "--version" in args: print version_string return + if "-n" in args or "--new-window" in args: + force_new_window = 1 - app = MeldApp() - if len(args) == 0: - pass - - elif len(args) == 1: - a = args[0] - if os.path.isfile(a): - doc = vcview.VcView(app.prefs) - def cleanup(): - app.scheduler.remove_scheduler(doc.scheduler) - app.scheduler.add_task(cleanup) - app.scheduler.add_scheduler(doc.scheduler) - doc.set_location( os.path.dirname(a) ) - doc.connect("create-diff", lambda obj,arg: app.append_diff(arg) ) - doc.run_diff([a]) - else: - app.append_vcview( [a] ) - - elif len(args) in (2,3): - app.append_diff(args) - else: - app.usage( _("Wrong number of arguments (Got %i)") % len(args)) + running_already = 0 + if dbus_available: + running_already = try_dbus() + if running_already: + if args and not force_new_window: + pass_args_dbus(args) + return + # either you're forcing a new window or it ain't running yet + app = MeldApp() + if dbus_available and not running_already: + register_dbus(app) + app.parseargs(args) app.main() _______________________________________________ meld-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/meld-list
