(jeffa) Re: Dynamic menu generation
by jeffa (Bishop) on Oct 31, 2002 at 03:17 UTC
|
use strict;
my %menu;
my @array = (
'Main//Reviews//PC',
'Other Menu//Other//Sub//Menus',
'Main//News',
'Main//Reviews//PS2',
'Main//Reviews//XBox',
);
for (@array) {
$_ =~ s/^/\$menu{'/;
$_ =~ s/\/\//'}->{'/g;
$_ =~ s/$/'}/;
eval "$_ = 1";
}
list_em(\%menu);
sub list_em {
my $ref = shift;
if (ref($ref) eq 'HASH') {
print "<ul>\n";
for (keys %$ref) {
print "<li>$_</li>\n";
list_em($ref->{$_});
}
print "</ul>\n";
}
}
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] |
Re: Dynamic menu generation
by djantzen (Priest) on Oct 31, 2002 at 03:59 UTC
|
Warning: this is pretty darn evil, but since it's almost Halloween I'll post it anyway.
my @array = (
'Main//News',
'Main//Reviews//PC',
'Main//Reviews//PS2',
'Main//Reviews//XBox',
'Other Menu//Other//Sub//Menus'
);
my %hash;
foreach (@array) {
s|(\w+\s+\w+)|\'$1\'|g;
s|\/\/|\}\{|g;
eval '$hash{' . "$_" . '} = 1';
}
sub build {
my $hash = shift();
while (my ($key, $value) = each %$hash) {
if (ref $value eq 'HASH') {
$html .= "<li>$key<ul>\n";
build($value);
$html .= "<\/ul>\n";
} else {
$html .= "<li>$key\n";
}
}
}
my $html = "<ul>";
build(\%hash);
$html .= "<\/ul>";
print $html;
Update: Of course Jeffa beats me to it... harumph.
Update: The ordering requirement can be satisfied using
Tie::IxHash for all of the HoH-based methods in this thread. | [reply] [d/l] |
Re: Dynamic menu generation
by tadman (Prior) on Oct 31, 2002 at 03:56 UTC
|
This seems to do the trick:
my @array = (
'Main//News',
'Main//Reviews//PC',
'Main//Reviews//PS2',
'Main//Reviews//XBox',
'Other Menu//Other//Sub//Menus'
);
sub menu
{
$_=q~;ir$w}Uw&Ii,jmcumUumbo#e_cjm>oImb}U|nyp@''@#l"ynrjmUtthU]h!U[$rhb
+]h!U[11mU=mboI|_|mU#|wU"mcuL)'(*=L#/l"ynrjmU)mboI|wU"mUuhb]mU[#|wU"mc
+uL)(*=)*<=hU]-s[)'*<=L#//f_y${sumc#/#tir$w~;y~L)oep<;@y>m}/Ushw![i=nb
+$1*l#_&|{"]u('f,tjIcr~"<)ftI*'i_@=}s1$u#]m>lcn|Lw;obp!h[,U/jy&({re~;s
+,.*,$&,ee;$_
}
print menu(sort@array),$/;
If you don't pass in a sorted array, it can create strange menus. It's also easily confused by similar leaf nodes. | [reply] [d/l] |
|
|
Okay, I am mystified (and if need be, humbled). I have seen this sort of genuinely obfuscated thing before (in someone's .sig file perhaps?) and even confirmed that it worked.
What I am wondering though, is how the heck do you come up with code like,
$_=q~;ir$w}Uw&Ii,jmcumUumbo#e_cjm>oImb}U|nyp@''@#l"ynrjmUtthU]h!U[$rhb
+]h!U[11mU=mboI|_|mU#|wU"mcuL)'(*=L#/l"ynrjmU)mboI|wU"mUuhb]mU[#|wU"mc
+uL)(*=)*<=hU]-s[)'*<=L#//f_y${sumc#/#tir$w~;y~L)oep<;@y>m}/Ushw![i=nb
+$1*l#_&|{"]u('f,tjIcr~"<)ftI*'i_@=}s1$u#]m>lcn|Lw;obp!h[,U/jy&({re~;s
+,.*,$&,ee;$_
I mean, I can't even recognize many operators in that mess, let alone interpret jmcumUumbo#e_cjm into anything meaningful. Also, I could not get this to work.
Clues for the clueless? Or perhaps I am missing some larger joke.
PCS | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
The first two statement in sub menu are:
$_ = q~ stuff ~;
y~ characters ~ other characters ~;
If you insert a "print;" here you will be a lot less mystified.
| [reply] [d/l] |
|
|
It works, but you'll have to be careful about how you copy it. Perl Monks inserts red plus signs (+) to break up the lines, that if pasted in to the program will cause it to fail. You can edit these out if you're careful, and join the program back in to one line, or use the "D/L Code" link to get a clean copy.
Now, this is intentionally obfuscated, but the non-obfuscated source isn't that much clearer. Here's the encoded program that is being run:
*menu=sub{my(@r,@s,@c);for(@_){@c=split'//';while(@s&&$s[$#s]ne$c[$#s]||@s>@c){pop@s;push@r,"</UL>";}while(@s<@c){push@s,$c[@s];push@r,"<UL><LI>$s[-1]</LI>";}}join!1,@r;};&menu
| [reply] [d/l] |
Re: Dynamic menu generation
by sauoq (Abbot) on Oct 31, 2002 at 03:02 UTC
|
I'm not sure in what sense you have to turn it into a "menu." In your example, you indicate it should be turned into an unordered list. That said, You would probably be better off using a hash of nested hashes instead of an array of strings to hold the "menu" data.
my %hash = (
Main => {
Reviews => {
'PC' => A_LINK_OR_CALLBACK_FUNCTION,
'PS2' => A_LINK_OR_CALLBACK_FUNCTION,
'XBox' => A_LINK_OR_CALLBACK_FUNCTION,
},
News => A_LINK_OR_CALLBACK_FUNCTION,
},
'Other Menu' => {
Other => {
Sub => {
Menus => A_LINK_OR_CALLBACK_FUNCTION,
},
},
},
);
Note that I use A_LINK_OR_CALLBACK_FUNCTION to represent where you would probably store a URL (if this is for a web page) or a callback function (if this is for a GUI based program.)
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] |
Re: Dynamic menu generation
by nutshell (Beadle) on Oct 31, 2002 at 03:22 UTC
|
my @array = (
'Main//News',
'Main//Reviews//PC',
'Main//Reviews//PS2',
'Main//Reviews//XBox',
'Other Menu//Other//Sub//Menus'
);
Ex2:
my @array = (
'Main//Reviews//PS2',
'Other Menu//Other//Sub//Menus',
'Main//Reviews//XBox',
'Main//News',
'Main//Reviews//PC'
);
Ex3:
my @array = (
'Other Menu//Other//Sub//Menus',
'Main//News',
'Main//Reviews//XBox',
'Main//Reviews//PS2',
'Main//Reviews//PC'
);
--nutshell
Update 1: Didn't look at jeffa's code yet.
Update 2: Jeffa's code is almost there... it just doesn't retain the order things are defined in.
Update 3: Ok - I now know that I can't create a hash to simulate the menus tree but rather that I must use an array. I'm not sure how to do this... please help. | [reply] [d/l] [select] |
Re: Dynamic menu generation
by graff (Chancellor) on Oct 31, 2002 at 03:03 UTC
|
Are you talking about menus in a Perl/Tk application?
If so, it's easy to define menus based on, e.g. data read
from a file; it's even easy to change menu contents on the
fly depending on what the user choses to do.
But I have to second tadman's request: show us some code
that you have tried or would like to try. Without that,
the question is too vague to give detailed help.
| [reply] |
Re: Dynamic menu generation
by nutshell (Beadle) on Oct 31, 2002 at 02:19 UTC
|
I forgot to add that the members in the array aren't necessarily going to be in order. For instance @array could look like:
my @array = (
'Main//Reviews//PC',
'Other Menu//Other//Sub//Menus',
'Main//Reviews//PS2',
'Main//News',
'Main//Reviews//XBox'
);
--nutshell | [reply] [d/l] [select] |
|
|
You can always use sort @array so I don't see how this is an issue. What's your initial idea? Surely you have some code that was an attempt to solve this problem. What trouble did you have?
| [reply] [d/l] |
|
|
I'm trying to take that array and generate the HTML shown above with it.--nutshell
| [reply] |
Re: Dynamic menu generation
by dingus (Friar) on Oct 31, 2002 at 17:37 UTC
|
#use Data::Dumper;
my @array = (
'Main//Reviews//PS2',
'Other Menu//Other//Sub//Menus',
'Main//Reviews//XBox',
'Main//News',
'Main//Reviews//PC'
);
array2list(@array);
sub array2list() {
my %h;
for (@_) {
my $hr = \%h;
for (split('//', $_ )) {
$hr->{$_} = [(scalar keys %{$hr}), {}] unless (exists($hr->{$_}));
$hr = $hr->{$_}[1];
}
}
#print Dumper(\%h),hr;
displaylist (\%h);
}
sub displaylist() {
print '<ul>';
my $hr = shift;
for (sort {$hr->{$a}[0]<=>$hr->{$b}[0]} keys %{$hr}) {
print '<li>',"$_"; # $hr->{$_}[0]\n";
displaylist ($hr->{$_}[1]) if (scalar keys %{$hr->{$_}[1]});
}
print '</ul>';
}
Some comments tomake this a little less confusing:
The Data::Dumper bits can be uncommented if you want to know what the heck %h turns out to be. They are clearly not required.
The ordering requirement means that yo can't just ahve a hash of hashrefs. So each hash value is an array ref containing a order created number and a sub hashref. At the twigs the sub hashref is empty.
the subroutine displaylist() is called recursively to print the UL.../UL for a hashref | [reply] [d/l] |