Archive for 2月, 2010

2010/02/28 Ustream Producerでレイヤーにアクセス

Ustream Producerのドキュメント内のレイヤーにアクセスするAppleScriptです。

これらレイヤーがどういうものかといえば、

ust4.jpg

という構成になっています。ただ、レイヤーを新規に作成したり削除したりする、という操作は行えません。

スクリプト名:Ustream Producerでレイヤーにアクセス
tell application "Ustream Producer"
  tell document 1
    set layCount to count every layer
    
repeat with i from 1 to layCount
      tell layer i
        name
      end tell
    end repeat
  end tell
end tell

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

2010/02/28 Ustream Producerでdocumentの情報を取得する

Ustream Producerの処理の情報を取得するAppleScriptです。

Ustream Producerで何が「書類」なのかといえば、起動するとオープンするメインウィンドウそのものが書類であり、新規書類作成を行うと(ログイン操作を求められ)同じようなウィンドウがもう1枚オープンされます。

stream3.jpg

書類から情報を取得すると、書類の名称が取得可能。その割に書類のフルパスは取得できません。

「transition speed」にアクセスすると、結果が何も返ってきません。

「active transition popup」にアクセスすると、ポップアップメニューの内容にアクセスできるらしいのですが、ポップアップメニューの内容を変更しても、この属性値の内容は変わりません。

stream2.jpg

スクリプト名:Ustream Producerでdocumentの情報を取得する
tell application “Ustream Producer”
  set dCount to count every document
  
–> 1
  
  
tell document 1
    name
    
–> “名称未設定 1″
    
transition speed
    
–> (何も結果が返ってこない。エラーにはなっていない)
    
active transition popup
    
–> 1(Transitionのポップアップメニューで初期状態とは違う項目を選んでもこの値は変わらない。謎)
  end tell
end tell

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

2010/02/28 Ustream Producerの情報を取得する

Ustream Producerのアプリケーションの情報を取得するAppleScriptです。

ust1.jpg

Ustream ProducerのAppleScriptの用語辞書の出来は、いまひとつ。

だいたい、用語辞書を見れば「Wirecast Scripting」と元になったアプリケーション(名前を変えただけ?)の名前が残っている始末。

ustdict.jpg

辞書には命令が載っていても、propertiesなどは取得してもどの階層のオブジェクトからは情報が(まとめて)取れませんし、ものすごく出来が悪い印象です。

スクリプト名:Ustream Producerの情報を取得する
tell application “Ustream Producer”
  –properties
  
–> error “Ustream Producer でエラーが起きました:properties を取り出すことはできません。利用が許されていません。” number -1723 from properties
  
set a to name
  
–> “Ustream Producer”
  
  
set b to version
  
–> “1.0″
  
  
set c to frontmost
  
–> false
end tell

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

2010/02/27 Bilingual article Test

[en]

This is test posting for bilingual article (English and Japanese).

[ja]

日本語と英語の記事を両立させるためのテストです。予想していたのとずいぶん違う見え方です。日本語ユーザーがアクセスした時には日本語の記事しか見えない、という動きをするのかと思っていました。

2010/02/26 「AppleScript基礎文法最速マスター」を更新中

本サイトでは、あまりコテコテの入門者向けコンテンツというのは書いてこなかったのですが、プログラマーの友人たちから「たまに書く必要があるときに、基礎文法だけでもまとめてあると助かる」という話があったので、「AppleScript基礎文法最速マスター」というメニューを作成し、ぼちぼち書いています。

→ メニューを整理して「BEGINNERS」に名称変更

まだ試行錯誤の最中なので、個別のページにリンクを張ることは推奨されません。ページの並び順を制御するために、ああでもないこうでもない、と試しているところです。各ページのファイル名などもちょくちょく変わっていたりします。

もうちょっと書けば、AppleScriptの基礎文法についてはおそらく網羅できるものと思われます。ただ……AppleScriptの場合、文法が分かったぐらいではアプリケーションのコントロールについてはまったく手が出ないので……実戦レベルをクリアするためには、もうちょっと何か一工夫必要になるものと思われます。

初見のアプリケーションのAppleScriptを書くといった場合には、

(1)アプリケーションの機能や役割を理解する
(2)ASから実行して意味のある機能について考える
(3)AS用語辞書をオープンして、基礎的な処理(アプリケーションやドキュメントの属性値を確認したり、設定したり)を試してみる
(4)AS用語辞書を見て、ASから使える命令語を確認。何ができるか、そのためにどのような前提条件(ドキュメントをオープンしておくとか、何かを選択しておくとか)をクリアすべきかを検討する

といった作業を行っています。

また、これと並行して海外のMLの過去ログを検索して、対象アプリの記述例が出ていないかを確認したりします。特定の記法以外は通らなかったりするパターンが多いといった理由により、アプリケーションのコントロール部分は誰が書いてもそれほど変わらないものなので……すでに書いた実績があれば、それを参照したほうが早いということになります。

プログラミング能力よりも……情報収集・分析能力のほうが求められる処理系、という印象です。

2010/02/25 I/Oデータの地デジチューナー「m2TV」添付ソフトがAppleScriptに対応

アイ・オー・データ機器の地上波デジタルチューナー「m2TV」添付ソフトがAppleScriptに対応しているとのこと(Twitter経由でhitoriblogさんの情報)。

地デジのTVをすでに持っているので、AppleScriptで遊ぶためだけに買うのは……なんですが、メーカーにメールでも書いて貸してもらいましょうか?(問い合わせ先が分からない、、、)

