Yesterday I was reading Dan Frakes' "Plain Clip revisited" MacGem post, which explains how to use the free (donations excepted) Plain Clip utility with TextExpander to automatically paste whatever is in the clipboard with any formatting information removed when you type "ptp" (which is the abbreviation he chose to assign to this "snippet" in TextExpander). I need to do that occasionally (and again, I've been doing it by pasting into BBEdit and then copying back to the clipboard), so I downloaded Plain Clip and a free trial of TextExpander and began setting it up. Dan Frakes uses an AppleScript to run Plain Clip through the command-line. But I noticed I can define a shell script in TextExpander so I don't need to bother with an AppleScript "do shell script" wrapper. But I couldn't get it to work. I quickly found a link in the comments to Gordon Meyer's "A tip for using Plain Clip with TextExpander" blog post, which solved the problem for me.
And that's when a light bulb finally went off in (over?) my head. If I created a simple command-line utility to do word wrapping, I could create a TextExpander snippet to paste quoted text. And about 30 minutes later that's just what I had.
When I need to create a command-line utility, I almost always turn to Python. And as is so often the case with Python's "batteries included" nature, I found a textwrap module that provided almost everything I needed.
Note that even though you can't see the code at the end of long lines, it's there. Just copy it all and paste it into your favorite text editor to read it all.
This script wraps the textwrap module with a command-line interface.
from textwrap import TextWrapper
DEFAULT_WIDTH = 70
DEFAULT_QUOTE_STRING = '> '
"""The entry function."""
parser = optparse.OptionParser(description='Text wrapper', prog='wwrap')
default='%d' % DEFAULT_WIDTH,
help='maximum length of wrapped lines; defaults to 70')
help="add '%s' to start of each wrapped line"
help='remove TXT from start of each line prior to'
help="remove '%s' from the start of each line prior"
" to wrapping" % DEFAULT_QUOTE_STRING)
options, arguments = parser.parse_args()
if not options.width:
print "I don't know how the width wasn't specified, since it's"
print "supposed to default to %d. Aborting." % DEFAULT_WIDTH
width = int(options.width)
print "ERROR: the width specified ('%s') is not a number" % (
if options.remove and options.removequotes:
print "ERROR: cannot use both --remove and --removequotes options"
options.remove = DEFAULT_QUOTE_STRING
wrapper = TextWrapper()
wrapper.initial_indent = DEFAULT_QUOTE_STRING
wrapper.subsequent_indent = DEFAULT_QUOTE_STRING
wrapper.width = width
lines = sys.stdin.read().split('\n')
for i, line in enumerate(lines):
lines[i] = line[len(options.remove):]
if __name__ == '__main__':
This code should be quite self-explanatory. As is (also) so often the case with Python, the "meat" of these 81 lines are the 7 lines starting with line 67 where I read in the text to be wrapped from stdin. All the preceeding lines are for handling the command-line options.
I put this in a file called "wwrap" and did a `chmod +x` on it. I then created a symbolic link to it in /usr/local/bin/, and I was ready to create my TextExpander snippet.
Now I can just type 'qtp' and the quoted, wrapped form of whatever text is in the clipboard is pasted in.
I'm inspired to look for more workflows I can simplify with TextExpander and possibly Python. (I'm going to start by trying to figure out how to re-create the "Create tr.im shortened URL" in Dan Frakes' TextExpander screenshot.)