Archive for 10月, 2013

2013/10/25 Mavericsで追加になったuseコマンドについて

OS X 10.9, Mavericksで追加になった「use」コマンドについて、ちょっとした注意点を見つけました。

useコマンドには、

 (1)特定アプリケーションへのtellブロックのデフォルト化
 (2)AppleScriptライブラリの使用指定
 (3)AppleScript実行環境(AppleScriptラインタイム)のバージョン指定
 (4)Scripting Additionの使用の有無の指定
 (5)AppleScriptライブラリ中における、Frameworkのinclude指定(AppleScript/Objective-C)

3つ5つの機能があるとのこと(→ 参考)。

ただし、useコマンドが追加になったOS X 10.9.0に搭載されているAppleScriptバージョン2.3よりも大きな値を指定しても、コンパイル(構文確認)時にエラーになります。

また、2.3よりも小さな値を指定しても、それらのバージョンには「useコマンドそのもの」が実装されていないので、指定しても意味がありません。古いOS上にそのScriptを持って行って、useコマンドを受け付けるわけではありませんので。

use4.png

今後、OSのバージョンが上がった時に、(3)が意味を持ってくることになります。

このコマンドを新設した意図は、

 (1)過去との互換性をていねいに維持するよりも、新規機能追加を行う方向に舵を切った
 (2)AppleScript Libraryなど「致命的」な差が10.9で生じたので、10.9以前と切り分けるための安全策

の2つが考えられるのですが、いまのところ判断材料が何もありません。OS X 10.10とその上で動くAppleScriptの内容を確認したときに、明らかになることでしょう。いろいろ考えると、前者(1)であるように思えます。

use1.png
▲バージョン2.3を指定してコンパイル(構文確認)を行うと、問題ない。これより小さい値も指定できるが、そもそも意味がない

use2.png
▲2.3よりも大きな値を指定すると……

use3.png
▲構文確認時にエラーが出ます。ただ、このエラーメッセージはちょっと分りにくいような

2013/10/23 「ほぼApple」がMavericksのAppleScriptObj-Cの変更について掲載

Sal Soghoian+Shane Stanley+αの「ほぼApple」が更新していると見られているmacosxautomation.comにOS X 10.9 Mavericks上のAppleScriptObjCの変更点についてのページが掲載されました

まだ、表記が安定しておらず、このページでは「AppleScriptObj-C」と表記しています。「AppleScriptObjC」「AppleScriptObjective-C」「AppleScript/Objective-C」はだいたい同じものを指していると思って差し支えありません。ここでは、略称のASOCで呼ぶことにします。

ASOCで毎日プログラミングをしている酔狂なユーザーにはきわめて重要な情報が掲載されています。

AppleScriptObjective-C(あえてこう書く)の後方互換性などについての注意点が書かれています。ただし、各文章の記載内容の対象が……

(A)AppleScript Editor上で「Cocoa-AppleScript Applet」を作成した際の環境
(B)Xcode上でCocoa-AppleScriptアプリケーションを作成した際の環境
(C)上記両方とも

のどれなのかが、ひじょーーーーに分りにくい点に要注意です。

まず、10.9上のAppleScriptObjective-Cについては、「_」が「:」になったあたりが変更点。それがすべてのようです。で、どちらの表記でも大丈夫とのこと。10.9のXcode上で「_」の表記を行ってもビルド&実行できるようで(B)。

あと、一度構文確認して保存したScript(A)については、10.9上で「:」の表記を行っても、10.8に持っていくと「_」になって表示されるそうです。後方互換性については注意が(10.8までだけど)払われているとのこと。

10.9上のXcode上で保存した「.applescript」ファイル(B)は、10.8に持って行けないとのこと。まあ、そうでしょうね。単なるテキストですし。

このあたりの互換性維持のためには、つねにXcodeプロジェクト内の.applescriptファイルについては、外部エディタ(AppleScriptObjC Explorer 2あるいはその後継アプリ)で編集するといいよ、というTIPSが掲載されています(Shane、商売上手だな)。

