I have just written my first serious application that does something (considered "something" in my eyes anyways :p). After having learnt Tk for a while I got the idea of writing this GUI application that makes it easier for you to write a node in the Monastery, it makes short the process of having to manually fill in the markup elements by tag in the Monastery.
I'm aware that it has been done before but I haven't found that code in here, hence I thought this is going to be my first offering to our Dear Monastery. At the same time get advice from those who're masters in programming and who know Tk better than I do since my coding style is still evolving and requires perfection.
. Here's the thing:
Special thanks to my buddies in here who took it upon themselves to correct some of my mistakes and provide generous suggestions, esp my man ssandv, dear ELISHEVA and my look-up example Marshall.
Now to cut it short, please take a critical scan at my code and give me your feed back to some of the issues illustrated therein or to any other that you thing are relevant.
You can find my code in the link below, I made comments on the things I got stuck, and I am soliciting advice, criticism, encouragement from you all.#!/usr/local/bin/perl ###################################################################### +#################################### ###################################################################### +#################################### #This is a program that simulates some of the tasks of posting and pre +viewing a node at PerlMonks. # # I thought of making such a program for the following reasons: + # # 01-Practice the Tk module to a decent level or ma +stery. # # 02-Make a GUI that could enable Perl newbies to p +ost nodes quicker without # # using some of the deprecated tags like <pre> and. + # # 03-Participate at the Monastery by contributing s +omething that can also be used # # by everyone who wants a speedier approach to posting a node with s +ome of the following advantages: # # *The lengthoverhead of the preview button response +is minimized. # # *Minimizing the clutter of the most used tags at yo +ur personalized node dispatcher. # # *Giving an insight into the MarkUp of the Monastery + that is visualizable. # # *presenting wpl.exe to newbies and how it allows a +program to run without console. # # *Some other advantages and ideas like checking the +module availablity, strictures..etc# # 04- Improve my coding style and entertain construc +tive criticism from all. # ###################################################################### +#################################### ###################################################################### +#################################### ###Checking whether the required modules are installed + before everything else### @modules=("use Tk", "require Tk::BrowseEntry", "require Tk::DialogBox" +,"require Tk::Dialog"); foreach(@modules){ eval; if($@){ $_=~/\w+\W(\S+)/; print "Module $1 does not exist, please install it fir +st!\n"; } }; use strict; use warnings; use Tk; ## Declaring Main, side Panel, Top Panel, Text Area, p +review Area and Two menus## my ($main, $menuBar, $sideBar, $textBar,$textArea, $prevArea); my ($fileMenu, $editMenu); $main = MainWindow->new(); $main->title('PM HTML Encoder (BioHisham@gmail.com) '); $menuBar=$main->Frame()->pack(-side=>'top',-fill=>'x'); $sideBar=$main->Frame()->pack(-side=>'left', -expand=>1, -fill=>'both' +); $textBar=$main->Frame()->pack(); $fileMenu=$menuBar->Menubutton(-text=>'File', -relief=>'raised')->pack +(-side=>'left'); $editMenu=$menuBar->Menubutton(-text=>'Edit', -relief=>'raised')->pack +(-side=>'left'); $textArea=$textBar->Scrolled( #text Area, the width is not t +he default 70 like the PM's, 'Text', #because my screen width doesn +'t allow that. -scrollbars=>'ow', #the o let's the scrollbar sho +w when necessary. -width=>'50', -height=>'30' )->pack(-side=>'left'); $prevArea=$textBar->Scrolled( #preview Area. 'Text', -scrollbars=>'ow', -width=>'50', -height=>'30' )->pack(-side=>'right'); ## Populating the File menu and setting behavior + ## ## I dont know what else to place on these menus ho +wever :( ## my $exitCmd=$fileMenu->command( -label=>'exit', -accelerator=>'(Alt + F4)', -command=>sub{exit;} ); $main->bind('<Alt - F4>'=>sub{exit;}); ######################################## ### Buttons FOR: ### ### CODE, Paragraph, ### ### preview, Read More, ### ### Internal Links, ### ### External Links, ### ### Lists invocation and Preview ### ###################################### my ($codeTag, $html_var,$listTag,$readTag,$internLink, $extLink,$lineT +ag,$prevTag,$paraTag, $listButton, $resetAll); #Buttons $codeTag=$sideBar->Button( -text=> 'CODE', -relief=>'ridge', -height=> 2, -width=> 10, -command=>\&CodeIt)->pack(); $paraTag=$sideBar->Button( -text=> 'PARAGRAPH', -relief=>'ridge', -height=> 2, -width=> 10, -command=>\&ParaIt)->pack(); #$lineTag=$sideBar->Button( #this is the <br> not deployed yet # -text=>'Line Break', # -relief=>'ridge', # -height=> 2, # -width=>10, # -command=>\&LineIt # )->pack(); $readTag=$sideBar->Button( -text=> 'Read More', #Not sure I presented this the right + way though cuz it confused me -relief=> 'ridge', -height=> 2, -width=> 10, -command=>\&LinkIt )->pack(); $internLink=$sideBar->Button( -text=> 'Internal link', -relief=> 'ridge', -height=> 2, -width=> 10, -command=>\&linkIt_Intern, )->pack(); $extLink=$sideBar->Button( -text=> 'External Link', -relief=> 'ridge', -height=> 2, -width=> 10, -command=> \&linkIt_Ext, )->pack(); $listButton=$sideBar->Button( #Hitting this button casuses many i +nstances of the listBrowse widget -text=> 'list', -height=> 2, -width=> 10, -relief=> 'ridge', -command=> \&listBrowse, )->pack(); $resetAll=$sideBar->Button( -text=> 'Reset All', -height=> 3, -width=> 10, -relief=> 'groove', -background=>'white', -command=>sub{ for($textArea, $prevArea){ $_->delete('1.0','end'); } } )->pack(-fill=>'x', -expand=>'1', -side=>'bottom'); ## Since lists are either ordered or unordered + I made a BrowseEntry ### ## to show lists types upon hitting the List B +utton. ### require Tk::BrowseEntry; require Tk::DialogBox; require Tk::Dialog; my $choice="number"; #the default list item. sub listBrowse{ $listTag=$sideBar->BrowseEntry( -variable=>\$choice, -browsecmd=>\&Verify )->pack(); $listTag->insert("end","Number"); $listTag->insert("end","Bullet"); } my ($number,$listItems, $dialog, $errorDialog, $entry); $dialog=$main->DialogBox( -title=>'Enter List Length', -buttons=>['ok', 'cancel'] ); $errorDialog=$main->Dialog( #this is an error message w +hen the user enters -title=>'error', #an invalid choice in the D +ialogBox. -text=>'invalid number', -bitmap=>'error', -buttons=>['Ok'] ); $entry = $dialog->add( #adding an entry widget to th +e dialog box body. 'Entry', -width=>40, )->pack(); $prevTag=$sideBar->Button( -text=>'PREVIEW', -relief=>'ridge', -height=> 2, -width=>10, -command=> \&SeeIt, )->pack(); MainLoop; { #setting scope for $srting# sub CodeIt{ my ($string, $pos); $string = "<code>\nPlace Code Here\n</code>"; $textArea->insert('end',"$string"); } sub ParaIt{ my ($string, $pos); $string = "<p>\nenter some lines of text\n</p>"; $textArea->insert('end',"$string"); } sub SeeIt{ #this subroutine would create a temporary file to write the te +xt area content to and then #would use the temporary file as the source to write to the pr +eview area from. #N.B: I COULD NOT unlink OR delete THE TEMPORARY FILE THUS CRE +ATED AND COULDN'T HANDLE THE while #LOOP TO WORK OFF THE TEXT AREA DIRECTLY WITHOUT CREATING AN I +NTERMEDIARY CHANNEL. my (@data, $line, $filename); $html_var=$textArea->get('1.0','end'); #get the text from the +widget into a string variable. $filename="FileInputSample.tmp"; open FH, ">$filename" or die "$!"; print FH $html_var; open FH, "$filename", or die "$!"; while(@data=<FH>){ foreach $line (@data){ #This has been thorny because + one list type overrules the other. #Could not get to allow mixing + of list types. $line =~ s/(<.?code>)//; $line =~ s/(<p>|<ol>)/\n/; $line =~ s/<\/p>//; if($line =~ s/<.?ol>//){ my $i=1; map {s/<li>/"\t".$i++."-"/e} @ +data; map {s/<\/li>//} @data; }elsif($line =~ s/<.?ul>//){ map {s/<li>/"\t* "/e} + @data; map {s/<\/li>//} @data +; } #elsif } #foreach $prevArea->delete('1.0', 'end'); $prevArea->insert('1.0',"@data"); }#while close ('FH'); unlink("$filename") or die "Failed to delete the temporary fil +e $!\n"; #deleting the file } #sub LineIt{ #related to the deactivate +<br> # $string="<br>Enter a new Line"; # $pos=$textArea->index('insert'); #get current cursor positio +n # $textArea->insert("$pos","$string"); # } sub LinkIt{ #When I tested this one, I don't think I can make it + work as it should by #retracting the linked page to a mere hypertext. my ($string, $pos); $string=qq("<readmore title="Link Title Here"> Text Goes here +</readmore>"); $pos=$textArea->index('insert'); $textArea->insert("$pos","$string"); } sub linkIt_Intern{ my ($string, $pos); $string = "[Node Name or Node ID, pad: or doc: or username]"; $pos = $textArea->index('insert'); $textArea->insert("$pos","$string"); } sub linkIt_Ext{ my ($string, $pos); $string = qq([href://http://www.Site.com|Label]); $pos=$textArea->index('insert'); $textArea->insert("$pos", "$string"); } my $result; #the result from the DialogBox which can be ok or cancel. my $flag; #a flag returned to control subroutines flow. sub Verify{ #whether the choice is equal to bulltes or numbers and act acc +ordingly if($choice eq "Bullet"){ $entry->delete('0.0','end'); #reset the entry widge +t in the dialog box. my $result=$dialog->Show; #show the dialog box a +nd capture response. if($result eq "ok"){ $number=$entry->get(); #if the return value of VerifyListNumber is 1 +or 0 and acts accordingly: Bullets() if(VerifyListNumber()); +#dont go to bullets() unless flag is 1 $errorDialog->Show() if(!VerifyListNumber()); +#when the flag is 0. }elsif($result eq "cancel"){ $entry->delete('0.0','end'); return; } }elsif($choice eq "Number"){ $entry->delete('0.0','end'); my $result=$dialog->Show; if($result eq "ok"){ $number=$entry->get(); Numbers() if (VerifyListNumber()); $errorDialog->Show() if(!VerifyListNum +ber()); }elsif($result eq "cancel"){ $entry->delete('0.0','end'); return; } } } sub VerifyListNumber{ chomp $number; if($number=~/\D+/){ $flag=0; return $flag; }else{$flag=1; return $flag;} } sub Bullets{ my ($string, $pos); $listItems="<li>Enter Item</li>\n"; $string = "<ul>\n".($listItems x $number)."\n</ul>"; $pos = $textArea->index('insert'); $textArea->insert("$pos","$string"); } sub Numbers{ my ($string, $pos); $listItems="<li>Enter Item</li>\n"; $string = "<ol>\n".($listItems x $number)."\n</ol>"; $pos = $textArea->index('insert'); $textArea->insert("$pos","$string"); } }#ending the subroutines scope. # Any ideas, feedback and criticism are accepted with an open h +eart. # Thanks for your time, your efforts and your assitance. #This has been when I could come up with to the best of my abilities, +I could not simulate underlined text to #represent links to websites, I couldn't get the program distinguish m +ultiple instances of lists and operate #accordingly, there might be other bugs lurking around but I could not + unearth them for a critical eye scanning #is sharper and finer than a learner's eye.
In reply to RFC: Monastery Markup Renderer by biohisham
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |