Archive for the 'Script Editor/AppleScript Editor' Category

2016/09/27 指定のAppleScriptを実行専用で保存

指定のAppleScriptをスクリプトエディタでオープンして、実行専用で保存するAppleScriptです。つまり、AppleScriptでスクリプトエディタをコントロールしてAppleScript書類を操作します。

この手のAppleScriptは、Mac OS X 10.4の時代ぐらいから可能になってきた(スクリプトエディタがScriptから操作可能になった)わけですが、当初は不安定でとても大変でした。そうしたScriptを書くためにはScript Debuggerを併用する必要がありました。ただ、いまはまったくそういう心配はありません。いちおう念のために、スクリプトエディタを「名前」ではなく「Bundle ID」で指定しておくぐらいのケアをしています。

冒頭のchoose fileコマンドのオプション指定およびtellブロックでスクリプトエディタをBundle IDで指定している箇所は、Script Assistantで調査して自動記入したものです。こういう些細な調べものはScript Assistantまかせにしています。

実際には、指定フォルダ以下のAppleScript書類をすべてSpotlightでリストアップし、本ルーチンを呼び出して実行専用で保存し直すような処理のために用意しました。

AppleScript名:指定のAppleScriptを実行専用で保存
– Created 2016-09-26 by Takaaki Naganoya
– 2016 Piyomaru Software
–http://piyocast.com/as/archives/4234
set aFile to choose file of type {“com.apple.applescript.script”} –only applescript
set aRes to saveAppleScriptAsRunOnly(aFile) of me

on saveAppleScriptAsRunOnly(aFile)
  tell application id “com.apple.scripteditor2″
    try
      open aFile
      
check syntax
      
save front document as “script” in aFile with run only
      
close front document without saving
      
return true
    on error
      return false
    end try
  end tell
end saveAppleScriptAsRunOnly

★Click Here to Open This Script 

2014/10/28 Script Editor 2.7で新しいdocumentの属性値「event log」にアクセスする

OS X 10.10, Yosemiteのスクリプトエディタ(旧称:AppleScriptエディタ)バージョン2.7のAppleScript用語辞書で、唯一拡張されたdocumentオブジェクトの属性値「event log」にアクセスするAppleScriptです。

実行すると、

scr1.png

オープン中のドキュメントの名称一覧を表示(用語辞書をのぞく)するので、どれかを選択すると、イベントログの内容を表示します。

この、event logが何に該当するかといえば・・・

log1.png

log2.png

log3.png

log4.png

「返された値」の内容がそのまま(プレーンテキストになって)入ってきます。使い道はいまひとつ分かりませんが、、、

AppleScript名:Script Editor 2.7で新しいdocumentの属性値「event log」にアクセスする
tell application “Script Editor”
  –AppleScript用語辞書のウィンドウを除外して、オープン中の書類名をすべて取得
  
set dList to name of every document whose path does not end with “.sdef”
  
  
set dRes to choose from list dList
  
if dRes = false then return
  
set ddRes to first item of dRes
  
  
tell document ddRes
    set aLog to event log –指定ドキュメントウィンドウ中の「返された値」に表示された内容がプレーンテキストで入る
  end tell
end tell

aLog

–>
(*
“tell application \”Script Editor\”
  get properties of document \”ASDictionary\”
    –> {modified:false, path:\”/private/var/folders/h4/jfhlwst88xl9z0001s7k9vk00000gr/T/ASDictionary.sdef\”, class:document, name:\”ASDictionary\”}
end tell
結果:
{modified:false, path:\”/private/var/folders/h4/jfhlwst88xl9z0001s7k9vk00000gr/T/ASDictionary.sdef\”, class:document, name:\”ASDictionary\”}

*)

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2014/10/23 複数のOSA言語がデフォルトでインストールされたはじめてのシステム

OS X 10.10ははじめて複数のOSA言語がデフォルトでインストールされてリリースされたMac OSとなりました。

過去に、English Dialect、French Dialect、Japanese DialectといったAppleScriptの「方言」が存在していた時期は(Classic Mac OS 8.5まで)ありましたが、複数のOSA言語がデフォルトで提供されたのははじめてです。

OSA言語自体は、昔からサードパーティ製のさまざまなものが存在しており、その中でも最も有名かつ長命だったのはUserland FrontierやLate Night SoftwareのJavaScript OSAでしょう。

今回、OS X 10.10ではApple純正のJavaScript OSAが標準で添付されており(Script EditorのOSA言語ポップアップから選択可能)、一般のユーザーがOSA言語を自由に選択可能な状態となったのははじめてのことです。

osapopup1.png

osa1.png

osa2.png

osa3.png

AppleScriptでScript Editorに対してOSA言語の一覧を取得し、各種OSA言語のプロパティを取得してみましょう。

スクリプト名:OSA言語のプロパティを取得
tell application “Script Editor”
  set langList to every language
  
–> {language “AppleScript Debugger 5″, language “AppleScript”, language “JavaScript”}
  
  
repeat with i in langList
    tell i
      properties
      
      
–> {name:”AppleScript Debugger 5″, supports compiling:true, description:”AppleScript Debugger 5 Scripting System”, class:language, supports recording:true, id:”asDB”}
      
      
–> {name:”AppleScript”, supports compiling:true, description:”AppleScript。”, class:language, supports recording:true, id:”ascr”}
      
      
–> {name:”JavaScript”, supports compiling:true, description:”JavaScript”, class:language, supports recording:false, id:”jscr”}
      
    end tell
  end repeat
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

▲language “AppleScript”のdescriptionが”AppleScript。”になっているのはバグ(指摘済みだが直るのやら ーー;)

AppleScriptはrecordingをサポートしているが、JavaScript OSAはrecordingをサポートしていないよ、という情報が取得できました(ほとんどrecordingは活用されていないし、Appleもアプリケーションにrecording対応は求めていないのでいいんじゃないかと)。

JavaScript OSAはAppleScriptとほぼ同じことができます。

