Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Seeing Perl in a new light

by Lady_Aleena (Deacon)
on Apr 12, 2009 at 12:40 UTC ( #757092=perlmeditation: print w/ replies, xml ) Need Help??

Going back to the drawing board

I decided to go with a full blown meditation because I think I had a revelation of sorts. Those who have wished upon so many occasions to reach through their monitors and bash my head into my monitor, desk, or keyboard for being so dense as to the power of Perl may now see their days of telling me to convert my site to Perl come to an end. I may have finally seen the light. I apologize ahead of time for the rambling, confusing, and disjointed nature of this meditation.

I also apologize for being so intransigent and belligerent about using Perl more broadly for my site. As with anything new, I am fearful of change. When I was first introduced to SSI I got belligerent with those trying to help me. After getting over my initial trepidation, I went as wild as a could with it. Once I find something I think of as good, I rarely want to change to anything else. My anxiety has shown through on so many occasions with those here having the tremendous burden of dealing with my dismissiveness of Perl for my simpler pages. Now, I think that I have taken SSI as far as I can but need to upgrade to something better. I now think Perl can help me with that.

What has changed you may be asking? Well, I was playing around with some subs when what Perl could possibly do for my site hit me square in my gray matter. The stray thought crossed my mind that Perl may be able to print the file name of the script on which I was working. Then it further hit me that it could probably print the directory name as well, all the script's sibling files, and maybe the entire directory structure above and below it. With that on my mind, I began to do some serious thinking about the structure and semantics of my site.

For the navigation of my site, I was thinking that I could probably have a script build it completely from the directories' and files' names. For the navigation within a directory, the first link would be to the "home" page which would be the top level index.pl file in the top directory (duh, right?). The navigation section of the page would include all the sub-directories and files in the same directory, and the files in the sub-directories (on down to the bottom) of each. For the home page and other files in the home directory, the navigation would basically be every page on the site. In sub-directories, there would be a path back home over the pages in that directory. For a second level directory, the top link would be home, and the second link would be the next directory up. The files in the parent directories would not be printed, however the files for the sub-directories would be.

Some sub-directories would be purposefully excluded from any listing, such as an images or javascript directory (if there are any scripts left when this is all done). I have neither right now, and if this system could be set up, I could have them. I have only one CSS file, but I would set up a directory just for it and exclude it from the navigation listing. I could just set up a directory called files for all the image, script, and css files and just have one exclusion, so that is not set in stone just yet.

Also in the navigation section of the pages, there may be external links. I could possibly set up a file called navigation_links.pl or something that could be read into the navigation section under the internal navigation. If there are more than a certain number of links, another script could be called upon to create a full blown external_links.pl (which would then delete navigation_links.pl), with a link in the navigation section to it. After the external_links.pl is created, it can be edited by hand to add any formatting needed. So the script would check for external_links.pl (if found print the link to it), then then navigation_links.pl (if found, print the list of links), or print nothing at the bottom of the navigation section.

At the very tail end of the navigation section would be an Amazon link (by section and if applicable), a Firefox link, and a valid HTML link.

I wouldn't have to do a thing when I add a new file with the navigation system above. If the script works as I think it will, any new files would be added to the navigation without me having to open a single file to add the page to the list. When I add a file now, I have to open up another file to make sure that the new file is listed.

With so much on my pages the same, having one script that has all of the base material on it would be great. The script would include little things like the DTD and charset and all of the other opening HTML needed for the pages and the ending HTML too. The individual scripts would just have the juicy centers in them from a page with just simple paragraphs to very complex tables needing gads of page specific scripting.

For all the directories, there will be index.pl files which will be part of the navigation but take their names from their directories. There is also some index page specific styles which will have to be added to them. I already know of one index file that will have to have something added to override a certain index style (maybe my $IndexStyle = "no";). Other files will have classes added to their body tags only if my $PageStyle is declared.

For the titles of the pages, I was thinking of them being Lady Aleena's sub-directory - file name. For the initial heading, just the file name. I will have to think about that a lot when naming the directories and files since I would like the titles to make sense. The renaming is going to be a bit of a headache. I don't know how Lady Aleena's movies - Favorites - Comedies would look. I would really like it to me Lady Aleena's favorite comedy movies, but I can't have different naming protocols for the various directories. I am also not sure if I want to have all lower case file names and do some sort of text transformation to make the initial letters capitals later. Also, for multiple word file names, I will be using underscores for the spaces, so I know I will have to add a regex to replace the underscores with spaces. So, I could name a file love_poems, and hopefully it can be printed out as Love poems or Love Poems. If that file is in the poetry directory, the title would be Lady Aleena's poetry - Love poems. In the navigation section, poetry would need to be capitalized.

For some pages, I may be including forms such as my movie list pages and proficiencies page. I would love to have a console where I can see all of the submissions on one page where I can vet them instead of getting them by e-mail.

I thought about writing a sub that would make internal links for my site. There could be a script generated listing of all the pages of my site, so that all I have to do is add '.SiteLink("page name").' whenever I wanted an internal link, or just '.Link("page name or external page title","external link").'.

With SSI I lost some of my directory structure, hopefully Perl will give it back to me. I am still trepidatious about doing this. There are some pages that seem too hard to convert over or would be very time consuming. I am not sure where to go after the following code:

#!/usr/bin/perl -w use strict; use warnings; use diagnostics; use CGI::Carp qw(fatalsToBrowser); use vars qw(); print "content-type: text/html \n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w +3.org/TR/html4/strict.dtd"><html><title>';

If you have made it this far, thank you for bearing with me. I would like to know if any of these ideas are impossible in Perl. Are there any ideas you would tweak? Any just plain too silly? Am I on the wrong track with anything? I would like to start by getting my thoughts in the proper order and the right terminology down before I dive in (like what search terms to use to look up printing file names and such).

I have a blank slate in front of me, I would like to begin filling it.

Have a nice day!
Lady Aleena

Comment on Seeing Perl in a new light
Select or Download Code
Re: Seeing Perl in a new light
by ELISHEVA (Prior) on Apr 12, 2009 at 12:56 UTC

    Welcome to the power of the "sub"!

    My advice: take it slow. Convert a very small section of your site. Get comfortable with the process of converting and the kind of subroutines that you will need. See if you notice some patterns in how you go about converting things. Apply what you learn to the next batch of pages. You will surely learn as you go... and there are many here to help you.

    Now would also be a very good time to learn about version control. In any case do lots of back-ups. Mistakes are a natural part of learning and you don't want to break your site while you are trying to make it easier to manage and expand.

    Best of luck, beth

      My dearest ELISHEVA, you put me on the path by showing me the power of the sub! Without you, I would not have had this revelation. I have written several since, though they are mostly simple things that are not much to look at.

      I would like to start writing the shell, especially the navigation part. That is the most daunting of tasks. I will be uploading this to my perlmonk.org account not my xecu.net account. That will give me the freedom to start from scratch with things. Write the shell script, get comfortable with it, then start on the massive reorganization and rewrite of my site. With this new way of thinking, there will be a new way of doing. That makes me equals amounts eager and anxious. Weird isn't it?

      Have a nice day!

      Lady Aleena
        you put me on the path by showing me the power of the sub

        Of course you have heard the old Navy joke, that "the best marine is a submarine". :-)


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku
      ELISHEVA...You mentioned version control, I am not exactly sure of what you mean by that. gwadej also suggested it. Could you please tell me what exactly that entails?
      Have a nice day!
      Lady Aleena
        Version Control lets you do two things:
        1. Keep all (old) versions of your files around without cluttering up the structure on your disk.
        2. Allows more than one programmer work on the same project without getting in each other's way (by overwriting, deleting, changing, moving, ... files).
        A nice explanation is on Visual Guide to Version Control. Personally I use Subversion (which plays very nice with Windows and is integrated into my IDE Komodo), but if you got a lot of people working on the same project GIT comes highly recommended nowadays. Perl5 has recently moved to GIT.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        A version control system is a stand-alone, fundamental component of a configuration management system that is responsible for the management of individual versions of controlled files/items, providing the ability to manage versions of controlled item versions, typically involving the...
        • Management i.e. creation, update & conditional deletion of item versions
        • Support of version branches
        • Support for the merging of item versions
        • Management i.e. creation, update & conditional deletion of controlled item version labels
        Note that the merging of item versions is specific to software configuration control/management systems, the facility is neither required, nor indeed present, in hardware control/management systems.

        Note also that the management of item version labels provides the basis for baseline management - in which aggregates of items (& their versions) are managed as enitities in their own right.

        I would take issue with CountZero in as much as ... Allows more than one programmer work on the same project ... is not necessarily provided by a version control system, it is known (in the trade) as co-ordination of concurrent development and is a fundamental requirement of any configuration management system.

        A user level that continues to overstate my experience :-))

        This is going to be another piece you will think is unnecessary in the beginning. Years ago, I saw version control described as a time machine for your development.

        A version control system allows you to go back to earlier versions of your code or compare your two different version of code. This is most useful while things are changing.

        For example, imagine that you've got a mostly stable version of your code in place. Now imagine you have a great idea that will only take a few minutes to code up.... 4 hours later, nothing is working and you are wishing you could go back to where you were 4 hours ago. Version control to the rescue.

        You could do the same thing by zipping up your entire site any time you feel it is worth keeping.

        Version control can also help with seeing what changes you have made (to help you find where you went wrong). Say you want to compare what you did 2 hours ago with what you have now.

        The point of enlightenment for me was when I realized that I could use version control proactively. Make sure everything is under version control. Try something experimental that might break everything. If it works, keep it. If it doesn't, toss it. No real loss.

        Of course, there are better and more advanced ways to make use of version control, but these would be helpful right away.

        G. Wade
