Archive for 10月, 2012

2012/10/27 AppleScript EditorのEaster Egg、日本語環境にはなし

AppleScript Editor上で252文字以上の長さの変数を使用すると、エラーメッセージが表示され……その内容がイースターエッグなのだそうで(→ AppleScript Easter Egg: Way too long, dude.)。

ただし、この表示は日本語環境では再現しません。

asedit_1.png

asedit_2.png

理由はいろいろあるかと思われますが、Mac OS XやiOSのOSメッセージのローカライズをApple自身が行っているわけではない、と考えると納得が行きます。

loc1.png

The OmniGroupのソフトウェアのAbout画面に「翻訳:LocTeam」の表示があり、探してみるとLocTeamのWebサイトが簡単に見つかります。

このLocTeamのWebサイトを見ると、Mac OS XやApple純正アプリのローカライズをこの会社が担っていることが分ります。Appleは核となる英語の文字リソース部分のみ作り、LocTeamに各国語へのローカライズを依頼している……と見るのが妥当でしょう。

そうした仕事のやりとりの中で、オリジナルの文字リソースの意味と、各国語へのローカライズ後の内容で意図が(正しい方に)変わるというのはありえる話です。Appleのエンジニアの悪ふざけをLocTeamがローカライズ時に修正したものと推察されます。

2012/10/27 OS X v10.8.2 追加アップデート 1.0がMail.appのAppleScript系のバグを修正

「OS X v10.8.2 追加アップデート 1.0」は非常に変則的なOSのアップデートでしたが、Mac OS X 10.6以来ながらく発生していたMail.appのバグを修正するものでした。

Mac OS X 10.6以降、AppleScriptからMail.app上でフォルダを作成すると、一番末尾にフォルダが並んでしまうというバグです。GUI側から作成したフォルダはABC順に並ぶのですが、AppleScript側から作成するとまともにソートされず、既存のフォルダの後に追加される格好になっていました。

これが、OS X v10.8.2 追加アップデート 1.0によって修正され、長らく悩まされていたMail.appのバグが直ったのでした。

ただ、急に直るということは……逆に、バグが復活する可能性もあるわけで、アップデートのたびに確認すべき項目であるともいえます。もちろん、リリース前にAppleのエンジニア自身が確認すべきことは言うまでもありません。

2012/10/27 iBooks Author 2.0も依然としてAppleScript非対応

縦書きの電子ブックを作成できるようになったiBooks Author v2.0。他の機能には目もくれず、真っ先にAppleScriptエディタでAppleScript用語辞書をチェック。これが、あいかわらずAppleScriptにまともに対応していないことを確認しました。用語辞書があっても、あるだけです。残念!

一応、AppleScript用語辞書はオープンできるものの、オブジェクトの定義がうそっぽいのと、本来必要だと思われるコマンドが搭載されておらず……Appleのエンジニア(もしくは外注の会社)が「仕事しているフリ」をしているようにしか見えません。

おまけに、Apple純正ソフトウェアにもかかわらずRetinaアイコンに対応していないという、「手抜き感」あふれる仕上がりです。

本来、AppleScriptに対応して他のアプリケーションで組まれたデータを大量に電子ブックに変換するフローを構築する礎になるべき存在だと思うのですが、そこまでは手が回っていないということでしょうか。

ibooksauthor.png

スクリプト名:iBooks Author v2.0のScripting(最低限、使い物にならない)対応度の調査
tell application “iBooks Author”
  properties
  
–> {name:”iBooks Author”, frontmost:false, class:application, version:”2.0″}
  
  
–make new document
  
–> 新規ドキュメントの作成はできない。ただし、GUIから作成したときに「名称未設定2」のように数字はカウントアップされている
  
  
tell document 1
    properties
    
–> {name:”名称未設定 2″, path:missing value, class:document, modified:false}
    
    
(*
    set aList to every item
    –> error “iBooks Author でエラーが起きました:every item of document 1 を取り出すことはできません。” number -1728 from every item of document 1
    *)

  end tell
  
  
(*
  tell window 1
    properties
    –> error “iBooks Author でエラーが起きました:window 1 を取り出すことはできません。正しくないインデックスです。”
  end tell
  *)

