Mimsy: Hacks

What app keeps stealing focus?—Friday, January 8th, 2016

I’ve been having a problem lately on Mac OS X Yosemite, 10.10, with losing focus on the window I’m typing in. Most of the time it didn’t happen often; sometimes it would happen three or four times over several minutes. The screen doesn’t change: the menu bar still tells me I’m in Safari or iA Writer or whatever.

A quick Google search on “Mac OS X application window keeps losing focus” and I found I wasn’t alone. The problem seems to be that some background app is stealing the focus, but since it’s a background app the menu doesn’t change from the current app.

On How do I tell which app stole my focus in OS X?, medmunds provided a neat little Python script for displaying the current active app as soon as the active app changes. It also displays the path to the app so that you know specifically where the offender lies.

I quickly realized that I keep a lot of windows open, and the Terminal window soon disappeared behind all of my working windows. Obviously once I noticed a focus change, I could go back to Terminal to see what it was, but if it happened while I was reading a web page, I might not notice it for a long time—scrolling doesn’t even need focus to work.

So I did another search on “Python Mac OS X speak” and found an answer by arainchi that should, and did, allow importing the Mac’s built-in speech synthesizer software. I added a volume reduction (hearing a loud voice announcing the app change every time I switched an app became annoying very quickly) and improved the responsiveness of the script. Mac OS X Python supports fractional sleep times, so I reduced it to two-tenths of a second instead of a whole second.

Draw a circle on an iPad map from three points in Pythonista—Tuesday, December 1st, 2015

I happened across a copy of 57 Practical Programs & Games in BASIC while traveling a month ago, and was once again fascinated by the simple toolchests we used back in the seventies and eighties. I fooled around with it a bit, typing up the programs in HotPaw BASIC on the iPad. I now have the BASIC code in HotPaw necessary to tell what day of the week any date, post 1752, fell on, as well as a Chi-Square evaluator that I’ll probably never use.

Day of the week in HotPaw BASIC

While reading through it, I came across the code for Circle determined by three points and thought about how cool it would be to use that simple code on modern mobile tools. It should be a snap to write an on-the-fly app in HotPaw BASIC or Pythonista. Take a snapshot of a map, tap three points, and see what the circle is.

HotPaw BASIC does not appear to have access to the iPad’s photo library, but Pythonista does. It has a photos module that allows you to pick_image and several methods in the scene module for simple manipulations and display.

The code itself is pretty simple. Create a scene, override touch_end to capture points (touch_end is similar to onClick in JavaScript), and the BASIC code from 57 Programs converted to Python, to determine the center and radius of a circle given three points on the screen.

icalBuddy and eventsFrom/to—Wednesday, August 19th, 2015

I use icalBuddy extensively along with GeekTool to display events on my desktop. I have the fairly standard sort of “here are your upcoming events”:

  • icalBuddy --excludeCals Television --excludeEventProps url --dateFormat "%A" --includeOnlyEventsFromNowOn eventsToday+4

This shows everything from the rest of today through four days from now. But you’ll notice it excludes one calendar: I really don’t need to see a list of the television shows I sometimes watch. They’re not that important to me.

Up until about a week ago, I showed only television shows for today:

  • icalBuddy --includeCals Television --excludeEventProps url --dateFormat "%A" --includeOnlyEventsFromNowOn eventsToday

And it worked fine, until the local old movies television station had William Castle’s classic 13 Ghosts on at 1:20 AM a few weeks ago. I missed it, because 1:20 AM isn’t today, it’s tomorrow. But by the time I look at it tomorrow morning, 1:20 AM is long gone.

I initially changed it to “eventsToday+1”, but that clutters up my desktop with events for tomorrow night, which I don’t need to know about now. I don’t plan my life around television shows, I just want to know if there’s something interesting right now. What I really want is for today’s list to include until tomorrow morning. The icalBuddy man page indicates that it’s possible to specify a range that includes an hour on a relative end date, but the documentation is currently wrong. For the option “eventsFrom:START to:END”, it says:

Print events occurring between the two specified dates. The dates (START and END) may be specified in a natural language form (such as "tomorrow at noon" or "june 10 at 6 pm") or as relative dates (such as "today+3" or "yesterday-2") but the safest format is "YYYY-MM-DD HH:MM:SS +HHMM"

Specifying tomorrow at noon, or tomorrow at 8 am, or tomorrow at anything just shows everything from tomorrow. A quick use of --debug confirmed it: icalBuddy interprets “tomorrow at” anything to be “[tomorrow] at 11:59:59 PM Central Daylight Time”.

