Archive for 6月, 2009

2009/06/30 Diary++Xで指定カテゴリ内のアーティクルを取得する

Diary++Xで、指定カテゴリ内のアーティクルを取得するAppleScriptです。

指定のカテゴリ内に入っているアーティクルを取得するのに、指定カテゴリの「contained articles」という属性に対してアクセスする必要があります。このあたりに少々クセがあるのが気になりますが、そういうものだと思えば納得できるレベルでしょうか。

普通、こうした場合には「every article」で指定カテゴリ内に存在するアーティクルを取得することになるはずですが……おそらく、実装のしやすさからこのような仕様になったものでしょう。

AppleScriptの初心者がつまづくのが、こういうイレギュラーな実装を行っているアプリケーションに出くわした時です。実は、言語処理系そのものではなくアプリケーション側の対応に問題があるケースの方が多く……アプリケーション開発者がAppleScriptについて十分な知識を持っていないために起こるトラブルが多いといえます。

Diary++X作者のMikoさんは日本のアプリ開発者の中でもAppleScriptへの理解がある方ですが、まだ本アプリケーションの開発段階が初期段階であるために目下試行錯誤している状態なのでしょう。

スクリプト名:Diary++で指定カテゴリ内のアーティクルを取得する
tell application Diary++X
  tell document 1
    tell category 履歴
      set cList to every category
      
> {category “履歴:2009年6月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年5月1日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月30日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月28日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月27日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月26日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年1月21日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2007年10月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2007年1月9日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2006年9月3日” of category “履歴” of document “Diary++X” of application “Diary++X”}
      
      
tell first category
        set aList to contained articles
        
repeat with i in aList
          tell i
            set aType to type
            
log aType
          end tell
        end repeat
      end tell
    end tell
  end tell
end tell

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

2009/06/29 Diary++Xでカテゴリ情報を取得

Diary++Xでカテゴリの情報を取得するAppleScriptです。

diary1.jpg

Diary++Xでは、Mail.appのように「受信/ML/Apple/AppleScript Users」といったように階層構造をそのまま指定することはできません。だいたい、MacJournalと同レベルの実装にとどまっている状態で、実用的なスクリプトを書くためにはカテゴリ階層へのアクセスの改善がポイントになるでしょうか。

ブックマークの機能も持っていますが、はたして「ブックマーク」という概念自体に意義があるのかどうかという点にも疑問が残ります。いっそ、ページの内容を取得してPDFでコンテンツそのものを保持しておいたほうが「Webページスクラップブック」として有効に利用できるのではないか……などと思うものです。

スクリプト名:Diary++でカテゴリ情報を取得
tell application "Diary++X"
  tell document 1
    set cList to every category
  end tell
end tell

> {category "日記" of document "Diary++X" of application "Diary++X", category "メモ" of document "Diary++X" of application "Diary++X", category "ブックマーク" of document "Diary++X" of application "Diary++X", category "履歴" of document "Diary++X" of application "Diary++X"}

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

2009/06/29 Diary++Xでドキュメントの情報を取得

Diary++Xでドキュメントの情報を取得するAppleScriptです。同梱のドキュメントによれば、Diary++Xは同時に1つのドキュメントだけを開けるようになっているとのこと。

さらに、ドキュメントのプロパティに「選択中のアーティクル」(current selected articles)があるのが注意点でしょうか。複数の選択アーティクルを許容し、リストで取得できるようになっています。

ただし、「選択中のカテゴリ」の情報を取得できるようにはなっておらず、このあたりに課題を残しているといえるでしょう。

スクリプト名:Diary++でドキュメントの情報を取得
tell application "Diary++X"
  tell document 1
    properties
  end tell
end tell
> {modified:false, class:document, current article:article -2.147483648E+9 of document "Diary++X" of application "Diary++X", current selected articles:{}, file:file "Cherry:Users:maro:Library:Application Support:Diary++X:", name:"Diary++X"}

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

2009/06/29 Diary++Xでアプリの情報を取得

バージョンアップしてAppleScript系の実装が修正されたDiary++X v1.02。AppleScript側からアーティクル(記事)への読み書きを行う前に特定の命令を実行する必要がなくなりました。

そんなDiary++Xでアプリケーションの情報を取得するAppleScriptです。Selectionの属性はApplicationではなくdocumentから取得するようになっているので、この階層で何か有用な情報が得られるとかいったことは特にないようです。

スクリプト名:Diary++でアプリの情報を取得
tell application "Diary++X"
  properties
end tell
> {frontmost:false, class:application, version:"0", name:"Diary++X"}

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

2009/06/29 Safariで表示中のページ内容をMacJournalの現在選択中のJournalにペースト

Safariで表示中のページ内容を、MacJournalの現在選択中のJournalにペーストするAppleScriptです。

AppleScriptに対応しているのに、実践的な機能が欠けているためにいまひとつ自動化しづらいMacJournal。一括自動処理はしづらくても、ワンアクションだけ自動化するのであればなんとか使えることでしょう。

MacJournalには、Webの内容をコピー&ペーストして内容をとっておいています。ブックマークだと、内容が消えたり、Blogなどはサイトごとなくなったりすることは日常茶飯事。ローカルなりWeb上のアルバムにとっておくなりしておく必要があることでしょう。

重要なページだとコピー&ペーストして必要な部分だけクリッピングしておくのですが、そうでもないページはこの程度で十分でしょう。もうちょっと改良して、Safariで表示中のページの内容を、CLIのWebレンダラーを併用してPDFに落としておいてから、MacJournalにPDFを取り込むところまで作り込むといい感じでしょうか。

スクリプト名:Safariで表示中のページ内容をMacJournalの現在選択中のJournalにペースト
ページにフレームを使っていないことが前提条件
tell application Safari
  set wCount to count every window
  
if wCount = 0 then
    display dialog Safariでウィンドウがオープンされていません buttons {”OK“} default button 1
    
return
  end if
  
  
tell document 1
    set aURL to URL
    
set aTitle to name
  end tell
  
set aText to text of document 1 本文テキスト
end tell

MacJournalの操作
createNewEntryonMacJournal() of me

tell application MacJournal
  tell document 1
    set aSel to selected entry
    
set name of aSel to aTitle
    
set plain text content of aSel to (aURL & return & return & aText)
  end tell
end tell

MacJournalで新規エントリを作成して選択状態にしておく
on createNewEntryonMacJournal()
  activate application MacJournal
  
tell application System Events
    tell process MacJournal
      set aName to title of menu item 1 of menu 1 of menu bar item 3 of menu bar 1
      
if aName = 新規エントリー then 日本語環境用。他の言語環境では、ここのチェックを行わないか、あるいは書き換えること
        click menu item 1 of menu 1 of menu bar item 3 of menu bar 1 Menu > New Entry
      end if
    end tell
  end tell
end createNewEntryonMacJournal

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

2009/06/25 WordPressのBlogに画像ファイルをアップロード

WordPressのBlogに選択した画像をアップロードするAppleScriptです。

WordPressに対してXML-RPC経由でああでもないこうでもない、と画像のアップロードを行うテストを繰り返してきたものの、アップロードされるのにbase64でエンコードされたテキストになるばかりで、デコードされませんでした。

いろいろ調べてみたところ、こちらに画像アップロードのサンプルAppleScriptが置いてあるのを見つけました。しかし、アップロードするための呼び出し部分は書いていないし、そのままでは正規表現用のOSAXが必要なものでした。

  「この程度、OSAX使わなくても書けるだろー」

OSAX依存部分をAppleScriptのサブルーチンで置き換えてみました。本サンプルには、Blogのユーザー名とパスワードは記入していませんが、ご自分でお持ちのBlogのユーザー名とパスワードを記入し、BlogのXML-RPCで呼び出すURLを記入して実行してみてください。

WordPress ME 2.0.11および(本稿執筆時点で)最新のWordPress2.8での動作を確認してあります。

スクリプト名:WordPressのBlogに画像ファイルをアップロード
http://theotherblog.com/wp-content/files/newMediaObject.html
書き換えて、TextCommands OSAXを使用しなくても動くようにした

property curl : "/usr/bin/curl"
property theUsername : "Blogのユーザー名"
property thePassword : "Blogのパスワード"

set aFile to choose file
UploadImage(aFile) of me

on UploadImage(theFile)
  
  
try
    tell application "Image Events"
      launch
      
set this_image to open theFile
      
extract the property value
      
set theType to file type of this_image
      
set theLocation to location of this_image
      
set theName to name of this_image
      
set {theWidth, theHeight} to dimensions of this_image
      
close this_image
    end tell
    
display dialog "Resolution: " & (xres as string)
  on error error_message
    display dialog error_message
  end try
  
  
get the action from the pages source code
  
set action to "http://piyocast.com/as/xmlrpc.php"
  
  
set theBits to encodeAsBase64(theFile)
  
set theType to "image/png"
  
  
set theTemplate to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<methodCall>
<methodName>metaWeblog.newMediaObject</methodName>
<params>
<param>
<value><string>1</string></value>
</param>
<param>
<value><string>" & theUsername & "</string></value>
</param>
<param>
<value><string>" & thePassword & "</string></value>
</param>
<param>
<value><struct>
<member>
<name>bits</name>
<value><base64>
" & theBits & "</base64></value>
</member>
<member>
<name>name</name>
<value><string>
" & theName & "</string></value>
</member>
<member>
<name>type</name>
<value><string>
" & theType & "</string></value>
</member>
</struct></value>
</param>
</params>
</methodCall>
"
  
  
set theScript to (curl & " -d" & space & "" & theTemplate & "" & space & " -H \"Content-Type: text/xml\" -X POST " & action) as text
  
  
try
    set theText to do shell script theScript
    
set theURL to doRegex(theText, "<string>(http://.*)</string>")
    
set theText to retNoTagValue(theText, "string") of me
    
return theText contains a URL to the file on the server
  on error err
    display dialog err as string
    
return false
  end try
  
  
I could use parse XML except fishing out the URL is easier…
  
  
end UploadImage

on encodeAsBase64(theFilePath)
  set thePath to quoted form of POSIX path of (theFilePath)
  
set theScript to "openssl base64 < " & thePath
  
return do shell script theScript
end encodeAsBase64

文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

指定タグを外す
on retNoTagValue(aLine, parseTagVal)
  set parseTagVal to "string"
  
set beginTag to "<" & parseTagVal & ">"
  
set endTag to "</" & parseTagVal & ">"
  
  
set sNum to offset of beginTag in aLine
  
set sNum to (length of beginTag) + sNum
  
set eNum to (offset of endTag in aLine) - 1
  
set resText to (characters sNum thru eNum of aLine) as text
  
  
return resText
  
end retNoTagValue

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

2009/06/21 Xcode 3.1.3でブレークポイント/ステップ実行/変数内容モニタの動作を確認

先日公開されたiPhone 3.0 SDKに含まれているXcode 3.1.3で、実際に既存のAppleScript Studioのプロジェクトを試してみました。

xc1.jpg

xc3.jpg

