CotEditorのメンテナーの@1024jp氏の談話によると、
https://x.com/1024jp/status/1896829943587508664
CotEditor v 5.1.0 → 5.1.1 でAppleScript経由のprint機能がうまく動作していなかったのを動作するように修正したとのこと。
ここのところ、macOS側の機能の不全により、AppleScript経由でのprint機能の実行がうまく動作していないケースが発生しており、それに対処したとのこと。
CotEditorのメンテナーの@1024jp氏の談話によると、
https://x.com/1024jp/status/1896829943587508664
CotEditor v 5.1.0 → 5.1.1 でAppleScript経由のprint機能がうまく動作していなかったのを動作するように修正したとのこと。
ここのところ、macOS側の機能の不全により、AppleScript経由でのprint機能の実行がうまく動作していないケースが発生しており、それに対処したとのこと。
CotEditorがバージョン5.1.0にアップデートしました(翌日、5.1.1にアップデートしましたが、AS的には差はありません)。
アップデート内容は多岐に渡っていますが、AppleScript的には、documentのcontentsにeditable(boolean)属性が追加されました。
実際に、AppleScriptからこの属性値を操作して、想定どおりの挙動を行うかどうかをチェックしてみました。こうしたテストは開発者側でも行なっているかどうか怪しいところなので(とくにAppleのノーチェックぶりが目に余る)、大事な作業です。
想定どおりの動作を行なっているので、確認OKです!
AppleScript名:v51.0 document editable test.scpt |
tell application "CotEditor" tell front document set editable of it to true set edF to editable –> true set contents of it to "ABC" set editable of it to false set edF to editable –> false set contents of it to "CDE" end tell end tell |
オープンソースのテキストエディタ「CotEditor」の「write to console」コマンドにオプションが追加されました。
title(実行したAppleScript名の表記)と、timestamp表示の有無を指定できるようになっています。
ただし、これらのオプションが効くには条件があります。CotEditorの外部から、スクリプトエディタやScript Debuggerなどで実行したAppleScript内でCotEditorに対してwrite to consoleコマンドを実行した場合には、これらのオプションを指定していても、とくにtitle(ファイル名)については効きません。
CotEditorの内蔵スクリプトメニュー内で実行したAppleScriptにおいて「write to console」コマンドを実行した場合にはtitle(ファイル名)、timestamp(日時)の指定が有効です。
AppleScript名:コンソールテスト1.scpt |
tell application "CotEditor" write to console "ぴよまるさんだよ" with title without timestamp write to console "ぴよぴよさんだよ" with title and timestamp end tell |
新刊電子書籍「AppleScript基礎テクニック(33)複数のアプリをコントロール」を刊行しました。全74ページ、サンプルAppleScriptアーカイブつき。
→ 販売ページ
macOS上のGUIアプリの書類やウィンドウ中で選択中のオブジェクトを取得し、その情報をもとにAppleScriptで処理を行なって、もとの選択オブジェクトに反映させるといった処理を、日常的に行っています。
このような書き方ができると、まるでAppleScriptによってGUIアプリの機能を拡張しているようにも見えます。実際には外部で処理を行なっていたとしても、使い勝手としては拡張しているように振る舞えます。
ある意味、AppleScriptの備える最強の機能といってもよいでしょう。本書で、この強力なselection機能について、その概要から実例、注意点にいたるまで幅広くご紹介いたします。
PDF 74ページ、Zipアーカイブ添付
■最初に:macOS 13以降では最初にステージマネージャを必ずオフにしてください
macOS 13.x
macOS 14.x
macOS 15.x
その他、オフにすることが望ましい機能
■アプリ上の選択中のオブジェクトにアクセスする予約語「selection」
GUIアプリ上の選択中のオブジェクトを知る
選択中のオブジェクトは、1つだけじゃない
選択中のオブジェクトを加工することも
選択中のオブジェクトの情報分析
■選択中のオブジェクトの情報をもとに他のアプリで処理
selection系の機能をサポートしているアプリ一覧
selectを含む予約語を持つアプリと予約語①
selectを含む予約語を持つアプリと予約語②
selectを含む予約語を持つアプリと予約語③
■selectionの主な実例
selectionの取得方法①(Finder)
selectionの取得方法②(Finder)
selectionの書き換え①(Finder)
selectionの書き換え②(Finder)
selectionの取得方法③(Finder)
selectionの取得方法(住所録)
selectionの書き換え(住所録)
selectionの書き換え(住所録)
selectionの取得方法①(Keynote)
selectionの取得方法②(Keynote)
selectionの書き換え(Keynote)
selectionの取得方法①(ミュージック)
selectionの取得方法②(ミュージック)
selectionの書き換え(ミュージック)
selectionの取得方法①(CotEditor)
selectionの取得方法②(CotEditor)
selectionの書き換え(CotEditor)
selectionの取得方法①(Numbers)
selectionの取得方法②(Numbers)
active sheetの取得方法(Numbers)
selection rangeの取得方法①(Numbers)
selection rangeの取得方法②(Numbers)
selection rangeのセル内容書き換え①(Numbers)
selection rangeのセル内容書き換え②(Numbers)
selection rangeのセル内容書き換え③(Numbers)
selectionの取得方法①(Excel)
selectionの取得方法②(Excel)
選択中のワークシートの取得方法(Excel)
selectionの書き換え(Excel)
selectionの取得方法(Pixelmator Pro)
select-を含む予約語解説①(Pixelmator Pro)
select-を含む予約語解説②(Pixelmator Pro)
select-を含むコマンド実例①(Pixelmator Pro)
select-を含むコマンド実例②(Pixelmator Pro)
select-を含むコマンド実例③(Pixelmator Pro)
select-を含むコマンド実例④(Pixelmator Pro)
select-を含むコマンド実例⑤(Pixelmator Pro)
select-を含むコマンド実例⑥(Pixelmator Pro)
select-を含むコマンド実例⑦(Pixelmator Pro)
select-を含むコマンド実例⑧(Pixelmator Pro)
select-を含むコマンド実例⑨(Pixelmator Pro)
select-を含むコマンド実例⑩(Pixelmator Pro)
select-を含むコマンド実例⑪(Pixelmator Pro)
■selectionを使用うえで注意すべき点
注意点1:大量のオブジェクトの受け渡しに要注意
注意点2:情報の書き戻し時には時間がかかる例も
注意点3:選択オブジェクトの種別判定を①
注意点3:選択オブジェクトの種別判定を②
CotEditorで2つの書類をオープンしておき、行単位での差分を検出し、新規書類に結果を出力するAppleScriptです。
もともと、macOS搭載のFramework名一覧の差分を検出する資料を作成する必要があり、これを片付けるために作成しました。
本AppleScriptを実行すると……
のように、結果を出力します。それほど巨大なデータを想定して作ってはいないので、ほどほどの規模に抑えて利用してください。
AppleScript名:左右のドキュメントを比較.scpt |
use AppleScript version "2.4" use scripting additions use framework "Foundation" script spd property aList : {} property bList : {} end script set (aList of spd) to {} set (bList of spd) to {} tell application "CotEditor" set dCount to count every document if dCount is not equal to 2 then display notification "Error: This script needs only 2 documents" return –Document number Error end if tell window 1 set w1Bounds to bounds copy w1Bounds to {w1X1, w1Y1, w1X2, w1Y2} set w1Doc to document of it end tell tell window 2 set w2Bounds to bounds copy w2Bounds to {w2X1, w2Y1, w2X2, w2Y2} set w2Doc to document of it end tell if w1X1 > w2X1 then set {w1, w2} to {2, 1} else set {w1, w2} to {1, 2} end if tell document w1 –左ウィンドウ set (aList of spd) to paragraphs of contents end tell tell document w2 –右ウィンドウ set (bList of spd) to paragraphs of contents end tell end tell –ゴミ掃除 set (aList of spd) to cleanUp1DList((aList of spd), {" "}) of me set (bList of spd) to cleanUp1DList((bList of spd), {" "}) of me –差分計算 set (cList of spd) to getDiffBetweenLists((aList of spd), (bList of spd)) of me –結果出力テキスト組み立て set aRes to listToTextUsingDelim(addItems of (cList of spd), "") set bRes to listToTextUsingDelim(minusItems of (cList of spd), "") –結果の新規書類への出力 set d3 to makeNewCotEditorDoc("左→右で追加された項目" & return & return & aRes) of me set d4 to makeNewCotEditorDoc("左→右で削除された項目" & return & return & bRes) of me on getDiffBetweenLists(aArray as list, bArray as list) set allSet to current application’s NSMutableSet’s setWithArray:aArray allSet’s addObjectsFromArray:bArray –重複する要素のみ抜き出す set duplicateSet to current application’s NSMutableSet’s setWithArray:aArray duplicateSet’s intersectSet:(current application’s NSSet’s setWithArray:bArray) –重複部分を削除する allSet’s minusSet:duplicateSet set resArray to (allSet’s allObjects()) as list set aSet to current application’s NSMutableSet’s setWithArray:aArray set bSet to current application’s NSMutableSet’s setWithArray:resArray aSet’s intersectSet:bSet –積集合 set addRes to aSet’s allObjects() as list set cSet to current application’s NSMutableSet’s setWithArray:bArray cSet’s intersectSet:bSet –積集合 set minusRes to cSet’s allObjects() as list return {addItems:minusRes, minusItems:addRes} end getDiffBetweenLists on cleanUp1DList(aList as list, cleanUpItems as list) set bList to {} repeat with i in aList set j to contents of i if j is not in cleanUpItems then set the end of bList to j end if end repeat return bList end cleanUp1DList –デリミタ文字を指定してリストを文字列化 on listToTextUsingDelim(aList, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set outText to every text item of aList set outText to outText as string set AppleScript’s text item delimiters to curDelim return outText end listToTextUsingDelim –指定テキストでCotEditorの新規書類を作成 on makeNewCotEditorDoc(aCon) tell application "CotEditor" activate set newDoc to make new document tell newDoc set contents to aCon end tell end tell end makeNewCotEditorDoc |
macOS 13.xで、アプリケーション組み込み型のAppleScript実行環境(内蔵Script Menu装備)において、ホームディレクトリ下のAppleScriptライブラリを読み込んで実行することが「できなかった」ものを、「できる」ように改修されたようです。
実際に確認を行ったのは、macOS 13.xとCotEditorの組み合わせにおいてです。macOS 13の早期バージョンにおいてはライブラリ呼び出しが行えなかったものが、macOS 13.6.2においては呼び出せるように変わっています。なお、CotEditor側ではAppleScript実行機能まわりに改修を行なっていないことを確認しています。
CotEditorのAppleScript実行機能の実装はosascriptコマンドを呼び出すというものであり、手間をかけていない割に.scpt形式も.scptd形式も実行できるため、「妥当な実装」といったところでしょう。
自分は、各AppleScriptランタイム環境においてAppleScriptライブラリの読み込みと実行が行えるかをチェックしており、現時点でこれが行えない環境は……
・Automatorおよび書き出したアプレット(古すぎる。廃止予定)
・スクリプトエディタの内蔵コンテクストメニュー(セキュリティ的に無理そう)
・フォルダアクション(セキュリティ的に無理そう)
・Switch Control(パレットごと配布することを考えると、やらないほうが安心?)
・FileMaker Pro(構造が違いすぎて対応が難しい?)
・Hammerspoon(applescriptFromFile)(できてもおかしくないが……)
と認識しています。もしかしたら、Hammerspoonは再確認したら動くかもしれません。
なお、もっと巨大で深刻なバグ(AppleScriptドロップレットにドラッグ&ドロップしたファイルが正しく処理されない問題)はmacOS 10.12から相変わらず放置されています。
これも同じく、8bitコンピュータ時代のクロスアセンブラが出力していたダンプリストを、BASICのPOKE文に展開して出力するという、20〜30年前の仕様のテキスト変換を行うために作ったものです。
CotEditorでオープン中のダンプリストのテキストの変換対象行を選択しておいた状態で実行すると、変換したリストを新規書類に出力します。
AppleScript名:HexDump to BASIC.scpt |
— – Created by: Takaaki Naganoya – Created on: 2023/01/09 — – Copyright © 2023 Piyomaru Software, All Rights Reserved — tell application "CotEditor" tell front document set aaSel to paragraphs of contents of selection end tell end tell set sNum to 100 set allText to "" repeat with i in aaSel set tmpL to "" set bList to words of i set aStr to retOnLineBasicPoke(bList) of me set allText to allText & ((sNum as string) & ": ") & aStr & return set sNum to sNum + 1 end repeat tell application "CotEditor" set newDoc to make new document tell newDoc set contents of it to allText end tell end tell on retOnLineBasicPoke(aList) set addrStr to first item of aList set aList to rest of aList set aaList to items 1 thru 8 of aList set aStr to "POKE #0, &" & addrStr & ", " repeat with i in aaList set j to contents of i set aStr to aStr & "&" & j & ", " end repeat return text 1 thru -3 of aStr end retOnLineBasicPoke |
これ、8bitコンピュータ時代のクロスアセンブラが出力していたIntel Hexaフォーマットのダンプリスト(EPROMライター向けの出力フォーマットらしい)を、BASICのPOKE文に展開して出力するという、20〜30年前の仕様のテキスト変換を行うために作ったものです。
CotEditorでオープン中のIntel Hexaのテキストの変換対象行を選択しておいた状態で実行すると、変換したリストを新規書類に出力します。
汎用性は一切ないのですが、実際にさまざまな本を作る際に、こうした「ちょっとしたツール」を作るのと作らないのとでは生産性が段違いです。
ただ、元データと最終成果物を示すと途中のロジックをプログラム側で考えて出力してくれるといいのに、とは思います。
AppleScript名:Intel Hexa to BASIC.scpt |
— – Created by: Takaaki Naganoya – Created on: 2023/01/09 — – Copyright © 2023 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "CotEditor" tell front document set aaSel to paragraphs of contents of selection end tell end tell set sNum to 100 set allText to "" repeat with i in aaSel set tmpL to "" set j to contents of i set {addrStr, hexList} to procOneLine(j) of me set aStr to retOnLineBasicPoke(addrStr, hexList) of me set allText to allText & ((sNum as string) & " ") & aStr & return set sNum to sNum + 1 end repeat tell application "CotEditor" set newDoc to make new document tell newDoc set contents of it to allText end tell end tell on retOnLineBasicPoke(addrStr, aList) set aStr to "POKE #0, &" & addrStr & ", " repeat with i in aList set j to contents of i set aStr to aStr & "&" & j & ", " end repeat return text 1 thru -3 of aStr end retOnLineBasicPoke on procOneLine(a) set fChar to first character of a if fChar is not equal to ":" then error set byteC to text 2 thru 3 of a set byteNum to retIntFromHexString(byteC) of me set addrStr to text 4 thru 7 of a set hList to {} repeat with i from 10 to (10 + (2 * (byteNum – 1))) by 2 set tmpStr to text i thru (i + 1) of a set the end of hList to tmpStr end repeat return {addrStr, hList} end procOneLine on retIntFromHexString(aHex as string) set {aRes, hexRes} to (current application’s NSScanner’s scannerWithString:aHex)’s scanHexInt:(reference) if aRes = false then return "" –エラーの場合 else return hexRes end if end retIntFromHexString |
Piyomaru Software Booksの69冊目。「CotEditor Scripting Book with AppleScript」を発売しました。PDF 343ページ+サンプルScriptZipアーカイブ で構成されています。
→ 販売ページ
アプリケーションのすべてのScriptingをわかりやすく詳細にまとめた徹底解説シリーズの第5弾。
CotEditorは(起動、動作が)速い、うまい、フリー、と3拍子そろった、Macユーザー定番のテキストエディタです。
macOS専用に作られているため、その分、macOSならではの機能を活かす方向に全振りした作りになっています。
そんなCotEditorはもちろんAppleScriptに対応しており、さまざまな作業の部品としてCotEditorを利用したり、CotEditor自体の機能をAppleScriptで追加することもできます。macOS 12以降に対応。
・スクリプトエディタを起動しよう
スクリプトエディタを起動しよう!
スクリプトエディタのヘルプ
色設定を変えてみよう!
スクリプトを入力してみよう
スクリプトを保存しよう
スクリプトを実行しよう(1/3)
スクリプトを実行しよう(2/3)
セキュリティとプライバシー
プライバシーとセキュリティ(13.x以降)
セキュリティとプライバシー>プライバシー
プライバシーとセキュリティ(macOS 13)
・CotEditorを起動しよう
CotEditorを指定
CotEditor.appを起動
CotEditor.appを終了
CotEditorのAppleScript用語辞書の調べ方
メニュー項目や画面強制操作の調べ方
CotEditorの詳細仕様について
・CotEditor自体の情報を取得しよう
CotEditorの名前を取得
CotEditorのバージョンを取得
CotEditorのプロパティ項目と内容
・オープン中の書類へのアクセス
CotEditorでオープン中の書類へのアクセス
最前面の書類、ウインドウにアクセス
documentの属性情報にアクセス
windowの属性情報にアクセス
ウインドウ関連の操作で「できない」こと
・書類の選択部分へのアクセス
selection=選択中のテキスト
selection自体のプロパティ
selection内容のテキストの取得
selection内容の書き換え
selectionの作成
・書類のスクロールとジャンプ
書類のスクロール①
書類のスクロール②
書類の指定行にジャンプ
書類の乱数行にジャンプ
・ウインドウの操作
ウインドウの属性値へのアクセス
指定ウインドウを最前面に表示
指定ウインドウの表示状態を変更
指定ウインドウをズーム表示
参考:最前面のウインドウをフルスクリーン表示
指定ウインドウのサイズを変更
・CotEditor内蔵コンソールへの文字列出力
コンソールに文字列を出力
・内蔵/OS搭載スクリプトメニューからの操作
2つのScript Menu環境
CotEditor内蔵スクリプトメニュー
macOS搭載標準スクリプトメニュー
各スクリプトメニューの技術仕様
・AppleScriptからCotEditorを操作するパターン
・ファイルのオープン
ファイルを指定して書類をオープン
複数のファイルを指定して書類をオープン
コラム「CotEditorが使用するパス表現」
・ファイルの保存
書類を指定パスに保存
書類を新規作成して本文を設定して指定パスに保存
保存済み書類に変更が加わっていたら保存
・ファイルのクローズ
書類をクローズ(with saving)
書類をクローズ(without saving)
書類をクローズ(saving ask)
新規書類をクローズ
・各種文字操作(選択範囲の操作)
change case
change kana
change roman width
shift right
shift left
move line up
move line down
sort lines
delete duplicate line
comment out
uncomment
smarten quotes
straighten quotes
smarten dashes
normalize unicode
・各種文字操作(document全体の操作)
find(1/2)
find(2/2)
replace
string
・タブ、改行コードの取り扱い
改行コードの変更タブ幅の変更
文字コードの指定
convert
reinterpret
・書式つきテキスト対応機能
CotEditorの書式つきテキスト対応機能
書式つきテキスト機能にAppleScriptからアクセス
・AppleScript非対応機能を呼び出す
AppleScriptで操作可能な範囲
GUI Scripting:メニューなどを強制操作①
GUI Scripting:メニューなどを強制操作②
GUI Scripting:メニューへのアクセス
指定ウインドウを最前面に移動
・プリントアウト
CotEditorからの印刷出力(macOS 13)
AppleScriptによるプリントアウト
GUI Scriptingによるプリントアウト①
GUI Scriptingによるプリントアウト②
GUI Scriptingによるプリントアウト③
GUI Scriptingによるプリントアウト④
GUI Scriptingによるプリントアウト⑤
正規表現
正規表現が使えるAppleScriptコマンド
findコマンド+正規表現(GUI側との対応)
replaceコマンド+正規表現(GUI側との対応)
replace サンプル①
replace サンプル②
replace サンプル③
replace サンプル④
・オープン時に縦/横書きを強制できる書類仕様
xattrコマンドで強制的に縦書き表示
・文字数のカウント
CotEditorの文字数カウント機能
AppleScriptの文字カウント
・内蔵スクリプトメニューの独自仕様
フォルダ階層構造がそのまま反映される
内蔵スクリプトメニューの独自機能
メニュー上の並び順を指定
メニュー上の区切りセパレータ表示指定
キーボードショートカットの指定
Scriptをメニューに出さない(非表示設定)
・CotEditorのAppleScript関連機能のバグ(v4.4.2)
・高度なサンプル集
AppleScriptで操作可能な範囲
最前面のウィンドウをフルスクリーン表示(1/2)
最前面のウィンドウをフルスクリーン表示(2/2)
選択範囲のテキストをhexdump(1/2)
選択範囲のテキストをhexdump(2/2)
選択範囲のカンマ区切りテキストをNumbersへ(1/2)
選択範囲のカンマ区切りテキストをNumbersへ(2/2)
選択範囲のテキストの文字比率グラフを表示(1/8)
選択範囲のテキストの使用文字比率のグラフ表示(2/8)
選択範囲のテキストの使用文字比率のグラフ表示(3/8)
選択範囲のテキストの使用文字比率のグラフ表示(4/8)
選択範囲のテキストの使用文字比率のグラフ表示(5/8)
選択範囲のテキストの使用文字比率のグラフ表示(6/8)
選択範囲のテキストの使用文字比率のグラフ表示(7/8)
選択範囲のテキストの使用文字比率のグラフ表示(8/8)
・便利な他のプログラムや周辺機器
さまざまなAppleScript呼び出しプログラムから操作①(1/2)
さまざまなAppleScript呼び出しプログラムから操作①(2/2)
さまざまなAppleScript呼び出しプログラムから操作②
さまざまなAppleScript呼び出しプログラムから操作③
さまざまなAppleScript呼び出しプログラムから操作④
・CotEditorのAppleScript用語辞書解説
・CotEditorのAppleScript用語の変遷
・CotEditor&AppleScript Q&A
・AppleScript mini Reference
・macOS搭載 AppleScript関連ドキュメント
・AppleScript関連の情報源
・macOSバージョンとAppleScriptの動向
・AppleScript予約語一覧
・サードパーティ製FrameworkやAppleScript Librariesを呼ぶ
・エラーコード表
CotEditor v4.4.1+macOS 13.1 Betaの組みわせで発生しているAppleScriptの問題について書いておきます。
CotEditorの内蔵スクリプトメニューから呼び出すAppleScriptは、実行プログラムがosascriptで、macOS標準搭載のスクリプトメニューと部品は同じですが、挙動や制約条件が異なります。
macOS 13+CotEditorの内蔵スクリプトメニューから呼び出すAppleScriptで、「path to me」を実行したらエラーになる現象に直面しています。
AppleScript名:mepath_without_block.scpt |
set mePath to POSIX path of (path to me) display dialog mePath as string |
ただし、解決策はすぐに見つかって、tellブロックでpath to meを囲ってあげることです。tell current applicationで囲ってあげるのが一番手っ取り早いところ。using terms from scripting additionsも使えそうです。
AppleScript名:mepath.scpt |
tell current application set mePath to POSIX path of (path to me) end tell display dialog mePath as string |
macOS 12.6.1がアップデートして12.6.1になるというわけのわからないバージョン番号の採番ルールが展開されている今日このごろ。
macOS 12の初期において、Shortcuts.appやCotEditor内部のAppleScript実行環境において、script objectで論理分割した中にあるハンドラを呼べない という問題が確認されました。ただし、macOS 12.6.1で気づいたということであって、もう少し前のバージョンでこの変更が加わっていた可能性もあります。
ハンドラ呼び出しの範囲がscript objectを超えられないというわけで、CotEditor PowerPackの作成時に大幅にScriptを書き換える必要があって手間がかかった記憶があります。
AppleScript基礎テクニック集25巻にて「CotEditorのメニューScriptとShortcuts.appでは対策が必要」と書こうとして、念のために実際にmacOS 12.6.1の上でCotEditor v4.3.6で確認したところ、動きました。Shortcuts.appでも同様にscript object内部のハンドラを外部から呼び出せるようになっていました。
# 慌てて、書籍の方を書き換えました
各プログラム側で何かそんなマイナーな問題への対策を行ったような雰囲気はなかったので、OS側の実行モジュール(osascript?)で対策を行ったような雰囲気があります。ただ、Appleがリリースノートを一切出さないので、確認のしようがありません(ものすごく不信感しかないので、リリースノートは出してほしいなー。まさか、詳細なリリースノートを出さないことで、クラッカーへの情報流出を防止できている、とか現状を肯定的に捉えているのだろうか)。
Piyomaru Software Booksの60冊目。GUIアプリケーションを強引に動かす「GUI Scripting」について動作原理から気をつけるべき点、実戦レベルのScriptで注意している点やサンプルなどをまとめた「AppleScript実践的テクニック集(1)GUI Scripting」を発売しました。本文283ページとなっています。
→ 販売ページ
「AppleScript実践的テクニック集」とは、従来の「基礎テクニック集」の枠組みでは収まりきらないテーマを扱う新シリーズです。基礎テクニック集は32ページ前後のコンパクトな構成にするために、いろいろ省略した部分もありましたが、この枠組みに入り切らないテーマを別枠でご紹介することにしたものです。
ページ数の上限をとくに設けず、徹底的に情報を入れる設計です。それでいて、「基礎テクニック集」ゆずりの図や表を多用した構成はそのままです。
使い所さえ間違えなければ強力な武器になるGUI Scriptingについて、動作原理からノウハウ、注意すべきポイントや実戦レベルのScriptで気をつけていること、さまざまな「ありがちな処理」のサンプルなどを紹介する1冊です。
AS用語辞書にすべての機能は掲載されていません①
AS用語辞書にすべての機能は掲載されていません②
AppleScript非対応機能を呼ぶGUI Scripting
GUI Scriptingとは?
GUI ScriptingはSystem Eventsごしに操作
操作対象のアプリケーション①
操作対象のアプリケーション②
KeynoteでASから利用できない機能を呼ぶ
GUIアプリケーションの挙動確認が欠かせません
メニュー項目操作の実例
実行結果のリストアップ①
実行結果のリストアップ②
デフォルト状態だとGUI Scriptingは無効
AppleScript実行アプリケーションを登録
設定するとGUI Scriptingが有効に
スクリプトメニューも登録必須
資料:macOS上のAppleScript実行環境①
資料:macOS上のAppleScript実行環境②
メニュー項目:メニューを頂点としたツリー
ウィンドウ上のオブジェクト:ウィンドウが基準
簡単なGUI部品の求め方
GUI Scriptingの有効チェック
属性値の取得(properties)
属性値の取得(AX-attributes)
GUI部品のクリック
指定座標のクリック
参考資料:GUI Scriptingの座標系
ポップアップメニューの項目選択
キー入力操作
項目選択
コンテクストメニューの表示
スクロール操作
ファイル保存/書き出し
自分で発生させたモーダルなダイアログのクリック
ドラッグ&ドロップ操作
日本語IMの文字入力モード取得/設定
マウスカーソルを移動させる必要性
マウスカーソルの強制移動とクリック
指定フォルダ以下のPagesなどをPDF出力して連結
実際のメインScript部分
generatePDFLibの当該箇所
本プログラムが環境の影響を受けた点
参考資料:デスクトップの表示/非表示切り替え
Xcodeに入っているGUI部品探索ツール
Accessibility Inspectorの画面構成①
Accessibility Inspectorの画面構成②
プロセス一覧から対象を選択してInspection
指定プロセスのGUI部品の追跡中の画面表示
GUI部品の追跡ポーズ中の画面表示
OSアップデートごとにGUI構成は変わる
GUI Scripting処理部分だけをサブルーチンに分離
GUI Scripting処理部分をライブラリに分離
OSアップデートの影響を受けにくい構造に
GUI Scriptingの信頼性は?
一般的な信頼性の計測方法
経験に基づく傾向と対策
GUI Scriptingで直面した問題とその解決策
指定した処理の終了前に次の処理が行われる
同じ名前のプロセスが存在していると名称衝突①
同じ名前のプロセスが存在していると名称衝突②
指定のアプリケーションの全メニュータイトルを取得
選択中のテキストを取得
選択中のテキストを書き換え
Safariの最前面のウィンドウへの参照を得る
GUI部品への参照から所属するアプリケーション名を取得
Dockに登録されているアイコンの情報を取得
Keynoteで選択中のテキストを縦書きに
CotEditorで最前面のウィンドウを縦書きに
click【クリック】コマンド
key code【キーコード】コマンド
keystroke【キーストローク】コマンド
perform【パフォーム】コマンド
select【セレクト】コマンド
application【アプリケーション】クラス
action【アクション】クラス
application process【アプリケーションプロセス】クラス
attribute【アトリビュート】クラス
browser【ブラウザ】クラス
busy indicator【ビジーインディケータ】クラス
button【ボタン】クラス
checkbox【チェックボックス】クラス
color well【カラーウェル】クラス
column【カラム】クラス
combo box【コンボボックス】クラス
desk accessory process【デスクアクセサリプロセス】クラス
drawer【ドロワー】クラス
group【グループ】クラス
grow area【グローエリア】クラス
image【イメージ】クラス
incrementor【インクリメンタ】クラス
list【リスト】クラス
menu【メニュー】クラス
menu bar【メニューバー】クラス
menu bar item【メニューバーアイテム】クラス
menu button 【メニューボタン】クラス
menu item 【メニューアイテム】クラス
outline 【アウトライン】クラス
pop over 【ポップオーバー】クラス
pop up button 【ポップアップボタン】クラス
process 【プロセス】クラス
progress indicator 【プログレスインジケータ】クラス
radio button 【ラジオボタン】クラス
radio group【ラジオグループ】クラス
relevance indicator【レレベンスインジケータ】クラス
row【ロー】クラス
scroll area【スクロールエリア】クラス
scroll bar 【スクロールバー】クラス
sheet 【シート】クラス
slider【スライダ】クラス
splitter【スプリッタ】クラス
splitter group【スプリッタグループ】クラス
static text【スタティックテキスト】クラス
tab group【タブグループ】クラス
table【テーブル】クラス
text area【テキストエリア】クラス
text field【テキストフィールド】クラス
toolbar【ツールバー】クラス
UI element【ユーアイエレメント】クラス
value indicator【バリューインディケータ】クラス
window【ウインドウ】クラス
macOSバージョンとAppleScriptの動向
macOSとAppleScriptの要素技術史
各macOSごとのAppleScript解説
macOS内AppleScript補助ツールの歴史
System EventsのAppleScript用語辞書変更点
AppleScript 各ランタイム環境情報
AppleScript予約語一覧
AppleScriptのエラーコード
あとがき
奥付
オープンソース開発されているフリーのテキストエディタ「CotEditor」v4.1.2において、AppleScript系の機能が追加されています。
・DocumentオブジェクトのhasBOM属性
has BOM (boolean, r/o) : Is the file encoding of the document has BOM (byte order mark)?
・convertコマンドのBOMオプション
convert v : Convert the document text to new encoding. convert document : The document to convert encoding. [lossy boolean] : Allows lossy conversion? [BOM boolean] : Has the new encoding a BOM (byte order mark)? to text : The new encoding, either in localized encoding name or an IANA charset name. → boolean : Did the convertion succeed?
・新設のjumpコマンド
jump v : Move the caret to the specified location. At least, either one of a parameter is required. jump document : The document to move. to line integer : The number of the line to go. If a negative value is provided, the line is counted from the end of the document. [column integer] : The location in the line to jump. If a negative value is provided, the column is counted from the end of the line.
こんなサンプル書類があったとして、
AppleScriptのdocumentオブジェクトの文字データを取得してダンプしてみても、
--No BOM {"E3", "81", "B4", "E3", "82", "88", "E3", "81", "BE", "E3", "82", "8B", "E3", "82", "BD", "E3", "83", "95", "E3", "83", "88", "E3", "82", "A6", "E3", "82", "A7", "E3", "82", "A2", "0A", "61", "62", "63", "64", "E9", "AB", "98", "E5", "B3", "B6", "E5", "B1", "8B", "65", "66", "67", "68", "69", "0A", "0A"} --with BOM {"E3", "81", "B4", "E3", "82", "88", "E3", "81", "BE", "E3", "82", "8B", "E3", "82", "BD", "E3", "83", "95", "E3", "83", "88", "E3", "82", "A6", "E3", "82", "A7", "E3", "82", "A2", "0A", "61", "62", "63", "64", "E9", "AB", "98", "E5", "B3", "B6", "E5", "B1", "8B", "65", "66", "67", "68", "69", "0A", "0A"}
この状態ではhasBOM属性値で差があっても、内部データでは差が出ません。これをファイルに書き込んで、ファイル内容についてチェックを行うと、
--No BOM 0000000 81e3 e3b4 8882 81e3 e3be 8b82 82e3 e3bd 0000010 9583 83e3 e388 a682 82e3 e3a7 a282 610a 0000020 6362 e964 98ab b3e5 e5b6 8bb1 6665 6867 0000030 0a69 000a 0000033 --With BOM 0000000 bbef e3bf b481 82e3 e388 be81 82e3 e38b 0000010 bd82 83e3 e395 8883 82e3 e3a6 a782 82e3 0000020 0aa2 6261 6463 abe9 e598 b6b3 b1e5 658b 0000030 6766 6968 0a0a 0000036
のように、差を検出できます。
CotEditorでオープン中の最前面の書類の選択範囲のテキストを行ごとにチェックし、行頭に存在する数字を、それらのうちの最小値を検出しつつ、指定のステップ数でリナンバー(番号振り直し)を行うAppleScriptです。
さまざまな項目の整理のために、テキストの先頭に仮想的なノンブル(ページ番号的なもの、ソート順を指定するための番号)を振っています。この番号ではじまるテキストをもとにFinder上でフォルダ整理をしており、項目の前後関係を入れ替えると…前後関係を明示するために、番号を振り直す必要が出てくるわけです。
# Numbers上やExcel上で行うと、余計な書体スタイルなどが入ってきて邪魔なので、テキストエディタ上で行うことが多いです
その番号の振り直しを行うAppleScriptです。macOS 12.2beta+CotEditor v4.0.9で動作確認を行っています。
▲選択範囲内の行頭の番号を振り直す。ちなみに、表示例はボツになった本の企画
本来は「行頭にある数字」を指示する必要があるものの、まだうまく機能していません。桁数でなんとなく判別しているだけです。
▲フォント作者の方々の合意を得られなさそうで流れた企画「同人フォントソムリエ」
AppleScript名:選択範囲の行頭にある数字をリナンバーする v1.scptd |
— – Created by: Takaaki Naganoya – Created on: 2022/01/02 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions property NSMutableArray : a reference to current application’s NSMutableArray property myNumStep : 1000 tell application "CotEditor" tell front document set aSel to contents of selection set aSelList to paragraphs of aSel end tell end tell –範囲指定がない場合 if length of aSelList = 0 then display dialog "Error: No Selection" buttons {"OK"} default button 1 with icon 2 return end if –過大な範囲指定チェック if length of aSelList > 1000 then set bRes to button returned of (display dialog "選択範囲が1000行を超えています。処理に時間がかかることが予想されますが、実行しますか?") end if –行頭の数字部分のみ取得して、数字の最小値を取得する set topNumList to getNumbersAtLineBegennings(aSelList) of me set minNum to calcIntMinAsStr(topNumList) of me –行頭部分の数字部分のみリナンバー set bRes to renumberNumsAtLineBegennings(aSelList, minNum as integer, myNumStep) of me –1D Arrayを改行コードをデリミタに指定しつつテキスト化 set outStr to retDelimedText(bRes, return) of me tell application "CotEditor" tell front document set contents of selection to outStr end tell end tell –行頭に入っている数字の文字のみリナンバー –実際には行頭判定はまだ行えていない。行頭の番号と文の途中に出てくる数字の区別は「桁数」でのみ行っている on renumberNumsAtLineBegennings(aSelList as list, firstNum as string, stepNum as number) set aDigit to length of firstNum –桁数 copy firstNum to aCount set aRes to {} repeat with i in aSelList set j to (contents of i) as string set nRes to (getNumberCharsOnlyAtBegening(j) of me) as string if nRes is not equal to "" then –InputとOutputが違った set n1Res to removeNumCharsOnly(j, aDigit) of me set tmpNumStr to zeroPadding(aCount, aDigit) of me set n1Res to tmpNumStr & n1Res set aCount to aCount + stepNum set the end of aRes to n1Res else set the end of aRes to j end if end repeat return aRes end renumberNumsAtLineBegennings –1D Listの最小値を文字列で返す on calcIntMinAsStr(aList as list) set nArray to (NSMutableArray’s arrayWithArray:aList) set maxRes to (nArray’s valueForKeyPath:"@min.self")’s intValue() return maxRes as string end calcIntMinAsStr –行頭に入っている数字の文字のみ抽出 on getNumbersAtLineBegennings(aSelList as list) set aRes to {} repeat with i in aSelList set j to contents of i set nRes to getNumberCharsOnlyAtBegening(j) of me if nRes is not equal to "" then set the end of aRes to nRes end if end repeat return aRes end getNumbersAtLineBegennings –数字のみ返す on getNumberCharsOnlyAtBegening(aStr as string) set anNSString to current application’s NSString’s stringWithString:aStr set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9]{4,}" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()} return anNSString as text end getNumberCharsOnlyAtBegening –数字のみ削除して返す on removeNumCharsOnly(aStr as string, aDigit) set anNSString to current application’s NSString’s stringWithString:aStr set anNSString to anNSString’s stringByReplacingOccurrencesOfString:("[0-9]{" & (aDigit as string) & ",}") withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()} return anNSString as text end removeNumCharsOnly –指定桁数で指定の数にゼロパディングして文字列を返す on zeroPadding(aNum as number, aDigit as number) 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 zeroPadding –1D Listを指定デリミタをはさみつつテキストに on retDelimedText(aList as list, aDelim as string) 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 retDelimedText |
CotEditorでオープン中の最前面の書類の内容をすべて選択してコマンド(半角→全角 文字変換)を実行するAppleScriptです。
データ処理内容の確認のためにCotEditor上で処理したときに「あれ? 書類の内容を全選択する処理って書いたことなかったわ〜」と気づいて、慌てて書きました。
AppleScript名:最前面のドキュメント内を全選択して全角変換.scpt |
tell application "CotEditor" tell front document set tLen to length set aRange to {0, tLen} set range of selection to aRange change roman width selection to full end tell end tell |
macOS用テキストエディタ「CotEditor」の機能強化AppleScript集「Script Pack v3」の配布を開始しました。
→ 配布ページ
Script Packは従来バージョン同様に、機能強化ユーティリティScript集の「PowerPack」および、AppleScriptによる基礎的なCotEditorの操作を解説した「Basic Pack」から構成されています。macOS 10.15.xおよび11.x+CotEditor v4.xとの組み合わせで利用することを想定しています。M1 Mac上でも動作確認ずみです。
PowerPack v3では、CotEditor上で編集中のテキストの文字種別を集計してグラフ表示させたり、編集中のテキストで使われている単語をもとにタグクラウド表示を行うなど、従来では把握しにくかったテキストの傾向をビジュアル表示する機能を追加しています。
外部アプリケーションを使わずにCSVデータのプレビュー(100行までの制限あり)、Markdownテキストのプレビューを行えるなど、CotEditorの動作速度を損うことなく大幅な機能追加を行なっています。
電子書籍の新刊を出しました。「機能強化AppleScript集 CotEditor用 PowerPack 取扱説明書」ページ数:191ページ、フォーマット:PDF+Zipアーカイブ(PowerPack、BasicPack)となっています。
→ 販売ページ
→ お試し版書籍ダウンロード
「CotEditor」は、Github上のオープンソース・プロジェクトで公開されているmacOS用の高機能テキストエディタです。本書は、そのCotEditorに便利で強力な機能を追加できるAppleScript集「PowerPack v3」の取扱説明書です。
本書にはPowerPack v3(ソース編集可能版)+Basic Packが含まれています。現在準備中の一般配布版のPowerPack v3は内容が見られません。ただ実行するだけです。
新たにリリースしたPowerPackバージョン3では、グラフ表示やタグクラウド表示などの「ド派手な機能」を追加。Markdown書類のプレビューやCSVデータの表プレビュー、タブ区切りテキストによるKeynote書類の生成、ミュージック.appのトラックへの歌詞データの書き込みなど、AppleScriptによる高度な処理を手軽にご堪能いただけます。
CotEditorの強化用AppleScript集、PowerPackを近日中にv3.0にアップデートします。また、同時にこのPowerPackの使い方を詳細に説明したドキュメントをBooth上で電子ブックとして販売します。
今回の目玉は、グラフ表示。
AppleScriptによって、CotEditorで編集中の最前面のドキュメントの文字種別を分析して、アニメーションしつつグラフ表示します。文章書きがとっても気にする、漢字、ひらがな、カタカナなどの文字種別の使用比率をグラフ化。
AppleScriptでワードクラウド表示。AppleScriptで記述した世界最小(自称)の簡易日本語形態素解析プログラム「easyJParse」を組み込んで、簡易的にワードクラウドを組み立てて表示します。文章内容の傾向を客観的に把握するための表示です。
AppleScriptだけでMarkdownのプレビュー表示を行います。
さらに、AppleScriptでCSVのプレビュー表示も。小規模なデータならその場でダイアログ上でプレビュー表示を、大きなデータはNumbersに渡してそちらで表示させるという寸法です。
CotEditorでオープン中の複数のウィンドウから、各ウィンドウ(書類)の選択範囲を取得し、各ウィンドウの画面上の位置情報をもとに、その順番(Y座標、X座標)にテキストを組み合わせて新規書類を作成するAppleScriptです。
▲DEMO
▲Live Coding
当初、ウィンドウの重ね合わせ順(windowのindex)も考慮していたのですが、実際にためしてみたところ、重ね合わせ順を使うのは無駄だったので、機能を外しました。
AppleScript名:CotEditorの各Windowで選択しておいた内容を重ね合わせ順と座標でソートして結合.scpt |
— – Created by: Takaaki Naganoya – Created on: 2021/02/10 — – Copyright © 2021 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" use scripting additions use framework "Foundation" set wList to {} tell application "CotEditor" set wCount to count (every window whose visible is true) if wCount < 2 then return repeat with i from 1 to wCount tell window i set tmpBounds to bounds set tmpProp to properties end tell set tmpDoc to document of tmpProp tell tmpDoc set aCon to contents of selection end tell set tmpX to item 1 of tmpBounds set tmpY to item 2 of tmpBounds set tmpRec to {winIndex:i, winX:tmpX, winY:tmpY, selText:aCon} set the end of wList to tmpRec end repeat end tell –座標値をもとにソートして選択テキストを返す set sWList to sortRecListByLabel(wList, {"winY", "winX"}, {true, true}) of me set anArray to current application’s NSArray’s arrayWithArray:sWList set vList to (anArray’s valueForKey:"selText") as list set jointStr to retArrowText(vList, return) of me –CotEditor上で指定テキストでドキュメントを新規作成 makeNewCotEditorDoc(jointStr) 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 sortRecListByLabel(aRecList as list, aLabelStr as list, ascendF as list) set aArray to current application’s NSArray’s arrayWithArray:aRecList set aCount to length of aLabelStr set sortDescArray to current application’s NSMutableArray’s new() repeat with i from 1 to aCount set aLabel to (item i of aLabelStr) set aKey to (item i of ascendF) set sortDesc to (current application’s NSSortDescriptor’s alloc()’s initWithKey:aLabel ascending:aKey) (sortDescArray’s addObject:sortDesc) end repeat return (aArray’s sortedArrayUsingDescriptors:sortDescArray) as list end sortRecListByLabel –指定テキストでCotEditorの新規書類を作成 on makeNewCotEditorDoc(aCon) tell application "CotEditor" activate set newDoc to make new document tell newDoc set contents to aCon end tell end tell end makeNewCotEditorDoc |
CotEditor v3.9.7(macOS 10.1510.13以降対応)でAppleScript用語辞書にコマンドが追加されていました。
document中のselectionに対して処理を行うもので、英語のダブルクォート/シングルクォートをワープロ的なクォート開始文字とクォート終了文字に置き換えます。
AppleScript名:smarten quotes |
tell application "CotEditor" tell front document smarten quotes selection end tell end tell |
AppleScript名:straighten quotes |
tell application "CotEditor" tell front document straighten quotes selection end tell end tell |