Archive for the 'Preview.app' Category

2013/12/01 プレビュー.appをAppleScriptから操作

10.9から正式にAppleScript対応になったOS X標準搭載のPDFブラウズアプリケーション「プレビュー.app」(Preview.app)をAppleScriptからコントロールするサンプルです。

preview_dic.png

たしか、プレビュー.appは(Mac OS Xの前身である)NeXTstepの頃から存在していたように思うのですが……それが2013年になってAppleScriptに対応したというのは感慨深いです。以前、AppleScript非対応の時代のプレビュー.appを強引にAppleScript対応にするという試みは行ったことがありますが、そこまで強引なことをしなくてすむのは、いいと思います。

……で、プレビュー.appをAppleScriptからコントロールできるとどういう用途に使えるのか? という話になります。目下、AppleScriptへの対応度の高いPDFビューワーといえばフリーソフトウェアの「Skim」が著名であり、フリーでなくとも「PDFpen」などもあるため、何をいまさら……という感はあります。

さらに、「AppleScriptに対応した」とはいうものの、AppleScript用語辞書を見ると、本当に「最低限」の制御ができるだけの内容です。

アプリ起動、終了、ファイルオープン、ファイル保存、ドキュメントの状態取得、アプリケーションの状態取得、ウィンドウの状態取得、印刷……と、これだけです。

プレビュー.appが持っている「プレビュー.appらしい機能」(インスペクタで表示される内容が取得できるとか、ソフトプルーフができるとか、注釈にアクセスできるとか、PDF保存時にQuartzフィルタをかけるとか)は何も呼び出せません。メニューやボタンをGUI Scripting経由で操作して無理矢理コントロールするほかありません。Apple純正アプリのAppleScript対応度としては「仕事をしているフリ」のレベルを出ない内容です。

ところが、プレビュー.appでPDFをオープン+保存できることには、それだけでもかなり意義があります。

さまざまなアプリケーションでPDFを加工して保存した場合に、PDFのファイルサイズが大きなままである場合があります。実際にSkimでPDFを加工処理したときに、このような症状に遭遇しました。自分で使う分にはあまりこだわりませんが、これをお客に納品する必要があるとか、納品する書類の素材として使うような場合には気になります。

切り抜きなどして元よりもファイルサイズが小さくなる「はず」だけれども加工前とファイルサイズが変わらない状態の(ちょっと状態に疑問が付く)PDFを、「プレビュー.app」でオープンして保存すると、この状態が是正されました。

今後、プレビュー.appが持つ豊富な機能がAppleScript側に順次解放されるかどうか、次期OSアップデート時の行方が気になります。待ちきれなければ、Skimを併用すれば詳細なPDFの情報取得などは問題なく行えますので、ぜひSkimを使ってください。

スクリプト名:プレビュー.appのプロパティを取得する
tell application “Preview”
  properties
  
–> {frontmost:false, class:application, name:”Preview”, version:”7.0″}
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:プレビュー.appにbundle IDでtellする
tell application id “com.apple.preview”
  properties
  
–> {frontmost:false, class:application, name:”Preview”, version:”7.0″}
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:プレビュー.appで指定PDFをオープン
set aFIle to choose file of type {“com.adobe.pdf”}

tell application “Preview”
  open aFIle
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:プレビュー.appでオープンした書類のプロパティを取得する
set aFIle to choose file of type {“com.adobe.pdf”}

tell application “Preview”
  open aFIle
  
  
tell document 1
    properties
    
–> {modified:false, path:”/Users/maro/Desktop/blazingshadow1_trial.pdf”, class:document, name:”blazingshadow1_trial.pdf”}
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:プレビュー.appでファイルをオープンして保存してクローズ
set aFIle to choose file of type {“com.adobe.pdf”}

set aDocDir to path to desktop folder

tell application “Preview”
  open aFIle
  
  
tell document 1
    set aName to name
  end tell
  
  