400行弱の小規模なAppleScript Studioのプロジェクトで、ブレークポイントにおけるデバッグ時の停止、および変数値のモニタリングが有効であることを確認。1,000行オーバーの中規模プロジェクトで動作が変わるかどうかは未確認ですが、Xcode 3.1.2から機能ダウンしているわけではないといった印象を受けています。

これまでにXcode 3.x系で発生していたマイナーなバグを修正した、というリリースノートの内容については、一応信じてよさそうです。

2009/06/20 AppleScript Studioを念頭に置いたライブラリ整備

AS Holeに掲載しているAppleScriptには、「OSAXを使えばもっと簡潔に書ける」ものもあります。OSAXとは、AppleScriptの命令語を拡張する機能拡張書類で、Scripting Additionとも呼ばれます。Classic Mac OSの時代には200以上の個性あふれるOSAXが存在しており、その時代は「OSAXを使っていかに短く(楽に)プログラムを書くか」というのがテーマだったように(個人的に)感じています。

Mac OS X時代に入って、Xcode+Interface Builderによる、GUIつきAppleScriptアプリ開発のための「AppleScript Studio」環境が利用できるようになったことで、「再配布可能な、どこでも動くプログラムコード」を意識。それまでとは180度方向転換して、OSAXを極力利用しない記述スタイルに変更しました。

プログラム配布先のMacにプログラムが依存しているOSAXがインストールされていなかったら、アプリケーションを配布しても「動かない」ということになってしまいます。実際、アプリケーション・バンドルの中にOSAXを入れて配布することも可能ですが、再配布が許可されているOSAXにかぎられます(XMLlib OSAXとか)。

実際に、ソーティングのための命令を備えたOSAXもありますが、アプリケーションと一緒に再配布できなければ、ユーザーに「OSAXを別途ダウンロードしておいてください」とお願いする必要があります。また、Classic Mac OS時代に苦しめられた「OSAX命令同士のコンフリクト」についても、Mac OS Xになったからといって、解消されたわけではありません。昔、2000年ごろに来日したAppleのAppleScript製品担当のSal Soghoianに直接言ったのですが、結局うやむやに。

そんなわけで、あくまでもAppleScriptオンリーで、あるいはshellの(標準的に利用できる)コマンドをまじえて書き、OSAXの使用を控えている次第です。

2009/06/20 ファイルの安全な書き出し

本Blogで使用している「AppleScriptのHTML書き出しツール」(AppleScriptで書いてあります)を使っていて、Mac OS X 10.5環境でうまくファイルを書き出せないケースに遭遇したことがありました。

一度テンポラリ領域(path to temporary items from system domain)に書き出したあとにiconvでutf-8にコード変換しているのですが、ファイルの書き出しを行おうとしてエラーで止まる。何回かそんなケースに遭遇するうちに、安全なファイル書き出しを試作すべきでは? と考え……一度テンポラリ領域に安全な名前で書いてから、あとでファイルを移動しつつリネームするという処理を書いてみました。

先のHTML書き出しツールでいえば、テンポラリ領域への書き出し時にこのルーチンを使用し、一度安全な名前で書き出してからリネームされるようになります。はたして、どこに問題があるのか見えてきていませんが、これで様子を見たいところです。

スクリプト名:ファイルの安全な書き出し
set aFPath to choose file name
set aData to ABC
set fRes to write_to_file_Safely(aData, aFPath) of me

安全なファイルの書き出し
on write_to_file_Safely(this_data, target_file)
  set finalPath to target_file
  
  
テンポラリフォルダに一度書き出して、ターゲットのパスに移動  
  
set tmpFol to path to temporary items from system domain
  
set tmpName to do shell script date +%Y%m%d%H%M%S
  
set tmpPath to (tmpFol as string) & tmpName
  
  
テンポラリのパスにファイル書き出し
  
try
    set the target_file to the tmpPath as text
    
set the open_target_file to open for access file target_file with write permission
    
set eof of the open_target_file to 0 つねにoverwrite mode
    
write this_data to the open_target_file starting at eof
    
close access the open_target_file
    
  on error error_message
    try
      close access file target_file
    end try
    
return error_message
  end try
  
  
ファイルの移動を行う
  
set tFilePOSIX to quoted form of POSIX path of target_file
  
set fPathPOSIX to quoted form of POSIX path of finalPath
  
set sText to mv & tFilePOSIX & & fPathPOSIX
  
try
    do shell script sText
  on error error_message
    return error_message
  end try
  
  
return true
  
end write_to_file_Safely

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

2009/06/20 WordPress.comが受け取るXML-RPCのメソッド名一覧を取得する

本Blogでも利用しているBlogソフトウェアWordPress。さまざまな外部のサービスと連携するために、XML-RPCによるAPIが用意されています。そのWordPressのAPIを呼び出すサンプルです。

手始めに、WordPressのホスティングを行っていて、3GBまで無料で利用できるWordPress.comにアカウントを取得。このサービスがどのようなAPIを持っているか、その一覧を取得するAppleScriptを書いてみました。

XML-RPCによるWebサービスは、必死になって探さないとなかなか継続して行われているサービスを(日本国内で)みつけることは難しいところですが、Blogはその例外といえるのかもしれません。

