Tuesday 10 February 2009

流程图生成器

一直想写一个来着,趁着这次在python.ubuntu.org.cn写[常用库系列]的机会写了这个。目前还不太完善,不过会慢慢改进。接下来要做的就是用pyparsing来完善和扩展我的流程图定义文件。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import yapgvb
import optparse

FORMATS = {"png" : yapgvb.formats.png,
        "jpg" : yapgvb.formats.jpg,
        "gif" : yapgvb.formats.gif}
ENGINES = {"dot" : yapgvb.engines.dot,
        "neato" : yapgvb.engines.neato,
        "circo" : yapgvb.engines.circo,
        "twopi" : yapgvb.engines.twopi}

if __name__ == '__main__':
#    args = sys.argv
#    if len(args) < 2:
#        print "Usage: python state_machine.py <def file>"
#        sys.exit(0)

    parser = optparse.OptionParser()
    parser.add_option("-f", "--format", dest="format",
            help="store the flow chart in FORMAT",
            metavar="FORMAT", default="png")
    parser.add_option("-o", "--output", dest="output",
            help="save the flow chart to FILE",
            metavar="FILE")
    parser.add_option("-e", "--engine", dest="engine",
            help="the layout ENGINE to use for the flow chart",
            metavar="ENGINE", default="dot")

    options, args = parser.parse_args()
    if len(args) < 1:
        parser.print_usage()
        sys.exit(0)

    graph = yapgvb.Graph("States")
    node_dict = {}

    with open(args[0]) as def_file:
        lines = [l.strip() for l in def_file.readlines()]
        for line in lines:
            nodes = line.split("=>")
            prev_node = None
            for node in nodes[::-1]:
                label = node.strip().split("#")
                if not node_dict.has_key(label[0]):
                    node_in_graph = graph.add_node(label=label[1],
                            shape='ellipse', fillcolor='yellow',
                            style='filled', width=0.5)
                    node_dict[label[0]] = node_in_graph
                else:
                    node_in_graph = node_dict[label[0]]

                if prev_node:
                    edge = node_in_graph - prev_node
                    edge.arrowhead = 'normal'

                prev_node = node_in_graph

    graph.layout(ENGINES[options.engine])
    format = FORMATS[options.format]
    if options.output:
        out_file = options.output
    else:
        out_file = args[0] + "." + format

    graph.render(out_file, format)

No comments: