AppleScript


21
Feb 12

Plain Text to OmniFocus

This is an oldie and a goodie. Rob Trew makes some damn fine AppleScripts for getting tasks in and out of OmniFocus as well as some great DEVONthink tools.

For all my grief for AppleScript, his work is an excellent model of the power of scripting on the Mac. I also love the structure of his scripts. Unlike mine, he properly designs his scripts with methods and descriptive structure. This is how you write an AppleScript:


AppleScript

His Taskpaper to Omnifocus script is particularly amazing. It does not require TaskPaper either. I can sketch out a large project in plain text (my preferred medium) using the TaskPaper format:

Build Death Star:
- Call about completion of clone army @GPhone @due(2012-02-28)
- Check schematics @due(2012-02-24)
- Ask designer about the unprotected vent @flag
- Call Darth to schedule meeting @due(2012-02-27 08:00)
    - Lookup Darth's number @Outlook
    - Send flowers (Padmé anniversary) @PC @due(2012-02-24)
- Buy new Overlord todo app from the droid app store @amazon

After drafting a project, I just copy the project outline to the clipboard and run Rob’s script.1 A popup window shows what will happen and the results afterward.

At the completion, a new project is sitting in OmniFocus with the tasks and structure as I outlined.


Death Star

To get at the script, view the package contents of Rob’s droplet. The script is buried a few levels deep.

Note that this script expects the old TaskPaper format, not the new indented format. I’ve had problems with the project structure when I use the new TaskPaper format.

Commentary

My biggest complaint about OmniFocus (for me) is that it’s great at capturing quick actions and mind-dumps but it sucks for designing and planning a moderately complex project. OmniOutliner is great at planning large projects because I can easily grab and move tasks and milestones around. The Omni Group makes some great stuff, but absolutely none of it works well together. Why can’t I copy an outline and past it into OF to create a new project?2 How about a direct link between OmniFocus and OmniPlan? These are great applications individually, but they are silos fighting against each other.


  1. Rob actually makes the script available through a droplet. The droplet can process multiple text files in one go. 

  2. Don’t even get me started about the import/export options. They just don’t work consistently or predictably. After designing a project with 50+ tasks and sub-tasks, it’s a real pisser when it doesn’t import properly. 


8
Feb 12

AppleScripts for Address Book and iCal

A nice collection of AppleScripts for Address Book and iCal cleaning. Some real gold in there.


26
Jan 12

Rich Text in AppleScript and Shell Scripts [Link]

A nice simple combination of pretty basic shell commands to pipe formatted text to the clipboard. A bonus tip to convert Markdown to RTF on its way to the clipboard too.

 

Nik’s Crappy Blog


23
Jan 12

BBEdit and Markdown: Insert End Reference Script

As mentioned previously, I have a love-hate relationship with AppleScript.1 It’s an insanely bad language for the importance it has garnered on my system. But sometimes it’s all I’ve got. In this case, I wanted a pop-up menu of all of my end references in the current BBEdit document. I took it a bit further and ended up with something that I truly like.

try
    tell application "BBEdit"
        set results to find "^\\[.*?\\]: http(s?):\\/\\/.*" options {search mode:grep, starting at top:true, wrap around:true, returning results:true} searching in {text of front text document}
        set ResultList to found matches of results
        set choiceList to {}
        repeat with refLink in ResultList
            set end of choiceList to refLink's match_string
        end repeat
        set pasteLink to (choose from list choiceList with prompt "Choose a Link:") as text
        set startDelim to AppleScript's text item delimiters
        set AppleScript's text item delimiters to {":"}
        set linkName to text item 1 of pasteLink
        set AppleScript's text item delimiters to startDelim
        set selection to linkName
    end tell
end try

The script leverages BBEdit’s grep search to get a list of all Markdown reference style links. A popup menu is then displayed.

Selection Window

Selecting the appropriate item inserts the reference marker at the current cursor in BBEdit. This is perfect for the way I write. I typically gather a large number of references first and then start writing. As I write, I can now quickly insert the reference pointer inline.
Inserted Link

Update: If you replace find string with this line the script now works for footnotes instead.

set results to find "(^\\[\\^.*?\\]):(.*)" options {search mode:grep, starting at top:true, wrap around:true, returning results:true} searching in {text of front text document}

Update 2: Sorry for the messy code. I’ve cleaned it up a bit. Did I mention I have a day job, a three year-old and a wife in Law School (night school). Excuses, excuses.


  1. Mostly hate. 

23
Jan 12

Change Language Script for BBEdit

Do you want a script to quickly change the language of the current document in BBEdit?[1] Here you go:

tell application "BBEdit"
    set source language of front text document to "Markdown"
end tell

I have several languages triggered by the same keyboard shortcut (ctrl-shift-L) using Keyboard Maestro. The group is only available while in BBEdit so there’s no need to include an “activate” command. Since they all use the same shortcut, I actually get a quick list to choose from.


  1. The ctrl-opt-L shortcut does something similar in BBEdit right out of the box. It opens the language menu. Typing the language then selects that option. This script is quicker and I only see my most commonly used languages.  ↩


22
Jan 12

Quick Notes With BBEdit

Occasionally I just want to make a quick note in NVAlt/Simplenote/Dropbox[1]. Of course, I can command tab to NVAlt and create a new note in relatively few clicks. But I’m using BBEdit more and more. If I want to create a quick note from BBEdit it’s not so quick. Here’s a modification of a script from John Gruber that creates a new note in my NVAlt Dropbox folder and opens it in BBEdit. The script is designed to be triggered from LaunchBar. Save the script (after updating the path with your own NVAlt document folder) in ~/Library/Application Support/LaunchBar/Actions.

on handle_string(message)
    set notesFolder to "/Volumes/Macintosh HD 2/Dropbox/Notes/"
    set timeStamp to (do shell script "date +'%Y%m%d_%H%M%S'")
    set filePath to quoted form of ((POSIX path of notesFolder) & message & "_" & timeStamp & ".txt")
    do shell script "/usr/local/bin/bbedit -c " & filePath
end handle_string

To avoid any need to check for an existing file and warning if one already exists, I just create the file with my standard timestamp nomenclature. The idea is to get in and out, not to reach for the mouse to respond to a warning.

Note that this requires the BBEdit command line tools. If you bought BBEdit from the app store, it is a separate download from BareBones. The “-c” flag causes BBEdit to create a new file in that location.

Also note, I do not have my local/bin directory on my user path. So I must include the full path to use the BBEdit command line.


  1. I have all three syncing. If I make a note in Dropbox then it is automatically kept in sync with Simplenote by NVAlt.


21
Jan 12

Dialog Window Bug in Automator

Automator has an odd bug that is very enticing. I’d love large text entry boxes in AppleScript dialogs, rather than the anemic single line input that is possible. Automator has an “Ask for Text” action that produces a similar dialog box. However, if the Title field is left empty the text entry box is five lines tall.

Ask for input

 

Large Text Box

But, when a Title is provided, the scrawny single line text input box is back.

Text Entry with Title

I considered building a workflow that used the tall text input box, but decided against it. What if Apple ever fixed bugs in Automator?


21
Jan 12

Using HTML Forms with AppleScript [Link]

This script by Nik Friedman is pretty interesting. It uses an HTML form for input rather than the crappy AppleScript dialogs. The approach involves bundling the form with the AppleScript and then loading it in a Safari window with a custom URI loading function in the AppleScript. Or something like that.

He is able to produce an AppleScript form that looks pretty nice.

AS From


19
Jan 12

AppleScriptObjC Explored

Add this to the list of bad decisions I will make in 2012. I’m going to work through the entire book and see where I end up. I think I will either end up really liking Cocoa AppleScript, really hating AppleScript or mostly using Python. That’s almost where I am now.


9
Jan 12

Select Next Word Script for BBEdit

Continuing the riff on BBEdit, here’s a script that uses the grep match for a single word. It’s an AppleScript that I bound to the shift-cmd-right arrow combo. If there is no word selected, it selects the closest next word. If there is a word already selected, it selects the next whole word. It’s a take on John Gruber’s original Select+Word script with the additional benefit of being able to walk the selection down a line one word at a time.

Of course the secret was figuring out the magic words to get BBEdit to do what i wanted. Thankfully, Chris Stone on the BBEdit groups was happy to provide his considerable expertise.

try
    tell application "BBEdit"
        tell text of front text document
            set current_offset to characterOffset of selection
            set current_line to startDisplayLine of selection
            if length of selection = 0 then
                select (last word of display_line current_line whose characterOffset ≤ current_offset)
            else
                set results to find "\\b\\S+\\b" options {search mode:grep, showing results:false, returning results:true} with selecting match
            end if
        end tell
    end tell
on error errMsg number errNum
    set {cr, sep} to {return, "------------------------------------------"}
    set e to sep & cr & "Error: " & errMsg & cr & sep & cr & "Error Number: " & errNum & cr & sep
    beep
    display dialog e
end try


9
Jan 12

Moving Text Editors: Taking BBEdit Seriously