ちなみに、WordPress.comにコンテンツをホスティングすると、AS-Holeのコンテンツ内に記述しているスクリプトリンク(「applescript://」ではじまるリンク)がすべて無効化されてしまうので、現状ではWordPress.comにAS Holeを移転させることはできません。

スクリプト名:WordPress.comが受け取るXML-RPCのメソッド名一覧を取得する
tell application "http://piyomaru.wordpress.com/xmlrpc.php" たぶん、最新版のWordPress(2.8)
  call xmlrpc {method name:"mt.supportedMethods", parameters:{}}
end tell

> {"wp.getUsersBlogs", "wp.getPage", "wp.getPages", "wp.newPage", "wp.deletePage", "wp.editPage", "wp.getPageList", "wp.getAuthors", "wp.getCategories", "wp.getTags", "wp.newCategory", "wp.deleteCategory", "wp.suggestCategories", "wp.uploadFile", "wp.getCommentCount", "wp.getPostStatusList", "wp.getPageStatusList", "wp.getPageTemplates", "wp.getOptions", "wp.setOptions", "wp.getComment", "wp.getComments", "wp.deleteComment", "wp.editComment", "wp.newComment", "wp.getCommentStatusList", "blogger.getUsersBlogs", "blogger.getUserInfo", "blogger.getPost", "blogger.getRecentPosts", "blogger.getTemplate", "blogger.setTemplate", "blogger.newPost", "blogger.editPost", "blogger.deletePost", "metaWeblog.newPost", "metaWeblog.editPost", "metaWeblog.getPost", "metaWeblog.getRecentPosts", "metaWeblog.getCategories", "metaWeblog.newMediaObject", "metaWeblog.deletePost", "metaWeblog.getTemplate", "metaWeblog.setTemplate", "metaWeblog.getUsersBlogs", "mt.getCategoryList", "mt.getRecentPostTitles", "mt.getPostCategories", "mt.setPostCategories", "mt.supportedMethods", "mt.supportedTextFilters", "mt.getTrackbackPings", "mt.publishPost", "pingback.ping", "pingback.extensions.getPingbacks", "demo.sayHello", "demo.addTwoNumbers", "wpStats.check_key", "wpStats.get_blog_id", "wpStats.get_site_id", "wpStats.update_bloginfo", "wpStats.update_postinfo", "wpStats.ping_blog", "wpStats.flush_posts"}

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

2009/06/17 郵便専門ネットでXML-RPC経由で郵便番号を6桁(チェックデジット付き)の全国地方公共団体コード/JISコード/市町村コードに変換

郵便専門ネットで、指定の郵便番号に対応する地方公共団体コード(JISコード、チェックサム付き=6桁)を取得するAppleScriptです。

スクリプト名:郵便専門ネットでXML-RPC経由で郵便番号を6桁(チェックデジット付き)の全国地方公共団体コード/JISコード/市町村コードに変換
tell application "http://yubin.senmon.net/service/xmlrpc/"
  call xmlrpc {method name:"yubin.postcodeToJiscode6", parameters:{"1760024"}}
end tell

> "131202"

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

2009/06/17 郵便専門ネットで引数に指定した郵便番号で何件ヒットするのかをint型で返す

郵便専門ネットで、XML-RPC経由で引数に指定した郵便番号(7桁なくてOK)で、該当する郵便番号が何件ヒットするかを数値で返すAppleScriptです。

スクリプト名:郵便専門ネットで引数に指定した郵便番号で何件ヒットするのかをint型で返す
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.getFetchCountByPostcode“, parameters:{”19800“}}
end tell

> 41

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

2009/06/17 郵便専門ネットで郵便番号の存在チェック

郵便専門ネットで、郵便番号の存在チェックを行うAppleScriptです。存在する場合にはtrue、存在しない場合にはfalseが返ります。

スクリプト名:郵便専門ネットで郵便番号の存在チェック
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.postcodeExists“, parameters:{”1760024“}}
end tell
> true

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

2009/06/17 郵便専門ネットでXML-RPC経由で郵便番号から住所を返す

郵便専門ネットで、XML-RPC経由で郵便番号から住所を返すAppleScriptです。

スクリプト名:郵便専門ネットでXML-RPC経由で郵便番号から住所を返す
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.fetchAddressByPostcode“, parameters:{”1760024“}}
end tell

> {{data_type:”p”, town_kana:”なかむら”, town:”中村”, pref_kana:”とうきょうと”, yid:39309, jiscode:”13120″, pref:”東京都”, city:”練馬区”, city_kana:”ねりまく”, addr_name_kana:application “http://yubin.senmon.net/service/xmlrpc/”, other:application “http://yubin.senmon.net/service/xmlrpc/”, addr_name:application “http://yubin.senmon.net/service/xmlrpc/”, postcode:”1760024″}}

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

2009/06/17 郵便専門ネットでXML-RPC経由で引数に都道府県のJISコード(JISコードの先頭2文字)を渡すと、その都道府県に属しているJISコードを取得

郵便専門ネットで、XML-RPC経由で地方公共団体コード(JISコード)の先頭2文字を渡すと、そこに所属するJISコードの一覧を返すAppleScriptです。

スクリプト名:郵便専門ネットでXML-RPC経由で引数に都道府県のJISコード(JISコードの先頭2文字)を渡すと、その都道府県に属しているJISコードを取得
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.jiscodeFromPrefcode“, parameters:{”13“}}
end tell

> {”13101″, “13102″, “13103″, “13104″, “13105″, “13106″, “13107″, “13108″, “13109″, “13110″, “13111″, “13112″, “13113″, “13114″, “13115″, “13116″, “13117″, “13118″, “13119″, “13120″, “13121″, “13122″, “13123″, “13201″, “13202″, “13203″, “13204″, “13205″, “13206″, “13207″, “13208″, “13209″, “13210″, “13211″, “13212″, “13213″, “13214″, “13215″, “13218″, “13219″, “13220″, “13221″, “13222″, “13223″, “13224″, “13225″, “13227″, “13228″, “13229″, “13303″, “13305″, “13307″, “13308″, “13361″, “13362″, “13363″, “13364″, “13381″, “13382″, “13401″, “13402″, “13421″}

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

2009/06/17 郵便専門ネットで一度に取得できるデータ件数を返す

郵便専門ネットで、XML-RPC経由で一度に取得できるデータ件数を返すAppleScriptです。

スクリプト名:郵便専門ネットで一度に取得できるデータ件数を返す
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.getMaxFetchCount“, parameters:{}}
end tell
> 100

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