set newPath to (aDocDir as string) & aName
  
  
save document 1 in file newPath
  
  
close document 1
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/05/24 Finder上で選択中のファイルをPreviewでオープンして保存してクローズ

Finder上で選択中のファイル(たぶんPDF)をPreview.appでオープンして、保存してクローズ……を繰り返すAppleScriptです。

PhotoshopでPDFを加工したところ、そのままではファイルサイズが大きく、古いOS(Mac OS X 10.4.11とか)では内容を確認できない状態でした。

……ちょっと困りました。そこで、OS X 10.8上のPreview.appでファイルを保存し直したところ、ファイルサイズも小さくなり、古いOSでもオープンできるようになりました。

何か、ほかにも回避方法はありそうですが……とりあえず、本AppleScriptによって、Finder上でPhotoshopによる加工を行ったPDFを選択しておき、Scriptを実行することですべて保存し直します。

なお、本AppleScriptはGUI Scriptingを利用しているため、あらかじめシステム環境設定の「アクセシビリティ」で「補助装置にアクセスできるようにする」にチェックを入れておく必要があります。また、将来のOSバージョンアップによってPreview.appのメニュー内容が変更になった場合には、そのままでは動かず修正(メニューアイテム番号部分のみ)が必要になる可能性が高いです。

スクリプト名:Finder上で選択中のファイルをPreviewでオープンして保存してクローズ
tell application “Finder”
  set aList to selection as alias list
end tell

repeat with i in aList
  
  
set j to contents of i
  
set jj to j as string
  
  
–Preview.appで選択されたファイルをオープンする
  
set appBundleID to “com.apple.Preview”
  
tell application “Finder”
    open file jj using application file id appBundleID
  end tell
  
  
delay 0.1
  
  
–Preview.appでファイル保存→クローズを行う
  
activate application “Preview”
  
tell application “System Events”
    tell process “プレビュー”
      click menu item 8 of menu 1 of menu bar item 3 of menu bar 1 –保存
    end tell
  end tell
  
  
delay 0.1
  
  
tell application “System Events”
    tell process “プレビュー”
      click menu item 5 of menu 1 of menu bar item 3 of menu bar 1 –閉じる
    end tell
  end tell
  
end repeat

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/02/08 Preview.appで最低限のScript命令実行機能をイネーブルに

たまたま、Mac OS X Hintsに掲載されているのを見つけ、半信半疑で実行してみたら……open、print、quit、closeなどの基礎的な命令をPreview.appが受け付けるようになりました。

なんでも、AppleのAppleScript製品担当のSal Soghoianがコメント欄にそのような投稿をしたのだとか(汗) そもそも、なぜそのようなゲリラ的なことをやるのか? Mac OS Xの製品版のPreview.appにちゃんとしたScript対応機能を持たせればそれでよいのではないか?

疑問は尽きないのですが、とりあえずSal Soghoianが書いた内容であれば、とくに転載しても問題はないでしょう。

# 注意:本Scriptを実行する前にPreview.appのファイルを必ずバックアップしておいてください

処理内容自体は、Info.plistにエントリを追加しているだけなので、Xcode Toolsに入っている「Property List Editor」を使ったほうが安全と思われます。

スクリプト名:Preview.appに最低限のScript命令実行機能をイネーブルに
try
  tell application Finder
    set the Preview_app to (application file id com.apple.Preview“) as alias
  end tell
  
set the plist_filepath to the quoted form of ((POSIX path of the Preview_app) & Contents/Info“)
  
do shell script defaults write & the plist_filepath & space & NSAppleScriptEnabled -bool YES
end try

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/10/21 PDFのページ数を数えるv3

PDFのページ数を数えるScriptを久しぶりに動かしてみたら、Mac OS X 10.5.5上で期待どおりの動作を行わなかったので、修正を行ってみました。

