Am I Being Punked?

The title is what I was saying to myself as I built a couple of scripts for a twitterfriend. Guy had asked about printing to n-up PDF from Keynote via AppleScript. I happened to have Pages running so I started poking about.

First, you have to print to do n-up PDFs. The export to PDF function in any iWork app is incapable of doing that. Okay, that’s a pain in the ass, but sure, I can justify that, n-up is traditionally the realm of printing. But, at least with the basic “print” command, you can get most of the way there:

tell application "Pages"
	set theDoc to the first item of every document
	--the "ignoring is needed so the script doesn't stall at the dialog
	ignoring application responses
		print theDoc with properties {pages across:3, pages down:2} with print dialog
	end ignoring
end tell

This is pretty straightforward. The only odd bit is the “ignoring” part. That’s in there because otherwise, the script will pause forever on the print sheet.

Now, if you have a PDF printer already set up, and it’s your default, then you redo the print statement to not display the print dialog, et voila, you have a PDF, (depending on how said printer handles saving.)

If you don’t have a PDF printer set up, then we have to do a bit of UI scripting. This is tedious for a few reasons that I’ll get into after the code.

--System Events manages ALL UI scripting
tell application "System Events"
     --target  pages
     tell its application process "Pages"
          --obviously for your needs, 
	  --you'd have to manage window targeting
          --since you have to do it by name
	  tell its window "johnwelch.pages"
	       --talk to the existing print sheet from 
	       --the tell keynote/pages block
	       tell its sheet 1
	            set theMenuButton to its menu button "PDF"
	            --expand the button
		    click theMenuButton
		    --go down twice
		    key code 125
		    key code 125
		    --hit return which brings up 
		    --another sheet 1
		    key code 36
		    --gives the sheet time to display
		    delay 5
				
		    tell its sheet 1
		         --this saves. I have no way to 
			 --deal with overwriting files 
			 --without doing more targeting.
			 --this is so messed up.
			 tell its button "Save" to click
		    end tell
	       end tell
	  end tell
     end tell
end tell

It’s fairly straightforward. There’s a document (*.pages) with print sheet (sheet 1). This is the first issue. Give this a better name. “Print Sheet” maybe? Because as we’ll see, this sheet can have a sheet and what is its name? Right, sheet 1.

Minor fail there. It would be better for the name to be descriptive. Then we tell UI scripting to click on the menu button “PDF”. This is the second failure, but only a partial one. Depending on the machine, this menu can have a number of different items, but there are some that are static, namely:

  1. Open In Preview
  2. Save as PDF
  3. Save as PostScript

I should be able to directly access those. (Honestly, the menu isn’t that dynamic. It would be pretty easy to determine the number of items before it opens. As it stands now, until you click on it, it has…zero items. So we have to do two down arrows (key code 125) and a return (key code 36) to select the right option. Being able to directly click a menu item by name is much better, and would make this much more simple.

If I could do more in the print command, like have a property that was “Save as: PDF” with an element that took an alias or fURL, that would be even better, because then the entire UI scripting block would literally not be needed. But it doesn’t, so it is, and why not just make things easier? This would also probably be a help for accessibility, something of minor importance to Apple, or so I hear.

Now, we’ve “clicked” on “Save as PDF” which gives us a sheet for sheet 1 named? Right, “sheet 1”. Begin to see why I think that name is a bad idea? Like maybe name this one “Save as PDF”. I dunno where I’ve seen that before, but it seems logical. But I’m sure “sheet 1 of sheet 1” is better. I eagerly await the explanation of how.

Note, this does nothing to handle “a file with that name already exists.” I’m sure you can handle that via UI Scripting, but as we’ll see in the Keynote section, I just don’t feel like doing the extra work.

So I get done with this, and I’m excited, because Keynote should be about the same. Minor changes in terms of tell block and System Events targeting, Bob’s your Uncle.

Bob Is Not Your Uncle

In fact, Bob is so not your Uncle, he’s at someone else’s house being their uncle, and they are all laughing at you for you have no Bob to be your uncle.

Keynote’s accessibility is a shameful mess. I don’t say that lightly. Here’s the first part:

tell application "Keynote"
     set theDoc to the first item of every document
     ignoring application responses
          --the "ignoring is needed so the script
          --doesn't stall at the dialog
          --note that Keynote ignores the n-up 
          --properties because pound sand, that's why
	  print theDoc with properties {pages across:3, pages down:2} with print dialog
     end ignoring
end tell

Our first sign we’re in trouble is that Keynote ignores the n-up settings in the print command. Oh, it looks good in the UI, but if you save that to a PDF without taking further action, you do not get what the UI says you will. This is the first, cardinal, unforgiveable sin of development:

Never Lie To The Human

There’s no excuse for this. None. But Keynote lies to you here. Which is a shame, because you now have to undertake a journey of purest suck.

tell application "System Events"
     --target keynote
     tell its application process "Keynote"
          --obviously for your needs, you'd have 
	  --to manage window targeting
	  --since you have to do it by name
	  tell its window "Open House Preso.key"
	       --talk to the existing print sheet
	       --from the tell keynote/pages block
	            tell its sheet 1
		    --this is where you select a 
		    --grid layout. No, it has no
		    --goddamned name.
		    --no, i don't know why.
		         tell its checkbox 2 to click
		         --oh, you thought the "how 
			 --many slides per page" popup 
			 --had a name? LOL
			 --it's pop up button 1 of group 3
			 --because THAT'S NOT FRAGILE
			 tell its group 3
			      tell its pop up button 1
			      --expand the button
			      click
			      --go down one option
			      key code 125
			      --hit return
			      key code 36
			 end tell
		    end tell
		    set theMenuButton to its menu button "PDF"
		    --expand the button
		    click theMenuButton
		    --go down twice
		    key code 125
		    key code 125
		    --hit return which brings up 
		    --another sheet 1
		    key code 36
		    --gives the sheet time to display
		    delay 5
				
		    tell its sheet 1
		         --this saves. I have no way 
		         --to deal with overwriting files 
			 --without doing
			 --more targeting. this is so messed up.
			 tell its button "Save" to click
		    end tell
	       end tell
	  end tell
     end tell
end tell

SIGH…

Where oh where do I start?

Well, what the hell, when you’re in a swamp, it doesn’t matter which way you walk, you’re getting gunk in your shoes. So to click on “Grid” which is the only way to get n-up printing, even though, as you recall, we had told Keynote to print n-up and it looks like it will, it is again lying to us. So we have to do this.

According to System Events, “Grid” is checkbox 2 of sheet 1. Now, let us be clear on what we’re talking about here…

That is a mighty strange checkbox

I have seen stupid and I have been stupid and I have never seen a checkbox that looks like that. This is a checkbox:

Look! Checkboxes!

Yes, I know, you can have pictures, but come on. First, everything in that grouping is mutually exclusive. I can’t select slide AND grid or grid AND outline. So even allowing for pictures, those aren’t checkboxes, they’re flibbertygribbin’ radio buttons. So again, again, Keynote’s UI is lying. But even worse, want to know what the name of the “Grid” “checkbox” is? Checkbox 2. No, really, that’s the name.

Accessibility fail, and you don’t have to take my word for it, here, from the accessibility inspector:

HAH! IT’S NOT JUST MEEE-EE

Apple’s. Own. Accessibility. Inspector. is pointing out this problem. So it’s not only not a checkbox, it’s badly done accessibility-wise, and it makes scripting it fragile, because what if something changes and it’s no longer checkbox 2, it’s now pop up button elebenty? (I mean, if you’re going to lie about what something is, go big.) Oh look, you have to rewrite. ]

