<?xml version="1.0" encoding="windows-1252"?>
<node id="859515" title="tabs to html list" created="2010-09-09 10:07:27" updated="2010-09-09 10:07:27">
<type id="1042">
CUFP</type>
<author id="961">
Anonymous Monk</author>
<data>
<field name="doctext">
converts 4-space (or tab) indented text into a html list of lists 
&lt;readmore&gt;
&lt;c&gt;#!/usr/bin/perl --

use strict;
use warnings;

use Data::Dumper;
use HTML::TreeBuilder;

Main(@ARGV);
exit(0);

sub Main {
    my $list = Blahblah( \*DATA );
    {
        my $tree = HTML::TreeBuilder-&gt;new();
        $tree-&gt;eof;

#~         $tree-&gt;look_down(qw!_tag body!)-&gt;push_content( @$list );
        $tree-&gt;look_down(qw!_tag body!)-&gt;push_content($list);
        print $tree-&gt;as_HTML( '&gt;&lt;&amp;' =&gt; "\t" ), "\n";    # tab indent
        $tree-&gt;delete;
        undef $tree;
    }

#~    warn Dumper($list), "\n";
} ## end sub Main

sub Blahblah {
    my $fh       = shift;
    my $root_ref = ['ul'];

#~     my $root_ref = [ ];
    my $curr_ref = $root_ref;
    my @prev_ref;
    my $curr = 0;
    my $last = 0;

    while ( readline $fh ) {
        next if !/\w/;    # skip blank lines
        chomp;
        $last = $curr;
        $curr =
          /^((?:    |\t)+)/
          ? length($1) / 4
          : 0;

        if ( $curr &gt; $last ) {
            my $new = ['ul'];
            push @{
                ref $curr_ref-&gt;[-1]
                ? $curr_ref-&gt;[-1]
                : $curr_ref
              },
              $new;
            push @prev_ref, $curr_ref;
            $curr_ref = $new;
        } elsif ( $curr &lt; $last ) {
            while ( $last != $curr ) {
                $last--;
                $curr_ref = pop @prev_ref;
            }
        } ## end elsif ( $curr &lt; $last )

        s/^\s+//;
        push @$curr_ref, [ 'li', $_ ];
    } ## end while ( readline $fh )
    return $root_ref;
} ## end sub Blahblah

__DATA__
a
    1
    2
    3
b
    1
    2
        a
        b
            1
            2
                a
                b
                c
            3
        c
    3
c
d


    7
        7a
        7b
            7b1
            7b2
                7b2a
                7b2b
                7b2c
            7b3
        7c
    8

&lt;/c&gt;
output         &lt;ul&gt;
            &lt;li&gt;a&lt;ul&gt;
                    &lt;li&gt;1&lt;li&gt;2&lt;li&gt;3&lt;/ul&gt;
            &lt;li&gt;b&lt;ul&gt;
                    &lt;li&gt;1&lt;li&gt;2&lt;ul&gt;
                            &lt;li&gt;a&lt;li&gt;b&lt;ul&gt;
                                    &lt;li&gt;1&lt;li&gt;2&lt;ul&gt;
                                            &lt;li&gt;a&lt;li&gt;b&lt;li&gt;c&lt;/ul&gt;
                                    &lt;li&gt;3&lt;/ul&gt;
                            &lt;li&gt;c&lt;/ul&gt;
                    &lt;li&gt;3&lt;/ul&gt;
            &lt;li&gt;c&lt;li&gt;d&lt;ul&gt;
                    &lt;li&gt;7&lt;ul&gt;
                            &lt;li&gt;7a&lt;li&gt;7b&lt;ul&gt;
                                    &lt;li&gt;7b1&lt;li&gt;7b2&lt;ul&gt;
                                            &lt;li&gt;7b2a&lt;li&gt;7b2b&lt;li&gt;7b2c&lt;/ul&gt;
                                    &lt;li&gt;7b3&lt;/ul&gt;
                            &lt;li&gt;7c&lt;/ul&gt;
                    &lt;li&gt;8&lt;/ul&gt;
        &lt;/ul&gt;&lt;/readmore&gt;
not the first time i wrote something like this, hopefully I won't reinvent again</field>
<field name="reputation">
29</field>
</data>
</node>