2009/06/17 郵便専門ネットでXML-RPC経由で郵便番号に対応する世界測地系(WGS84)の緯度経度コード(Geocode)を返す

郵便専門ネットでXML-RPC経由で郵便番号に対応する世界測地系(WGS84)の緯度経度コード(Geocode)を返すAppleScriptです。

スクリプト名:郵便専門ネットでXML-RPC経由で郵便番号に対応する世界測地系(WGS84)の緯度経度コード(Geocode)を返す
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.postcodeToGeocode“, parameters:{”1760024“}}
end tell

> {”35.7321262″, “139.6382562″}

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

2009/06/17 郵便専門ネットで道府県のコード(地方公共団体コードの先頭2文字)から都道府県名を返す

郵便専門ネットで都道府県のコード(地方公共団体コードの先頭2文字)から都道府県名を返すAppleScriptです。

スクリプト名:郵便専門ネットで道府県のコード(地方公共団体コードの先頭2文字)から都道府県名を返す
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.getPrefName“, parameters:{”13“}}
end tell
> “東京都”

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

2009/06/17 郵便専門ネットでXML-RPC経由でJISコード(5桁、6桁どちらでも)から、その市区町村に属している郵便番号のリストを取得

郵便専門ネットから、XML-RPC経由で地方公共団体コード(JISコード)の、5桁あるいは6桁(チェックサムつき)から、その地方公共団体に所属する郵便番号をリストで返すAppleScriptです。

スクリプト名:郵便専門ネットでXML-RPC経由でJISコード(5桁、6桁どちらでも)から、その市区町村に属している郵便番号のリストを取得
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.postcodeFromJiscode“, parameters:{”011037“}}
end tell

> {”0070001″, “0070002″, “0070003″, “0070004″, “0070005″, “0070006″, “0070011″, “0070030″, “0070031″, “0070032″, “0070033″, “0070034″, “0070801″, “0070802″, “0070803″, “0070804″, “0070805″, “0070806″, “0070807″, “0070808″, “0070809″, “0070810″, “0070811″, “0070812″, “0070813″, “0070814″, “0070815″, “0070819″, “0070820″, “0070821″, “0070822″, “0070823″, “0070824″, “0070825″, “0070826″, “0070827″, “0070828″, “0070829″, “0070834″, “0070835″, “0070836″, “0070837″, “0070838″, “0070839″, “0070840″, “0070841″, “0070842″, “0070843″, “0070844″, “0070845″, “0070846″, “0070847″, “0070848″, “0070849″, “0070850″, “0070851″, “0070852″, “0070861″, “0070862″, “0070863″, “0070864″, “0070865″, “0070866″, “0070867″, “0070868″, “0070869″, “0070870″, “0070871″, “0070872″, “0070873″, “0070874″, “0070880″, “0070881″, “0070882″, “0070883″, “0070884″, “0070885″, “0070886″, “0070890″, “0070891″, “0070892″, “0070893″, “0070894″, “0070895″, “0078501″, “0078503″, “0078505″, “0078507″, “0078508″, “0078632″, “0600905″, “0600906″, “0600907″, “0600908″, “0600909″, “0608533″, “0608576″, “0608582″, “0608791″, “0650000″, “0650004″, “0650005″, “0650006″, “0650007″, “0650008″, “0650009″, “0650010″, “0650011″, “0650012″, “0650013″, “0650014″, “0650015″, “0650016″, “0650017″, “0650018″, “0650019″, “0650020″, “0650021″, “0650022″, “0650023″, “0650024″, “0650025″, “0650026″, “0650027″, “0650028″, “0650030″, “0650031″, “0650032″, “0650033″, “0650041″, “0650042″, “0650043″, “0658501″, “0658508″, “0658510″, “0658511″, “0658518″, “0658522″, “0658533″, “0658543″, “0658550″, “0658555″, “0658558″, “0658567″, “0658578″, “0658601″, “0658609″, “0658610″, “0658611″, “0658612″, “0658633″, “0658639″, “0658686″}

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

2009/06/17 郵便専門ネットでバージョン番号を取得

XML-RPC経由で、インターネット上のWebサービスを呼び出すサンプルのAppleScriptです。

たまたまみつけた、「XML-RPCサービス - 郵便専門ネット」というサイトのサービスを呼び出してみます。とりあえず、ごあいさつまでに(サービスの)バージョン番号を取得。

ちなみに、郵便専門ネットさんのWebサービスでは1分間に30回以上呼び出すとエラーになるとのことです。

スクリプト名:郵便専門ネットでバージョン番号を取得
http://yubin.senmon.net/service/xmlrpc/
tell application http://yubin.senmon.net/service/xmlrpc/
  call xmlrpc {method name:”yubin.getVersion“, parameters:{}}
end tell
> “9.05a”

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

2009/06/17 Blogの運用ポリシーを変更

本Blogは、スパムなどの対策のために「コメントを書くために、ユーザー登録していただく」というポリシーで運用してきました。WordPressのプラグインで海外からのスパムコメントは除外できている状態です。

