diff options
Diffstat (limited to 'Demo/stdwin/wdiff.py')
-rwxr-xr-x | Demo/stdwin/wdiff.py | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/Demo/stdwin/wdiff.py b/Demo/stdwin/wdiff.py deleted file mode 100755 index 50ca032..0000000 --- a/Demo/stdwin/wdiff.py +++ /dev/null @@ -1,484 +0,0 @@ -#! /usr/bin/env python - -# A window-oriented recursive diff utility. -# NB: This uses undocumented window classing modules. - -# TO DO: -# - faster update after moving/copying one file -# - diff flags (-b, etc.) should be global or maintained per window -# - use a few fixed windows instead of creating new ones all the time -# - ways to specify patterns to skip -# (best by pointing at a file and clicking a special menu entry!) -# - add rcsdiff menu commands -# - add a way to view status of selected files without opening them -# - add a way to diff two files with different names -# - add a way to rename files -# - keep backups of overwritten/deleted files -# - a way to mark specified files as uninteresting for dircmp - -import sys -import os -import rand -import commands -import dircache -import statcache -import cmp -import cmpcache -import stdwin -import gwin -import textwin -import filewin -import tablewin -import anywin - -mkarg = commands.mkarg -mk2arg = commands.mk2arg - -# List of names to ignore in dircmp() -# -skiplist = ['RCS', 'CVS', '.Amake', 'tags', 'TAGS', '.', '..'] - -# Function to determine whether a name should be ignored in dircmp(). -# -def skipthis(file): - return file[-1:] == '~' or file in skiplist - - -def anydiff(a, b, flags): # Display differences between any two objects - print 'diff', flags, a, b - if os.path.isdir(a) and os.path.isdir(b): - w = dirdiff(a, b, flags) - else: - w = filediff(a, b, flags) - addstatmenu(w, [a, b]) - w.original_close = w.close - w.close = close_dirwin - return w - -def close_dirwin(w): - close_subwindows(w, (), 0) - w.original_close(w) - -def filediff(a, b, flags): # Display differences between two text files - diffcmd = 'diff' - if flags: diffcmd = diffcmd + mkarg(flags) - diffcmd = diffcmd + mkarg(a) + mkarg(b) - difftext = commands.getoutput(diffcmd) - return textwin.open_readonly(mktitle(a, b), difftext) - -def dirdiff(a, b, flags): # Display differences between two directories - data = diffdata(a, b, flags) - w = tablewin.open(mktitle(a, b), data) - w.flags = flags - w.a = a - w.b = b - addviewmenu(w) - addactionmenu(w) - return w - -def diffdata(a, b, flags): # Compute directory differences. - # - a_only = [('A only:', header_action), ('', header_action)] - b_only = [('B only:', header_action), ('', header_action)] - ab_diff = [('A <> B:', header_action), ('', header_action)] - ab_same = [('A == B:', header_action), ('', header_action)] - data = [a_only, b_only, ab_diff, ab_same] - # - a_list = dircache.listdir(a)[:] - b_list = dircache.listdir(b)[:] - dircache.annotate(a, a_list) - dircache.annotate(b, b_list) - a_list.sort() - b_list.sort() - # - for x in a_list: - if x in ['./', '../']: - pass - elif x not in b_list: - a_only.append((x, a_only_action)) - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if os.path.isdir(ax) and os.path.isdir(bx): - if flags == '-r': - same = dircmp(ax, bx) - else: - same = 0 - else: - try: - same = cmp.cmp(ax, bx) - except (RuntimeError, os.error): - same = 0 - if same: - ab_same.append((x, ab_same_action)) - else: - ab_diff.append((x, ab_diff_action)) - # - for x in b_list: - if x in ['./', '../']: - pass - elif x not in a_list: - b_only.append((x, b_only_action)) - # - return data - -# Re-read the directory. -# Attempt to find the selected item back. - -def update(w): - setbusy(w) - icol, irow = w.selection - if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]): - selname = w.data[icol][irow][0] - else: - selname = '' - statcache.forget_dir(w.a) - statcache.forget_dir(w.b) - tablewin.select(w, (-1, -1)) - tablewin.update(w, diffdata(w.a, w.b, w.flags)) - if selname: - for icol in range(len(w.data)): - for irow in range(2, len(w.data[icol])): - if w.data[icol][irow][0] == selname: - tablewin.select(w, (icol, irow)) - break - -# Action functions for table items in directory diff windows - -def header_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (-1, -1)) - -def a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.a, string)) - if w2: - w2.parent = w - -def b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.b, string)) - if w2: - w2.parent = w - -def ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anydiff(os.path.join(w.a, string), os.path.join(w.b, string),'') - w2.parent = w - -def ab_same_action(w, string, sel, detail): - ax = os.path.join(w.a, string) - if os.path.isdir(ax): - ab_diff_action(w, string, sel, detail) - else: - a_only_action(w, string, sel, detail) - -def anyopen(name): # Open any kind of document, ignore errors - try: - w = anywin.open(name) - except (RuntimeError, os.error): - stdwin.message('Can\'t open ' + name) - return 0 - addstatmenu(w, [name]) - return w - -def dircmp(a, b): # Compare whether two directories are the same - # To make this as fast as possible, it uses the statcache - print ' dircmp', a, b - a_list = dircache.listdir(a) - b_list = dircache.listdir(b) - for x in a_list: - if skipthis(x): - pass - elif x not in b_list: - return 0 - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if statcache.isdir(ax) and statcache.isdir(bx): - if not dircmp(ax, bx): return 0 - else: - try: - if not cmpcache.cmp(ax, bx): return 0 - except (RuntimeError, os.error): - return 0 - for x in b_list: - if skipthis(x): - pass - elif x not in a_list: - return 0 - return 1 - - -# View menu (for dir diff windows only) - -def addviewmenu(w): - w.viewmenu = m = w.menucreate('View') - m.action = [] - add(m, 'diff -r A B', diffr_ab) - add(m, 'diff A B', diff_ab) - add(m, 'diff -b A B', diffb_ab) - add(m, 'diff -c A B', diffc_ab) - add(m, 'gdiff A B', gdiff_ab) - add(m, ('Open A ', 'A'), open_a) - add(m, ('Open B ', 'B'), open_b) - add(m, 'Rescan', rescan) - add(m, 'Rescan -r', rescan_r) - -# Action menu (for dir diff windows only) - -def addactionmenu(w): - w.actionmenu = m = w.menucreate('Action') - m.action = [] - add(m, 'cp A B', cp_ab) - add(m, 'rm B', rm_b) - add(m, '', nop) - add(m, 'cp B A', cp_ba) - add(m, 'rm A', rm_a) - -# Main menu (global): - -def mainmenu(): - m = stdwin.menucreate('Wdiff') - m.action = [] - add(m, ('Quit wdiff', 'Q'), quit_wdiff) - add(m, 'Close subwindows', close_subwindows) - return m - -def add(m, text, action): - m.additem(text) - m.action.append(action) - -def quit_wdiff(w, m, item): - if askyesno('Really quit wdiff altogether?', 1): - sys.exit(0) - -def close_subwindows(w, m, item): - while 1: - for w2 in gwin.windows: - if w2.parent == w: - close_subwindows(w2, m, item) - w2.close(w2) - break # inner loop, continue outer loop - else: - break # outer loop - -def diffr_ab(w, m, item): - dodiff(w, '-r') - -def diff_ab(w, m, item): - dodiff(w, '') - -def diffb_ab(w, m, item): - dodiff(w, '-b') - -def diffc_ab(w, m, item): - dodiff(w, '-c') - -def gdiff_ab(w, m, item): # Call SGI's gdiff utility - x = getselection(w) - if x: - a, b = os.path.join(w.a, x), os.path.join(w.b, x) - if os.path.isdir(a) or os.path.isdir(b): - stdwin.fleep() # This is for files only - else: - diffcmd = 'gdiff' - diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &' - print diffcmd - sts = os.system(diffcmd) - if sts: print 'Exit status', sts - -def dodiff(w, flags): - x = getselection(w) - if x: - w2 = anydiff(os.path.join(w.a, x), os.path.join(w.b, x), flags) - w2.parent = w - -def open_a(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.a, x)) - if w2: - w2.parent = w - -def open_b(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.b, x)) - if w2: - w2.parent = w - -def rescan(w, m, item): - w.flags = '' - update(w) - -def rescan_r(w, m, item): - w.flags = '-r' - update(w) - -def rm_a(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.a, x) - if os.path.isdir(x): - if askyesno('Recursively remove A directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def rm_b(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.b, x) - if os.path.isdir(x): - if askyesno('Recursively remove B directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def cp_ab(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(ax): - if os.path.exists(bx): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(ax) + mkarg(w.b)) - else: - runcmd('cp' + mkarg(ax) + mk2arg(w.b, x)) - update(w) - -def cp_ba(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(bx): - if os.path.exists(ax): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(bx) + mkarg(w.a)) - else: - runcmd('cp' + mk2arg(w.b, x) + mkarg(ax)) - update(w) - -def nop(args): - pass - -def getselection(w): - icol, irow = w.selection - if 0 <= icol < len(w.data): - if 0 <= irow < len(w.data[icol]): - return w.data[icol][irow][0] - stdwin.message('no selection') - return '' - -def runcmd(cmd): - print cmd - sts, output = commands.getstatusoutput(cmd) - if sts or output: - if not output: - output = 'Exit status ' + `sts` - stdwin.message(output) - - -# Status menu (for all kinds of windows) - -def addstatmenu(w, files): - w.statmenu = m = w.menucreate('Stat') - m.files = files - m.action = [] - for file in files: - m.additem(commands.getstatus(file)) - m.action.append(stataction) - -def stataction(w, m, item): # Menu item action for stat menu - file = m.files[item] - try: - m.setitem(item, commands.getstatus(file)) - except os.error: - stdwin.message('Can\'t get status for ' + file) - - -# Compute a suitable window title from two paths - -def mktitle(a, b): - if a == b: return a - i = 1 - while a[-i:] == b[-i:]: i = i+1 - i = i-1 - if not i: - return a + ' ' + b - else: - return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:] - - -# Ask a confirmation question - -def askyesno(prompt, default): - try: - return stdwin.askync(prompt, default) - except KeyboardInterrupt: - return 0 - - -# Display a message "busy" in a window, and mark it for updating - -def setbusy(w): - left, top = w.getorigin() - width, height = w.getwinsize() - right, bottom = left + width, top + height - d = w.begindrawing() - d.erase((0, 0), (10000, 10000)) - text = 'Busy...' - textwidth = d.textwidth(text) - textheight = d.lineheight() - h, v = left + (width-textwidth)/2, top + (height-textheight)/2 - d.text((h, v), text) - del d - w.change((0, 0), (10000, 10000)) - - -# Main function - -def main(): - print 'wdiff: warning: this program does NOT make backups' - argv = sys.argv - flags = '' - if len(argv) >= 2 and argv[1][:1] == '-': - flags = argv[1] - del argv[1] - stdwin.setdefscrollbars(0, 1) - m = mainmenu() # Create menu earlier than windows - if len(argv) == 2: # 1 argument - w = anyopen(argv[1]) - if not w: return - elif len(argv) == 3: # 2 arguments - w = anydiff(argv[1], argv[2], flags) - w.parent = () - else: - sys.stdout = sys.stderr - print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]' - sys.exit(2) - del w # It's preserved in gwin.windows - while 1: - try: - gwin.mainloop() - break - except KeyboardInterrupt: - pass # Just continue... - -# Start the main function (this is a script) -main() |