Making Application using ASOC

AppleScriptObjC の覚書で色々と気がついた所を書きましたが、それらは実際に触ってみないと分からないことだったりします。Hello World を表示するアプリケーションを作りながら、色々と確認してみます。

Xcode や Interface Builder の使い方は、ここでは取り扱いません。それらは既に優秀な解説があります。知識としては、Cocoa はじめの一歩から手に入る Become An Xcoder ぐらいの知識が必要です(後は練習問題 12 ぐらいまでができれば大丈夫です)。訳者様に感謝です。

HelloWorld アプリケーションの UI は以下のようになります。

ASOCHelloWorld_UI.png

では、多くを端折っていきます。Xcode で Cocoa-AppleScript Application の新規プロジェクトを作成したら、アプリケーションのコントローラーを追加します。「ファイル」メニューの「新規ファイル...」から AppleScript class を選択します。NSObject のサブクラスにしておきます。ファイル名は AppController としておきます。

ASOCHelloWorld_AddFile.png

AppController.applescript を開き、アウトレットとアクションを追加します。

script AppController
    property parent : class "NSObject"

    -- Outlets
    property _window : missing value
    property textField : missing value
    property helloButton : missing value

    -- Actions
    on greeting_(sender)
        textField's setStringValue_("Hello, World")
    end greeting_
end script

アウトレットは property で宣言し、値は missing value にしておきます。アクションは引数を一つ取るハンドラとして定義します。引数を取るのでアンダースコアが必要です。Objective-C で書くなら次のようになります。

IBOutlet NSWindow *window;
IBOutlet NSTextField *textField;
IBOutlet NSButton *helloButton;

- (IBAction)greeting:(sender);

これらは通常ヘッダファイル(.h)の方に記述しますが、ASOC では、一つのスクリプトオブジェクトがヘッダファイル(.h)と実装ファイル(.m)を兼ねています。だから、上記のように書けてしまいます。あと、型の指定は当然できませんし、IBOutlet や IBAction などのキーワードも ASOC では利用できません。

なら、Interface Builder はどうやってそれらを識別するのかというと、識別されません。Interface Builder 上では全てが表示されます。ハンドラやプロパティが増えると、いささか鬱陶しいことになります。

ということで、MainMenu.xib を開いて Interface Builder で UI を作成し、アウトレットとアクションを接続します。

まず、MainMenu.xib のウィンドウに Library パレットから Object を追加します。

ASOCHelloWorld_AddObject.png

この Object を選択したまま、Inspector パレットで Class を AppController にします。

ASOCHelloWorld_ClassInspector.png

これで Interface Builder で AppController で定義したアウトレットとアクションが接続できるようになります。

ASOCHelloWorld_TargetAndAction.png

このような感じになります。保存したら Interface Builder での作業は終わりです。Xcode に戻って「ビルドと実行」を行います。アプリケーションが起動したら、ボタンを押してみてテキストフィールドに「Hello, World」と表示されるのを確認してください。

ASOCHelloWorld_UI.png

以上の作業は、AppleScript Studio での作業とは全く異なります。というより、Cocoa/Objective-C でアプリケーションを作るのとほとんど同じです。その気になれば、バインディングも使えます。

では、このアプリケーションを叩き台に色々と調べてみます。まず、スクリプトオブジェクトの外にハンドラを定義します。

on greeting()
    display dialog "Hello, World"
end greeting

greeting_ からこのハンドラを呼び出すように変更します。

on greeting_(sender)
    -- textField's setStringValue_("Hello, World")
    greeting()
end greeting_

実行してもエラーになると思います。これはどのようにしても無理なようで、スクリプトオブジェクト外にあるハンドラは呼び出すことができません。では、どうするかというとスクリプトオブジェクトにしてしまいます。

script HelloWorldDialog
    on greeting()
        display dialog "Hello, World"
    end greeting
end script

このようにしておけば、通常のようにスクリプトオブジェクトのハンドラを利用できます。

on greeting_(sender)
    -- textField's setStringValue_("Hello, World")
    HelloWorldDialog's greeting()
end greeting_

つまり、これはクラスの定義ではありません。スクリプトオブジェクトの定義です。ゆえに、このスクリプトオブジェクト内ではメソッドを作成するように引数の数だけアンダースコアは必要ありません。

しかし、下手にこのスクリプトオブジェクトの親を指定してしまうと、クラスとして扱われるようになってしまいます。

script HelloWorldDialog
    -- NSObject などを継承するとクラスになる
    property parent : class "NSObject"

    on greeting()
        display dialog "Hello, World"
    end greeting

    on greeting_(yourName) -- 引数があるのでアンダースコアが必要になる
        display dialog "Hello, " & yourName
    end greeting_
end script

スクリプトオブジェクトをそのまま利用するか、クラスとして利用するか。どちらも一長一短です。クラスとして利用するなら、別のファイルにしていても property で指定するだけでそのクラスのメソッド(ハンドラ)が利用できます。が、メソッドの命名規則は Objective-C に準じます。

