#!/usr/bin/python

# Improved version by
# Stephen Thorne <stephen@thorne.id.au>

import sys, os, optparse, itertools

class InFile:
    def __init__(self, filename):
        self.maxlen = 0
        self.lines = [l.rstrip() for l in file(filename)]

        self.nlines = len(self.lines)
        if self.nlines == 0:
            self.lines.append("")
        self.maxlen = max(map(len, self.lines))

    def make_line(self, line, nlines, width, trunc):
        truncated = ' '
        if len(line) > width and trunc:
            truncated = '*'
        return "%s%s%s" % (line[:width], ' '*(width-len(line)), truncated)

    # pad to the max len, with a extra space then the deliminator
    def padded_lines(self, nlines, width=0, trunc=False):
        if not width:
            width = self.maxlen
        # add on some extra for the divider and spaces
        for line in self.lines:
            yield self.make_line(line, nlines, width, trunc)
        for line in ['']*(nlines-self.nlines):
            yield self.make_line(line, nlines, width, trunc)

usage = "side-by-side [-w width] file1 file2 ... filen"

parser = optparse.OptionParser(usage, version=".1")

parser.add_option("-w", "--width", dest="width", action="store", type="int",
                      help="Set fixed width for each file", default=0)
parser.add_option("--no-div", dest="nodiv", action="store_true",
                  help="Don't print any divider characters", default=False)
parser.add_option("--no-trunc", dest="trunc", action="store_false",
                  help="Don't show truncation with a '*'", default=True)

(options, args) = parser.parse_args()

if not args:
    parser.error('No Files Supplied')

try:
    flist = [InFile(f) for f in args]
except IOError, (error, message):
    print "Can't read input %s : %s" % (filename, message)
    sys.exit(1)

max_lines = max([f.nlines for f in flist])

if options.nodiv:
    divider = ' '
else:
    divider = '|'

all_lines = [f.padded_lines(max_lines, options.width, options.trunc) for f in flist]
    
sys.stdout.writelines([divider.join(x) + '\n' for x in itertools.izip(*all_lines)])
