Depends on how you test fastest. Microsoft claims IE is the fastest browser. Everyone else, and I do mean EVERYONE else says it's the slowest. So how do people test and how do they get the results they spout off?

Here's the latest - http://www.codexon.com/posts/a-real-benchmark-real-websites-with-chrome-firefox-opera-safari-ie

This test is about rendering time. It doesn't emphasize JavaScript, it shows the rendering time to load all the elements of the web page and display them. This is a test that's actually fairly even between browsers. They've all been laying out web pages for a long time and have gotten the process down pretty well. But, sure enough, IE comes in last, but it's "only" 275% slower then Safari, Chrome and Opera and only 33% slower then Firefox.

Want a little more real-world then that? Here's another speed comparison - http://lifehacker.com/5286869/lifehacker-speed-tests-safari-4-chrome-2-and-more

That one shows IE, Safari and Firefox pretty much neck and neck with page loading and has Chrome about 25% faster.

But it's the chart from Test #2 that has the numbers that start to reveal the huge performance gaps that everyone talks about. The chart that shows Chrome as 10 times faster then IE and Safari as 8 times faster.

So it's JavaScript that is the heart of the real performance differences. Here's a test that focuses on just that - http://www.tgdaily.com/index2.php?option=com_content&do_pdf=1&id=42850

And when you look at that test, you see that Chrome ranges from 33 to 3 times faster then IE and Safari ranges from 31 to 6 times faster.

When you pull it all together it boils down to this:

  • All the browsers actually perform well in general browsing.
  • Safari and Chrome are generally the fastest with Firefox trailing closely.
  • Safari and Chrome beat the pants off of IE in JavaScript performance.

Safari and Chrome (with Firefox coming along) are positioning themselves to take advantage of heavy, Javascript-rich web applications. Applications that IE simply won't be able to run. For most of today's sites, they're all pretty fast. But for the leading edge of RIA applications, IE is a slow dog.


After Apple's new laptop announcement I was curious about the price difference between Apple and Dell.  I mostly ignored the Windows vs. OS/X value proposition but equated OS/X Leopard with Vista Home Premium (not basic).

Many of the comparisons I've seen try to put dollar figures on intangibles like the value of the iLife suite against comparable Windows programs or of good design or of solid construction.  I'm not going to do that.  You can decide for yourself whether that carries any weight for you.

If you're interested in just the summary - at the low-end, Apple tends to be 10-20% more expensive then Dell for equivalent performance and features.  In addition, Dell will sell hardware that has much lower performance and features then Apple will and that end of the market is completely unserved by Apple.

Here's the results:

Apple 13" MacBook (5 lbs, 12.8"w x 1.1"h x 8.9"d)
- Starts at $999 ($920 from MacMall w/$45 mail-in rebate)
- Comes with 2.13 GHz Core 2 Duo, 3MB L2 Cache
- Comes with OS/X Leopard
- Comes with iLife 09
- Comes with camera
- Comes with 2GB DDR2 memory
- Comes with 160GB 5400 RPM hard drive
- Comes with 8x slot loading CD/DVD burner
- Comes with 55 watt hour battery
- Comes with 802.11n
- Comes with Bluetooth
- Nvidia GeForce 9400M
- Ends at $999 ($920 from MacMall w/$45 mail-in rebate) with:
- No ExpressCard slot
- No 8-in-1 media card reader
Dell Inspiron 13 (4.9 lbs, 12.5"w x 1.5"h x 9.4"d)
- Starts at $499
- +$175 2.1 GHz Core 2 Duo, 3MB L2 Cache
- +$30 Vista Home Premium
- Comes with Microsoft Works 9
- +$25 to add camera
- Comes with 2GB DDR2 memory
- Comes with 160GB 5400 RPM hard drive
- Comes with 8x slot loading CD/DVD burner
- +$30 56 watt hour battery
- +$25 802.11n
- +$25 Bluetooth
- Intel GMA X3100
- Ends at $779 with:
- Slightly slower processor
- Slightly slower memory
- Slightly smaller battery
- Much slower video
- No gigabit ethernet
- Firewire 400 but not 800
- ExpressCard slot
- 8-in-1 media card reader

Apple (through MacMall) is 15% more expensive then Dell.  That price difference ($141) buys you slightly better performance, much better graphics, a better screen and a slightly smaller case but no ExpressCard and no 8-in-1 media card reader.

The MacBook is clearly a better option for video editing, but they're both equally adept at web surfing and email.  If you live near an Apple store, you can take advantage of the free Genius bar support.  Is that worth a $141 premium?  Depends on your priorities.

Let's move up to the "premium" 13" laptops.

Apple 13" MacBook Pro (4.5 lbs, 12.8"w x 1"h x 9"d)
- Starts at $1199
- Comes with 2.26 GHz Core 2 Duo, 3MB L2 Cache
- Comes with OS/X Leopard
- Comes with iLife 09
- Comes with camera
- +$100 4GB DDR3 memory
- +$100 320GB 5400 RPM hard drive
- Comes with 8x slot loading CD/DVD burner
- Comes with 58 watt hour battery
- Comes with 802.11n
- Comes with Bluetooth
- Nvidia GeForce 9400M
- Backlit keyboard
- Ends at $1399 with:
- No ExpressCard slot
- SD card reader but no 8-in-1 media card reader
Dell XPS M1330 (4 lbs, 12.5"w x 1.4"h x 9.4"d)
- Starts at $749
- +$125 2.1 GHz Core 2 Duo, 3MB L2 Cache
- Comes with Vista Home Premium
- Comes with Microsoft Works 9
- Comes with camera
- $35 4GB DDR2 memory
- Comes with 320GB 5400 RPM hard drive
- Comes with 8x slot loading CD/DVD burner
- +$30 56 watt hour battery
- +$25 802.11n
- +$25 Bluetooth
- +$125 Nvida 8400M GS
- Ends at $1114 with:
- Slightly slower processor
- Slightly slower memory
- Slightly smaller battery
- Slower video
- No gigabit ethernet
- Firewire 400 but not 800
- No backlit keyboard
- ExpressCard slot
- 8-in-1 media card reader

Apple's price (you can't custom configure from third-party dealers) is 20% more expensive then Dell's.  That price difference ($285) buys you slightly better performance, better graphics, a better screen and a slightly smaller, aluminum case but no ExpressCard and no 8-in-1 media card reader.

The MacBook Pro is still a better option for video editing and graphics work and has a higher build quality.  If you switch the XPS M1330 to a better screen with LED backlighting the Dell gets smaller but almost halves the remaining price difference with the Mac.

Overall, what's important to understand is that the Dell's have to be upgraded to match the Apple laptops.  This isn't necessarily a knock on Dell.  Many consumers wouldn't bother upgrading their chosen laptop, they would accept the cheapest options and live with the decreased speed and functionality.  So the Inspiron 13 could be as cheap as $499 (45% less then the Mac).  For those consumers, the Mac is extremely expensive.

The difference between the two approaches is that Apple decides what the minimum, acceptable hardware performance and feature set will be for their laptops.  Dell allows customers to make that decision themselves.  For consumers looking for the cheapest computing without regard for performance, Apple doesn't provide any realistic options.  For consumers like myself, who are looking for performance and feature options, Apple is within shouting distance on price.

My first job out of college I was given a development task by my manager.  I went through the requirements and noticed that it wouldn't be possible to implement them as written.  So I gathered up my materials and walked into my manager's office.  I explained to her what the issue was and told her I couldn't complete the assignment.

She looked at me for a moment, as if expecting something more, and then said, "So how do we resolve this?"  I was taken aback.  I told her again that the requirements couldn't be implemented - as if she hadn't heard me the first time.

She looked at me for another moment and said to me, "Don't ever come into my office again with a problem until you've spent time thinking of solutions".  Her message was crystal clear.  It wasn't her job to solve my technical problems.  That's what she was paying me for.

As architects and developers it's our job to solve those technical problems and implement realistic solutions.  It's not a viable option to reach a road-block and throw up our hands.  We can't rely on anyone else to bail us out when the going gets tough.

I've taken that to heart for the entirety of my career.  That meeting with my long-ago manager was the last time I was at a loss for alternative solutions.  And it's a lesson I've attempted to pass on to others.

I've noticed again and again that's its a common problem.  Especially among developers who think of themselves as cogs in the machine.  You're not a cog.  Your job is a difficult one but you have the capacity to solve your own problems and find your own solutions.

So the next time you realize that you've reached a difficult stage and that you cannot solve it on your own, don't setup a meeting or send out an email until you've worked out some alternatives on your own.  You may not have found the final solution but you'll make it clear that you didn't just give up.  Because that approach, is unacceptable.