添付ソフトのAppleScript用語辞書次第ですが、Web上から情報を収集して録画するとか、twitter経由で録画予約するとか、いろいろできそうな感じがします。

2010/02/23 MicrosoftがSilverlight 4 on MacでAppleScriptサポートを検討中?

Twitter上で情報収集を行っていたら、そんな噂を聞きつけたので……キーワードをGoogleに突っ込んで探してみたところ、こんな(↓)ページが。

Silverlight 4’s COM+ Automation Raises Security and Portability Concerns

ポータビリティ(移植性)がなくなるし、セキュリティ的にアレでナニなのでやらないんじゃないの? という見方のようです。

セキュリティ的にどうかといわれれば、本Blogをごらんの方にはお分かりのように、AppleScriptからはだいたいなんでもできてしまうような気がする(汗)ので、Webページを表示させたら勝手にAppleScriptが実行されるというのはちょっと怖いです。

2010/02/23 32bitアプリのIMからdisplay dialogに日本語文字入力ができない

Mac OS X 10.6.2の環境に日本語IM「かわせみ」をインストールして使っていますが、AppleScriptエディタ上でちょろっと、

display dialog “なにか入力してね!” default answer “”

などと書いて実行してみたところ……

as64_2.jpg

何も入力されませんでした(汗) 正確にいえば、表示されないだけで文字は入力されているようなのですが、AppleScript側には入力したとおりの文字が返ってきません。

すぐに物書堂さんにTwitterで問い合わせてみたところ、かわせみ自体が32ビットで動作しているので、AppleScriptエディタないしはAppleScriptアプレットを32ビットモードで動作させてほしいとのことでした。

as64_1.jpg

ATOKのように、積極的にAppleScriptの一部機能(GUI Scriptingのキーボード入力エミュレーション)を妨害するようなIMは(Scripterとしては)常用できませんが、かわせみがダイアログ入力できないというのは残念です。

ダイアログで入力できないだけであり、AppleScriptエディタ上でプログラムを組んでいる最中は、とくに問題なく日本語入力できます(なので、いままで気付かなかったわけで)。

as64_3.jpg

ことえり、Google日本語入力は問題なく入力でき(自分で確認しました)、かわせみとATOKは32ビットで動作しているのでダイアログに日本語入力できないとのこと(物書堂さんより)。

64ビットに移行していないOSAXなども多いので、AppleScriptエディタやアプレットを32ビット起動するというのもたしかに解決策ではあるのですが、そんな事情もよく分からない入門者がつまづかないよう祈るばかりです(汗)。

2010/02/23 Mac OS X 10.5/10.6上のファイル名/フォルダ名に関するバグ

AppleScriptにおける「パス」について(5)のコメント欄で教えていただいた件を実際に確認してみました。

asbug1.jpg

濁点つき(たぶん、半濁点も)のフォルダを用意して(たぶん、ファイルでも同様)……そのファイル名を取得。ファイル名の1文字目のidを調べると、文字+濁点(or 半濁点)に分離してIDが取得されてしまうというものです。

スクリプト名:AS_bug_check
set aFol to choose folder

tell application “Finder”
  set aName to name of aFol
end tell

set anID to id of first character of aName

–「ふつうのFolder」を選択した場合
–> 12405

–「だくてんテスト」を選択した場合
–> {12383, 12441}–> 「た」+濁点

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

通常、1文字に対応する値が返ってくるところで、リストで2文字分返ってきてしまいます。それぞれ、文字コードの内容をUnicode Checkerで調べてみると……

asbug2.jpg

asbug3.jpg

ご覧のとおりです。

asbug4.jpg

Finderから取得したファイル名/フォルダ名の文字数をカウントする分には大丈夫そう(↑)なのですが……

asbug5.jpg

ファイル名を1文字ずつ分解して(characters of)、IDを取得するとごらんのとおり(↑)です。

2010/02/17 AppleScriptにおける「パス」について(5)

もしも、現在お使いの環境がMac OS X 10.4.11などの古い環境(Mac OS X 10.5より前)の場合には、Mac OS Xのバグについても考慮しておく必要があります。

Mac OS X 10.5以前は、フォルダ名に濁点や半濁点を含む文字列があった場合……

  例:ぴよぴよ(半濁点を含む)
  例:びっくり(濁点を含む)

ファイル名/フォルダ名をFinderから取得して文字ごとに取り出すような処理をすると、「濁点と文字が分離されてしまう」というバグがありました。

filename.jpg

▲「Webログ」フォルダを選択した場合の実行結果(Mac OS X 10.4.11)

長い間、US Appleの担当者に散々文句を言って、ようやく10.5で直った次第です(ただ、その一方で10.5以降ではカタカナと平仮名の区別ができなくなるというおそるべきバグが……)。

回避方法は、一度stringにcastしてからunicode textにcastする、というものです。ものすごく、意味不明な処理を書かなくてはならず、本当にイライラするところですが……動かないよりはマシということで、長年この記述を行ってきました。いまでも、Mac OS X 10.4.11上で動作させる必要のあるAppleScriptは、そのような処理を書いています。

2010/02/17 AppleScriptにおける「パス」について(4)

Mac OS X上でパスを記述する際に、気をつけるべき点があります。それが、ローカライズド・フォルダ。基本的かつ重要なフォルダについては、それぞれの言語環境に合わせてローカライズした名前をユーザーに見せる仕組みがローカライズド・フォルダですが……裏を返せば、Finder上で見えてる名前と本当の名前が違う場合がある、というわけです。

