NetNewsWire to Delicious

October 28th, 2005

NetNewsWire “Save to Delicious” scripts are popping up everywhere! I sent one to the NetNewsWire mailing list some time ago that handles the whole operation (IMHO) better than the others. The difference? The others either only bookmark web pages, or only bookmark news items. What!? Mine does both. This is a Mac!

You can download it directly here, or check out the rest of my free AppleScripts.

PS: Don’t forget to replace “YOUR_ACCT_NAME” with your actual DelIcioUs account name, in the script!

Victory over “[Process Completed]”!

October 23rd, 2005

I have been plagued by a bug I see often in Terminal. I know it’s been at least months, and it may have even been years. But it’s gotten worse lately. I call it the “phantom [Process Completed] bug.” The symptoms of this issue are that every so often an innocent attempt to open a new Terminal window instead yields an immediate “[Process Completed]”. What this has meant for me is that I’ve basically gotten used to “trying again” whenever I see this. It sucks though, because it limits my ability to automate with confidence when it comes to opening new shell windows. The thing about this bug is seems to “happen only every other time per pseudo-tty.” So if it fails once, it will probably not fail the very next time you try it! A dangerous recipe for “acceptance,” but this is a terrible concession to have to make to a computer!

Things finally came to a head today and I decided to track down the root cause. I posted to the MacOSX-Dev mailing list for help, and Chad Leigh pointed me in the direction of some very helpful advice that, while it alleviates a separate problem I was experiencing (running out of processes, and getting fork failures), it doesn’t solve the “Process Completed” problem.

I needed to collect some hard data, so I started out by rebooting my machine. On a freshly booted machine, I am able to create a dozen new Terminal windows without running into the problem a single time. Close those dozen windows and try again, and about half of them fail! So this has something to do with reusing pseudo-TTYs? I decided to switch over to “iTerm” for a little comparison. Sure enough, opening a dozen windows there yields about the same failure rate.

I searched the web (again, I had tried this months ago), and came up with some interesting leads. Some people have noticed that the problem is worse with zsh. I run zsh, lucky me! Other people have noticed that the problem only happens when a Terminal window is closed without manually closing down the shell inside first. Sure enough, I almost always close my shells with Cmd-W, allowing Terminal to “take out the trash.” I run some more tests, and what do you know? I can “cleanse” ttys by making sure that I run “exit” on the shell before closing the window.

Since the rumor is that it happens more in zsh than other shells, I’m inclined to believe it’s a shell bug. I decide to test against a very simple shell: “bc” the built in UNIX calculator. Setting my default shell to “/usr/bin/bc”, I go on a rampage of opening a dozen or more new shells, closing them all, and trying again. Sure enough, “bc” is completely clean. It can take a beating and happily reopen on the same old tty that got slammed last time-around. I switch back to zsh, and open a bunch of terminals again. They’re all clean! So bc left them clean enough for zsh’s liking. It must be something about the way zsh “takes out the trash” (or doesn’t).

I switch the default shell to “/bin/sh”. In twelve opens, I witness the failures due to booby-traps set by zsh. Close twelve. Open twelve again: all clean. Sh (bash, actually) cleans up well! Try with tcsh: all clean, too!

Damn you zsh! I love ya, but you’re a messy sucker!

I’m not about to give up zsh, and I’m not quite ready to look into locating the bug in zsh, but I need to work around this. I know that if I type “exit” every time I need to close a shell window, I will never see the bug again, but I’m too lazy to remember to do that! FastScripts/AppleScript tag team to the rescue. I wrote this simple script:

tell application "Terminal"
try
do script "exit" in window 1
close window 1
on error
beep
end try
end tell

With FastScripts I’m able to override just about any menu shortcut in just about any app, so I set it up as an Terminal-specific script, and assign it the shortcut Cmd-W. Now, whenever I type Cmd-W in Terminal, the same shortcut I’ve been using for years to close shell sessions, the Terminal first performs an explicit “exit” in the window, and then closes it. I get to keep my behavior, but the buggy zsh conditions are no longer produced.

I’m so excited by this that I’ve spent a few minutes just holding Cmd-N down for several seconds, closing all the windows, and repeating. Ah, it’s going to be a nice autumn.

Update: I thought I had observed some funkiness with the state of the pseudo tty files after zsh was closed on them, but I’ve come to find out that the behavior is not unique to zsh. I think it’s a red herring. Other shells sometimes leave the tty in this funky state and it doesn’t seem to affect their ability to reopen the tty as a healthy session.

Update 2: It occurred to me that one of the downsides to replacing Cmd-W with a scripted keyboard shortcut is that I can’t take advantage of the “hold down the keys for repeated invocation” functionality that you normally get for free with menu items.

I decided the only reason I was taking advantage of this in Terminal is because it lacks a proper “Close All” function. So, I wrote another script, this one mapped to Cmd-Opt-W in Terminal, which will first go through and call “exit” in all the open windows, and then close them all:

tell application "Terminal"
return count of windows
if ((count of windows) is equal to 0) then
beep
else
repeat with thisWindowNumber from 1 to (count of windows)
do script "exit" in window thisWindowNumber
end repeat

repeat count of windows times
close window 1
end repeat
end if
end tell

Save HTML from Mail Message

October 22nd, 2005

