Numbersでオープン中の最前面の書類のすべてのシートの表1の行数の合計を計算するAppleScriptです。
Blogアーカイブ本作成のために書いたものです。
この記事数をカウントするために使いました。
AppleScript名:Numbersでオープン中の最前面の書類のすべてのシートの表1の行数合計を計算する |
set aCount to 0
tell application "Numbers" return aCount |
Numbersでオープン中の最前面の書類のすべてのシートの表1の行数の合計を計算するAppleScriptです。
Blogアーカイブ本作成のために書いたものです。
この記事数をカウントするために使いました。
AppleScript名:Numbersでオープン中の最前面の書類のすべてのシートの表1の行数合計を計算する |
set aCount to 0
tell application "Numbers" return aCount |
Edama2さんからの投稿Scriptです。アラートダイアログ中に各種GUI部品を詰め込む「箱庭インタフェース」シリーズ。テーブルビューを表示して、Finderからのアプリケーションのドラッグ&ドロップを受け付けるAppleScriptです。
–> Download Editable & Executable Script Bundle Document
カスタムクラスの作り方がわかったので、懲りずにTable Viewネタです。 Thanks Shane Stanley! アプリケーションフォルダ直下のアプリを、NSValueTransformerを使ってコラムにローカライズ名とアイコンを表示するのと、finderからのドラッグ&ドロップでアイテムの追加です。 追加時に重複チェックをしているので試す時はユーティリティフォルダか別の場所にあるアプリで試してください。
本Scriptは自分も作りたいと思いつつも調査が進んでいなかったものですが、TableViewでFinderからのドラッグ&ドロップを受け付けます。
これを鍛えて再利用しやすい部品に育てることで、ドロップレットの代替品にできると思っています。macOS 10.12以降、Finder上のファイルをAppleScriptドロップレットにドラッグ&ドロップで処理させても、OS側がダウンロードファイルにつけた拡張属性(Xattr)「com.apple.quarantine」がついているとドロップレット側で処理できなかったりします(回避方法はありますけれども)。
このドロップレットという仕組みを使わずに、同様にドラッグ&ドロップによる処理を手軽にできる代替インタフェースとしてこのようなものを考えていた次第です。自分で作らなくてもEdama2さんが作ってくださったので助かりました、、、、
AppleScript名:アラートダイアログ上にTable Viewを表示 v9_アイコンを表示、Finderからのドラッグ&ドロップ |
use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppleScriptObjC" use scripting additions on run # アラートダイアログでtableviewを表示 ## retrieve date ## ContentView を作成 |
AppleScript名:subClasses |
#MARK: – NSValueTransformer script YKZURLToIcon property parent : class "NSValueTransformer" property allowsReverseTransformation : false –>逆変換 property transformedValueClass : a reference to current application’s NSImage –>クラス #変換処理 on transformedValue:fileURL if fileURL is missing value then return set appPath to fileURL’s |path|() set iconImage to current application’s NSWorkspace’s sharedWorkspace’s iconForFile:appPath return iconImage end transformedValue: end script script YKZURLToDisplayedName #MARK: – Array Controller #MARK: – NSTableCellView |
Numbersでオープン中の最前面の書類中にあるすべてのシートの名前を置換するAppleScriptです。
内容は簡単ですが、Numbersにそうした機能が存在しないので、作っておくと便利です。アーカイブ本を作るのに、こうした(↓)資料を作る必要があるわけですが、そのためにこうしたこまごまとしたScriptをその場で作って作業の効率化を図っています。
▲上の画像あくまでは処理イメージなので、厳密に同一データの処理前・処理後の画面スナップショットではありません。各シートの名称の一部の文字列(YYYY部分)のみ置換されていることをご確認ください
AppleScript名:Numbersで各シート名称を置換 |
tell application "Numbers" tell front document set tList to every sheet repeat with i in tList tell i set aName to name set bName to replaceText(aName, "2011_", "2013_") of me set name to bName end tell end repeat end tell end tell –任意のデータから特定の文字列を置換 |
一部の本Blog愛読者の方々から「アーカイブ本まだ?」と言っていただいて気にはしておりました。ここに、Blogアーカイブ本のVol.5(2013〜2014年)の発売をお知らせいたします。
本Blog「AppleScriptの穴」は、開設10年目を迎える直前の2018年1月末に、格安ホスティングサービス「Xserver」との間の手違いでDBがシャットダウンされ、そのままの形で公開し続けることができなくなってしまいました。
そこで、AppleScriptのプログラムによるFinder上のAppleScriptの自動HTML化、AppleScriptによるXML-RPC経由でのWordPressへの自動記事投入といったさまざまなソリューションを投下して、現在の登録記事数に復旧。自動記事投入による復旧を行なったために、当時の作業環境でオープンできない(OSバージョン依存、アプリケーション依存)Scriptについては掲載を見送っています。
旧AppleScriptの穴:2008〜2018年 Mac OS X 10.4〜10.5の時代に開設
現AppleScriptの穴:2018年〜 Cocoa APIを呼びまくる現在のスタイルが定着
自動投入可能なコンテンツを優先して掲載したため、旧Blogと現Blogでは掲載内容が大幅に変わっています。別物といってよいでしょう。
そのため、Cocoa APIを使用しない「オールドスタイルのAppleScript」(とくに昔のバージョンのアプリケーション依存)については再掲載が難しく、このBlogアーカイブ本シリーズにしか情報をまとめていません。
旧Blogアーカイブ本シリーズも、1年ごとに区切って記事をPDF化して5冊目。この頃の記事投稿数が少なかったので、Vol.5は2013年1〜2014年12月の2年分の内容をまとめています。全429ページ、2,000円。
ファイル形式はPDFで、キーワードによる全文検索や印刷が行えます。本文からリンクしているXcodeプロジェクトのダウンロードリンクも新たに現行Blogにアップロードしたアーカイブにリンクし直しています。
もちろん、各プログラムリスト末尾にURLリンクをそなえ、ワンクリックでプログラム内容をスクリプトエディタに転送可能です。
ほとんどの掲載プログラムについてコメントを行い、現時点(2020年時点)で評価してどうか、ということを追記しています。
AppleScriptObjCでViewを印刷
AppleScriptObjCで透明ウィンドウを表示
Bundle IDで指定したアプリの非同期起動
指定プロセスの死活判定
最前面のアプリケーションをいったん終了させてから起動
指定プロセスの死活判定 v2
複数のピリオドが入る数字の文字列を数値として解釈して返す
与えられたICC Profileの名称リストからもっともバージョンの新しい(大きい)数字を持つものを返す
システムにインストールされているICC Profileのうち、指定キーワードに該当する名前を持つものでバージョン番号が最新のものを返す v2
Photoshopのsave optionをテキストで指定して反映させるテスト
AppleScriptObjCでボタンの文字色を変更
Xcode 4.6でAppleScript用語辞書の若干の間引きを
USBメモリやネットワーク上のサーバーなどをアンマウント
AppleScriptObjCでボタンを動的に生成
AppleScriptObjCでボタンを動的に生成(横に複数作成)
miで文字置換
AppleScriptObjCでMyriad Helpersの三角関数を使ってWindowを円運動
AppleScriptObjCとメモリ管理
AppleScriptObjCでPDFViewを使ってPDFをプレビュー(3)
ログファイルから時間帯ごとの度数分布を計算
指定のコード体系の全パターンのコードを生成 v1
指定のコード体系の全パターンのコードを生成 v2
指定のコード体系の全パターンのコードを生成 v3
指定のコード体系の全パターンのコードを生成 v4
指定のコード体系の全パターンのコードを生成 v5
リストを任意のデリミタ付きでテキストに v2
特定の語句を含むMail.appのフォルダ(mailbox)を抽出してフルパスを文字列化
現在表示中のCanvasに存在しているラインのうち青いものに影を付ける
miで選択中の内容をファイルに書き出してperlのプログラムとしてterminalで実行
miで選択中の内容をファイルに書き出してperlのプログラムとしてterminalで実行 v2
文字入力モードを制御
iTunesのMobileアプリをコピーしてすべて展開する
Find same file name with different extension
AppleのAppleScript関連ドキュメントの個人的な翻訳サイト
インストールされているアプリのAS辞書を書き出すv2
Mailで選択中のmessageの親フォルダのフルパスを文字で取得する
指定フォルダ中のファイル名が拡張子を外すと衝突するかどうかチェック
AppleのiBookstoreが日本国内向けにコンテンツ販売を開始
Safariで指定可能なユーザーエージェントのリストを返す
Safari 6で指定のURLをオープンする
Safariで指定User Agentで指定URLをオープン
共通項目をキーにしてリスト内の項目を統合する v2
アプリケーションのクラッシュレポートダイアログの表示切り換え
入れ子のリストの昇順、降順ソート(超高速版)
IPアドレスがプライベートIPアドレスかどうかチェック
OS X 10.8のdateに強烈なバグ
1Dリスト中のシーケンシャルサーチ
1Dリストのスイープ
自然言語による相対日付指定v14
CSVデータを読み込んでリスト化
SafariでRadiko選局を行う 10.6.8+5.1.8版
SafariでRadikoの選局を行う v2
開始日と終了日の間を、指定日数単位で切った{開始日,終了日}のリストの日付文字列リストを返す
手作りのノンブルが作ってあるPowerPoint書類に対して、座標位置(一番左側に寄せてある)を手がかりにフレームを取得してリナンバリング
0〜255の8ビットの値から構成されるRGB値のリストの色をプレビューする
Photoshop CS6でRGB→LAB、LAB→RGB変換
0〜255の8ビットの値から構成されるRGB値のリストの色をプレビューする
PowerPointで、オブジェクトの外側の線の色を、水色から青に変更
Photoshop CS6でRGB→LAB、LAB→RGB変換
Photoshop CS6でRGB→HSB、HSB→RGB変換
Photoshop CS6でRGB→RGB Hex、RGB Hex→RGB変換
Photoshopでオープン中の画像をグレースケール→白黒2値の画像にモードを変換する
Safariでオープン中のファイルを別途ダウンロードv2
Photoshop上で選択範囲を指定色(RGB)で塗りつぶす
AppleScriptの処理中断
PDFのページ数を数える
EPSファイルの破損チェック(高速版)
プレビュー.appをAppleScriptから操作
国民の祝日を求める v4
AppleriptObjCベースのCocoaアプリケーションのSandbox化は可能か?
入り組んだリストの中に指定要素が存在するかどうかをチェック
Mail.appのメールボックスオブジェクトを渡すと、テキストのフルパスに変換 v1
Mail.appの指定メールボックス内に任意のメールボックスを新規作成 v2
OmniOutlinerで選択中の行の内容のうち指定列のデータをすべて取得
リストをテキストに
指定の文字エンコーディングでテキストをファイルに保存
ASObjCExtrasでファイルの情報を取得
ASObjCExtrasで1Dリスト中の合計値、最大値、最小値を求める
ASObjCExtrasで1D List中のヌル要素を削除
ASObjCExtrasで1D List中のmissing valueを置換
ASObjCExtrasで2DのListをフラット化(1D List化)
OS X 10.10 Yosemite のAppleScript関連バグまとめ
2Dリストで最長の要素に満たない個数の要素は後ろに埋め草を追加
2D Listの各要素に指定の1Dリストの内容をインサートする
指定ファイルからサイズ情報を取得
ドロップレットのデバッグ方法
Finder Windowを円運動 v2
list同士のdiffをとる(asoc)
listの共通項を返す(asoc)
1D Listのユニーク化(asoc) 処理内容比較
asocで文字置換
2D Listを1D Listに変換
レコードの操作
レコードのリストをソート(asoc)
レコードのリストから抽出(asoc)
リストから抽出(asoc)
レコードのリストから抽出(別リストに該当するもののみ)
Keynote 6.5で各スライドのタイトル、マスタースライド名を取得してデータ化
1D Listを文字列長でソート
2D Listを文字列長でソート
1D Listを文字列長でソート v2
10.10でプリンタを選択して印刷
10.10でプリンタの情報を取得する
無限次元リストのフラット化
2D Listを文字列長でソート
1D Listの内容すべてに指定数値を加算
画像の特定のピクセルの色を取得
画像中の色数をカウント
指定アプリケーションがフルスクリーン状態かどうか調べる
NSNumberFormatterのテスト
as integerの落とし穴
数値の桁数を求める
同一パターンの連番文字列の作成
1Dリスト中の複数指定アイテムの出現位置をリストで返す
CoreImageでフィルタしまくり
Bluetoothに接続中のデバイス名を取得するv2
NSSoundで音声を再生
バージョン番号文字列からメジャーバージョンを求める
バージョン番号文字列からメジャーバージョンを求める v2v3
指定AppleScriptをしらべたり実行したりする
指定ロケールの月名、曜日名を取得する
AppleScriptでJavaScriptを実行する
SafariのWebViewのGUI Scripting的な参照を取得する
アプリケーションのローカライズ分布を取得する
アプリケーションのローカライズ分布を取得するv2
アプリケーションのローカライズ分布を取得する v4
アプリケーションのローカライズ分布を取得する v5
アプリケーションごとのローカライズ言語数を求める
オーディオファイルのチャンネル数と再生時間を取得する
aListのうち、bListに入っていない項目を返す
PDFをページごとに分解する
文字エンコーディングを自動判別してテキストファイル読み込み v1
文字エンコーディングを自動判別してテキストファイル読み込み v2
GUI Scripting、それは画面上のGUI部品に直接メッセージを送って強引にアプリケーションを動かす必要悪。AppleScript非対応機能を強引に動かすことが目的の機能です。
MarkdownエディタのMacDownも、PDF書き出しについてはAppleScript用語辞書にコマンドが掲載されていないので、Markdown書類のPDF書き出しはGUI Scriptingで行なっています。
メイン環境をmacOS 10.12.6から10.14.6に移行して、はじめて動かした重量級のAppleScriptがあります。指定フォルダ以下のPages、Markdown、Wordなどの書類をすべてデスクトップ上にPDFで書き出して、ファイル名順にならべかえて1つのPDFにまとめるAppleScriptです。
つまり、電子書籍の書き出し&連結作業を1本でこなすScriptなわけで、自分にとっては命綱的に重要なAppleScriptです。
で、こいつがmacOS 10.14.6上でまともに動かないことが判明して、顔色が変わりました。
システム環境設定のセキュリティ系の妨害を受けているのかと思って確認してみると、必要な設定はすべて行なってある状態。MacDownからのPDF書き出しだけが効いていません。
–注意!! ここでGUI Scriptingを使用。バージョンが変わったときにメニュー階層などの変更があったら書き換え
on macDownForceExport()
activate application "MacDown"
tell application "System Events"
tell process "MacDown"
— File > Export > PDF
–click menu item 2 of menu 1 of menu item 14 of menu 1 of menu bar item 3 of menu bar 1
click menuItemRef1
–Go to Desktop Folder
keystroke "d" using {command down}
–Save Button on Sheet
click button 1 of sheet 1 of window 1
end tell
end tell
end macDownForceExport
★Click Here to Open This Script
ためしに、SIPを解除して実行してみたものの、それでも問題は解決しません。
動きを観察していると、書き出し時に「保存」ではなく「キャンセル」ボタンをクリックしている模様。そこで、ボタンをIndexではなくTitleで指し示してみたら、問題なく書き出しできました。
–注意!! ここでGUI Scriptingを使用。バージョンが変わったときにメニュー階層などの変更があったら書き換え
on macDownForceExport()
activate application "MacDown"
tell application "System Events"
tell process "MacDown"
— File > Export > PDF
–click menu item 2 of menu 1 of menu item 14 of menu 1 of menu bar item 3 of menu bar 1
click menuItemRef1
–Go to Desktop Folder
keystroke "d" using {command down}
–Save Button on Sheet
click button "保存" of sheet 1 of window 1 –保存ボタンのIndexが変わっていた
end tell
end tell
end macDownForceExport
★Click Here to Open This Script
# 久しぶりに怪奇現象っぽい挙動で震えました。だいたい、怪奇現象とか心霊現象っぽい挙動というのは、技術や経験が足りない場合に「そう見える」だけであって、知っていたり経験していれば「当然」という現象に見えます
いま、ちょうどGUI Scriptingは端境期で、手で書かなくてもアプリケーションの状態を検知してオブジェクト階層を動的に走査して動かすようなScriptが一部で使われている一方で、古いタイプのIDやTitleを直接指定するような書き方が残っていたりします。
OSがアップデートされても、IDで書いておけば同じGUI部品を指定できるだろう、という思い込みがありましたが、Titleで指定していたほうがIDの数え方が変わっても影響がない、という現象だったのでしょうか。
久しぶりにハマりそうになりました。あと、MacDownのソースに手を入れて、PDF書き出し命令ぐらいは自前で実装したい気がします。
Edama2さんと「無理だよねー」「そうそう、絶対無理〜」などとメールで言っていたら、Shane Stanleyから届いた「できるよ」という衝撃のメール。
スクリプトエディタ上で記述する通常のAppleScriptで、CocoaのCustom Class宣言と呼び出しができるとのこと。
自分で動作確認してみるまで、半信半疑でしたが、、、、できますねこれは、、、
–> Download Editable and Executable Script Bundle
冗談半分で思いついたことを試してみたらできてしまったり、冗談半分でできるわけないよねと念のために書いておいたことが世界の誰かの目に止まったりと、「冗談半分」ってけっこう重要なことだと思えてきました。
以下、Shane Stanleyの説明による、その書き換え手順です。
こういう(↑)スタイルですね。かならずscript宣言しつつ、parent属性を宣言しておくところがXcode上のAppleScriptアプリケーションのスタイルです。あとで動作確認して、アプリケーションの起動や終了に関するイベントハンドラを書いておいたのは無駄(実行されない)ではないかとも思われました。
普通、AppleScriptのファイルが入る/Contents/Resources/Scripts/でも、ライブラリを入れておく/Contents/Resources/Script Libraries/でもなく、/Contents/Resources/の直下に入れます。ファイル名はオリジナルのEdama2さんのものをそのまま採用していますが、割となんでもいいようです。Custom Classファイルは分割してもいいし、このサンプルのようにまとめてもいいんでしょう。
# 追加実験してみたところ、Resourcesフォルダ以下の/Scriptsや/Script Libraries/フォルダと重複しない名称の別フォルダ(例:/Classes/)に入れておいても大丈夫でした
見たことのない光景ですが、書くことについてはとくに障害はありません。AppKit.Frameworkもuse宣言しておいたほうがよかったかもしれません。
set theBundle to current application’s NSBundle’s bundleWithPath:pathToFolderWithScripts
theBundle’s loadAppleScriptObjectiveCScripts()
★Click Here to Open This Script
試行錯誤して、上記の「pathToFolderWithScripts」にバンドル内の/Contents/Resources/を入れて実行すればよいことが理解できました。
以上の変更を加えて、ためしにスクリプトエディタ&Script Debugger上で実行してみたところ、改変前と変わりなく実行できてしまいました(冒頭のスクリーンショット)。
いや、これはめちゃくちゃすごいですよ!! 何がすごいって、CocoaのCustom Classをスクリプトライブラリ中に入れて呼び出せるということで、けっこう無茶な箱庭インタフェースが作れてしまう予感が、、、、。
そして、AppleScriptObjC(AppleScriptObjC.frameworkより)でスクリプトエディタの「.scpt」形式のファイルを読み込んで実行できてしまったということは、Xcode上のAppleScriptアプリケーション内のScriptもテキスト形式だけでなく、スクリプトエディタで編集できる.scpt形式のファイルを突っ込んで編集できる可能性が見えてきました。
ただ、テキスト形式になっていないと、Interface Builderとの連携のあたりで問題になりそうな気もします。
AppleScript名:customClassTest.scptd |
— – Created by: Edama2 2020/01/10 – Adviced by: Shane Stanley 2020/01/11 – Modified by: Takaaki Naganoya 2020/01/12 — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppleScriptObjC" use scripting additions property _clock_text_view : missing value –> 時計用の文字列 –Script Bundle内のResourcesフォルダを求める my performSelectorOnMainThread:"raizeWindow:" withObject:(missing value) waitUntilDone:true # ウィンドウを作成 #タイマー割り込み |
AppleScript名:CocoaAppletAppDelegate.scpt |
script CocoaAppletAppDelegate property parent : class "NSObject" on applicationWillFinishLaunching:aNotification — end applicationWillFinishLaunching: on applicationShouldTerminate:sender return current application’s NSTerminateNow end applicationShouldTerminate: end script script CustomWindow script RoundView |
本Scriptは、Edama2さんから投稿していただいたものです。Cocoa AppleScript AppletでCustom Classを宣言して作られた、丸いウィンドウ(透明ウィンドウの上に丸いグラフィックを描画)を表示して、タイマー割り込みで時計を表示するAppleScriptです。
–> Download Editable and Executable Applet
AppleScriptのランタイム環境はいくつかあり、それぞれに「できること」と「できないこと」、「手軽さ」などが異なります。
(1)スクリプトエディタ上で記述、実行する環境
一番セキュリティ上の制約が緩く、できることの多い環境です。
(2)Script Debugger上で記述、実行する環境
Cocoaのイベントやオブジェクトのログ表示などができる環境です。
(3)Applet環境
AppleScriptの実行ファイルです。
(4)Script Menu環境
macOS標準装備の、メニューからAppleScriptを実行できる環境です。
さらに、Cocoa Scriptingの機能に着目してみると、見え方が変わります。
本Scriptを記述している「Cocoa AppleScript Applet」環境(上の図の赤い部分)は、スクリプトエディタ上で記述する通常のAppleScriptと、Xcode上で記述するCocoaアプリケーションの中間的な性格を持つものです。スクリプトエディタ上で直接は動かせず、アプレット形式で動作させることになりますが、スクリプトエディタ上で動かすよりも、よりCocoaの機能が利用できます。
Cocoa AppleScript Appletでは、アプリケーション(Applet)起動や終了の最中で発生するイベントを利用できますし、本ScriptのようにCocoaのCustom Classを宣言できます。これは、普通のスクリプトエディタ上で記述する(本Blogの大部分のScriptのような)Scriptではできない真似です。
→ Shane Stanleyからツッコミが入って、手の込んだ作業を行うとできるとかで(テンプレートそのままでは無理)、後で実際に試してみます
タイトルは「丸いウィンドウと時計の表示」 NSWindowのカスタムクラスを使ったタイトルバーなしのドラッグで移動できる丸いウィンドウとオマケに時計を表示したものです。 初心者受けしそうなやつです。 問題はそこではなく、 XcodeやCocoa applescript appletから実行するASOCだとカスタムクラスが作れるけど、 ノーマルのapplescriptから実行するASOCではカスタムクラスが作れないということです。 表現がややこしいですが...。 ノーマルのapplescriptからカスタムクラスを作ると、ただのスクリプトオブジェクトにしかなりません。 誰かうまい解決方法を知っている人がいたら教えてください。
ちょうど、こういう資料をまとめていたので補足説明に役立ってしまいました。スクリプトエディタ上で記述する通常のAppleScriptでもCustom Cocoa Classが宣言できると便利そうですが、どんなもんでしょうか?
Custom Classは便利なので使いたくなる一方、AppleScriptのインタプリタ上で実行するため、Objective-Cなどで書くのと同じような感覚で使うと「遅くて使えない」という話になると思いますが、このEdama2さんのサンプルぐらいの使いかたであれば、ちょうどいいんじゃないかというところです。
歴史的にみると、Cocoa-AppleScript Appletは、Xcode上で記述するCocoa-Applicationを簡略化してスクリプトエディタ上でCocoa Scriptingを手軽に使えるように手直しした「途中」の環境といえます。
Cocoa-AppleScript Appletは、GUIが手軽に作れるわけでもなく、スクリプトエディタ上で直接実行やログ表示ができるわけでもなありません。マスターしたところで最終到達点がCocoaアプリケーションほど高くなく、編集や習熟もしづらいことから「中途半端」「使えない」という評価になっていました(自分も使っていませんでした)。
その後、Cocoa-AppleScript Appletの機能要素をさらにダウンサイジングして、スクリプトエディタ上で手軽に記述・実行ができるように進化したのが現在・広くつかわれているCocoa Scripting環境です。
ただ、使いやすくなって広く使われるようになったはいいものの、「Xcodeを使うまでもないが、もうちょっとCocoaの機能が利用できないか?」という意見も出るようになり、Cocoa-AppleScript Appletを再評価してもいいんじゃないかと考えるようになってきてはいます。
ちなみに、本Cocoa-AppleScript AppletでCustom Classを宣言しているのと同じような書き方で、通常のCocoa Scriptingの環境で動かすような変更を加えたScriptもEdama2さんが試していますが、それは「動かない」ということで結論が出ています。
AppleScript名:CocoaAppletAppDelegate.scpt |
script CocoaAppletAppDelegate property parent : class "NSObject" property _clock_text_view : missing value –> 時計用の文字列 property _clock_timer : missing value –> 時計用のNSTimer on applicationWillFinishLaunching:aNotification my raizeWindow() end applicationWillFinishLaunching: on applicationShouldTerminate:sender my _clock_timer’s invalidate() return current application’s NSTerminateNow end applicationShouldTerminate: # ウィンドウを作成 on raizeWindow() # 時計用の文字を作成 tell current application’s NSTextView’s alloc() tell initWithFrame_(current application’s NSMakeRect(35, 120, 300, 40)) setRichText_(true) useAllLigatures_(true) setTextColor_(current application’s NSColor’s whiteColor()) setFont_(current application’s NSFont’s fontWithName:"Arial-Black" |size|:48) setBackgroundColor_(current application’s NSColor’s colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.0) setAlphaValue_(1.0) setEditable_(false) –setString_("00:00:00") set my _clock_text_view to it end tell end tell # 時計を更新するNSTimerを作成 set my _clock_timer to current application’s NSTimer’s scheduledTimerWithTimeInterval:1 target:me selector:"idleHandler:" userInfo:(missing value) repeats:true # 丸いViewを作成 set aFrame to current application’s NSMakeRect(0, 0, 300, 300) tell current application’s RoundView’s alloc() tell initWithFrame_(aFrame) setNeedsDisplay_(true) setSubviews_({my _clock_text_view}) set customView to it end tell end tell #スクリーンのサイズを調べる set aScreen to current application’s NSScreen’s mainScreen() # Window set aBacking to current application’s NSWindowStyleMaskBorderless –set aBacking to current application’s NSBorderlessWindowMask set aDefer to current application’s NSBackingStoreBuffered tell current application’s CustomWindow’s alloc() tell initWithContentRect_styleMask_backing_defer_screen_(aFrame, aBacking, aDefer, false, aScreen) –setTitle_(uniqueName) –>タイトル setBackgroundColor_(current application’s NSColor’s clearColor()) –>背景色 setContentView_(customView) –>内容ビューのセット setDelegate_(me) –>デリゲート setDisplaysWhenScreenProfileChanges_(true) –>スクリーンプロファイルが変更されたときウインドウの内容をアップデートするか setHasShadow_(true) –>ウインドウに影があるか setIgnoresMouseEvents_(false) –>マウスイベントを無視するか –setLevel_((current application’s NSScreenSaverWindowLevel) + 1) –>ウインドウの前後関係の位置 setOpaque_(false) –>ウインドウを不透明にするか setReleasedWhenClosed_(true) –>閉じたときにメモリを解放するか # |center|() makeKeyAndOrderFront_(me) –>キーウインドウにして前面に持ってくる –setFrame_display_(aFrame, true) –>表示 end tell end tell end raizeWindow #タイマー割り込み on idleHandler:aSender set mesStr to time string of (current date) (my _clock_text_view)’s setString:mesStr end idleHandler: end script script CustomWindow script RoundView |
Script Object関連の調べ物をしていて、AppleのWebサイト掲載のReferenceを見ていたら、サンプルをまじえて説明されていたので、理解が深まりました。
AppleScript:トップレベルObject。不変
my(me):現在のScript Object。可変
it:現在のアプリケーションObject。可変
AppleScript > my(me) ≧ it
というレベルになっていることもよく理解できました。
ただ、サンプルが自分的にいまひとつわかりやすくなかったので、自分用に書き換えてみました。バージョン取得ではなく、「名前を取得」しないといまひとつ分からないんじゃないでしょうか。
AppleScript名:testScript |
me –> «script»–実行中のAppleScript書類(Script Object) AppleScript it tell application "Finder" on testMe() script aTEST |
最前面のアプリケーションのAppleScript用語辞書をオープンするAppleScriptです。
macOS標準装備のScript Menuに入れて呼び出すことを前提に作りました。はるかかなた昔に作って、OSバージョンが上がるごとに細かい改修を行なって使い続けているものです。
この手のScriptは日常的にAppleScriptを書いている人間なら、たいてい書いてみたことがあるはずです。しかし、あまり生真面目なアプローチでアプリケーションバンドル中のsdefのパスを求めてオープンといった処理を行っていると、「例外」にブチ当たって困惑します。
sdefファイルを直接持っていないAdobe Creative Cloud製品です。InDesignあたりがそうなんですが、直接sdefを保持しておらず、どうやら実行時に動的に組み立てるようで、絶体パス(absolute path)で指定してもsdefをオープンできません。
また、Microsoft Office系アプリケーションのsdefも、外部の(OS側のsdef)テンプレートをincludeするようなので、生真面目に対象アプリケーションのInfo.plistの情報をもとにアプリケーションバンドル中のsdefファイルをオープンするように処理すると、sdefの一部のみを表示するようになってしまって、sdef全体を表示することができません。
そうしたもろもろの問題に当たって、結局アプリケーションそのものをScript Editorでオープンするように指定しています。
AppleScript名:–このアプリケーションの用語辞書を表示する v4 |
— Created 2017-07-23 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –最前面のプロセスのファイルパスを取得する –スクリプト用語辞書をScript Editorでオープンする手順 on getAppPropertyFromInfoPlist(aP, aPropertyLabel) |
AppleScript users ML上で2016/10/16〜18に行われていた議論の内容を自分でも再確認しました(Thanks Yvan!)。一時フォルダの場所を求める「path to temporary items」の値が、macOS 10.12から変更になっています。
▲AppleScript Users ML上の議論のフロー(Mail Flow Visualizerによりバッチ出力。つまり、Mail.app上で出力フローを選択してAppleScriptでフロー図出力しています)
AppleScript標準装備の「path to」コマンドは、Classic MacOS環境からMac OS X環境に移行した後に重要度が上がったコマンドです。OS側が用意している特別な意味を持つフォルダの場所を返してくれます。
とくに、(いまさらですが)Mac OS X環境はマルチユーザー環境なので、とくにPicturesとかDocumentsとかDesktopとかの特別なフォルダのパスを求める機能は基礎的ではあるものの、とても重要です。このあたりをめんどくさがってなんでもかんでも固定パスで書きたがる人を見かけたことがありますが、その人が書いたプログラムは他のユーザー環境で動かなくて苦労していました(本人ではなく周囲の人々が)。
AdobeのCS/CCアプリケーションのサンプルAppleScriptでも固定パスで書かれたものを多数見かけましたが、あれはなんだったんでしょう。
もともと、path toコマンドにより求められる各種パスには、
system domain:/System network domain:/Network user domain:~
などのほか、
local domain:/Library Classic domain: Classic Mac OSのシステムフォルダ(Classic環境をサポートするOS&ハードウェアの組み合わせ上でのみ有効)
などの「ドメイン」が指定できることになっていました。system domainはOSのSystemが利用、User domainはユーザーのホームフォルダ以下。network domainはmacOSのNetBootが廃止/他の機能への移行対象となっている(すでに、iMac ProではNetBoot非サポート)ほか、そのような環境下にないと有意な結果が得られません。
ドメインの区分けが存在するものの、これらの区分のうちClassic domainははるかかなた昔に消滅、network domainも使ったことのあるユーザーは稀(まれ)でしょう。
そんな中、作業用の一時フォルダの場所を求める「path to temporary items」の仕様がmacOS 10.12で変更になっていました。
テンポラリフォルダの特性ゆえに、細かいディレクトリ名はユーザー環境ごと、実行時ごとに微妙に異なりますが(赤字部分が変化する部分)、上の図では(↑)どのあたりに作られるのかという点に着目して色分けしてみました。
macOS 10.12以降では、user domainでもsystem domainでも同じような場所が指定されることになることがわかります。
ちなみに、Cocoaの機能を用いて求められる一時フォルダはまた別の場所が示されています。
use framework "Foundation"
current application’s NSTemporaryDirectory() as text
–> "/var/folders/h4/jfhlwst88xl9z0001s7k9vk00000gr/T/"
ディスプレイの輝度変更を行うAppleScriptです。
AppleScriptにディスプレイの輝度変更を行う機能はないので、GUI Scripting経由で(画面上のGUI部品を野蛮に操作して)変更するか、あるいは「他の方法」を採用することになります。
本Scriptは「他の方法」をとってみたものです。画面の輝度変更については、そのようなニーズがあり、割とまともにOSに機能が実装されていることもあり、IOKitを呼び出して変更している例がいろいろ見つかります(Objective-Cとかで)。そういったものをFramework化してAppleScriptから呼び出すか、あるいはコマンドライン上で動作するプログラムをAppleScript内に入れて呼び出すか、といったところになります。
Github上で探し物をしてみたところ、nriley氏の「brightness」というツールがコマンドライン上から呼び出せるようになっており、AppleScriptのバンドル内に突っ込んで呼び出しやすそうでした。
そこで、実際にAppleScriptバンドル書類中に突っ込んで、いい感じに呼び出せるように最低限の機能を実装してみました。ディスプレイの接続数の確認(getDisplayNumber)、指定ディスプレイの現在の輝度確認(getBrightNess)、そして指定ディスプレイの輝度設定(setBrightNess)です。
–> Download displayBrightness.scptd (Script Bundle with brightness binary in its bundle)
ディスプレイ番号は1から始まるものとして扱っています。輝度は0.0〜1.0(1.0が一番明るい)までの値を指定します。
一応、brightnessユーティリティでは複数のディスプレイが接続された状態を前提に処理しているのですが、どうせ輝度変更ができるのはMacBook ProやiMacなどの内蔵ディスプレイだけです。外部接続したディスプレイの輝度は変更できません。
本Scriptのようなお気楽実装だと問題になってくるのが、
(1)デスクトップマシン(MacPro、Mac miniなど)で外部ディスプレイを接続していない(ヘッドレス運用)の場合への対処
(2)ノート機+iMac/iMac Proで、メインディスプレイを本体内蔵ディスプレイ「以外のもの」に指定している場合への対処
(3)ノート機で、Lid Closed Mode運用している(本体を閉じて外部ディスプレイをつないで使っている)状態への対処
などです。本Scriptはそこまで厳密な対応を行っていません。ただ、実用上はこのぐらいで問題はなさそうだ、という「割り切り」を行って手を抜いています。
各条件でテストを行って「使える」という確証が得られたら、sdef(AppleScript用語辞書)をつけたライブラリにでもするとよさそうです。
また、本Script中に同梱しているbrightnessツールの実行ファイルはNotarizationを通していないため、2020年2月3日を過ぎると10.15.2以降のmacOSで何らかのダイアログが出て実行をキャンセルされる可能性がありますが、正直なところmacOS 10.15.xは「バグが多すぎ」「実用性なし」と判断。macOS 10.15.xは自分としては「パス」するつもりなので、現時点において対処する必要性を感じません(仕事で納品するバイナリについては全力で対処しますが)。
AppleScript名:displayBrightness.scptd |
— – Created by: Takaaki Naganoya – Created on: 2020/01/04 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set dRes to getDisplayNumber() of me set bRes to getBrightNess(1) of me set sRes to setBrightNess(1, 0.7) of me on getDisplayNumber() on getBrightNess(displayNumber as integer) on setBrightNess(displayNumber as integer, targBrightnewss as real) |
Mac App Storeで、Piyomaru SoftwareによるMac用アプリケーション「Double PDF」の新バージョンv2.0をリリースしました。100% AppleScriptで記述しています。
本バージョンは、macOS 10.13においてScripting Bridge経由でPDFViewを正しくアクセスできないバグが発生している症状を回避したものです。表示中のページ管理などをすべてアプリケーション側で行うことにより、機能の回復を実現しました(書いていて情けない)。
v1ではGPUImage.frameworkを利用して画像処理していましたが、これを取り外してすべてAppleScriptで処理するように変更しました。
■v2.0の追加機能
・ダークモード対応
・画像比較時のカラーモード追加(従来はグレースケールのみ)
・30言語に対応(English, Catalan, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Norwegian Bokmål, Polish, Portuguese, Romanian, Russian, Simplified Chinese, Slovak, Spanish, Swedish, Thai, Traditional Chinese, Turkish, Ukrainian, Vietnamese)
・Unicode文字の「Zero Width Space」削除機能を追加
■v2.0の修正機能
・順次Diffチェック時に、アプリケーションアイコン上に描画するプログレスバーの進捗度が間違っていたのを修正
指定文字列のAppleScriptをコンパイル(構文確認、中間コードへのコンパイル)、実行してエラーの詳細を取得するAppleScriptです。
AppleScript名:指定文字列のAppleScriptを実行してエラー詳細を取得.scptd |
— – Created by: Takaaki Naganoya – Created on: 2020/01/01 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set asSourceString to "set a to 123 set asObj to current application’s NSAppleScript’s alloc()’s initWithSource:(asSourceString) –AppleScriptオブジェクトがコンパイル(構文確認、中間コードへの解釈)ずみかどうかをチェック –コンパイル(構文確認)してエラー確認 set exeRes1 to asObj’s executeAndReturnError:(reference) –> {missing value, (NSDictionary) {NSAppleScriptErrorMessage:"beepz変数は定義されていません。", NSAppleScriptErrorBriefMessage:"beepz変数は定義されていません。", NSAppleScriptErrorNumber:-2753, NSAppleScriptErrorRange:(NSConcreteValue) NSRange: {13, 5}}} |