他方、スクリプトオブジェクトとして利用すると、Objective-C の命名規則から逃れられますが、別ファイルにしたときに読み込みが面倒になります。awakeFromNib などを利用して読み込みますが、path to me は利用できないので、NSBundle を利用します。

on awakeFromNib()
    -- load script object.
    tell NSBundle's mainBundle()
        set theFile to pathForResource_ofType_("HelloWorldObject", "scpt")
    end tell
    set HelloWorldObject to (load script (theFile as text) as POSIX file)
end awakeFromNib

AppleScript の me は ASOC ではクラス自身を表すので、path to me は利用できません。また、上記では pathForResourceofType が返した NSString を AppleScript の text に型変換しています。AppleScript では NSString をそのまま利用できないようです。

Cocoa/Objective-C では色々と便利な関数が用意されています。それらは、ASOC では利用できません。例えば、矩形を表す NSRect を作成する NSMakeRect といった関数は使えません。これらはどのように作るのかというと、AppleScript の record クラスで代用します。

set rect to {origin:{x:10, y:10}, |size|:{|width|:100, height:100}}

このような record を作り、Objective-C のメソッドに渡せばいいようです。NSRange、NSSize、NSPoint なども同様です。NSLog は AppleScript の log 命令で代用できます。

アプリケーションを作成している時、特定のクラスを利用したい時があります。先ほどの NSBundle のように。Cocoa/Objective-C なら特に意識もしないで NSBundle のクラスメソッドを利用できたりするのですが、ASOC の場合、利用したいクラスを property で指定しておく必要があります。具体的には次のようになります。

property NSBundle : current application's class "NSBundle"

この property をどこで宣言しておくかというと、クラス(スクリプトオブジェクト)の外か、クラスの property として宣言します。

-- スクリプトのトップで宣言
property NSBundle : current application's class "NSBundle"

script AppController
    property parent : class "NSObject"
    -- クラスで宣言
    -- property NSBundle : current application's class "NSBundle"
end AppController

これで NSBundle を利用できるようになります。Objective-C の import のようなものかと思うけど、そうではないようで、一気にクラスを参照したいがために AppKit.h や Cocoa.h を指定してもだめなようです。

property AppKit : class "AppKit" -- 利用できない

このようにクラスを property で参照しておくと、クラスが持っている定数等が利用できるようになります。

-- NSBundle's notification key
-- log NSBundle's NSBundleDidLoadNotification
log current application's NSBundleDidLoadNotification

その際、current application を通して定数を指定するようにします。コメントアウトしている方は利用できません。NSWindow の初期化処理を参考に。

script CustomWindow
    property parent : class "NSWindow"

    on initWithContentRect_styleMask_backing_defer_(contentRect, aStyle, bufType, frag)
        continue initWithContentRect_styleMask_backing_defer_(contentRect, ¬
            current application's NSTexturedBackgroundWindowMask, ¬
            current application's NSBackingStoreBuffered, ¬
            false)

        return me
    end initWithContentRect_styleMask_backing_defer_
end CustomWindow

横長になるのは AppleScript の宿命です。このように利用します。初期化処理ではスーパークラスの初期化処理を最初に呼び出しますが、ASOC では continue を使ってスーパークラスの初期化を行います。また、初期化の最後に Objective-C では self を返しますが、ASOC では me を返します。

Cocoa/Objective-C のメソッドの中には AppleScript の予約語になっているものがあります。例えば、size や width もそうですし、set や center といった語は AppleScript で定義されています。NSWindow にはウィンドウをディスプレイの真ん中に移動させる center というメソッドがありますが、これを利用するには | でメソッドを囲むようにします。

_window's |center|()

ちなみに上記は以下のようにも記述できます。

tell _window to |center|()
|center|() of _window

どの書き方でも構いません。Objective-C は以下のようにメソッドを連続して記述することがあります。

NSString *string = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];

ASOC で同じように記述するなら、s を使った以下の書き方が分かりやすいかもしれません。

