commit f2e836da0dafde74e678a1943dc281dd6669eaae Author: Erik Osheim Date: Mon Aug 2 11:14:18 2010 -0400 initial import diff --git a/cleanse b/cleanse new file mode 100755 index 0000000..629a41e --- /dev/null +++ b/cleanse @@ -0,0 +1,22 @@ +#!/usr/bin/python +# +# by Erik osheim +import optparse, os + +epilog = 'Remove various junky files left lying around.' +patterns = ('*~', '.#*', '#*', '*.orig', '*-') + +parser = optparse.OptionParser(epilog=epilog) +parser.add_option('-f', '--fake', dest='fake', action='store_true', + help="print files; do not remove them") +opts, args = parser.parse_args() + +stanzas = ' -o '.join(["-name '%s'" % x for x in patterns]) +cmd = "find . -type f \\( %s \\) -print" % stanzas + +if opts.fake: + print "files that would be deleted:" +else: + cmd += " -exec rm {} ';'"; + +os.system(cmd) diff --git a/histo b/histo new file mode 100755 index 0000000..5f27a1a --- /dev/null +++ b/histo @@ -0,0 +1,105 @@ +#!/usr/bin/python +import optparse +import os +import sys + +# this is a dictionary of all the "items" (lines) that have been seen, mapping +# to a count of how many times it was seen. +seen = {} + +parser = optparse.OptionParser() +parser.set_defaults(draw=False, nullok=False, valsort=False, reverse=False, + hwidth=None, percent=False, strip=False, delim=' ', + swap=False, josh=False, nopad=False) +parser.add_option('-d', '--draw', action='store_true', dest='draw', + help='draw histogram with horizontal graph') +parser.add_option('-D', '--delim', action='store', type="string", dest='delim', + help='use STR as delimiter (default: " ")', metavar='STR') +parser.add_option('-f', '--frequency', action='store_true', dest='valsort', + help='sort by frequency') +parser.add_option('-J', '--josh', action='store_true', dest='josh', + help='josh rosenberg compatibility mode') +parser.add_option('-N', '--nopad', action='store_true', dest='nopad', + help='do not column-align output') +parser.add_option('-p', '--percent', action='store_true', dest='percent', + help='show percent rather than count') +parser.add_option('-r', '--reverse', action='store_true', dest='reverse', + help='reverse sort') +parser.add_option('-s', '--strip', action='store_true', dest='strip', + help='strip input lines') +parser.add_option('-S', '--swap', action='store_true', dest='swap', + help='swap output fields') +parser.add_option('-w', '--width', action='store', type='int', dest='hwidth', + help='use NUM characters for graph drawing', metavar="NUM") +parser.add_option('-z', '--null', action='store_true', dest='nullok', + help='allow null lines') +(opts, args) = parser.parse_args() + +# allow some special delimiters to be translated +delims = {'\\t': '\t', '\\v': '\v', '\\0': '\0'} +opts.delim = delims.get(opts.delim, opts.delim) + +# josh rosenberg compatiblity mode +if opts.josh: + opts.delim = '\t' + opts.swap = True + opts.nopad = True + +# process each line on stdin. we can optionally strip whitespace, and we always +# strip a trailing newline. by default we ignore empty lines, but nullok causes +# us to count them as well. +for line in sys.stdin: + key = line[:-1] + if opts.strip: + key = key.strip() + if key or opts.nullok: + seen.setdefault(key, 0) + seen[key] += 1 + +# sort either by key or by count, depending on the user wanted +keys = seen.keys() +if opts.valsort: + cmpf = lambda a, b: cmp(seen[b], seen[a]) +else: + cmpf = lambda a, b: cmp(a, b) +keys.sort(cmpf) + +# optionally reverse the sort if the user wanted +if opts.reverse: keys.reverse() + +# determine max key length, max count, and total count; also, the printed length +# of the max count. +kmax, cmax, total = 0, 0, 0 +for key in keys: + cmax, kmax, total = max(seen[key], cmax), max(len(key), kmax), total + seen[key] +smax = len(str(cmax)) + +# if we need to draw, we should make some guesses about the screen size. we +# should probably never try to draw more than 40 characters worth of stars. +width = os.environ.get("COLUMNS", 80) +if opts.hwidth is None: + opts.hwidth = min(abs(width - kmax), 40) + +for key in keys: + # figure out how to draw the key + if opts.nopad: + vkey = key + else: + vkey = '%-*s' % (kmax, key) + + # figure out how to draw the value + if opts.draw: + ratio = float(seen[key]) / cmax + nstar = int(round(opts.hwidth * ratio)) + value = '%*s' % (opts.hwidth, '*' * nstar) + elif opts.percent: + perc = float(seen[key]) * 100 / total + value = '%5.1f%%' % perc + else: + value = '%*d' % (smax, seen[key]) + + # figure out which order to write them in + if opts.swap: + print "%s%s%s" % (vkey, opts.delim, value) + else: + print "%s%s%s" % (value, opts.delim, key) diff --git a/patchinfo b/patchinfo new file mode 100755 index 0000000..c06c15f --- /dev/null +++ b/patchinfo @@ -0,0 +1,83 @@ +#!/usr/bin/python +# +# by Erik Osheim +# +# available under the GNU GPL version 2. +# +# This program is designed to provide analysis of patches or diff files. + +import optparse +import re +import sys + +# matches the diff stanza, which have no leading identifier +diff_re = re.compile('^[0-9a-zA-Z,]+$') + +# analyze a particular patch, which is assumed to contain multiple files +def info(f, verbose=False): + paths = [] + l = 0 + first = True + for line in f: + if first: + if diff_re.match(line): + paths.append(['-', 0, 0, 0, 0]) + first = False + + if diff_re.match(line): + if not paths: + paths.append(['-', 0, 0, 0, 0]) + paths[-1][1] += 1 + elif line.startswith('diff'): + path = line.split()[-1] + l = max(l, len(path)) + paths.append([path, 0, 0, 0, 0]) + elif line.startswith('Index'): + path = line.split()[1] + l = max(l, len(path)) + paths.append([path, 0, 0, 0, 0]) + elif line.startswith('---') or line.startswith('+++') or line.startswith('='): + pass + elif line.startswith('@@'): + paths[-1][1] += 1 + elif line.startswith('+') or line.startswith('>'): + paths[-1][2] += 1 + paths[-1][3] += 1 + elif line.startswith('-') or line.startswith('<'): + paths[-1][2] -= 1 + paths[-1][4] += 1 + + if len(paths) != 1: + title = '%d paths' % len(paths) + else: + title = '1 path' + + if verbose: + title = 'TOTAL ' + title + else: + l = len(title) + + totals = [0, 0, 0, 0] + for info in paths: + for i in range(0, 4): + totals[i] += info[i + 1] + + lens = [len(str(n)) + 1 for n in totals[:2]] + fmt = '%%-%ds %%%dd groups, %%+%dd lines (+%%d -%%d)' % tuple([l] + lens) + for info in paths: + if verbose: + print fmt % tuple(info) + + print fmt % tuple([title] + totals) + +if __name__ == "__main__": + op = optparse.OptionParser() + op.add_option('-v', '--verbose', dest='verbose', action='store_true') + + opts, args = op.parse_args() + + if args: + for arg in args: + info(open(arg, 'r'), verbose=opts.verbose) + else: + info(sys.stdin, verbose=opts.verbose) diff --git a/sgrep b/sgrep new file mode 100755 index 0000000..a5e8be2 --- /dev/null +++ b/sgrep @@ -0,0 +1,11 @@ +#!/bin/sh +grep --binary-files=without-match \ + --exclude-dir=CVS \ + --exclude-dir=.svn \ + --exclude-dir=.hg \ + --exclude-dir=.git \ + --exclude '*~' \ + --exclude '.#*' \ + --exclude '#*' \ + --exclude '*-' \ + "$@" diff --git a/unbox b/unbox new file mode 100755 index 0000000..47c4286 --- /dev/null +++ b/unbox @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# +# by Erik Osheim +# +# This program unboxes various archive + +import os +import shutil +from subprocess import call +import sys +import tempfile + +# list each kind of archive in terms of extension, and then program and +# arguments to use. Use None to indicate where the filename should be placed. +handlers = { + '.zip': ['unzip', None], + '.tgz': ['tar', 'xvzf', None], + '.tbz': ['tar', 'xvjf', None], + '.tar.gz': ['tar', 'xvzf', None], + '.tar.bz2': ['tar', 'xvjf', None], + #'.tar.xz': ['tar', 'xvJz', None], +} + +# program usage +def usage(err=None): + retval = 0 + if err: + retval = 1 + print 'error: %s' % err + print 'usage: unbox ARCHIVE' + sys.exit(retval) + +if __name__ == "__main__": + args = sys.argv[1:] + if not args: + usage() + elif len(args) > 1: + usage('too many arguments') + path = args[0] + if not os.path.exists(path): + usage('path %r does not exist' % path) + + cmd = None + for ext in handlers: + if path.endswith(ext): + cmd = handlers[ext] + base = path[:-len(ext)] + if not cmd: + usage("can't handle path %r" % path) + + d = tempfile.mkdtemp(prefix='unbox-') + + fd, path2 = tempfile.mkstemp(dir=d) + os.write(fd, open(path, 'rb').read()) + os.close(fd) + + cwd = os.getcwd() + print d + os.chdir(d) + + base2 = os.path.basename(path2) + + # put the path into the command + cmd = [x or base2 for x in cmd] + + retcode = call(cmd) + if retcode != 0: + print 'error: %s failed (%d)' % (cmd[0], retcode) + sys.exit(1) + + os.unlink(path2) + + items = os.listdir(d) + if len(items) == 1: + shutil.move(d + '/' + items[0], cwd) + shutil.rmtree(d) + else: + shutil.move(d, cwd + '/' + base)