Re: Seeing Perl in a new light
by gwadej (Chaplain) on Apr 12, 2009 at 16:42 UTC

    Congratulations on the next step in your understanding of programming.

    Possibly the biggest problem you will have at this point is in the sheer number of approaches you now have available. As ELISHEVA points out, you would be wise to change a small portion of your site using your intended method at first.

    Based on past experience, I can say that whatever you come up with first won't be right. This is not meant to discourage you, but to make you think. When you get your first version built, you will have a better understanding of what you can do (and will have learned more). You may then want to change your approach.

    Also as ELISHEVA advised, version control becomes very handy at this point. It helps you save the various attempts you've made and allows you to make wild changes freely, knowing that you can always go back to something from before.

    One thing to consider on the file naming approach is an old maxim of programming:

    All problems in computer science can be solved by another level of indirection.

    Imagine that you had a file that listed the filenames and appropriate titles. Now, if your titling function used a the title fro the file if it exists, or a constructed title like you describe, you can add files easily and fixup names as needed. This may be a bit more complicated than you had considered, but having a real programming language opens up new ways of thinking about your problems.

    Congratulations again and welcome to the journey.

    G. Wade

      gwadej...thank you for your support. Now, I have to find the ways and means to get to my goal. I wish that this lent itself to baby steps, but it really doesn't. This is to be the shell script for all of the pages of my site. I am not sure if it is possible to do it just for one small section. I have asked ELISHEVA to clarify what version control entails, though you are always welcome to chime in to that too. As for file names, well, I am a Wikipedian, so I will come up with something. :)

      Have a nice day!
      Lady Aleena

        One way to do the baby steps thing is to set up a single directory where you will try this approach. Think of it as a test site or sub-site. Then, go wild in that directory.

        One of the realities of programming is that you will have bugs. Fixing these are much easier if you are not stressed about getting your whole site back on line.

        As you get an idea fleshed out and (relatively) stable, you can apply that idea (and possibly code) to your main site.

        I know it seems like unnecessary, extra work, but we are suggesting this based on years (in my case around 20) of development in multiple languages on and off the web. The first time you really mess up, you'll thank us. (And if you don't really mess up, you're not trying hard enough.<grin/>)

        Stay curious and have fun.

        G. Wade
      That maxim is from David Wheeler. However Kevlin Henney's corollary has much truth as well: "...except for the problem of too many layers of indirection."
Re: Seeing Perl in a new light
by CountZero (Bishop) on Apr 12, 2009 at 17:33 UTC
    Lady Aleena,

    "'t Is costly wisdom that is bought by experience" as Roger Ascham, Scholemaster said.

    Now for your project, it looks to me that the major part of your web-site is entirely static in nature, but that from time to time you add files and links and ... which must be reflected in the various pages you have on your site.

    One solution would be to have the structure of the web-site "rendered" on the fly for every hit, but that seems wasteful of resources since the majority of the info did not change at all and once the changes have been rendered they should not be re-rendered when next this page is accessed.

    Another --IMHO preferable-- solution is to use a templating system, such as Template::Toolkit to rebuild your site every time you change something. it has a lot of functionality already build in to add headers and footers. The pages are mostly pure HTML with the variable bits and pieces either written in the Template::Toolkit language (which is very close to Perl) or even directly in Perl itself.

    In the docs of Template::Toolkit we read:

    A number of special directives are provided, such as INSERT, INCLUDE and PROCESS, which allow content to be built up from smaller template components. This permits a modular approach to building a web site or other content repository, promoting reusability, cross-site consistency, ease of construction and subsequent maintenance. Common elements such as headers, footers, menu bars, tables, and so on, can be created as separate template files which can then be processed into other documents as required. All defined variables are inherited by these templates along with any additional "local" values specified.

    Just like you and Perl, it took me a while to discover the beauty and usefulness of this templating system, but now I use it regularly (and not only to make web-sites). Check it out, it could empower your new understanding of Perl even more!

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      CountZero...What you are discussing is the navigation section of the pages which I would like to have created with each hit, I think. I am open to be swayed to having a semi-static list somewhere of every page and directory on my site. I would prefer to have the navigation be where I get it written, test that it works, once it does, make it live, then forget it is there.

      I gave Template::Toolkit a quick skim and am unsure how it can help me. I would like to build as much of this from scratch before I start looking into modules. In my neophyte opinion, the module is more confusing at the moment. I have just wrapped my head around subs, but that module as a whole confuses me.

      What I am hopefully building is a shell for all of the pages on my site, a template if you will. It seems funny to me to use a template to build a template. :)

      I wish I understood how to make this a module, but even that is out of reach for now. Instead of useing it, I will be doing it instead. I know I should be looking at the former, but the module mojo makes no sense to me.

      Have a nice day!
      Lady Aleena
        Just go as fast as you are comfortable with now, but remember there will be new horizons and perspectives around each corner and be prepared to be flexible and drop any "fixed" knowledge when something better comes along.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Seeing Perl in a new light