set str to NSString's alloc()'s initWithData_encoding_(theData,current application's NSASCIIStringEncoding)'s autorelease()

横長なのは Objective-C でも AppleScript でも同じですね。今回は Objective-C の視点から ASOC を見てみました。ASOC のいいところは、AppleScript で Objective-C のような構文を記述しながら、既存の AppleScript を混在できるところにあります。

on awkeFromNib()
    tell application "Finder"
        set loc to insertion location as text
        textField's setStringValue_(loc)
    end tell
end awakeFromNib

Cocoa/Objective-C ほど面倒ではなく、AppleScript Studio ほどイライラせずにすみます。PyObjC のプロジェクトテンプレートが Xcode 3 からなくなったのには驚きましたが(古い Xcode から移植しましたら使えました)。ASOC がいつまでサポートしてくれるのでしょう。AppleScript Studio や PyObjC に比べると、サポートの手間は少ないと思うのですが。

AppleScriptObjC 覚書

いまさら感がありありなのですが、AppleScriptObjC。通称、ASOC。Mac OS X 10.6 Snow Leopard とともに紹介されたので、既に登場から 1 年以上経っているわけですが。そろそろ、資料も揃ったことだろうとネット上を検索してみるが...これがなんとも少ない。

困ったものです。

日本で AppleScriptObjC をキャッチアップしているのは唯一ぴよまるソフトウェアさんぐらいしか見当たりません。

...困ったものです。とりあえず、Mac OS X Automation で公開されているチュートリアル動画を参考にいくつかアプリケーションを作ってみました。

アプリケーションを作っているときに気がついたことを箇条書きで書いていきます。

  • ASOC でアプリケーションを作るのは、Cocoa/Objective-C でアプリケーションを作るのと同じ。
  • AppleScript Studio とは異なる。
  • AppleScript の知識より Cocoa/Objective-C の知識が必要。
  • ASOC は、Cocoa/Objective-C でアプリケーションを作成したことがあるなら、すぐに理解できる(と思う)。
  • ASS アプリケーションを ASOC にそのまま移植するのは難しい。
  • 逆に Cocoa/Objective-C アプリケーションを ASOC に移植するのが簡単かというと、諸般の事情により一筋縄にはいかない。
  • ASOC は Cocoa の機能を全て利用できる...といったことを言われるが、そんなことはない。現状では利用できないものも多々ある。例えば、モーダルダイアログは利用できるが、シートは利用できない。

次にプログラムを書いているときに気がついたことなど。

  • ASOC のプロジェクトには登録されてるファイルはアプリケーションのデリゲートとして登録されている。
  • ASOC のクラスはヘッダファイル(.h)と実装ファイル(.m)がない。
  • ASOC のクラスは一つのスクリプトファイル(というより、スクリプトオブジェクト)で定義する。
  • スクリプトオブジェクト = クラスなので、一つのスクリプトファイルで複数のクラスを定義できる。
  • 継承は AppleScript の parent 属性を利用する。
  • テンプレートでは parent に NSObject が指定されているが、実はなくてもいい。スーパークラスに NSObject が密かに指定されている...みたい(継承をたどっていくと BAGenericObject に突き当たる)。
  • 親の指定がされていない AppleScript のスクリプトオブジェクトを継承元に指定することができる。
  • 継承元が指定されていない AppleScript のスクリプトオブジェクトをクラスとして扱うことができる。
  • 継承元が指定されていない AppleScript のスクリプトオブジェクトをクラスとして扱えば、クラスとして振る舞う。AppleScript のスクリプトオブジェクトとして扱えば、スクリプトオブジェクトとして振る舞う。
  • クラスで利用する変数(クラス変数やインスタンス変数)は AppleScript の property で定義する。
  • クラスのメソッドは AppleScript のハンドラで定義する。
  • Objective-C のメソッドはコロンで引数を表すが、ASOC ではアンダースコアで表す。drawRect: は drawRect_ になる。
  • このため ASOC 内でメソッドを定義した時、引数の数だけアンダースコアが必要になる。2 つの引数を取る append(x, y) があったとする。これは、ASOC のクラス内では appendWithX_andY_(x,y) といった形になる。Objective-C でメソッドを定義するのと同じだ。
  • メソッドの返り値や引数に型の指定はない。
  • Objective-C に用意されているメソッドの中には AppleScript で予約されているものがある。set や center 等。それらのメソッドを利用するには | でメソッドを囲む。
  • クラス内で他のクラスを利用するには、そのクラスを property を利用して参照する。
  • クラス(スクリプトオブジェクト)定義の外でハンドラを定義しても利用できない。Objective-C の関数のようなことはできない。
  • スーパークラスのメソッドは、continue を使って呼び出す。
  • NSRect や NSSize、NSPoint 等は AppleScript のレコードで定義できる。
  • 引数に NSArrayを取る Objective-C のメソッドには AppleScript の list クラスを渡すことができる。
  • 引数に NSDictionary を取る Objective-C のメソッドには AppleScript の record クラスを渡すことができる。
  • NSString と AppleScript の text は同じではない。引数に NSString を取る Objective-C のメソッドには AppleScript の text クラスを渡すことができる。が、NSString を AppleScript で利用するには型変換が必要(な時がある)。
  • Objective-C のメソッドは ASOC で利用できるが、簡易に利用するために用意されている関数群(NSMakeRect() や NSLog())等は、ASOC では利用できない。
  • NSTimer や通知などに利用するセレクタは文字列で指定する。その際、引数はコロンで表す。アンダースコアではない。
  • Objective-C の nil は AppleScript の missing value で代用。
  • path to me は利用できない。ASOC では me は自身のクラスを表す。
  • ASOC は既存の AppleScript の言語仕様を拡張しているわけではない。利用できるのは AppleScript 言語のみ。これが、いくつかの面倒を引き起こす。例えば、論理積や論理和を取りたいとき。C 言語の & や | は利用できない。
  • ASOC で Objective-C のカテゴリやプロトコルを定義することはできない。

と、思いつくままに羅列。読んだだけでは意味が分からないものもあると思いますが、細かいことはまた次回。


Snow Leopard で Dock の使い勝手が良くなったのだけど...

Snow Leopard から Dock の設定(「システム環境設定」にある)で「ウィンドウをアプリケーションアイコンにしまう」という設定が追加されました。従来まではウィンドウをしまうと Dock にずらずらっとウィンドウが並んで格納されていました。これだと Dock がウィンドウで埋められてみっともないことになっていました。

Snow Leopard から追加された「ウィンドウをアプリケーションアイコンにしまう」という設定を有効にすると、ウィンドウが Dock 内にある各アプリケーションに格納されるようになります。これで、Dock がいろんなアプリケーションのウィンドウで埋め尽くされることがなくなって、快適...なはずなのですが、問題はこのようにしてアプリケーションに格納したウィンドウをすべて元に戻したいとき。

ちょっと調べただけなのですが、どうもアプリケーションアイコンに格納したウィンドウ全てを一度で元に戻す方法はないようで...(調査不足かもしれませんが)。

最初のうちはウィンドウを一つずつ手動で元に戻していたのですが...これが、面倒。で、Dock に格納しているウィンドウをすべて元に戻す AppleScript を書く。

Script Editor で開く

tell application id "com.apple.systemevents"
    set front_application to a reference to (processes whose visible is true and frontmost is true)
    if (count front_application) is 0 then return
    set app_id to bundle identifier of (item 1 of front_application)
end tell

tell application id app_id
    try
        set window_list to a reference to (windows whose miniaturized is true)
        if (count window_list) is 0 then return
        set miniaturized of window_list to false
    on error msg number num
        activate
        display dialog (num & ": " & msg) as text with icon 1
    end try
end tell

こういうとき、System Events があると助かります。特定のアプリケーションだけではなく、すべてのアプリケーションを対象に処理を行うことができるから。

最前面にあるアプリケーションに対して実行しますが、アプリケーションによってはエラーがでるかもです。とりあえず、うちでは使えているので無問題。

application id を利用しているので Mac OS X 10.5 以降で利用可能。それ以前の環境では application id を指定している部分を変更すれば、利用できます。

スクリプトメニューなどに入れてご笑味くださいませ。

Google のコマンドラインツールを使ってみる

Google から Google の各種サービスをコマンドラインから操作できるツール(GoogleCL)が出たようで、さっそく試してみました。

とりあえず、インストールした環境などを...。

  • Mac OS X 10.6.4
  • Python 2.6.1(Mac OS X にインストールされているもの)
  • gdata 2.0.10

python や Google Data API は、日常的に利用しているので環境が整っているのだけど、そうでないと Python から利用できる Google Data API(gdata)のライブラリのインストールから始める必要があります。Python が必須ですが、これは Mac OS X に最初から入っているもので構いません。

Python は必要だけど、GoogleCL を利用するために Python の知識はとりあえず必要ありません。Python は GoogleCL が背後で利用しているだけです。

gdata for python のインストール

以前のことなので詳細は忘れてしまいましたが...まず、gdata-python-client - Project Hosting on Google Code から gdata-2.0.10.tar.gz(2010年6月19日現在)をダウンロードします。

gdata を利用するには ElementTree というパッケージが必要なのですが、Mac OS X 10.6 にインストールされている python には既に ElementTree が入っているため、ElementTree をインストールする必要はありません。

以降、Terminal での作業になります。

Terminal を起動し、gdata-2.0.10.tar.gz のある場所に移動します。

$ tar zxvf gdata-2.0.10.tar.gz 
$ cd gdata-2.0.10/
$ sudo python setup.py install

これで Python 用の gdata ライブラリがインストールされます。

gdata さえあれば、Google の各種サービスを Python で利用することができるのですが、GoogleCL は gdata を意識せずに Terminal から Google の各種サービスを利用できるようになります。

直接 Python から gdata を利用するより処理は制限されますが、GoogleCL は gdata を実際に利用するより、気楽に利用できます。

GoogleCL のインストール

googlecl - Project Hosting on Google Code から googlecl-0.9.5.tar.gz(2010年6月19日現在)をダウンロードします。

以降、Terminal での作業になります。

Terminal を起動し、googlecl-0.9.5.tar.gz のある場所に移動します。

$ tar zxvf googlecl-0.9.5.tar.gz 
$ cd googlecl-0.9.5/
$ sudo python setup.py install

以上で GoogleCL を利用するためのライブラリはインストールできました。

実際に使ってみる

GoogleCL は、Terminal から利用します。最初にヘルプを参照しておくといいと思います。

$ google -h

コマンドラインからの利用は以下のようになります。

google [picasa|blogger|youtube|docs|contacts|calendar] TASK [options]

コマンド名の後に利用するサービス、その後に行う処理、最後にオプションを記述します。単純にコマンド名だけを入力すると、対話モードに移行します。

$ google[return] # 対話モードへ
> picasa list title
headerbg-1.png
sidebarbg.png
postbg.png
...
> ^D # 終了(Control-D)

サービスにより利用できるタスクとオプションは異なります。この辺りのことはヘルプに詳しいです。

では、Blogger サイトのリストを取得してみます。

$ google blogger list

Terminal で上記のコマンドを実行すると、ユーザー名を尋ねられます。blogger で利用しているユーザー名(Google アカウントのメールアドレスの @ の前の部分。もしくは、メールアドレス)を入力します。

すると、OAuth による認証を促されます。

Please log in and/or grant access vis your browser at...の後に https で始まる URL が表示されると思います。この URL をコピーし、Safari などのブラウザでアクセスします。

ブラウザで認証を行った後、Terminal に戻り、Enter(Return)キーを押すと、Blogger での記事タイトル一覧と URL が取得できます。認証に失敗すると Failed to get valid access token! と表示されて、処理は終了します。

各サービスは初回実行時にのみ認証を求めます。この認証を行っておくと、以降の操作では認証は必要ありません。

設定ファイル

GoogleCL のインストールが完了すると、ユーザーのホームディレクトリに googlecl という Finder で表示されない非表示のディレクトリが作成されます。

$ open ~/.googlecl

このディレクトリの中に config というファイルがおさめられています。これはテキストファイルで GoogleCL で利用する各種設定が記述されています。この設定ファイルの説明は googlecl-0.9.5(googlecl-0.9.5.ter.gz を解凍したディレクトリ)にある README.config に記述されています。

各サービスにアクセスし、認証を行うとこの設定ファイルにユーザー名が保存されます。また、OAuth で行った認証もこのディレクトリに保存されます。

一度、ユーザー名を入力し、認証が行われると、次回からはそれらの入力は不要になります。別のユーザー名でログインを行いたい場合は、-u オプションを使うことで別のユーザーでログインすることができます。

$ google blogger list -u ユーザー名

設定ファイルはセクションに分割されており、各設定はキーと値のペアで記述されます。セクションは [GENERAL] といった感じで角括弧で囲まれており、直前のセクションとは空行で分割されます。例えば、以下のようになります。

[GENERAL]
regex = True
...

[CONTACTS]
list_style = title,email

regex がキーで True が値になります。このキーは -n(--title) オプションを指定するときに正規表現の使用を許可します。

$ google blogger list title --title=^WWDC # WWDC で始まるタイトルを表示
WWDC のサンプル

GENERAL セクションはすべてのサービスで利用する設定を記述しておく場所です。その他、各サービスごとにセクションは作成されます。

各サービスで利用できるタスクに list があります。これは各サービスの一覧(例えば、Google Docs のファイルの一覧や Blogger のブログタイトルの一覧など)を表示するタスクです。このタスクはオプションとして表示する項目を指定することができます。

例えば、blogger のタイトルと URL を表示させたいなら次のようになります。

$ google blogger list title,url-direct

list の後で title,url-direct と指定してしていますが、この表示する項目の指定を list_style と言います。

設定ファイルには GENERAL セクションでデフォルトの表示設定が次のように指定されています。

[GENERAL]
list_style = title,url-site

list タスクで list_style を指定しない場合、この設定を利用します。一方、Contacts セクションでは list_style は次のように設定されています。

[CONTACTS]
list_style = title,email

このサービスを利用するときはこちらの設定が優先されます。list_style の指定は、各項目を , で区切ります。各項目の間に空白を入れてはいけません。各サービスにより利用できる項目は異なります。詳しくは README.txt に書かれているので参照してみてください。

AppleScript からの利用

do shell script で利用できます。ただし、デフォルトでは google コマンドが /usr/local/bin にインストールされるため、絶対パスを利用します(インストール場所を変更しているときは適宜修正してください)。

do shell script "/usr/local/bin/google blogger list"

Automator からの利用

AppleScript の do shell script から利用できるということは Automator からでも利用できるということです。

コマンドラインから Picasa に画像をアップロードするには次のようにします。

$ google picasa post --title='アルバムの名前' *.jpg

--title オプションで指定するのは既存のアルバムの名称です。上記のコマンドを実行すると、カレントディレクトリ内にある拡張子 jpg のファイルをすべて指定のアルバムにアップロードします。

このとき注意しないといけないのはアルバムの名前です。アルバムの名前の一部が重複しているとアルバムを選択する必要があります。Picasa に「Summer 2008」、「Summer 2008」という名前のアルバムが既に存在し、次のコマンドを実行すると、どちらのアルバムかを確認するために入力を求められます。

$ google picasa post --title='Summer' *.jpg
More than one match for title Summer
0) Summer 2008
1) Summer 2008
Please select one of the items by number: 1 # 数値を指定し、enter

