Perl is like using a hand saw

I love Perl. I really do. But it's been six years since I used it with any frequency, and re-learning it is a pain in the ... well, it's a pain.
I spent the better part of today writing a Perl program with the simple task (ha) of taking a raw text file of the Bible and converting it into something that iBible can use.
It's like re-learning a language that is somewhat familiar but not.
Anyway, I finally got it to work after nearly destroying my computer with a fist.
Creating a flexible data model
Let's say you're writing a program to access and read the Bible. Let's just say.
Sounds simple (and it is simple, by the way, no matter what programming language and IDE you're using). The hard part is making it useful for the end user. Anyone can program a Bible reader. It was one of the first things I ever did.
It's as simple as opening up a Bible text, dumping the text into a dictionary (or associative array, depending on what language you're using) and then referring to that array by number to retrieve the chapter or verse you're looking for.
For some end users, that's all they need. Hooray. You're done.
But let's just say you wanted your program to be a bit more flexible and thus useful. For instance, say you wanted your text to have notations based on specific words in specific verses (I'm thinking of Strong's numbers here. For the uninitiated, Strong's numbers are number-coded references to specific words in the Bible. If you look up the numbers in the Strong's Dictionary, they give you a Greek or Hebrew definition for the English word the code refers to).
iBible versions 1 through 2.7 did that. Easy enough, but clunky as all get-out. You basically had to open a new window with a completely different text of the Bible that had the numbers in parentheses next to the words they represented. Double-click a number and the Greek or Hebrew definitions popped up on the screen. Effective, but essentially a kludge and I'm not proud of it.
There are more elegant ways to do it, and Core Data allows us to explore those ways. Here's the data model for iBible 3 (so far):

