Ideal data structure for nested list format?

Discussion in 'Perl Misc' started by Tuxedo, Sep 4, 2010.

  1. Tuxedo

    Tuxedo Guest

    In trying to construct a nested html list with perl I have some questions
    what the ideal data structure may be for the specific purpose.

    The menu is generated on the fly for each page request. The script lives in
    a perl file named menu.pl and the current page that is accessed is known to
    the script via a server environment variable accessible in a $current_page
    perl variable. The html parts are imported onto individual html pages
    through SSI (includes) and all pages are placed at a root level, so there
    are no sub-directories or chances of any pages having a same name.

    This is a simplified html output of the menu in an unordered list format:

    <ul>
    <li><a href=1.1.html>Level 1.1</a>
    <ul>
    <li><a href=2.1.html>Level 2.1</a></li>
    <li><a href=2.2.html>Level 2.2</a>
    <ul>
    <li><a href=3.1.html>Level 3.1</a></li>
    <li><a href=3.2.html>Level 3.2</a></li>
    </ul>
    </li>
    <li><a href=2.3.html>Level 2.3</a></li>
    </ul>
    </li>
    </ul>

    So there are three levels and the first two levels have nested lists
    within. If for example page 3.2.html is accessed, the script should write
    out that <li> entry *without* the enclosing <a href=3.2.html>..</a> parts,
    as well as add a css-class to that one list item: <li class=current_page>.

    The script should know its nearest parent <li> item, so in case of
    accessing page 3.2.html, that would be the <li> with the 2.2.html link.
    This entry should then have have the css-class: <li class=parent_level_2>.

    Additionally, the second nearest parent should be given another css-class,
    such as <li class=parent_level_1> (so it may be styled differently).

    If the current page is one that does not exist in the menu, although the
    menu has been imported on such a page, then no special classes or non-link
    formatting is needed for any of the array entries. The html output would
    just appear exactly as the above example.

    Without the actual link names, I guess the list may be constructed with a
    LoL or an AoA, such as:

    my @AoA = ('1.1.html',
    ['2.1.html',
    '2.2.html',
    ['3.1.html',
    '3.2.html'],
    '2.3.html']);

    If so, a parallel AoA's would be needed for the link names to be combined
    in a final loop. Or is some other data structure better suited for the
    purpose? I.e.: sticking all items together in a nested html list in order
    of entry in the perl code, as well as figure out the opening parent <li>
    points (if any) in order to apply custom css-classes to relevant <li>'s.

    Looking at perldsc, in addition to AoA, alternatives such as HoA, AoH, HoH
    as well as some more elaborate data structures exist. I'm not sure what's
    best? The maintenance of the link list will involve changing or updating
    entries only very occasionally, so it can be done in separate arrays in
    case that's better. Anyway, it's not important how, as long as it works...

    What is the ideal data structure for the particular hierarchial list
    functionality and where the described level specific output can easily be
    incorporated?

    Many thanks for any advise or general pointers.

    Tuxedo
    Tuxedo, Sep 4, 2010
    #1
    1. Advertising

  2. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    Many thanks for the detailed concept in how to build the particular menu
    and list format. I understand it's not entirely ready-to-run code, and so
    I'd like to know how your example can generate the final html code. Perhaps
    you or someone here can help fill in the missing parts?:

    #!/usr/bin/perl -w

    use warnings;
    use strict;

    my @pages = (
    { page => "1.1.html", title => "Level 1.1", children => [
    { page => "2.1.html", title => "Level 2.1" },
    { page => "2.2.html", title => "Level 2.2", children => [
    { page => "3.1.html", title => "Level 3.1" },
    { page => "3.2.html", title => "Level 3.2" },
    ] },
    { page => "2.3.html", title => "Level 2.3" },
    ] },
    );

    # and then build a hash of 'parents', like so

    sub populate_parents;
    sub populate_parents {
    my ($parents, $pages, $parent) = @_;

    for (@$pages) {
    my $page = $_->{page};
    push @{$parents->{$page}}, $parent;
    my $kids = $_->{children};
    $kids and populate_parents $parents, @$kids, $page;
    }
    }

    my %parents;
    populate_parents \%parents, \@pages, undef;

    # This will give you a data structure like

    %parents = (
    "1.1.html" => [undef],
    "2.1.html" => [undef, "1.1.html"],
    "3.1.html" => [undef, "1.1.html", "2.2.html"],
    # ...
    );

    # Then, given a page name, you can build another hash

    my $page = "3.1.html";
    my $parents = $parents{$page};
    my %class =
    map +($parents->[$_] => "parent_level_$_"),
    grep defined $parents->[$_],
    0..$#$parents;

    The above code 'as is' returns the error "Not an ARRAY reference at
    ../menu.pl line 23", which is on the line beginning with "for (@$pages) ".

    If only the arrays and hashes could be generated without error, I can then
    try to access and print the entries through some kind of loop construct.
    Any additional ideas and code bits would be greatly appreciated!

    Thanks again,
    Tuxedo
    Tuxedo, Sep 4, 2010
    #2
    1. Advertising

  3. Tuxedo

    Uri Guttman Guest

    >>>>> "T" == Tuxedo <> writes:

    T> Ben Morrow wrote:
    T> [...]

    T> Many thanks for the detailed concept in how to build the particular menu
    T> and list format. I understand it's not entirely ready-to-run code, and so
    T> I'd like to know how your example can generate the final html code. Perhaps
    T> you or someone here can help fill in the missing parts?:

    T> #!/usr/bin/perl -w

    T> use warnings;
    T> use strict;

    T> my @pages = (
    T> { page => "1.1.html", title => "Level 1.1", children => [
    T> { page => "2.1.html", title => "Level 2.1" },
    T> { page => "2.2.html", title => "Level 2.2", children => [
    T> { page => "3.1.html", title => "Level 3.1" },
    T> { page => "3.2.html", title => "Level 3.2" },
    T> ] },
    T> { page => "2.3.html", title => "Level 2.3" },
    T> ] },
    T> );

    gack!! use a templater. many to choose from. check out mine called
    Template::Simple. you pass it a data structure and template and you get
    rendered text. nothing more to it. you can nest structures, templates
    and template chunks all you want. lists are automatic too with no extra
    markup (a list of elements renders a list of template chunks). all you
    need to do is create your html templates (again, they can be included
    and nested) and render with one call.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Sep 4, 2010
    #3
  4. Tuxedo

    Tuxedo Guest

    Uri Guttman wrote:

    [...]

    > gack!! use a templater. many to choose from. check out mine called
    > Template::Simple. you pass it a data structure and template and you get
    > rendered text. nothing more to it. you can nest structures, templates
    > and template chunks all you want. lists are automatic too with no extra
    > markup (a list of elements renders a list of template chunks). all you
    > need to do is create your html templates (again, they can be included
    > and nested) and render with one call.
    >
    > uri
    >


    Thanks for the tip, I've not tried Template::Simple before so I'm not sure
    how it works yet. I need to install and test it as well as delve into the
    manual, which looks a little less than simple at first sight...

    Can anyone advise me how to generate the following type of nested list by
    Template::Simple?

    <ul>
    <li><a href=1.1.html>Level 1.1</a>
    <ul>
    <li><a href=2.1.html>Level 2.1</a></li>
    <li><a href=2.2.html>Level 2.2</a>
    <ul>
    <li><a href=3.1.html>Level 3.1</a></li>
    <li><a href=3.2.html>Level 3.2</a></li>
    </ul>
    </li>
    <li><a href=2.3.html>Level 2.3</a></li>
    </ul>
    </li>
    </ul>

    And is it actually possible to apply the advanced formatting relating to
    the $current_page URL along with any parent <li class=bits> if and where
    parent entry <li>'s are present? (as detailed in my first post in this
    thread). Can all of this be done with the help of Template::Simple?

    Many thanks,
    Tuxedo
    Tuxedo, Sep 5, 2010
    #4
  5. Tuxedo

    Uri Guttman Guest

    >>>>> "T" == Tuxedo <> writes:

    T> Thanks for the tip, I've not tried Template::Simple before so I'm
    T> not sure how it works yet. I need to install and test it as well as
    T> delve into the manual, which looks a little less than simple at
    T> first sight...

    it has 4 markups. 150 lines of total code. simple is as simple codes!

    the docs are fairly clear (as clear as i can write them!). can you ask
    specific questions?

    T> Can anyone advise me how to generate the following type of nested list by
    T> Template::Simple?

    T> <ul>
    T> <li><a href=1.1.html>Level 1.1</a>
    T> <ul>
    T> <li><a href=2.1.html>Level 2.1</a></li>
    T> <li><a href=2.2.html>Level 2.2</a>
    T> <ul>
    T> <li><a href=3.1.html>Level 3.1</a></li>
    T> <li><a href=3.2.html>Level 3.2</a></li>
    T> </ul>
    T> </li>
    T> <li><a href=2.3.html>Level 2.3</a></li>
    T> </ul>
    T> </li>
    T> </ul>

    not much different than with any other templater. first break it up into
    'chunks' as i call them. each ul/li level and possibly each data row
    would be a chunk. a template chunk maps to a perl hash. lists are just
    generated by passing an array of hashes instead of a single hash. note
    that you can skip a chunk by not stuffing it or passing an empty hash to
    it. that is how you do conditionals

    so the inner levels would be something like this (VERY untested as i am
    typing on the fly):

    [% START unordered %]
    <ul>
    [% START link_line %]
    <li><a href=[%level%].html>Level [%level%]</a></li>
    [% END link_line %]
    </ul>
    [% END unordered %]

    that is the basic template. recursion to make any depth is not directly
    supported but you can fake it easily with a code ref in the data or
    doing subtemplates yourself.

    save that in a file and you can apply data to it and render it. if you
    break up your data with code refs at different levels, each code ref can
    render its level using the same template. a little more complex but
    doable. the code refs are best if they are closures. they get passed the
    template and they should have their data as closure args. i am not going
    to teach that now.

    so the basic data would look like this for the inner levels:

    {
    unordered => {
    link_line => [
    { level => '3.1' },
    { level => '3.2' },
    ]
    }
    }


    as you can see the data matches the tree shape of the template. when i
    get some time i may show how to do deeper recursion with closures. just
    not tonight.

    T> And is it actually possible to apply the advanced formatting relating to
    T> the $current_page URL along with any parent <li class=bits> if and where
    T> parent entry <li>'s are present? (as detailed in my first post in this
    T> thread). Can all of this be done with the help of Template::Simple?

    didn't follow that so i can't help.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Sep 5, 2010
    #5
  6. On 2010-09-04 22:44, Uri Guttman <> wrote:
    >>>>>> "T" == Tuxedo <> writes:

    >
    > T> Ben Morrow wrote:
    > T> [...]
    >
    > T> Many thanks for the detailed concept in how to build the particular menu
    > T> and list format. I understand it's not entirely ready-to-run code, and so
    > T> I'd like to know how your example can generate the final html code. Perhaps
    > T> you or someone here can help fill in the missing parts?:
    >
    > T> #!/usr/bin/perl -w
    >
    > T> use warnings;
    > T> use strict;
    >
    > T> my @pages = (
    > T> { page => "1.1.html", title => "Level 1.1", children => [
    > T> { page => "2.1.html", title => "Level 2.1" },
    > T> { page => "2.2.html", title => "Level 2.2", children => [
    > T> { page => "3.1.html", title => "Level 3.1" },
    > T> { page => "3.2.html", title => "Level 3.2" },
    > T> ] },
    > T> { page => "2.3.html", title => "Level 2.3" },
    > T> ] },
    > T> );
    >
    > gack!! use a templater.


    With a templater you still need to represent the data you want to render
    with the templater. I don't see how you could represent a tree, where
    each node contains a link to a page and a title, much differently in
    perl than Ben showed above (I am assuming that "page" and "title" aren't
    as redundant as the seem to be in the example. Instead of "Level 1.1"
    the title would probably be something like "1.1 - Introduction" in the
    real world).

    > many to choose from. check out mine called Template::Simple. you pass
    > it a data structure


    Yup. But you have to have the data structure first. That's what you
    quoted above.

    hp
    Peter J. Holzer, Sep 5, 2010
    #6
  7. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    > That would be because I'm an idiot, and was typing in the code without
    > testing it, and made an elementary mistake. However, I'm going to leave
    > it to you to find it, because you need to understand the code at least
    > that well before you use it. (I'll give you a hint: $pages isn't an
    > array reference, and it ought to be.)
    >
    > Ben
    >


    Thank for the hint. Anyway, why should you test the code? After all, you've
    already offered some most helpful advise along with even purpose written
    code. Nobody expects it to work without errors, although it would be nice
    if it did. That said, I'm the better runner-up for the idiot title in not
    seeing through your code properly. However, once I know it may produce the
    relevant list order and particular variable output, I would surely study it
    character-by-character until I do know its intricate functionality.

    On the line where the error is returned it says @$pages. As far as I
    understand an array reference is written \@pages

    So I changed @$pages to \@pages as I guess it should be. The same error no
    longer occurs but instead there are some other errors:

    tuxedo:~$ ./menu.pl
    Pseudo-hashes are deprecated at ./menu.pl line 24.
    Argument "1.1.html" isn't numeric in hash element at ./menu.pl line 24.
    Use of uninitialized value in hash element at ./menu.pl line 25.
    Pseudo-hashes are deprecated at ./menu.pl line 26.

    These are lines 24/25/26 of code :

    my $page = $_->{page};
    push @{$parents->{$page}}, $parent;
    my $kids = $_->{children};

    Again, I do not see through these particular errors and so any further
    hints from anyone here would be greatly appreciated :)

    Tuxedo
    Tuxedo, Sep 5, 2010
    #7
  8. Tuxedo

    Tuxedo Guest

    Uri Guttman wrote:

    > >>>>> "T" == Tuxedo <> writes:

    >
    > T> Thanks for the tip, I've not tried Template::Simple before so I'm
    > T> not sure how it works yet. I need to install and test it as well as
    > T> delve into the manual, which looks a little less than simple at
    > T> first sight...
    >
    > it has 4 markups. 150 lines of total code. simple is as simple codes!


    I installed Template::Simple as stand-alone module, after installing
    File::Slurp and setting a use lib 'external_modules/lib/perl5/site_perl'
    call in the Makefile.PL script within the Template-Simple-0.02 directory.

    The 'make test' stage of the installation failed with many errors (too many
    to list here). Some were 'Can't locate File/Slurp.pm'. Perhaps this was the
    cause of all consecutive errors, because of the external module location
    and so File::Slurp could not be found by this installation step. Maybe this
    is not important? Aftrer all, the other steps: perl Makefile.PL
    PREFIX=/mypath/external_modules/, make and make install worked fine, so I
    think the module should now be fully functional. When being in the
    directory where I ran the installation, I can do 'perldoc Template::Simple'.

    PS: I install modules in external directories because I usually run into
    insufficient system privilidges on various web hosts.

    > the docs are fairly clear (as clear as i can write them!). can you ask
    > specific questions?


    Can someone here place the list example in an working working script? Are
    separate parts meant to exist in separate files? Alternatively, I think I
    need an 'hello, I'm a template' equivalent 'hello world'... Anyone?

    [...]

    > so the inner levels would be something like this (VERY untested as i am
    > typing on the fly):
    >
    > [% START unordered %]
    > <ul>
    > [% START link_line %]
    > <li><a href=[%level%].html>Level [%level%]</a></li>
    > [% END link_line %]
    > </ul>
    > [% END unordered %]


    [...]

    > so the basic data would look like this for the inner levels:
    >
    > {
    > unordered => {
    > link_line => [
    > { level => '3.1' },
    > { level => '3.2' },
    > ]
    > }
    > }


    [...]

    > T> And is it actually possible to apply the advanced formatting relating
    > T> to the $current_page URL along with any parent <li class=bits> if and
    > T> where parent entry <li>'s are present? (as detailed in my first post
    > T> in this thread). Can all of this be done with the help of
    > T> Template::Simple?
    >
    > didn't follow that so i can't help.


    The $current_page is a variable output when a page access matches one that
    exists in an array field, being the filename portion of the current URL.
    The $current_page is known to any perl process while run through a CGI
    process, which is importing the link list onto otherwise static HTML pages.
    To clarify by an example, if you are at a page (one you happen to know)
    such as http://bestfriendscocoa.com/recipes.html then 'Tasty Recipes' in
    the header would not show as what may appear to some people as a link to a
    different page, but would instead be printed in plain text.

    Any other formatting I refer to is applicable in a nested navigation system
    of the unordered list I posted previously, typically used by many CSS
    navbars. For example, if users are on page 3.2.html, the parent <li> which
    contains the link 2.2.html, would be formatted with a style class <li
    class=parent_level_2>, while the parent of that, being the <li> containing
    the link 1.1.html would be formatted with an <li class=parent_level_1>.
    This allows for building a clear navigation system. I guess
    Template::Simple can do all this, but maybe not all as any kind of standard
    function. After all, the idea of the list output is actually very simple.

    Tuxedo
    Tuxedo, Sep 5, 2010
    #8
  9. Tuxedo

    Uri Guttman Guest

    >>>>> "BM" == Ben Morrow <> writes:

    BM> Using T::S you would need to go through and insert class => "..."
    BM> entries in your main data structure. There isn't any way to use a
    BM> subsidiary hash the way I was suggesting. (This is one of the things I
    BM> find slightly irritating about T::S, though I've yet to find a better
    BM> alternative for basic (i.e., 'don't want TT2') stuff.)

    how would you modify T::S to accomodate your idea? remember, my goal was
    a very simple and fast templater. you can do very fancy stuff with code refs
    in the data tree. the first public version was 37 lines of code. that
    morphed into 150 lines when i made it OO and a proper module. that is
    the definition of simple! :)

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Sep 6, 2010
    #9
  10. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    >
    > Quoth Tuxedo <>:
    > > Uri Guttman wrote:
    > >
    > > > >>>>> "T" == Tuxedo <> writes:


    [...]

    > > I installed Template::Simple as stand-alone module, after installing
    > > File::Slurp and setting a use lib 'external_modules/lib/perl5/site_perl'
    > > call in the Makefile.PL script within the Template-Simple-0.02
    > > directory.

    >
    > Why did you do that? You shouldn't be editing the Makefile.PL at all.
    > Put external_module/.../site_perl in PERL5LIB in the environment,
    > instead.


    Is PERL5LIB meant to be a temporary Unix environment variable at time of
    installation, pointing to /some/external_module/.../site_perl? Eg.:
    PERL5LIB=/path/to/module_dir/
    Does Makefile.PL probe for that during module installation, to find any
    relevant dependency modules that may not otherwise exist in Perl's standard
    library locations? Or do you mean something else regarding PERL5LIB?

    [...]

    > If you haven't run the tests you have no reason for thinking that.


    I'm not sure what you mean, I ran 'make test' and there were many errors.

    [...]

    > my $T = Template::Simple->new;
    > my $ref = $T->render(<<T, { world => "I'm a template" });
    > Hello, [% world %]!
    > T
    > print $$ref;


    Thanks for this bit of code, I'm sure it works :)

    [...]

    > Using T::S you would need to go through and insert class => "..."
    > entries in your main data structure. There isn't any way to use a
    > subsidiary hash the way I was suggesting. (This is one of the things I
    > find slightly irritating about T::S, though I've yet to find a better
    > alternative for basic (i.e., 'don't want TT2') stuff.)


    Thanks for this advise as well. It sounds highly complex to make T::S do
    what I'd like for this particular, yet simple, nested list structure.

    Tuxedo
    Tuxedo, Sep 6, 2010
    #10
  11. Tuxedo

    Tuxedo Guest

    Peter J. Holzer wrote:

    > > T> Ben Morrow wrote:


    [...]

    > > T> #!/usr/bin/perl -w
    > >
    > > T> use warnings;
    > > T> use strict;
    > >
    > > T> my @pages = (
    > > T> { page => "1.1.html", title => "Level 1.1", children => [
    > > T> { page => "2.1.html", title => "Level 2.1" },
    > > T> { page => "2.2.html", title => "Level 2.2", children =>
    > > [
    > > T> { page => "3.1.html", title => "Level 3.1" },
    > > T> { page => "3.2.html", title => "Level 3.2" },
    > > T> ] },
    > > T> { page => "2.3.html", title => "Level 2.3" },
    > > T> ] },
    > > T> );
    > >


    > >Uri Guttman <> wrote:
    > > gack!! use a templater.

    >
    > With a templater you still need to represent the data you want to render
    > with the templater. I don't see how you could represent a tree, where
    > each node contains a link to a page and a title, much differently in
    > perl than Ben showed above (I am assuming that "page" and "title" aren't
    > as redundant as the seem to be in the example. Instead of "Level 1.1"
    > the title would probably be something like "1.1 - Introduction" in the
    > real world).


    I think you understand well. The actual content on 1.1.html may indeed be
    an introduction to sub-branches that grow directly off the main information
    trunk so to speak, i.e. 2.1, 2.2 and 2.3, while 2.2.html is an introduction
    node to what exists on the next level, i.e. 3.1 and 3.2. In a real
    situation, an <li> node is just an overview of what exists directly one
    level deeper within it's own <li></li> scope. Yet, nodes are actual html
    pages, like any other pages, only the content is different. As you say, the
    intermediate or the first <li> may appear redundant in my example. The
    structure may be a bit better described as:

    + Overall topic (node)
    * Some topic
    + Sub-topic (node)
    * Some topic ZZz
    * Some topic Xxx
    * Some other topic

    As long as the actual information contained in the various pages is well
    arranged by topics and sub-topics, this structure can work just fine for
    whatever purpose it serves. For example, some people may click on a node
    for an intro, overview or table-of-contents or whatever happens to be
    suitably kept in such a place, while others may go directly to a sub-topic
    page. I guess this is not an entirely unusual format used in navigation
    systems with typical HTML/CSS menus. These can be styled in different ways,
    such as clicking on a topic to reveal sub-topics, or by tree-expansion
    on-mouseover or other special effects. This is all done with help of CSS
    and that requires the right list structure to begin with. Almost all such
    navigation systems on the web are built on simple unordered html list.

    > > many to choose from. check out mine called Template::Simple. you pass
    > > it a data structure

    >
    > Yup. But you have to have the data structure first. That's what you
    > quoted above.


    I had also thought an LoL could be combined with another LoL holding the
    titles, but maybe this is somewhat limiting in design:

    my @lol = ('1.1.html',
    ['2.1.html',
    '2.2.html',
    ['3.1.html',
    '3.2,html'],
    '2.3']);

    Template driven or not, in case someone has written a template or module
    that can output the exact type of listing format needed, it will surely do
    fine too. The code may however best be written from scratch. After all, the
    actual final tree format is not an irregular structure of some kind.

    How Ben wrote it looks fine to me and is certainly easy to maintain
    whenever changes are needed. I just couldn't run his code without errors
    and I can't see through the entire perl syntax unfortunately... But if you
    say it can't be done differently in perl, then that must also be the right
    way to go! What type of Perl data structure is it btw.? An AoH?

    Tuxedo
    Tuxedo, Sep 6, 2010
    #11
  12. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    > > Is PERL5LIB meant to be a temporary Unix environment variable at time of
    > > installation, pointing to /some/external_module/.../site_perl? Eg.:
    > > PERL5LIB=/path/to/module_dir/

    >
    > Yes. This will only apply while the envvar is set, though: you will
    > still need
    >
    > use lib "...";


    Yes I presumed I should 'use lib' for the required T:S File:Slurp
    dependency.

    [...]

    > You may want to look into local::lib, which makes the process of
    > maintaining your own set of modules much easier.


    Sounds good, my external modules are always scattered all over :)

    > When MakeMaker is looking for dependancies, it searches the current
    > @INC. When you run Makefile.PL with PERL5LIB set, those values will be
    > added to @INC, so any modules in those directories will be found by
    > MakeMaker. Similarly, when you run 'make test' with PERl5LIB set, the
    > test scripts will see an @INC which has those modules in.


    Thanks for explaining this so clearly.

    > ...so you can't assume the module will work OK if you ignore the errors
    > and install it anyway.


    True, and I will remember.

    [...]

    > Doing nested lists like this certainly isn't straightforward. You may
    > find it easier to jump straight to using TT2 (that is, Template.pm on
    > CPAN). It's a little heavyweight for a simple job like this, but that
    > probably doesn't matter.


    Right, it shouldn't matter, even if a procedure turns out slow because in
    the end I convert everything into static html. It's just the sheer volume
    of extra documentation to read. There's even a fairly thick book on the
    subject of TT2 alone... But TT2 does indeed look interesting, so many
    thanks for sharing this tip!

    Tuxedo
    Tuxedo, Sep 6, 2010
    #12
  13. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    > One of these two calls *doesn't* pass an arrayref as the second argument.


    [...]

    Should it be:

    \@$kids

    At least there are no confusing errors now. Can you give any further hints
    how to print the items in a nested list structure? The script so-far is:

    #!/usr/bin/perl -w

    use warnings;
    use strict;

    my @pages = (
    { page => "1.1.html", title => "Level 1.1", children => [
    { page => "2.1.html", title => "Level 2.1" },
    { page => "2.2.html", title => "Level 2.2", children => [
    { page => "3.1.html", title => "Level 3.1" },
    { page => "3.2.html", title => "Level 3.2" },
    ] },
    { page => "2.3.html", title => "Level 2.3" },
    ] },
    );

    #and then build a hash of 'parents', like so

    sub populate_parents;
    sub populate_parents {
    my ($parents, $pages, $parent) = @_;

    for (@$pages) {
    my $page = $_->{page};
    push @{$parents->{$page}}, $parent;
    my $kids = $_->{children};
    $kids and populate_parents $parents, \@$kids, $page;
    }
    }

    my %parents;
    populate_parents \%parents, \@pages, undef;

    # This will give you a data structure like

    %parents = (
    "1.1.html" => [undef],
    "2.1.html" => [undef, "1.1.html"],
    "3.1.html" => [undef, "1.1.html", "2.2.html"],
    # ...
    );

    # Then, given a page name, you can build another hash

    my $page = "3.1.html";
    my $parents = $parents{$page};
    my %class =
    map +($parents->[$_] => "parent_level_$_"),
    grep defined $parents->[$_],
    0..$#$parents;

    Thanks for your help in piecing this puzzle together. After all, this is
    nothing for beginners.

    I'm hoping I won't be needing a template plugin after all :)

    Tuxedo
    Tuxedo, Sep 6, 2010
    #13
  14. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    > I think you need to take a step back, and go through the whole thing
    > again with perlreftut and perldsc in your hand until you understand what
    > it's doing and how it does it. I'm not going to give you any more bits
    > of sample code until you've understood these bits, because I really
    > believe that using bits of code you don't understand is dangerous.


    I'm always looking forward to a message from you. Each of your answers is a
    challange for me. I admit, I'm not the brightest student but you can be
    sure I tried my best. Actually, I'm sitting day and night over the code but
    I'm afraid I need another hint. It's not that I don't want to learn, I
    simply can't see the light at the end of the tunnel....

    Thanks for your help so far.

    Tuxedo
    Tuxedo, Sep 6, 2010
    #14
  15. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    > > Ben Morrow wrote:


    [...]

    > Where are you stuck, specifically, when it comes to understanding the
    > code you've got? Once you've actually understood what that does you
    > should be able to write the printing code on your own.


    If it was as simple as to pin-point one specific part I would have asked
    that more specific question. As in most programs, the individual parts are
    generally glued together in complex ways that can make it difficult to see
    any one part clearly without understanding most of it to begin with.
    However, the job needs to be done and there isn't enough time, as such I
    will just generate the list in flat format across all pages and run a regex
    search-and-replace modifying the relavant node and parent <li>'s. It is
    more complicated to maintan as in changing a few more lines of regex calls
    and certainly not very smart code, but the end-result is the same. It is
    certainly not the way I like it but for now it is just simpler to deal with
    than processing nested data structures.

    I did a quick search and found it odd I could not find a single template or
    module that does the job of generating nested ul's and li's specifically,
    considering how complex it can be to build such procedures from scratch.

    Thanks for your code and advise, it will surely come in handy once I've had
    time to catch up with nested data structures in perl. This is not the kind
    of stuff for a non-programmer or anyone below genius to learn overnight :)

    Tuxedo
    Tuxedo, Sep 7, 2010
    #15
  16. Tuxedo

    Tuxedo Guest

    Uri Guttman wrote:

    [...]

    > my @pages = ( {
    > page => '1.1.html',
    > title => 'Level 1.1',
    > children => [
    > {
    > page => '2.1.html',
    > title => 'Level 2.1',
    > },
    > {
    > page => '2.2.html',
    > title => 'Level 2.2',
    > children => [
    > {
    > page => '3.1.html',
    > title => 'Level 3.1',
    > },
    > {
    > page => '3.2.html',
    > title => 'Level 3.2',
    > },
    > ],
    > },
    > {
    > page => '2.3.html',
    > title => 'Level 2.3',
    > },
    > ],
    > }, );


    Yes, the above certainly looks and reads better. Well noted.

    Thanks,
    Tuxedo
    Tuxedo, Sep 7, 2010
    #16
  17. Tuxedo

    Tuxedo Guest

    I wrote:

    [...]

    But for some reason it all breaks when I hit reply!

    Must be my newsreader.

    Tuxedo
    Tuxedo, Sep 7, 2010
    #17
  18. Tuxedo

    Tuxedo Guest

    Ben Morrow wrote:

    [...]

    > I disagree. If you were to start by picking one small part--even a
    > single line--and working out what it does, you would find you got
    > further than you think before you got stuck. It *will* be hard work, and
    > it *will* take time, but that's not something I can help with.


    Sure, I completely agree! However complicated or simple is a relative term
    however. My general impression from various perldocs is that much of it was
    written by programmers for programmers, more as reference to those who are
    already highly experienced, especially C-veterans. Nothing wrong with that
    and I may be flamed for suggesting here that sometimes much perl
    documentation could be better written, including more simple examples, that
    is if it's to effectively address anyone wishing to learn perl from scratch.

    [...]

    > OK. That may be a sensible solution for now.


    Workable but far less than using an ideal data structure. In any case, it's
    only pre-processing html, so the poor programming won't affect the end
    result, at least not in another way than from a maintenance point of view.

    > It's not at all complex. Once you understand the data structures
    > involved it's actually quite simple, and until you do there's not much a
    > module can do to make it easier.


    I have the same feeling. In fact, I think it is probably best done without
    modules, unless the module happens to be designed for the very purpose of
    generating nested list formats with current URL parameter and tree
    structure indicators, including documentation with plenty of clear examples.

    [...]

    > Noone said you have to learn it overnight.


    I will look into your code at a later time.

    Thanks again,
    Tuxedo
    Tuxedo, Sep 7, 2010
    #18
  19. Tuxedo <> wrote:
    >I did a quick search and found it odd I could not find a single template or
    >module that does the job of generating nested ul's and li's specifically,
    >considering how complex it can be to build such procedures from scratch.


    ???

    Sorry, but there is nothing, absolutely nothing, complex about
    recursively walking through a LOL and printing each node.
    Recursive data structures and algorithms are standard topic pretty early
    on in any computer science program and you really can't do much useful
    programming without them. They are a standard tool of the trade, like a
    wrench or a blow torch is for a plumber.

    > This is not the kind
    >of stuff for a non-programmer or anyone below genius to learn overnight :)


    Then that is your problem. A plumber needs to know how to use a blow
    torch and a programmer needs to know how to use recursive data
    structures. Neither is rocket science, but without the knowledge you
    won't get far in either area, not even as a dabbling amateur.

    jue
    Jürgen Exner, Sep 7, 2010
    #19
  20. Tuxedo <> wrote:
    >Sure, I completely agree! However complicated or simple is a relative term
    >however. My general impression from various perldocs is that much of it was
    >written by programmers for programmers, more as reference


    Yes, that is certainly true.

    Just like in a user manual for a car you wouldn't expect a comprehensive
    "How to drive on public roads" manual, would you?

    > to those who are
    >already highly experienced, especially C-veterans.


    Remove the "highly" and remove "C" (although there is a slight tendency
    to explain things from a UNIX perspective).

    The perldoc is certainly _NOT_ a learning manual for how to drive a car.
    It expects that you are familiar with the standard terms and concepts of
    the trade which you would have learned during your training, just like
    you would have learned how to drive on public roads in your driving
    school.

    >Nothing wrong with that
    >and I may be flamed for suggesting here that sometimes much perl
    >documentation could be better written, including more simple examples, that
    >is if it's to effectively address anyone wishing to learn perl from scratch.


    And that is explicitely _NOT_ the purpose of these docs. There are
    plenty other books and other resources to learn the basics about
    programming (those principles don't change, no matter which programming
    language you are using) and to learn(!) about the basics of Perl.

    The gold standard for the latter is of course "Learning Perl" which will
    provide you with a structured introduction where you learn Perl from the
    ground up in a meaningful sequence.

    Trying to learn programming (in general, not just the specifics of a
    particular programming language) from the reference manual of a
    particular language is the totally wrong approach. It's like trying to
    learn how to pilot a plane from the user manual of a Boeing 737.

    jue
    Jürgen Exner, Sep 7, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Satish Appasani

    Ideal way of posting a value to a new page?

    Satish Appasani, Jul 29, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    370
    Natty Gur
    Jul 29, 2003
  2. Don Wash
    Replies:
    22
    Views:
    768
    darrel
    Aug 13, 2004
  3. Glenn  Doten
    Replies:
    1
    Views:
    421
    Mark Rae
    Aug 4, 2004
  4. Glenn  Doten
    Replies:
    1
    Views:
    369
    Scott M.
    Aug 4, 2004
  5. Replies:
    1
    Views:
    208
Loading...

Share This Page