A small adjustment to SnapClip

As I buy more business supplies online and fewer in regular retail stores, I find myself taking more screenshots of digital receipts to attach to my expense reports. My SnapClip Keyboard Maestro macro (along with its predecesor scripts) has been my go-to utility for this, even though I originally wrote it mainly to capture screenshots of windows for posting here on the the blog. Because my pattern of use has changed, it seemed like a good time to give it a couple of tweaks to make it faster to use for its most common task.

The purpose of SnapClip is to give me a one-stop keyboard macro for screenshots that aren’t intended to be immediately uploaded to the leancrew server. It handles the following types of screenshot:

The changes I’ve made recently have been the addition of saving to a file and switching the default from window capture to rectangle capture. A small change in focus to better fit how I work now.

SnapClip is triggered by the ⌃⌥⌘4 keystroke combination. Like the built-in ⇧⌘4, it starts by presenting a crosshair for selecting a rectangular area but can be switched to window capture mode by tapping the spacebar. Once the rectangle or window has been selected, SnapClip presents the following dialog:

SnapClip dialog

The defaults are to save the image to the clipboard only and to not add a blue background border. Strictly speaking, I don’t need SnapClip to handle this default condition. Using the standard ⇧⌘4 capture and holding down the Control key when making the selection will put the screenshot on the clipboard instead of saving it to a file. The advantage of SnapClip is that I can do more than the built-in screen capture with a single keystroke combination.

I generally don’t use the background border option when taking rectangular screenshots, but I do like adding the border when taking window screenshots. It changes the screenshot from this

Screenshot without border

to this

Screenshot with border

Turning on the file saving option saves a copy of the screenshot to the Desktop with a filename in yyyymmdd-HHMMSS.png format. I do this when I expect to need the screenshot more than once. I may, for example, paste it immediately into a tweet or text message but also expect to incorporate it into a blog post or an email later.

That’s what SnapClip does. Here’s how it’s made. It is, as I said, a Keyboard Maestro macro:

Keyboard Maestro SnapClip macro

The only action in the macro is this Python script:

 1:  #!/usr/bin/env python
 3:  import Pashua
 4:  import tempfile
 5:  from PIL import Image
 6:  import sys, os
 7:  import subprocess
 8:  import shutil
 9:  from datetime import datetime
11:  # Local parameters
12:  type = "png"
13:  localdir = os.environ['HOME'] + "/Pictures/Screenshots"
14:  tf, tfname = tempfile.mkstemp(suffix='.'+type, dir=localdir)
15:  bgcolor = (61, 101, 156)
16:  border = 16
17:  desktop = os.environ['HOME'] + "/Desktop/"
18:  fname = desktop + datetime.now().strftime("%Y%m%d-%H%M%S." + type)
20:  # Dialog box configuration
21:  conf = '''
22:  # Window properties
23:  *.title = Snapshot
25:  # Border checkbox properties
26:  bd.type = checkbox
27:  bd.label = Background border
28:  bd.x = 10
29:  bd.y = 60
31:  # Save file checkbox properties
32:  sf.type = checkbox
33:  sf.label = Save file to Desktop
34:  sf.x = 10
35:  sf.y = 35
37:  # Default button
38:  db.type = defaultbutton
39:  db.label = Clipboard
41:  # Cancel button
42:  cb.type = cancelbutton
43:  '''
45:  # Capture a portion of the screen and save it to a temporary file.
46:  status = subprocess.call(["screencapture", "-io", "-t", type, tfname])
48:  # Exit if the user canceled the screencapture.
49:  if not status == 0:
50:    os.remove(tfname)
51:    sys.exit()
53:  # Open the dialog box and get the input.
54:  dialog = Pashua.run(conf)
55:  if dialog['cb'] == '1':
56:    os.remove(tfname)
57:    sys.exit()
59:  # Add a desktop background border if asked for.
60:  snap = Image.open(tfname)
61:  if dialog['bd'] == '1':
62:    # Make a solid-colored background bigger than the screenshot.
63:    snapsize = tuple([ x + 2*border for x in snap.size ])
64:    bg = Image.new('RGB', snapsize, bgcolor)
65:    bg.paste(snap, (border, border))
66:    bg.save(tfname)
68:  # Put the image on the clipboard, save to Desktop if asked for,
69:  # and delete the temporary file.
70:  impbcopy = os.environ['HOME'] + '/Dropbox/bin/impbcopy'
71:  subprocess.call([impbcopy, tfname])
72:  if dialog['sf'] == '1':
73:    shutil.copyfile(tfname, fname)
74:  os.remove(tfname)

The script uses two nonstandard Python modules:

  1. Pashua, which provides bindings to Carsten Blüm’s lovely Pashua utility for creating dialog boxes from short textual descriptions.
  2. Image from the Python Imaging Library, which, as its name suggests, provides image editing commands.

The script also calls impbcopy, Alec Jacobson’s command line utility for putting the contents of an image file onto the clipboard.

You’ll need all of these utilities and modules installed if you want to run your own SnapClip.

Most of the script was described in my post from last year. The differences between then and now are relatively minor:

If you’ve been reading ANIAT for any length of time, you’re sick of hearing me say this, but I’ll say it anyway. The great advantage of building your own tools is that you can make them fit exactly how you work. Even if how you work changes.