end tell

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

2012/10/21 MacTech Magazine最近の動向

img_0176.PNG

いまひとつ紙のバージョンが電子ブックになるのに時間がかかるMacTech Magazine。とくにこの夏あたりは遅れ気味。いま10月下旬ですが、2012年8月号までしか電子ブックで出ておりません。

この半年ほどの間の、AppleScript/AppleScriptObjC関連記事インデックスです。

2012/8
「Understanding AppleScript Dictionaries」……AppleScript用語辞書を作る際の解説記事(7ページ)。

2012/6
「A Better Editor with AppleScript ObjC」……AppleScriptObjCでテキストエディタを作成する記事。サンプルのProjectもダウンロード可能(10ページ)
「Dragging On with AppleScriptObjC」……AppleScriptObjCでドラッグ&ドロップ(WindowやViewの上で)する原理を説明する記事(9ページ)

とくに、2012/6がおすすめです。

もう少しテンポよく電子ブック版も発売してほしいものです。あと、バックナンバー(1年分)を出すとか。

2012/10/21 AppleScriptObjC Exploredの4訂版がリリース

Shane StanleyによるAppleScriptObjCのバイブル「AppleScriptObjC Explored」の第4訂版がリリースされました。同書籍はPDF+サンプルコード(25以上のプロジェクト)+補助コード(Myriad Helper)で提供される電子書籍です。

英語で書かれていますが、図版が多用されており、それほど難しい用語も使っていないので、あまり難しいとは思いません(ただ、後半の方が内容が簡単なので、後半の「Reference Section」を先に読む方が分りやすいかも、、、)。

書籍部分はPDFであるため、検索やコピーが容易で、iPadやiPhoneに転送してGood ReaderなどのPDFリーダーで読むこともできます(私もよく電車の中でiPadで読んでいます)。お好みとあらば、カラーレーザープリンターで印刷して紙で読むこともできるでしょう(258ページあります)。

asocv4.png

この4訂版は、Mac OS X 10.8とXcode 4.5に対応したもので、前バージョンの3訂版を購入したユーザーには2012年12月31日までは割引が適用されており、昨日私が購入したところ917円でした。

AppleScriptObjCの情報としては、これ以上正確なものは存在していない(Appleがドキュメントを出していないため)ので、AppleScriptObjCでプログラムを組みたいユーザーはこれを買って読むのが最も確実で正確な方法です。

2012/10/17 Photoshopで指定ファイルをオープン

Photoshop CS3のバグに負けずに指定ファイルをオープンするAppleScriptです。

AdobeのアプリケーションのScriptingは、Adobeの作ったアプリケーション側のバグと、AppleがOSに作ったバグの狭間で「これはどちらのバグでしょうかね〜」と途方に暮れながら対策を考えたり、場合によっては実現不可能なものとして「あきらめる」というハードな作業を伴います。

指定のファイルをオープンするだけでも命がけ、パスの階層が深い場所にあるファイルはオープンできなかったり、ファイル名およびパス名のどこかに全角英数字および全角スペースが入っていた場合にもファイルのオープンが行えません(しかも、何の警告メッセージもなしに)。

そこで、ファイルをオープンできなかった場合、上記の2つのケースに対処するように試みてみました。フォルダ階層が深かった場合にはデスクトップにコピーしてからオープンを試み、さらにオープンできなかった場合にはファイル名をuuidgenから生成した「安全な」ファイル名に付け替えてオープンを試みます。

スクリプト名:Photoshopで指定ファイルをオープン
set aFile to choose file

set pRes to openPSDCS3file(aFile) of me –ファイルオープン完了時にはtrueが、オープンできなかった場合には {false,erMesList} のリストが返る

–Photoshop CS3の2つのバグに対応したファイルオープンルーチン
on openPSDCS3file(aFile)
  
  
set erMesList to {}
  
  
–Trial Level 1
  
–通常のファイルオープン
  
tell application “Adobe Photoshop CS3″
    close every document
    
try
      open aFile
      
return true
      
    on error erMes
      –オープン対象のファイルの場所が深すぎるとオープンできない
      
