フリーでScriptableなmacOS用PDFビューワー「Skim」上でオープン中のPDFで、選択中のテキストの内容を取得するAppleScriptです。
フリーかつオープンソースで提供されているアプリケーションのうち、奇跡的に豊富なAppleScript対応機能を備えるPDFビューワー、それがSkimです。Skimに比べればPreview.appなど取るに足らない存在。「PDFビューワー四天王」のうち、その最上位に君臨するアプリケーションこそがSkimです(四天王とかいいつつ、Skim、Preview、Acrobatの3人しかいないのはお約束)。
▲SkimでPDFをオープンし、「AppleScriptってなんだろう?」の文字列を選択
ただ、そんなグレートな存在のSkimでも、「選択中のテキストを取得する」という処理を書いたことはありませんでした。
Skimの「selection」によって取得されるのがテキストではなくRTFなので、AppleScriptの基本的な機能ではこのRTFはひどく扱いが難しいデータ「でした」。
しかし、Cocoaの機能を利用することで、テキストへの変換は可能です。
それでも、Cocoaが期待するRTFのデータとAppleScriptの世界のRTFのデータ同士の変換が難儀でした。食後の腹ごなしに行うには手に余るといったレベル。
そこで、お気軽データ変換の最後の砦であるクリップボードを経由してRTFをAppleScriptの世界からCocoaの世界に受け渡してみたところ、大成功。あとは、PDFから取得したテキストデータによくあることですが、日本語のテキストだとUnicodeのNormalize方法の問題によりひらがな/カタカナと濁点や半濁点が分離した状態で返ってきました。
これについても、Cocoaの機能を利用してNormalizeを行い、常識的なテキストに変換できました。
AppleScript名:Skimでオープン中のPDFの選択中のテキストを返す |
— – Created by: Takaaki Naganoya – Created on: 2019/09/16 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Skim" tell front document set aSel to selection repeat with i in aSel set aCon to contents of i set rList to RTF of aCon set sCon to "" repeat with ii in rList set the clipboard to ii set aText to getClipboardAsText() of me set aCon to aCon & aText end repeat set aStr to textfy(aCon) of me return aStr end repeat end tell end tell –Normalize Unicode Text in NFKC on textfy(aText as string) set aStr to current application’s NSString’s stringWithString:aText set aNFKC to aStr’s precomposedStringWithCompatibilityMapping() return aNFKC as string end textfy –Clipboard内の情報をテキストとして取得する on getClipboardAsText() — get the pasteboard items set theClip to current application’s NSPasteboard’s generalPasteboard() set pbItems to theClip’s pasteboardItems() set theStrings to {} repeat with anItem in pbItems if (anItem’s types()’s containsObject:(current application’s NSPasteboardTypeString)) then set end of theStrings to (anItem’s stringForType:(current application’s NSPasteboardTypeString)) as text end if end repeat return theStrings as text end getClipboardAsText |
とか言ってたら、夕飯の買い物に出かけようとした頃にShane Stanleyから「もっとシンプルに書けるよー」というサンプルが届いて脱力しました。もっと簡潔に書けたようです(同一サンプルで日本語データに対してチェックずみ)。
ただ、PDFから文字取り出ししたあとは、Unicodeの再Normalizeは割とやらないといけないケースが多いので、選択部分(selection)からRTFじゃなくてcharacterでデータを取り出せばよかったというあたりが反省点でしょうか。
set theText to ""
tell application "Skim"
tell front document
set aSel to selection
repeat with anItem in aSel
set theText to theText & (characters of anItem) as text
end repeat
end tell
end tell
return theText