本Blogには、たいしたことのない動作確認用Scriptから、ちょっと公開したくないようなまとまった大きさのScriptまで掲載しています。AppleScriptでプログラムを作るという場合には、そのまま使っていただいて構いませんが、「動かなかった」という情報については必ずフィードバックしてください

自分で書きためたScriptは数千本ありますが、新しいOSやアップデータが出るたびにすべてチェックするわけにも行かないので、「動いた」という情報より「動かなかった」という情報の方がありがたいのです。

円滑なフィードバックのために、ユーザー登録しなくてもコメントが書けるよう設定を変更した次第です。

2009/06/17 AppleScript記述支援システム

飲み会の時に「標準の状態のままでは、AppleScriptを書くのに支援機能が少なすぎる。実際のところはどうなのか?」といったことを知り合いから聞かれたので、MacBook Pro 17インチを取り出して、普段使っている記述支援拡張Scriptを紹介しました。

Mac OS X 10.4からスクリプトエディタはコンテクストメニューからAppleScriptを呼び出して実行できるようになっていますが、素のままのスクリプトエディタでは、たいして生産性を上げることはできません。

かわりに、自前で強化しまくった開発支援用Scriptを入れています。以前に共著で書いた書籍「AppleScriptリファレンス」を持ち歩かなくても済むことを目的に作り始めたものです。実際、このAppleScript記述支援システムを使うようになってからというもの、何も参考書を持ち歩かなくても困らなくなりました。

スクリプトエディタ自体がAppleScriptからコントロールできるアプリケーションなので、記述内容をAppleScript側から走査して、内容を書き換えたり、構文要素を補ったりしています。

アプリケーションへのtellブロックの記述も、コンテクストメニューから呼び出し一発。

sc1.jpg

sc2.jpg

sc3.jpg

巨大なAppleScript同士をつないだりする時に必須な、変数名の置換。この支援Scriptは、構文要素を識別して変数名のみを置換します。

sc10.jpg

sc11.jpg

AppleがOSに標準添付する程度のScriptでは、こんな手の込んだ芸はとても期待できません。

sc20.jpg

ほぼすべてのAppleScriptの構文要素をコンテクストメニューから入力できるようになっています。

sc30.jpg

巨大なAppleScriptの解析のために、スクリプトエディタ内のAppleScriptを解析して、各ルーチンの呼び出し状態をMindJet MindManager上にプロットするAppleScriptのツールも利用しています。

ほかにも、生産性を上げるために……

InDesignなどの、ウンザリするほどプロパティが多いアプリケーションを相手にScriptingするときの労力軽減のために(AppleScript Studioで)作成した、「プロパティ値のdiffツール」。

sc40.jpg

選択中のオブジェクトのプロパティをログで取得しておいて、色をつけたり文字を入力したりして状態を変えたあとにもう一度Scriptでプロパティを取得。前後のプロパティ値をこのdiffツールに入れると、どの部分に変化があったかをレポートしてくれます。

sc41.jpg

もちろん、作りためた大量のAppleScriptライブラリや、海外のMLのログ整理システムなど、紹介し切れないほどの生産性支援システムが稼働していますが……そこまで必要性を感じるかどうかは人それぞれでしょう。

記述支援Scriptについては、インターネット経由でのアップデートのためのシステムさえ作れば、支援Scriptにバグがあったときの差し替えや、Appleが例によってOSにバグを作ったときの回避Scriptを配信できるようになるので、そのあたりちょっと頑張っておきたいところです。

2009/06/16 FireFoxでオープンしているURLを取得。Leopard対応版

FireFoxでオープンしているURLを取得するAppleScriptの、Leopard以降で実装された機能を活用して記述したものです。

Mac OS X 10.4などでは、System Eventsにプロセス一覧を尋ねて、その中にFireFoxが入っていないかどうかを確認することになりますが、Mac OS X 10.5ではrunningというプロパティを取得できるようになったので、これを参照するのがスマートでよいでしょう。

もともとは、shellからAppleScriptを呼び出して、FireFoxの状態を取得したいという相談(?)を持ちかけられたもので……osascriptコマンドでこのAppleScriptを呼び出すといった感じになるかと>masuiさん

スクリプト名:FireFoxでオープンしているURLを取得。Leopard対応版
tell application "Firefox"
  if running then Mac OS X 10.5 or later
    set aURL to «class curl» of window 1
  else
    set aURL to ""
  end if
end tell
return aURL

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

2009/06/16 Dockに登録されている情報を取得する(Leopard以降用)

Dockに登録されているアプリケーション、フォルダ、書類、しまわれたウィンドウの情報を取得します。

uib1.jpg

PreFab UI Browser(仕事でGUI Scriptingを使って自動化を行うのであれば、必須のツール)を用いてDockの内容を確認したところ、属性がローカライズされた状態で取得されていることが判明。最近、DockをAppleScriptからコントロールしていなかったので、気にもしていませんでしたが……この挙動で正しいのかどうかは意見が分かれるところでしょう。

そもそも、UI Element Scripting(=GUI Scripting)が障碍者の操作支援用の機能からはじまったことを思えば、属性名がローカライズされた方がText To Speechの機能で読み上げる際に便利でしょう。

一方、強引にアプリケーションをコントロールするための最終的な機能としてUI Elemenet Scriptingを位置づけるのであれば、OSのバージョンが1つ変わったぐらいでこのあたりの仕様を変えてほしくないところです。

なんにせよ、OSのメジャー/マイナーアップデートのたびにすべてのScriptを走らせてチェックを行うというのも、本来はAppleがやるべき仕事のはずです。