ふだん見ている「書類」や「デスクトップ」といったフォルダ名は、本当のフォルダ名ではありません。Finder上でカスタムアイコンが付いているようなフォルダは軒並みローカライズド・フォルダで表示されており、実際には「Documents」とか「Desktop」という名前がついています。

このあたり、AppleScript上でパスを記述する際に問題になるかもしれません(普段から英語で表記していたので、その存在を忘れていました)。

「フォルダの本当の名前」を確認するのに一番よいのは、Terminal.appを起動して確認するとか……あるいは、ちょっとしたAppleScriptを記述して

  set a to choose folder

実際にAppleScriptから「本当の名前」を確認してみることです。

2010/02/17 AppleScriptにおける「パス」について(3)

昨今のOSはほとんどそうですが、Mac OS XはマルチユーザーのOS(複数ユーザーの使用を前提としたOS)であるため、ユーザーごとにホームディレクトリが異なります。また、Finder上でハードディスクの名前もユーザーが自由に変えられるようになっています。

このため、ホームディレクトリへのパスや、その他の重要なフォルダへのパスについても、プログラム上に直接文字列で書いておくと、他のマシンや他のユーザー環境で実行できなくなってしまいます。

そこで、途中までのパスについてはコンピュータからpath to命令で取得し、その後のパスのみ文字列で書いておき、それらを結合するというのが一般的なパスの記述方法です。

set picFol to path to pictures folder from user domain
–> alias “Cherry:Users:maro:Pictures:”

さらに、上記サンプルで出てきていますが、「ドメイン」の概念が必要になります。
たとえば、「ライブラリ」フォルダというものは、

  Macintosh HD:システム:ライブラリ:
  Macintosh HD:ライブラリ:
  Macintosh HD:Users:hiyoko:ライブラリ:

の3種類があって、それぞれ「system domain」、「local domain」、「user domain」のドメイン指定によって指定できます。

スクリプト名:ライブラリフォルダを各ドメインで取得
set libFol to path to library folder from system domain
–> alias "Macintosh HD:System:Library:"

set libFol to path to library folder from local domain
–> alias "Macintosh HD:Library:"

set libFol to path to library folder from user domain
–> alias "Macintosh HD:Users:maro:Library:"

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

たいていは、自分のユーザーディレクトリの下にあるフォルダを扱う場合がほとんどなので、user domainを指定することになるでしょう。

2010/02/17 AppleScriptにおける「パス」について(2)

AppleScriptにおけるパス記述方式は、Mac OS形式、POSIX path形式、URL形式の3つがあります。出現頻度および重要性もこの並びのとおりです。

■Mac OS形式

フォルダ名を「:」で区切って記述する、Classic Mac OSから引き継がれたパス記述形式。AppleScriptの世界でもっともよく使われます。「東京都練馬区中村橋」という住所をMac OS形式で記述すれば、

  東京都:練馬区:中村橋:

になります(中村橋がファイルではなくフォルダの場合)。「中村橋」がファイルである場合には、

  東京都:練馬区:中村橋

になります。

ハードディスクの名称が「Macintosh HD」で、ユーザーが「maro」の場合のホームディレクトリは、

  Macintosh HD:Users:maro:

と表現されます。aliasはこの形式で表現されます。

■POSIX path形式

UNIXの世界で用いられるパス記述形式です。ディレクトリ(フォルダ)階層を「/」で区切ります。また、パスの途中にスペースなどが入る場合には、パス全体をクォートでくくる必要があります。

さきほどの東京都練馬区中村橋は、

  /東京都/練馬区/中村橋/

のように表現されます。特筆すべき点は、このPOSIX pathはルート「/」を頂点とするツリー構造であり、HDDの名前が変わろうがその構造は変わりません。

ハードディスクの名称が「Macintosh HD」で、ユーザーが「maro」の場合のホームディレクトリは、

  /Users/maro/

ハードディスクの名称が「Hiyoko」で、ユーザーが「maro」の場合のホームディレクトリも、

  /Users/maro/

という形式で表現されます。AppleScriptの世界におけるパスはMac OS形式で統一されることが望ましいところですが、shellコマンドを呼び出すような場合には必要になりますし、一部の出来の悪いアプリケーションがこのpathを必要とします(CocoaではPOSIX pathが使われるため)。パス処理関連で代表的な出来の悪いアプリケーションとして、Adobe Acrobat DistillerとKeynoteがあります。

とくに、Adobe Acrobat Distillerでは、POSIX形式のパスにクォート処理を行って渡すとエラーになるなど、本当にチェックしてから発売しているのか疑問に思えるほどです。

path1.jpg

Keynoteでは、ファイルのオープンにaliasを要求するのに、画像を連続配置するmake image slidesコマンドではPOSIX pathを要求します。

path2.jpg

path3.jpg

こうした、出来の悪いアプリケーションが存在することを意識したうえで、Mac OS形式とPOSIX path形式を使い分ける必要があります。また、これらの形式は相互変換できるように命令が用意されています。

■URL形式

ほとんど登場する機会はないのですが、Webブラウザなどにファイルを指定するような場合に使います。基本的にはPOSIX pathと同じですが、先頭にプロトコルを示す「file://」が付くことと、マシンのローカルに存在していることを示すために、localhostからパスが始まります。

ハードディスクの名称が「Macintosh HD」で、ユーザーが「maro」の場合のホームディレクトリは、

  file://localhost/Users/maro/

