macOS 12.5上のスクリプトエディタで、バンドル形式のAppleScript書類を「実行専用」で書き出してみたところ、Finderのファイルプレビューで中身が見えますね(^ー^;;;
これを脆弱性と言わずに何と言うのだろーか? Apple純正のスクリプトエディタで「実行専用」で書き出すと、Finderプレビューで内容が読めてしまうというのは。
重要なScriptについては、Script Debuggerで書き出すことをおすすめします。
Release候補だった21G69から若干ビルド番号が上がって、21G72がmacOS 12.5としてリリースされました。
macOS 12.x系は、正式リリース後から大幅な変更が続けられており、「それは、リリース前にやっておくことでは?」「リリースの意味とは?」「実質、リリース後の1年で開発が完結しているのでは?」といった疑問が山のように出てくるOSになっています。
それでも、破滅的なバグやユーザー環境を無視しまくった改変などを各βの段階でとどめておけたのは、よかったことでしょう。魔のAppleの手から世界を救っても、自分にはほとんど利益がないところがなんとも。
Appleのソフトウェアも、App Storeのレビューチームの手で一度レビューを加えるべきなんではないでしょうか。β版に致命的なバグが多すぎです。
macOS 12の各Betaの出来が著しくよくないので、macOS 13betaの出来映えに不安を覚える昨今です。macOS 12は、β版のときには非常に出来が良かったのに、リリース後にどんどん不具合が増えるという謎のリリースが行われていました。もう2年に一度ぐらいのアップデートぐらいにしないと無理だと思います。
外付けのSSDにmacOS 12.4→macOS 13 beta 3にアップデートの順でアップデートしてインストールしてみました。
慣れの問題なのか、iOSに寄せた画面構成に変更して、デザインがどんどんダメになっていっているような印象があります。「コレジャナイ感」が全体に漂っています。やる気のなさでWindowsと似ている印象です。
Blogへの画面キャプチャの掲載は控える必要はありますが、バージョン情報やその他のファイルについてはとくに問題ないものと考え、調査した概略を記しておきます。
真剣に使い込んだわけではなく、あくまでも触ったぐらいの試用です。
これは、macOS 12の時にもかなり後のβになってからバージョン番号が変わったので、なんともいえません。現状はそうだというだけです。
スクリプトエディタの環境設定から、スクリプトメニューを有効にしてもメニューバー上に表示されません。プログラム的には同じ場所に存在しており、単独で起動ができない状況。ただし、これが「廃止された」という話ではなく、現状では起動できていない(macOS 13のセキュリティモデルと合致していないため起動できない???)状況です(多分)。廃止、という状態ではないと思います。macOS 13 beta4でもまだ起動できていません。
System PreferenceがSystem Settingsに名称変更になりました。User InterfaceがmacOS(NEXTSTEP)風からiOS風に変更になっており、Preferences Paneの区分が変わってしまっています。AppleScriptから各パネルを表示できるようになっており、このあたりでmacOS 13上のパネルIDなり名称でオープンできることと、旧来のIDや名称で表示できるという状態にまで持っていくのか? あるいは、いつものApple風のお仕事でいえば「macOS 13上では何もしなかった」ということもありえます。
スクリプトエディタの編集支援のために用意されている「Script Assistant」の仕組みにおいて、macOS 12では「絵文字入りのフォルダ、絵文字入りのファイル」が入っていると、項目が重複して表示されるバグが発生していました。macOS 13beta 4ではこれが発生していないことを確認しています。
本Blogに掲載しているプログラムリストは、すべてapplescript:// URLリンクを埋め込んであり、リスト末尾にあるリンクをクリックするだけで、スクリプトエディタに内容を転送できるようにしています。
ところが、macOS 12.5RCにおいてSafariで表示した本Blog内のコンテンツで、applescript:// URLリンクをクリックしたところ、
・プログラムリストが短いと内容はスクリプトエディタに転送される
・プログラムリストが一定基準よりも長くなると、スクリプトエディタに内容は転送されなくなる
といった現象が確認されています。知り合いにいろいろ確認してみたところ、
・macOS 12.5以前のOSであっても、上記のような現象を確認していた
という話です(「じゃあ教えてよ!」と心の中でツッコミを入れていましたが)。
macOS 10.15のときに、PDFView上のURL Link(applescript://)が一律で無視されたときには、不服申し立てを行い、最終的には、
・macOS標準添付のPreview.app上のPDFはapplescript:// URL Linkは無視される
・サードパーティのアプリケーション上のPDFViewのapplescript:// URL Linkの妨害はやめる
ということになったようです。いつ状況が変わるかわからないので、未来永劫この状況が維持されるかどうかは不明です。自分だけがAppleに文句を言っていたわけではないと思いますが、基本的にAppleとの歴史は戦いの積み重ねです。Appleのやらかしを指摘して、事実関係のみ述べ、修正されるまで執念深く追求するという戦いの繰り返しです。
→ 本件は私のやらかしかもしれません、、、、
本BlogへのAppleScriptのプログラム掲載に使用しているAppleScript→HTML変換プログラム「AS Publisher v18」の内容を再確認してみましたが、Cocoaの機能を用いて文字列をURLエンコードしているだけです(そんなに複雑な処理をしていません)。部品単品でエンコード/デコードを行って検証してみたものの、呼び出している部品に問題は見つかりませんでした。
→ この部品でURLエンコードする方法を間違っていたもよう。ただし、過去のmacOSでは「間違ったURLエンコードが飛んでくることがあるので、対処しとくか」という処理になっていたところが、「厳密に正しいものしか処理しないようにしよう」という方針に変わったことが原因?
次に、Safariで何らかの妨害をしている可能性について検証してみました。
Safariではなく、CotEditor上でURLエンコードしたAppleScriptのプログラムのHTMLコンテンツをオープンし、CotEditorの最前面の書類からURL部分をURL Event的にオープン。これもSafari同様の問題が発生していることを確認しました。
コンテンツ中のURL部分をData Detectorを用いて抽出→Openさせた場合、URL内容が一定以上の長さを超えると途中で切られてしまうという動作を確認。macOS全体で「長いURL」への応答を殺しているという現状を確認。こういう話は一切WWDCでやらずに、コソコソ変更するんですよねー。
→ 事実関係を確認すると、本件についてはとくに悪意はない模様
本問題の確認直後、すぐにAppleにバグレポートを行いました。この後は、PDFViewのときと同様に、Appleと2・3年あまりも不毛なやりとりを続けることになるのでしょう。事実上の牛歩戦術ともいえます。
そのやりとりをしている2・3年の間、ぼーっとしているわけにも行かないので対応策を考えておかなければなりません。
確実で安全な対策は、Script Debuggerでapplescript:// URLリンクを受信するように、Script Debugger側で設定することです。これなら、途中でApple側の妨害や嫌がらせに遭うことなく、プログラムリストの内容を転送できます。
ただし、「AppleScriptを今日はじめました」という人がScript Debuggerをダウンロードしているはずがないので、そこには対策しておく必要があります。
少ない労力で対処するのであれば、掲載リストのZipアーカイブをダウンロードできるようにしておくぐらいでしょう。
プラス、本Blogの過去記事アーカイブの英訳版を企画中ですが、日本語版も出してもいいような気もします。
電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第21巻、「Cocoa Scripting」です。PDF 42ページ。サンプルScriptのZipアーカイブを添付。
→ 販売ページ
Cocoa Scriptingについては、既刊の「Cocoa Scripting Course」があり、同書の冒頭の入門部分を再編集したものが本書です。
macOS 10.10以降、すべてのAppleScriptの実行環境において、Cocoa呼び出しの機能がサポートされました。いわゆる、Cocoa-Bridgeされた言語になったのです。
Cocoaのすべての機能を呼び出せるわけではないですし、主にmacOSのFoundationとAppKitの範囲内ですが、一部の機能が呼び出せるだけでも機能は膨大で、かつ、これまでに無理やり間に合わせで組んでいたような内容が、本物を呼べるようになり、AppleScriptの世界に質と量と処理速度の面で大きな変化をもたらしました。
Cocoaのオブジェクトに特有の挙動……オブジェクトの生成に専用のメソッドを利用し、属性値を取り出すのにもメソッド呼び出しが必要。複数のオブジェクトが同じことを確認するのに、上位クラスで定義されている照合メソッドを呼び出す必要があるなど、実際に使ってみるとそんなに難しくはないと感じました(量が多くて面倒なだけで)。
Cocoa Scriptingは何のために?
Cocoa Scriptingってどういうもの?
Cocoa Scriptingの実際
Cocoa Scriptingの威力
Cocoa Scriptingのメリット
Cocoa Scriptingに必要なもの
Cocoa Scriptingまとめ
Cocoa Scripting9つの誓い
Cocoa Scripting環境の進化の歴史
Cocoa Scriptingに適したmacOS
参考資料:AppleScriptランタイム環境情報
SIP解除の是非
開発・実行環境のちがい
処理手順の違い
メインスレッド実行が必須な機能への対処
delegation, notification
実行環境の違いによる書き換え
AppleScriptでCocoaオブジェクトを呼び出すと…
サブルーチン記述
Objective-C風ハンドラにおけるme/my記述
クラス拡張(継承)
高速なCocoa Scriptを書くためには
アプリケーションとの相互乗り入れに注意
暗黙の型変換
一部のAppleScript内蔵コマンドで書き換えが必要
計算の優先順位を示すカッコを修正
オブジェクトの数え方
Application ScriptingとCocoa Scripting
毎回毎回、何かかしら嫌がらせをブチ込んでくるmacOS 12.5シリーズ、RC(21G69)で「applescript://」Custom URL Linkが一定以上の長さになると無視されることが判明しました。
これは、本Blogなどに掲載しているURLリンク入りのプログラムリストの機能を無効にするものです。
この動作は、macOS 10.15のPDFViewで行った嫌がらせと同じ仕様です。さんざん文句を言ったところ、Preview.app上でのURLイベントクリックについてはStop、他のアプリケーションのWindow上のPDFViewについては嫌がらせをしなくなったという経緯があります。
自分も本件はAppleにバグレポートしますが、Appleはレポート件数で重要かそうでないか判断するので、本Blogをご覧の方々にもAppleへのレポートをお願いしたいところです。
–> Demo Movie of macOS 12.5RC applescript:// URL Link ignorance
電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第20巻、「コンパイル(構文確認)」です。PDF 32ページ。
→ 販売ページ
スクリプトエディタのウィンドウに、思わせぶりに配置されている「コンパイル」コマンドのボタン。
この「コンパイル」というのは、世間一般的には、プログラム言語を実行コードに変換する作業です。SwiftやObjective-Cなどの言語で「コンパイル」といったら普通は実行コードへの変換です。
しかし、スクリプト言語で、かつインタプリタ(逐次実行)型言語であるAppleScriptにおいて、その意味は少し異なっています。AppleScriptのコンパイルとは、構文確認+中間コードへの変換です。
また、AppleScriptの実行処理系が演算の優先順位の指定を必要とした場合には、どこか適当な(正確ではなくあてずっぽうという意味で)場所にカッコを補います。
コンパイル時の構文チェックは、AppleScriptの最低限のお約束的な文法チェックだけなので、対象のアプリケーションのオブジェクト階層や、コマンドを実行する対象のオブジェクトが正しいか、といった厳密なチェックは行われません。実行して確認する必要があります。コンパイル(構文確認)の挙動は独特で、誰もが知っておくべき内容です。
AppleScriptのコンパイル(構文確認)とは?
最低限の構文チェック
ライブラリ、Frameworkのチェック
OS(AppleScript)互換性チェック
実行環境チェック
中間コードへの置き換え
構文色分け設定にもとづいて書式適用
コンパイル(構文確認)時に大/小文字を書き換え
空白文字,インデント文字の置き換え
if, tell, repeatなどのブロックの入力補完
特殊記号の置き換え
パラメータのboolean表記を置き換え
列挙パターン表記の置き換え ほか
演算優先順位を示すカッコを補う①
演算優先順位を示すカッコを補う②
実行環境にアプリケーションが存在しない場合
バンドルIDが同じで名称変更になった場合
macOS 12.xのBetaではいろいろ楽(苦)しませていただいています。ええもう本当に。
本日ダウンロードできるようになったmacOS 12.5(21G69)がBetaなのか正式リリースなのか不明ですが(Release候補、という噂が)、いまのところAppleScriptの実行が封じられたり、Dockに登録したアイコンにファイルをドラッグ&ドロップで2・3回渡すとファイルがオープンできなくなるといったBeta 5の不具合には遭遇してはいません。
Apple側はRelease Notesを出すわけでもなく、説明も一切しないので、何を基準に内容を判断すべきなのかよくわかりません。
macOS 12.3の頃のβでもさんざんやらかしてくれましたし、macOS 12.5 betaでもやらかしました。しばらくβに付き合うのは勘弁していただきたい。これだけ大規模な問題のあるBetaをノーチェックで出すのは(頭が)どうにかしている、としか言えません。
macOS 10.13の「Beta段階ではまともに動いていたのに、Release段階で廃墟リリース」というやらかし。10.15の「夏の間にゴミクズ化してまともに動かない」とか、macOS 11.0の「(機能によっては)Apple Siliconで10年前のIntel Macの70倍遅い」(12.xで直りましたが)とかいう、目の覚めるようなクズOSアップデートの数々。
社内でダメなものにダメと言わないから、こんなものを出し続けるのではないでしょうか? 社内でもチェックぐらいはしてほしいですよね。これで明らかになったのは、Apple社内でmacOSのβ版をまるっきり使っていない、まったく試していないということです。
■表 macOS 12.x上で発生した(している)AppleScript系のバグと解決状況一覧
発生バージョン | 内容 | 解決したか? | 状況説明 |
12.x | スクリプトエディタのコンテクストメニューで、絵文字を含むフォルダ/ファイルの内容が(複数階層下では)重複して表示される | No | |
12.3 | AppleScript書類をオープンできない | Yes | |
12.2? | Scriptを実行すると「表があふれました」というエラーが表示される | ???? | |
12.2? | インストールされていないアプリケーションを操作するScriptをオープンできない | Yes | 12.5では保存されたままの内容でオープンできている |
12.3 | Finder上のselection itemsをオープンした際に、作成したアプリは起動されるがファイルはオープンされない | Yes | macOS 12.3.1/12.4beta1で解消 |
12.5beta5 | アプリケーション同士のイベントのやりとりが2回以上発生するとエラー-609になる | Yes ??? | 12.5にて解消? 確認中 |
対象のキーワードの構成情報を分解して、2つのキーワードの共通要素をリストアップする「マッキー演算」を行うライブラリ「Common Elements Lib」をアップデートしました。
–> Common Elements Libをダウンロード(v1.3a)
マッキー演算とは、「槇原敬之」と「SMAP」の共通項を求め、結果に「世界に一つだけの花」をリストアップする処理です(ほかにも出てきますが)。
–> {“第58回NHK紅白歌合戦”, “木村拓哉”, “東京都”, “ニッポン放送”, “テレビ朝日”, “ミリオンセラー”, “大阪城ホール”, “インターネットアーカイブ”, “社長”, “ミュージックステーション”, “ケンタッキーフライドチキン”, “スポーツニッポン”, “日刊スポーツ”, “第42回NHK紅白歌合戦”, “リクルートホールディングス”, “エフエム東京”, “日本ゴールドディスク大賞”, “フジテレビジョン”, “J-POP”, “小倉博和”, “世界に一つだけの花”, “We are SMAP!”, “日本”, “日本武道館”, “ISBN”}
WikipediaのMedia APIを用いて問い合わせを行って計算を行います。そのため、(Wikipedia上における当該項目の記事内容の変化によって)実行時期によって演算結果に差が出ます。
アップデート理由は、前バージョンではインターネット接続確認を「http://www.google.com」に対して行っていたところに、このドメインに対してhttp経由でのアクセスが行えないようになったので、エラーを起こすようになりました。
このドメインにhttps経由でアクセスするよう変更しました。
電子書籍の新刊を発売しました。新シリーズ「AppleScript基礎テクニック集」の第19巻、「リモートコントロール」です。PDF 37ページ、付録AppleScriptのZipアーカイブを添付。
→ 販売ページ
AppleScriptは、リモートコントロールを行うために作られた言語です。1台のコンピュータ上でスクリプトの実行環境と、操作対象のアプリケーションという別々のプロセスの間でメッセージを送り合って、制御を行います。その姿は、あたかも電話をかけて出前の注文をお願いしているかのようです。
1台のコンピュータ上ですら「通信」しているのですから、ネットワーク、主にLAN上で通信して他のコンピュータ上で起動しているアプリケーションとの間で通信して操作するのも同様に「通信」でできます。これがリモートApple Eventsです。
柔軟に通信を行って、イベントを投げ合うのがAppleScriptの本来の姿ではあるのですが、昨今のセキュリティ問題の高まりにより、あまり野放図に柔軟な処理ができないようにいろいろな制約が設けられるようになった……はずだったのですが、なぜかmacOS 10.13あたりからふたたび制限が緩和され、ネットワークごしのリモート・アプリケーション操作機能が復活しました。
いろいろ注意すべき点はありますが、使いこなすと便利で楽しいリモートコントロール。詳しく分かりやすく、誰も教えてくれない内容について、1冊まとめて説明いたします。
macOS 12.5 beta 5の不具合でAppleScriptはおろかドラッグ&ドロップでファイルのオープンができなくなるわ、Finderのtoolbarに登録したアイコンのクリックも3回目以降は効かなくなるわで、最悪の作業環境の中、LAN上の他のOSバージョンのマシンにリモートコントロールで作業を依頼していろいろ作っていました。
リモートコントロールのための言語
AppleScript実行時のリモートコントロールの詳細
通常のリモートコントロールのイメージ
同一マシン上のリモートコントロールのイメージ
リモートマシンのリモートコントロール
リモートAppleEventsの歴史
AppleScriptと常駐アプレットの間で通信する
アプリケーション操作と同じ呼び出しも可能
他のユーザの常駐アプレットをリモートコントロール
他のユーザに切り替えて常駐アプレットを実行
同一マシン上の他のユーザのプロセスを指定
操作対象となるコンピュータの名前を調べる
コンピュータ名/Bonjour名は編集可能
対象マシンのユーザ名を確認
例:macOS 10.15以降のユーザ名制限解除
ネットワーク上の他のマシン上のアプレット操作
リモート・マシンの指定方法
リモートApple Events操作時の注意点
他のマシン上のアプリケーションのリモートコントロール
リモートコントロールを行うべきか、べきでないのか?
対象マシン上のアプリケーションをコントロール
電子書籍の新刊を発売しました。新シリーズ「AppleScript基礎テクニック集」の第18巻、「グラフ表示ダイアログ」です。PDF 37ページ、付録AppleScriptのZipアーカイブを添付。
→ 販売ページ
地味で控え目なAppleScriptにおいて、ダイアログ上でアニメーション表示可能なグラフを表示できるようになったのは、ごくささいな小さな発見があったためです。
macOS 10.10以降ですべての実行環境でサポートされるようになったCocoa呼び出し機能。当然WebViewも生成して表示可能なことはわかっていました。ところが、標準的なNSWindowの上にWkWebViewを配置して初期設定を行なっただけでは、WkWebView上のイベント回しが効かず、アニメーション表示は行えませんでした。
ところが、そんな状況を打破したのはNSAlertダイアログ。ごくごく限られたUIを乗せて利用するようにメーカー側から指導されてきた、誰も見向きもしなかった間に合せのダイアログ表示インタフェースです。
ところが、このNSAlert上でWkWebViewを表示すると、Webコンテンツのイベント回しをきちんと処理して、グラフ表示アニメーションやマウスによる操作、マウスカーソル移動のマウスオーバーのイベントにも反応することがわかりました。
ここから、さまざまなJavaScript製グラフ表示ライブラリを試行錯誤し、今日ではテキストエディタ上の選択範囲のテキストの文字種別を円グラフでアニメーション表示するといった、きわめて身近で日常的な用途に手軽にグラフ表示ダイアログが利用されるようになりました。
このやり方について、基礎的なところから詳細に解説を行い、実際に動くコードを提示し、macOS上のさまざまな実行環境での状況をご紹介しています。
グラフ表示ダイアログの全体像
グラフ表示ダイアログの構成技術
組み立てるWeb系データの構造
CDN上のグラフ表示ライブラリを呼ぶ
Web表示部品をダイアログ上に表示
JavaScriptで扱えるデータを組み立てる
AppleScriptのバンドル中からhtmlを読み込む
HTMLテンプレートファイルを準備
HTMLテンプレートをまとめる作業
JavaScript書き換え例
Webダイアログで
さまざまなグラフを表示
AMCharts:円グラフ
AMCharts:棒グラフ
AMCharts:ワードクラウド
AMCharts:世界地図+国選択
AMCharts:世界地図(ドリルダウン)+国選択
特殊なAS実行環境ではさらなる変更も必要
Automator環境では、表示されない
ショートカット環境では、表示されない
Switch Control環境では表示OK!
Service Station環境で動作
Stream Deck環境で動作
FileMaker Pro環境では動く
Visual Studio Code環境で表示OK(一応)
本日リリースされたmacOS 12.5beta 5で大問題が発生しています。Scripterは本アップデートに絶対にアップデートしてはいけません。
# macOS 12.xの環境が複数あって、まともに動作しない状態にしてもダメージがなければ、macOS 12.5 beta 5を体験してもよいでしょう。イキュラス・キオラ(いやな記憶を消す魔法)
# macOS 12.5正式リリース版では修正されたようです。
KeynoteでもCotEditorでもいいのですが、AppleScriptから(Script Editor、Script Debuggerなど実行環境を問わずに発生)GUIアプリケーションを操作すると、1・2回目は正常に動くのですが、3回目あたりから(同じ処理であっても)エラー -609になります。
一部で「AppleScriptユーザーにだけ影響があるのでは?」と言われましたが、全ユーザーに影響があります。
Dockの上に登録しているアプリケーションのアイコンに、書類をドラッグ&ドロップする操作を3回繰り返しただけでオープンできなくなりますし、Finder上で書類をダブルクリックないしCommand-Oでオープンしても、3回目からはエラーになります(Finderの再起動が必要に)。
今朝方から、Switch Controlでいつも画面上に出しているフローティングパレットからSafariのコントロールができなくなっていて、「Webサイト側の仕様が変わったのか?」などと思っていたのですが、CotEditorもKeynoteもみんなこの状況に陥っていました。
どうも、AppleEventのやりとりを監視しているようで、プロセス間通信が同じアプリケーション間で発生すると2〜3回目からエラー -609になります。
自社製品を使っていない管理職が「こうしろ」とてきとーに仕様を決めているようにしか見えないのですが(ーー;;;;
–> See macOS 12.5 beta 5 bug example movie 1
–> See macOS 12.5 beta 5 bug example movie 2
これまでにも、AppleはOS X 10.7あたりでURLイベント経由で実行されたAppleEventについて、複数のアプリケーション操作をともなう動作を行なったときには、問答無用で処理を止めるといった変更を、Scripterに何の説明もなく行ってきました。
このURLイベント系の場合には「セキュリティ向上」という話の枠組みの中で「仕方ないかな」という納得感はありましたが、このmacOS 12.5 beta 5の「3ステップ爆弾」(Three steps bomb)についてはまったく納得できません。
この仕上がりでリリース(β版だけど)する連中の気が知れません。使っていると、ムカムカします(Dockへの書類のドラッグ&ドロップも3回目以降はエラーになります。本当に使って試したのか疑問な仕上がり)。macOS 13の出来が不安になるような出来です。macOS 10.13のときにも盛大にやらかしたので、macOS 13という名前で不吉なものを感じてしまいます。
# macOS 12.5正式版では修正されたようです。リリースノートも何もないので、Apple側がこのどえらいバグをどこまで認識しているのか不明ですけれども
Keynoteの最前面の書類で表示中のスライド中の表で、選択中の各セルの内容の文字列の長さを表インタフェースで一覧表示するAppleScriptです。
こんなKeynote書類上の表があったとして、その選択中の各セルに入っている文字列の長さを、AppleScriptライブラリ「display table by list」を用いて一覧表示します。実行には同ライブラリのインストールが必要です。
実行の前提として、Keynoteで書類をオープンしてあり、書類上の表の集計対象のセルを選択しておくことが必要です。
文字列長と元の文字列を一覧表示します。
AppleScript名:Keynoteの表で選択中のセルの文字列長さを一覧表で表示.scpt |
— – Created by: Takaaki Naganoya – Created on: 2022/07/04 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" — El Capitan (10.11) or later use framework "Foundation" use scripting additions use easyTable : script "display table by list" tell application "Keynote" tell front document tell current slide try set theTable to first table whose class of selection range is range on error display notification "Numbers: There is no selection" return end try tell theTable set aRes to value of cells of selection range end tell end tell end tell end tell set fLabels to {"文字列長", "文字列"} set newList to {} repeat with i in aRes set j to contents of i if j is not equal to missing value then set aLen to length of j set the end of newList to {aLen, j} end if end repeat tell current application set aRes to (display table by list newList main message "テキストの文字列長" sub message "Keynoteの表で選択中のテキストの各セルの文字列長" size {800, 400} labels fLabels icon "") end tell |
Keynoteの最前面の書類で表示中のスライド(ページ)で選択中の表の、指定行のテキストのセルの文字列長の分布をグラフ出力するAppleScriptです。
# Blogの英訳本の企画を動かしていますが、たしかに日本語のタイトルを(日本人が)見てもけっこうわかりにくいのかも?
# タイトルをGoogle翻訳に突っ込むと、それなりに「そんな感じじゃね?」という英語が出てきますが、、、
こういう、電子書籍の紹介文を掲載しているページがあって、そこに書いてある紹介文の長さの分布を計算してみるために、ありものの部品を組み合わせて作ったものです。
「だいたい3行ぐらい」というふんわりとしたルールのもとに18冊分ほど書いてきましたが、本の冊数が増えてページを追加するにあたって、文字列長の分布を計算してみようと思い立ってScriptを書いてみました。
043 # 044 ## 045 046 ### 047 048 ## 049 ### 050 # 051 # 052 # 053 054 # 055 056 # 057 # 058 059 060 061 062 063 064 065 066 067 068 #
分布はわかりましたが、似たような処理を行うことが多いので、何か簡単なGUIをつけておいたほうがいいような気がするような、、、
AppleScript名:選択中の表のデータを取得して、特定の行のデータの文字列長を集計.scpt |
— – Created by: Takaaki Naganoya – Created on: 2022/07/04 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSMutableArray : a reference to current application’s NSMutableArray set aList to get2DListFromKeynoteTableSelection() of me if aList = "" then return false –取得した各セルの文字列長をすべて取得する set aLen to length of aList set aaLen to length of item 1 of aList set nList to {} repeat with i from 3 to (aLen) by 3 repeat with ii from 1 to aaLen set the end of nList to length of (contents of item ii of item i of aList) end repeat end repeat –文字列長の度数分布を計算 set minRes to calcMin(nList) of me set maxRes to calcMax(nList) of me set itemCount to maxRes – minRes set n2List to makeBlankListByItem(itemCount + 1, 0) of me repeat with i in nList set j to contents of i set tmpNum to contents of item (j – minRes + 1) of n2List set tmpNum to tmpNum + 1 set item (j – minRes + 1) of n2List to tmpNum end repeat –文字列長の度数分布のグラフを文字出力 set tList to {} set aCount to minRes repeat with i in n2List set gText to returnRepeatedText(i, "#") of me set tNumStr to makeFN(aCount, 3) of me set totalText to tNumStr & " " & gText set the end of tList to totalText set aCount to aCount + 1 end repeat return retArrowText(tList, return) of me –リストを任意のデリミタ付きでテキストに on retArrowText(aList, aDelim) set aText to "" set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set aText to aList as text set AppleScript’s text item delimiters to curDelim return aText end retArrowText on returnRepeatedText(aNum, aChar) set aText to "" repeat aNum times set aText to aText & aChar end repeat return aText end returnRepeatedText on makeBlankListByItem(itemNum, blankItem) set tmpList to {} repeat itemNum times set the end of tmpList to blankItem end repeat return tmpList end makeBlankListByItem on calcMin(aList as list) set tmpFItem to first item of aList set aClass to class of tmpFItem set nArray to (NSMutableArray’s arrayWithArray:aList) if aClass = real then set maxRes to (nArray’s valueForKeyPath:"@min.self")’s doubeValue() else set maxRes to (nArray’s valueForKeyPath:"@min.self")’s intValue() end if return maxRes end calcMin on calcMax(aList as list) set tmpFItem to first item of aList set aClass to class of tmpFItem set nArray to (NSMutableArray’s arrayWithArray:aList) if aClass = real then set maxRes to (nArray’s valueForKeyPath:"@max.self")’s doubeValue() else set maxRes to (nArray’s valueForKeyPath:"@max.self")’s intValue() end if return maxRes end calcMax on makeFN(aNum, aDigit) set aText to "00000000000" & (aNum as text) set aLen to length of aText set aRes to text (aLen – aDigit + 1) thru -1 of aText return aRes end makeFN –Keynoteで選択中の表のすべてのセルのデータを2Dで返す on get2DListFromKeynoteTableSelection() tell application "Keynote" tell front document tell current slide try set theTable to first table whose class of selection range is range on error return "" –何も選択されてなかった場合 end try tell theTable set selList to value of every cell –すべてののデータを取得 set selHeight to count every row set selWidth to count every column end tell end tell end tell end tell set aLen to length of selList set aaLen to selHeight set bList to {} repeat with i from 1 to aaLen set aHoriList to {} repeat with ii from 1 to selWidth set j1 to ii + (i – 1) * selWidth set tmpCon to contents of item j1 of selList set aClass to class of tmpCon if aClass = number or aClass = integer or aClass = real then set tmpCon to tmpCon as integer end if set the end of aHoriList to tmpCon end repeat set the end of bList to aHoriList end repeat return bList end get2DListFromKeynoteTableSelection –テキストを指定デリミタでリスト化 on parseByDelim(aData, aDelim) set aText to current application’s NSString’s stringWithString:aData set aList to aText’s componentsSeparatedByString:aDelim return aList as list end parseByDelim –1D/2D Listのユニーク化 on uniquifyList(aList as list) set aArray to current application’s NSArray’s arrayWithArray:aList set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self" return bArray as list end uniquifyList |
電子書籍の新刊を発売しました。新シリーズ「AppleScript基礎テクニック集」の第17巻、「リスト(配列)」です。PDF 35ページ、付録AppleScriptのZipアーカイブを添付。
→ 販売ページ
AppleScriptにも配列変数はあります。その名も「リスト型変数」、一般的には「リスト」と呼ばれています。
AppleScriptのリストに対して、他のプログラミング言語と比べて「配列の要素が1から始まるなんて信じられない!」という意見も見かけますが、0で始まる(0-based index)か、1で始まる(1-based index)かの違いだけです。
リスト(配列)を使った基礎的な処理、要素の取り出しやループ、削除、しぼりこみ、ソートなどの定番をご紹介。 PDF 35ページ、サンプルScriptのZipアーカイブつき
AppleScriptの配列=リスト型変数
リストの名前の付け方
リストの要素指定①
リストの要素指定②
リストに入れられるデータ
リストの内容でループ
複数の配列を同時にループ
指定要素を削除
指定アイテムを指定アイテム番号に挿入
配列の添字っぽい書き方でアクセス
2次元リストから要素の内容を部分一致で抽出①
2次元リストから要素の内容を部分一致で抽出②
1次元リスト、数値ソート(昇順)
1次元リスト、数値ソート(降順)
1次元リスト、数値ソート(昇順/降順)
1次元リスト、カスタムソート順でソート
2次元リスト、数値ソート(昇順)(1/3)
2次元リスト、数値ソート(昇順)(2/3)
2次元リスト、数値ソート(昇順)(3/3)
1次元リスト、数値ソート(昇順/降順)
1次元リスト(配列)を幅を指定しつつ2次元リストとして評価し、1番左側のセルとの変化を横方向にサーチして検出するAppleScriptです。
もともと、macOS標準搭載の「辞書.app」に収録される各辞書データの名称が、各OSバージョンでどのように変化しているかを表計算ソフトNumbers上でチェックしていました。辞書.appの辞書をCocoa Frameworkを通じて呼び出し、さまざまな便利な処理を行っているため、辞書名称が変わると日常的に利用しているAppleScriptに影響が出てしまいます。その変化を検出するために、辞書名の変化を知っておこうというチェック作業が発生しています。
辞書.appの収録辞書名称は、意図したものか意図していないものか不明ですが、OSバージョンごとに微妙に変化することが知られています。そうした名称細部の変化を実際にチェックするのに、専用のScriptを使っていました(過去形)。
ただし、NumbersのデータをAppleScriptから取得すると、2D Listではなく1D Listとして返ってきます。そのさいに、BridgePlusの機能を用いて1D→2D変換を行ったのちに、いろいろ処理を行ってきました。
リストの1D→2D変換処理なんて、使っている場所が多すぎて数えきれないぐらいですが、Script Menu上で動かすScriptでBridgePlusを呼び出せなくなっており(macOS 10.14以降)、今後Script Menuが機能強化されるとは考えにくいところです。
サードパーティのFastScriptsなどでFramework入りScriptの実行をサポートするとか、そういう進化ができてほしいところですが、それもちょっと期待できません。
結果として、BridgePlusを極力使わなくて済むように、機能の置き換えを進めるしかありません。無理な機能もありますが、1D→2D変換ぐらいなら問題ありません(そして、出現頻度がおっそろしく高いものであります)。
そして、実際にNumbers上のデータを横方向(左→右、冒頭から末尾へ)に走査して変更を検出する処理を書いてみました。
処理に柔軟性が欲しかったので、追加でフラグ(reNewF)を用意しました。
これがfalseの場合には、横方向に変更を走査し、変化を検出した場合には評価を打ち切ります。trueの場合には、変化を検出した場合でも変化の検出を続行します。
AppleScript名:1D Listを2D的に評価してアイテム内の相違点を検出.scptd |
— – Created by: Takaaki Naganoya – Created on: 2022/06/28 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set aList to {1, 1, 1, 2, 3, 3, 3, 3, 3, 4, 3, 5} set diffRes to getListDifference2D(aList, 3, true) of me –> {{xAddrs:{2}, yAddr:2}, {xAddrs:{2}, yAddr:4}}–reNewF=falseで評価 –> {{xAddrs:{2}, yAddr:2}, {xAddrs:{2, 3}, yAddr:4}}—reNewF=true で評価 –1D Listを、2D Listとして評価しつつ、{cell1, cell2, cell3}のcell 1とcell2, cell3が違っていないか評価して返す on getListDifference2D(dList as list, aWidth as integer, reNewF as boolean) script tdSpd property dList : {} end script copy dList to (dList of tdSpd) set diffList to {} set diffAdrList to {} set yOffsetCount to 1 set aCountMax to ((length of dList) div aWidth) repeat with aC from 1 to (length of dList) by aWidth set tmpList to items aC thru (aC + aWidth – 1) of (dList of tdSpd) set i1 to first item of tmpList set i2 to rest of tmpList set xOffsetCount to 2 set xDiffList to {} repeat with ii in i2 set jj to contents of ii if i1 is not equal to jj then set the end of diffList to {i1, jj} set the end of xDiffList to xOffsetCount if reNewF = true then copy jj to i1 else exit repeat end if end if set xOffsetCount to xOffsetCount + 1 end repeat if xDiffList is not equal to {} then set the end of diffAdrList to {xAddrs:xDiffList, yAddr:yOffsetCount} end if set yOffsetCount to yOffsetCount + 1 end repeat return diffAdrList end getListDifference2D |
電子書籍の新刊を発売しました。新シリーズ「AppleScript基礎テクニック集」の第16巻、「スクリプトエディタの使い方」です。PDF 38ページ、付録AppleScriptのZipアーカイブを添付。
→ 販売ページ
スクリプトエディタは、Classic Mac OSのスクリプト編集プログラムをAppleがMac OS Xに移植したものです。
初期にはCarbonベースで書かれ、v10.4でCocoa&Universal Binary化、v10.6で64bit化。v11でApple Silicon/Intel 64のUniversal Binary化と、Mac上のすべての移行を経験してきた猛者です。
原始時代のスクリプト編集プログラムには、検索機能すら実装されておらず、Script Debuggerとの差は明白でした(仕事で使うならScript Debuggerが必要、という状況はいまでも変わりません)。
そんなスクリプトエディタも、Mac OS X 10.4で32Kバイト以上のスクリプトが編集可能になり、AppleScriptからのコントロールが行えるようになったことで、「使える道具」になってきました。
同時にURLイベントに対応したことで、筆者のBlog「AppleScriptの穴」掲載の、リンクのクリックで内容が転送されるプログラムリストをWeb上で共有できるようにもなりました。
本書を通してご覧になると、「これは拾い物!」「こんなの知らなかった!」というスクリプトエディタの機能が見つかることでしょう。
本書付録には、スクリプトエディタのコンテクストメニューから起動するスクリプト記述支援AppleScript集「Piyomaru Script Assistant v2.1」、各種macOS標準搭載アプリケーション用のテンプレートAppleScript集を添付。
さまざまな角度から、スクリプト記述のための生産性を向上させる仕組みを提供しています。
スクリプトエディタの機能一覧
スクリプト新規作成/テンプレートからの作成
ユーザー用Scriptテンプレートの追加方法
Cocoa-AppleScriptアプレットの新規作成
URLイベント受信
短縮入力の展開
「説明」欄の編集
構文書式設定
コンパイル(構文確認)
バンドル内ファイル編集
Info.plist編集
スクリプトアシスタント入力
ヘルプの閲覧
AppleScriptからの操作
新規作成スクリプトのデフォルトウィンドウ指定
その他の機能
AppleScriptの実行環境における位置付け
実行/強制メインスレッド実行
ログ表示/履歴管理
スクリプトメニューの有効化/無効化
用語辞書の閲覧
ライブラリ管理
スクリプト保存
スクリプト書き出し/コード署名
Piyomaru Script Assistantの最新状況をまとめておきました。
スクリプトエディタのコンテクストメニューから呼び出す入力補助スクリプト群は「スクリプトアシスタント」と呼ばれています。
Mac OS X 10.4の時代からこの「スクリプトアシスタント」が存在しており、簡単なスニペット入力のための機能がAppleから提供されてきました。
Apple純正のスクリプトアシスタントについては「帯に短し、たすきに長し」(翻訳できるのか、この日本語の慣用句表現)といったところであり、「これ、もうちょっとなんとかなんねえの?」というものでもありました。
そして時は流れ、「スクリプトアシスタント」はそのままの内容で提供し続けられていたため、すっかり内容が陳腐化。仕組みはいいのにOS標準添付されているScriptが使いものにならないという状態が続いていました。
Piyomaru Softwareでは自分がScriptを書くために、サポート範囲を広げた自家用版のスクリプトアシスタントを作って利用してきました。Mac OS X 10.4の時代からこうしたものが存在していました。これは、書籍「AppleScriptリファレンス」を持ち歩かなくても、多くの構文要素を入力できるようにする、というところに目標を設定していました。
さらに、OS X 10.10以降でCocoa Scriptingがすべての実行環境でサポートされるようになると、Cocoa Scriptingの利用を前提としたスクリプトアシスタントの必要性が高まり、Piyomaru Softwareでは電子書籍の付録として「Piyomaru Script Assistant」を作成しました。
そして、Piyomaru Script Assistant自体も毎年のOSアップデートを経て、部分的に動かないものが出てきました。
主に、Piyomaru Script Assistantに含んでいる、「Piyomaru Softwareが提供しているAppleScriptライブラリを呼び出すScript」の中で動かないものが出てきた、という状況です。
これは、作りたての頃は非常に役立つものでしたが、Googleが提供する検索結果画面のHTMLをXML的に解釈して結果を取得するという作りであったために、時間の経過とともに「動かなくなる」ことが確実視されていたものでもあります。
CotEditor用のPowerPackでも実装レベルを後退させており、AppleScript単独でGoogle検索を行うようなものではなく、Safari経由で検索結果を表示するというものを提供しています。
Appleがドラッグ&ドロップ系の機能を縮小するのでは? ということから企画したライブラリであり、有用性については疑いようもないのですが、macOS 11あたりでUI仕様が大幅に変更になったことにより、動かなくなっています。
ちょっとコードの規模が大きいのと、99%自分が作ったものではないので、これはメンテナンスし切れない感じです。オープンソース化して様子を見るというのが「考えられる対応」でしょうか。
macOS 12上で動かなくなっていました。理由は判明していて、改修版をBlogにアップロードしてあります。
macOS 12で発生、継続しているバグが、「ファイル名に絵文字を使っているScriptをScript Assistantの仕組みを使ってコンテクストメニュー表示させると、ファイル名/フォルダ名が重複して表示される」というものです。
一度「これで治ったか?」という確認が来ましたが、解消されていません。
新刊「AppleScript基礎テクニック集⑯スクリプトエディタの使い方」の付録として、若干のアップデートを行なった「Piyomaru Script Assistant v2.1」を添付しており、上記の問題が確認されているScriptを削除しています。
Keynoteでオープン中の最前面の書類の現在のスライド(ページ)の上で3重のshapeオブジェクトを下に敷いているテキストアイテムを検出し、文字色を変更するAppleScriptです。
macOS 12.5beta+Keynote v12.1の組み合わせで作成・チェックしてみましたが、Keynote v12.xの固有の機能などは使っていないので、もっと古い環境でも動くはずです。
▲処理後 右側のテキストの色まで変わってしまっているのは意図しなかった処理(わかってたけど)
Keynote書類上でshapeオブジェクトを重ねて何かを表現することはよくありますが、重ねた場所の上に置いてある文字色だけ変更したい場合が往々にしてあります。
さっさと動かすことだけ考えて、ありものの「オブジェクトの重ね合わせ検出」Scriptを使い回しました。そのため、本当に入れ子状態の3つのオブジェクトを検出しているわけではなく、重ね合わせが3回発生しているテキストアイテムを検出しています。
もうちょっと凝った処理を行えば、本当に3階層の入れ子状態のshapeを検出できそうな気はしますが、さすがに使い捨てレベルのScriptにそんなに手間暇をかけるわけにもいかないので、現状ではこんなものでしょう。
Keynoteのselectionがまともに動くようになったので、いろいろ実践的なレベルのScriptを書けるようになりましたが、オブジェクトの重ね合わせ順なども取れたりすると、もっといろいろ書けそうです。
オブジェクトのposition、width、heightを取得する処理は、もうちょっと高速に実行できるように書けそうです(まだまだ、安全第一の処理内容)。
あとは、imageオブジェクトのpathとかイメージデータそのものを取得して、各種画像フィルタをかけてKeynote書類に書き戻せるとよさそうな気がします。
AppleScript名:テキストアイテムと1重のシェープの重なり検出 v2.scptd |
— – Created by: Takaaki Naganoya – Created on: 2022/06/25 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set collisonNum to 1 set targPointSize to 32.0 set targColList to {0, 0, 0} –Black set tList to {} –text items set trList to {} set sList to {} –shapes set srList to {} –set bgColList to {} –background color set colList to choose color tell application "Keynote" tell front document tell current slide –text itemの情報抽出ループ set allTList to every text item repeat with i in allTList set j to contents of i tell j set {xPos, yPos} to position set aWidth to width set aHeight to height set aRect to makeRect(xPos, yPos, aWidth, aHeight) of me end tell set the end of tList to j set the end of trList to aRect end repeat –shapeの情報抽出ループ set allSList to every shape repeat with i in allSList set j to contents of i tell j set {xPos, yPos} to position set aWidth to width set aHeight to height –set aBGCol to background color set aRect to makeRect(xPos, yPos, aWidth, aHeight) of me end tell set the end of sList to j set the end of srList to aRect set the end of bgColList to aBGCol end repeat set atLen to length of trList set arLen to length of srList set outTlist to {} –shapeと重ね合わせが発生しているtext itemの検出ループ repeat with i from 1 to atLen set atRec to contents of item i of trList set atObj to contents of item i of tList set collisionC to 0 set tmpCSize to point of first character of object text of atObj –当該text itemに対して、shapeオブジェクトとのNSRectの重ね合わせが指定数発生しているかをチェック repeat with ii from 1 to arLen set tmpRect to contents of item ii of srList set aF to detectRectanglesCollision(atRec, tmpRect) of me –背景色(background color)のリストを確認 set aBG to contents of item ii of bgColList –if {aF, aBG, tmpCSize} = {true, targColList, targPointSize} then set collisionC to collisionC + 1 if {aF, tmpCSize} = {true, targPointSize} then set collisionC to collisionC + 1 end repeat –オブジェクトのRectangleが重なり合っている「回数」で判定 if collisionC = collisonNum then set the end of outTlist to atObj end if end repeat end tell end tell end tell –文字色を塗り替えるループ tell application "Keynote" tell front document tell current slide repeat with i in outTlist set j to contents of i ignoring application responses set color of object text of j to colList end ignoring end repeat end tell end tell end tell on makeRect(xPos, yPos, aWidth, aHeight) return current application’s NSMakeRect(xPos, yPos, aWidth, aHeight) end makeRect –NSRect同士の衝突判定 on detectRectanglesCollision(aRect, bRect) set a1Res to (current application’s NSIntersectionRect(aRect, bRect)) as {record, list} set tmpClass to class of a1Res if tmpClass = record then –macOS 10.10, 10.11, 10.12 return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}}) else if tmpClass = list then –macOS 10.13 or later return not (a1Res = {{0.0, 0.0}, {0.0, 0.0}}) end if end detectRectanglesCollision –1から任意の数までのアイテムで、2個ずつの組み合わせのすべての順列組み合わせパターンを計算して返す –ただし、1×1とか2×2などの同一アイテム同士の掛け合わせを除去するものとする on retPairPermutationsWithoutSelfCollision(aMax) set aList to {} repeat with x from 1 to aMax repeat with xx from 1 to aMax if x is not equal to xx then set tmpItem to {x, xx} set a2List to sort1DNumList(tmpItem, true) of me if {a2List} is not in aList then set the end of aList to a2List end if end if end repeat end repeat return aList end retPairPermutationsWithoutSelfCollision –1D List(数値)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート on sort1DNumList(theList as list, aBool as boolean) tell current application’s NSSet to set theSet to setWithArray_(theList) tell current application’s NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(missing value, aBool) set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor} return (sortedList) as list end sort1DNumList |
v12で発生していた、新規書類をAppleScriptから保存できないバグは修正されていません。