Mavericks上ではXcode 5が必要になり、Xcode 5上で「use garbage collection」のコンパイルオプションは、遠くない将来に無効化されるだろうから、その点に気をつけるべし、との記載もあります。

OS X 10.6, 10.7上では「use garbage collection」のオプションが必要ですが、10.9上のXcode 5上でASOCで開発する場合には、10.6や10.7のサポートが間もなく行えなくなるよ、という話です。

2013/10/23 「ほぼApple」がMavericksのAppleScriptサイトを更新

「THIS WEBSITE IS NOT HOSTED BY APPLE INC」と銘打たれているmacosautomation.comサイト上に、OS X Mavericksの新機能に関する紹介ページがオープンしています(英文)。

同サイトは、AppleのSal Soghoianなのか、あるいはオーストラリアのShane Stanleyが更新されていると見られているサイトで、「Appleではない」といいつつも「ほぼApple」のインサイダーが更新しているものです。

iCloudのサポート

AppleScriptエディタがiCloudをサポート。AppleScriptをiCloudに保存できるようになった。

Code Signing

AppleScriptエディタとAutomatorによってアプリケーション/アプレットをexportする際に、Code signできるようになった(要・Mac Developpersアカウント)。

AppleScript Libraries

既報のとおり。表記がWWDCの時にはAppleScriptObjective-Cだったのが、AppleScript/Objective-Cになっている。どちらが公式表記なのか不明(たぶん後者)。

AppleScript Librariesを指定するuse文

特定のアプリへのtellブロックを宣言できるのと、AppleScript Librariesを指定するuse文の新設。

システムレベルのNotificationサポート

display notificationコマンドが新設され、OSの通知センターにAppleScriptから通知を表示できるようになった。

Speakable-Workflows

従来からあったSpeakable Items Script(音声認識で呼び出せるAppleScript)が拡張され、AutomatorのWorkflowも呼び出せるようになった。ただし、在来型の音声認識エンジンを使っているだけなので、英語オンリーであるうえに認識度も従来どおり。

GUI Scripting

GUI Scriptingが継続採用されているよ、という点を強調。

2013/10/23 Welcome to Maverics (10.9)

Appleの新製品発表会でOS X 10.9 Mavericsが無償アップデートとして提供されることが発表され、すぐにMac App Storeからのダウンロードができるようになりました。

個人的には、β版をずっとサブマシン(MacBook Air 11インチ)で試しており、本Blog掲載Scriptに関しても「10.9savvy」のものは10.9上で実際に動作確認したものです。

Mavericsは、AppleScriptの20年の歴史上もっとも大幅な改変が行われたアップデートになるでしょう。詳細は、Release Notesが出てからになりますが、簡単な変更点を。

AppleScript Library

AppleScriptにはじめてライブラリ機能が付加されました。しかも、AppleScript用語辞書をライブラリに付けることもできるため、OSAXをAppleScriptで書けるようになった、という状態に限りなく近いと思います。

# AppleScriptの命令語をAppleScript自体で拡張できるようになった、ということです。

AppleScript Libraryの内容は通常のAppleScriptでも、AppleScriptObjective-C(AppleScriptObjCとちょっと違う)でも記述可能です。

ある意味、本ブログの位置付けの変更を問われる機能です。Webベースでコードを紹介するのも大事なことですが、共有ライブラリの形でScriptを公開して、ユーザーの底上げを図るという方向性も必要なのかもしれません(ただ、海外のユーザーとも相談して、どこかで集中して行ったほうがよさそう)。

AppleScriptアプレット/Automatorアプリケーション配布時のCode Signing対応

他人にAppleScriptのアプレットを配布したり、Automatorのワークフローを配布するさい、アプリとして書き出す操作を行うときに、Code Signを行えるようになりました。

