Sunday, December 13, 2009

Christmas party

My company Christmas party was Friday night. I wore a gray shirt and red tie. I'm documenting it here so I don't wear the exact same thing next year. Good day.

Sunday, November 1, 2009

The Next Level of Bible Study

It occurred to me while working on the Logos iPhone app that there have been a number of technologic breakthroughs over the last few thousand years that have been transformative in how they advance the study of scripture.
  • Translation of the Bible into one's own language.
  • Printing of the Bible providing a cheap, portable copy.
  • Computerization of the Bible, indexing for search and linking to other resources.
I think now we have reached the next level of Bible study tooling. With the Logos iPhone app you have a mobile library that fits in your pocket. There many different translations of the Bible, original language texts, reverse interlinears and text comparisons. There are help resources such as dictionaries, commentaries, charts and maps. Everything is cross referenced. Everything is indexed for nearly instantaneous search. Because it is an Internet-based application, it is virtually infinitely expandable.

Think about that for a minute. In my pocket, right now, is a device that provides me a virtually infinite amount of information useful for Bible study, presented in an easy to use, organized manner. It blew my mind a little bit when I realized that.

I think the Logos iPhone app represents the next technological breakthrough that takes Bible study to another level. But at Logos, we're never satisfied. Wait until you see how we can use these tools to help people not only more and better Bible study, but also also help people do more of it together.

We got the Logos iPhone app through on the first try

I didn't expect it to happen, but Logos Bible Software for the iPhone was accepted 15 days after the first submission. Woo hoo! Find it in the App Store. It's FREE. We already have an update in the works that will fix a few annoyances and we'll be submitting that soon.

Logos Bible

Wednesday, August 5, 2009

Detecting a swipe in WebKit

I was a bit surprised that there wasn't a built-in swipe event for iPhone web apps or an easy to find library to detect one, so I wrote one based on the Mobile Safari documentation.

You may need to tweak the vertical threshold (15) or horizontal threshold (50).


/**
* You can identify a swipe gesture as follows:
* 1. Begin gesture if you receive a touchstart event containing one target touch.
* 2. Abort gesture if, at any time, you receive an event with >1 touches.
* 3. Continue gesture if you receive a touchmove event mostly in the x-direction.
* 4. Abort gesture if you receive a touchmove event mostly the y-direction.
* 5. End gesture if you receive a touchend event.
*
* @author Dave Dunkin
* @copyright public domain
*/
function addSwipeListener(el, listener)
{
var startX;
var dx;
var direction;

function cancelTouch()
{
el.removeEventListener('touchmove', onTouchMove);
el.removeEventListener('touchend', onTouchEnd);
startX = null;
startY = null;
direction = null;
}

function onTouchMove(e)
{
if (e.touches.length > 1)
{
cancelTouch();
}
else
{
dx = e.touches[0].pageX - startX;
var dy = e.touches[0].pageY - startY;
if (direction == null)
{
direction = dx;
e.preventDefault();
}
else if ((direction < 0 && dx > 0) || (direction > 0 && dx < 0) || Math.abs(dy) > 15)
{
cancelTouch();
}
}
}

function onTouchEnd(e)
{
cancelTouch();
if (Math.abs(dx) > 50)
{
listener({ target: el, direction: dx > 0 ? 'right' : 'left' });
}
}

function onTouchStart(e)
{
if (e.touches.length == 1)
{
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
el.addEventListener('touchmove', onTouchMove, false);
el.addEventListener('touchend', onTouchEnd, false);
}
}

el.addEventListener('touchstart', onTouchStart, false);
}



Use it like this:

addSwipeListener(document.body, function(e) { alert(e.direction); });

Friday, July 10, 2009

Thursday, July 2, 2009

Logos Bible Giveaway

Logos is giving away some nice dead-tree Bibles to promote the coal-powered Bible website I've been very involved with.

Here are the details:

Logos Bible Software is celebrating the launch of their new online Bible by giving away 72 ultra-premium print Bibles at a rate of 12 per month for six months. The Bible giveaway is being held at Bible.Logos.com and you can get up to five different entries each month! After you enter, be sure to check out Logos and see how it can revolutionize your Bible study.

Wednesday, April 29, 2009

Global Search and Replace with Perl

I've used this article for reference many times before, but it is no longer available. I've reproduced it from an archive.org copy.