スクリプト名:Dockに登録されている情報を取得する(Leopard以降用)
set dockRes to retDockPrefs() of me
> {apps:{”Finder”, “ML Ranking”, “アクティビティモニタ”, “辞書”, “DragThing”, “Okaeri”, “Safari”, “スクリプトエディタ”, “Mail”, “MacJournal”, “Xcode”, “プレビュー”, “Adobe Photoshop CS3″, “Snood”, “アドレスブック”}, docs:{”tokyo_pod_023.mp3″}, wins:{”Google”, “Free File Hosting Made Simple - MediaFire”, “Write Your Own Automator Actions - O’Reilly Media”, “Canvas”, “起動ディスクの空き容量が搭載メモリ+1Gバイトを切ったら警告”, “選択したファイルの中にあるJPEGファイルを作成日時でソートして連番でリネーム v2″, “東京ポッド許可局アーカイブス”, “アドレスブックでcountry codeが空いている住所で日本の都道府県に該当するものにjpを入れる”, “アドレスブックで特定の会社に所属するpersonの情報のみ抽出”, “アドレスブックで特定住所を含むpersonのみ抽出”, “アドレスブックに入っている会社名の一覧を取得する”, “アドレスブック上で会社の引っ越しを行う実験”, “アドレスブックで選択中の連絡先の情報を取得”}, folders:{”書類”}}

Dockに登録されている情報を取得する(Leopard以降用)
on retDockPrefs()
  tell application System Events
    tell application process Dock
      tell list 1
        アプリケーション
        
set apList to title of every UI element whose description is equal to アプリケーション Dock 項目
        
登録された書類
        
set docList to title of every UI element whose description is equal to 書類 Dock 項目
        
最小化されたウィンドウ
        
set winList to title of every UI element whose description is equal to しまわれたウインドウ Dock 項目
        
フォルダ
        
set folList to title of every UI element whose description is equal to フォルダ Dock 項目
        
      end tell
    end tell
  end tell
  
return {apps:apList, docs:docList, wins:winList, folders:folList}
end retDockPrefs

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

2009/06/16 機種IDを取得する

Macの機種IDを取得するAppleScriptです。

本AppleScriptを実行すると、いま使っているMacBook Pro Core 2 Duo 2.4GHz 17インチのマシンでは、「MacBookPro3,1」が返ってきます。

こうした機種IDと実際の製品名の一覧については、フリー・ソフトウェアの「MacTracker」に情報が掲載されているため、これを参照するのがよいでしょう。

mactrack1.jpg

スクリプト名:機種IDを取得する
set machineID to getMachineID() of me

機種IDを取得する
on getMachineID()
  set a to do shell script ioreg -c CPU -w 0 | head -n 2 | tail -n 1
  
  
set sPos to offset of < in a
  
if sPos = 0 then return “”
  
  
set spPos to offset of +-o in a
  
if spPos = 0 then return “”
  
  
set cpuText to text (spPos + 3) thru (sPos - 1) of a
  
return cpuText
end getMachineID

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

2009/06/16 起動ディスクの空き容量が搭載メモリ+1Gバイトを切ったら警告

起動ディスクの空き容量が、搭載メモリ(Swap分?)+1Gバイトを切ったら警告するAppleScriptです。

大量の画像をコピーして編集/合成するとかムービーの合成をするといった場合、HDDの空き容量を一度確認しておく必要があります。HDDが湯水のように使える昨今では珍しくなりましたが、マシンによっては空き容量ギリギリで動いているものもあります。そうした状況を回避するため、事前にこうしたAppleScriptでチェックしておくとよいでしょう。

MacBook Airなどのマシンでは空き容量ギリギリで動いていることもあるかもしれないので、実行中のマシンの機種IDを取得して、MacBook AirであればHDD空き容量の制限をゆるくするとかいった処理を行ってみてもいいかもしれません。

スクリプト名:起動ディスクの空き容量が搭載メモリ+1Gバイトを切ったら警告
起動ディスクの空き容量が実装メモリ+1Gバイトを切ったら警告
set myRAM to physical memory of (system info) 搭載メモリを求める
set requireHDDspace to myRAM + 1024 メモリ実装分+1GB
set requreHDDspaceStr to (requireHDDspace as string) & 000000

set freRes to chkDiskSpace(requreHDDspaceStr) of me
if freRes = false then
  display dialog HDDの空き容量が足りません with title エラー buttons {”OK“} default button 1
  
return
end if

起動ディスクの空き容量をチェックする
on chkDiskSpace(aLimitStr)
  tell application Finder
    set a to free space of startup disk
  end tell
  
set numberString to Stringify(a) of me
  
  
この記法(considering numeric strings)はMac OS X 10.4以降でないと通じない
  
considering numeric strings
    if aLimitStr > numberString then
      return false
    else
      return true
    end if
  end considering
end chkDiskSpace

指数表示数値を文字列化
on Stringify(x) for E+ numbers
  set x to x as string
  
set {tids, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, {”E+“}}
  
if (count (text items of x)) = 1 then
    set AppleScript’s text item delimiters to {tids}
    
return x
  else
    set {n, z} to {text item 1 of x, (text item 2 of x) as integer}
    
set AppleScript’s text item delimiters to {tids}
    
set i to character 1 of n
    
set decSepChar to character 2 of n “.” or “,”
    
set d to text 3 thru -1 of n
    
set l to count d
    
if l > z then
      return (i & (text 1 thru z of d) & decSepChar & (text (z + 1) thru -1 of d))
    else
      repeat (z - l) times
        set d to d & 0
      end repeat
      
