indent2tree

パブリックドメイン版 cflow には GNU cflow

-T, --tree                 * Draw ASCII art tree

というオプションがないので、インデントで表された呼び出し構造(オフサイドルール?)をツリー形式に変換するコマンドを書いてみた。

#!/usr/bin/python

import sys

def getlevel(s):
    return len(s) - len(s.lstrip())

def parselist(lines):
    if len(lines) == 0:
        return [[], 0]

    tree = []
    i = 0
    currentlevel = getlevel(lines[0]) 

    while i < len(lines):
        level = getlevel(lines[i])

        if level > currentlevel: # Indent increases. Beginning of a new block
            subtree, readcount = parselist(lines[i:])
            tree.append(subtree)
            i += readcount
        elif level < currentlevel: # decrease. End of the block
            return [tree, i]
        else: # Same indent
            tree.append(lines[i].rstrip())
            i += 1
    return [tree, i+1] 

def printtree(tree, level, prevhead):
    for i in range(len(tree)):
        node = tree[i]
        if type(node) == type(""):
            if i == len(tree) - 1:
                print prevhead + "\-" + node.lstrip()
            else:
                print prevhead + "+-" + node.lstrip()
        else:
            if i == len(tree) - 1:
                printtree(node, level+1, prevhead + "  ")
            else:
                printtree(node, level+1, prevhead + "| ")

if __name__ == '__main__':
    tree, readcount = parselist(sys.stdin.readlines())

    #print tree
    #print readcount

    #printtree(["a", ["b", ["c"]], ["d", ["e"]], "f"], 0, "")
    printtree(tree, 0, "")

例:

$ cat i
a
 b
 c
  d
   x
    y
   z
    t
     v
   w
  e
 f
 g
h
$ indent2tree < i
+-a
| +-b
| +-c
| | +-d
| | | +-x
| | | | \-y
| | | +-z
| | | | +-t
| | | |   \-v
| | | \-w
| | \-e
| +-f
| \-g
\-h

cflow の出力をツリー形式に変換する。

$ cflow prcc.c|sed -e 's@^[0-9]\+\t@@'|indent2tree