I verified, however, that the to: option can accept partial days, by using the actual date (August 20 at 7 pm, for example), so I messed around until I found a format that works. Rather than “tomorrow at time”, use “time at tomorrow”:

  • icalBuddy --includeCals Television --excludeEventProps url -f --dateFormat "%A" --includeOnlyEventsFromNowOn eventsFrom:today to:"noon tomorrow"
  • icalBuddy --includeCals Television --excludeEventProps url -f --dateFormat "%A" --includeOnlyEventsFromNowOn eventsFrom:today to:"9 am tomorrow"

The first is interpreted as noon tomorrow, and the second as 9 am tomorrow, only showing things in the morning from tomorrow instead of all day.

Retry SSH connections after transient error—Monday, October 20th, 2014

The Timeout class works great for retrying connections after they timeout, but what about more prosaic errors? I’ve been getting a bunch of AuthenticationException errors in my Python/Paramiko connection attempts lately. I’d been just capturing all SSHExceptions (of which AuthenticationException is a subclass) and reporting the error, but this is just a transient error that almost always goes away on the very next upload.

That makes it a perfect candidate for retrying the connection. I renamed the class from Timeout to Persistence, because this more generic class is going to be more persistent at making connections.1

[toggle code]

  • from paramiko import SSHException, AuthenticationException
  • class Persistence(object):
    • def __init__(self, function=None, seconds=30, tries=3, errorMessage='Timeout'):
      • self.seconds = seconds
      • self.tryLimit = tries
      • self.tries = 1
      • self.function = function
      • self.errorMessage = errorMessage
    • def act(self):
      • signal.signal(signal.SIGALRM, self.handleTimeout)
      • signal.alarm(self.seconds)
      • try:
        • self.function()
      • except AuthenticationException, error:
        • self.tryAgain(AuthenticationException(error), 'Authentication exception')
      • signal.alarm(0)
    • def tryAgain(self, exception, message):
      • if self.tries >= self.tryLimit:
        • raise exception
      • else:
        • print message, 'try', self.tries, self.errorMessage
        • sleep(2*self.tries)
        • self.tries = self.tries + 1
        • self.act()
        • print 'Succeeded on try', self.tries
    • def handleTimeout(self, signum, frame):
      • self.tryAgain(TimeoutError(self.errorMessage), 'Timed out')

All it really does is add a tryAgain method that can be called both by the handleTimeout method and any exceptions in try/except. If the failure continues more than three times, the exception is passed back up as normal.

AppleScript, variables, and dropped filenames in Automator—Monday, October 6th, 2014
Prepend Disclaimer workflow

Simple workflow to prepend a known PDF to an arbitrary dropped PDF.

Over on Stack Overflow the other day, someone asked an intriguing question about wanting to prepend a disclaimer page to hundreds of PDF files. Now, merging multiple PDFs into a single PDF is the kind of task Automator excels at, and it’s very easy to do. Appending a single page to multiple PDF files, however, is a classic loop. This is not something Automator excels at. It requires thinking outside the workflow.

The basic workflow is an application—application workflows take dropped items and do things with them.

  1. Get Specified Finder Items (the disclaimer)
  2. Combine PDF Pages (appending pages)
  3. Move Finder Items (to a special folder created for the combined items)
Disclaimer Loop workflow

Automator can loop through dropped items one at a time using Run Workflow.

However, this only works for one file at a time. How to prepend the disclaimer to hundreds of files? Automator has a loop workflow action, but all it does is go back to the beginning of the workflow. It doesn’t do anything to incrementally loop through the list of dropped files. For that, we need the Run Workflow action. This runs a different workflow, and can send its own dropped items one at a time to that second workflow.

But, there’s a second problem: the Combine PDF Pages action creates files with a random filename. There is no option to tell it to take one of the dropped files and use that as its new filename.

Automator has some very impressive variable options: there are variables that are really AppleScripts, variables that are really shell scripts, variables containing many system names and common system paths. There is no variable that contains the dropped filename, however, and the AppleScript/Shell Script variables don’t take any arguments. As far as I can tell, the variables are all, basically, static, even if in a dynamic way. There is, thus, no way to modify the dropped file’s path using either an AppleScript variable or a Shell Script variable in order to get the dropped file’s base name.

Two search bookmarklets for Django—Tuesday, August 19th, 2014