画面上のウィンドウの文字やメニューの状態を検出して処理を行うUI Element Scripting(GUI Scripting)を用いた場合に、アプリケーションの画面構成が変更になると当初の想定どおりの動作が期待できなくなってしまう、その実例といえるでしょうか。

preview_app.jpg

Mac OS X 10.4と10.5のPreview.appでは、PDFのページ数表示が異なります。Mac OS X 10.5では当初は異なる表示を行っていたのですが、途中で変更になったようです。

とりあえず、極力バージョンに依存しないよう配慮して修正してみました。

→ こちらの方がおすすめです

スクリプト名:PDFのページ数を数えるv3
set a to choose file
set pNumStr to getPDFPages(a) of me
set pNum to pNumStr as number

指定PDFのページ数をPreview.appを使って数える。要・GUI Scriptingオン
Mac OS X 10.4および10.5対応
ただし、日本語環境であることが動作の前提条件
on getPDFPages(aFile)
  tell application Preview to open aFile
  
activate application Preview
  
tell application System Events
    tell process プレビュー
      tell window 1
        set aTitle to title
      end tell
      
keystroke w using command down
    end tell
  end tell
  
  
このあたりを変更した(v3) 10.4 & 10.5で共通ルール
  
set pRes to trimStrings(aTitle, “, “) of me
  
set pRes to repChar(pRes, ページ“, “”) of me
  
if pRes contains / then
    set aPos to offset of / in pRes
    
set pRes to text (aPos + 1) thru -1 of pRes
  end if
  
  
return pRes
end getPDFPages

任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
あんまり出来がよくないのでちょっと直した
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

文字置換
on repChar(origText, targChar, repChar)
  set origText to origText as string
  
set targChar to targChar as string
  
set repChar to repChar as string
  
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/07/15 PDFのページ数を数える

指定のPDFのページ数を数えます。この手の処理を行うには、GhostScriptやらpdftkをインストールして、というのがお約束のやり方です。また、Acrobat Professionalを使ってページ数を数える、というのも一般的な方法でしょう(ふつうのAcrobat Readerは、AppleScript用語辞書が見えるのにAppleScriptからのコントロールを拒絶します)。

Acrobat Professionalは高いし、GhostScriptやらpdftkがあまねくすべてのマシンにインストールされているわけではないため、もうちょっと違うアプローチを試してみたのが本Scriptです。

なんと、Preview.appでオープンしてタイトルバーの文字列を取得して、文字を切り抜きしてページ数を取得するとかいう、えらく強引な方法でやってみました。10.4.11と10.5.4で動作確認してあります。こんな方法がいいとは思わないのですが、AppleScriptからPDFのページ数を調査する手段が限られているため、「ないよりはマシ」といったレベルのScriptです。

ただし、GUI Scriptingがオンになっていないと動作しませんし、日本語環境以外では動きません。

→ こちらのほうがおすすめです(10.5以降)

スクリプト名:PDFのページ数を数える v2
set a to choose file
set pNumStr to getPDFPages(a) of me
set pNum to pNumStr as number

指定PDFのページ数をPreview.appを使って数える。要・GUI Scriptingオン
Mac OS X 10.4および10.5対応
ただし、日本語環境であることが動作の前提条件
on getPDFPages(aFile)
  tell application Preview to open aFile
  
activate application Preview
  
tell application System Events
    tell process プレビュー
      tell window 1
        set aTitle to title
      end tell
      
keystroke w using command down
    end tell
  end tell
  
  
set v2 to system attribute sys2
  
if v2 = 4 then
    Mac OS X 10.4.xの場合
    
set pRes to trimStrings(aTitle, “, ページ)“) of me
  else if v2 = 5 then
    Mac OS X 10.5.xの場合
    
set pRes to trimStrings(aTitle, /“, “) of me
  end if
  
return pRes
end getPDFPages

任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
あんまり出来がよくないのでちょっと直した
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に