Find your own solutions
My first job out of college I was given a development task by my manager.  I went through the requirements and noticed that it wouldn't be possible to implement them as written.  So I gathered up my materials and walked into my manager's office.  I explained to her what the issue was and told her I couldn't complete the assignment.
She looked at me for a moment, as if expecting something more, and then said, "So how do we resolve this?"  I was taken aback.  I told her again that the requirements couldn't be implemented - as if she hadn't heard me the first time.
She looked at me for another moment and said to me, "Don't ever come into my office again with a problem until you've spent time thinking of solutions".  Her message was crystal clear.  It wasn't her job to solve my technical problems.  That's what she was paying me for.
As architects and developers it's our job to solve those technical problems and implement realistic solutions.  It's not a viable option to reach a road-block and throw up our hands.  We can't rely on anyone else to bail us out when the going gets tough.
I've taken that to heart for the entirety of my career.  That meeting with my long-ago manager was the last time I was at a loss for alternative solutions.  And it's a lesson I've attempted to pass on to others.
I've noticed again and again that's its a common problem.  Especially among developers who think of themselves as cogs in the machine.  You're not a cog.  Your job is a difficult one but you have the capacity to solve your own problems and find your own solutions.
So the next time you realize that you've reached a difficult stage and that you cannot solve it on your own, don't setup a meeting or send out an email until you've worked out some alternatives on your own.  You may not have found the final solution but you'll make it clear that you didn't just give up.  Because that approach, is unacceptable.

Ok, I'm kidding about the lazy part.

But here's an interesting open source tool - Cucumber. It's a Behavior Driven Development (BDD) testing framework.

You write the test scripts in plain language:

Feature: Search courses
In order to ensure better utilization of courses
Potential students should be able to search for courses
Scenario: Search by topic
Given there are 240 courses which do not have the topic "biology"
And there are 3 courses A,B,C that each have "biology" as one of the topics
When I search for "biology"
Then I should see the following courses:
| title |
| A |
| B |
| C |

And then interpret them using test code:

Given /there are (.*) courses which do not have the topic "(.*)"/ do |num_courses, topic_name|
 ... write the code to get the number of courses without the topic and verify the number...
end
 
Given /there are (.*) courses (.*) that each have "(.*)" as one of the topics/ do |num_courses, course_names, topic_name|
 ... write the code to check this one too...
end
 
When /I search for "(.*)"/ do |topic_name|
 ... search for the topic name and save the list of courses ...
end
 
Then /I should see the following courses/ do |table|
 ... check that the saved list of courses matches the data in the table...
end

The idea is to let the tests describe the behavior of the system and then code to fulfill the tests. Cucumber is written in Ruby and so are the tests. But it runs on JRuby and on IronRuby so it can be used to test Java code and .Net code.

I develop by some general principles. One of the strongest is "generous on input, strict on output". This means that the code should be tolerant of variations in it's input but should be strictly correct when outputting data. This ranges from the small to the large.

As an example, when you accept a boolean as a string, ignore the case and allow it to be expressed as "1, 0, T, F, Y, N, TRUE, FALSE, YES, NO, etc.". If it's not anything you're prepared to see, assume it's false. But when outputting a boolean as a string, stick to one single convention and one single case religiously.

When you parse a custom format file, assume fields might be left out, or that they may be malformed. Attempt to "do the right thing" with the values you do get and set sane defaults.

Do you do this in every single routine throughout your code? No, you do it at the boundaries. But those boundaries can be hard to see. If you're writing a Java library, you do it at the published interface points. If you're writing PL/SQL packages, you do it on the non-local procedures and functions. If you're writing anything that reads from the network or a file, that's a boundary point. Anywhere your code will reasonably connect to code you didn't write and data you didn't create, is a boundary.

There's another name for this: code defensively.

Assume the other programmers are wild anarchists who revel in destroying your code. Assume they don't read your documentation and will call your routines simply by guessing what the parameters mean. Because that's exactly what will happen.

This approach will save you a ridiculous amount of time dealing with defects both subtle and obvious.

But there's a flip side to this. It's called failing fast. You should attempt to be lenient with what your code accepts, but when basic requirements are validated, you should fail fast and clearly. Is that parameter absolutely required and can never be null? Test it right at the start and throw an exception that explains exactly what was wrong with the input. Don't let the null percolate through the code until it causes a problem.

With these two techniques you'll find that consumers of your code will have an easier time. You'll find fewer defects raised. And you'll find that your own maintenance of your code will be easier.


We accomplish tasks. We get things done. We meet schedules and check off boxes on requirements lists. We implement features and run tests.

