Posts Tagged ‘applescript’

Save As Optimized PDF using Acrobat Pro via the command line

Saturday, January 2nd, 2016

Here’s a tremendously hacky way to automate the procedure of optimizing a PDF using Acrobat Pro (with default settings) from the command line. It’s an applescript sending mouse clicks and keyboard signals so don’t get too excited.

However, I’m doing this all the time and it will hopefully save clicking through menus.

#!/usr/bin/osascript
on run argv
    if (count of argv) < 2 then
        do shell script "echo " & "\"optimizepdf path/to/input.pdf simple-output-name\""
    else
        set p to item 1 of argv
        set out_name to item 2 of argv
        set abs to do shell script "[[ \"" & p & "\" = /* ]] && echo \"" & p & "\" || echo \"$PWD/\"" & p & "\"\""
        set a to POSIX file abs
        tell application "Adobe Acrobat Pro"
            activate
            open a
            tell application "System Events"
                click menu item "Optimized PDF..." of ((process "Acrobat")'s (menu bar 1)'s ¬
                    (menu bar item "File")'s (menu "File")'s ¬
                    (menu item "Save As")'s (menu "Save As"))
                tell process "Acrobat"
                    keystroke return
                    keystroke out_name
                    keystroke return
                    keystroke "r" using {command down}
                end tell
            end tell
            close document 1
        end tell
    end if
end run

Then you can run this with something like:

optimizepdf path/to/input.pdf simple-output-name

overwrite warning: this will overwrite the output file (and potentially files named similarly if the keystrokes fail or get garbled).

Oddly, it seems to work fastest if the input document is not already open in acrobat pro.

This code above is written for Acrobat Pro Version 10.1.16.

Update: Here’s a legacy version for Acrobat Pro Version 9.5.1

#!/usr/bin/osascript
on run argv
    if (count of argv) < 2 then
        do shell script "echo " & "\"optimizepdf path/to/input.pdf simple-output-name\""
    else
        set p to item 1 of argv
        set out_name to item 2 of argv
        set abs to do shell script "[[ \"" & p & "\" = /* ]] && echo \"" & p & "\" || echo \"$PWD/\"" & p & "\"\""
        set a to POSIX file abs
        tell application "Adobe Acrobat Pro"
            activate
            open a
            tell application "System Events"
                click menu item "PDF Optimizer..." of ((process "Acrobat")'s (menu bar 1)'s ¬
                    (menu bar item "Advanced")'s (menu "Advanced"))
                tell process "Acrobat"
                    keystroke return
                    keystroke out_name
                    keystroke return
                    keystroke "r" using {command down}
                end tell
            end tell
            close document 1
        end tell
    end if
end run

Note: You may have to enable scripts to use keystrokes.

Continuously refresh markdown output

Tuesday, June 17th, 2014

I had a hard time finding a chrome plugin for a rendering markdown which supported LaTeX equations. Instead I’m using multimarkdown which supports equations with mathjax. However, to render the html output I need to open it in Chrome and refresh it when anything changes. So my pipeline looks like:

repeat
  edit .md files
  run multimarkdown command
  open/refresh .html file in chrome
end

I found this nice ruby/applescript script.
I’ve modified it to support markdown files and to run a command when a file changes:

#!/usr/bin/env ruby
# watch.rb by Brett Terpstra, 2011 <http://brettterpstra.com>
# with credit to Carlo Zottmann <https://github.com/carlo/haml-sass-file-watcher>

trap("SIGINT") { exit }

if ARGV.length < 2
  puts "Usage: #{$0} watch_folder keyword command"
  puts "Example: #{$0} . mywebproject"
  exit
end

dev_extension = 'dev'
filetypes = ['css','html','htm','php','rb','erb','less','js','md']
watch_folder = ARGV[0]
keyword = ARGV[1]
command = ARGV[2]
puts "Watching #{watch_folder} and subfolders for changes in project files..."

while true do
  first = true
  while true do
    files = []
    filetypes.each {|type|
      files += Dir.glob( File.join( watch_folder, "**", "*.#{type}" ) )
    }
    new_hash = files.collect {|f| [ f, File.stat(f).mtime.to_i ] }
    hash ||= new_hash
    diff_hash = new_hash - hash
    if not diff_hash.empty?
      if first and not command.empty?
        val=`#{command}`
        first = false
      else
        break
      end
    else
      sleep 1
    end
  end


  unless diff_hash.empty?
    hash = new_hash

    diff_hash.each do |df|
      puts "Detected change in #{df[0]}, refreshing"
      %x{osascript<<ENDGAME
            tell application "Google Chrome"
    set windowList to every window
    repeat with aWindow in windowList
        set tabList to every tab of aWindow
        repeat with atab in tabList
            if (URL of atab contains "#{keyword}") then
                tell atab to reload
            end if
        end repeat
    end repeat
        end tell
ENDGAME
}
    end
    sleep 1
  end

end

Save this in a file watch.rb and then call with something like:

watch.rb . readme "multimarkdown readme.md -o readme.html"

Qt application launched in background, not stealing focus

Tuesday, April 22nd, 2014

We’re building a Qt executable (not an app bundle) with cmake. When running it feels like an application, dock icon, menu bar and all, but when it’s first launched from the command line with something like:

./my_app_exec

The application opens behind the terminal. The focus stays with the terminal. This was frustrating because then each time I launch the application I need to CMD+SHIFT+TAB to get to the application.

Here’s a dirty hack workaround. In my main function just after main_window.show() or whatever I add a bit of apple-specific applescript to do the alt tabbing for me:

mainWin->show();
#ifdef __APPLE__
    system("osascript -e 'tell application \"System Events\" "
      "to keystroke tab using {command down, shift down}'");
#endif

Change matlab current directory to match terminals current directory

Friday, January 17th, 2014

Here’s a little “one-liner” I’ve aliased to change the current directory in MATLAB to the current directory of a bash script in terminal. It uses applescript to send the cd command to matlab.

osascript -e "`echo -e \"tell application \\"MATLAB_R2013b\\"\ndelay 0.1\nactivate\ntell application \\"System Events\\"\n keystroke \\"   cd $(pwd)\\"\nkeystroke return\nend tell\nend tell\"`"

You may need to fiddle with the delays on your machine.

I alias this to cdmatlab by playing this at the bottom of my ~/.profile:

alias cdmatlab='osascript -e "`echo -e \"tell application \\"MATLAB_R2013b\\"\ndelay 0.1\nactivate\ntell application \\"System Events\\"\n keystroke \\"   cd $(pwd)\\"\nkeystroke return\nend tell\nend tell\"`"'

Automatically quit Papers (or any app) after long idle time

Friday, August 9th, 2013

I use the Papers app to organize my academic papers and Dropbox to “sync” Papers’ Library between my home and work computers. Only Papers will freak out if I try to open it on both computers. Papers: your library is currently in use. If I have access to Internet then I can just remote desktop or ssh into the other computer and quit papers. But if I’m offline then I’m locked out of Papers or I run the risk of screwing up its database. To solve this I wrote a little script that I run every five minutes. It checks if the computer is idle for a while then shuts down Papers. Save this in a file called quit_app_on_idle.app:

on run argv
  set app_name to item 1 of argv
  set min_idle to ((item 2 of argv) as number)
  -- Idle time in seconds
  -- http://macscripter.net/viewtopic.php?pid=144392
  set idle_time to ((do shell script "/usr/sbin/ioreg -c IOHIDSystem | /usr/bin/awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'") as number)

  if idle_time >= min_idle then
    -- quit Papers if running
    -- http://macscripter.net/viewtopic.php?id=4396

    tell application "System Events" to set processExists to exists process app_name

    if processExists then
      tell application app_name
        quit
      end tell
    end if
  end if
end run

Then set up a cronjob to run this every 5 minutes checking for 30 minutes (1800 seconds) of idle time before closing Papers.

*/5 * * * * osascript /usr/local/bin/quit_app_on_idle.scpt Papers2 1800

Preview crashes when reopening PDFs created with LaTeX

Sunday, March 17th, 2013

To typeset documents I use pdflatex. I edit my tex files using vim and build the pdfs using a makefile. At the end of my make sequence I like to have:


open my.pdf

Which on my mac causes preview to open my pdf document.

When I recompile and this command runs, sometimes preview just focuses the already open document, but other times it opens a new window. I haven’t backwards engineered how it decides which to do, but it might be correlated with the amount of change in between. In any case, Preview recently has been crashing when it tries to open the same document in a new window. For small, short-term articles this is not so annoying. But now, writing my t****s, I’m really getting frustrated.

I wrote an applescript to replace the open command above. First you’ll need to enable applescript for Preview.app. Then you can save the following in preview.scpt.


on run argv
	set file_name to item 1 of argv
	try
		tell application "Preview"
			activate
			set open_already to false
			repeat with this_doc in every document
				set open_already to open_already or (name of this_doc as string is equal to file_name)
				if open_already then
					return "open already"
				end if
			end repeat
			if not open_already then
				open (do shell script "pwd") & "/" & file_name
				return ""
			end if
		end tell
	on error errMsg
		return errMsg
	end try
end run

You can run with:


osascript preview.scpt my.pdf

The rerun to see that no action is taken.

Scroll a bit in safari window, take screenshot repeat

Friday, February 22nd, 2013

Here’s an applescript I used to make a series of screen captures of scrolling through a web page in safari:


tell application "Safari"
	activate
	set sc to 0
	repeat
		set thescript to "if((window.pageYOffset + window.innerHeight)<document.body.clientHeight)
		{
    	window.scrollBy(0,10); // horizontal and vertical scroll increments
		}"
		do JavaScript thescript in current tab of first window
		set imagePath to (path to desktop as text) & "screenCapture_" & my zero_pad(sc, 6) & ".png"
		delay 1.5
		do shell script "screencapture -o -mx -T0 " & quoted form of POSIX path of imagePath
		delay 0.5
		set sc to sc + 1
	end repeat
	
end tell

on zero_pad(value, string_length)
	set string_zeroes to ""
	set digits_to_pad to string_length - (length of (value as string))
	if digits_to_pad > 0 then
		repeat digits_to_pad times
			set string_zeroes to string_zeroes & "0" as string
		end repeat
	end if
	set padded_value to string_zeroes & value as string
	return padded_value
end zero_pad

Source

Screen capture a remote desktop into the remote clipboard

Friday, January 6th, 2012

I’m working a bit with Apple Remote Desktop now and I’m having trouble taking screen captures. It seems easy to take a screen capture that ends up as a file on or in the clipboard of the client side. But I’d rather be completely immersed in the remote computer, so ideally when I hit CMD+SHIFT+3 I’d get a screen shot the size and resolution of my remote desktop saved to the remote’s clipboard.

Here’s what I’m doing for now. I prepare my app that I want to screen capture then I switch to terminal and issue


echo "tell application \"skinning\" to activate" | osascript - && screencapture -c

This switches to my app and takes a screen capture into the clipboard.

Share internet (via wifi Airport) applescript

Sunday, July 17th, 2011

Here’s an applescript we’ve been using at home to share the ethernet internet connection between our two laptops. The computer with the ethernet cord plugged in runs this script, then the other computer can connect to the wireless network of that computer’s name and share its internet connection.


tell application "System Preferences"
	activate
end tell

tell application "System Events"
	tell process "System Preferences"
		click menu item "Sharing" of menu "View" of menu bar 1
		delay 2
		tell window "Sharing"
			if value of checkbox 1 of row 11 of table 1 of scroll area 1 of group 1 is 1 then
				click checkbox 1 of row 11 of table 1 of scroll area 1 of group 1
				click checkbox 1 of row 11 of table 1 of scroll area 1 of group 1
			end if
			
			
			click checkbox 1 of row 11 of table 1 of scroll area 1 of group 1
			delay 1
			if (exists sheet 1) then
				if (exists button "Turn AirPort On" of sheet 1) then
					click button "Turn AirPort On" of sheet 1
					delay 1
				end if
				click button "Start" of sheet 1
			end if
		end tell
	end tell
	tell application "System Preferences" to quit
end tell

Downloads

ShareInternet.app (zip) Here’s a version wrapped into an app with a nice little icon so you can put it on your dock.

Ignore nytimes paywall with simple client-side javascript, or applescript

Thursday, April 21st, 2011

Today was my first experience with the New York Times paywall. It manifested as an html overlay on top of the article I wanted to read. The article seemed to have fully loaded which made me think that if I could just get rid of the overlay I’d be able to read it.

This turned out to be the exactly case. I just zapped the div containing the overly (properly labeled id='overlay' and restored the overflow of the main page (to get scrolling back).

ignore nytimes paywall

This is easily accomplished with three lines of client side javascript:


document.getElementById('overlay').parentNode.innerHTML = '';
document.body.style['overflow-x'] = 'auto';
document.body.style['overflow-y'] = 'auto';

There are many ways of issuing your own javascript on pages opened in your browser, whatever that might be.

For me on a mac with safari, wrapping the above into a little applescript is easiest. I save this in a file called Ignore-nytimes-paywall.scpt:


tell application "Safari"
	try
		set doc to front document
		do JavaScript "document.getElementById('overlay').parentNode.innerHTML = '';" in doc
		do JavaScript "document.body.style['overflow-x'] = 'auto';" in doc
		do JavaScript "document.body.style['overflow-y'] = 'auto';" in doc
	on error errText number errNum
	end try
end tell

It seems that coming up with your own hack for knocking down the nytimes paywall is the trend these days. We’re all blowing our technological Joshua trumpets ;-).

Update: I’m now more convinced that nytimes is just using this paywall as an experiment. Ignoring the paywall is even easier than I thought:

Readers need only remove “?gwh=numbers” from the URL. They can also clear their browser caches, or switch browsers as soon as they see the subscription prompt. All three of these simple fixes will let them continue reading.

Source

Update:
Seems the paywall organization has changed a little bit and now the client side javascript should be:


document.getElementById('regiwallBackground').style.display = 'none';
document.getElementById('regiwallOverlay').style.display = 'none';
document.body.parentElement.style.overflow = 'scroll';