There are plenty of good reasons to be eagerly awaiting a stable release of Textmate 2 but there are also equally valid reasons to avoid it. I’ve used both but I’ve never been an expert at either. I’ve used them for small personal projects but nothing that would exercise all of the features. For web development, I use Coda, for python scripts, I use BBEdit and now CodeRunner. Most of my writing for this site is done between Simplenote, NVAlt and MultiMarkdown Composer. Recently I decided to invest myself in BBEdit so I could leverage some of the power it provides.[1]

What I’ve discovered is that BBEdit is an incredibly complicated and simple tool. It’s a plain text editor on the surface, but it’s highly customizable (like Textmate or even Vim). I’ve been documenting some of my experience and this post describes some of what I like about BBEdit 10.

Customizations

Most BBEdit customizations are available by dropping a plain text or AppleScript file in the application support directory. BBEdit makes it easy to access these locations and there are no secret “default writes” voodoo to add new features to BBEdit. It’s all readable text.

Text Clippings

Text clippings are like TextExpander snippets or Keyboard Maestro hotkeys, but more powerful. They are more like Keybindings in their ability to manipulate and select text.

Text clippings in BBEdit have their own vocabulary for performing text substitution and selection, very much like TextExpander insertions. You’ll want to read the manual for this one, but one important term is the #SELECTIONORINSERTION# keyword. This keyword grabs the current selection. If there is not one then the insertion point will be placed here after expanding the clipping. This is very handy for creating custom text wrapping functions. For example auto-wrapping a selection in braces or parentheses.

Wrapping Text

The markdown wrapping I’ve grown accustomed to in NVAlt is great. Select some text and hit the bracket key to surround the text. Or just auto-pairing brackets and parentheses as I type is a time saver. BBEdit provides options for this and much more.

Here is a basic text clipping for bracketing a selection. If there is text selected already, then the text will be enclosed and the insertion point placed to the right of the last bracket. However, if no text is selected then paired brackets are inserted and the insertion point is placed between the brackets.

Here are some not so fancy clippings for markdown:

  1. Surround with hash Marks (##SELECTIONORINSERTION##)
  2. Surround with spaces ( #SELECTIONORINSERTION# )

I can combine these two clippings to quickly make markdown headers by hitting “#” three times and then hitting shift-space to get “### ###” with the insertion mark waiting in the middle. This is a lightning fast way to create MD headers.

Beyond that, I’ve created several clippings for wrapping text in parentheses, braces brackets, asterisks, quotes and literals.

The real power of these clippings are realized when they are associated with keyboard shortcuts. For example, using the “[” key for wrapping selected text just like in NVAlt or MultiMarkdown Composer. But BBEdit will not allow standard system keys to be overriden for clippings.

Keyboard Maestro Overrides

BBEdit will not allow a text clipping to be set to a hotkey that is used by the system.[2] For example, if I want to wrap a selection in brackets, I can not set the clipping to use the “[” key as default. One trick to override this behavior is to [use a Keyboard Maestro group][gruber inetercept] that is only active in BBEdit. That group then contains macros with hotkeys mapped to their BBEdit counter part. Here’s an example. This macro simulates the difficult to remember BBEdit hotkey of ctrl-opt-[ but the macro is triggered by the “[” key.

Trigger Override

Scripts

BBEdit is probably the most scriptable application I have ever worked with. Nearly every aspect of BBEdit can be controlled through AppleScript. But what’s more important, BBEdit provides a mechanism for tying scripts into text clippings[3] and menus. There’s a nice tutorial over at MacTech.

Selection Control

There are plenty of options in BBEdit for moving around a document and selecting text. BBEdit brings a lot to the table right out of the box. But if that’s not enough, just about everything can be customized with AppleScripts.

BBEdit already hase built in support for hopping through text, stoping at CamelCase characters (ctrl-right arrow). But this too could have been done with an AppleScript.

Mr. Gruber has one of the earliest examples I could find of selecting the word that the insertion point is in.

There’s a script to select the current paragraph text, excluding the leading indent and newline characters.

Scripts are made even more powerful when combined with BBEdit’s Grep searching, also accessible through AppleScript. There’s a short tutorial (albeit rather old) at Anybrowser.org.

Sure, BBEdit is scriptable. So are a lot of applications. I was impressed but not surprised about the scripting support. But then I discovered the menu scripting support. Menu scripting provides the ability to add-to and override the BBEdit menus with custom scripts. For example, instead of using the built-in FTP service, there’s a script to override the menu and launch Transmit instead.

Markdown

It’s only natural that BBEdit is one of the premier Markdown environments, given Gruber’s affinity for BBEdit. BBEdit comes with a number of features that support Markdown, but I also installed the Markdown Extensions by Watts Martin. These additional options for getting MD in and out of BBEdit, as well as adding support for MultiMarkdown.

The Markdown language module provides syntax highlighting for links, headings, block quotes, code and lists. There is support for MultiMarkdown through add-ons but the built-in syntax highlighting does not extend to any other MMD features. Fortunately, I use Marked for MMD preview so very little has changed for my writing workflow. I do miss the MMD highlighting though.

Huge win here for BBEdit. If the text exists, BBEdit will find it. BBEdit supports standard Find and Replace, but as mentioned previously, it also supports grep search and replace. If you’re not familiar with grep, check out this short tutorial. Grep is an advanced search function built into UNIX and BBEdit takes full advantage of it. Grep patterns can be saved and recalled at any time. Let’s say you want to match any pattern that looks like a phone number. Grep’s your solution[4]:

[[:digit:]]{3}[ -]\?[[:digit:]]{4}

BBEdit also supports grep searching through AppleScript. Which means a common search can also be tied to a hotkey trigger. For example, a hotkey to automatically select the current word.

Sure, there are good tools for Textmate, like AckMate, but grep is part of BBEdit’s DNA.

BBEdit also supports a beefed up version of good ’ol “Find”, called “Live Search”. when using Live Search, BBEdit begins highlighting matches in the text, as the search term is entered. It’s impressive to see, partly because it is so darn fast. It’s instantaneous on a 1000 paragraphs of text.

Markers

BBEdit provides quick access to functions through a dropdown document menu. When working in Markdown, the menu displays all of the headings with an integer to indicate the heading level. This is nothing ground breaking but it’s nice.

But BBEdit takes quick access one step further with document markers. Markers are like bookmarks within a document. They are invisible in the document text but BBEdit tracks and displays a list of markers when needed. It’s subtle, but very handy. For example, if I’m not happy with a specific piece of text, I can mark it to review later. Another way I’ve been using this feature is to take a break from one section and work on something else. Before I start a new paragraph, I mark the text that I want to revisit. Later, I browse my list of markers to refresh my memory.

The Bad

So it’s not all milk and honey with BBEdit. While I’ve been able to move to BBEdit full time[5] there are still some rough spots.

AppleScript

AppleScript support in BBEdit is both the best and worst things. Almost every function of BBEdit can be accessed through AS. That seems to come at a price though. Unlike Textmate bundles or Sublime Text[6] which can be written in any language, BBEdit is weighed down by AppleScript, which is not versatile or mature enough to do real work. AppleScript is awkward and poorly defined in comparison to other scripting languages. There are too many non-obvious limitations and options. I never know when I should “Tell text of front text window” or more generally “tell front text window”. These are apparently two different things that are only discovered through trial and error.[7]

There’s a lot of AppleScript legacy with BBEdit and it’s likely to remain part of the application until Apple kills it off. I’d like to see BBEdit support additional scripting languages to work on documents.

Color Schemes

BBEdit supports several text coloring options through their Codeless Language Model and their BBColor color schemes. These are nice, but fairly limited. Since BBEdit supports such great grep processing, it seems like that could be leveraged to provide syntax highlighting that is not bounded by a programming language model. For example, why is the Markdown highlighting defined by keywords, numeric constants, string constants and other terms more appropriate for a programming language? I’d like to see a syntax highlighter based on pattern matches that are more general. I’ve found a number of color schemes around the internet but there is no good single source. The closest to a single source I have found is on Github.

Scripting Documentation

The documentation for scripting BBEdit is just “good enough”. Most of what I learned was through extensive Google searching. Many of the examples are very old. There does not appear to be a single repository of AppleScripts to pull from. For an application with such extensive AppleScripting support, it’s frustrating to not have a single repository of examples. However, the Google group for BBEdit is very good and the responses are quick and helpful.

Conclusion

It was worth the investment. I don’t mean just monetarily. I invested many hours into BBEdit and I’m sure there are many more to come. But it was worth it. I have an environment that I feel productive in. I’ve customized it to my exact needs but I’m still producing plain text and working with my other favorite applications like Marked, Simplenote, Dropbox and NVAlt. For the most part, the environment is portable to another Mac, by copying my BBEdit support directory to the new machine.

Advice

I’ll try to avoid the holy wars of text editors and skip the preaching that is abundantly available on the Internet. But if you came here for some advice, I’m happy to share what I think. BBEdit works for me right now. I trust the developers and the product to stick around and keep up support. BBEdit is not the cool new editor on the block, but it is comfortable, dependable and powerful. It has some nice styling and some thoughtful features. In the end, it’s just a damn text editor, albeit a very good one.


  1. For a discussion of migrating from Textmate to BBEdit, hit the BBEdit Google group.  ↩

  2. This is my test footnote  ↩

  3. Yes, I know. Just like TextExpander. I think this is more powerful than TE’s implementation though. In BBEdit, the script is embedded inside the snippet.  ↩

  4. Awk’s cool too. Please don’t email me.  ↩

  5. By “full time” I mean at my Mac. I don’t use a Mac at my day job and I also do a good bit of work on my iPad and iPhone.  ↩

  6. Yes, I own Sublime Text 2. It’s the best option for Windows.  ↩

  7. See this discussion on the BBEdit groups for example. This was pretty frustrating while trying to discover the proper way to phrase the script.  ↩


2
Jan 12

AppleScript-Cocoa Over PyObjC?

What’s more odd to me, is that Apple has dropped the PyObjC support but gave AppleScript a giant boost with Cocoa-AppleScript. Don’t get me wrong, I like AppleScript fine, but it sure isn’t as flexible as Python or Ruby[1].

Anyway, if your thinking about making any AppleScript-Cocoa projects, here’s a very good tutorial over at MacScripter.

 

UPDATE: There are also great resources over at MacAutomation.com, including what looks like a good book.


  1. I know about MacRuby and it’s the best reason yet for me to start thinking about Ruby over Python. I only have so much free time, and almost no work time to invest in learning a new language.  ↩

30
Dec 11

Junecloud Automator Actions

Junecloud makes the terrific Delivery Status widget and Delivery Status Touch for iOS. If you do a lot of package tracking, these are the best tools available.

But I noticed that they also provide a free set of Automator actions that are very handy.

  • “Save for Web” generates images with specific size and quality settings.
  • “Make Names Web-Friendly” replaces spaces and other special characters to web friendly characters such as underscores.
  • “Create Clean Archive” makes a zip archive but removes all of the resource forks and Mac specific cruft.
  • “Create Symbolic Link”

Good stuff.


26
Dec 11

Scripting Bridge Redirect

A funny thing happened when I was reading through references for Python on OS X. Dr.Drang had a link to Apple’s Scripting Bridge page. The funny part is that Apple appears to now redirect that page to the Automator page. It doesn’t give me a lot of confidence in learning the Scripting Bridge.

Here’s the new home.


22
Dec 11

Timestamps in AppleScript

AppleScript is easy for most basic file manipulations on the Mac. For example, I can get a files modification timestamp with the following bit of AppleScript:

set modificationDate to modification date of this_item

where “this_item” is a reference to a file. “modificationDate” now contains a value like “Wednesday, December 21, 2011 7:24:22 PM”

But that’s a pretty awkward timestamp if I want to use it to name a file. In AppleScript, reformatting a timestamp is awkward and tedious. I often resort to other options. I have two preferred methods.

AppleScript -> Shell

Embeding a bit of shell script into AppleScript is easy. Here’s an AppleScript handler that takes a date like the one above and returns a nicely formatting compact timestamp

on FormatTime(AS_Date)
        return (do shell script "date -j -f '%A, %B %e, %Y %l:%M:%S %p' '" & AS_Date & "' '+%Y%m%d_%H-%M-%S'")
end FormatTime

where “AS_Date” is the native AppleScript timestamp. This works, but it’s not very universal. The AS_Date must always be in the format of ”Wednesday, December 21, 2011 7:24:22 PM” or the script will throw an error.

So I have another bit of AppleScript that relies on Python to do the hard bit of parsing a date and returning a formatted timestamp

AppleScript -> Shell -> Python

That’s right, AppleScript runs a shell command, which in turn calls the Python processor. Now that Python is running within the AppleScript, I have access to some of the best date and time libraries around. Specifically, the dateutil never disappoints.

on pyFormatTime(AS_Date)
    set timeFormat to quoted form of "%Y%m%d_%H%M%S"
    return (do shell script "/usr/bin/python -c \"import time, dateutil.parser; print dateutil.parser.parse(" & AS_Date & ").strftime(" & timeFormat & "); \"")
end pyFormatTime

In this case, the AppleScript handler can accept any kind of date without knowledge of the format. It can then process the date and return a timestamp in my preferred format. For example all of the following dates will give the same timestamp:

  • “12-21-2011 7:24:22 PM”
  • “12-21-2011 19:24:22″
  • “12/21/2011 7:24:22 PM”
  • “Dec 21, 2011 7:24:22 PM”

If I wanted to get really fancy, I could also use parsedatetime to accept even more awkward date formats and return a specific timestamp. No need to go crazy though.