という形式で表現されます。URL形式では空白文字や一部の特殊記号、日本語の文字列などはURLエンコードされるため、パスの途中に空白文字を含むフォルダが存在する場合でも、クォート処理を行う必要はありません。

set a to choose folder

tell application “Finder”
  set aInfo to URL of a
end tell

–> “file://localhost/Users/maro/“

なお、AppleScriptの標準命令ではURL形式からMac OS形式に戻すことができません。本Blog上に掲載している「URLエンコードされたファイルパスを元のテキスト(POSIX Path)に戻す」サブルーチンを用いてPOSIX pathに変換し、そこからaliasに変換することはできます。

2010/02/16 AppleScriptで扱う「パス」について(1)

AppleScriptにかぎらず、HDD内のどこかに入っているファイルとか、自分のホームフォルダの「書類」フォルダとか、意図したものを指し示して処理を行いたいという場合がものすごく多くあります。

一般的に、そういうファイルシステム中における階層的な位置情報を「パス」と呼びます。英語でいうとpathです。

path.jpg

パスは住所の表記によく似ています。ただ、人に伝える住所はちょっと間違いがあってもなんとかなりますが、プログラム中に記述するパスには一切間違いが許されません。

「東京都練馬区中村橋」という住所があったとして、人に伝える場合には「とうきょうと 練馬く中村橋」でも伝わりますが、プログラム中ではこれが1文字間違っただけでも別の住所と見なされることになります。たとえ、空白文字(スペース)が抜けたとか、そうしたささいな間違いも許容されません(1バイトのアルファベットの大文字小文字の違いは同一視されます。これは、Mac OS Xが標準採用しているHFS plusの仕様です)。

そんなわけで、プログラム中にパスを書いておくのは、けっこう骨が折れる作業です。

さらに、プログラムを他人のマシン上でも動作させることを考えると、HDDの名称やユーザー名も違う可能性が高いので、ユーザーの環境情報を取得しつつ、パスを組み立てるという作業が必要になります。このあたり、昔のClassic Mac OSでは必要のなかった話ですが、Mac OS Xになって少々複雑に(ちょっとだけですが)なった話です。

2010/02/12 Google Chrome for Macの新バージョンβ版が登場

Google Chrome for Macの新バージョン「5.0.307.7 beta」の配布が開始されています。

chrome1.jpg

AppleScript用語辞書に変更は見られません。依然として、Window内部のTabにアクセスできなかったり、Selectionを取得できなかったりという状態です。今後も、Chromeに関してはこの程度のままになる可能性は否定できません。

まして、ApertureのようにAppleScript用語辞書にサンプルAppleScriptが書かれているとかいうこともありません。

2010/02/11 Aperture 3でalbumをカウントして名前を取得する

Aperture 3でalbumをカウントして名前を取得するAppleScriptです。

こんな、albumの構成になっている場合に……

ap2.jpg

こんな結果が得られます。

ap1.jpg

スクリプト名:Aperture 3でalbumをカウントして名前を取得する
tell application "Aperture"
  set aCount to count every album
  
repeat with i from 1 to aCount
    tell album i
      name
    end tell
  end repeat
end tell

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

2010/02/11 Aperture 3でアプリケーションのプロパティを取得

Aperture 3でアプリケーションのプロパティを取得するAppleScriptです。

selectionがこの階層から取得できる点と、tasksというのが気になります。

ほかにも、trash(たぶんゴミ箱)に「Scripting Trash」なる名前がついています。GUI側のゴミ箱と別にAppleScriptから操作する専用のゴミ箱が用意されているというのでしょうか? 意味不明の気合いが入っていることを感じさせます。普段の(やる気のない)Appleらしからぬテンションです。

スクリプト名:Aperture 3でアプリケーションのプロパティを取得
tell application “Aperture”
  properties
end tell
–> {class:application, fullscreen:false, selection:{image version id “wBxsWcCJQTqt%yjFTmsoUQ” of album id “allPhotosAlbum” of application “Aperture”}, frontmost:false, trash:trash id “ScriptingTrash” of application “Aperture”, version:”3.0″, name:”Aperture”, tasks:{}}

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

2010/02/11 Aperture 3でAppleScript関連機能に大きな前進

2010年2月9日に登場したAperture 3。「200を超える新機能」の中に、AppleScript系の機能追加がリストアップされています。

30日間お試しバージョンをダウンロードして、AppleScript系の機能をいろいろ調べ始めました。

AppleScript用語辞書をHTMLに書き出して、前のバージョンの用語辞書と差分を取って、基礎的なScriptを試し書きして……と、いつものように初見のアプリケーションのテスト書きをしていたところ、ApertureのAppleScript用語辞書に見慣れないものが……

aperture_dict.jpg

なんと!! AppleScript用語辞書の中にサンプルAppleScriptが書かれていました。しかも、リンクが埋め込んであって……「Example Script」のところをクリックすると、AppleScriptエディタにその内容が転送されます(本Blogのように)。