return (i & d)
    end if
  end if
end Stringify

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

2009/06/15 FireFoxでオープン中のURLを取得する

FireFoxでオープン中のURLを取得するAppleScriptです。

FireFoxは、AppleScript的にはろくにコントロールできないダメダメブラウザで、WebブラウザとAppleScriptの連携を行いたい場合には、Safariを使うことが強く推奨されます。

スクリプト名:FireFoxでオープン中のURLを取得する
tell application "Firefox"
  set aURL to «class curl» of window 1
end tell

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

2009/06/14 全国地方公共団体コードのチェックサム算出 v2

日本郵便が配布している郵便番号データをチェックしていたら……掲載されている地方公共団体コードがオリジナルの地方公共団体コードと異なっていることに気付きました。

総務省が全国津々浦々の地方公共団体に付けている「地方公共団体コード」が、財団法人地方自治情報センターのWebで確認できるようになっており、こちらの方が桁数が1桁多いです。

saf1.jpg

▲日本郵便

saf0.jpg

▲郵便番号コードをFileMaker Proにインポート。ただし、地方公共団体コード(f1)の桁数が少ない

saf3.jpg

▲財団法人 地方自治情報センターの(地方公共)団体コード。最下位桁にチェックサムが付いている

よくよく調べたら、日本郵便のデータ(全国版を一括ダウンロード可能)にはチェックサムがなく、財団法人自治情報センターのデータ(一括ダウンロードはできないわ、CSV形式のデータはないわ……ひどいですな)にはチェックサムが1桁付加されており、財団法人地方自治情報センターのページで計算方法を調べてみると………たいした内容ではなかったので、AppleScriptで書いてみました。

ひととおり検算してみ……たわけではいないのですが、問題があったらご指摘ください。

ちなみに、Intel Core 2 Duo 2.4GHzのMacBook Proで、1万回チェックサムを計算させて2秒弱。これを遅いと見るか速いと見るかは個人差があると思いますが、世間でよく(ASのことを)知らない人が「遅い遅い」と言っているのを見ると、「そうかな?」と思ってしまうところです。

スクリプト名:全国地方公共団体コードのチェックサム算出 v2
set chkSum to chkModulas11(”01100“) of me

全国地方公共団体コードのチェックサム算出
on chkModulas11(aCodeNumStr)
  
  
if length of (aCodeNumStr as string) is not equal to 5 then return false
  
set cList to characters of (aCodeNumStr as string)
  
set aMultNum to 6
  
set aRes to 0
  
  
第1桁から第5桁までの数字に、それぞれ6.5.4.3.2を乗じて算出した積の和を求め
  
repeat with i in cList
    set j to i as number
    
set aRes to aRes + j * aMultNum
    
set aMultNum to aMultNum - 1
  end repeat
  
  
if aRes < 11 then
    ただし、積の和が11より小なるときは、検査数字は、11から積の和を控除した数字とする
    
set eRes to 11 - aRes
  else
    通常パターン
    
その和を11で除し、商と剰余(以下「余り数字」という。)を求めて
    
set cRes to aRes mod 11 余りだけでよいのでは? 商を求めなくても余りは計算可能
    
set dRes to 11 - cRes
    
set eRes to last character of (dRes as string) 下1桁の数字を検査数字とする    
  end if
  
  
return eRes as number
end chkModulas11

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

2009/06/13 6/13にTMUGのMeetingで新作「Moving Agency」をデモ

直前になっての告知です。6/13(土)に市ヶ谷で行われるTMUG(Tokyo Macintosh Users Group)の例会で、最新の自作アプリケーションのデモを行います。

アドレスブック上で会社の名称変更(例:アップルコンピュータ株式会社→アップルジャパン株式会社)および所在地変更などの作業を一括で行う、いわばアドレスブックの引っ越し屋さんアプリケーションです。もちろん、100%AppleScriptで記述しています。

→ 東京マッキントッシュ・ユーザーズグループ

2009/06/13 津田大介氏の最近の発言を取得してMacJournalにスクラップする

twitterrificをコントロールして、津田大介氏のtwitter上の発言を集めて、時系列順に並べかえ直して、MacJournalの指定のジャーナル内に新規ジャーナルエントリを作成して、そこに文章を入れるAppleScriptです。

mj11.jpg

▲twitteriffic上で津田大介氏によるテキスト中継が行われている様子

mj10.jpg

▲スクリプト実行後 MacJournalの指定エントリに発言内容がまとめられている

スクリプト名:津田大介氏の最近の発言を取得してMacJournalにスクラップする
津田大介氏のtwitter上の発言を集めてテキスト化
tell application "Twitterrific"
  set tList to every tweet whose screen name is equal to "tsuda"
  
set textList to {}
  
repeat with i in tList
    set the end of textList to {date of i, text of i}
  end repeat
end tell

set sortedList to shellSortListAscending(textList, 1) of me

set pureText to {}
repeat with i in sortedList
  set {aDate, aText} to i
  
set the end of pureText to (aText & return & return)
end repeat

set pureText to pureText as string

Journalの階層状況は個人によって異なるので、このまま動くわけではありません
ご自分の環境に合わせて書き換えて使ってみてください
tell application "MacJournal"
  tell document 1
    tell journal "個人"
      tell journal "業界動向"
        tell journal "音楽配信"
          tell journal "津田大介"
            set jRes to make new journal entry
            
tell jRes
              set plain text content to pureText
            end tell
          end tell
        end tell
      end tell
    end tell
  end tell
end tell

シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

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