I've had to consider that my end users might want to use other versed text besides the Bible in their program. That means I can't call the main dataform "Bible." I also can't call the sections "Books", because though that's a perfectly reasonable Bible convention, it's not always the case in other versed text. Same for "Chapters," which I call sub-sections, and verses, which I call paragraphs. For instance, Genesis 1:1 is a descendent of three things: Tome (Bible), Section (Genesis), Sub-section (Chapter 1). And it is Paragraph 1 of Tome, Section and Subsection.
If I want to be flexible with my text, I need to abstract it as much as possible from my understanding of what a Bible should be. And that's not just a concession to non-Biblical texts. Some versions of the Bible use different book names, different chapter numbers and different verse numbers. If I'm rigidly stuck to 66 books, X number of chapters per given book, I can no longer have my program easily read other versions of the Bible than the one for which I specifically programmed it.
In addition, if I want my notes to work (Strong's, etc), then I have to let them determine which parts of the Tome they work on and which parts they don't. Otherwise I'll have to spend hours programming for EACH new kind of note, and the idea is to make iBible 3 very flexible - able to accept notes and texts I haven't even dreamed of.
Core Data: Jeesh!
Working on iBible 3, and I'm using a framework from Apple called Core Data. Long story short, it makes the handling of data in an application a lot smoother and simpler, but the learning curve is high.
Since I started programming (back with BASIC, then Perl. Get off my lawn, you!) reading data from disk and writing it back to disk used some sort of hand-coded I/O, meaning I had to write code to open a file, read the contents of the file, parse the contents and then stash it away somewhere where the program could use it (and the inverse process to save data to a file).
Core Data basically handles the heavy lifting of that stuff so I can concentrate on the rest of the program. That's good and bad. It's good because I would much rather concentrate on the rest of the program. It's bad because I have to learn how to use Core Data and all of the tutorials on the Internet are CRAP!
There. I said it.
I'm thinking that, as I learn Core Data, I'm going to post about it here, breaking down the jargon (oh, is it ever loaded with jargon) and explaining it so a person can scale the wall of the castle of Core Data without having to learn magic and fly over.
Reboot: iBible
So I haven't touched iBible since 2003. That's right; seven years. Initially, I wrote iBible in RealBasic because RealBasic offered an IDE that compiled applications for both Classic and OS X platforms. If you have no idea what I'm talking about, nevermind. It's not important. I just felt like I needed to justify why I did it.
I hated RealBasic with a passion. It was clunky, and if you wanted your application to do anything REALLY cool, you had to use a kludge or three thousand. The point is, the code was ugly, it was difficult to maintain and a pain to mess with overall.
So after I had a fairly good set of features, I lost my motivation to work on it.
Fast-forward to today, seven years after I wrote the last line of code for iBible (a program that people are STILL downloading and registering to this day). I have a LOT of ideas for a new version that is faster, more stable, and more importantly, native to OS X - and to the iPhone and iPad. In fact, without tipping my hand here, I have some ideas that are revolutionary, and I'm starting now on recoding iBible from scratch.
Here's some of the stuff I can say: iBible 3 will have:
- The ability to read any versed text. That means it will read any version of the Bible, plus it could potentially read other texts such as the Koran, the Book of Mormon or poetry arranged into numbered chapters and verses.
- The ability to associate notes with that text. That means the Bible could use Strong's definitions for words, the Thompson Chain Reference for deeper study, Matthew Henry's Complete Commentary on the Bible and basically any commentary ever written for whatever text you're using.
- User notes. You can comment on any part of the Bible you want, and your notes will stay around. For instance, in my church, when I preach a sermon on a certain range of scripture, I can now associate a note with that range of scripture and save the sermon there forever.
There is a LOT more, but that's all I can say without tipping my hand too much, because some of what I'm doing has been done in NO other Bible program out there. Like the beginning of iBible, I'm adding stuff that I need and have always needed, but couldn't find a program to do it.
Stay with me, I'm hot and heavy on this one.
Date fun
I found early on, back when I was programming with Perl, that dealing with dates is a pain in the ass.
It has to do largely with our calendar system, which is screwed royally because of leap years, short months, etc.
So when I needed to detect if one item was older than the other, I came across the idea that server time doesn't really care what day it is, it just cares how much time has elapsed since a certain date.
That said, the rest was easy (this code is in php):
function dateIsCurrent($expiration_date){
if( strtotime($expiration_date) > time() ){
return true;
} else {
return false;
}
}
The function requires one argument (a date). strtotime is a PHP function that converts a supplied date into time, which is essentially a number of seconds. the function compares that time with the current time, and if it's greater than the current time, it returns true, meaning the supplied date is current. Otherwise, it returns false, because the current time is greater than the supplied time (meaning more seconds have passed in current time than in the time of the date that is supplied - or it's later now than it was in the date you supplied this function). Enjoy.
The way to call it is also simple:
if ($dateIsCurrent(2010-05-03) {
//do something
}
Detecting browser in php for css
In designing websites, I've discovered that the old problems with Internet Explorer are still around, mainly that you can code a beautiful website only to discover that Internet Explorer doesn't support the coolest things you've done.
The reasons behind this are multiple, but the short version is that Microsoft wanted to own the Internet, so it refused to participate in Web standards by having their browser support them, forcing webpage designers to make concessions for Internet Explorer when they designed. The hope was that they'd just throw up their hands, use Internet Explorer's proprietary coding and eventually everyone would have to use Internet Explorer (and Windows) if they wanted to surf the Web.
But that backfired, and Internet Explorer is losing Web presence daily. That said, the newest Web standards are unevenly implemented across browsers, with Safari being the only browser I've found so far that actually implements CSS3 properly. The problem is, JavaScripts designed to detect browsers are woefully out of date and oftentimes provide wrong information, meaning you have to put in a boatload of effort to code a page to detect which browser you're using, and then it's tough to implement whatever changes you make throughout the page.
This stuck out like a sore thumb on one of the latest sites I was coding, Square Deal Music, for which I had coded all sorts of cool stuff, including gradient overlays in the div containers, which were not supported on Firefox, I discovered to my chagrin. That means Firefox users would see my dark text against a dark background, making it quite difficult to read - and ugly to boot.
So Friday I came up with a solution: I would code one CSS stylesheet for Safari (which adheres completely to Web standards) and another for every other browser. Then, in php, I would detect the browser and print the link for the correct stylesheet based on which browser was being used:
if ( strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') ){
$Safari = TRUE;
echo "<link rel=\"stylesheet\" href=\"Safari.css\">";
} else {
$Safari = FALSE;
echo "<link rel=\"stylesheet\" href=\"BadBrowser.css\">";
}
strpos returns the position of the quoted string in the passed string. If the string does not exist inside the larger string, it returns FALSE, which is why I use it here as kind of a poor man's grep or regex. I'm just testing to see if the string "Safari" exists in the user-agent field the HTTP server passes to php.
A bonus of this approach is the $Safari variable is then available through the rest of the page so I can implement all sorts of things, like popping up a div to alert the viewer that they can download a free browser to see the site as it was intended. Like this:
if ($Safari == FALSE) {
echo "<div class=\"badbrowser\"><h2>BAD BROWSER! You are viewing a crippled version of this site because your browser is not standards-compliant. Download <a href=http://apple.com/safari>Safari</a> for free and you can see this site as it was intended.</h2></div>";
}
Fun, eh?