ThisService: a cool MacOS X utility
Situation now understood! Read this post.
Since writing this I've been having problems with service scripts ignoring line endings in some applications, which prevents these services working correctly on multi-line input. Until I understand it a bit better, be aware that multi-line input might not be processed correctly!
From John Gruber at Daring Fireball comes news of a cool new utility called ThisService. This donation-ware application does one thing brilliantly: it creates system services out of scripts. (This is a MacOS X post...)
A service, on MacOS X, is a small piece of code that can be launched while you're in any program. Services appear on the application menu, and typically do one useful job, either with the selection, or with the frontmost document. For example, if you've selected a path name in a text document, the Finder offers the service of creating a new window and showing you that file's icon. And if you select an icon in the Finder, applications such as BBEdit offer the service of opening that file in that application. Simple, but effective. Services can be provided by the big applications, or can be smaller stand-alone services.
Up to now it hasn't been easy to develop your own services. Now, though, with ThisService, you can take your scripts, written in a language of your choice (which is newLISP, obviously :-)), and create a system-wide service.
There are three basic possibilities. You can write a service that works on selected text, creates new text, or does both.
Here's how the "Create" option might work. Here's my newLISP script:
#!/usr/bin/newlisp (println (date (date-value) 0 "%Y-%m-%d %H:%M:%S")) (exit)
which I save in a file called "insert-iso8601.lsp". Then, using ThisService, I create a new service that runs this script when it's invoked. Because this script doesn't act on existing text, I just select the "Produces output" button. If I want to, I can create a keyboard shortcut for it too.
And that's it. This script is now available to me in every application that supports services (and that's most of them, with some predictable exceptions).
If you want to write a service to process selected text, you write a script that reads STDIN and writes to STDOUT. Here, for example, is a very simple filter:
#!/usr/bin/newlisp (while (read-line) (println (lower-case (current-line))))
which converts the selected text to lower-case. Here, you would specify that the service both creates output and acts on input.
For something like a word-counting script, you can specify that only input is required:
#!/usr/bin/newlisp (set 'words '()) (while (read-line) (set 'words (append words (parse (current-line) "\s" 0)))) (clean empty? words) (exec (format "/usr/local/bin/growlnotify %d -m \"word count \"" (length words))) (exit)
The word count is output using Growl.
Here's another quick script - a rewrapping command for rewrapping selected text:
#!/usr/bin/newlisp (set 'words '())
(while (read-line) (set 'words (append words (parse (current-line) "\s" 0)))) (clean empty? words) (clean (fn (x) (= "\r" x)) words) (set 'cursor 0) (dolist (w words) (print w " ") (inc 'cursor (+ 1 (length w))) (if (> cursor 40) (begin (set 'cursor 0) (println)))) (exit)
I haven't yet used this enough to decide whether this is a good way to re-wrap text. Improvements welcome!