Archive for the 'ダイアログ表示(dialog)' Category

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/09/29 record型で結果が返ってくる内容の取り出し方【超基礎】

【ご注意】本エントリは、分かっていない方向けの説明用です。ふつーに分かっている方々にはあらためて参考になるような情報は含まれていません。

Twitter上で「OS X 10.9にしたらAppleScriptの命令の実行結果の返り順が変わった。バグだ」という投稿を見かけました。

よくよく聞いてみると、それはdisplay dialogコマンド(default answer指定時の、文字入力ダイアログ)の結果を(record形式データ)てきとーに取り出して「順番が違う、バグだ」と言っているのでした。

AppleがOSに添付しているAppleScriptをそのまま使ったようで……

apple_sample.png
▲こういう記述は恥ずかしいです、的な記述のオンパレード。読みにくいうえに恥ずかしい。部分的に書いてはダメな記述もある(recordをlistにcastすんな!)。メーカーがOSに添付しているScriptにこれはないだろー(ーー;

そうした(OSについてくる)コードの品質はいまひとつなのと、どーせ英語環境でしかチェックしていないのと、Apple弁はなまりが強い(theとかresultとかやたらと使いまくる)ので、あれを読んで理解しろとかいう方が無茶な感じではあります。

# Adobeのアプリケーションのように、同じオブジェクトの属性値を求めて、返り値内のラベルの順番が変わるとかいうのは、かなり問題ですが、この(↑)程度なら問題はないレベルです。

そこで、実際に解説を。

dsp.png

ダイアログを表示して文字入力を行うのは、だいたいこんな感じです。ダイアログのタイトルとか、ダイアログに対するアイコン表示指定なんかもできますが、それは省略しています。

スクリプト名:dialog0
set a to display dialog “なんか入力して” buttons {“OK”} default button 1 default answer “”

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

ここ(↑)に掲載しているScriptは、WebブラウザからAppleScriptエディタ(10.10からはスクリプトエディタに改称)に直接コード内容を転送するURLリンクを含んでいます(そのまま実行する機能はないのでセキュリティホールにはならないはず)。

MacのWebブラウザで「▼新規書類に」をクリックすると、AppleScriptエディタが立ち上がって(セキュリティ設定次第では、確認ダイアログが出る場合も)新規Scriptが作成されてそこに内容が転送されます(iOSやWindowsなど他のOSではURLリンクは無効です)。

ここで返ってくる値は、

スクリプト名:dialog1
set a to display dialog “なんか入力して” buttons {“OK”} default button 1 default answer “”
–> {button returned:”OK”, text returned:”あああああ”}

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

のようになります。{button returned:”OK”, text returned:”ああああ”}といった内容です。

この内容が何なのかを調べると……

スクリプト名:dialog2
set a to display dialog “なんか入力して” buttons {“OK”} default button 1 default answer “”
class of a
–> record

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

recordと返ってきます。recordはラベルのついた値の組み合せで構成されるデータで、ここでは「button returned」と「text returned」の2つのラベルがついたデータのセット(record)が返ってきていることが分かります。

recordから値を取り出すには、ラベルを指定すればOKです。また、record型のデータ内では、ラベルの順番などはとくに意識しないで処理できます。

で、正しくデータを取り出すにはそれぞれラベルを指定してあげる必要があるので、このような処理になります。

スクリプト名:dialog3
set a to (display dialog “なんか入力して” buttons {“OK”} default button 1 default answer “”)
–> {button returned:”OK”, text returned:”あああああ”}
set bText to button returned of a –押されたボタン上のラベルが文字列で入る
–> “OK”
set iText to text returned of a –ダイアログに入力されたテキストが入る
–> “ああああ”

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

2010/11/13 文字入力ダイアログ(伏せ字表示)

display dialogで文字入力を求めるさい、パスワードなどの「そのまま表示されては困る」ようなものを入力させる際に、入力内容をすべて「・」に置き換えて伏せ字表示する記述例です。

dialog_secur.jpg

「with hidden answer」はずいぶん昔に追加されたオプションですが、どうもご存じでない方が多いようなので。

この伏せ字表示の入力ダイアログからは、コピー&ペーストでその内容を取り出すことはできませんし、GUI Scripting経由で入力内容を取り出すこともできません。Mac OS Xの仕様上そうなっているわけですが、そんなことができたらセキュリティホールになってしまうため、これらの操作が「できない」のが正しい挙動です。

スクリプト名:文字入力ダイアログ(伏せ字表示)
display dialog “パスワードを入力してね” default answer “” buttons {“OK”} default button 1 with hidden answer

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

2010/06/19 ペアになる値のセットを選択

ペアになる値のセットを選択するAppleScriptです。1,2,3の値のリストに対して、赤、青、緑のそれぞれの色を割り当てる場合に、1に対するものはどれか、2に対するものはどれか……と、ユーザーに尋ねて対応リストを作成します。

pair1.jpg

pair2.jpg

pair3.jpg

pair4.jpg

最後に、ペアを構成するリストの最後の項目については、組み合わせパターンが残りのものしか存在しないため、あえてダイアログで確認せずにペアを決定します。

スクリプト名:ペアになる値のセットを選択
set aList to {“10W”, “20W”, “30W”}
set bList to {“あか”, “あお”, “きいろ”}

set resPair to {}
repeat ((length of aList) - 1) times
  set aRes to choose from list aList with prompt “以下の内容から選択”
  
if aRes = false then return
  
set aaRes to contents of first item of aRes
  
  
set bRes to choose from list bList with prompt “「” & aaRes & “」に該当するものを以下から選択”
  
if bRes = false then return
  
set bbRes to contents of first item of bRes
  
  
set the end of resPair to {aaRes, bbRes}
  
  
–サブルーチン「deleteNumfromListByDelList」の仕様で、削除対象データをリストで渡す
  
set aList to deleteNumfromListByDelList(aList, {aaRes}) of me
  
set bList to deleteNumfromListByDelList(bList, {bbRes}) of me
  
end repeat

–最後の項目はユーザーに尋ねなくても、残ったものを使えばよい
set the end of resPair to {contents of first item of aList, contents of first item of bList}

resPair
–> {{”10W”, “あか”}, {”20W”, “あお”}, {”30W”, “きいろ”}}

–指定のリストから削除指定リストに入っているアイテムを削除する
–こちらは、deleteListに入っているデータに該当するものを削除する
on deleteNumfromListByDelList(aList, deleteList)
  set newList to {}
  
repeat with i in aList
    set j to contents of i
    
if j is not in deleteList then
      set the end of newList to j
    end if
  end repeat
  
  
return newList
end deleteNumfromListByDelList

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

2010/01/17 リストから選択してアイテム番号を返す〜複数選択対応

choose from listで複数選択を行いつつ、選択した項目がそれぞれリストの何アイテム目かの情報を返すAppleScriptです。

以前に、複数選択ではないバージョンは作ってあったのですが、Omni Outlinerから選択部分を取得するAppleScriptを作成する際に、即興で作ったものです。

スクリプト名:リストから選択してアイテム番号を返す〜複数選択対応
set aList to {“red”, “blue”, “green”, “white”}
set aMes to “項目を選択してください(Command-クリックで複数選択可能)”
set aRes to retMultipleItemFromListByItemNo(aList, aMes) of me

–リストから選択してアイテム番号を返す(複数項目選択対応)
on retMultipleItemFromListByItemNo(aList, aMes)
  set aRes to choose from list aList with prompt aMes with multiple selections allowed
  
if aRes = false then return 0
  
  
set hitList to {}
  
repeat with i1 in aRes
    set aRes to contents of i1
    
set hitNum to 1
    
repeat with i in aList
      set j to contents of i
      
if j is equal to aRes then
        exit repeat
      end if
      
set hitNum to hitNum + 1
    end repeat
    
set the end of hitList to hitNum
  end repeat
  
return hitList
end retMultipleItemFromListByItemNo

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

2008/12/11 月あるいは期間入力サブルーチン

処理対象の月(年/月)の入力を求めるサブルーチンです。単月だけでなく、範囲を「…」で指定することも可能で、「2008/3…4」とか「2008/12…2009/3」といった指定が可能です。

dialog.jpeg

返り値は、範囲の開始と終了がdateオブジェクトで返ってきます。

「2008/12」と指定した場合、{date “2008年 12月 1日 月曜日 0:00:00 AM”, date “2009年 1月 1日 木曜日 0:00:00 AM”}。

「2008/3…7」と指定した場合、{date “2008年 3月 1日 土曜日 0:00:00 AM”, date “2008年 8月 1日 金曜日 0:00:00 AM”}。

「2008/12…2009/3」と指定した場合、{date “2008年 12月 1日 月曜日 0:00:00 AM”, date “2009年 4月 1日 水曜日 0:00:00 AM”}。

もともとは、iCalに重複登録されたイベントの削除を行うためのサブルーチンだったので(mobile meとかiPhoneとかEntourageなどとあちこちシンクロしていたらそうなったらしい)、その削除対象を指定するために作ったものです。返り値の終了日時がびみょーに1秒ほどオーバーしているところが気になる(すでに翌日になっている)場合には、終了日時から1秒引いておくなどして使ってみてください。

スクリプト名:月あるいは期間入力サブルーチン
指定期間のイベントを取得
set todayDat to current date
set targYear to (year of todayDat) as string
set targMonth to (month of todayDat as number) as string
set aTarg to text returned of (display dialog "重複イベントの削除対象月は?(YYYY/MM)" default answer (targYear & "/" & targMonth))
set {sDate, eDate} to getRangeFromDateText(aTarg) of me

on getRangeFromDateText(aText)
  if aText does not contain "" then
    普通にYYYY/MM指定のみ行った場合
    
set sDate to (aText & "/1")
    
set eDate to (date sDate) + (getMlen(year of (date sDate), month of (date sDate)) of me) * days
    
set sDate to date sDate
    
  else
    期間を「YYYY/MM…YYYY/MM」  で指定した場合
    
set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to ""
    
set tList to text items of aText
    
set AppleScript’s text item delimiters to curDelim
    
    
set item1T to contents of item 1 of tList
    
set item2T to contents of item 2 of tList
    
    
set sDate to date retYYYYMDD(item1T) of me
    
set eDate1 to date retYYYYMDD(item2T) of me
    
set eDate to eDate1 + (getMlen(year of sDate, month of eDate1) of me) * days
  end if
  
  
return {sDate, eDate}
end getRangeFromDateText

on retYYYYMDD(aText)
  if aText contains "/" then
    set bText to aText & "/1"
  else
    set thisYear to (year of (current date)) as string
    
set bText to thisYear & "/" & aText & "/1"
  end if
  
return bText
end retYYYYMDD

指定月の長さを得る(日数)
on getMlen(aYear, aMonth)
  
  
set aYear to aYear as number
  
set aMonth to aMonth as number
  
  
set aDat to (aYear as text) & "/" & (aMonth as text) & "/1"
  
if aMonth is not equal to 12 then
    set eDat to ((aYear as text) & "/" & (aMonth + 1) as text) & "/1"
  else
    set eDat to ((aYear + 1) as text) & "/" & (1 as text) & "/1"
  end if
  
  
set eDat to date eDat
  
set eDat to eDat - 1
  
  
set mLen to day of eDat
  
return mLen
  
end getMlen

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

2008/09/09 choose from listのデフォルト値を指定する(複数指定)

リストの中からユーザーに選択を求める「choose from list」で、複数のデフォルト選択値を指定するScript記述例です。

choosefromlist2.jpeg
(more…)

2008/09/07 リストから選択してアイテム番号を返す

非常によくある処理、choose from listでリストからの選択を求め、選択された項目のリスト番号を返します。本当は、choose from list命令に選択されたリスト項目の番号を返すようなオプションがあるべきなのですが、ないのでみんなこのように組んでいるわけです。
(more…)

2008/09/07 choose from listのデフォルト値を指定する

リストの中からユーザーに選択を求める「choose from list」で、デフォルト選択値を指定するScript記述例です。あまり使う機会は多くはないのですが、とりあえず。

choosefromlist.jpeg

スクリプト名:choose from listのデフォルト値を指定する
set choices to {"ひよこ", "うし", "ぴようるふ", "にわとり"}
set default_items to {"ぴようるふ"}
choose from list choices default items default_items

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