つまり、アルバムの指定をこのように行っていると AppleScript や Automator などからでは実行できないのです(AppleScript や Automator などからでは数値の入力ができないため)。アルバムの名称は一意のものにしておくのが無難です。

一例として Finder の選択項目を Picasa にアップロードする Automator サービスを。このサービスでは「AppleScript を実行」アクションを利用します。「AppleScript を実行」アクションに以下のコードを記述します。

Script Editor で開く

-- アップロード先(Picasa ウェブアルバムで作成したアルバムの名前)
property album : "ALBUM_NAME"
-- アップロードの対象とするファイルの拡張子
property file_extensions : {"png", "jpg", "jpeg", "tiff", "tif"}

on run {input, parameters}

    if input is {} or input is {""} then
        error -128 -- 終了
    end if

    tell application "Finder"
        set file_list to {}
        repeat with this_item in input
            if name extension of this_item is in file_extensions then
                set end of file_list to quoted form of (POSIX path of (this_item))
            end if
        end repeat
    end tell

    if file_list is {} then
        --ファイルがない場合、終了
        error -128
    end if

    set AppleScript's text item delimiters to space
    set file_list to file_list as text
    set AppleScript's text item delimiters to {""}

    set the_command to "/usr/local/bin/google picasa post --title="
    set the_command to the_command & quoted form of album & space
    set the_command to the_command & file_list

    do shell script the_command

    return file_list
