#!/usr/bin/env python
# vim:set ft=python fileencoding=utf-8 sr et ts=4 sw=4 : See help 'modeline'

"""
SYNOPSIS

    filter-ansi [-h] [-v,--verbose] [--version]

DESCRIPTION

    This removes unprintable characters and ANSI escape codes from input.
    This is useful for removing escape codes from typescript files
    (generated by the `script` command).

    You can use this as a pipeline filter or you can pass a filename to be filtered.

    This docstring will be printed by the script if there is an error or
    if the user requests help (-h or --help).

EXAMPLES

    The following are some examples of how to use this script.
    The following are equivalent.

    $ cat typescript | filter_ansi

    $ filter_ansi typescript

EXIT STATUS

    This exits with status 0 on success and 1 otherwise.
    This exist with a status greater than 1 if there was an
    unexpected run-time error.

AUTHOR

    Noah Spurrier <noah@noah.org>

LICENSE

    This license is approved by the OSI and FSF as GPL-compatible.
        http://opensource.org/licenses/isc-license.txt

    Copyright (c) 2011, Noah Spurrier
    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

VERSION

    Version 1
"""

__version__ = 'Version 1'
__author__ = 'Noah Spurrier <noah@noah.org>'

import sys
import os
import traceback
import optparse
import time
import string

def filter_ANSI (line_input):

    """This removes ANSI escape sequence from the line_input.
    It returns a new line. """

    line, i, imax = '', 0, len(line_input)
    handling_ansi_sequence = False
    for character in line_input:
        if handling_ansi_sequence:
            if character.lower() in 'abcdhsujkm':
                handling_ansi_sequence = False
        else:
            if character in string.printable and ord(character) != 13:
                line = line + character
            elif ord(character) == 27:
                handling_ansi_sequence = True
            elif ord(character) == 8:
                line = line[:-1]
    return line

def main (options=None, args=None):

    # Handle stdin or a file.
    if args is None or len(args)==0:
        fin = sys.stdin
    else:
        fin = file(args[0], 'r')

    for line in fin.readlines():
        sys.stdout.write (filter_ANSI (line))
        sys.stdout.flush()

if __name__ == '__main__':
    try:
        start_time = time.time()
        # TODO: set version here.
        parser = optparse.OptionParser(
                formatter=optparse.TitledHelpFormatter(),
                usage=globals()['__doc__'],
                version='TODO')
        parser.add_option ('-v', '--verbose', action='store_true',
                default=False, help='verbose output')
        (options, args) = parser.parse_args()
        #if len(args) < 1:
        #    parser.error ('missing argument')
        if options.verbose: print (time.asctime())
        exit_code = main(options, args)
        if exit_code is None:
            exit_code = 0
        if options.verbose:
            print (time.asctime())
            print ('TOTAL TIME IN MINUTES: %f'%((time.time()-start_time)/60.0))
        sys.exit(exit_code)
    except KeyboardInterrupt, e: # The user pressed Ctrl-C.
        raise e
    except SystemExit, e: # The script called sys.exit() somewhere.
        raise e
    except Exception, e:
        print ('ERROR: Unexpected Exception')
        print (str(e))
        traceback.print_exc()
        os._exit(2)