これまで、AppleScriptでアプレットを作って配布するだけなら、Mac Developper Programへの参加などは行う必要がなかったのですが、どうもこの流れからすると「少なくとも仕事でScriptを書いている人はDevelopper登録しておいたほうがいい(おかないと困ることがある/おくべきである)」状況に。

もちろん、自分の作ったScriptを他人に配布しないとか、アプレットの状態では配布しないといった場合にはこのかぎりではありません。

AppleScriptObjCからAppleScriptObjective-Cへ

WWDCのビデオで何の前置きもなくこの名前が出ていました。「AppleScriptObjC 2.0」という位置付けになるのかと思います。

AppleScriptObjective-Cは、AppleScriptObjCの記法を若干変更したもの、と個人的には理解しています。これまで、Cocoaのメソッドを呼び出すさいには、

 setString_(”ふにゃふにゃ”)

のように、「:」を「_」に置き換える作業が必要でした。

AppleScriptObjective-Cでは、

 setString:”ふにゃふにゃ”

のように、ほぼObjective-Cの記法で書けるようになりました。

ハンドラも、これまでは、

on applicationShouldHandleReopen_hasVisibleWindows_(sender, flag)

のように書いていたものが、

on applicationShouldHandleReopen:sender hasVisibleWindows:flag

のように変わりました。

確認したかぎり、従来のAppleScriptObjCのプログラムも問題なく10.9上で動作していますので、あまり問題はないと思われますが……10.8上でAppleScriptObjCで作っていたプログラムを、AppleScriptObjective-Cに書き換える必要が出てきたらダルいとか、1つのXcodeプロジェクト内にAppleScriptObjCとAppleScriptObjective-Cのプログラムを同居できるのかとか、いろいろ試してみたいところであります。

なお、AppleScriptエディタ上で作れる「Cocoa-AppleScript Applet」のプログラムについては、すでにAppleScriptObjCではなくAppleScriptObjective-Cベースになっているので、「ファイル」>「テンプレートから新規作成」>「Cocoa-AppleScript Applet」と操作して新規作成し、「CocoaAppletAppDelegate.scpt」を表示させることで、AppleScriptObjective-Cの実際のコード例を確認できます。

Objective-CのBlocks(^の入っているやつ)構文までサポートしているのか、いないのか(これのサポートがないと呼び出せない機能が増えてきている)については、やっぱりRelease Notesを待たなくては分りません。

問題は、OS周辺ではなくApple純正アプリ

iWorkが軒並みiOSデバイスとの互換性の名のもとに作り直しになり、「ちょっと似ている感じの別物」になっています。

これまでも、まがりなりにもAppleScriptに対応していたこれらのiWorkアプリが、

Numbers v3.0:全滅(AppleScriptサポート機能なし)
Pages v5.0:ほぼ全滅(AppleScript用語辞書はあるが、予約語がほとんどない。「貧者のInDesign」とまで言われた豊富な機能サポートはどこへ?)
Keynote v6.0:ほとんどダメ(一部機能のみ実装されているが、大幅な後退)

のきなみ、AppleScriptからの「通常の」コントロールができなくなっています(GUI Scripting経由ならOK)。

新しいiWorkアプリが、バージョンアップとともにAppleScript対応機能を拡充させていくのか、あるいはそのままの状態なのかは分りませんが……私の記憶するかぎりでは、はじめて他人にアップデートをおすすめできないiWorkになりました。

OS X 10.8のバグ修正

・dateのバグ(一度stringにしてから再度dateにcastするとおかしくなる)
→ 修正されています

・iCal上のeventがリマインダー上のeventと区別できない
→ 修正されていません

新規追加されたアプリのAppleScript対応

・iBooks:未対応
・マップ:予約語が限定的ながら、AppleScript用語辞書あり。open locationとかopen urlあたりで指定の緯度/経度の場所をマップでオープンできそう。
・プレビュー:open, close, saveが可能に