It doesn't have to look pretty. It doesn't have to be polished to a high sheen. It has to be professional and correct.

This is how you mark off requirements and move forward. This is how you check the box next to features. This is how you get things done.

But what would it be like if you could make it as perfect as you could? What would it be like if you tried to polish it? How would it feel if the client said making it right was better then just making it?

Let's use cell phones as an example.

Any idiot can do cut and paste. It's in Windows. It's in Linux. It's in OS/X. It's on smart phones from every vendor. It's basic.

And it's not (yet) on the iPhone.

How can they be so bad at their jobs that they can't implement such a trivial feature? Because they tried to get it right. Not done. Done right.

Stack an iPhone against an Android. The iPhone loses on features. It will probably always lose on features.

Where's email search? The Blackberry has it. What a rip. Look at Apple using hype to sell a sub-standard product. Search is basic. Put a box at the top of the mail program and index the mail. How hard is that?

Whenever something doesn't make sense it helps to step back and ask the question - why? Why isn't something as basic as cut and paste already done? Why isn't mail search, something so simple, already done?

Because the implementers don't feel the standard paradigms are good enough. They don't want to just get it done. They want to get it done right.

This isn't an approach that Apple has invented. You can see it in many places. You can see it in Microsoft's UI refresh of Office. You can see it in the Web 2.0 sites that focus on usability over feature set. You can quibble with the chosen solutions. Maybe they're not your cup of tea. Maybe you don't even see the benefit of spending the time and effort to find a better solution.

I've been down both paths. And I can tell you which one I prefer. Elegance over junk. Simplicity over complexity. Thoughtfulness over thoughtlessness.

Hopefully it's not just me.


Mac's like their inexplicable keyboard symbols. Mac documentation, both for Apple software and third-party software make heavy use of keyboard symbols and often don't take time to explain them. It takes a little hunting around to find what the characters mean.

Keyboard keys are the first, biggest stumbling block when switching to a Mac from Windows or Linux. Especially on a laptop keyboard where keys you expect to see, like backspace and dedicated home and end keys simpler aren't there. You don't realize how strongly ingrained ctrl-c/ctrl-v are, until you have to switch to command-c/command-v.

Symbol Unicode Purpose
2318 Command key. Sometimes the key has an Apple symbol on it as well. If you're coming from Windows or Linux, this acts like the control key does on those operating systems. Copy and paste use the command key. This is one of the biggest adjustments coming from another platform. It's also what trips you up when moving between operating systems.
2335 Option key. Sometimes the key has the option symbol, sometimes it has the word 'option' and sometimes it has 'alt' on it. If you're coming from Windows or Linux, this acts like the alt key.
2303 Control key. This acts like a normal control key, but, if you're coming from Windows or Linux, it loses its special meaning for copy and paste commands. This is actually useful in terminal windows since the Mac copy and paste doesn't conflict with the terminal ctrl-c.
21e7 The shift key. Usually labeled shift.
21a9 The return key. Works just like you expect.
2305 The enter key. Mac's have both a return key and an enter key. Confusingly, the return key is also often labeled as an enter key. The enter key is the small one. Some applications give the enter key special meanings that differ from return.
232b Delete key. Another hard one to adjust to from other operating systems. The Mac delete key works like backspace in Windows and Linux. The forward delete is what most people expect from this key.
2326 The forward delete. What people on other operating systems think the delete key is.
238b Escape key. Often labeled 'esc' on the keyboard. The most confusing part of this is the symbol, I can never remember what it is at first glance.
23cf Eject key. Used to eject cd's and dvd's from the drive.
2196 The home key. Smaller keyboards don't have this as a dedicated key. The left arrow needs to be combined with the command key to make home.
2198 The end key. Same as with home. Smaller keyboards need to do command-left arrow to get end.


In case you didn't follow the Apple earnings call last night (which I'm ashamed to say I did), you might have missed the news (reported everywhere) that Apple just had their best second quarter in their history. That's in the midst of a horrible recession. Everything was roses for Apple in all but one category - Mac sales were down 3%. That's against an industry backdrop of a 7% drop in sales. But it's still a drop. When asked about it, Apple said the consumer space was doing great for them (read, MacBooks) but the professional and educational space was down. So, personal purchases haven't been affected by the recession, but company/government spending is down.

