2718.us blog » Programming http://2718.us/blog Miscellaneous Technological Geekery Tue, 18 May 2010 02:42:55 +0000 en hourly 1 http://wordpress.org/?v=3.0.4 MacWJ: It’s like Windows Journal for Tablet Macs http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/ http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/#comments Fri, 07 May 2010 09:59:44 +0000 2718.us http://2718.us/blog/?p=263 MacWJ… because there are oh-so-many tablet Macs.  There are ModBooks and there are non-Apple tablet machines running Mac OS X.  So, if you have such a device and are looking for something that provides a surface on which to draw, write, etc., with various “pens” and with the ability to save to PDF and PNG, MacWJ may be of use to you. It’s open-source under MIT license.

MacWJ requires OS X 10.5 or newer and some sort of tablet-pen input, whether a tablet-form computer or a Wacom graphics tablet or something else of that sort.  Ready-to-run recent build(s) are available on bitbucket, as well as the full source code.

]]>
http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/feed/ 0
Simplifying the Assembly of Localizations in Xcode http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/ http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/#comments Thu, 22 Apr 2010 20:11:51 +0000 2718.us http://2718.us/blog/?p=254 A comment on a bitbucket fork of Murky led me to “Automatically localize your nibs when building“, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode–pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, because I cannot adequately explain the big-picture part of the idea with a short quote.

My one complaint with the setup described is that the script for the “Run Script” build phase described there is a maintenance headache that I could do without.  Here’s my solution:  Create two new build targets, both of the “Shell Script” type–these are targets that just run a shell script, so they are created with only a “Run Script” build phase.  I called my two new targets “Create/Update English .strings files” and “Create/Update l10n XIBs” but you can call them whatever you want.

In the “Create/Update English .strings files” target’s “Run Script” phase, the script is:

# Create/Update English .strings files
  1. for xibFile in "$PROJECT_DIR/English.lproj/"*.xib; do
  2.  ibtool –generate-strings-file "${xibFile}.strings" "$xibFile"
  3. done
  4. exit 0

This uses ibtool to create a strings file for every XIB in the English localization (from foo.xib, foo.xib.strings will be created).

In the “Create/Update l10n XIBs” target’s “Run Script” phase, the script is:

# Create/Update l10n XIBs
  1. originalResourceDirectory="$PROJECT_DIR/English.lproj"
  2. for localizedDirectory in "$PROJECT_DIR/"*.lproj; do
  3.  if [ localizedDirectory != originalResourceDirectory ]; then
  4.   for xibFile in "${originalResourceDirectory}/"*.xib; do
  5.    xibBaseName=$(basename "${xibFile}")
  6.    ibtool –strings-file "${localizedDirectory}/${xibBaseName}.strings" \
  7.     –write "${localizedDirectory}/${xibBaseName}" \
  8.     "$xibFile"
  9.   done
  10.  fi
  11. done
  12. exit 0

This goes through every .lproj directory except English.lproj and uses ibtool to apply the .xib.strings files in those localizations to the XIB files in English.lproj.

By having these as two separate targets, they aren’t run every time I build and each part can be run on its own, on demand.  By using the power of shell scripting, I avoid having to alter the scripts for every new localization or XIB.

]]>
http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/feed/ 0
Changing from BSD to MIT License http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/ http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/#comments Mon, 29 Mar 2010 13:56:43 +0000 2718.us http://2718.us/blog/?p=246 I’m changing the license on most (maybe all) of my active open-source projects, largely because the MIT license does not have as many blanks that have to be filled in as the New BSD license and the language is a bit simpler.  To the best of my knowledge, any rights granted under the New BSD license are also granted under the MIT license, so this is really more of a housekeeping/paperwork issue than a conceptual or substantive change.

If this is of concern for some reason, for the things that were under BSD license and no longer are, the version-controlled repositories still have older versions that are BSD-licensed.

]]>
http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/feed/ 0
Integrating Version Control Revisions in Mac App Version Numbers http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/ http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/#comments Mon, 22 Mar 2010 13:57:26 +0000 2718.us http://2718.us/blog/?p=238 When I was using Subversion for version control in working on my Mac apps in Xcode, I had come to use a build script phase to tack on the subversion revision number as the last part to the version number:

# tack the subversion revision number onto the CFBundleVersion
  1. REV=`svnversion -n "${PROJECT_DIR}"`
  2. REV=${REV/#[0-9]*:/}
  3. REV=${REV//[^0-9]/}
  4. BASE=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${PROJECT_DIR}/Info.plist"`
  5. /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BASE.$REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

This takes the CFBundleVersion from the project’s Info.plist, adds a period and the subversion revision number, and injects that into the Info.plist of the built product.

When I made the move to Mercurial, I couldn’t quite do this anymore.  While subversion revision numbers are monotone increasing and consistent everywhere (they are the unique identifiers of a particular version), Mercurial’s “revision numbers” are local to a particular instance of the repository and may not match up from one instance to another.  Mercurial uses a hash as the unique identifier of a particular version, and these hexadecimal hashes are not monotone, making them unsuitable for use in CFBundleVersion.

Though it took some time, I’ve finally come to a system with Mercurial that I think is workable:

# use the number of minutes between the tip and the most recent tagged commit
  1. HG_LAST_TAG_TIMESTAMP=$(/usr/local/bin/hg log -r "$(/usr/local/bin/hg log -r '.' –template '{latesttag}' –repository "${PROJECT_DIR}|>")" –template "{date|hgdate}\n" –repository "${PROJECT_DIR}" | cut -f1 -d' ')
  2. HG_TIP_TIMESTAMP=$(/usr/local/bin/hg log -r '.' –template "{date|hgdate}\n" –repository "${PROJECT_DIR}" | cut -f1 -d' ')
  3. REV=$(( ($HG_TIP_TIMESTAMP$HG_LAST_TAG_TIMESTAMP) / 60 ))
  4. BASE=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${PROJECT_DIR}/Info.plist"`
  5. /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BASE.$REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

This calculates the number of minutes between the most recent tagged ancestor of the tip and the tip itself and adds that to the CFBundleVersion.  Because it’s time-based, it is guaranteed to be monotone increasing, consistent, and unique (well, provided multiple commits don’t happen within a 1-minute span, which is safe for me).

]]>
http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/feed/ 0
Converting a Google Code Project from Subversion to Mercurial http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/ http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/#comments Sun, 21 Mar 2010 15:01:33 +0000 2718.us http://2718.us/blog/?p=234 The Google Code support wiki article ConvertingSvnToHg is quite easy to follow, but there is one thing worth noting that is kind of buried in the comments.  Assuming you’re doing full history conversion, it is very useful to know that running hg convert locally is much much faster than running it on a remote SVN repository, so it is well worth using svnsync to make a local mirror of the SVN repository and then run hg convert on that.

]]>
http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/feed/ 0
Subversions is (on its way) Out, Mercurial is In http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/ http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/#comments Sat, 20 Mar 2010 14:33:24 +0000 2718.us http://2718.us/blog/?p=232 I have very happily been using Subversion since 2008.  I was quite clearly late to the version control system (VCS) party and I wish I’d known about VCS much earlier.  About 5-6 months ago, I finally gave in and tried Mercurial and hated it.  While I could kind of get my head around why I should like a distributed VCS (DVCS), I just couldn’t make the paradigm work for me.  I was pretty sure that with all the people talking about how great DVCS was, I must be doing something wrong, but that didn’t stop me from putting Mercurial back on the shelf.

A little over a month ago, I went back and played with Mercurial some more, and it just clicked.  I think it had something to do with reading the Mercurial guide, but I couldn’t really put my finger on it.  That is, until a few days ago, when I read Distributed Version Control is here to stay, baby.  Joel’s explanation of his transition to DVCS really hit on the shift in thinking that took place for me in moving to Mercurial.  Plus, it has one of the best lines I’ve ever read in a blog post:

If you are using Subversion, stop it. Just stop. Subversion = Leeches. Mercurial and Git = Antibiotics. We have better technology now.

]]>
http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/feed/ 0
A WebView Subclass with Isolated Cookie Storage http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/ http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/#comments Thu, 11 Mar 2010 07:38:14 +0000 2718.us http://2718.us/blog/?p=227 Following the advice of Kevin Ballard on StackOverflow, I created IGIsolatedCookieWebView, a subclass of WebView that does not access or affect the system-wide shared cookie storage (shared among all WebKit apps).  Each instance of IGIsolatedCookieWebView has its own cookie storage so that, for example, multiple instances of IGIsolatedCookieWebView within the same application can be logged in to the same web site with different credentials.  IGIsolatedCookieWebView should be usable in place of WebView, except that IGIsolatedCookieWebView uses the resource load delegate, so that can’t be used by the application.  IGIsolatedCookieWebView is published under a 3-clause BSD an MIT license.

]]>
http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/feed/ 0
A Drag-Resizable Subclass of NSComboBox http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/ http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/#comments Wed, 10 Mar 2010 09:57:02 +0000 2718.us http://2718.us/blog/?p=223 IGResizableComboBox is a drag-resizable subclass of NSComboBox—that is, IGResizableComboBox should be usable in place of NSComboBox and it adds a small bar at the bottom of the pop-up list that can be dragged to resize the pop-up list.  IGResizableComboBox is published under a 3-clause BSD an MIT license.