I run this site through a Django CMS. I often find myself looking for the most recent pages. Now, by default, the most recently edited pages show up at the top, and of course I can link a URL that specifically orders by when pages were added, but there is no way to limit it just to, say, the pages I’ve created this month. Even when I create only a few pages a month, which is normal, those views will still show, in my case, the hundred most recent pages. I’m not aware of a query parameter that will limit the number of results, nor of a query parameter that will only show within the last x days of a date field.

It is possible to show only a single month, but not to show only the current month. Any such bookmark will be out of date once the next month comes around. A JavaScript bookmarklet, however, can do this:

  • javascript:today=new%20Date();recentURL='https://django.localhost/admin/cms/page/?created__month='+(today.getMonth()+1)+'&created__year='+today.getFullYear();window.location=recentURL;

I also find myself going to the main list of pages and then doing a search. A bookmarklet can go directly to the search:

  • javascript:searchTerm=window.prompt('Search%20for?');searchURL='https://django.localhost/admin/cms/page/?q='+searchTerm;window.location=searchURL;

This will prompt for the search term and then construct a search URL with that term. It does not specifically encode the term, but I’ve tested it in Safari, Firefox, and Chrome and it works.

BASIC video decoder ring—Sunday, August 10th, 2014

I’ve been fooling around with BASIC a bit after getting HotPaw BASIC for iOS. First things were getting Mastermind (80 Microcomputing, October 1981, p. 122) and the infamous Super Star Trek BASIC programs working. I can now use my 64-gigabyte iPad 2 as a 1978 TRS-80 Model I.

One of the things I always had in mind back in the day but never got around to1 was a cipher decoder assistant. Over time, a cipher decoder seemed more and more pointless—who uses ciphers in the age of public keys?

Here’s a simple encipher program in Python for Editorial:

  • #coding: utf-8
  • import workflow
  • from random import shuffle
  • from string import ascii_lowercase
  • originalText = workflow.get_input().lower()
  • letters = list(ascii_lowercase)
  • cipher = list(ascii_lowercase)
  • shuffle(cipher)
  • cipher = dict(zip(letters, cipher))
  • cipheredText = ''
  • for letter in list(originalText):
  • if letter in cipher:
  • cipheredText = cipheredText + cipher[letter]
  • else:
  • cipheredText = cipheredText + letter
  • workflow.set_output(cipheredText)

This will shuffle the letters of the alphabet and use the new shuffling as the cipher. This puts it one step above a video decoder ring, which only had 25 possible ciphers.

The BASIC code acts as it would on any old computer of the era. It waits for text commands and prints out the currently-guessed cipher letter by letter and then the currently-guessed deciphered text.

HotPaw Basic on iOS—Sunday, July 13th, 2014

While looking at Chipmunk Basic yesterday, I noticed that Ron Nicholson also has a BASIC for iOS, HotPaw Basic. I’m not sure how useful it is, but it’s insanely fun. It appears to be based off of the Chipmunk code, and so works similarly. It also includes functions for accessing the touchscreen, the accelerometer, and the GPS location.

This is very simple code for drawing random circles wherever you’re touching the screen.

Compared to the other programming environment I have on my iPad, Pythonista, the built-in editor is archaic. It’s one-line-at-a-time editing pretty much just like I remember it from the early eighties—but even toward the late eighties, I was using a full-screen BASIC editor on OS-9. This is more like the old interactive BASICs where you replaced a line by retyping that line number; you can also edit a line by typing “edit” and the line’s number.

Type just the line’s number to delete that line.

Just like in the old days, it is very easy to program an endless loop; however, even these tiny computers we carry in our pockets are so fast that an endless loop can be impossible to break out of. My initial circles program just drew random circles at random locations on the screen; it locked up HotPaw Basic—the Stop button failed to work. Unlike the old days, however, one rogue program is less likely to lock up the entire system. The iPad itself experienced no slow-down and I was able to easily exit HotPaw Basic and restart it.

HotPaw automatically saves your current program in “tmp.bas”. You can also save it using the “save” command, load new ones using the “load” command, and view all programs using “dir”.

It does not support iCloud, which means that programs written on the iPad do not automatically transfer to the iPhone or other devices.

If you’re one of those people who look back fondly on BASIC, or if you have some BASIC programs you’d like to run on your iPhone or iPad, take a look at it. Most of the other BASIC languages I’m seeing on the app store are recreations of specific computers of the past, such as Commodore BASIC, or don’t even look like BASIC any more. Chipmunk Basic, while hardly modern, has been and continues to be updated for use today.

Older posts.