Macintosh, TipsNovember 20, 2009 1:08 pm

Not that I’m exactly the patient type (having been a happy user of uControl for a long time until OS X offered this keymap), but sometimes good features will come if you wait. Initially I wanted to have CAPS LOCK and CONTROL in the same place on all of my keyboards, and my laptops needed to switch them. (I have muscle memory for many Unix control-key options, and hitting CAPS LOCKS instead can lead to foul language.) Then I put my work MacBook Pro, originally with OS X 10.4, on a KVM with an IBM keyboard, and I needed to switch COMMAND and OPTION. However, this led to another annoyance: if I swapped COMMAND and OPTION for the external keyboard, they were swapped when I took the laptop sans external keyboard to a meeting.

I’ve been running 10.5 for ages, but I finally paid attention while I was tinkering with the keymap: it now supports per-recognized-keyboard remaps! I know the novelty will wear off soon and I’ll forget how much I love this feature unless someone asks me directly, but it’s a very welcome feature addition to the welcome feature of keymapping. Sometimes it is the little things that makes long meetings with minimal content not so annoying.

Macintosh, TipsOctober 12, 2009 11:33 am

The Drag a link to Tagger into the Finder toolbar screenshot was driving me nuts because it’s not that simple. I dragged, and the link just bounced back to the application. So I tried some keyboard combinations (since the screenshot indicates that it’s possible), and sure enough, COMMAND-OPTION is the magic pre-drop key combination! Of course, now I’m used to it in my Finder sidebar, so I don’t need it in my toolbar, but it’s nice to know I can do that when I want.

Macintosh, Favorite Software, Tips, JournalOctober 1, 2009 10:44 am

Well, I really want my notes to be accessible, and that means available to Spotlight more and more now, so with some sadness and some help from touch -r, I just migrated the first document from Alepin to Journler.