end run

最後に

GoogleCL のすべては README.txt、README.config および、コマンドのヘルプに記述されています。これらを熟読することをお勧めします。

わざわざ Python から gdata を 直接たたく必要がない分(Python を知らなくても使えるし)、かなり気楽に Google の各種サービスを利用することができます。また、コマンドラインからの利用なので、AppleScript や Automator との組み合わせも簡単です。

反面、利用できないサービスもありますし、利用できたとしても操作には制限があります。この辺りは今後のアップデートに期待しましょう。

Safari 機能拡張の証明書を取得する

Google Chrome を使い始めて約 2 週間。いくつか拡張機能を入れ、それなりに使い勝手が良くなり、色々な操作が Google Chrome に集約でき始めた昨今。なんで、Safari 5 が公開されて、しかも拡張機能に対応しているのでしょうか。再度、Safari を使い始める理由ができてしまった...。

今回の Safari、AppleScript 的にはなにも変わりはありません。しかし、なんといっても Safari リーダーの機能はすばらしい。利用できるページとそうでないページがありますが(これはどのようなページを作れば Safari リーダーは利用できるのでしょうか?)。

そして、正式な拡張機能への対応があります。で、早速拡張機能を使ってみようと思ったのですが...、Safari 5 のデフォルトの設定では拡張機能が隠されていますね。