2013/10/10 AppleScriptObjCで複数項目選択可能なポップアップボタンを

AppleScriptObjCのプログラムで、複数項目が選択可能なポップアップボタンを作ってみました。

作ってみましたといっても、ポップアップボタンは、ボタンをクリックすると表示されるメニュー項目のうち、選択状態にあるものをボタンのタイトルとして表示するというものであり、複数項目の選択はできません。

mpop9.png

できないながらも、どーにかして複数項目選択できるようにしなくてはならない(このへん、海外のクライアントの要望)ということで、NSPopupButtonをそのままで使うことは無理です。

そこで、NSPopupButtonをクリックすると表示されるメニューの方をなんとかしてしまえ、ということになります(このあたりまでは、海外のサイトでもよく話が出ている)。

メニューとしてNSCustomViewとかNSBoxあたりを指定する、というのがだいたいのオチなのですが……実際に試してみると、言うほど簡単ではありません。

さらにメニューに表示させる項目の数を動的に変化させたいという話もあり、メニューとして表示させるビューの大きさの制御とか、NSMatrixの位置をNSCustomViewやNSBox内のどこを基準に寄せるかといった話をクリアしなくてはなりません。

popup1.png

結局、それが面倒だったので、NSMatrixを直接メニューとして指定して表示させるようにしてみました。

popup2.png

これなら、NSMatrixを載せている「下地」との位置関係やサイズの調整などを一切行わなくてすむために、楽にできました。

そこまでクリアしても、まだ大変なことが続きます。

メニューで複数項目を選択できるところまではなんとかクリアしたのですが、その選択内容をポップアップボタンのタイトルに指定すると……メニュー内に新たな選択項目として追加されてしまうのでした。

……いろいろ思い悩んだ結果、クライアントには「勘弁してください」と泣きつき、この「複数項目選択可能なポップアップボタン」はお蔵入りに。

正確にいうと、ポップアップボタンにわざわざしなくても、ウィンドウ上にふつーにチェックボックスとして並べれば、その方が確実だしよいのではないか、という提案を行いました。

ところが、その翌日にはなんとか動くところまで持って行けました。結局、ポップアップボタンに選択状態を表示させるとメニューに追加されてしまうので、選択内容を別の部品に表示させることに。

枠や下地の描画をやめて、マウスクリックを無視するように設定して、ポップアップボタンの上に載せておけば、まるでポップアップボタンに選択状態を表示している……かのように見えるはずです。

mpop1.png
▲ビルドして起動したところ

mpop2.png
▲「+」ボタンをクリックしてテーブル内の行を追加し、それぞれにデータを入力

mpop3.png
▲ひととおりメニューに表示する項目を入力し終わったら、「Reflect」ボタンをクリック。これで、テーブルの内容をもとにポップアップメニューを動的に作成

mpop4.png
▲テーブル内容をもとに作成されたポップアップメニュー

mpop6.png
▲メニュー内の複数項目を選択できる

mpop7.png
▲複数選択した状態を別のテキストフィールド上に表示

→ Xcodeプロジェクトのダウンロード(69KB)

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– ViewInMenu

– Created by Takaaki Naganoya on 2013/10/08.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
  property pu : missing value – IBOutlet for the popUpButton
  
property item1 : missing value
  
property mat : missing value – IBOutlet for the matrix of NSLabels
  
  property theData : {} – the table data
  
property theArrayController : missing value
  
property aTable : missing value
  
  property aTextF : missing value
  
  
  
  
  
  on applicationWillFinishLaunching_(aNotification)
    
    set theData to {}
    
    set item1 to current application’s NSMenuItem’s alloc()’s initWithTitle_action_keyEquivalent_(“”, missing value, “”)
    
item1’s setView_(mat)
    
item1’s setTarget_(me)
    
pu’s removeAllItems()
    
