Macでオリジナルプロトコルを実装してみた
※ 2014/04/13 にシェルコマンドで空白を用いたい場合の処理を追記しました
私は、普段からコマンドラインランチャーとして、 Alfred というアプリケーションを使用しています。
Alfredでは、URLとコマンドキーワードを設定すれば、そのキーワードでURLを開く(たとえば、キーワード「google」でGoogle検索のURLを開く)ことができます。
私は、常々このAlfredでシェルコマンドを起動させることはできないかなーと考えていました。
(注:実はシェルコマンドの起動はAlfred ProもしくはAlfred 2を買えばビルトインで実装されていますが、私はお金払いたくないので実装しました)
そして、Macのアプリケーションには、iTunesの「 itunes: 」のような オリジナルプロトコル が実装されているものがあります。
なので「 shell: 」というオリジナルプロトコルが実装されている AlfredShellRunner というアプリケーションを作って、
Alfredでシェルコマンドを起動できるようにしてやろう、と考えました。
( 要訳: Alfredというアプリでシェルコマンドを起動させたいからオリジナルプロトコルがついてるアプリケーションをつくるよ)
参考:
OSXでオレオレ・プロトコルのヘルパアプリケーションを作成する - http://blog.katsuma.tv/2007/12/osx_protocol_helper.html
アプリケーションの構成
Macでのアプリケーションは、 .app という拡張子がついたディレクトリによって表しています。
AlfredShellRunner.app
- Contents/
- Info.plist
- MacOS/
- Resources/
オリジナルプロトコルを実装するには、 Info.plist を使用します。
Info.plist
Info.plistは、アプリケーションの設定情報(アプリケーション名やアイコンファイルパス等)を XML にしたものです。
オリジナルプロトコルの情報は、このInfo.plistに記載します。
その歳、「 CFBundleURLTypes 」というKEYタグを使います。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Alfred Shell Runner URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>shell</string>
</array>
</dict>
</array>
こんなかんじ。
CFBundleURLTypes には、これらのキー情報を設定出来ます。
- CFBundleTypeRole (必須) - string
- CFBundleURLIconFile - string
- CFBundleURLName - string
- CFBundleURLSchemes - array
CFBundleTypeRole
このキーは、URL タイプを尊重した、アプリケーションの役割を指定します。値は Editor、Shell、None のいずれかとすることができます。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter3.html)
-
Editor(編集者)
アプリケーションはそのタイプを読み、操作し、保存することができます。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter6.html#chapter6-2) -
Shell(シェル)
アプリケーションは他のプロセスのための実行時サービスを提供します―たとえば、Java アプレットビューアのように。書類の名前は(アプリケーションの名前の代わりに)ホストされるプロセスの名前です。そして、書類が開かれるたびに新しいプロセスが作成されます。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter6.html#chapter6-2) -
None(なし)
アプリケーションはデータを理解せず、タイプに関する情報の宣言だけを行います(たとえば、Finder はフォントのためのアイコンを宣言します【Finder はフォントを編集するためのアプリケーションではないが、ファイルアイコンを表示するためにフォントに関する宣言を行う、という場合】)。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter6.html#chapter6-2)
CFBundleURLIconFile
このキーは、この URL タイプに対して用いるための、アイコン画像ファイルの(拡張子を除く)名前を格納します。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter3.html)
CFBundleURLName
このキーは、この URL タイプのための抽象化された名前を格納します。このキーは特定のタイプを参照するための主な手段となります。
また、この名前はタイプ名の「人が読める版」を提供するために、InfoPlist.strings ファイル内のキーとしても使用されます。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter3.html)
CFBundleURLSchemes
このキーは文字列の配列を格納しており、そのそれぞれは、このタイプによって取り扱われる URL スキームを識別します。
(引用元: http://potting.syuriken.jp/potting_conv/BPRuntimeConfig_J/chapter3.html)
アップルスクリプトを書く
AppleScriptエディタを開いて、以下の内容を入力。
on open location shellURL
if shellURL starts with "shell://" then
-- "shell"プロトコルを開いた場合
activate
set len to the length of shellURL
set shelltext to text from character 9 to character len of shellURL
-- "shell://" 以降の文字列を取得
tell application "Applications/Utilities/Terminal.app"
-- Terminal.app を起動
activate
do script with command shelltext
-- シェルスクリプトを実行
end tell
end if
quit
end open location
(追記2014/04/13) シェルコマンドに空白を用いたい場合
上記のapple scriptだと、 shell://python -c 'print "hello"' のようなシェルコマンドを使うことはできません。なぜなら、URLスキームでは空白が %20 という文字に置換されるからです。
しかし、AppleScriptには文字列置換はできません。なので delimitors という機構を使います
on replace(src, tg, rp)
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to tg
set myList to text items of src
set AppleScript's text item delimiters to rp
set myText to myList as string
set AppleScript's text item delimiters to oldDel
return myText
end replace
これで文字列を置換する関数が設定できました。
あとは、AppleScriptに文字列を置換する一行を書けば良いだけです。
on replace(src, tg, rp)
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to tg
set myList to text items of src
set AppleScript's text item delimiters to rp
set myText to myList as string
set AppleScript's text item delimiters to oldDel
return myText
end replace
on open location shellURL
if shellURL starts with "shell://" then
-- "shell"プロトコルを開いた場合
activate
set len to the length of shellURL
set shelltext to text from character 9 to character len of shellURL
set shelltext to replace(body, "%20", " ")
-- "shell://" 以降の文字列を取得して%20を置換
tell application "Applications/Utilities/Terminal.app"
-- Terminal.app を起動
activate
do script with command shelltext
-- シェルスクリプトを実行
end tell
end if
quit
end open location
入力したら、ファイル->保存で「 ファイルフォーマット 」を「 アプリケーション 」にして保存。
Info.plistにプロトコル情報を追記
これでアプリケーションは完成したが、この状態では まだオリジナルプロトコルの内容がInfo.plistに書かれていない状態 です。
なので、上記のオリジナルプロトコルの記述を、 保存したアプリケーション/Contents/Info.plist に追記してください。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleURLTypes</key>
(省略)
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Alfred Shell Runner URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>shell</string>
</array>
</dict>
</array>
</dict>
</plist>
追記すると上記のようになります。
保存したアプリケーションをdmgにする
しかし、追記しただけではまだダメです。この追記したInfo.plistを実行させるには、アプリケーションを一度 .dmg ファイルに圧縮して、インストールする必要があります。
DMGに圧縮する方法はこちらを参考にしてください。 -> http://memorva.jp/internet/mac/dmg_disk_image_file.php
アプリケーションをdmgにして、再度インストールして実行すると、もうオリジナルプロトコルが実装されています。
あとは、AlfredでカスタムURL検索で shell://{query} と入力すれば完了!!!