……Appleらしからぬいいアイデア(^ー^; どこからか、小人さんがやってきて実装してくれたのでしょうか?

どおりで、AppleScript用語辞書の差分を調べて相違点が多いと思っていました。今後、この動きがApple純正のAppleScript対応アプリケーションに波及するのか、それともこれまでのように対応度がまちまちなままなのか……動向を見守りたいところです。

2010/02/10 フォルダの選択(内容確認つき)v2

ちょっと気の利いた複数folder選択」を発展させ、選択したフォルダの一覧を確認表示するようにしたAppleScriptです。

最大の見どころは、フォルダパスを一覧表示するさいに、どのパスかを示す文字の長さをそろえて、フォルダパスの内容確認を行いやすくした「umekusaKit」です。

dialog1.jpg

これで、選択した複数パスの一覧を表示し、処理前に確認するように書いておけば、ささいなミスもなくなるに違いありません。

ちなみに、この一覧表示で「Cancel」ボタンをクリックすると……

dialog2.jpg

のように、処理を中断します。

どうも、プログラムを見直してみると……もっと汎用的なサブルーチンに仕立てて、もっと簡単に利用できるようにできそうな気がします。まだ、手直しできる余地が大きそうですが、使用頻度はあまり高くなさそうなので……このままかもしれません。

スクリプト名:フォルダの選択(内容確認つき)v2
property aFol : missing value
property bFol : missing value
property cFol : missing value

set a1Mes to “コマの書類の親フォルダ”
set b1Mes to “ページアップ先のフォルダ”
set c1Mes to “ページ台紙が入っているフォルダ”

set a2Mes to “(komaFolderServerPath)を選択”
set b2Mes to “(pageUpOutputTargetPath)を選択”
set c2Mes to “(pageDaishiFolder)を選択”

if aFol = missing value then
  set aFol to choose folder with prompt (a1Mes & a2Mes)
else
  set aFol to choose folder default location aFol with prompt (a1Mes & a2Mes)
end if

if bFol = missing value then
  set bFol to choose folder with prompt (b1Mes & b2Mes)
else
  set bFol to choose folder default location bFol with prompt (b1Mes & b2Mes)
end if

if cFol = missing value then
  set cFol to choose folder with prompt (c1Mes & c2Mes)
else
  set cFol to choose folder default location cFol with prompt (c1Mes & c2Mes)
end if

–設定内容の確認表示
set aaList to {a1Mes, b1Mes, c1Mes}
set {r1, r2, r3} to makeSameString(aaList, “ ”) of umekusaKit –ウメクサ文字には全角スペースを指定

set aList to {r1 & “ = ” & aFol as string, r2 & “ = ” & bFol as string, r3 & “ = ” & cFol as string}
set defaultItem to contents of item 1 of aList

–最終確認
set aRes to choose from list aList with prompt “この設定でよいですか?” default items defaultItem with title “指定内容の最終確認”
if aRes = false then
  display dialog “処理を中止します” buttons {“OK”} default button 1 with icon 1 with title “処理中止”
  
return
end if

–このあとにメインの処理が入る

–文字リストをchoose from listで表示させる際に長さを揃えるために作った
script umekusaKit
  –最大の長さの文字列に合わせて、ウメクサ文字を後ろに追加する
  
–fillCharは1文字であることを期待している
  
–全角文字と半角文字が「混在しない」ことを期待している。あるいは、半角文字の文字長が一緒とか
  
on makeSameString(aList, fillChar)
    –リスト中の文字列長の最大値を求める
    
set lenList to {}
    
repeat with i in aList
      set the end of lenList to length of (contents of i)
    end repeat
    
set maxLen to item (maximumItemNoFromList(lenList) of me) of lenList
    
    
–最大長に合わせて各項目の末尾にfillCharを追加する
    
set retList to {}
    
repeat with i in aList
      set newStr to contents of i
      
set aLen to length of i
      
repeat with ii from 1 to (maxLen - aLen)
        set newStr to newStr & fillChar
      end repeat
      
set the end of retList to newStr
    end repeat
    
    
return retList
  end makeSameString
  
  
–最大値の項目番号を取得する
  
on maximumItemNoFromList(nList)
    script o
      property nl : nList
      
property itemNo : 1
    end script
    
    
set max to item 1 of o’s nl
    
repeat with i from 2 to (count nList)
      set n to item i of o’s nl
      
if n > max then
        set max to n
        
set o’s itemNo to i
      end if
    end repeat
    
return o’s itemNo
  end maximumItemNoFromList
end script

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

2010/02/04 指定されたファイルのparentにラベルとコメントを付ける

指定されたファイルの親フォルダに指定のラベルと指定のコメントを付けるAppleScriptです。

実に簡単な内容で、あまり多くの人が気にも止めない内容に見えるのですが、AppleScript的な世界観における重要度はかなり高い処理です。下手をすると、高速ソートルーチンよりも重要かもしれません。

本処理は、さまざまなファイルを大量に処理するようなケースで、かつ、データが各フォルダに分けられて入っている(InDesignの書類とか)ようなケースを想定しています。そして、フォルダ内のデータにエラーが発生した場合には、親フォルダにラベルをつけて色を変え、さらにエラー原因をコメントとして残しておく、ためのものです。

こうした処理が入っているかどうかでツール系のScriptの使い勝手は大きく変わってくるため、「必須」を通り越して「ないとおかしい」というレベルのものです。さらに、Finder上で新規Windowを作成して、エラー対象ファイル/フォルダを選択状態にしておくとか……そうした処理は、ぜひやっておきたいものです(大量にあると困りますけれど)。

スクリプト名:指定されたファイルのparentにラベルとコメントを付ける
set aFile to choose file
set aComment to “エラーだぴよー”
setLabelAndCommentToParentFol(aFile, aComment) of me

–指定されたファイルの親フォルダにラベルとコメントを付ける
on setLabelAndCommentToParentFol(aFile, aComment)
  tell application “Finder”
    set aParent to (parent of aFile) as alias
    
set label index of aParent to 4 –ぶるーのラベル
    
set comment of aParent to aComment
  end tell
end setLabelAndCommentToParentFol

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

2010/02/04 Preview.appで用紙サイズおよび用紙方向を指定して印刷 v2

GUI Scripting経由でPreview.appで印刷を実行。プリンタ名、用紙サイズ、用紙方向を指定して印刷を行うAppleScriptです。

GUI Scriptingを使用しているため、「システム環境設定」の「ユニバーサルアクセス」で、「補助装置にアクセスできるようにする」をオンにしている必要があります。

ただし、使用プリンタは各ユーザー環境によって異なるため、そのまま使えるものとは思わないでください。

また、Preview.appで「画像オープン→印刷→画像クローズ」といった連続したフローを実現するものでもありません。Preview.appで画像をオープンすると、WindowのIDが画像をオープンするたびに+1されるようで、画像を1枚しかオープンしていないのにwindow 2を指定する必要があるとか、そういう状況を考慮した作りにはなっていません。

スクリプト名:Preview.appで用紙サイズおよび用紙方向を指定して印刷 v2
(*
2010/1/19

v2
Preview.appでは、書類をオープンするたびにWindowのインデックスがインクリメントされるらしく、
1枚目の書類はwindow 1でアクセスできるが、2枚目の書類(1枚しかウィンドウは開いていない)に
対しては、Window 2でアクセスする必要がある。これに対処する必要がある(問題未解決)

v1
シンプルタイプのプリントダイアログから拡張プリントダイアログに大きさをひろげたケースと、
最初から拡張プリントダイアログが表示されているケースでは、ポップアップメニューのIDが異なる。

拡張ダイアログが表示されていなかったら、拡張表示にして一度キャンセルし、再試行するようにした(10回まで)

*)

–set directionF to "V" –用紙方向=たて方向
set directionF to "H" –用紙方向=たて方向

set printerName to "PS-NX650"
set paperSize to "A4"

printViaGUI(directionF, printerName, paperSize) of me

on printViaGUI(directionF, printerName, paperSize)
  activate application "Preview"
  
tell application "System Events"
    tell process "プレビュー"
      
      
set goF to false
      
repeat 10 times
        –メニューから印刷を実行
        
click menu item "プリント…" of menu 1 of menu bar item "ファイル" of menu bar 1
        
        
tell window 1
          tell sheet 1
            –拡張プリントダイアログを表示させる
            
set sheetClosed to value of checkbox 1
            
if sheetClosed = 0 then
              click checkbox 1
              
click button "キャンセル"
            else
              set goF to true
              
exit repeat
            end if
          end tell
        end tell
        
      end repeat
      
      
if goF = false then return
    end tell
  end tell
  
  
  
  
  
activate application "Preview"
  
tell application "System Events"
    tell process "プレビュー"
      
      
–メニューから印刷を実行
      
click menu item "プリント…" of menu 1 of menu bar item "ファイル" of menu bar 1
      
      
tell window 1
        tell sheet 1
          
          
–出力先のプリンタを指定
          
tell pop up button 4 –「プリンタ」ポップアップボタン
            set aTitle to value
            
if aTitle is not equal to printerName then
              click
              
tell menu 1
                set mList to title of every menu item
                
set aRes1 to retIHitItem(mList, printerName as Unicode text) of me
                
if aRes1 = false then
                  return mList
                end if
                
click menu item aRes1
                
              end tell
            end if
          end tell
          
          
          
–用紙サイズを変更
          
tell pop up button 1
            
            
set aTitle to value as string
            
if aTitle is not equal to paperSize then
              click
              
tell menu 1
                set mList to value of every menu item
                
                
set aLen to length of mList
                
select menu item 1 –最終アイテムを選択しておく
                
                
set aRes2 to retIHitItem(mList, paperSize as string) of me
                
if aRes2 = false then
                  return false
                end if
                
click menu item aRes2
              end tell
            end if
          end tell
          
          
–用紙方向を指定
          
if directionF = "V" then
            click radio button 1 of radio group 3
          else if directionF = "H" then
            click radio button 2 of radio group 3
          end if
          
          
–「用紙サイズに合わせる」をクリック
          
click radio button 2 of radio group 1
          
          
–「プリント」ボタンをクリック
          
–click button "プリント"–ここをコメントアウトすると印刷を行う。
          
beep
        end tell
      end tell
    end tell
  end tell
end printViaGUI

–指定リスト中の何アイテム目かを調べて返す
on retIHitItem(aList, anItem)
  set aCount to 1
  
set hitF to false
  
repeat with i in aList
    set j to contents of i
    
if j = anItem then
      set hitF to true
      
exit repeat
    end if
    
set aCount to aCount + 1
  end repeat
  
  
if hitF = false then return false
  
  
return aCount
end retIHitItem

–GUI Scriptingの命令が続く中でdelayコマンドをエラーになるので、
–wait部分だけサブルーチン化
on waitSec(aNum)
  delay aNum
end waitSec

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

2010/02/03 Preview.appでプリンタと用紙サイズを指定して印刷

一般的なAppleScriptの命令を使用して、特定のプリンタへの印刷は実行できますが、用紙サイズまでは指定できません。そこで、仕方なくGUI Scriptingを使用して印刷を実行することになります。

ここで、「仕方なく」という前置きが入るのは、GUI Scriptingという仕組みが通常のAppleScriptによる命令よりも遅く、また確実性が劣るためです。確実性が高くないといっても、OSやアプリのクラッシュを伴うようなレベルではなく、アプリケーション側の状態を詳細に調べながら操作しないと「思い通りに動かない」という話です。

■GUI Scriptingを使えるようにするために

GUI Scriptingが動作するためには、システム環境設定の「ユニバーサルアクセス」で「補助装置にアクセスできるようにする」にチェックが入っている必要があります。GUI Scriptingは使用に注意を要する機能であるため、デフォルト状態ではオフになっています。

sysprop.jpg

このチェックボックスをオンにすれば、GUI Scripting系の命令を実行できるようになります(プログラムを作成するだけであれば、オンにする必要はありません)。

■GUI Scriptingとは何なのか?

OS標準で搭載されているSystem Events.appが持っている「Process Suites」という命令群が、GUI Scripting(=UI Element Scripting)の命令です。他のSystem Eventsの命令については、システム環境設定/ユニバーサルアクセスでオンにしなくても普通に使えます。

sys2.jpg

一般的なAppleScriptでは、アプケーション内部のオブジェクトを経由して機能を呼び出すのに対し、GUI Scriptingはアプリケーションの外部からGUI部品を指定して命令を行います。このため、あるボタンを押そうとしたときに、もちろんオンになっていないと押せないですし、アプリケーション内部の状態がそのボタンがオンになる条件を満たしている必要もあります。

簡単な記述でアプリケーションをコントロールできるというのがGUI Scriptingの「理想」ではあるものの、実際に書いてみると……通常のAppleScriptとはまた別のマニアックなノウハウが必要な記法、と見るべきです。内部命令を経由しないでGUI ScriptingだけですべてのAppleScriptのプログラムを作成するというのが「幻想」というより「無理」であることはよく覚えておいてほしいと思います。通常のAppleScriptの「補助」的に使うのがGUI Scriptingの正しい使い方です。

■GUI Scriptingをはじめる前に

いろいろと前置きが長くなってしまいましたが、アプリケーションを無理矢理操作するため、「奥の手」としてGUI Scriptingが必要になるケースは確実にあります。そういう意味では、不完全なソリューションではあるものの、「じゃあいらないんだね?」とGUI Scriptingになくなられると困ります。ものすごく困ります。

GUI Scriptingでは、画面上のGUI部品を指定して命令を記述することになりますが、この部品の番号や並び順を知るためには、どうしてもツールが必要です。

(1)PreFab UI Browser
仕事でScriptを書く必要があるとか、確実かつ迅速にGUI Scriptingによるプログラムを作成する場合には必要です。ただし、このソフトでカバーできるのは8割程度であり、あとの残り2割をカバーするためには後述の「Accessibility Inspector」が必要になります(同ツールはXcode Toolsに含まれるため、Xcode Toolsのインストールが必須です)。

sys4.jpg

(2)Accessibility Inspector
Xcode Toolsをインストールすると、一緒に入ってきます。PreFab UI Browserでカバーできない一部のGUI部品の情報を調べるために必要です。具体的に言ってしまうと、PreFab UI Browserではポップアップメニューの内容までは追えません。とくに、ポップアップボタン「ではない」GUI部品からポップアップメニューを表示させるようなイレギュラーなプログラムでは本ツールの併用が必要です。

sys3.jpg

(3)「強引GUI Scripting」のためのツール
記述のために情報を調べるツールではなく、AppleScriptから命令して強引にマウスカーソルを移動させたりクリック動作させるようなツールです。ツールによって一長一短があるので、複数用意して用途に応じて使い分けるのが理想的です。プロのScripterはこの手のツールをいくつも手元に置いてあった、いざという時に備えています。何を使っているか、どの程度のAppleScriptライブラリを書きためているか等の情報はもちろんのこと、存在自体が門外不出のノウハウといえます。

これらのツールがそろってはじめて安心してGUI Scriptingのプログラムを作りはじめられます。……ない環境では、とても書く気になれません。

■アプリケーションの挙動を追う

GUI Scriptingでは、アプリケーションの状態を正確に認識した上で記述を行う必要があります。特定のウィンドウ上の特定のTabの中にあるGUI部品を操作する場合には、そのTabが表示されていなければなりません。ポップアップメニュー上の項目を選択するためには、ポップアップメニューを表示させておかなければなりません。通常のAppleScriptによるアプリケーション内部オブジェクト経由のコントロールの方が簡単と思えるほど、アプリケーションによってGUI部品の挙動が異なるため、正確な状況把握は欠かせません(PreFab UI Browser必須)。

■GUI部品の指定はIDか名前で

GUI ScriptingでGUI部品を指定する際には、window 1やmenu 1のように番号(ID)で指定する場合と、button “OK”のように名前で指定する場合があります。

名前で指定できたほうが、何を意味しているのか分りやすくてよさそうなものなのですが、名前で指定できるケースはあまり多くありませんし、だいたい……現在使用中の言語(日本語とか、英語とか)から別の言語環境でScriptを実行するような場合にはまったく動かなくなってしまいます。

このため、IDで指定することが多いのですが……アプリケーションがバージョンアップしたら、そのIDそのものも変わってしまうことが多々あり……GUI部品を検索して実行するような対策を行うケースもあります。

■実際に「プレビュー.app」のGUI Scriptingを行ってみよう

まずは、プレビュー.appで何も画像を開いていない状態で作業をはじめましょう。何もオープンしていない状態と画像をオープンしている状態でWindowの枚数がどう違うか、確認を行います。

何か画像をプレビュー.appでオープンすると、visibleなWindowの枚数が増えます。invisibleなwindowはほかにも何枚か用意しているようなので、ここでvisibleを指定しないで枚数を数えるとひどい目に遭います。

Windowの枚数だけでなく、画像をオープンしていない状態ではメニューの「プリント」の項目が有効になっていません。このため、「プリント」をGUI Scriptingで操作しようとしても、実行できません。このあたりで(オープンされている画像の有無を)判断するという手もあるわけです。

画像をオープンしている状態でメニューから「プリント」を実行できることを確認できたら、プリントダイアログの制御に入ります。

プリントダイアログは、デフォルトの小さいダイアログと拡張ダイアログで切り換えができるようになっており、この切り換えボタンの状態を取得して、「いま、どちらのダイアログが表示されているのか」を調べなければなりません。拡張ダイアログが表示されていないと、用紙サイズなどの詳細な情報にアクセスできません。

sys5.jpg

sys6.jpg

拡張ダイアログを表示して、用紙サイズやプリンタ名などを指定できるようになって、ようやくこれで出来上がった……と、安心していたのもつかの間……標準ダイアログの状態から拡張ダイアログに切り替えた後で、ポップアップメニューの操作が行えない。最初から拡張ダイアログが出ている分には問題ないのに……。

結論からいえば、同じGUI部品でも標準ダイアログと拡張の上でIDが異なっていました。さりとて、GUI部品に名前がついておらず名前による指定ができなかったので……拡張ダイアログが「出ていない」場合には、拡張ダイアログに切り換えたあとで、一度プリントをキャンセルし、再度プリント操作を行って拡張ダイアログ上の各種GUI部品をコントロールする……という方法で対処しました。

ちょっとしたことであれば、GUI Scriptingを少々かじったぐらいで処理できるかもしれません。ただし、そこに柔軟性を加えようとか、確実に動くようにしたい場合には、このぐらいの処理が必要になります。少々極端な例に見えるかもしれませんが、決して珍しいレベルではありません。

PreFab UI Browserを使って状態やIDを確認し、試行錯誤した末に最適な方法を見つけるなど、地道な……何かプログラミングとは別の作業のような気もするのですが、GUI Scriptingの実戦的なノウハウというのは、こういう感じのものです。

2010/02/03 タイマー割り込み処理

AppleScriptには、タイマー割り込みの機能があります。タイマー割り込みとは、一定間隔で処理を行うことで……メインの処理を行っていても(割り込みを行って)、途中でその処理を行います。

タイマー割り込みがあるあたり、単なるスクリプト言語の処理系「らしからぬ」雰囲気ですが……たしかに、タイマー割り込みが活躍するケースは多いので、この機能があるのは助かります。

ただし、いくつか知っておくべきことがあります。

(1)タイマー割り込みは、AppleScriptをアプリケーション形式で保存して実行したときにしか効かない

timer1.jpg

AppleScriptエディタ上で実行したり、Script Menuから呼び出した場合には使用できません。アプリケーションとして保存し、アプリケーションとして起動された場合に限ります。

(2)タイマー割り込みは、「実行後、自動的に終了しない」をオンにしないと意味がない

timer2.jpg

すぐに終わるようにしている場合には、タイマー割り込みは効きません。

(3)タイマー割り込みは、秒単位でしか呼び出せない
0.1秒単位とか、1/64秒間隔で呼び出すといったことはできません。仮にできたとしても、あまり短い間隔で呼び出されると逆にメイン側の処理効率が落ちます(AppleScriptObjCでやってみたら、CPU負荷が増えてしまいました)。

(4)時間が長くかかる割り込み処理を実行中に、後続の割り込み処理を行わせてはいけない
10秒間隔で割り込み処理を呼び出すようにしているときに、実行完了に1分かかる処理を行うような場合……割り込み処理が完了する前に後続の割り込み処理が呼び出されてしまいます。

処理内容に矛盾が生じてしまったり、不具合が生じてしまう可能性があるため、後続の割り込みをブロックし、処理が終わったら割り込みを許可するようにしなくてはなりません。このあたり、割り込み処理の「基本」なのですが……AppleScriptの処理系では面倒を見てくれないので、自前で書いておく必要があります。

スクリプト名:タイマー割り込み
property enableF : true –タイマー割り込みイネーブルフラグ
property intervalSec : 1 –タイマー割り込み発生間隔(秒)
property vList : {“Agnes”, “Albert”, “Alex”, “Bad News”, “Bahh”, “Bells”, “Boing”, “Bruce”, “Bubbles”, “Cellos”, “Deranged”, “Fred”, “Good News”, “Hysterical”, “Junior”, “Kathy”, “Pipe Organ”, “Princess”, “Ralph”, “Trinoids”, “Vicki”, “Victoria”, “Whisper”, “Zarvox”}

–起動処理
on run
  set intervalSec to 5 –割り込み間隔を5秒に変更
  
set enableF to true –割り込みイネーブルフラグをtrue(割り込み可能)に変更
end run

–割り込みサービスハンドラ
on idle
  –割り込み処理メインで処理が終了するまで、タイマー割り込みは許可しない
  
if enableF = true then
    set enableF to false
    
    
idleMain() of me
    
    
–タイマー割り込みメインの処理が終わったら、割り込みを許可する
    
set enableF to true
  end if
  
  
–次回の割り込みを呼び出す相対秒数をリターンする(必須)
  
return intervalSec
  
end idle

–タイマー割り込み処理メイン
on idleMain()
  set aChar to contents of (some item of vList) –乱数選択
  
repeat 3 times
    say “Say Hello to piomal software.” using (aChar as text)
  end repeat
end idleMain

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