pu’s |menu|()’s addItem_(item1)
    
    aTextF’s setStringValue_(“”)
    
  end applicationWillFinishLaunching_
  
  
  
  
  
  on applicationShouldTerminate_(sender)
    return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
  
  
  
  on matrixClick_(sender) – IBAction for the matrix
    
    aTextF’s setStringValue_(“”)
    
    tell theArrayController
      set outList to arrangedObjects() as list
    end tell
    
    set aLen to length of outList
    
set aList to {}
    
    
    repeat with i from 0 to (aLen - 1)
      
      set aTmpVal to mat’s cellAtRow_column_(i, 0)’s integerValue()
      
set aTmpVal to aTmpVal as number
      
      if aTmpVal is equal to 1 then
        
        set aTmpText to mat’s cellAtRow_column_(i, 0)’s title()
        
set the end of aList to aTmpText
        
      end if
      
    end repeat
    
    set aText to retArrowText__(aList, “, “)
    
set aText to aText as string
    
    aTextF’s setStringValue_(aText)
    
  end matrixClick_
  
  
  
  
  –Array Controllerから動的にメニューを作成する
  
on buttonClick_(sender) – IBAction for the button
    
    set outList to {}
    
    tell theArrayController
      set theList to arrangedObjects() as list
    end tell
    
    log {“theList”, theList}
    
    repeat with i in theList
      set j to contents of i
      
set jj to aTitle of j
      
set jj to jj as string
      
set the end of outList to jj
    end repeat
    
    set aLen to length of outList
    
    
    mat’s renewRows_columns_(aLen, 1)
    
mat’s sizeToCells()
    
    repeat with i from 0 to (aLen - 1)
      set aStr to contents of item (i + 1) of outList
      
set aStr to aStr as string
      
mat’s cellAtRow_column_(i, 0)’s setTitle_(aStr)
    end repeat
    
    
    aTextF’s setStringValue_(“”)
    
  end buttonClick_
  
  
  –リストを任意のデリミタ付きでテキストに
  
on retArrowText__(aList, aDelim)
    
    set aText to “”
    
set aLen to length of aList
    
set aCount to 1
    
    repeat with i in aList
      set j to i as string
      
      if aCount < aLen then
        set aText to aText & j & aDelim
      else
        set aText to aText & j
      end if
      
      set aCount to aCount + 1
      
    end repeat
    
    return aText
    
  end retArrowText__
  
  
  
  
end script

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

2013/10/06 リストの左右ローテーション

リスト(配列)型変数の要素(item)の左右ローテーションを行うAppleScriptです。

データのローテート(回転)というのは……

元データ:
–> {1, 2, 3, 4, 5}

左ローテート1回:
–> {2, 3, 4, 5, 1}

右ローテート1回:
–> {5, 1, 2, 3, 4}

という処理です。そういう処理が必要になったので、手っ取り早く作ってみました。

rotate.png
▲回転系のInterfaceをAppleScriptObjCで作っていたときに、必要になりました

左ローテートと右ローテートのサブルーチンに、処理対象となるリストと、各ローテーションの回数を数値で指定して指示するようになっています。

スクリプト名:リストの左右ローテーション
set aList to {“”, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”}

set aRes to rotateLeft(aList, 3)
–> {””, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”}

set bRes to rotateRight(aList, 4)
–> {””, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”, “”}

–リストの左ローテーション
on rotateLeft(aList, shiftCount)
  set aLen to length of aList
  
  
repeat shiftCount times
    set aCarry to contents of first item of aList
    
set aList to items 2 thru -1 of aList
    
set the end of aList to aCarry
  end repeat
  
  
return aList
  
end rotateLeft

–リストの右ローテーション
on rotateRight(aList, shiftCount)
  set aLen to length of aList
  
  
repeat shiftCount times
    set aCarry to contents of last item of aList
    
set aList to items 1 thru -2 of aList
    
set the beginning of aList to aCarry
  end repeat
  
  
return aList
  
end rotateRight

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