It still has some quirks:

  • behavior is strange when the pop-up is above the combo box (whereas it is usually below) [fixed; when the pop-up is above the combo box, the drag-handle is at the top and the top edge moves while the bottom edge stays fixed at the combo box]
  • the formula for resetting the number of visible items after dragging occurs is not quite right [fixed; dragging now snaps to whole-item positions]
]]>
http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/feed/ 0
StartSSL: Free/Cheap SSL Certificates http://2718.us/blog/2009/11/03/startssl-freecheap-ssl-certificates/ http://2718.us/blog/2009/11/03/startssl-freecheap-ssl-certificates/#comments Tue, 03 Nov 2009 09:11:50 +0000 2718.us http://2718.us/blog/?p=198 StartCom is the certificate authority providing StartSSL certificates: unlimited 1-year domain-validated single-site SSL certificates for free (“Class 1″); unlimited 2-year domain-validated single-site, UCC, or wildcard certificates after paying $39.90 to further validate your account (“Class 2,” which necessitated photo IDs and a phone call, and is good for 1 year); 2-year EV certificates for $149.90 (I have no idea if this is a good price or not, as I have no use for an EV certificate right now).  The “Class 1″ and “Class 2″ SSL certificates, both 1- and 2-year, both single-site and wildcard are chained certificates, requiring an intermediate certificate, but the underlying root certificate was included in FF3.5, Chrome, Safari4, and IE6 (these are the browsers to which I have easy access for testing).  I wasn’t able to find a proper comprehensive list of who’s root certificates are included in which versions of what browsers (if anyone can point me to such a list, I’d be grateful).

$39.90 for unlimited 2-year wildcard certs is a whole heck of a lot cheaper than anything else I’ve seen.  In fact, that’s not much off of what I’d been paying for 2 years of a single-site certificate, having done a lot of comparison-shopping.  And it’s really hard to beat free for single-site certificates.  It’s an easy replacement for self-signed certificates at the same price.

]]>
http://2718.us/blog/2009/11/03/startssl-freecheap-ssl-certificates/feed/ 1
IMAP, Hosted Email, imapfilter http://2718.us/blog/2009/09/23/imap-hosted-email-imapfilter/ http://2718.us/blog/2009/09/23/imap-hosted-email-imapfilter/#comments Wed, 23 Sep 2009 22:25:31 +0000 2718.us http://2718.us/blog/?p=184 Of all the various services that I use/host online, I consider email to be, by far, the most critical.  It’s been over 11 years since I registered my first domain name so as to have a permanent email address regardless of changes in educational institution or employer.  I’ve gone through a variety of email setups in that time.  I started with email included in a broader (web) hosting package, using POP (as I did throughout my time in school).  Later, I tried hosting my own mail server at home, paying for a backup/relay server since my connection was unreliable.

At some point, I came to my senses and moved to IMAP, simultaneously moving back to hosted email (because, really, hosting an email server on a home machine is a mess), but with a provider that only hosted email.  IMAP was, at that moment, the ultimate solution to my issues of email being out of sync between multiple computers.  On the other hand, with IMAP, all of my email lived on the hosting company’s servers, so having an email hosting company that knew what they were doing was important.

The other major issue in the move to IMAP was filtering.  I had well over 100 filter rules in Eudora when I stopped using POP.  With IMAP, I no longer had to have filtering rules on every instance of my mail client, but I had to set up the filter rules in the framework allowed by my email host.  (One provider had a Bayesian filter system that could be set to learn from every message move made via IMAP, which was cool, but slow to learn and not accurate enough.)  As time went on, and through changing email hosting providers, this became very cumbersome (especially compared to using procmail on a receiving account, which is how I selectively filter the email that goes to my Blackberry).

When I finally gave up on the hosting company’s email filters, I had nearly 150 filters and there were dozens more I wanted, but just couldn’t be bothered to set up.  With 150 filters and no simple way to group and arrange them, managing the filters was impossible.  If I wanted to rename a mailbox that was the destination for a filter, I had to hunt down the filter and change it, which meant digging through a massive webpage listing of 150 filters.  But using an email hosting provider was non-negotiable for me.

After much searching for ways to run procmail on a remote IMAP account and finding nothing, I finally settled on trying imapfilter.  At first, dealing with the Lua scripting language used to configure it was tedious, but it was easy to learn and thus wasn’t a problem for long.  Now, a week into using imapfilter, my config.lua file is 372 lines long–it’s doing all the filtering I’d been doing through the email hosting company interface, all the filtering I wanted to do, grabbing some spam that persistently evaded the spam filter system, and automatically taking messages that I put in my Junk folder and sending them back to the spam filter system’s reporting address.  I have imapfilter running on a VPS (which I use for a variety of utility things) via cron job every few minutes.  When I want to add a new filter or change the behavior of an existing filter, I can just fire up (Mac)Vim, open the remote file, and apply the power of Vim for quick and easy editing.

It’s the biggest difference in my email use since the move to IMAP.  If you’re using IMAP and you want more powerful/flexible filtering, you should definitely look into imapfilter.

]]>
http://2718.us/blog/2009/09/23/imap-hosted-email-imapfilter/feed/ 0