(source: http://hacks.oreilly.com/pub/h/73)



There are a couple of switches that make Perl a very useful command-line editing tool. Learn these switches, and you too can learn how to mumble magic Perl one-liners to confound your friends (and frighten your project manager).

The first is -e. Give Perl a -e followed by a line of code, and it will run it as if it were an ordinary Perl script:

rob@catlin:~$ perl -e 'print "Hi, Ma!\n"' 
Hi, Ma!


Note that a trailing ; isn't needed on one-liners. It's generally a good idea to wrap your line in single quotes to prevent the shell from attempting to interpret special characters (like the ! and \ above).

The next switch is a little more complicated, it but becomes second nature once you start using it: -p. From perldoc perlrun:

-p causes Perl to assume the following loop around your
program, which makes it iterate over filename arguments somewhat like sed:

LINE:
while (<>) {
... # your program goes here
} continue {
print or die "-p destination: $!\n";
}


The line in question ($_) is automatically printed on every iteration of the loop. If you combine -p and -e, you get a one-liner that iterates over every file on the command line or on the text fed to it on STDIN. For example, here's a complicated cat command:

rob@catlin:~$ perl -pe 1 /etc/hosts 
#
# hosts This file describes a number of hostname-to-address
# mappings for the TCP/IP subsystem.
#

# For loopbacking.
127.0.0.1 localhost


The 1 is just a return code (as if you entered 1; in a Perl script, which is equivalent to return 1;). Since the lines are printed automatically, we don't really need the program we specify with -e to do anything.

Where it gets interesting is in providing a bit of code to manipulate the current line before it gets printed. For example, suppose you wanted to append the local machine name to the localhost line:

rob@catlin:~$ perl -pe 's/localhost/localhost $ENV{HOSTNAME}/' /etc/hosts 
#
# hosts This file describes a number of hostname-to-address
# mappings for the TCP/IP subsystem.
#

# For loopbacking.
127.0.0.1 localhost catlin.nocat.net


or maybe you'd like to manipulate your inetd settings:

rob@caligula:~$ perl -pe 's/^(\s+)?(telnet|shell|login|exec)/# $2/' \  /etc/inetd.conf


That will print the contents of /etc/inetd.conf to STDOUT, commenting out any uncommented telnet, shell, login, or exec lines along the way. Naturally, we could redirect that back out to a file, but if we just want to edit a file in place, there's a better way: the -i switch.

-i lets you edit files in place. So, to comment out all of the above lines in /etc/inetd.conf, you might try:

root@catlin:~# perl -pi -e 's/^(\s+)?(telnet|shell|login|exec)/# $2/' /etc/inetd.conf


or better yet:

root@catlin:~# perl -pi.orig -e 's/^(\s+)?(telnet|shell|login|exec)/# $2/' /etc/inetd.conf


The second example will backup /etc/inetd.conf to /etc/inetd.conf.orig before changing the original. Don't forget to HUP inetd to make your changes take.

It's just as easy to edit multiple files in place at the same time. You can specify any number of files (or wildcards) on the command line:

rob@catlin:~$ perl -pi.bak -e 's/bgcolor=#ffffff/bgcolor=#000000/i' *.html


This will change the background color of all html pages in the current directory from white to black. Don't forget that trailing i to make the match case insensitive (to match bgcolor=#FFFFFF or even BGColor=#FfFffF).

What if you're in the middle of working on a CVS project, and need to change the CVS server that you'd like to commit to? It's easy, if you pipe the output of a find through an xargs running a perl -pi -e:

schuyler@ganesh:~/nocat$ find -name Root | xargs perl -pi -e 
's/cvs.oldserver.com/cvs.newserver.org/g'


Then reset your $CVSROOT and do your CVS check in as normal, and your project will automagically end up checked into cvs.newserver.org.

Using Perl from the command line can help you do some powerful transformations on the fly. Study your regular expressions, and use it wisely, and it can save piles of hand edits.

Thursday, April 23, 2009

Do you chew gum you find on the street?

I came across this the other day and found it quite amusing and very true:
Scott's Rule of Programming - Rule# 0x3eA
Just because code is on the Internet doesn't mean you should cut and paste it into your production system. Do you chew gum you find on the street? Give code you find on the 'NET the same amount of attention you'd give advice scrawled on a public bathroom wall.
-- Scott Hanselman

Wednesday, April 22, 2009

Adventures in parenting

Frustrated because my coffee and oatmeal were now quite cold and my daughter (6 months) would not let me put her down, I turned to my son (21 months) and said, "Ugh! Why does your sister require constant attention?" He replied, "baby sorry, baby sorry."

Monday, March 2, 2009

Verse of the day

If a man loudly blesses his neighbor early in the morning,
it will be taken as a curse.

Proverbs 27:14 (NIV)

Wednesday, January 28, 2009

Quote of the day

Walter Williams says that by taking money out of the private sector to stimulate the economy, Congress is "taking buckets of water from the deep end of a swimming pool and dumping them into the shallow end in an attempt to make it deeper."

Friday, January 16, 2009

Memory Management != Resource Management

On Jeff Atwood's blog, in a post about garbage collection and modern programming languages he states "I view explicit disposal as more of an optimization than anything else." I think it is a mistake to take this point of view. In modern languages we use objects to represent system resources in addition to just data. In those situations it isn't good enough to just let the garbage collector clean up after you.

I can't count the number of times I've come across bugs that were the result of a developer assuming the garbage collector would close a file handle for him and that code failing randomly because the garbage collector hadn't run yet and file was locked. For example, I've seen a lot of Java methods that open a FileInputStream, read all the data, and return without closing the stream.

Garbage collection is great for memory management because it doesn't usually matter when memory is freed. Other system resources, on the other hand, usually need to be freed deterministically. The Disposable pattern handles this situation pretty well.