拡張機能を有効にするには、最初に環境設定の「詳細」タブにある「メニューバーに開発メニューを表示」にチェックを入れます。

safari_preference.png

そして、「開発」メニューの「機能拡張を有効にする」を選択します(Safari では「機能拡張」なのですね。Google Chrome では「拡張機能」ですが)。

safari_dev_menu.png

すると、環境設定に「機能拡張」タブが追加されます。ここでインストールされた機能拡張の管理ができるようになります。

safari_extension_preference.png

ユーザーが機能拡張を利用するには、これで利用できるようになります。拡張子「safariextz」のファイルをダウンロードし、ダブルクリックすれば Safari にインストールされます。インストールされる場所は ~/Library/Safari/Extensions です。

さて。

多くの人は機能拡張をどうやって作るのか?の方に興味があると思います。機能拡張を作るには Safari の「開発」メニューにある「機能拡張ビルダーを表示」を選択します。

safari_extension_builder_menu.png

このメニューを選択するとウィンドウが表示さるのですが...多くの人は「証明書」をまだ入手していないと思います。機能拡張を作成する前に証明書を Safari Dev から入手する必要があります。そして、証明書を入手するには Safari Developer Program に入会する必要があります。

以下の手順は Mac での場合になります。

Safari Dev Center に移動し、Safari Developer Program に入会します。既に入会されているなら、ログインしてください。この辺りの手順は割愛。

ログインすると、(おそらく)ページの右の方に「Safari Extension Certificate Utility」と書かれている部分があります。

safari_extension_certificate_utility.png

「Get Started」をクリックして証明書の作成を始めます。最初に「Request a Safari Extension Certificate」というページが表示されると思います。このページに「Launch Assistant」というボタンがあります。これをクリックします。

safari_certificate_utility.png

すると、ページ内に次のようなパネルが表示されます。

safari_certificate_utility_panel.png

このパネルの手順に従って証明書を発行してもらいます。証明書の要求書を作成するため、キーチェーンアクセス.app を起動します。「キーチェーンアクセス」メニューの「証明書アシスタント...」に「認証局に証明書を要求...」というメニューがあります。