If Mac sales are down, how was this the best Apple second quarter ever? The iPhone and the iPod Touch. They're selling like hot cakes all around the world. In the next few days the App Store will have it's 1 billionth app download. In seven months. In the last few weeks there have been blog postings from PSP game development companies to small mobile app development companies talking about iPhone development. All of them in glowing terms. Apparently, compared to development for Nokia, BlackBerry, Nintendo DS and Sony PSP, the iPhone/iPod Touch is a dream.

Is it all peaches and cream? No, Android is a serious competitor. It's much more open then the iPhone platform but has been limited by carrier and equipment. That should be changing over the next year. And the much-hyped Palm Pre will be coming out soon. Advanced press on that device has been very good.

But, to throw another complexity into the mix, the next generation of the iPhone is expected in June, together with the iPhone 3.0 release. That release is set to bring:

  • Full Bluetooth access (phone to phone gaming w/o wifi, transfer of business cards, documents, etc.)
  • Voice recognition
  • Full GPS access (turn-by-turn driving applications from folks like TomTom running on your phone)
  • Micro payments within applications (this has huge potential)
  • Push notifications
  • Full external accessory access (control accessories connected to the iPhone port, e.g., insulin tester)
  • Interface improvements (cut and paste, full content searching, MMS, app integrated email, data detectors everywhere, video recording, etc.)

And the next generation hardware will (supposedly) have video hardware that is significantly better then the current model together with an improved camera and a magnetometer (compass).

And that's with only 21 million sold. So, as this article points out - http://www.techcrunch.com/2009/04/23/the-state-of-the-iphone-is-strong-very-strong/ - the state of the iPhone is very strong.


I've been asked by multiple people what I think of the acquisition of Sun by Oracle. I've assembled my thoughts on the matter. I don't have any particular insight, just a general experience with Oracle. And all of this is subject to the deal being completed sometime in the summer.

Oracle is now a hardware company. They own SPARC servers, Intel servers, data centers in a box and storage servers. My guess is they will sell the hardware business as multiple businesses. The SPARC business to Fujitsu. The Intel servers might go to Cisco (to bolster their new business), IBM or Dell. The storage servers might go to IBM or another storage business. The data centers in a box? No idea. Maybe IBM.

Now the software side, which is overall a more understandable fit for Oracle.

Oracle is a big Linux supporter. They sell Linux. They're also driving the next generation file system in Linux, btrfs. Oracle now owns Solaris which comes with ZFS and DTrace. My guess is they'll GPL ZFS and DTrace, pull in the cream of the engineering staff for Solaris and continue the support contracts for Solaris. Will they GPL Solaris as a whole? Probably.