by Your Mother (Canon) on Apr 12, 2009 at 18:10 UTC

    I went through the same thing; the "revelation" coming 1998-1999. I had coded up a pretty large site (something like 400 pages) in HTML by hand. I was an experienced editor so I was quite good with find/replace/copy/paste sorts of things and it seemed manageable. I discovered Perl. I rewrote everything with it. Then I did it again. Then part of it again. Then again. Then I stopped and learned a framework after having redone the whole thing anywhere from 2-6 times depending on the part of the site(s).

    And that's both the problem and the meat. I *wish* I had been turned on to templating engines and frameworks sooner. TT2 would have steamrolled the first three revisions of the site(s), saving me probably a solid year's worth of work. But if I had picked up those things early I probably wouldn't be employed as a Perl hacker today because I wouldn't have developed both the chops (especially debugging chops) and the experience to know to never again write a line of code someone else already wrote with a test suite and a decent distribution.

    So, have fun, but go slow with attacking problems with new code and ask here often about things you're doing. If I had discovered this place earlier, or even recognized its importance sooner after I did discover it, I could have gained the experience and chops much faster and with a lot less pain. :)

    A tip: HTTP/CSS/XHTML/JS stuff is extremely valuable to doing good and quick web-work; and it's easier to confront if you admit it right away instead of fighting it and digging in with the Perl as a defense against it.

      Your Mother...Hopefully I will only need this one file to build the framework for all of the rest. I am thinking about naming it base.pl then do "base.pl" on every page of the site or something similar. If I understood the module making mojo, I would probably be able to use base, but that requires more than I know now.

      The first thing I need to know is how to grab file and directory names. I haven't been able to find anything on google about getting things from the environment, if that is the correct term. Then I have to learn how to write a regex. Fun, fun, fun.

      As for the other files, the ones that I do not want to include in the navigation, do not worry. I will still be using my css file, images, and any javascripts that can not be replaced with Perl. What I was discussing is where to put them. See below.

      /root
       /files - Where everything that is not meant for the viewing public goes.
      
      -or-
      
      /root
       /css - Where my style sheet(s) will go. (I may break it up into smaller pieces.)
       /images - Where my images will go.
       /javascripts - Where my javascripts will go.
       /other - Where everything else that is not meant for the viewing public goes.
      
      -or-
      
      /root
       /files
        /css - Where my style sheet will go.
        /images - Where my images will go.
        /javascripts - Where my javascripts will go.
        /other - Where everything else that is not meant for the viewing public goes.
      

      When I write the navigation, I will exclude those directories from it. I am just not sure which way I want to go right now. Currently, I have everything crammed into the root directory that is site wide like my style sheets, images, etc. I may go with the first or third option, since it would be easier to exclude just one directory, than four or more.

      Have a nice day!
      Lady Aleena
