Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re: Directory Tree Structure

by graff (Chancellor)
on Oct 21, 2005 at 12:51 UTC ( [id://501973]=note: print w/replies, xml ) Need Help??


in reply to Directory Tree Structure

Given that you already have the listing of directories (presumably as created by a command line like  find examples -type d), I think it's pointless to talk about using File::Find (which is certainly not an improvement over the unix "find" utility).

As I understand it, the question is how to parse that listing into an appropriate html structure to render it as a nested set of unordered lists. This should be fairly simple, given that the input list is already sorted as shown in your example:

use strict; # let's assume you read the list from stdin: my @paths = <>; chomp @paths; s/:$// for @paths; # don't want the punctuation my $prev_path = shift @paths; my $prev_depth = ( $prev_path =~ tr{/}{/} ); # count /'s my $indent = 1; print "<UL>\n <LI> $prev_path: </LI>\n"; for ( @paths ) { my $depth_now = ( tr{/}{/} ); if ( index( $_, "$prev_path/" ) == 0 ) { # $prev_path is contained within this one, so indent print ' ' x $indent, "<UL>\n"; $indent++; } elsif ( $depth_now < $prev_depth ) { # need to back off the indentation while ( $depth_now < $prev_depth ) { $indent--; print ' ' x $indent, "</UL>\n"; $prev_depth--; } } print ' ' x $indent, "<LI> $_: </LI>\n"; # put ":" back in $prev_path = $_; $prev_depth = $depth_now; } while ( $indent ) { $indent--; print ' ' x $indent, "</UL>\n"; } __OUTPUT__ <UL> <LI> examples/html: </LI> <UL> <LI> examples/html/bars: </LI> <LI> examples/html/headers: </LI> <LI> examples/html/links: </LI> <LI> examples/html/lists: </LI> <LI> examples/html/menus: </LI> <LI> examples/html/rgb: </LI> <LI> examples/html/tables: </LI> </UL> <LI> examples/ps: </LI> <UL> <LI> examples/ps/marks: </LI> </UL> <LI> examples/splash: </LI> <UL> <LI> examples/splash/dropbox: </LI> <LI> examples/splash/frame: </LI> <LI> examples/splash/hair: </LI> <LI> examples/splash/icon: </LI> <LI> examples/splash/menu: </LI> <LI> examples/splash/menubar: </LI> </UL> </UL>
(updated to fix one of the comments in the code; also, looking more closely at the OP, I realize that I left out some of the desired formatting in the LI elements: having an href attribute containing the full path, and using just the last component of the path as the displayed text. I'll leave that as an exercise... it should be easy enough to work out.)

Replies are listed 'Best First'.
Re^2: Directory Tree Structure
by rupesh (Hermit) on Oct 21, 2005 at 13:13 UTC

    graff, Thanks.

    It's just what I wanted.

    Sad, though, that you can do a "++" only once. ;).

    Cheers,
    Rupesh.
Re^2: Directory Tree Structure
by Lady_Aleena (Priest) on Oct 03, 2009 at 21:46 UTC
    graff,

    I know that this is almost 4 years later, but I see a problem with the output of the code. It would cause several HTML validation errors.

    If you please look at your output at <LI> examples/html: </LI>. The </li> needs to be down after </ul> after <LI> examples/html/tables: </LI> since the indented unordered list is within the above list item.

    I have tried fixing it and will keep trying in the meantime, but so far I have had only a little success.

    <ul> <li>Foo level 1 <ul> <li>Foo level 2 <ul> <li>Bar</li> <li>Baz</li> </ul> </li> #This closes Foo level 2 <li>Qux</li> <li>Quux</li> </ul> </li> #This closes Foo level 1 <li>Widget</li> </ul>
    Have a nice day!
    Lady Aleena
      Lady Aleena,

      Nice to hear from you again. What particular method are you using for html validation? (That is, who says that <ul>...</ul> positioned between </li>...<li> is invalid?) UPDATE: almut's reply clears this up -- I'm wrong, and the markup I posted above is Not Good™.

      I'm somewhat skeptical that the output I posted above constitutes an error in html syntax. Despite knowing that this markup is invalid, it may be worth pointing out that I stuck it into a file surrounded by <html>...</html> and loaded it into Safari and Firefox, and they both render it as I would expect (i.e. as intended). So in that sense at least, it works.

      Having said that, I'll acknowledge that the following layout for the markup also works, and I can well imagine that one or another validator might it has been shown that html validators should insist on this version (even though I don't see it as a necessary condition it seems to work either way):

      <UL> <LI> examples/html: <UL> <LI> examples/html/bars: </LI> <LI> examples/html/headers: </LI> <LI> examples/html/links: </LI> <LI> examples/html/lists: </LI> <LI> examples/html/menus: </LI> <LI> examples/html/rgb: </LI> <LI> examples/html/tables: </LI> </UL> </LI> <LI> examples/ps: <UL> <LI> examples/ps/marks: </LI> </UL> </LI> <LI> examples/splash: <UL> <LI> examples/splash/dropbox: </LI> <LI> examples/splash/frame: </LI> <LI> examples/splash/hair: </LI> <LI> examples/splash/icon: </LI> <LI> examples/splash/menu: </LI> <LI> examples/splash/menubar: </LI> </UL> </LI> </UL>
      If you are having trouble getting the code to output this pattern, show the code you have so far, and we'll see what's up with that.
        who says that <ul>...</ul> positioned between </li>...<li> is invalid?

        W3C Markup Validation Service  :)

        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <title></title> </head> <body> <UL> <LI> examples/html: </LI> <UL> <LI> examples/html/bars: </LI> </UL> <LI> examples/ps: </LI> </UL> </body> </html> --- Validation Output: 1 Error Line 11, Column 6: document type does not allow element "UL" here; ass +uming missing "LI" start-tag
        graff,

        Here is what I have so far. Unfortunately, I haven't worked out a few things like having it only read the files in the directories and excluding the subdirectories in directory_contents. I am getting duplicates.

        I have been shown a few other things, but haven't quite gotten the kinks worked out of those either.

        #!/usr/bin/perl use strict; use warnings; use diagnostics; use File::Find; use File::Spec; my $rootdir = "C:/Documents and Settings/<my name>/My Documents/fantas +y"; my @files; sub wanted { my $text = $File::Find::name; push @files, $text; return; } sub directory_contents { my ($contents) = @_; my $file_tab = $contents; $file_tab =~ s{$rootdir}{}; my $tab = "\t" x ($file_tab =~ tr{/}{}); my @list = (map("$tab<li>".$_."</li>\n",grep{m/^($contents)\//} @fil +es)); #the grep is where I think I need to put the stop on going lowe +r. return join("",@list); } sub print_directory { my ($file) = @_; my $file_tab = $file; $file_tab =~ s{$rootdir}{}; my $tab = "\t" x ($file_tab =~ tr{/}{}); my $directory = qq{$tab<li>$file\n$tab<ul>\n}.directory_contents($fi +le).qq{$tab</ul>\n$tab</li>\n}; print $directory; } find(\&wanted, $rootdir); foreach my $entry (File::Spec->no_upwards(@files)) { print_directory($entry) if -d $entry; }
        Have a nice day!
        Lady Aleena

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://501973]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-19 16:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found