Oracle now owns Java. I have no idea what they'll do with that. They'll probably continue with the support contracts and JME licensing agreements. They might open up the remainder of the licensing for Java, resolving the last remaining issue with the TCK (they voted that way in the past). But that will eat into their JME licensing (which is supposedly why Sun didn't follow through on this). My guess is that they'll open the TCK anyway.

Oracle now own OpenOffice. Oracle has never had an office suite. Do they want it? No idea. I think they'll probably open the development process up.

JavaFX? I can't see it surviving. I think Oracle will cancel it.

Oracle now own NetBeans. They already own JDeveloper which is a truly mediocre IDE and they are huge supporters of Eclipse. I think NetBeans will get canceled. And SunStudio? Maintenance mode.

Oracle owns OAS and WebLogic. GlassFish? Canceled.

MySQL? MySQL is eating into Oracle from the bottom end to a small extent. Oracle already owned one of the data engines in MySQL. They'll probably look at this as an upsale area. Throw MySQL primarily into maintenance mode, sell licensing and support for the bottom end and have their sales team try to upsell to Oracle DB. They will probably restrict further development of high-end replication features.

VirtualBox? Oracle is a Xen shop. Maybe they'll merge the teams but I doubt it. VirtualBox is more of a consumer product right now. Not sure what Oracle will do with it.

Q-Layer? This will get used by Oracle. Q-Layer already makes use of Xen and fits pretty well with what Oracle is already doing.

Identity Manager? Moved into the Oracle stack.

Web Server/Web proxy? Maintenance.


As I continue my attempts to increase my daily efficiency, I wanted to be able to post tweets through LaunchBar. There are numerous scripts that accomplish this. I found one that was almost what I was looking for.1 The only thing missing was the ability to automatically shorten URLs. You can find the resulting script here.

The previous authors worked their magic so that the script has the features:

  • Warns if the tweet message is over 140 characters
  • Escapes the message so it's safe to send
  • Outputs Growl notification on success and on error
  • Pulls authentication information from the OS/X keychain

The authentication is taken from the last user id and password provided when accessing twitter.com.

A caveat: this script won't work for you if you use multiple Twitter accounts.

 
--   This script was put together with the help of the following sources:
--   http://blog.codahale.com/2007/01/15/tweet-twitter-quicksilver/ by Coda Hale
--   http://i.grahamenglish.net/540/iquicktwitter-my-quicksilver-twitter-ichat-growl-hack/ by Graham English
--   http://www.leancrew.com/all-this/2009/02/url-shortening-scripts-fixed-i-think/ by @drdrang (fix for &ampersand issues)
--   put together and adapted by @ptujec to work with LaunchBar
--   minor changes to convert urls to tiny versions by @ctwise (http://tedwise.com)
-----------------------------------------------------------------------   
 
-- take string from LaunchBar
on handle_string(tweet)
	 -- shorten urls
	 set tweet to replace_http(tweet) 
 
	 -- do wordcount
	 set wordcount to do shell script "echo " & quoted form of tweet & " | wc -c"
	 set wordcount to do shell script "echo " & quoted form of wordcount & " | sed 's/^[     ]*//'" 
 
	 if wordcount as integer > 140 then
		 -- notify when tweet contains more than 140 characters
		 my growlRegister()
		 growlNotify("Tweet too long", "(" & wordcount & ") characters")
		 return nothing
	 end if 
 
	 --do tweetescape
	 set tweet_new to tweetescape(tweet) 
 
	 -- take logininformation from keychain
	 tell application "Keychain Scripting"
		 set twitter_key to first Internet key of current keychain whose server is "twitter.com"
		 set twitter_login to quoted form of (account of twitter_key & ":" & password of twitter_key)
	 end tell 
 
	 -- update twitter
	 set twitter_status to quoted form of ("source=launchbarat&status=" & tweet_new)
	 set results to do shell script "curl --user " & twitter_login & " --data-binary " & twitter_status & " http://twitter.com/statuses/update.json" 
 
	 -- display dialog results
	 my growlRegister()
	 -- you can change "Tweet" into a diffent text e.g. "Zwitscher"
	 growlNotify("Tweet", tweet)
end handle_string 
 
-- fix for &ampersand issues (by @drdrang)
on tweetescape(tweet)
	 set cmd to "
from urllib import quote
print quote(\"\"\"" & tweet & "\"\"\", \"/:\")
"
	 return (do shell script "python -c " & (quoted form of cmd))
end tweetescape 
 
-- additional scripting for Growlnotification
using terms from application "GrowlHelperApp"
	 on growlRegister()
		 tell application "GrowlHelperApp"
			 register as application "Tweet" all notifications {"Alert"} default notifications {"Alert"} icon of application "Launchbar.app"
		 end tell
	 end growlRegister
	 on growlNotify(grrTitle, grrDescription)
		 tell application "GrowlHelperApp"
			 notify with name "Alert" title grrTitle description grrDescription application name "Tweet"
		 end tell
	 end growlNotify
end using terms from 
 
-- This uses the built in splitting in AppleScript.
-- Most of the code just restores the delimiters.
on split(theText, splitText)
	 set tid to AppleScript's text item delimiters
	 set AppleScript's text item delimiters to splitText
	 set theTextItems to text items of theText
	 set AppleScript's text item delimiters to tid
	 return theTextItems
end split 
 
-- I tried the opposite of the split implementation but for some
-- reason it doesn't work reliably
on join(theList, joinText)
	 set result to ""
	 repeat with theToken in theList
		 if length of result = 0 then
			 set result to theToken
		 else
			 set result to result & joinText & theToken
		 end if
	 end repeat
	 return result
end join 
 
-- Send the url to tiny url for shortening
on shorten_url(theURL)
	 set theURL to tweetescape(theURL)
	 set results to do shell script "curl   http://tinyurl.com/api-create.php?url=" & theURL
	 return results
end shorten_url 
 
-- Find everything that looks like a URL and shorten it
-- The number 25 is the length of a tiny url, no point in
-- shortening a url if it's already below that.
on replace_http(theText)
	 set tokens to split(theText, " ")
	 set output to {}
	 repeat with theToken in tokens
		 if (theToken starts with "http://") and length of theToken > 25 then
			 set the end of output to shorten_url(theToken)
		 else
			 set the end of output to theToken
		 end if
	 end repeat
	 return join(output, " ")
end replace_http
 


Next Page »