#!/usr/bin/env python # Copyright (C) 2006 Julian Smith, jules@op59.net. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA '''Params: --dw Extract @: from specified window's titlebar -c Open document, using new selection. --delay -s Open document, using existing selection if possible. -t --throwbackx Location of the throwbackx executable. -v Verbose ''' import os, re, sys, time debugout = sys.stdout #debugout = open( '/home/jules/throwback-out', 'a') def make_command( filename, line, titlebar): ''' Returns a command that will open at line number , using info in to ssh to appropriate machine and cd to appropriate directory. We expect to be @:[/]... ''' # make a command that calls nedit's client, variously called ncl, # neditc etc. i have a softlink in ~/bin/n on all my systems. command = '~/bin/n -line ' + str( line) + ' \'' + filename + '\'' if titlebar: user_machine, directory = titlebar.split( ':', 1) directory = directory.split( ' ', 1)[0] if not directory.endswith( '/'): directory = os.path.dirname( directory) command = 'ssh -X ' + user_machine + ' "cd ' + directory + ' && ' + command + '"' return command def parse( selection): ''' parses the given X Window selection, returning (, ), both strings. ''' m = re.match( '[^ ]+@[^ ]+ +(.*)', selection) if m: #print 'skipping prefix: ', selection selection = m.group(1) #print 'skipping prefix: ', selection # try gdb format: m = re.match( 'File "([^"]+)", line ([0-9]+)', selection) if m: return m.group(1), m.group(2) # gdb backtrace format: m = re.match( '#[0-9][^\n]+ at ([^:]+):([0-9]+)', selection) if m: return m.group(1), m.group(2) # try python format: m = re.match( 'Line ([0-9]+) of "([^"]+)"', selection) if m: return m.group(2), m.group(1) # gcc/grep format: # skip any initial `[...]': if selection.startswith( '['): i = selection.find( ']') if i>0: selection = selection[i+1:].strip() m = re.match( '([^:]+):([0-9]*)', selection) if m: filename = m.group(1) line = m.group(2) if line=='': line = '1' return filename, line m = re.match( '([^: ]+)', selection) if m: filename = m.group(1) return filename, 1 raise Exception( 'can\'t parse selection: ' + repr( selection)) def read_x_selection( throwbackx_exe): #child_in, child_outerr = os.popen4( throwbackx_exe + ' --selection') child_in, child_outerr = os.popen4( 'xclip -o') return child_outerr.read() def main(): verbose = 0 desktop = None window = None throwbackx_exe = None do = None selection = '' #print 'argv=', sys.argv args = iter( sys.argv[1:]) while True: try: arg = args.next() except StopIteration: break if arg=='--dw': desktop = args.next() window = args.next() elif arg=='-c': do = 'c' elif arg=='-s': do = 's' elif arg=='-t': do = 't' selection = args.next() elif arg=='--throwbackx': throwbackx_exe = args.next() elif arg=='-v': verbose += 1 #if verbose==1: # debugout = open( '/home/jules/throwback-out', 'a') elif arg=='--delay': time.sleep( int( args.next())) elif arg=='-h' or arg=='--help': print __doc__ else: raise Exception( 'unrecognised option: ' + arg) verbose = 0 if verbose==1: debugout = open( '/home/jules/throwback-out', 'a') if do: if not throwbackx_exe: # find our directory; it should contain the throwbackx executable: throwback_dir = os.path.dirname( os.path.abspath( sys.argv[0])) throwbackx_exe = os.path.join( throwback_dir, 'throwbackx.exe') if not os.path.isfile( throwbackx_exe): raise Exception( 'can\'t find ' + throwbackx_exe + '. it should' ' be built from the throwbackx.c source file - see that file' ' for details.') if do=='s': # use existing selection if available: selection = read_x_selection( throwbackx_exe).strip() if selection=='': # fake a triple-click to select whole line under the pointer. os.system( throwbackx_exe + ' --click --click --click') selection = read_x_selection( throwbackx_exe).strip() if verbose: print >>debugout, 'selection is:', selection filename, line = parse( selection) if verbose: print >>debugout, 'filename:', filename print >>debugout, 'line:', line #if not os.path.exists( filename): # raise Exception( 'fiename doesn\'t exist: ' + filename) if desktop and window: if verbose: print >>debugout, 'dw:', desktop, window # we have a windowID, so try to read its titlebar, and from that # infer the user/machine: child_in, child_outerr = os.popen4( throwbackx_exe + ' --title ' + desktop + ' ' + window) titlebar = child_outerr.read() else: titlebar = None command = make_command( filename, line, titlebar) if verbose: print >>debugout, 'command is:', command os.system( command) if __name__=='__main__': try: main() except Exception, e: if 0: print >>debugout, 'throwback:', e sys.exit(1) else: raise