Tuesday, September 23, 2008

This is how I relax.... lol.

Having taken some time to analyze the mailcap and mime.types files, which map media types to handler programs and file extensions respectively. I've decided to implement something, uhh.... more "fun" out of it, for my own usage. I'll use mailcap and mime.types to setup a suitable mime/file associations to desire, and a mixture of m4 and environment varables to make it more useful hehe. I've also setup a small wrapper around Pythons mailcap and mimetypes modules, so I'm happy !


Since I need a handler that includes a web browser, rather then creating an if x is probably running ... script, to just use $BROWSER. But since, there is a shitload of apps that don't understand it, I've created quick python script to handle it. Thus, mailcap will execute this script, which will "figure it out". Once I realized how much I could use such a quickie, I added a little more abstraction to it; making it usable with other variables. And used getopt for a simple interface to it.

#!/usr/bin/env python

import sys, os, getopt

# default values for -e and -s options
envvar = "BROWSER"
envsep = ":"
# skip executing program 
noexec = False

# accepted options, usage statement, and manual page
shortopts = "hme:s:n"
longopts = [ 'help', 'man', 'environment=', 'separator=', 'no-exec' ]
def usage():
    print """
usage: %s [options] file ...

    Parse a field delimited list of programs, executing each in turn, until the
    specified application has opened the indicated file(s).

Options:

    -h,--help    display this useless message
    -e,--environment the environment variable to look up, default to BROWSER
    -s,--separator    the field separator for -e VAR, defaults to :
    -m,--man    view this manual page
    -n,--no-exec    do not execute any programs, useful if parsing $PATH

    --long-options may be abbreviated.

Exit Status: 

    The return status of the last executed program handler. If no program was
    executed, return with a non-zero exit status.

Caveats:

    A non-zero exit status is considered a successful execution.

    Programs found by parsing the environment variable, are passed onto the
    system shell UNMODIFIED. This is not secure, but it is flexible.
""" % sys.argv[0]
    sys.exit(1);


try:
    opts, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
except getopt.GetoptError, e:
    print(str(e))
    usage()

for opt, arg in opts:
    if opt in ('-h', '--help'):
        usage()
    elif opt in ('-m', '--man'):
        # XXX works on unix, dos, winnt, osx
        os.system("%s -h | $PAGER || more" % sys.argv[0])
        sys.exit(0)
    elif opt in ('-e', '--environment'):
        envvar = arg
    elif opt in ('-s', '--separator'):
        envsep = arg
    elif opt in ('-n', '--no-exec'):
        noexec=True
    else:
        assert False,"unhandled option: %s" % opt

# exec handlers until success, abort, or exit
try:
    browser = os.environ[envvar]
    apps = browser.split(envsep)
    for handler in apps:
        # just print it, don't execute it
        if noexec:
            print handler
            continue

        ret = os.system(handler)
        if not ret == 0:
            print("Bad handler -- %s" % (str(handler) % " ".join(args)))

except KeyError:
    print("No %s set!!!" % envvar)
    sys.exit(1)
except Exception, e:
    print("Un-handled exception! -- %s" % e.message)



One of the common questions of a language, is how to parse command line options? I've tried several interfaces in differing languages, but I know one thing... The getopt(3) routine in C on unix is awesome for short options. Give something more portable and with (easy) support for long options, and I'll have a big grin on my face >_>. But if I have to wade through 20 pages of documentation for a comparable OOP-Interface, I'll be snoring before I get to writing usage().

No comments:

Post a Comment