Re: Seeing Perl in a new light
by BJ_Covert_Action (Beadle) on Apr 13, 2009 at 16:52 UTC
    As with anything new, I am fearful of change
    - Originally posted by Lady Aleena

    ...as so many people are. However, it is important to remember that change is as important a form of quality as status quo is. That is, change, dynamics, drives any given system forward on the slow, inevitable path of progress. It must exist or else the universe stagnates and all becomes null. Likewise, status quo must offset change. It must restrain dynamic progress and be in a constant tension war with change. Otherwise degenerate rampancy occurs and nothing resembling good ever is saved. Change and status quo are equally necessary and equally quality. Without one, you wouldn't have the other, and without the other, you wouldn't have the one. The two are linked intimately in an infinite conflict of progress and restraint in such a way as to allow the progressive evolution and function of the universe. Fear not change. Fear not status quo. Accept both as they present themselves to be the better option.

    Regarding your revelation, congratulations. I would agree that taking patient, methodical baby steps would behoove your progress :)

    Cheers.

Re: Seeing Perl in a new light
by TGI (Vicar) on Apr 15, 2009 at 21:32 UTC

    From what you describe, and how you seem to be thinking about your site structure, you might want to check out HTML::Mason.

    Take a look at the homepage, and also there is a book available for free online (and in dead tree format too).

    I know Mason adds a whole extra set of concepts to wrap your head around, but it will give you some powerful tools to achieve what you are looking for. The docs are pretty good, and as I said, it seems like a good conceptual fit.

    Happy hacking!


    TGI says moo