keychain_access_ceritification.png

このメニューから「証明書アシスタント」を起動します。メールアドレスと通称を入力します。「要求の処理」は「ディスクに保存」にチェックを入れます。

keychain_certificate_assistant.png

「続ける」をクリックすると保存場所を尋ねてくるので場所を選択し、保存します。これが証明書の要求書になります。保存が完了すると Safari に戻り、「Continue」をクリックします。ファイル選択ボタンが表示されるので、先ほど保存した要求書を選択し、「Generate」ボタンをクリックします。

すると、証明書を生成し始めます。少しの間待っていると証明書が生成されるのでダウンロードします。拡張子「cer」のファイルがダウンロードされるのでキーチェーンアクセスに読み込ませます(cer ファイルをダブルクリックするとキーチェーンアクセスが読み込んでくれます)。

これで Safari 機能拡張を作成する準備ができました。この証明書がないと、機能拡張のビルドができないのですね。

Safari Dev Center からは機能拡張のリファレンスやガイド、いくつかのサンプルがダウンロードできます。まずは、この辺りのサンプルを眺めてみるといいと思います。

「あなたもマジックができる」というけれど...

たまには AppleScript とは違う話題などを。iPhone アプリあなたもマジックができるについて。まぁ、iPhone アプリのことですが、マジックに関することを少し。殴り書きですが。

実は、買うつもりはなかったのです...。

AppBank さんのレビュー([iPad, iPhone] あなたもマジックができる: 誰でも手品がマスターできる!1460)を見てから、App Store でレビューを見ていてボタンを押し間違えてしまいました。

せっかく買ったのですからレビューと思ったのですが、読み返してみてレビューというより、問題提起、疑問の提示みたいになってしまいました。

このアプリのレビューを書いているサイトは AppBank さんを始め、いくつかあり、おおむね高評価なのですが、それらとは全く違うレビューになります。たまたま、少しマジックのことを知っているので、レビューというより批判です。

ところで、こういったアプリ(基本的には動画を表示するだけのアプリ。アプリというより、こんなもの Web ページでもいいでしょ、わざわざアプリにする必要ないでしょ)のレビューはどこまで内容に突っ込んでいいのでしょうか。このようなアプリだけではなく、例えば、電子書籍のようなもの。最近、読んだものでは iPhoneとツイッターは、なぜ成功したのか?。

こういうものって内容のレビューをすればいいのでしょうか。それとも、アプリの使い勝手をレビューすればいいのでしょうか。アプリの使い勝手ということでいえば、両者とも最低です。なぜ、iPhone や Twitter の使い心地を論じている書籍のアプリがあれほど使いにくいのかがいまだに分かりません。

どうして、誰も使いにくいって言わないのだろう。

iPhoneとツイッターは、なぜ成功したのか?のレビューではないので多くは書きませんが、どうして、林信行さんがあの内容であのアプリを承諾したのかが理解できません。あの内容なら、ぜひ、こだわってほしかったです。使い勝手に。

あれじゃ、書籍をそのまま流し込んだだけじゃないの?一つ言うなら、時々、注釈が入るのだけど、その注釈は注釈の説明に移動するリンクが張られているのだけど、その注釈の説明はおおむね、章の最後に記述されている。多くの書籍はそのようになっていますし、このアプリでも踏襲されています。

問題は、書籍と同じ構成のため、ページをめくっていくと再度同じ注釈に出くわすということです。こんなもの、飛ばせよ。一度、見たのだから。断言するけど、これは書籍のデータをそのまま流し込んだだけ。iPhone には iPhone の見え方、見せ方があるでしょ。これだけのことで内容は良くても、読む気はなくなってしまいます(特に内容が内容なだけに)。

似たようなことはあなたもマジックができるにも言えます。マジックの手順の説明は 1, 2, 3...と番号順に進んでいくのですが、時々、他のマジックの手順 5 を参照してちょうだい、みたいなことが書かれている。書かれているのだけど、そこに移動するリンクはない。当然、参照して戻るためのリンクもない。

えっとね。マジック入門のようなアプリを作っているんでしょ。いってみれば、専門書。それが、なんでこういうところの使い勝手が悪いの?

マジックに関する書籍で一番面倒なのは、いろんなページに行ったり来たりしなければならないこと。アプリなんだし、相互参照ぐらい簡単でしょ。たとえ、それが動画でも。

iPhone や iPad などのモバイルアプリや電子書籍はまだまだ混沌とした状況だから玉石混淆...というのは分かります。しかし、手を抜いているようにしか見えないこれらの問題は必ず自分たちの首を絞めます(もちろん、真っ先にレビューしなければいけないはずのマジシャンの首もね)。

そして、これはあなたもマジックができるのレビューを掲載しているいくつかのサイトの問題でしょうけど、ほんとに買ったの?ほんとに買って中身を見てみたなら腹がたったと思うのですが、そういうレビューは見かけない。レビューを書くなら、いいところだけではなく、悪いところも書いてください。