Usually when I get an email message with HTML content, I reach for the delete key faster than you can say “spam!” But there are some messages I receive which contain important HTML content. For instance, the invoicing system one of my large corporate clients uses (why, I don’t know), is completely unusable in most regards. The only way I have found to get a personal copy for my records of invoices I issue through it is to have it email me a copy. When the copy arrives, of course it is in a table-heavy HTML format, which is unreadable even if I attempt to save it as plain text. It looks terrible as HTML too, but at least it’s readable!

So, I get this HTML email regularly, and I need to save it to my “Unpaid Invoices” folder. Unfortunately, Apple Mail has no obviously easy way to do this. I have before today resorted to various steps including showing the raw source and manually copy/pasting the HTML portion out and into another file. Today I decided the B.S. stops and I get an easy solution.

I didn’t even bother looking around for an existing script. I knew what I wanted so I wrote it. The result is a script that should do a reasonably good job of grabbing the HTML out of a selected message and saving it to disk for you. I don’t think of this as something that most people want to do often, but if you find you do need it, now you don’t have to write it yourself:

Click here to download: Save HTML Content

Blogging with Style

October 18th, 2005

Since I’m a little obsessed with AppleScript, I end up pasting AppleScript code into my blog. I recently decided it was a real shame that I couldn’t easily replicate the way AppleScript code looks in Script Editor, in my blog. I thought about this situation for a while, and then did some experimenting.

If I copy the contents of a Script Editor window, and paste it into TextEdit, it looks great! Just like Script Editor! Why can’t I get that in HTML? I decided to try saving as HTML from TextEdit. Sure enough, that yields an HTML look-alike, but it depends on a rather elaborate set of CSS definitions in the <head> block of the document. I’m not ambitious enough to figure out whether I can include non-inlined CSS styles in random locations like the content of my blog post. Besides, I’d like to be able to “grab some styled text” and run with it.

It occurred to me that maybe AppleScript itself could help me get the formatting I needed. After a little tinkering, Sure enough, with TextEdit and the Text Suite, I can parse a chunk of styled text and spit out reasonably similar-looking HTML!

In this blog entry, I submit to you a script that will turn the text from the front-most document in TextEdit into a self-contained, inline styled chunk of HTML. It’s not pretty, but it works! As a proof-of-concept, the following code was copied from Script Editor, pasted into TextEdit, and then run from Script Editor. Because of some WordPress funkiness I had to change a few minor details in the source for this page, but I think you’ll find that the script works as expected in most contexts.:


tell application "Script Editor"
-- Since we are probably capturing newlines, tabs, etc.,
--
Let’s tag the content as "pre-formatted".
set myHTML to "<pre>"

-- Prefetch lists from the runs for performance during loop
set {myFonts} to {font} of attribute runs of document 1
set {myColors} to {color} of attribute runs of document 1
set {mySizes} to {size} of attribute runs of document 1
set {myTexts} to {characters} of attribute runs of document 1

-- Build an independent HTML span for every attribute run
repeat with attrIndex from 1 to count of attribute runs of document 1
-- Figure the color
set thisColor to (item attrIndex of myColors)
set redComp to (my RGBColorNumToHex(item 1 of thisColor) as string)
set blueComp to (my RGBColorNumToHex(item 2 of thisColor) as string)
set greenComp to (my RGBColorNumToHex(item 3 of thisColor) as string)
set thisHexString to "#" & redComp & blueComp & greenComp

-- Font name and size
set thisFont to (item attrIndex of myFonts as string)
set thisFontSize to (item attrIndex of mySizes as string)

-- Get the text
set thisTextRun to (item attrIndex of myTexts as string)

-- Put it all together
set thisHTMLRun to "<span style=\"color:" & thisHexString & "; font-family:’" & thisFont & "’; font-size:" & thisFontSize & "pt;\">" & thisTextRun & "</span>"
set myHTML to myHTML & thisHTMLRun

end repeat
set myHTML to myHTML & "</pre>"
set the clipboard to myHTML
end tell

-- Based on Num32ToHex by Walter Ian Kaye
--
http://www.natural-innovations.com/as/snippets.html
on RGBColorNumToHex(num)
-- We want smaller numbers
set num to num / 256
set out to ""
repeat with idx from 1 to 0 by -1
set bas to (16 ^ idx) as integer
if numbas then
set mult to ((num – (num mod bas)) / bas) as integer
set out to out & character mult of "123456789ABCDEF"
set num to (numbas * mult)
else
set out to out & "0"
end if
end repeat
return out
end RGBColorNumToHex

Wow, that looks quite a bit more Script-Editor-like than your average web posting! It’s shamefully inefficent (take a look at the HTML it generates), but it gets the job done! I am happy to have this new tool at my disposal, but aside from producing rotten HTML code, the script is also dog slow. Also, when I copy the script above and paste it into Script Editor, it comes out double-spaced. Anybody out there have any tips for achieving this goal in a slightly more gallant manner?

Update: The script above has been updated since the original post. I discovered a few prefetching tricks that dramatically improve performance of the script. How dramatically? Thanks to Shark I can tell you! The test case for both scripts is converting the styled script text above from TextEdit to inline HTML. The old script? 58 seconds! 40% of which was spent in TextEdit itself. The optimized version above, which prefetches the pertinent styled text data from TextEdit? 4.5 seconds, with only 5.4% of the processor taken up by TextEdit. More than 10-times faster! Just imagine how fast it will be when a good scripter rewrites it!