Re: Seeing Perl in a new light
by Lady_Aleena (Deacon) on Apr 19, 2009 at 08:56 UTC

    My progress to date - Start.pm

    package Start; use strict; use warnings; use diagnostics; use vars qw($body_class $main_class $contents) use Cwd; use CGI qw(); use CGI::Carp qw(fatalsToBrowser); use File::Basename qw(fileparse basename dirname); use File::Spec; use Lingua::EN::Inflect qw(PL PL_N PL_V PL_ADJ NO NUM PL_eq PL_N_eq PL +_V_eq PL_ADJ_eq A AN PART_PRES ORD NUMWORDS inflect classical def_nou +n def_verb def_adj def_a def_an); print "content-type: text/html \n\n"; sub Class { my ($class) = @_; print " class=\"$class\""; } sub Heading { my ($level, $text) = @_; print "<h$level>$text</h$level>\n"; } #Written with the help of SAS_Spidey01 on #perl on freenode my $cwd = getcwd; my $rootdir = 0; sub get_rootdir { my @dirs = ('/home/lady_aleena/var/www', '/ftp/pub/www/fantasy', 'C: +/Documents and Settings/my name/My Documents/fantasy'); my @dir = grep { $_ if $cwd =~ /^$_/ } @dirs; return pop @dir; }; $rootdir = get_rootdir; #This sub written with the help of wfsp on PerlMonks and rindolf on fr +eenode #perl. sub Title { my $filename = basename($0); my $dirname = getcwd; if ($filename ne "index.pl") { $filename =~ tr/_/ /; $filename =~ s/.*\/+//; $filename =~ s/\.[^.]*\z//; $filename = ucfirst $filename; return $filename; } elsif ($dirname ne $rootdir) { $dirname =~ tr/_/ /; $dirname =~ s/.*\/+//; $dirname = ucfirst $dirname; return $dirname; } else { return "Lady Aleena's home"; } } print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w +3.org/TR/html4/strict.dtd"> <html><head><title>'.Title.'</title><meta http-equiv="Content-Type" co +ntent="text/html; charset=windows-1252"><link rel="stylesheet" type=" +text/css" href="../main.css"></head><body'; if ($body_class) { print Class($body_class); } print '><div id="bar"></div><div id="main"'; #menu will go between <di +v id="bar"> and </div>. if ($main_class) { print Class($main_class); } print '>'; Heading(1,Title); #the juicy center print "</div></body></html>\n"; 1
    For the juicy center, I am thinking of something simple, maybe...
    print <<"CONTENTS"; $contents CONTENTS

    The above did not work as expected. I am back to the drawing board for getting the juicy center code to run in that spot. I am currently looking at SelfLoader, but I am not sure that will work either.

    Thoughts and suggestions gladly accepted.

    Have a nice day!
    Lady Aleena
