indent2tree - メモ帳
僕もRubyで実装してみました。いきなり2つインデントした場合とかのエラーチェックは実装していません。手抜きです。
class Node def initialize(data = nil) @data = data @children = [] end def <<(node) @children << node end def dump(prefix = '', nexts = ['', '']) print "#{prefix + nexts[0]}#{@data}\n" if @data @children.each_with_index do |child, i| child.dump( prefix + nexts[1], (i == @children.size - 1) ? ['`-', ' '] : ['+-', '| ']) end end end def parse(lines) table = [Node.new] lines.inject(0) do |level, line| line =~ /^( *)/ new_level, new_node = $1.size + 1, Node.new($'.strip) table[(level < new_level) ? level : new_level - 1] << new_node table[new_level] = new_node new_level end table[0] end parse(ARGF.readlines).dump
以下、実行例です。
$ cat a.txt a b c d x y z t v w e f g h $ ruby indent2tree.rb < a.txt +-a | +-b | +-c | | +-d | | | +-x | | | | `-y | | | +-z | | | | `-t | | | | `-v | | | `-w | | `-e | +-f | `-g `-h
(追記)
ロジックを見直したら、微妙に簡単になりました。なんちゃてエラー処理も追加しました。
class Node def initialize(data = nil) @data = data @children = [] end def <<(node) @children << node end def dump(prefix = '', nexts = ['', '']) print "#{prefix + nexts[0]}#{@data}\n" if @data @children.each do |child| child.dump( prefix + nexts[1], (child == @children.last) ? ['`-', ' '] : ['+-', '| ']) end end end def parse(lines) table = [Node.new] lines.inject(0) do |level, line| line =~ /^( *)/ new_level, new_node = $1.size + 1, Node.new($'.strip) raise 'invalid indent.' if new_level - level > 1 table[new_level - 1] << new_node table[new_level] = new_node new_level end table[0] end if $0 == __FILE__ parse(ARGF.readlines).dump end