アプレットの記述ができ、実行専用で保存するとソースが見られなくなります。β版のときには大丈夫だったのですが、リリース版の10.10ではJavaScriptで記述したアプレットは、「実行専用」で保存してもScript Editorで中身が見えますね、、、(ーー;;

Script Menuから呼び出すことができ、Terminalからosascriptコマンドで呼び出すこともできます。

GUI Scriptingの機能も使えるし、Cocoaの機能も使えます。

ただ、AppleScript Librariesの機能はJavaScript OSA(v1.0)にはないので、そこはこれからの(OS X 10.11以降での)対応になる見込みです。また、Xcode上でASOCのようなGUIベースのアプリを作ることは(現時点では)できません。

64ビットに対応していないアプリケーション内のScriptメニューからは、おそらくJavaScript OSAは呼び出せないものとおもわれます。

標準添付のApple純正JavaScript OSAに対する印象については、内部計算(配列変数を作らせて値を埋めるとか)についてはものすごく速いものの、アプリへのコントロールを行わせるとAppleScriptの10倍ぐらい遅い、という感じです(簡単な属性へのアクセスでそのぐらい差がつく)。

得意不得意が明確すぎるというか、バージョン1.0なんてそんなもんだろう、というところでしょうか。

ひとついえるのは、OS Xがすでに安定期に入っているため、Classic Mac OSからMac OS Xへの移行期のような苦しみは味あわずに済みそう、というところでしょうか。

ただ、日本語環境でろくにテストをしていないのはAppleのお家芸なので、JavaScript OSAについては何が出てくるやら、、、、

2014/10/23 OS X 10.10リリースノート(正式公開版)

報告したつまらないバグが修正されないままリリースされたOS X 10.10。いまひとつテンションが上がらないところですが、リリースノートの内容を確認していきましょう(2回目ですが、変更点もあるので再確認)。

# 地味に、iWorkのAppleScript対応機能が向上したことの方が注目度大

■AppleScriptの機能追加

・プログレスバーの表示

ビルトインのプログレス表示機能が追加されました。現在、どのぐらいの進捗状況なのかをバー表示できます。

progress.png

本機能は3段階で実装されています。

(1)Script Editorの実行中表示(回転式インジケータ)
(2)メニューバーに表示される実行中表示(回転式インジケータ)
(3)プログレスバー表示

(1)および(2)については、Script Editor上で実行したり、Script Menuから呼び出して実行すると表示されるものです。

(3)が目玉。ただし、プログレスバーを表示させるためにはいくつか条件が必要です。

(条件1)アプレットとして保存、実行していること

Script Editor上で実行している状態ではプログレスバーは表示されません(けっこー重要)

(条件2)各種プロパティを定義してあること

progress total steps(プログレスバー表示時のステップ数)
progress completed steps(どのステップで終了か)
progress description(プログレスバー表示中の表示タイトル)
progress additional descripion(プログレスバー表示中のサブタイトル)

なお、progress total steps、progress completed stepsが「-1」に設定してあるとプログレスバー表示は行われません。

スクリプト名:プログレス表示テスト_exe
set progress total steps to 10
set progress completed steps to 10
set progress description to “Progress….”
set progress additional description to “This work is now in progress..”

repeat with i from 1 to 10
  display dialog “Now” buttons {“OK”} default button 1 giving up after 1
  
set progress completed steps to i
end repeat

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

・複数タイプ指定の型変更(cast)

通常、「a as integer」などのように、asで明示的な型変換が行えますが、このさいの型をリストで列挙できるようになりました。

a as {integer, string}

で、最初にヒットしたものが有効になるようです。

“3″ as {integer, string}だとintegerの3が返ってきます。
“A” as {integer, string}だとstringの「A」が返ってきます。
false as {integer,string}のようにマッチするものがない場合にはエラーを発生させます。

・ハンドラの型指定パラメータ

on changeStr(a as string) のように、ハンドラに型指定が書けるようになりました。dateを渡す必要があるのにdateでないものが来た場合に備えて型テストをしたりしていましたが、そういう手間が減りました。積極的に使っていきたいところです。

・無意味句を用いたハンドラ記述時のデフォルト値指定

AppleScriptでハンドラを「英文っぽく」書くために用意されている意味のない予約語(意味なし予約語)でハンドラ記述した場合に、省略されたパラメータがあったときに初期値を宣言しておけるというものです。

すぐに思いつく使い方は、AppleScriptの標準命令を乗っ取って別の使い方をするような場合でしょうか。

スクリプト名:型およびデフォルト値指定のハンドラ宣言
–パラメータを指定したり、しなかったりしてもハンドラ側でデフォルト値を設定していれば大丈夫
display dialog “こんにちは”
display dialog “こんにちは” with icon 1
display dialog “こんにちは” with icon 1 buttons {“OK”}
display dialog “こんにちは” with icon 1 buttons {“OK”} default button 1
display dialog “こんにちは” with icon 1 buttons {“OK”} default button 1 giving up after 10

–標準命令のdisplay dialogの実行を横取りする
on display dialog aString as string : “” with icon i as integer : 0 default button aButton as integer : 1 buttons aList as list : {} giving up after aSec as integer : 10
  
  
say aString using “Otoya” speaking rate 200
  
end display dialog

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

AppleScriptの標準命令の多くはこうして乗っ取って、別の動きをさせられるものの・・・プログラム中でパラメータを指定していたりしなかったりするので、たとえば動作確認のためdisplay dialogでエラーメッセージを表示させていたものを、運用時にはすべてログファイルにタイムスタンプとメッセージ内容を書き出すように変更したい、といった場合に・・・なかなか難しいものがありました。すべて同じパラメータ数が指定されているかチェックし直す必要があったり。1か所でもオプション指定数が異なると、乗っ取った側のハンドラでエラーが出てしまったり。

この新機能を使うと、AppleScript標準命令の乗っ取りも簡単かつ確実に行えるので・・・とても使い手があります。とくに、標準命令にバグを作られた(「is in」演算子でバグを作られたMac OS X 10.3のよーに)場合でも回避できそうな感じがするのでとってもいいです(回避できるケースばかりではないので、注意が必要)。

あと、AppleがObjective-Cで実装したおっそーーい命令(なぜかAppleScriptで書き直した方が数倍速くなる)を高速なルーチンに置き換えて処理するとか。

・AppleScript/Objective-Cサポートの強化

10.6でXcode上でのみ記述、10.7からScript Editor上でも記述できるようになったものの、明確に通常のAppleScriptと区別されてきたAppleScript/Objective-C(Cocoa-AppleScript。以下、ASOC)。

Cocoaの機能をAppleScript上で利用できるようにする機能です。

10.10では、より通常のAppleScriptとの垣根が低くなりました。Cocoa-AppleScript AppletでなくてもASOCの機能が使えるようになりました。Script Editor上で実行するAppleScriptでも、直接ASOCの機能を呼び出せます(下記リストも、Script LinkをクリックしてScript Editorに転送してコンパイル(構文確認)してすぐに実行できます)。

ただし、ASOCがらみの機能は別スレッドで実行されるとのことで、スレッド上で実行するとエラーになるものもあるので注意しろ、と参考にならなさそうな注釈が書かれています。

実際にASOC機能入りのAppleScriptをいろいろいじくってみると、ハンドラの中身は現行の(Objective-Cライクな記法が許容されている)ASOCなんですが、

 例:readPlistAt:thePath

ハンドラの外はObjective-Cライクな記法が許容されない、OS X 10.8の頃のASOCの記法が必要とされるというわけで、

 例:readPlistAt_(thePath)

ちょっと中途半場な印象を受けます。明示的にrunハンドラの中に記述しても状況は変わりません。とてもおかしな仕様です。
→ Update : その後、回避策が発見されました。my readPlistAt:thePath と書くと、構文確認時のエラーを回避できます。

スクリプト名:ASOCで指定PDFのページ数をかぞえる
use framework “Foundation”
use framework “AppKit”
use framework “QuartzCore”

use scripting additions
use AppleScript version “2.4″ –10.9上では実行できない。10.10以降

property nsurl : class “NSURL”
property PDFDocument : class “PDFDocument”

set aFile to choose file of type {“com.adobe.pdf”}
set aRes to pdfPageCount_(aFile as string)

–指定PDFのページ数をかぞえる(10.9対応。普通にPDFpageから取得)
–パラメータ:PDFファイルのHFS path(string)
–返り値:PDFファイルのページ数(整数値)
on pdfPageCount:aFile
  
  
tell application “Finder”
    set aFileURL to (URL of file aFile)
  end tell
  
  
set aFileURL to aFileURL as Unicode text
  
set theURL to nsurl’s URLWithString:aFileURL
  
  
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:theURL
  
set aRes to aPDFdoc’s pageCount()
  
  
return aRes as integer
  
end pdfPageCount:

–指定PDFのページ数をかぞえる(10.9対応。普通にPDFpageから取得)
–パラメータ:PDFファイルのPOSIX path(quoteされていない)
–返り値:PDFファイルのページ数(整数値)
on pdfCountPOSIXpath:aPDFPosixPath
  
  
set aFile to (aPDFPosixPath as POSIX file) –POSIX pathからPOSIX fileにcast
  
  
tell application “Finder”
    set aFileURL to (URL of (aFile as alias)) –aliasからでないとURLが取得できない
  end tell
  
  
set aFileURL to aFileURL as Unicode text
  
set theURL to nsurl’s URLWithString:aFileURL
  
  
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:theURL
  
set aRes to aPDFdoc’s pageCount()
  
  
return aRes as integer
  
end pdfCountPOSIXpath:

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

使ってみると・・・あれ? これってすごい便利かも、、、通常のAppleScriptでCocoaの機能が使えると、アプレット上でないと実行できない(10.9まで)よりもはるかに便利。

また、AppleScript Libraries用のScriptを書く場合に、 “AppleScript/Objective-C Library”チェックボックスにチェックを入れる必要がありましたが、10.10からはその必要がなくなりました(チェックボックス自体もなくなった)。

もしも、AppleScript Librariesを10.9用にも利用する(提供する)場合には、バンドル中のInfo.plist中に

OSAAppleScriptObjCEnabled = YES

のエントリを記述する必要があるとのことです。

廃止された機能

恒例の「xxxx.scripting」というOS標準搭載のGUIなしアプリケーションが廃止になった、ということは(10.10では)ないのですが、SpeechRecognitionServerがなくなりました。

speechfeedback.gif
▲AppleScriptから呼び出したり、(英語のみの)音声認識インタフェースからAppleScriptを実行したりできた(終始、実用性はいまひとつだった)

英語の音声認識コマンドが廃止になったということで、びみょーーに使い道がなかったし、英語にしか対応してこなかったので、いまひとつだったため・・・とくに、廃止されてもダメージはありません。

AppleScriptのCGI系の予約語がいまだに廃止されないのが不思議ですが、どこかにCGI機能を活用しているヘビーユーザーでもいるのでしょうか?

2014/10/23 編集中のScript BundleあるいはApplet全体の行数をかぞえる

Script Editor(10.9まではAppleScriptエディタ。以下、エディタと略)で編集中のアプレットやバンドル形式のAppleScriptの、バンドル内に入れてあるサブScriptすべての行数をカウントするAppleScriptです。

バンドル形式のAppleScript、あるいはアプレットに入れてあるサブScript(共有機能を突っ込んであったり、個別に動作確認する必要があるモジュールなど)すべての行数をカウントしようとすると、わりとやっかいで面倒です。

scripts.png

そこで、専用のScriptを組んでカウントすることにしました。

実行すると、エディタ上でオープンしているAppleScriptの一覧が出るので、

asdiaog.png

任意のScript(バンドルScript、アプレット)を選択すると、バンドル内のすべてのScriptの名称と行数、さらに総合計の行数をTAB区切りテキストに(エディタの「結果」欄に)出力します。

エディタで直接バンドル内のAppleScriptを(AppleScript側から指令して)オープンさせるとエラーになるので、shellのosadecompileコマンドを使ってAppleScriptを(中間言語形式から)テキストに逆変換し、行数をカウントしています。

行数のカウントまでshell側で「wc -l」で行わせた方が速そうでしたが、AppleScript側でテキストを取得できれば、改行のみの行を除外するといった処理もできるので、今後の発展性を考慮してshell側でカウントしないようにしました。

ちなみに、バンドル形式のAppleScript、あるいはアプレットについては、バンドル内に入れたAppleScriptをエディタ上から直接オープンすると、変更したり保存したりする際にエディタが暴走してしまいます(10.9、10.10で確認)。バンドル内のAppleScriptを編集したい場合には、Finder上でバンドル内容を表示させたうえで、Finder側でバンドル内のAppleScriptをダブルクリックして編集するとエディタが暴走せずに編集、保存が可能です。

スクリプト名:編集中のScript BundleあるいはApplet全体の行数をかぞえる
set resList to {}
set resTotal to 0

–編集中のAppleScriptのうち、行数カウント対象を選択する
tell application "Script Editor"
  set dList to name of every document
  
  
set dRes to choose from list dList
  
if dRes = false then return –キャンセル時の対応
  
  
set ddRes to first item of dRes
  
  
tell document ddRes
    set aPath to path
  end tell
  
end tell

–バンドル中のScriptをすべて取得
set realPath to aPath & "/Contents/Resources/Scripts/"
set sRes to do shell script "ls " & (quoted form of realPath)
set sList to paragraphs of sRes

repeat with i in sList
  
  
set j to contents of i
  
set jj to realPath & j
  
  
–osadecompileコマンドで中間言語形式のAppleScriptをテキストに逆変換して行数をかぞえる
  
set tempAS to do shell script "/usr/bin/osadecompile " & quoted form of jj
  
set tempList to paragraphs of tempAS
  
set asCount to length of tempList –wc- lでカウントしてもいいが、本文の内容を取り出せておけたほうが便利
  
  
–出力リストに名称、行数のペアで追加
  
if j = "main.scpt" then
    set the end of resList to {ddRes & " (" & j & ")", asCount}
  else
    set the end of resList to {j, asCount}
  end if
  
  
–合計行数の算出
  
set resTotal to resTotal + asCount
  
end repeat

–総合計を出力リストの末尾に追加
set the end of resList to {"Total:", resTotal}

–2D ListをTAB区切りテキストに変換して結果に出力
set resText to retItemDelimedAndParagraphDelimedText(resList, tab, return) of me

–>
(*
"A1.scpt  264
A2.scpt  360
A3.scpt  358
A4.scpt  298
B1.scpt  298
B2.scpt  243
B3.scpt  294
B4.scpt  258

(中略)

設定ファイルから実行年月日&時のリストを展開.scpt  299
Total:  3570"
*)

–入れ子のリストを、アイテム間のデリミタとパラグラフ間のデリミタを指定してテキスト化
–というか、入れ子のリストをタブ区切りテキストにするのが目的
on retItemDelimedAndParagraphDelimedText(aList, itemDelim, paragraphDelim)
  set aText to ""
  
  
repeat with i in aList
    set aStr to retDelimedText(i, itemDelim) of me
    
set aText to aText & aStr & paragraphDelim
  end repeat
  
  
return aText
end retItemDelimedAndParagraphDelimedText

on retDelimedText(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 retDelimedText

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2014/07/23 Script Editorで最前面のアプリの用語辞書を表示する v3

AppleScriptエディタ/Script Editorで、最前面のアプリの用語辞書を表示するAppleScriptです。

バージョンアップして、最前面のアプリがAppleScript等のOSA(Open Scripting Architecture)言語によるScriptingに対応しているかどうかを判定したのちに、辞書のオープンを行います。

Script Menuに入れて、メニューから呼び出すことを前提としています。

前バージョンでは、とくに対象アプリケーションのScripting対応については調べていなかったため、非対応アプリを指定すると、Script Editorで対象アプリをバイナリモードでオープンしてしまうなどの問題があり、それに対処したものです。

本AppleScriptは、各アプリケーションのバンドル中にあるInfo.plistを走査してOSA対応の判定を行っていますが、これは「NSAppleScriptEnabled」のエントリがInfo.plist上に存在した場合、慣習的に「true」しか指定されていない(そもそも非対応である場合にはNSAppleScriptEnabledのエントリそのものを作らない)ことから、「NSAppleScriptEnabled」が入っていれば対応……という「手抜き判定」をやっています。

真剣に作るのであれば、NSAppleScriptEnabledのエントリを取得して属性値がどうなっているか判定すべきです。

スクリプト名:Script Editorで最前面のアプリの用語辞書を表示する v3
–最前面のプロセスのファイルシステム上の位置を取得してaliasに変換する
tell application “System Events”
  set frontProc to every process whose frontmost is true and visible is true
  
set aProc to contents of first item of frontProc
  
set aFile to file of aProc
  
set aBundleID to bundle identifier of aProc
end tell

set aFile to aFile as alias

–バンドルパッケージ中のInfo.plistファイルを走査してAppleScript対応かどうかを調べる
set aFilePosix to quoted form of POSIX path of aFile
set infoPath to aFilePosix & “Contents/Info.plist”
set aRec to extractInfoPlistAndFindString(infoPath, “NSAppleScriptEnabled”)

–スクリプト用語辞書をScript Editorでオープンする手順
if aRec = true then
  –OS X 10.10でScript Editor側からアプリをオープンしてもダメだったので、Finder側からScript Editorで指定アプリをオープンすることに
  
tell application “Finder”
    set apFile to (application file id “com.apple.scripteditor2″) as alias
    
open aFile using application file apFile
  end tell
else
  tell application id aBundleID
    display dialog “本アプリケーションは、各種OSA言語によるコントロールに対応していません。” buttons {“OK”} default button 1 with icon 2 with title “Scripting非対応”
  end tell
end if

–指定のInfoPlist(たぶん)をextractして指定文字列を含んでいるかチェック
on extractInfoPlistAndFindString(aPosix, findStr)
  
  
try
    set a to (do shell script “/usr/bin/plutil -p “ & aPosix)
  on error
    return 0 –エラー(指定のパスにファイルが存在しない)
  end try
  
  
set b to (a contains findStr)
  
return b
  
end extractInfoPlistAndFindString

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2014/07/17 Script Editorで最前面のアプリの用語辞書を表示する

Script Editorの「Script Menu」に入れて使っているものですが……最前面にあるアプリケーションのScript用語辞書をオープンするAppleScriptです。

OS X 10.9までは、AppleScriptエディタで指定のアプリケーションをopenすると用語辞書が表示されていましたが、10.10ではそのままの方法が通じなかったので、やり方を変えてみました。

Finderから指定アプリに対しScript Editorを指定してオープンするという……画像ファイルをPreviewで開くか、Photoshopで開くか……という小技の応用でなんとかしました。

スクリプト名:Script Editorで最前面のアプリの用語辞書を表示する
tell application "System Events"
  set frontProc to every process whose frontmost is true and visible is true
  
set aProc to contents of first item of frontProc
  
set aFile to file of aProc
end tell

set aFile to aFile as alias

–OS X 10.10でScript Editor側からアプリをオープンしてもダメだったので、Finder側からScript Editorで指定アプリをオープンすることに
tell application "Finder"
  set apFile to (application file id "com.apple.scripteditor2") as alias
  
open aFile using application file apFile
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2014/05/16 AppleScriptエディタ上で選択部分を伏せ字に(記号だけ元のまま残す)

AppleScriptエディタ上の選択部分を伏せ字にするAppleScriptです。数字とアルファベットは伏せ字にしますが、記号などその他の文字は元のまま残します。

アルファベット大文字と数字は「X」に、アルファベット小文字を「x」に置き換え、他の記号をそのまま残しておきます。このほうが雰囲気が(全部Xに置き換えるよりも)分りやすいので、既存のScriptに手を加えてみました。

本AppleScriptは、/Library/Scripts/Script Editor Scripts/フォルダに入れて、AppleScriptエディタのコンテクストメニューから呼び出して使うことを想定しています。

サンプルをBlogに掲載するにしても、そのままでは掲載できない情報を含んでいるような場合には、本Scriptのようなツールを用いて機械的に伏せ字にしています。いちいち手で打ち直すのは面倒だし、間違いも起こるので……こうしたツールの併用は欠かせません。

ase10.png
▲AppleScriptエディタ上で伏せ字にしたい範囲のテキストを選択(本iAd identifierの内容はダミーです)

ase11.png
▲AppleScriptエディタのコンテクストメニューから……

ase12.png
▲本Scriptを呼び出す

ase13.png
▲選択範囲が伏せ字に

スクリプト名:選択部分を伏せ字に(記号だけ元のまま残す)
tell application “AppleScript Editor”
  try
    tell document 1
      set ab to contents of selection
      
set abList to characters of ab
      
      
set outStr to “”
      
repeat with i in abList
        set j to contents of i
        
        
set anID to id of j
        
        
if anID 65 and anID 90 then
          –アルファベット大文字
          
set outStr to outStr & “X”
        else if anID 97 and anID 122 then
          –アルファベット小文字
          
set outStr to outStr & “x”
        else if anID 48 and anID 57 then
          –数字
          
set outStr to outStr & “X”
        else
          set outStr to outStr & j
        end if
        
      end repeat
      
      
set contents of selection to outStr
    end tell
  end try
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/10/27 AppleScript EditorのEaster Egg、日本語環境にはなし

AppleScript Editor上で252文字以上の長さの変数を使用すると、エラーメッセージが表示され……その内容がイースターエッグなのだそうで(→ AppleScript Easter Egg: Way too long, dude.)。

ただし、この表示は日本語環境では再現しません。

asedit_1.png

asedit_2.png

理由はいろいろあるかと思われますが、Mac OS XやiOSのOSメッセージのローカライズをApple自身が行っているわけではない、と考えると納得が行きます。

loc1.png

The OmniGroupのソフトウェアのAbout画面に「翻訳:LocTeam」の表示があり、探してみるとLocTeamのWebサイトが簡単に見つかります。

このLocTeamのWebサイトを見ると、Mac OS XやApple純正アプリのローカライズをこの会社が担っていることが分ります。Appleは核となる英語の文字リソース部分のみ作り、LocTeamに各国語へのローカライズを依頼している……と見るのが妥当でしょう。

そうした仕事のやりとりの中で、オリジナルの文字リソースの意味と、各国語へのローカライズ後の内容で意図が(正しい方に)変わるというのはありえる話です。Appleのエンジニアの悪ふざけをLocTeamがローカライズ時に修正したものと推察されます。

2012/01/14 ドロップされたASをTextWranglerでdiff表示

ドロップされたAppleScriptをTextWrangler(version 3.5.3)でdiff表示するAppleScriptです。他のAppleScriptのファイルを処理してdiff表示(差分表示)を行うユーティリティ的なものです。

以前に、「ドロップされたASをdiff表示 Mac OS X 10.4対応版」というものを作ったことがありました。AppleScriptをdiff表示するのに、普通はApple純正のFileMergeを使っているのですが、そのためには文字コードなどの書き換えをする必要があり、TextWranglerを併用して……TextWrangler自体がdiff表示機能を持っていることを思い出し、TextWranglerでdiff表示させるというものでした。

すでに決着が付いたかのように思われていた、AppleScript業界の「diff問題」が再燃したのは、読者がいるんだかいないんだかさっぱり不明なこのBlogの、読者の方からの1通のメールからでした。

『いつもお世話になります。(サイトに)

希望といいますか要望だけで申し訳ないのですが、「ドロップされたASをdiff表示 Mac OS X 10.4対応版」の10.6対応版などを作ってはいただけないでしょうか?
というのも、10.6ならdiff表示v4で十分なはずなんですが、業務PCにてXcodeのインストールが許可されていないという事情がありまして、もしよろしければ、ご検討いただけますようお願いいたします。』

……「スクリプトエディタ」を操作していたところを「AppleScriptエディタ」に書き換えれば瞬殺ではないか、と思って手をつけてみたら……意外とたいへんでした(汗)

Mac OS X 10.6上でTextWranglerを使ってcompare fileコマンドでdiffを取ろうとすると……謎のエラーが出ます。

set oldPath to choose file
set newPath to choose file

set oldPath to oldPath as string
set newPath to newPath as string

tell application “TextWrangler”
  compare file oldPath against file newPath
end tell

こんな、最低限の基礎的な記述に戻してあげて(トラブル時にものすごく大事なやりかた)、テキストに書き出したAppleScriptを2つ指定してみると……あいかわらずエラーになります。

 「もう、TextWranglerじゃなくて別のツールでも使おうか……」

日も暮れて、そう考えかけたころ、「fileで指定しているのがいけないのでは?」と気付き、aliasで渡してみたら何事もなかったように表示されました。

tw_diff106.jpg

そもそも、TextWranglerのAppleScript用語辞書(アプリケーションのアイコンをAppleScriptエディタにドラッグ&ドロップすると表示)を見てみると、

twdic.jpg

などと書いてあるので、「そうかーaliasじゃダメなんだー」と受け取ったからです。これは、TextWranglerのAppleScript用語辞書が間違っています。

asdic.jpg

▲こんな風に書かなくては(AppleScriptエディタの用語辞書より「open」命令の記述)

このScriptをアプリケーション形式で保存し、出来上がったドロップレットに2つのAppleScript書類をドロップすると、TextWranglerでdiff表示を行います。

スクリプト名:asdiff
on run
  –環境確認を行うべき(書いてない)
  
  
–FileMergeの起動を最初にやっておく
  
tell application “System Events”
    set fmExists to (exists of process “TextWrangler”)
  end tell
  
  
if fmExists = false then
    tell application “TextWrangler”
      launch
    end tell
  end if
  
end run

on open fileList
  
  
tell application “Finder”
    set sortedList to sort fileList by creation date
  end tell
  
  
set sortedList to reverse of sortedList
  
  
set oldPath to writeASSourceToTempFolder((item 1 of sortedList) as alias)
  
set newPath to writeASSourceToTempFolder((item 2 of sortedList) as alias)
  
  
–do shell script “/usr/bin/opendiff ” & oldPath’s POSIX path’s quoted form & ” ” & newPath’s POSIX path’s quoted form & ” > /dev/null 2>&1 &”
  
  
tell application “TextWrangler”
    compare oldPath against newPath –Mac OS X 10.6用にaliasで渡すように書き換えた
  end tell
  
  
end open

–AppleScriptのソースを取得してファイルに書き出し
on writeASSourceToTempFolder(aScript)
  –ASのソースを取得
  
set scriptSource to getContentsOfScript(aScript) of me
  
if scriptSource = false then
    display dialog “指定のASのオープン時にエラーが発生”
    
return false –エラー
  end if
  
  
tell application “Finder”
    set origName to name of file aScript
  end tell
  
set origName to makestr_alphabetNumeric_only(origName) of me
  
  
  
–tmpにASのソースを一時ファイルとして保存
  
set tmpPath to (path to temporary items from system domain) as string
  
set aFN to do shell script “/bin/date +%Y%m%d_%H%M%S”
  
set tmpPathFull to tmpPath & origName & “_” & aFN & “.txt”
  
set fRes to write_to_file_UTF8(scriptSource, tmpPathFull, false) of me
  
if fRes = true then
    return tmpPathFull as alias –書き出したテキストのフルパスを返す(10.6用に変更)
  else
    return false –エラー
  end if
end writeASSourceToTempFolder

–指定したAppleScriptのソースを取得する(Mac OS X 10.4用)
on getContentsOfScript(aScript)
  tell application “AppleScript Editor”
    try
      with timeout of 600 seconds –アプリケーションの起動に時間がかかるケースもあるので180秒から延長
        set aScript to open aScript
      end timeout
    on error
      return false
    end try
    
    
tell window 1
      set aName to name
    end tell
    
    
tell document aName
      set aCon to contents
      
close without saving
    end tell
  end tell
  
  
return aCon
end getContentsOfScript

–ファイルへのUTF8での書き込み
on write_to_file_UTF8(this_data, target_file, append_data)
  try
    set the target_file to the target_file as text
    
set the open_target_file to ?
      open for access file target_file with write permission
    if append_data is false then ?
      set eof of the open_target_file to 0
    write this_data to the open_target_file as «class utf8» starting at eof
    
close access the open_target_file
    
return true
  on error
    try
      close access file target_file
    end try
    
return false
  end try
end write_to_file_UTF8

–アルファベットと数字のみの文字列にして返す
on makestr_alphabetNumeric_only(aKeyword)
  set aKeyword to aKeyword as string
  
set aKeyword to aKeyword as Unicode text
  
  
set cList to characters of aKeyword
  
set newName to “”
  
  
repeat with i in cList
    set aRes to checkAN(i) of me
    
if aRes = true then
      set newName to newName & (i as string)
    end if
  end repeat
  
  
return newName
end makestr_alphabetNumeric_only

on checkAN(aKeyword)
  set anList to {“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”, “n”, “o”, “p”, “q”, “r”, “s”, “t”, “u”, “v”, “w”, “x”, “y”, “z”, “-”, “+”, “.”, “_”, “=”, “(”, “)”, “#”, “$”, “%”, “&”, “~”, “^”, “0″, “1″, “2″, “3″, “4″, “5″, “6″, “7″, “8″, “9″}
  
  
set aKeyword to aKeyword as Unicode text
  
set aKeyword to aKeyword as string
  
set kList to characters of aKeyword
  
repeat with i in kList
    ignoring case
      if i is not in anList then
        return false
      end if
    end ignoring
  end repeat
  
return true
end checkAN

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/05/05 ドロップされたASをdiff表示 Mac OS X 10.4対応版

ドロップされた2つのAppleScript書類のdiff表示を行うAppleScriptのMac OS X 10.4対応版です。

まず、本AppleScriptを実行形式で保存(ドラッグ&ドロップを受け付けるドロップレットになる)しておき、比較を行うAppleScript2本をそのドロップレットにドラッグ&ドロップします。

Mac OS X 10.4上でTextWlangerがインストールされていれば、スクリプトエディタ経由でテキストを受け取ってTextWrangler上でTextWranglerのビルトインのdiff機能を用いてdiff表示を行います。

tw1.jpg

FileMergeでdiff表示することも考えないではなかったのですが、結局テキスト処理のためにTextWranglerが必要になってしまい、

 「それなら、TextWranglerでdiff表示させたほうが……」

ということで、TextWranglerでdiff表示させた次第です。なお、現時点でBareBones SoftwareからダウンロードできるTextWranglerは最低でもMac OS X 10.5を必要とするため、Mac OS X 10.4対応のTextWranglerをすでに用意してある環境でのみの実行が可能です。

スクリプト名:asDiff3.10411
on run
  環境確認を行うべき(書いてない)
  
  
FileMergeの起動を最初にやっておく
  
tell application "System Events"
    set fmExists to (exists of process "TextWrangler")
  end tell
  
  
if fmExists = false then
    tell application "TextWrangler"
      launch
    end tell
  end if
  
end run

on open fileList
  
  
tell application "Finder"
    set sortedList to sort fileList by creation date
  end tell
  
  
set sortedList to reverse of sortedList
  
  
set oldPath to writeASSourceToTempFolder((item 1 of sortedList) as alias)
  
set newPath to writeASSourceToTempFolder((item 2 of sortedList) as alias)
  
  
do shell script "/usr/bin/opendiff " & oldPath’s POSIX path’s quoted form & " " & newPath’s POSIX path’s quoted form & " > /dev/null 2>&1 &"
  
  
tell application "TextWrangler"
    compare file oldPath against file newPath
  end tell
  
  
end open

AppleScriptのソースを取得してファイルに書き出し
on writeASSourceToTempFolder(aScript)
  ASのソースを取得
  
set scriptSource to getContentsOfScript(aScript) of me
  
if scriptSource = false then
    display dialog "指定のASのオープン時にエラーが発生"
    
return false エラー
  end if
  
  
tell application "Finder"
    set origName to name of file aScript
  end tell
  
set origName to makestr_alphabetNumeric_only(origName) of me
  
  
  
tmpにASのソースを一時ファイルとして保存
  
set tmpPath to (path to temporary items from system domain) as string
  
set aFN to do shell script "/bin/date +%Y%m%d_%H%M%S"
  
set tmpPathFull to tmpPath & origName & "_" & aFN & ".txt"
  
set fRes to write_to_file_UTF8(scriptSource, tmpPathFull, false) of me
  
if fRes = true then
    return tmpPathFull 書き出したテキストのフルパスを返す
  else
    return false エラー
  end if
end writeASSourceToTempFolder

指定したAppleScriptのソースを取得する(Mac OS X 10.4用)
on getContentsOfScript(aScript)
  tell application "Script Editor"
    try
      with timeout of 600 seconds アプリケーションの起動に時間がかかるケースもあるので180秒から延長
        set aScript to open aScript
      end timeout
    on error
      return false
    end try
    
    
tell window 1
      set aName to name
    end tell
    
    
tell document aName
      set aCon to contents
      
close without saving
    end tell
  end tell
  
  
return aCon
end getContentsOfScript

ファイルへのUTF8での書き込み
on write_to_file_UTF8(this_data, target_file, append_data)
  try
    set the target_file to the target_file as text
    
set the open_target_file to
      open for access file target_file with write permission
    if append_data is false then
      set eof of the open_target_file to 0
    write this_data to the open_target_file as «class utf8» starting at eof
    
close access the open_target_file
    
return true
  on error
    try
      close access file target_file
    end try
    
return false
  end try
end write_to_file_UTF8

アルファベットと数字のみの文字列にして返す
on makestr_alphabetNumeric_only(aKeyword)
  set aKeyword to aKeyword as string
  
set aKeyword to aKeyword as Unicode text
  
  
set cList to characters of aKeyword
  
set newName to ""
  
  
repeat with i in cList
    set aRes to checkAN(i) of me
    
if aRes = true then
      set newName to newName & (i as string)
    end if
  end repeat
  
  
return newName
end makestr_alphabetNumeric_only

on checkAN(aKeyword)
  set anList to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", "+", ".", "_", "=", "(", ")", "#", "$", "%", "&", "~", "^", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
  
  
set aKeyword to aKeyword as Unicode text
  
set aKeyword to aKeyword as string
  
set kList to characters of aKeyword
  
repeat with i in kList
    ignoring case
      if i is not in anList then
        return false
      end if
    end ignoring
  end repeat
  
return true
end checkAN

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/08/10 Script Objectのparseのじっけん v4

AppleScriptのプログラムリストを解析して、Script Objectのリストアップを行うAppleScriptです。

AppleScriptのプログラムを解析する、自己解析系のAppleScriptを作りかけて……複数のAppleScript書類に存在しているハンドラ同士のdiffを取ろうとしていました。同じ名称のハンドラで、処理内容が異なる場合には困るので、比較しようと考えたわけです。

ハンドラ同士のDiffを取ろうと考えたときに、普通のハンドラなら簡単でよいのですが……

スクリプト名:script1
on test()
  display dialog “Test”
end test

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

ここに、Script Objectの宣言が加わってくると面倒です。さまざまな大きめのプログラムをつなげるときに、お互いにハンドラの重複があったりして統合が面倒という時があって、そういう時にはscript objectで論理分割して、同じハンドラ名称があっても別物扱いするようなことが……よくあります。

スクリプト名:script2
script scriptObj1
  on test()
    display dialog “Test”
  end test
end script

script scriptObj2
  on test()
    display dialog “Test”
  end test
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

このぐらいならまだかわいげがあるのですが、Script文は入れ子にできるので、これに対処する必要があります。

スクリプト名:script21
script scriptObj1
  on test()
    display dialog “Test@scriptObj1″
  end test
end script

script scriptObj2
  on test()
    display dialog “Test@scriptObj2″
    
    
script scriptObj21
      on test()
        display dialog “Test@scriptObj21″
      end test
      
script scriptObj211
        on testr()
          display dialog “Test@ scriptObj211″
        end testr
      end script
    end script
    
  end test
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

下のScriptをscript 21に対して実行すると、

–> {{”scriptObj1″, 1, 5}, {”scriptObj2″, 7, 23}, {”scriptObj21″, 11, 20}, {”scriptObj211″, 15, 19}}

といった結果が返ってきます。

このScript文を考慮してハンドラのリストアップを行うようにするといい感じでしょうか。

スクリプト名:Script Objectのparseのじっけん v4
–v4では、ネスティングしたScript文から再帰でオブジェクト名をピックアップ。一応の完全体
–v3では、Script文のネスティングに対応(ピックアップまで対応)
–v2では、Script文のネスティングに対応(対応しただけ)

global scObjList –このへん、必須(結果を値渡しではなく、グローバル変数へアクセスで行うため)
global aScriptList, a_r –ここも必須(再帰時にアクセスするのと、高速化のため)

–サンプルのAppleScript書類の内容をピックアップ
tell application “AppleScript Editor”
  set nameList to name of every document
  
set selDoc to choose from list nameList
  
tell document (contents of first item of selDoc)
    set a to contents
  end tell
end tell

set aScriptList to paragraphs of a
set a_r to a reference to aScriptList –間接アクセスで処理の高速化を行う

set allLen to length of a_r
set scObjList to {}

pickUpScriptObjectFromList(1, allLen) of me
set objList to shellSortListAscending(scObjList, 2) of me

objList

on pickUpScriptObjectFromList(startLineNum, endLineNum)
  
  
set curScriptObj to {} –name, startLine, endLiine
  
set nestingCounter to 0
  
set nestedF to false
  
set lineCounter to startLineNum
  
set findF to false –script object末尾検索フラグ。trueで末尾の”end script”の検索中
  
  
repeat with i from startLineNum to endLineNum
    
    
set ii to contents of (item i of a_r)
    
    
ignoring hyphens, punctuation and white space
      –Script文の開始位置を走査中
      
if findF = false then
        –Script文をみつけた場合
        
if ii begins with “script” then
          set aRes to parseScriptObjectName(ii) of me
          
set curScriptObj to {aRes, lineCounter, 0}
          
set findF to true
        end if
        
        
      else if findF = true then
        –Script文の末尾を走査中モード
        
if ii begins with “script” then
          set nestingCounter to nestingCounter + 1
          
set nestedF to true
          
        else if ii begins with “end script” then
          if nestingCounter = 0 then
            set item 3 of curScriptObj to lineCounter
            
set the end of scObjList to curScriptObj
            
            
if nestedF = true then
              –このへんで、Script Objectのネスティングに対して再帰でアプローチする
              
pickUpScriptObjectFromList((item 2 of curScriptObj) + 1, (item 3 of curScriptObj) - 1) of me –再帰時に捜索範囲を前後ともに1行ずつ狭める
            end if
            
            
set findF to false
            
set nestingCounter to 0
            
set nestedF to false
            
          else
            set nestingCounter to nestingCounter - 1
            
          end if
        end if
      end if
    end ignoring
    
    
set lineCounter to lineCounter + 1
    
  end repeat
end pickUpScriptObjectFromList

–与えられた1行分のテキスト(おそらく、script文の宣言部分)から、Script Object名称をparseする
on parseScriptObjectName(aText)
  set aOffst to offset of “script “ in aText
  
if aOffst = 0 then return “”
  
set aRes to text (aOffst + (length of “script “)) thru -1 of aText
  
return aRes
end parseScriptObjectName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

–シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/06/22 指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する 10.5_10.6

指定の文字列をAppleScriptとして評価して実行し、結果をすべて文字列で取得するAppleScript……の、Mac OS X 10.5/10.6の両バージョン対応版です。動作には、GUI Scriptingがオンになっている必要があります。

iChat経由でAppleScriptを実行するAppleScriptを作ったまでは良かったのですが、リモート環境にあるMacがMac OS X 10.5で稼働しており、10.5/10.6の両環境で動く必要が出てきました。

AppleScriptを記述したり生成用に使ったりするプログラムは、Mac OS X 10.5までは「スクリプトエディタ」、10.6からは「AppleScriptエディタ」という名前になっており、OSのバージョンを取得してGUI Scriptingでコントロールするパラメータを(ちょっとだけ)変更し、両プログラムのGUIのちがい(割り当てられたキーボードショートカットのキーが異なるとか)を吸収しています。

as106.jpg
▲Mac OS X 10.6上の「AppleScriptエディタ」の「表示」メニュー。「結果を表示」がCommand-3

as105.jpg
▲Mac OS X 10.5上の「スクリプトエディタ」の「表示」メニュー。「結果を表示」がCommand-2

とりあえず、10.4は対象にしなくてよさそうだったので10.4はサポートしていませんが、サポートしたい環境にいる方は、if文で10.4に対応させるといいかもしれません(そもそも、iChatのイベントでAppleScriptを動かす仕組みは10.5から導入されたので、あんまりうまみがありません)。

スクリプト名:指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する 10.5_10.6
set aScript to “tell app \”Finder\” to get properties of startup disk”
set asRes to getAppeScriptRes(aScript) of me

–指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
on getAppeScriptRes(aScript)
  tell application id “com.apple.scripteditor2″
    make new document
    
tell window 1
      set bDoc to name
    end tell
    
    
tell document bDoc
      set contents to aScript
      
      
–いきなり実行する
      
try
        execute
      on error
        close without saving
        
return false
      end try
    end tell
    
  end tell
  
  
  
set osVer to system attribute “sys2″
  
  
–GUI Scripting経由でAppleScriptの実行結果を取得する
  
activate application id “com.apple.scripteditor2″
  
tell application “System Events”
    
    
if osVer > 5 then
      –Mac OS X 10.6以降の場合(とりあえず10.6.x)
      
tell process “AppleScript エディタ” –各国語環境で名前は違うかもしれない、と日本語で書いてみる
        keystroke “3″ using {command down} –command-3 結果を表示
        
set resVal to value of text area 1 of scroll area 1 of group 1 of group 1 of splitter group 1 of window 1
      end tell
      
    else if osVer = 5 then
      –Mac OS X 10.5の場合
      
tell process “スクリプトエディタ” –ここも各言語環境で名前が違う、と日本語で書いてみる
        keystroke “2″ using {command down} –command-2 結果を表示
        
set resVal to value of text area 1 of scroll area 1 of group 1 of splitter group 1 of window 1
      end tell
    end if
  end tell
  
  
  
tell application id “com.apple.scripteditor2″
    tell document bDoc
      close without saving
    end tell
  end tell
  
  
return resVal
  
end getAppeScriptRes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/06/17 指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する

指定したAppleScript文字列を、実際にAppleScriptエディタ上で実行して、その結果を「文字列として」取得するAppleScriptです。

一昨日掲載した大物AppleScriptにも、かなり不満が残っていました。それは、「as:」とAppleScriptコマンドを実行させても、結果が文字化けして返ってくることがあることです。各アプリケーション依存のオブジェクト値だったりすると、無理やり文字列に直そうとしても、

“{class:«class cdis», name:\”Cherry\”, index:2, displayed name:\”Cherry\”, name extension:\”\”, extension hidden:false, «class ctnr»:«class pcmp» of application \”Finder\”, «class cdis»:«class sdsk» of application \”Finder\”, «class posn»:{98, 82}, «class dpos»:{1714, 37}, bounds:{66, 50, 130, 114}, kind:\”ボリューム\”, «class labi»:0, locked:false, «class dscr»:missing value, «class comt»:\”\”, size:5.33816377344E+11, «class phys»:5.33816377344E+11, creation date:date \”2010年2月20日土曜日 13:24:06\”, modification date:date \”2010年6月17日木曜日 11:00:56\”, «class iimg»:missing value, URL:\”file://localhost/\”, «class sown»:\”システム\”, «class sgrp»:\”admin\”, «class ownr»:«constant ****rdwr», «class gppr»:«constant ****rdwr», «class gstp»:«constant ****read», «class cwnd»:«class cwnd» of «class sdsk» of application \”Finder\”, id:-100, «class capa»:6.39791054848E+11, «class frsp»:1.05974677504E+11, «class isej»:false, «class istd»:true, «class dfmt»:«constant ****dfh+», «class Jrnl»:true, «class isrv»:true, «class igpr»:false} “

のように、残念な結果が得られてしまいます。

そこで、パーフェクトに指定のAppleScriptの実行結果を取得できる方法を検討してみました。

こういう用途になると、がぜん登場してくるのが、AS系のブラックテクノロジーともいえる「GUI Scripting」。将来の互換性とか、アプリケーションがバージョンアップしたら使えなくなるかもしれないとか、スピードがいまいちとか、そういうことにすべて目をつぶって「目的だけ果たせればそれでいい」という手段です。

前出の実行結果も、

“{class:disk, name:\”Cherry\”, index:2, displayed name:\”Cherry\”, name extension:\”\”, extension hidden:false, container:computer container of application \”Finder\”, disk:startup disk of application \”Finder\”, position:{98, 82}, desktop position:{1714, 37}, bounds:{66, 50, 130, 114}, kind:\”ボリューム\”, label index:0, locked:false, description:missing value, comment:\”\”, size:5.3381421056E+11, physical size:5.3381421056E+11, creation date:date \”2010年2月20日土曜日 13:24:06\”, modification date:date \”2010年6月17日木曜日 11:00:56\”, icon:missing value, URL:\”file://localhost/\”, owner:\”システム\”, group:\”admin\”, owner privileges:read write, group privileges:read write, everyones privileges:read only, container window:container window of startup disk of application \”Finder\”, id:-100, capacity:6.39791054848E+11, free space:1.05976844288E+11, ejectable:false, startup:true, format:Mac OS Extended format, journaling enabled:true, local volume:true, ignore privileges:false}”

……と、きちんと得られるようになり、「もうちょっと手を入れてみようか」と欲が出てきてしまうところです。

スクリプト名:指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
set aScript to “tell app \”Finder\” to get properties of startup disk”
set asRes to getAppeScriptRes(aScript) of me

–指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
on getAppeScriptRes(aScript)
  tell application “AppleScript Editor”
    make new document
    
tell window 1
      set bDoc to name
    end tell
    
    
tell document bDoc
      set contents to aScript
      
      
–いきなり実行する
      
try
        execute
      on error
        close without saving
        
return false
      end try
    end tell
    
  end tell
  
  
–GUI Scripting経由でAppleScriptの実行結果を取得する
  
activate application “AppleScript Editor”
  
tell application “System Events”
    tell process “AppleScript エディタ” –各国語環境で名前は違うかもしれない、と日本語で書いてみる
      keystroke “3″ using {command down} –command-3 結果を表示
      
set resVal to value of text area 1 of scroll area 1 of group 1 of group 1 of splitter group 1 of window 1
    end tell
  end tell
  
  
tell application “AppleScript Editor”
    tell document bDoc
      close without saving
    end tell
  end tell
  
  
return resVal
  
end getAppeScriptRes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/12/26 選択文字列を伏せ字に

AppleScriptエディタ上で選択中の文字列を伏せ字に置き換えます(文字数は同じですべて「X」の文字)。

/Library/Scripts/Script Editor Scriptsフォルダ以下に入れて、AppleScriptエディタのコンテクストメニューから呼び出すことを前提に作成したものです。

AppleScriptエディタ上で文字列を選択しておき……

ed1.jpg

Controlキーを押しながらマウスクリック、あるいはマウスの副(右)ボタンをクリックしてコンテクストメニューを表示して、

ed2.jpg

メニューから本Scriptを実行すると……

ed21.jpg

選択部分が伏せ字になります。

ed3.jpg

スクリプト名:選択文字列を伏せ字に
tell application “AppleScript Editor”
  try
    tell document 1
      set ab to contents of selection
      
set aCount to length of ab
      
set outStr to “”
      
repeat aCount times
        set outStr to outStr & “X”
      end repeat
      
set contents of selection to outStr
    end tell
  end try
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/12/15 最前面のアプリケーションに対するAppleScriptを新規作成 v3

最前面のアプリケーションに対するAppleScriptを新規作成し、同アプリケーションの用語辞書をAppleScriptエディタでオープンするAppleScriptです。Script Menuに入れて使います。

as2.jpg

/Library/Scriptsフォルダ内に入れて使うことを前提にしています。ここに入れたScriptは、どのアプリケーションが前面に表示されていてもメニューに表示されます。

本Scriptを実行すると、最前面のアプリケーションに対するtellブロックのAppleScriptが新規作成され、同アプリケーションの用語辞書がAppleScriptエディタで表示され、AppleScriptエディタが一番前に表示されます。

as1.jpg

ただし、スクリプタブル「ではない」アプリケーションに対して実行したときのエラートラップが有効に機能しておらず、AppleScriptエディタでエラーがキャッチされて実行が止まってしまいます。こうなると、AppleScriptエディタを強制終了する必要があるため、気をつけてください。

System EventsとFinderを使って最前面のアプリケーションがAppleScriptに対応しているかどうかチェックしてから処理……というパターンも書いてみたものの、Scriptableでないクセに「has scripting terminology」がtrue(System Events/Finder)だったり、「accepts high level events」がtrue(Finder)だったりするアプリケーションがあった(iThink 9.1.3 Trial)ので、搭載を見送った経緯があります。

スクリプト名:最前面のアプリケーションに対するAppleScriptを新規作成 v3
tell application “System Events”
  set appList to every process whose frontmost is true
  
set anApp to first item of appList
  
set aName to name of first item of appList
  
set aFile to file of anApp
end tell

try
  tell application id “com.apple.ScriptEditor2″
    open aFile
  end tell
on error aMes
  –display dialog “アプリケーション「” & aMes & “」のAppleScript用語辞書のオープンを試みましたが、以下の理由により失敗しました:” & return & aMes
  
return
end try

set aCon to “tell application “ & (ASCII character 34) & aName & (ASCII character 34) & return & return & “end tell” & return

tell application id “com.apple.ScriptEditor2″
  set aNewDoc to make new document
  
tell document 1
    set contents to aCon
    
try
      compile
    end try
  end tell
  
activate
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/10/28 最前面のアプリケーションのAppleScript用語辞書をオープンする

最前面のアプリケーションのAppleScript用語辞書をオープンするAppleScriptです。

日常的に、「起動中のアプリケーションのAppleScript用語辞書をオープンする」という作業が多いので、これを手っ取り早く行うためのScriptを作成しました。

Script Menuに本Scriptを登録しておいて、呼び出すと……

as1.jpg

このように、最前面のアプリケーションのAppleScript用語辞書がオープンします(個別のアプリケーション用のScriptフォルダではなく、共通でMenuに表示されるフォルダ=「コンピュータ・スクリプト・フォルダ」(/Library/Scripts/)に入れておく必要があります)。Script Menuに入れる際に先頭にハイフン(「–」)を入れているのは、メニューの上の方に表示させるための小細工です。

as2.jpg

AppleScriptエディタ/スクリプトエディタへのtellブロックをアプリケーション名称ではなくIDで指定しているのは、OSのバージョンが10.5→10.6と変わったときに書き換えなくてもすむようにするためです。

実際には、10.5→10.6に移行したときに書き換える必要はなく、「スクリプトエディタはどこにあるか?」とOS側が聞いてくるので、AppleScript Editorを選択すればOS内でひもづけが行われます。ただ、本Blogに掲載しているようなリンクであるとか、テキストの状態になっているAppleScriptをコンパイル(構文確認)する場合には、アプリケーション名の書き換えが必要になってしまいます。そういうケースに備えてIDで指定した次第です。

スクリプト名:最前面のアプリケーションのAppleScript用語辞書をオープンする
tell application “System Events”
  set pList to name of every process whose visible is true and frontmost is true
end tell

set aRes to first item of pList

tell application “System Events”
  set aP to file of process aRes
end tell

try
  tell application id “com.apple.ScriptEditor2″
    open aP
  end tell
on error aMes
  display dialogアプリケーション「” & aRes & “」のAppleScript用語辞書のオープンを試みましたが、以下の理由により失敗しました:” & return & aMes
end try

tell application id “com.apple.ScriptEditor2″
  activate
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/01/08 スクリプトエディタがオープンしているウィンドウのうち、指定名称のものを最前面に出す

スクリプトエディタでオープンしているAppleScriptのうち、指定名称のものを最前面に出します。ただ、このAppleScriptをスクリプトエディタ上で実行すると、スクリプトエディタの制御がうまく行きません。

実際には、Script Menuに入れて実行するか……Script Debugger上から実行することになります。GUI Scriptingを使用しているため、システム環境設定のユニバーサルアクセスで「補助装置にアクセスできるようにする」チェックボックスをオンにしておく必要があります。

スクリプトの内容を書式つきのリッチテキストで取得したかったので、特定のScriptのウィンドウを最前面に出す必要があったのでした。本来の目的(Mindjet MindManagerのノート欄に書式つきでAppleScriptのリストを入れたかった)は果たせませんでしたが……残骸のサブルーチンはきっとどこかで何か別の用途で役立つことでしょう。

(more…)

2008/05/08 スクリプトエディタ上のキャレットがある行に、ファイル名をコメントで展開

スクリプトエディタ自体も、AppleScriptからコントロールすることのできる「スクリプタブルな」アプリケーションであるため、AppleScriptによってさまざまな活用が行えます。本サイトで紹介しているように、サブルーチンを動作検証用の短いサンプルプログラムとともに保存して活用していますが……肝心のサブルーチンの先頭に「このルーチンはどのような動作を行うか」をコメントで書いておくことにしています。動作検証用コードは他のプログラムにコピーしませんが、サブルーチンと先頭のコメントは他のプログラムにまるごとコピーすることにしています。このコメントはそうした意味で必須のものなのです。

保存時に、「なるべく動作内容を把握しやすいファイル名で」保存することにしているため、そのファイル名と動作内容を記しておくコメントは……ほとんど、というよりも、「まるっきり一緒」ということになりがちです。

そこで、本スクリプトをScript Menuに入れておき、サブルーチンの先頭にカーソルを置いた状態でScript Menuから本スクリプトを実行すれば、ファイル名をそのまま選択位置にコメントで入れて、コンパイルまでしておいてくれるという仕組みです。個人的には、かなり便利に使っています。

途中「delay 0.1」でウェイトを入れているのは……ここでウェイトを入れないとうまく動作しなかったためで、まるで料理にふりかける一振りの塩のごとく、適切なウェイト命令は処理を適切に実行させる威力を発揮します。とくに、アプリケーションに対してコントロールを行うことがメインのAppleScriptにおいて、delay命令の持つ意義は大きなものになります。

sce1.jpeg

sce2.jpeg

sce3.jpeg

スクリプト名:スクリプトエディタ上のキャレットがある行に、ファイル名をコメントで展開

tell applicationScript Editor
  activate
  
tell window 1
    set a to name
    
    
set aText to” & a & return
    
set the clipboard to aText
    
  end tell
end tell

tell applicationSystem Events
  tell processScript Editor
    keystrokevusing {command down}
  end tell
end tell

delay 0.1

tell applicationScript Editor
  activate
  
tell document a
    compile
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/04/05 すべてのScriptをDockから取り出す

Script Menuに入れて使うタイプのScriptです。AppleScriptでプログラムを書き始めると、気がつけば大量のウィンドウを開いて作業をしていることがよくあります(汗) 邪魔なので途中のものをDockにしまっておいたりするわけですが、そのウィンドウをすべてDockから取り出すのは割と面倒です。で、面倒な作業をワンアクションで実行できるようにScriptを書いた次第です。

スクリプトエディタのウィンドウがDockに大量に入っている状態

スクリプト名:すべてのScriptをDockから取り出す
tell applicationScript Editor
  tell (every window whose name is not equal to “”)
    set visible to true
  end tell
  
tell windowイベントログの履歴to set visible to false
  
tell window結果の履歴to set visible to false
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に