Seeing Perl in a new light: Epilog
by Lady_Aleena (Deacon) on Sep 19, 2010 at 23:17 UTC

    It is now almost 18 months later, and I am happy with the results of those months. My goal of getting my site off of server side includes is so very much closer to completion. That isn't to say that I don't have a long way to go, but thanks to the help of my fellow monks, I have made a lot of progress.

    My blank slate is now filled with code that I use for almost everything I write. I will always be tweaking and looking for small ways to make things better, so I am including the four modules which make up the back bone of my site.

    I have a lot of people that hopefully know how thankful I am for all of their help.

    Base::HTML

    When I want a web page printed for my site, this comes first.

    Base::Roots

    This module gets all kinds of root information for my site or manipulates root information to get and print other things that are based on root.

    Base::Menu

    When my site is fully finished, I may fold this back into Base::HTML. Currently I am using it in two places, so a separate module was needed.

    Base::Nifty

    This is just a collection of subroutines that were too small to be on their own which I use in a lot of places all over my site.

    So, there it is, all of the Base modules for my site. I wouldn't have this if it weren't for the people here. Thank you all!

    Have a cookie and a very nice day!
    Lady Aleena

      I am writing to you about your approach for multiple similar pages. I am going to focus on the Monsters section of your site, because that is the part I've been looking at and am familiar with.

      You have a section on Role Playing, with a subsection titled "Monsters". You've got a CSV file with all the information for all the monsters you want a page for.

      Right now, it appears that each monster has its own Perl script. So there is "Dark Centaur.pl" for a dark centaur. And "Daemar.pl" for a Daemar and so forth. If you were to add a new monster you would add the monster to the CSV file and add a "New_Monster.pl" script.

      What makes much more sense is to make one script that handles all monster related issues. Call it monsters.pl. Then when you want to access a list of all monsters, I've put together a CGI script that does exactly that. One script will handle all the monsters and also provide a summary page with links to detail view of specific monsters.

      With this approach, to add a new monster, you simply add it to the CSV file. Everything else happens automatically.

      Let me emphasize this key point; <bThere is no need to have a one-to-one relationship between pages displayed and scripts that generate them. A single script can produce many different pages.

      Without any other messing about, here's a script that demonstrates how a single script can handle all your monsters.

      use strict; use warnings; use CGI (); use URI::Escape; use Text::CSV; use Data::Dumper; use constant DATA_FILE => 'Monsters.csv'; use constant ATTRIBUTES => ( 'Climate/Terrain', 'Frequency', 'Organization', 'Activity cycle', 'Diet', 'Intelligence', 'Treasure', 'Alignment', 'No. Appearing', 'Armor Class', 'Movement', 'Hit Dice', 'THAC0', 'No. of Attacks', 'Damage/Attack', 'Special Attacks', 'Special Defenses', 'Magic Resistance', 'Size', 'Morale', 'XP Value', ); use constant SECTIONS => ( 'Appearance', 'Combat', 'Habitat/Society', 'Ecology', 'Variants', 'Note', ); use constant FIELDS => ( 'Monster', ATTRIBUTES, SECTIONS, ); use constant SUMMARY_FIELDS => ( 'Monster', 'Climate/Terrain', 'Frequency', 'Organization', 'Activity cycle', 'Diet', 'Intelligence', 'Treasure', 'Alignment', 'No. Appearing', 'Hit Dice', ); my $q = CGI->new; my @monsters = $q->param( 'name' ); print @monsters == 1 ? monster_detail($q, $monsters[0]) : monster_summary($q, @monsters ); # -------------------------------- sub page_start { # Generate the standard HTML for the start of a page. # Returns html text. my $q = shift; # CGI Object my $title = shift; # Title of the page. my $html = <<END_HTML; <html> <head> <title>$title</title> </head> <body> <h1>$title</h1> END_HTML return $html; } sub page_end { # Generate the standard HTML for the end of a page. # Returns html text. my $q = shift; # CGI Object my $url = $q->url(-relative=>1); my $html = <<END_HTML; <p><a href='$url'>Monster List</a></p> </body> END_HTML return $html; } sub monster_detail { # Format a monster detail page # Returns html text. my $q = shift; # CGI object my $monster = shift; # Name of monster to display my $monster_data = load_monsters( $monster ); return error_page( $q, "'$monster': Monster not found.") unless @$monster_data; my $html = join '', $q->header, page_start($q, $monster_data->[0]{Monster} ), gen_detail( $monster_data->[0], [ ATTRIBUTES ], [ SECTIONS ] ) +, page_end( $q ); return $html; } sub monster_summary { # Format a monster summary page. # Returns html text. my $q = shift; # CGI object my @monsters = @_; # List of monsters to summarize. my $monster_data = load_monsters( @monsters ); return error_page( $q, "No matching monsters found (@monsters)." ) unless @$monster_data; my $html = join '', $q->header, page_start($q, 'Monster Summary'), gen_table( $monster_data, [ SUMMARY_FIELDS ], { Monster => sub { my ($attr, $item) = @_; my $name = $item->{$attr}; my $esc = uri_escape( $name ); return "<a href='?name=$esc'>$name</a>"; }, }), page_end( $q ); return $html; } =head3 load_monsters Accepts a list of monster names to load. If no list is provided, all +monsters will be loaded from the data file. Returns an array ref containing hash refs, each containing data from o +ne monster. =cut sub load_monsters { my %wanted_monster; @wanted_monster{@_} = (); my $csv = Text::CSV_XS->new ({ binary => 1, quote_char => '~', sep_char => '|', }) or die "Error creating CSV parser: ".Text::CSV->error_diag; open my $fh, "<:encoding(utf8)", DATA_FILE or die "Error opening data file: $!"; my @monsters; while (my $row = $csv->getline ($fh)) { my %monster; @monster{ FIELDS() } = @$row; push @monsters, \%monster if !%wanted_monster || exists $wanted_monster{ $monster{Mo +nster} }; } $csv->eof or $csv->error_diag (); close $fh; return \@monsters; } sub gen_table { # Generate monster summary table. # Returns html text. my $data = shift; # Array of Monster hashes my $fields = shift; # Array of fields to use my $formatter = shift || {}; # Hash of subs used to preprocess +fields my $html = '<table><tr>'; $html .= join '', map "<th>$_</th>", @$fields; $html .= '</tr>'; for my $item ( @$data ) { $html .= '<tr>'; $html .= join '', map "<td>$_</td>", map { exists $formatter->{$_} ? $formatter->{$_}( $_, $item ) : $item->{$_}; } @$fields; $html .= '</tr>'; } $html .= '</table>'; } sub gen_detail { # Generate monster detail view # Returns html text. my $data = shift; my $attr = shift; my $sections = shift; my $html = '<dl>'; $html .= join '', map "<dt>$_</dt><dd>$data->{$_}</dd>", @$attr; $html .= '</dl>'; for my $section ( @$sections ) { my @paras = split /\\/, $data->{$section}; $html .= "<h2>$section</h2>"; $html .= join '', map "<p>$_</p>", @paras; } return $html; }

      I know this code doesn't use your Base elements. I didn't want to download, configure and troubleshoot them. I thought it was more important to get this example together for you. You should be able to massage your standard infrastructure into this code.

      As you do, be aware that it has got a big, fatal bug--I didn't define an error_page routine, you'll see the error if you specify a bogus monster as the name parameter. You'll need to define an error page routine, or replace it with one that already exists in your libraries.

      The big theme of the discussion the other night was abstraction and generality. This is a good example of abstraction. Instead of one script for each monster, we have one script that can handle all the monsters by treating them as if they were identical. By doing so we can replace 20 scripts with one script.

      Start by converting the monsters to this method. Then repeat with spell books and weapons. As you build similar scripts, you might find similarities that point to opportunities for code reuse. Even better you may be able to work on an even more abstract level and simplify your code even more.

      First and foremost, you really need to move away from the SSI "one file per page" approach. Your life will be much simpler, and your stated goal of reducing your site size will be met.


      TGI says moo

        I have been thinking hard about your approach, and I don't think it will work. However, I may not have grasped the concept, so my thinking below may be completely wrong.

        You speak of creating an "all-in-one" script; and going with your example of my monsters, it would really slow up the loading of each page. Since the menu is generated solely by the directory and file structure of the site, every "all-in-one" would have to open up the data file(s) to populate that section.

        Currently, the Monster directory has a .pl file for each monster. Those are loaded into the menu script. However, a singular Monster_aio.pl would require that Monster.csv be opened to create links to each monster akin to <a href="Monster_aio.pl?name=monster">monster</a>. For other sections, there isn't a singular data file, but a list. So, Spellbook_aio.pl would have to go to the Spellbook data directory, read all the files there, and populate the list on the menu with <a href="Spellbook_aio.pl?name=character">character</a>. I am not too keen on opening almost all of my data files or directories for every page loaded.

        Sample from menu

        <ul> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Chaos_elemental-ki +n.pl" title="Chaos elemental-kin">Chaos elemental-kin</a> </li> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Daemar.pl" title=" +Daemar">Daemar</a> </li> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Dark_centaur.pl" t +itle="Dark centaur">Dark centaur</a> </li> </ul>

        After "all-in-one"

        <ul> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Monster_aio.pl=Cha +os_elemental-kin" title="Chaos elemental-kin">Chaos elemental-kin</a> </li> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Monster_aio.pl=Dae +mar" title="Daemar">Daemar</a> </li> <li class="inactive"> <a href="http://localhost/Role_playing/Monsters/Monster_aio.pl=Dar +k_centaur" title="Dark centaur">Dark centaur</a> </li> </ul>
        Have a cookie and a very nice day!
        Lady Aleena

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://757092]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2014-10-20 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (92 votes), past polls