で、なんで腹がたったかというと、解説の文章がアマチュア以下だから。少なくとも金をとって、マジックの演技をし、解説しているのなら、プロ根性を見せろと言いたい(マジックで演技を見せ、なんらかの報酬を得ればその人はプロです。本人の意思に関係なく。また、文章を書いて金をとっているのでしょ。もう少し、まともな文章を書いてください)。

で、内容なのですが...。

評価は分かれるでしょうね。おそらく、全くマジックをしたことのない初心者やマジックに興味のある人には、手頃な値段ということもあって受け入れられるでしょう。内容も数だけはありますし。

いわゆるマニアには酷評されるでしょう。紹介されているマジックが初心者向きだからではありません。作品のクレジットもなければ、誰が演じているのかも分からない。何を見せたいのかも分からなければ、パズルだけを紹介しているその姿勢(あの実演動画はいったいなにが不思議なのか?ビックリ箱としての驚きはあるでしょうが、それだけです)ゆえに。

客観的に見るなら、少しマジックをかじったことのある人が、小銭を稼ぐためにマジックの知識を切り売りしている...といった感じがします。

個人的には情報商材かよ、という気がします。

マジックをしたことがなく、マジックに興味ある、覚えたい、という人にはお勧めできるか?

マジックをすることはないけど、興味本位で見てみたいというだけなら購入されてもいいのでは?満足感は得られるでしょう。

意欲がある人には、お勧めしません。意欲がある人には初期投資が高くついても、書籍をお勧めします。英語でも構わないなら、Magic: The Complete Course (Book & DVD)。日本語でなら、華麗に決める本格マジック。どちらも DVD で一流のマジシャンによる演技、解説が見られます。

でも...こういうアプリってこれから増えるんだろうな。

収録されているマジックは以下になります。といっても、現象を書くと分かる人には分かってしまうので詳しく書くことはできません。

  1. 混沌な予言
  2. 4エース出現
  3. コイン移動
  4. 予想外のカード当て
  5. コイン消失
  6. ティッシュの復活
  7. 不思議な予言
  8. コイン貫通
  9. ミックスアップ
  10. 恋人の出会い

ところで、マジックで一番大事なものって何でしょうか。

それは、「マジックでなにを見せるか、なにを言いたいか、なにを表現したいか」だと思います。ごくごく当たり前のことを書けば、マジックなんてタネさえ知れば誰にでもできます。しかし、タネを知り Mr.マリックがやっていることと同じことをしても、同じように万雷の拍手を得ることはできません。Mr.マリックにはマジックを使って表現したいことがあります。マジックを使って伝えたいことがあります。

マジックというのはただの道具です。それ自体は面白くもなんともありません。面白くなるかどうか...人に感銘を与えるかどうかは、演技者が道具をどう扱うかにかかっています。

残念ながらあなたもマジックができるには「伝えたいこと」も「表現したいこと」も「自己主張」もありません。あったのかもしれませんが、伝わってきませんでした。どちらかというとマジックのタネ教えます、といった暴露サイトと同じレベルです。

もし、このアプリケーションの作成者がマジシャンを増やしたい、マジシャンの蒙を啓きたいと思ってこのアプリを作ったのだとしたら、やり方が間違っています。もっと、丁寧に作ってください。

サイトを移行します

まぁ...タイトルの通りなのですが、このサイトを他のブログサービスに移行させます。利用するのは Blogger です。

なぜ、移行するのかを少し。現在、ODN のホームページサービスを使っていますが、いかんせん古い。いまだにアップロードは FTP ですし(構わないといえば、構わないのですが...)、サービスも充実させる気がないようです。その昔、個人でホームページを作成するのが流行りましたが、そのときのままなのですね。サービスも使い勝手も。

HTML の手打ちは苦にならないのですが、サイトの管理が非常に面倒です。

Blogger は少し前から移行先としてぼちぼちと調べていました。ようやく、使い勝手もなんとなく分かってきました。カスタマイズの仕方や Google Data API を使った更新も慣れてきました。全面的な移行の準備が整った、というところです。

コンテンツは少しずつ移行している最中です。現在、3 分の 1 ほど終了。

移行にともない、あまり評判のよろしくなかったサイト名も変更します。ASH Planning。

個人的にはテキトウな自分に最適な名称だと思っていたのですが。完全に移行(コンテンツをすべて移動し終えるまで)するまでは、ここは残しておきます。移行後は、契約解除します。

永らくご愛顧いただきありがとうございました。それでは、ASH Planning でお会いしましょう。

あ。それと Google Friend Connect ですが、せっかく導入したのですが、このサイトの終了にともない、Google Friend Connect も ASH Planning に移行します。登録していただいた方には非常に迷惑な話なのですが、ASH Planning の方で再度登録していただけると幸いです。誠に申し訳ございません。