set the end of erMesList to erMes –エラーメッセージを保存
    end try
  end tell
  
  
–そもそもPhotoshopでオープンできないファイルを指定された場合
  
if erMes = “ファイルを開くオプションが正しくないため、ファイルを開けません” then –Wrong File Format Error
    return {false, erMesList}
  end if
  
  
  
–Trial Level 2
  
–フォルダが深かった場合にオープンできないバグに対応。デスクトップにコピーしてオープン
  
  
–エラー発生時の対応(たぶん、フォルダが深かった)
  
set dPath to path to desktop
  
set dPath to dPath as string
  
  
tell application “Finder”
    set dResFile to (duplicate aFile to folder dPath)
  end tell
  
set dResAlias to dResFile as alias
  
  
  
tell application “Adobe Photoshop CS3″
    close every document
    
try
      open dResAlias
      
return true
      
    on error erMes
      –オープン対象のファイルの場所が深すぎるとオープンできない
      
set the end of erMesList to erMes –エラーメッセージを保存
    end try
    
  end tell
  
  
  
–Trial Level 3
  
–ファイル名に全角数字および全角アルファベットが含まれていた場合にオープンできないバグ
  
  
–ファイル名がダメだったと仮定して、さらに安全な名前にリネームしてオープン)
  
set rndName to do shell script “/usr/bin/uuidgen”
  
tell application “Finder”
    set aExt to name extension of dResAlias
    
set tName to rndName & “.” & aExt
    
set name of dResAlias to tName
  end tell
  
  
  
tell application “Adobe Photoshop CS3″
    close every document
    
try
      open dResAlias
      
return true
      
    on error erMes
      –オープン対象のファイルの場所が深すぎるとオープンできない
      
set the end of erMesList to erMes –エラーメッセージを保存
    end try
    
  end tell
  
  
–2つのバグ以外のバグに遭遇した場合には、ギブアップ
  
return {false, erMesList}
  
end openPSDCS3file

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

2012/10/14 ディスプレイ解像度の変更を検出

ディスプレイ解像度の変更を検出するAppleScriptObjCのプログラムです。

検出してどーするんだ? という疑問は残りますが、割と手軽に検出できます。なにせ、ハンドラ1つを追加するだけですから。

→ Xcode Project をダウンロード

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– screenresolDetector

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


script AppDelegate
  property parent : class “NSObject”
  
property aWin : missing value
  
property aWinTitle : missing value
  
  on applicationWillFinishLaunching_(aNotification)
    – Insert code here to initialize your application before any files are opened
  end applicationWillFinishLaunching_
  
  on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
  
  –ディスプレイ解像度の変更を検出
  
on applicationDidChangeScreenParameters_(sender)
    
    say “Display Resolution Changed”
    
–aWin’s setTitle_(”Resolution Changed”)
    
  end applicationDidChangeScreenParameters_
end script

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

2012/10/07 Skimでオープン中のPDFの現在のページの内容をOmniGraffleにペースト

オープンソースのPDFビューワー「Skim」でオープン中のPDFの表示中のページの内容をそのままOmniGraffleの現在表示中のページ(canvas)にペーストするAppleScriptです。

現在、PDFビューワーのうちScriptableなものといえばAdobe AcrobatとSkim。Acrobatはインストールしてもいいことがあまりないように(個人的に)感じるので、ほぼ知り合いにはSkimのインストールをお願いしています。Mac OS X標準添付のプレビュー.appは(そのままでは)AppleScriptからはコントロールできないので、Skimはおすすめです。

本AppleScriptはSkimでオープン中のPDFの、現在表示中のページの内容を取得して……

skim_to_omni1.png

OmniGraffleの現在表示中のページ(Canvas)にその内容をペーストします。

skim_to_omni2.png

Skimには、指定の座標内の内容を取得する「grab」コマンドがあるので、取得した内容をそのままOmniGraffleに持って行けばいいだろうかと考えて一度試してみたのですが……思ったようには動かず、結局地道に「Grabした内容を一度ファイルに書き出して、OmniGraffleに書き出したPDFを読み込む」というやり方に落ち着きました。

