Scriptingを用いてスクリプトエディタ上でコンテクストメニューを表示させて、コンテクストメニューのキャプチャを行うAppleScriptです。10.14.6上で試しただけなので、10.15上では試していません(たぶん動くと思うのですが)。Debugger)から呼び出しています。Scripting」。ある顧客が「キーボードショートカットとキーボード操作をそのままScript化することでこれを作れ」という仕様を出してきて、とても実現できない内容がまだらに含まれていたので「ナイスジョーク!」と却下した記憶があります。「できること」(キーボードショートカット操作)に「できないこと」(目視で当該データの位置確認)を混ぜて仕様を出されると悪夢でしかありません。Scriptingで操作を行うと信頼性がないうえに、信頼性を確保するためには「待つ」という処理が必要だったり、本来のAppleScriptの処理速度よりも100倍以上遅くなるので、本当に必要な箇所にだけ使う&可能なかぎり使用しないというのが自分の基本的なスタンスです。10.13は無視)の資料を作るために、コンテクストメニューの内容を画面キャプチャする必要に迫られました。AppleScriptが500個ぐらい、階層化されたメニューに入っているので、これの画面キャプチャを撮るだけで一仕事です。テストで1階層分の資料を作ってみたのですが、けっこうかかります。そこで、スクリプトエディタ上で表示させたコンテクストメニューをプログラムで撮れないかを検討することになります。真っ先に調べたのはCocoaにそういう機能がないかどうか。自前のプログラムのビューの内容をキャプチャすることはできますが、他のアプリケーションのビューをキャプチャする機能は見つかりませんでした。仕方がないので、画面のキャプチャをまるごと取得して、撮影対象のビューの座標から画像の切り抜きを行うようにしてみました。Scriptingでコンテクストメニューを表示させるのは無理かと思っていたのですが、できるんですね。--コンテクストメニューの表示これで実際にコンテクストメニューの表示を行えました。Debuggerで実行。問題になったのは2点。1つは、画面キャプチャの撮影を行うフレームワークでメインディスプレイから画面イメージをNSImageで取得し、その結果をメイン側(暗黙のrunハンドラといったほうがいいのか)のプロパティに返しているのですが、すぐに反映されないらしくて、クラッシュを頻発。結局、プロパティに内容が反映されたことをループで時間待ちして受信。1つ困った点は、コンテクストメニューの表示解除(キャンセル)。1つのコンテクストメニュー表示&キャプチャ撮影だけでは意味がありません。選択メニュー項目を変更して、複数のコンテクストメニューのキャプチャを順次行えなくてはなりません。いろいろな方法を試してみたものの、最前面のアプリケーションを「スクリプトエディタ」でない状態を作ればコンテクストメニュー表示状態は解除されます(このあたり、AppleScriptが純粋なプログラマーに苦手とされる理由。実際に使っているユーザーでないとこういう発想自体が出てこない)。Debuggerをactivateすることでその状態(コンテクストメニュー表示解除)を作ってみました。そんなわけでコンテクストメニューの(選択項目を変更して全項目を選択状態にした)画面キャプチャができました。現在は1階層分のコンテクストメニューの撮影を行なっていますが、メニュー階層をすべてAppleScript側からスキャンして、それぞれのメニューに対して、各メニュー項目を表示した状態で巡回キャプチャできるとよさそうです。ハンドラは、Y座標の変換をこの用途(全画面キャプチャしたNSImageの切り抜き)の帳尻合わせのために書き換えています。この用途以外では使えないはずです。NaganoyaEdama2さんからの投稿Scriptです。アラートダイアログ中に各種GUI部品を詰め込む「箱庭インタフェース」シリーズ。テーブルビューを表示して、Finderからのアプリケーションのドラッグ&ドロップを受け付けるAppleScriptです。Stanley!アプリケーションフォルダ直下のアプリを、NSValueTransformerを使ってコラムにローカライズ名とアイコンを表示するのと、finderからのドラッグ&ドロップでアイテムの追加です。追加時に重複チェックをしているので試す時はユーティリティフォルダか別の場所にあるアプリで試してください。本Scriptは自分も作りたいと思いつつも調査が進んでいなかったものですが、TableViewでFinderからのドラッグ&ドロップを受け付けます。これを鍛えて再利用しやすい部品に育てることで、ドロップレットの代替品にできると思っています。10.12以降、Finder上のファイルをAppleScriptドロップレットにドラッグ&ドロップで処理させても、OS側がダウンロードファイルにつけた拡張属性(Xattr)「com.apple.quarantine」がついているとドロップレット側で処理できなかったりします(回避方法はありますけれども)。このドロップレットという仕組みを使わずに、同様にドラッグ&ドロップによる処理を手軽にできる代替インタフェースとしてこのようなものを考えていた次第です。Naganoya画像のすべてのピクセルが白であることをチェックするAppleScriptです。10.12上で作成した「空白画像検出v3」は一般的に処理時間のかかる空白画像の検出(ヒストグラム計算してチェックする?)が高速に処理できます(GPUImageでヒストグラム計算を行うより2倍ぐらい高速)。Photoshopが必要になるといった事態は避けられます。10.14.6上でこのルーチンを再度試してみたところ、思ったとおりに空白検出(数百万ピクセルの画像でも1つだけ黒であればfalseを返す)してくれません。書き方を変えていますが、単体で通常のAppleScript(Cocoa不使用)にコンテクストメニューから突っ込むモジュールとして運用するためです。copyしてくれない?参照ではなくすべてのデータをコピーするコマンドとして、copyコマンドはとても重宝しています。「パラメータの代入の方向が違う偏屈なコマンド」ではなく、明示的にデータ内容をコピーするためのコマンドと認識しています。10.14.6上で本ルーチンを試してみたところ、どうも参照をコピーしている気配がします。AppleScriptのオブジェクト(配列とか)をcopyコマンドでコピーすると、参照ではなくデータが複製されていることを確認しました。Cocoaオブジェクトのcopyも同様かどうかは、ちょっとそうじゃないんじゃないかというところです。|copy|()Cocoaの世界のオブジェクトのコピーはこんな感じ(↑)でできたので、今後はこちらを採用することにします。1×1のNSImageに色を塗るとデータサイズが増えるビットマップ画像の状態であるNSBitmapImageRepになっていれば、1×1画像のサイズは同じことが期待されます。10.12上ではそのように扱えていました。10.14上で1×1ドットのNSImageに対して色を塗って、NSBitmapImageRepを取得すると、塗らない状態のNSImageよりもデータ(NSData)サイズが大きくなることがわかりました。▲1×1のPNG画像をビットマップ化したデータ。10.15では大幅にデータ量が減る)。10.15.2)さすがに匙を投げかけましたが、比較元のデータに透明の色(clearColor())を塗る=画像的に意味はないが、同じ処理を通すことでデータサイズを同程度にするという処理を行うことで、いい感じに空白検出できるようになりました。Naganoya入力フォームつきのPDFにデータ入力して別名保存するAppleScriptです。他のGUIアプリを操作してフォーム入力するのではなく、直接PDFKitの機能を利用してフォームPDFへの記入を行なっています。テキスト入力フォーム、チェックボックス、コンボボックスへの入力に対処してみましたが、リストボックスの項目選択はまだ行えていません。Debugger上で表示したPDFフォーム上の各種プロパティ。Naganoya入力フォームつきのPDFにデータ入力して別名保存するAppleScriptです。PDFフォームといっても、別に入力したその場でどこかのサーバーにデータが送信されるわけでもなく、ただ紙に筆記用具で名前を書き込むがごとく、記入欄にデータが入力されたPDFが出来上がるだけです。サンプルのフォーム入りPDFをみつくろって、チェックボックス項目だけ値を変更して、別名保存してみました。本AppleScriptではフォームのうちチェックボックスのものの値だけ書き換えてみましたが、テキスト入力型の記入欄に文字データを突っ込むのも難しくはありません(多値ポップアップメニューからの選択がめんどくさい)。Naganoya与えられた文字列がURLエンコードずみ文字列かどうかをチェックするAppleScriptです。EventがデコードされずにOSデフォルト指定のスクリプトエディタに転送される、URLデコード不良バグが発生。Beta3でこのバグが修正されているように見えます。Editorに転送している処理が「余計」になってしまいます。再デコードした文字列は途中で途切れてしまうので、処理対象の文字列がURLエンコードされたものかどうかをチェックする必要が出てきました。このままOSにURLデコード不良バグが残存するよりは、こうしたプログラムでチェックしてから処理するほうがよいでしょう。NaganoyaオープンソースのGPUImage.frameworkはAppleScriptから呼び出すのも簡単ですし、機能セットも充実しており、非常に重宝して使っています。GPUImage自体はSwiftで書き直されたGPUImage2、OSの変更を受けてOpenGLではなくMetalを用いるように書き直され、いまだ発展途上のGPUImage3と変化してきました。45GPUImage2/3とバージョンが進むにつれて搭載フィルタ数が減っており、かつAppleScriptから呼べないため、GPUImage3は(自分の)移行先になりません。Objective-CベースのGPUImage1系のプログラムを使い続けるという判断をしている開発者は多いようで、Github上で派生プログラムが大量にみつかります。GPUImage1系はmacOSがOpenGLを完全廃止にしたとたんに動かなくなるはずです。このため、GPUImage1系に依存しているプログラムは別の部品を呼び出して処理する必要が出てきます。有望なのは、macOS標準搭載のCIFilter。CIFilterについては、実際にプログラムを組んでみて「組みにくい」という印象を受けていました(機能はちゃんとしていそうなものの、機能数にドキュメントが見合っていません)。あと、AppleScriptからパラメータを指定しにくいという印象を受けていました。その後、各種フィルタを呼び出す汎用ルーチンを整備することで、利用難易度を下げる努力を自主的に行なっています。174そこで、実際に処理速度の面でどうなのか、CIFilterとGPUImageを比較するとどうなのか、調べてみました。ありもののルーチンを引っ張り出してきて実行。どちらも期待どおりの動作をしてくれます。周辺ルーチンの仕様が違っていたのでそこも合わせます。commandの「uuidgen」はお手軽な反面、呼び出すのに時間がかかるので(手元の時間で0.1秒程度強)、より高速なCocoaのUUIDStringを用いる部品に置き換えました。それぞれのフレームワークごとの挙動の違いもあります。経験上、GPUImage.frameworkは初回実行時だけは時間が長くかかる傾向があり(1秒以上かかる)、2回目以降はより短い時間で処理できるようになることを確認しています。CIFilterは初回およびそれ以降の呼び出しでもさほど処理時間が変わりません。これら2つを実際に同じデータで同一条件下で比較してみたところ、同一の処理(画像の差分計算)を行なったかぎりでは処理時間に差はほとんど有意な差はありませんでした。2)を0.1〜0.2秒程度で処理できています。Disk上に置いたり、並列処理するとよいのではないでしょうか(シングルスレッド処理が高速なマシンを用意するというのが一番効きそうではあります。5Kの上位モデルとか)。v3」を作成済みなので、GPUImageなしでもさほど困りません。v3」で各種サイズの画像の空白検出を実行(単位:秒)Objective-C/Swift系の開発者の方々に「GPUImageを経由してGPUのパワーを使って処理するよりも、AppleScript単体で空白の比較演算処理したほうが速かった」という事実をお話しすると、最初は「嘘つけ」というひきつった笑顔の反応なのですが、実際にコードを動かして動作原理を丁寧に説明すると分かっていただけるようです。Naganoya指定ファイルからのメタデータ情報の取得を行うAppleScriptです。commandの「mdls」で行えます。ループですぺての属性値を取得するか、属性ラベルを指定して個別に属性値を取り出すことになります。commandのほうが手っ取り早そうです。Naganoya世界地図のSVGをHTMLReader.frameworkでparseして、目的のノードに塗り色の指定を行い、WkWebView上で表示するAppleScriptです。applet)昨日のものがあくまでSVGのParseと表示が目的の試作品であったのに対し、本Scriptは連続してポップアップメニューから対象を選んで表示するというものです。Debuggerから「Application(Enhanced)」で書き出さないと呼び出せないようです(これはちょっとひどいかも、、、、)。世界地図はWikipediaから拾ってきたもので、ISO国コードではなく名称でIDが振ってあり、日本もJapanではなくHokkaido、Honshu、Shikoku、Kyushuuに分けて登録されています。Naganoyaアラートダイアログ上のWebViewにSVGで作った円グラフを表示するAppleScriptです。Objective-Cで作られたチャート表示フレームワークなどを呼び出して試していますが、スクリプトエディタ上で作成したAppleScriptから呼び出すと、アニメーションしなかったり表示が行えなかったりといろいろ環境にフィットしていません。AppleScriptアプリケーションを作成した場合には割とチャート表示部品をそのまま使えますそこで、単純なグラフ表示を行うようにレベルを下げ、SVGをWkWebView上に表示する形式にしてみました。本Scriptでは最低限のサンプルを表示させていますが、SVGの組み立てをもう少し強化してグラフの背景を透明にできればいい感じになるのではないでしょうか。▲世界地図あたりだといい感じに見えるかもしれません。当該の国だけ色を変えるような処理を仕込めば何かに使えそうです。IDで指定したアプリケーションのバンドル中(/Contents/Resources/)の現在のLocalizationに存在する指定のstringsファイル内で、指定キーの値を取得するAppleScriptです。アプリケーションバンドル内の各ローカライズフォルダの名称は一意に決定されているものでもなく、ある程度の「ゆらぎ」が生じています。/Contents/Resources/Japanese.lproj//Contents/Resources/ja.lproj/NSLocaleからcurrentLocale()を取得すると、「ja-JP」のような識別子が得られます。これと上記のパターンのフォルダとの付け合わせのためのメソッドがどこかに存在しているはずなのですが、現状では見つけられていません(ないと各アプリケーションが正しくメニュー表示できていないので)。いまひとつ、しっくりきていません。getLocalizationsFromBundleID–指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。IDで指定したアプリケーションからすべてのLocaleを取得し、ダイアログ選択したLocale内のすべてのstringsファイルを読み込んでNSDictionary化して指定のキーワードを含むものを抽出するAppleScriptです。stringsファイルのパスをリストで返します。調査のための下調べを行うものです。getLocalizationsFromBundleID–指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。IDで指定したアプリケーションのバンドル中(/Contents/Resources/)のすべてのLocalizationに存在する指定のstringsファイル内で、指定キーの値を取得するAppleScriptです。macOSの日本語環境では、Finder上でコピーしたファイルのファイル名の後方に「のコピー」といった文字列が追記されますが、他のLocaleでどのような文字列が使用されているか調査するために作成したものです。getLocalizationsFromBundleID–指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。Naganoya指定フォルダ以下のすべてのファイル名とフォルダ名から絵文字を除去するAppleScriptです。StanleyのremoveEmojiルーチンを使っています。10.14.1で絵文字が大幅に追加されたため、これらの絵文字をファイル名に用いていた場合には10.14.1以下のバージョンのOS環境にそのままファイルを持っていくことができません。コピーできない(エラー)という状態になります。絵文字自体に害はないのですが、規格がコロコロ変わる(追加される)ことで、ファイル名に用いるのには問題があるということでしょう。▲もともとのファイル名、フォルダ名。絵文字を大量に使用している(普段はファイル名に絵文字は使っていません)▲本Scriptで一括で処理したファイル名、フォルダ名。pathを用いて指定フォルダ以下すべてをリネームするようなScriptは組んでいなかったので、ちょっと考えさせられました。10.13.6の環境に持っていけました。絵文字がないと寂しい感じがします指定フォルダ以下のファイル/フォルダを一括取得するのに、今回はあえてSpotlightを使っていません。ファイルサーバー上のファイル/フォルダを処理する可能性がありそうなのと、外部ライブラリを使わないほうがよいと考え、このような構成になっています。Naganoya指定のAppleScript書類からソーステキストを取得して、書き換えたあとに別途ファイル保存するAppleScriptです。OSAKitの機能を利用しており、スクリプトエディタを使用しません。最小限の実装しかしていませんが、これ以上どこをどうするという箇所もないのでこんなもんなんでしょう。.scptファイルについてはこんな感じで処理できそうですが、.scptdファイルの書き換え処理についてはノーアイデアです。バンドル内の指定の.scptファイルを書き換えるといった、rtfとrtfdの関係のような感じになるのだろうかと思わないでもありませんが、いろいろ落とし穴がありそうで困ります。Appletに書き出すAppleScriptも作って試していますが、OS内の機能をそのまま使っているだけだと、バンドル形式のScriptのバンドル中に含まれている他のファイル(ライブラリとか、Frameworkとか、起動時に表示できるdescription.rtfdファイルとか)をもともとのScriptからコピーしてくれないので、そのあたりいちいち自分で書かないといけないのでしょうか。スクリプトエディタをAppleScriptからコントロールしてAppleScript書類をAppletに書き出すような処理はよくやっていますが、OSAKitの機能を用いて同様のことは行えます。フラットなScript書類(バンドルではない)をアプレットに書き出す程度の処理が(現状では)到達点のようです。大量のAppleScript書類を高速にアプレット書き出しする必要があれば、それなりに時間をかけて処理を記述するかもしれませんが、そういう用途がなければスクリプトエディタをコントロールしたほうがよさそうです。Naganoya指定PDFのサイズ(幅、高さ)をPointで取得するAppleScriptです。10.13以降でboundsの値の返り方が変わったことに対応できていないので(それ以前に作ったので無理もないというか、勝手にAppleが仕様を変えたのが悪い)、対処してみました。NaganoyaバンドルIDで指定したアプリケーションのResourcesフォルダ中の、指定ロケールのstringsファイルをすべて読み込んでkeyを取り出すAppleScriptです。アプリケーション内の指定のローカライズしたメッセージ(テキスト)の内容を取り出すことはできますが、そのためにはキーを知っておく必要があります。そのキーを取り出してローカライズされた文字列を取り出すため、キーを調査してみました。これをそのまま何かのツールなりScriptに使うというものではなく、いわゆる「下調べ」のためのScriptの部品です。ありもののルーチンを再利用しただけのプログラムでできていますが、ありものはありもので、数千本のAppleScriptのストックからそれを探し出してくるのも一苦労です。アプリケーションバンドル内のResourcesフォルダ以下の(各lprojフォルダ以下の)stringsファイルの中身はまんま(シリアライズした)NSDictionaryなので、そのままDictionaryに読み込んでallkey()などのメソッドを実行できます。昔のstringsファイルはテキストファイルだったような気がしますが、テキストファイルだとparseしないといけないんで、ビルド時にparseしておいてDictionaryの状態でファイルに書いておくのは正しいと思います。8あたりから、アプリケーションのローカライズのルールが変更になったようで、基本となる言語環境がBase.lprojになり、英語はen.lprojといった1ローカライズ言語という位置付けに変更になりました。NSLocalizedStringFromTableInBundleを使ってアクセスしようかとも思ったのですが、こちらはまだ目的を達成できていません。11上で実験的に作成したAppleScriptアプリケーションのバンドル構造(左)。ローカライズしていない状態だとEnglishではなくBase.lprojが作成される。右はKeynote.app/Contents/Resources/ja.lprojフォルダの内容。getLocalizationsFromBundleID–指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。NaganoyaWebコンテンツ(HTML)の並列ダウンロードを行うAppleScriptです。Webコンテンツからデータを抽出する際に、あらかじめ一括でHTMLを並列ダウンロードしておいて、ダウンロードずみのデータを一括処理すると処理時間を大幅に短縮できます。「戦場の絆」Wikiから機体データの表をすべて取得するのに、順次HTMLを取得して抽出していた場合には3〜4分程度かかっていたものを、並列ダウンロードしたのちにデータ処理するように変更すれば、これが十数秒程度にまで高速化できます。既存のプログラムを修正してHTMLのダウンロード用に仕立ててみました。並列キュー(未処理タスク数)へのアクセスはAppleScriptからはできなかった(実行すると結果が返ってこなかった)のですが、そこに手をつけずに並列処理の完了状態を検出しています。ダウンロードが完了したデータはlist(配列)に入るので、リクエスト数と完了リクエスト数をループ内でチェックし、完了アイテム数がリクエスト数と同じになれば終了、条件を満たさない場合でも指定のタイムアウト時間を超えたらエラー終了という処理を行なっています。Debugger上では実行できないことです(結果が返ってきません)。AppleScriptアプレットに書き出して実行してみたところ、結果が返ってきません。10.12.6、10.13.6、10.14.6で同様)。Appのプロジェクト内で実行することはできました。このように、ランタイム環境に実行状況が左右される点にご注意ください。したマイナス面を補ってあまりあるほどダウンロードは高速です。90ファイル強のダウンロードを数秒で完了(マシン、ネットワーク速度、ダウンロード先サーバーの負荷状況、キャッシュ状態などに左右される、参考値です)するため、ダウンロード後に各HTMLからのデータ抽出も高速に行えます。Naganoyaedama2さんから投稿していただいた、指定URLの初出の指定タグ要素を抽出するAppleScriptです。戦場の絆Wiki上の指定ページ上の指定タグでマークされたテキストを取得します。ブログを見ていて思いつき、前に作りかけていたのを清書して送ります。名前は「指定URLのMS名を取得するv2b」です。内容はWKWebviewでページを読み込んで、javascriptで要素を取得しています。前の二つよりスマートではありませんが、こんなやり方もあるってことで...色々書き換えているうちに元がないですが、元ネタはapplescriptの穴からです。プログラムも短いわけではなく、処理速度も速いわけでもなく(自分の環境で9秒ぐらい)、ただ見ただけだと「????」という内容ですが、本プログラムの価値は処理対象ではなく、AppleScriptからWkWebViewに対して任意のJavaScriptを実行して処理しているサンプルであるという1点に尽きます。これはー、セキュリティ上のしばりがきつくて、けっこう大変なんですよ(遠い目)。以前、WKWebView上にYouTubeの指定URLのムービーを表示するというScriptを掲載したことがありますが、本当はこの上でJavaScriptを実行して指定の再生ポジションに再生位置をジャンプさせるといった処理を行いたかったのですが、WKWebView相手に(任意の)JavaScriptを実行させられず、時間切れで諦めたことがありました(そして絶賛放置中)。見かける記述のオンパレードがけっこうショッキングです。自分は「癖のないプログラムを読みやすく書く派」を自称していますが、日本国内にも割と海外のScripterに紹介したい(変わった)人たちがいて、edama2さんとMacLab.さんはその中に必ず入ってくる人たちでしょう。Stanleyが「HTMLをXMLと見立ててアクセスすれば外部フレームワークなしに処理できて簡単だよ」と、送ってくれたサンプルScriptです。2つの意味で焦りました。APIも呼べそうな雰囲気いろいろ考えさせられる内容でもあります。いう「それ自体で何か製品を構成できるほどのサイズの処理じゃないけど、何かに絶対に使ってますよね」的な処理をBlogで公開しておくことのメリットを感じつつ、XML処理とか正規表現の処理が個人的に不得意なので、とても参考になります。自分の用途が残念な(そんなに生産的でもなく趣味的な、という意味で)ものだったので、恐縮するばかりですー(オンラインゲームの機体のデータをWikiからまるごと引っこ抜くというものだったので)。