Alepin’s export preserves the hierarchy (the way I wish the document package’s internal structure did, #3 on my wishlist), but it doesn’t preserve timestamps. So the package structure is flat but with the timestamps I want, and the export structure is hierarchical with a ‘now’ timestamp. I believe I can fix this!

cd ~/Desktop/Notes\ Exported
find . -name \"*.rtf\" | grep -v TXT.rtf | tee adjustTimes.txt
find . -name \"*.rtfd\" | tee -a adjustTimes.txt
ORIG=~/Documents/stuff/Notes.alpn
while read FILENAME; do echo \"${FILENAME}\"; ls -l \"${FILENAME}\"; BASENAME=${FILENAME##*/}; ls -ld \"${ORIG}\"/\"${BASENAME}\"*; echo; done < adjustTimes.txt
while read FILENAME; do echo \"${FILENAME}\"; ls -l \"${FILENAME}\"; BASENAME=${FILENAME##*/}; ls -ld \"${ORIG}\"/\"${BASENAME}\"*; touch -r \"${ORIG}\"/\"${BASENAME}\"* \"${FILENAME}\"; ls -l \"${FILENAME}\"; echo; done < adjustTimes.txt
rm adjustTimes.txt

Let’s decompose that last long while loop. (And take out the touch command the first time you try this yourself!!! Make sure the right files show up, to make sure you won’t mind the results!)

while read FILENAME; do (stuff); done < adjustTimes.txt

This is a while loop that puts the entire line, one line at a time from that text file, into the variable FILENAME. This is the iterative engine!

First, display the filename (make sure spaces come through properly escaped) with echo "${FILENAME}". Then show the directory listing with timestamp via ls -l "${FILENAME}": too new.

Since Alepin’s package structure is flat, strip off everything in front the last slash; ## is greedy match removal, */ is anything before and including a slash. This should be the rtfd filename inside the Alepin document. However, rich-text-only exports from Alepin are sensibly just RTF. So to look at that timestamp, I need to convert *.rtf to *.rtfd … or just tack on * to match zero or more characters for ls -ld ~/Documents/stuff/Notes.alpn/"${BASENAME}"*.

If all that checks out when you test it, it’s time to move the Alepin timestamps to the Alepin export with touch -r ~/Documents/stuff/Notes.alpn/"${BASENAME}"* "${FILENAME}"! Admire the results with a final directory listing with updated timestamps: ls -l "${FILENAME}" (and a final echo for visual space).Ta-da!

Macintosh, Favorite SoftwareSeptember 29, 2009 3:18 pm

I think everyone has their own version of the perfect application to store all of those information tidbits. The time before last when I went looking for mine, I picked Alepin. Since it has been sold and hasn’t been updated, I had to pick another (Journler), but I still miss the good parts of Alepin. It’s easy to dream while your product is in update limbo, so here’s my sorted list of enhancements to make Alepin perfect.

  1. Spotlight support. This is a deal-breaker for me. Without Spotlight, I have to launch an application to find my memory. With Spotlight, I just search from the menubar and find any tidbit in any application (with a Spotlight importer).
    • QuickLook makes filtering Spotlight results just that much easier.
  2. I want per-page tags, preferably OpenMeta tags. I suppose the new developers would have to worry about which file systems don’t support extended attributes (like Dropbox, SMB mounts …) so I guess Alepin needs a hidden file for that, making it less clean. Or a warning “Tagging only supported on …” but that doesn’t catch a Finder copy that causes data loss. So they need duplicate tagging, OpenMeta where supported and a per-document-bundle hidden plist. And a method to sync those as needed.
  3. I always wished for the internal structure to match hierarchy, meaning “Show Package Contents” in the Finder would have the same nested folders as Alepin’s display, because then I could duplicate page names (Hotels in both the Asheville and Wilmington folders in Travel.alpn), and because then the “recoverability” if an Alepin doc gets corrupt is essentially perfect. All cases were my own fault and easily recovered, but I have had my Alepin documents get corrupted.
    • This could go interesting places, in that Alepin becomes a browser to a folder of RTFD, especially if metadata like tags goes on the file and the safety file can be re-created from the component documents.
    • Add in textutil’s ability to convert to rtfd … this could go many places. I haven’t thought this all the way through, especially since it’s not how I would use Alepin. I’m happy with its Import and Export (to nested folders that aren’t in its internal hierarchy!).
  4. Fix bug where editing a internal component rtfd (using “Show Package Contents” or found because of my tweakings for Spotlight) with TextEdit would cause the whole document.alpn to be corrupt on next launch. Since it showed up in a search, a proper Spotlight importer would help here too; but Alepin would need to be able to open an Alepin document in context to fix it well.
  5. Fix bug where password-protecting an Alepin document on one Mac, copying (well, bbouncer-approved rsync-ing) that document to another Mac and trying to open it would show the corrupt message. Yeah, apparently I can corrupt documents like nobody’s business.

I love(d) Alepin, but I need to be able to find and use what I’ve stored, in a format with easy recoverability from corruption, with solid import and export choices, preferably document-based. I tried (and bought) Circus Ponies, but since then I bought and am using Journler instead because it just feels easier.

Macintosh, Tips, UnixSeptember 15, 2009 11:50 am

It was a good ride while it lasted (I was an early adopter), but it was time to move off the PBworks (formerly pbwiki) boat. My site was hard to read on my iPod touch, and the new 2.0 migration took away my ability to edit from my touch. I do most of my “personal” web browsing from my touch while Cale is nursing, but I don’t do it often enough to want to pay for that feature. (I’m not fond of the 2.0 look either. I prefer simple. I think I’ll be happy, possibly happier, with jottit, simpler than a wiki, and wikidot, so customizable and lovely page tags with a flying tag cloud, instead.) I decided that a lot of what I had in pbwiki didn’t need to be online, so I decided to move it to Journler. I wish it were Alepin, but I want tags and Spotlight.

First I downloaded all of my files from my site (fill in your workspace name). I noticed that the zip file preserved the file modification times! Bonus!

I didn’t like how Journler imported HTML (as an attachment to an otherwise-empty entry), though, so I decided to convert to RTF instead. I was sure it had to be easy on OS X, so after discarding non-simple Google results, I found textutil! Score!

I opened Terminal, and changed to the directory of my HTML files.
textutil -convert rtf *.html
mkdir rtfdir
mv *.rtf rtfdir

That was a nice start, but I lost the timestamps! I was sure I could keep those, and I know touch modifies timestamps …
cd rtfdir
for filebase in $(ls *.rtf | sed 's/\.rtf$//g'); do touch -r ../$filebase.html $filebase.rtf ; done

Now to import into Journler … no problem: my data are in the entry (not attached to it), and the timestamps are preserved as creation date! Not a bad piece of command-line tomfoolery to get exactly what I wanted without touching each file by hand. I like textutil!

Don’t get me wrong: I think PBworks is a great service, and I don’t think anything bad about it. But I know what features I want, and it was time for me to move on for my needs.

Macintosh, Tips, Journal, CodeAugust 13, 2009 2:40 pm

When my USB thumb drive died, and then its brand new replacement followed it, I looked for an online alternative. I picked Syncplicity because I liked the screen shots: I knew exactly what I would see as a user. I used it to access live copies of my most-used files on both my work and home MacBook Pros. Well, Syncplicity decided to drop Mac support cold at the end of last month. I finally got around to uninstalling it, which was a pain because the directions disappeared out from under me.

If you need ‘em, those directions are:

1. Shut Syncplicity down
2. Delete /Applications/Syncplicity.app
3. Delete /Library/Contextual Menu Items/SyncpCMPlugin.plugin
4. Delete ~/Library/Application Support/Syncplicity
5. Restart your Mac

My first thought while reading those directions was:

1. osascript -e "tell application \"Syncplicity\" to quit"
2. rm -rf /Applications/Syncplicity.app
3. sudo rm -rf /Library/Contextual\ Menu\ Items/SyncpCMPlugin.plugin
4. rm -rf ~/Library/Application\ Support/Syncplicity
5. osascript -e "tell application \"Finder\" to restart"

so I decided to script it. Since the first and last steps were AppleScript commands, I dabbled around and came up with an AppleScript application to uninstall Syncplicity for the Mac (download).

For alternatives, I picked Dropbox (SugarSync is similar), but if you lean towards backups too then Mozy, iDrive, and rsync.net are also strong contenders.

The last step, after making sure all my files are current and local, is to cancel my account at Syncplicity. Time to move on!

Macintosh, Tips, CodeAugust 11, 2009 3:31 pm

From the inimitable Daring Fireball, how to see if an application is running with AppleScript:

tell application \"System Events\"
    count (every process whose name is \"BBEdit\")
end tell

I modified that into tell application "System Events" to set syncpRunning to count (every process whose name is "Syncplicity") for my purposes.

Macintosh, Journal, Code 12:38 pm

AppleScript sounds great: it’s a high-level language, and the code, done right, can be quite human-readable. That’s also the problem … there are so many cases where “to” and “of” both work, and then you run into a case where it matters. Frustrating! That makes me long for a less-flexible language; if there’s only one way to issue the command, look it up, use it, and you’re done. Or try to figure out where and why AppleScript is so slippery …

Anyway, yesterday’s quest was to identify special folders, like the Applications folder, without assuming /Applications.

Most of the names of special folders are listed in the AppleScript Language Guide: Commands Reference. Yay! However, some special folders aren’t there. You can find that longer list in AppleScript 1-2-3. For instance, I used this line of AppleScript
set removePlugin to (the path to "cmnu" as string) & "SyncpCMPlugin.plugin" as alias
where the path to "cmnu" gives me the path to the user’s Contextual Menu Items folder. That’s not as readable as I’d like my AppleScript, but there’s no human-readable version of the 4-letter code.

Today’s challenge is to discover if the Trash is empty or not with AppleScript; I’m not going to cheat and use shell.

I’ve tried
set trashItems to the count of every item in the trash
set number_of_items to (count (every item of the trash))
set tryThis to count of items in trash

and they don’t work.

Oh yeah, here’s what I mean about AppleScript being a slippery dog, and natural language failing.

These lines work:
tell application "Finder" to set trashList to (items of trash)
tell application "Finder" to open (the path to the trash folder as alias)

These lines do not work:
tell application “Finder” to set trashList to (items of trash folder) with Can't get every item of trash folder.
tell application “Finder” to open the trash

Since Unix is so good at text manipulation, I find that aspect of AppleScript frustrating, and the Working with Text AppleScript reference useful.

OK, so I have solved today’s AppleScript frustration to see if the Trash is empty or full.

set trashList to {""}
set trashFiles to {""}
tell application "Finder" to set trashList to (the items of the trash)
tell application "Finder" to set trashFiles to the name of the items in the trash
set old_delimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {", "}
set display_trashFiles to trashFiles as string
set trashCount to the count of trashFiles
if (trashFiles is {}) then
display dialog "There are no items in the Trash." buttons {"OK"} default button 1 with title "Trash Empty" with icon note
else
display dialog "There are items in the Trash." buttons {"OK"} default button "OK" with title "Trash Not Empty" with icon caution
end if
if trashCount > 1 then
display dialog "There are " & trashCount & " items in the Trash." & return & "list: " & (trashFiles as string) buttons {"OK"} default button "OK" with title "Trash Full" with icon stop
else if trashCount = 1 then
display dialog "There is " & trashCount & " item in the Trash." & return & "list: " & display_trashFiles buttons {"OK"} default button "OK" with title "Trash Full" with icon caution
else
display dialog "Empty, " & trashCount & " items in the Trash." & return & "list: " & display_trashFiles
end if
set AppleScript's text item delimiters to old_delimiters

tell application "Finder"
display dialog "What would you like to do?" buttons {"Empty Trash", "View Trash", "OK"} default button "Empty Trash" with icon note
if button returned of result is "Empty Trash" then
empty trash
else if button returned of result is "View Trash" then
open the (path to the trash folder as alias)
end if
end tell

That was harder than I expected, but now it’s done.

Macintosh, Favorite SoftwareAugust 9, 2009 10:05 pm

Just found where that annoying preference was hiding with AppCleaner, since of course Spotlight doesn’t want to search there … even if you don’t want to delete an application, what AppCleaner finds when you’re frustrated can still be valuable!

Macintosh, Project 7:33 pm

Unlike Syncplicity (dropping Mac support, failing most of Backup Bouncer), Dropbox passes Backup Bouncer!

sudo /usr/local/bin/rsync -aAHNX --delete --fileflags /Volumes/Src/ ~/Dropbox/bb/
sudo ./bbouncer verify -d /Volumes/Src/ /Users/hope/Dropbox/bb/
Verifying:    basic-permissions ... ok (Critical)
Verifying:           timestamps ... ok (Critical)
Verifying:             symlinks ... ok (Critical)
Verifying:    symlink-ownership ... ok
Verifying:            hardlinks ... ok (Important)
Verifying:       resource-forks ...
   Sub-test:             on files ... ok (Critical)
   Sub-test:  on hardlinked files ... ok (Important)
Verifying:         finder-flags ... ok (Critical)
Verifying:         finder-locks ... ok
Verifying:        creation-date ... ok
Verifying:            bsd-flags ... ok
Verifying:       extended-attrs ...
   Sub-test:             on files ... ok (Important)
   Sub-test:       on directories ... ok (Important)
   Sub-test:          on symlinks ... ok
Verifying: access-control-lists ...
   Sub-test:             on files ... ok (Important)
   Sub-test:              on dirs ... ok (Important)
Verifying:                 fifo ... ok
Verifying:              devices ... ok
Verifying:          combo-tests ...
   Sub-test:  xattrs + rsrc forks ... ok
   Sub-test:     lots of metadata ... ok 

That’s a clean slate for rsync 3.0.6 (patched) and for Dropbox (provisionally)! Nice to know Dropbox should keep my OpenMeta tags intact. At work tomorrow, we’ll see if Dropbox still passes, on the other end of the Dropbox wormhole; that will be the real test of Dropbox.

UPDATE: Not surprisingly, Dropbox doesn’t look as pretty on the other side of the wormhole. It mostly fails everything, so only use it for self-contained files (no extended attributes, no specialized metadata, no resource forks; just timestamps and bsd-flags).

sudo ./bbouncer create-vol Src
./bbouncer create /Volumes/Src
sudo ./bbouncer verify -d /Volumes/Src ~/Dropbox/bb
Verifying:    basic-permissions ... FAIL (Critical)
Verifying:           timestamps ... ok (Critical)
Verifying:             symlinks ... FAIL (Critical)
Verifying:    symlink-ownership ... FAIL
Verifying:            hardlinks ... FAIL (Important)
Verifying:       resource-forks ...
   Sub-test:             on files ... FAIL (Critical)
   Sub-test:  on hardlinked files ... FAIL (Important)
Verifying:         finder-flags ... FAIL (Critical)
Verifying:         finder-locks ... FAIL
Verifying:        creation-date ... FAIL
Verifying:            bsd-flags ... ok
Verifying:       extended-attrs ...
   Sub-test:             on files ... FAIL (Important)
   Sub-test:       on directories ... FAIL (Important)
   Sub-test:          on symlinks ... FAIL
Verifying: access-control-lists ...
   Sub-test:             on files ... FAIL (Important)
   Sub-test:              on dirs ... FAIL (Important)
Verifying:                 fifo ... FAIL
Verifying:              devices ... FAIL
Verifying:          combo-tests ...
   Sub-test:  xattrs + rsrc forks ... FAIL
   Sub-test:     lots of metadata ... FAIL 
	
sudo ./bbouncer verify -d /Volumes/Src ~/Dropbox/bb | grep ok
Verifying:           timestamps ... ok (Critical)
Verifying:            bsd-flags ... ok
./bbouncer clean /Volumes/Src
./bbouncer clean ~/Dropbox/bb 

So … be careful. On the origin end, your file is fine; on the other end of the wormhole, it might be mangled.