喫茶店でコーヒー1杯飲むぐらいの時間で作ったので、処理自体はかなり適当です。一時的にTemporary Items Folderに書き出したPDFファイルのゴミ捨て処理なども行っていません。現在表示中のページのみを処理するようにしてありますが、AppleScript的に一括処理を行うのであれば、Skimで表示中のPDFのすべてのページをループで処理してOmniGraffleにインポートするように書き換えるとよいでしょう。

スクリプト名:Skimでオープン中のPDFの現在のページの内容をOmniGraffleにペースト

set outFol to (path to temporary items from system domain) as string
set cName to do shell script “/usr/bin/uuidgen”

tell application “Skim”
  tell document 1
    tell current page
      set bList to bounds –{Left, Top, Right, Bottom} —> {0, Height, Width, 0}
      
set anImage to grab for bList –as PDF
    end tell
  end tell
end tell

set bbList to {contents of third item of bList, contents of second item of bList}

set target_file to outFol & cName
write_to_file(anImage, target_file, false) of me

makeShapeWithProperty(missing value, target_file, {0, 0}, bbList, “”, true) of omniGroupScriptLib

–指定画像ファイルを現在のドキュメントにインポートする
–Omni Groupの配布しているScriptから、関係ないルーチンとプロパティを削除してほぼそのまま使用
script omniGroupScriptLib
  
  
on makeShapeWithProperty(onCanvas, myFile, aPositionList, aSizeList, aURL, outLineFlag)
    using terms from application “OmniGraffle 5″
      tell application “OmniGraffle 5″
        tell document 1
          tell canvas 1
            set theShape to make new shape at front of graphics with properties {origin:aPositionList, thickness:0.5, fill:no fill, draws stroke:outLineFlag, size:aSizeList, draws shadow:false, autosizing:overflow}
            
            
set url of theShape to aURL
            
            
getPicture(theShape, myFile) of me
            
            
–後からこれらの属性をセットするのがミソ
            
set image sizing of theShape to stretched –ここが重要!!!
            
set size of theShape to aSizeList
            
            
return theShape
          end tell
        end tell
      end tell
    end using terms from – OmniGraffle
  end makeShapeWithProperty
  
  
  
– make the shape - I can’t get the import construct to work - so I make a shape and set its fill with the image.
  
on makeShape(onCanvas, myFile)
    using terms from application “OmniGraffle 5″
      tell application “OmniGraffle 5″
        tell onCanvas
          set theShape to make new shape at front of graphics with properties {origin:{0, 0}, thickness:0.0, fill:no fill, draws stroke:false, image scale:1, size:{20, 20}, draws shadow:false}
          
getPicture(theShape, myFile) of me
          
return theShape
        end tell
      end tell
    end using terms from – OmniGraffle
  end makeShape
  
  
– Get the dropped image, get it’s size and set it as a fill to the shape, and some (adjustable) settings.
  
on getPicture(theShape, myFile)
    set filePath to (myFile) as string
    
set posixPath to POSIX path of file filePath
    
try
      tell application “Image Events”
        launch
        
set this_image to open filePath
        
set the props_rec to the properties of this_image
        
copy (dimensions of props_rec) to {myX, myY}
        
close this_image
      end tell
    end try
    
    
using terms from application “OmniGraffle 5″
      tell application “OmniGraffle 5″
        ignoring application responses
          set image of theShape to posixPath
          
set image sizing of theShape to manual
          
set image scale of theShape to 0.5 ——-Retina Displayなので
          
set image offset of theShape to {0, 0}
          
set size of theShape to {myX, myY}
          
–select theShape
        end ignoring
      end tell
    end using terms from
  end getPicture
  
  
return theShape
  
end script

–ファイルの追記ルーチン「write_to_file」
–追記データ、追記対象ファイル、boolean(trueで追記)
on write_to_file(this_data, target_file, append_data)
  try
    set the target_file to the target_file as text
    
set the open_target_file to open for access file target_file with write permission
    
if append_data is false then set eof of the open_target_file to 0
    
write this_data to the open_target_file starting at eof
    
close access the open_target_file
    
return true
  on error error_message
    try
      close access file target_file
    end try
    
return error_message
  end try
end write_to_file

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