But wait, it gets better. So along with an accessibility audit fail, what does the actual inspector tool think this is? Well, let’s see…

Oh well, that makes sense, according to the Accessibility Inspector it’s a toggle button with a role of AXCheckBox that behaves like a radio button, that’s totally logicalAAAAAAAAAAAAAGAHWHAT IS GOING ON HERE, WERE YOU ALL HIGH?

Like, I’m trying to be nice here, but this is just awful. This is just a single control that has two different type values, no name and a role that makes no sense, and IF YOU WOULD JUST GIVE IT A LABEL, A TITLE, AND SOME HELP TEXT I WOULDN’T HAVE LOST TEN YEARS OFF MY LIFE SPAN NOT PUTTING MY HAND THROUGH THE SCREEN OF MY LAPTOP.

How does this get approved? I mean, Apple cares about accessibility, they’re hiring loads of accessibility people and this passes muster? Mind you, there’s four controls in this group.

we’re not done

Since we have now managed to select grid via equal amounts of magic and luck, we have a pop up that lets us select how many images per page. The default is four. Surely that has a name we can use, I mean it’s part of the “Grid Layout:” group, right?

Right?

Please?

Oh gods.

Nope. It’s pop up 1 of group 3. I mean, it’s not like it has a real name:

Saved from a life of sloth

Yeah. So…yeah. I mean, the accessibility audit is polite about it but even it is throwing up its hands at it all:

Bob will never be your uncle

Once you get to where you’ve “clicked” on pop up 1 of group 3 (such an intuitive name, I shall remember it always), then it’s generic up/down arrow keystrokes and the enter keystroke and you’re out of this grotty hell and “clicking” away on the PDF menu item button tra-la-la, time to get ragingly drunk so as to forget this ever happened.

There’s no excuse for this…mess. I am not a coder. I can beat on ASOC/Python/Bash to get things done, and I’m attempting to learn Swift (on macOS, so we all know I’m doomed, because heaven forfend the gods of coding education stoop to making tutorials for the Mac.) But I am not a coder/dev/whatever by any means. Which means this issue is so obvious, so pronounced that you do not need terribly special skills to spot it. By “spot it” I mean get thoroughly Bog’d.

I just wanted to write a script to do a fairly simple thing and found…this. I don’t even know where to begin to report the bugs on this, there are no less than eleven separate accessibiity bugs in the print dialog alone, along with the print script command bug and the feature requests that would make this all go away.

Where, exactly, do I begin? Because I do have things to do. Like not be found dead at my laptop with the feedback assistant waiting patiently for the next item in the list.

Look, clearly the iWork team needs some QA people for their UI accessibility stuff. And scripting stuff. Y’all should maybe give me a call, send me an email, I appear to have skills you desperately need. We can fix this, it is totally fixable, fixing it is necessary. So let’s do this?

Advertisements