Archive for 10月, 2015

2015/10/29 指定フォルダ内のフォルダのみを取得する

Cocoaの機能を用いて、指定フォルダ以下のフォルダだけを取得するAppleScriptです。

こちらも、US AppleのAppleScript Users MLにShane Stanleyが投稿したものです。ただ、まっとうに処理しているので・・・実行にはそれなりに時間がかかります。Spotlightの機能を用いて取得した方がはるかに高速です。

フォルダだけを抽出するのであればSpotlightを用いることになるでしょうけれど、この用途「以外」で何か別の用途で活用できる雰囲気がしています。

AppleScript名:ASOCで指定フォルダ内のフォルダのみを取得する
– Created 2015-10-13 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set thePath to POSIX path of (choose folder)
set fListRes to my getFoldersIn:thePath
–>  {file "Macintosh HD:Users:me:Pictures:2014カレンダー表紙?", file "Macintosh HD:Users:me:Pictures:ASBook", file "Macintosh HD:Users:me:Pictures:ASBook:AS_beginner", file "Macintosh HD:Users:me:Pictures:Camera Roll", file "Macintosh HD:Users:me:Pictures:DESIGN GARDEN PROJECT", ….

on getFoldersIn:posixPath
  script spd
    property allItems : {}
  end script
  
  
set allItems of spd to {}
  
  
– make URL
  
set theNSURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
– make file manager
  
set theNSFileManager to current application’s NSFileManager’s new()
  
  
– get URL enumerator
  
set theNSFileEnumerator to theNSFileManager’s enumeratorAtURL:theNSURL includingPropertiesForKeys:{current application’s NSURLIsDirectoryKey, current application’s NSURLIsPackageKey} options:((current application’s NSDirectoryEnumerationSkipsPackageDescendants) + (current application’s NSDirectoryEnumerationSkipsHiddenFiles as integer)) errorHandler:(missing value)
  
  
– get all items from enumerator
  
set (allItems of spd) to theNSFileEnumerator’s allObjects()
  
set theFolders to {} – to store folders
  
  
– loop through
  
repeat with i from 1 to count of (allItems of spd)
    – is it a directory?
    
set {theResult, isDirectory} to ((item i of (allItems of spd))’s getResourceValue:(reference) forKey:(current application’s NSURLIsDirectoryKey) |error|:(missing value))
    
if isDirectory as boolean then
      set {theResult, isPackage} to ((item i of (allItems of spd))’s getResourceValue:(reference) forKey:(current application’s NSURLIsPackageKey) |error|:(missing value))
      
      
– is it not a package?
      
if not isPackage as boolean then
        set end of theFolders to (item i of (allItems of spd))’s |path|() as «class furl»
      end if
    end if
  end repeat
  
  
return theFolders
end getFoldersIn:

★Click Here to Open This Script 

2015/10/29 指定パスの可視、不可視を設定

Cocoaの機能を用いて指定パス(~/Libraryとか)の可視/不可視を設定するAppleScriptです。

Shane StanleyがAppleScript Users MLに投稿した内容を使いやすいように変更したものです。最初のバージョンでは可視/不可視の設定をトグルで指定するようになっていたのですが、それだと使いにくいので、明確にtrue/falseで指定するようにしました(falseで可視、trueで不可視)。

AppleScript名:ASOCで指定パスの可視、不可視を設定
– Created 2015-10-28 by Shane Stanley
– Modified 2015-10-29 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

setInvisibleOfThePath(“~/Library”, false) of me –falseで可視、trueで不可視

–指定パスの可視、不可視の設定
on setInvisibleOfThePath(posixPathStr, aBool)
  set anNSString to current application’s NSString’s stringWithString:posixPathStr
  
set anNSURL to current application’s |NSURL|’s fileURLWithPath:(anNSString’s stringByExpandingTildeInPath())
  
set theKey to current application’s NSURLIsHiddenKey
  
set {theResult, oldValue} to anNSURL’s getResourceValue:(reference) forKey:theKey |error|:(missing value)
  
anNSURL’s setResourceValue:(aBool) forKey:theKey |error|:(missing value)
end setInvisibleOfThePath

★Click Here to Open This Script 

2015/10/28 Keynote 6.6のじっけん(4)〜グラフを作成

Keynote 6.6をAppleScriptから操作してグラフを作成するじっけんです。

iworkautomarion.com掲載Scriptの内容をそのまま実行しようにも、各種名称がローカライズされてしまっているので、そのままでは動かないため書き換えました(あと、趣味に合わせて微調整)。

keynote_2dpie.png

いろいろ数値で調整してみましたが、うまくグラフが中央にこないので適当なところでごまかしています。

AppleScript名:Keynote 6.6でドキュメントを新規作成してグラフ(2D円グラフ)を作成
set targWidth to 500
set targHeight to 500

tell application “Keynote”
  set thisDocument to make new document with properties {height:764, width:1024, document theme:theme “ブラック”}
  
  
tell thisDocument
    
    
set aHeight to height
    
set aWidth to width
    
    
tell slide 1
      set base slide to master slide “タイトル(上)” of thisDocument
      
set object text of default title item to “2D円グラフ”
      
      
tell default title item
        set height to 80
      end tell
      
      (
add chart row names {“ROW A”} column names {“COL A”, “COL B”, “COL C”} data {{103, 25, 30}} type pie_2d group by chart column)
      
      
tell chart 1
        
        
set width to targWidth
        
set height to targHeight
        
        
set position to {(aWidth / 2) - (targWidth / 2), (aHeight / 2) - (targHeight / 2) + 20}
        
      end tell
      
    end tell
  end tell
end tell

★Click Here to Open This Script 

2015/10/28 Keynote 6.6のじっけん(3)〜表を作成してデータで埋める

Keynote 6.6でドキュメントを新規作成し、スライド(ページ)を追加して、そこに表(table)を作成してすべてのセルをデータで埋めるAppleScriptです。

kn_table.png

AppleScript名:Keynote 6.6でテーブルを新規作成してデータで埋める
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
tell application "Keynote"
  set aDoc to (make new document with properties {document theme:theme "ホワイト", width:1024, height:768}) –Normal Slide
  
–set aDoc to (make new document with properties {document theme:theme "ホワイト", width:1920, height:1080})–Wide Slide
  
tell aDoc
    set aSlide to make new slide at end with properties {base slide:master slide "空白"}
    
    
tell aSlide
      set aTable to make new table with properties {row count:10, column count:3}
      
      
tell aTable
        set cCount to count every cell
        
        
repeat with i from 1 to cCount
          set value of cell i to (i as text)
        end repeat
        
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

2015/10/28 Keynote 6.6のじっけん(2)〜放射状にラインを引く

Keynote 6.6でドキュメント上に放射状にラインを引くじっけんです。手作業ではさすがにかったるい内容ですが、AppleScriptからであれば「やってみようかな」という気になる内容です。

実行にはShane StanleyのAppleScriptライブラリ「BridgePlus」をあらかじめインストールしておく必要があります。

kn1.png

(少々ごまかしつつも)さっくりできました。拡大するとこんなかんじです。

実用性はひたすらありませんが、こういう操作ができるようになったのかと思うと感慨深いものがあります。

kn2.png

AppleScript名:Keynote 6.6で放射状にラインを引く
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use bPlus : script “BridgePlus”

set aNum to 250

load framework

tell application “Keynote”
  –新規ドキュメント作成
  
set aDoc to (make new document with properties {document theme:theme “ホワイト”, width:1024, height:768})
  
–set aDoc to (make new document with properties {document theme:theme “White”, width:1024, height:768})
  
tell aDoc
    set aHeight to height
    
set aWidth to width
    
    
set aCenterW to aWidth / 2
    
set aCenterH to aHeight / 2
    
    
set aMas to master slide “空白”
    
–set aMas to master slide “Blank”
    
    
tell slide 1
      set base slide to aMas
      
      
repeat with i from 1 to 130 by 6
        set {x, y} to calcSinCos(i, aCenterW, aCenterH, aNum) of me
        
make new line with properties {start point:{aCenterW, aCenterH}, end point:{x, y}, rotation:i}
      end repeat
      
    end tell
  end tell
end tell

on calcSinCos(i, aCenterW, aCenterH, aNum)
  tell current application
    set aSinNum to (current application’s SMSForder’s sinValueOf:i)
    
set aCosNum to (current application’s SMSForder’s cosValueOf:i)
    
set x to ((aNum * (aSinNum as real))) + aCenterW
    
set y to (aNum * (aCosNum as real)) + aCenterH
    
return {x, y}
  end tell
end calcSinCos

★Click Here to Open This Script 

2015/10/28 Keynote 6.6のじっけん(1)

先日Keynote、Pages、Numbersがアップデートされたので、実際にどの程度(AppleScript的に)使い物になってきたのかじっけんしてみました。

kn66.png

ごあいさつ:アプリケーションのプロパティを取得

このレベルで問題が出たら大変ですが、さすがにそういうことはありません。

AppleScript名:Keynote 6.6でアプリケーションのプロパティを取得する
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
tell application “Keynote”
  properties
  
–> {frozen:true, class:application, playing:false, version:”6.6″, slide switcher visible:false, name:”Keynote”, frontmost:false}
end tell

★Click Here to Open This Script 

ドキュメントの新規作成

アプリケーション側はバグっていないんですが、KeynoteのAppleScript用語辞書に掲載されている「サンプル」が間違っています。

apple_sample.png

本当はwidthとheightを指定するのですが、用語辞書のサンプルではdocument widthとdocument heightと書かれています。ちなみに、先日更新されたiworkautomation.comのKeynoteの説明では、widthとheightを指定していますね(アプリケーションの用語辞書も直そうよ、、、、、)。

Master slideの名称やthemeの名称を調べてみると、このへんローカライズされています。フランス語とか日本語とか、利用者の言語環境が異なると(英語以外だと)AppleScriptを修正する必要があるので、この手の「ローカライズしすぎ問題」はどうにかならないものでしょうか(Appleがローカライズの外注に細かく指定してないからこうなる)。

AppleScript名:Keynote 6.6でドキュメントを新規作成して指定可能なマスタースライド一覧を取得
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  –Keynoteの用語辞書のサンプルどおりに書いても動かない!!
  
set aDoc to (make new document with properties {document theme:theme “ホワイト”, width:1920, height:1080})
  
  
tell aDoc
    set masList to name of every master slide
    
–> {”タイトル & サブタイトル”, “画像(横長)”, “タイトル(中央)”, “画像(縦長)”, “タイトル(上)”, “タイトル & 箇条書き”, “タイトル、箇条書き、画像”, “箇条書き”, “画像(3 点)”, “引用”, “写真”, “空白”}
  end tell
end tell

★Click Here to Open This Script 

ちょっと順番が狂いましたが、新規ドキュメント作成時に指定可能なテーマ名の一覧も取得できます。こちらも名称はすべてローカライズされたものが取得されますし、ローカライズされた名称で指定することになります。

AppleScript名:Keynote 6.6で利用可能なテーマの一覧を取得
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  set installedThemes to name of every theme
end tell
–> {”ブラック”, “ホワイト”, “グラデーション”, “ショールーム”, “モダンタイプ”, “展示”, “ドラフト”, “写真エッセイ”, “クラシック”, “スレート”, “クリームペーパー”, “アルチザン”, “即興”, “ルネッサンス”, “写真ポートフォリオ”, “論説”, “京都風”, “ブラシ塗りキャンバス”, “活字組”, “モロッコ風”, “クラフト”, “インダストリアル”, “モダンポートフォリオ”, “ハーモニー”, “方眼紙”, “ブループリント”, “フォーマル”, “革装本”, “ビンテージ”, “ハードカバー”, “布装本”, “黒板”, “羊皮紙”}

–CAUTION: Name of Keynote themes are *localized*

★Click Here to Open This Script 

利用可能なテーマすべてで新規ドキュメントを作ってみました。たまーに、指定しても指定できないものが入っているケースがあるので、すべて新規作成できることを確認しておくことには意味があります(本当)。

AppleScript名:Keynote 6.6で利用可能なテーマすべてで新規ドキュメント作成
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  set installedThemes to name of every theme
  
repeat with i in installedThemes
    set j to contents of i
    
make new document with properties {document theme:theme j}
  end repeat
end tell

★Click Here to Open This Script 

スライドの新規作成

Keynoteでは、書類(document)の下に存在する各ページのことをslideと呼びます。このslideの新規作成を実験してみました。

AppleScript名:Keynote 6.6で新規ドキュメント&スライド作成
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  –Keynoteの用語辞書のサンプルどおりに書いても動かない!!
  
set aDoc to (make new document with properties {document theme:theme “ホワイト”, width:1024, height:768}) –Normal Slide
  
–set aDoc to (make new document with properties {document theme:theme “ホワイト”, width:1920, height:1080})–Wide Slide
  
  
tell aDoc
    set masList to name of every master slide
    
–> {”タイトル & サブタイトル”, “画像(横長)”, “タイトル(中央)”, “画像(縦長)”, “タイトル(上)”, “タイトル & 箇条書き”, “タイトル、箇条書き、画像”, “箇条書き”, “画像(3 点)”, “引用”, “写真”, “空白”}
  end tell
  
  
tell aDoc
    repeat with i from 1 to 10
      make new slide at end with properties {base slide:master slide “タイトル(上)”}
      
    end repeat
  end tell
end tell

★Click Here to Open This Script 

スライドのタイトルにアクセス

まだうまく使いこなせていませんが、スライドのタイトルに文字を突っ込めますね。フォントサイズも指定可能で、フォントも指定できます。

その一方で、左寄せ(left align)といった指定ができないのが気になります。あらかじめテーマで(画面上から手動で)定義しておくということでしょうか。

AppleScript名:Keynote 6.6でslideのタイトルにアクセス
– Created 2015-10-27 by Takaaki Naganoya
– 2015 Piyomaru Software
tell application “Keynote”
  tell document 1
    tell slide 1
      tell default title item
        properties
        
–> {opacity:100, parent:slide 1 of document id “9F67B27D-BAEC-4B87-9829-DE3823B54533″ of application “Keynote”, class:shape, reflection showing:false, background fill type:no fill, position:{75, 35}, object text:”", width:874, rotation:0, reflection value:0, height:170, locked:false}
        
tell object text
          properties
          
–> {font:”HiraKakuProN-W3″, color:{0, 0, 0}, class:word, size:80}
          
          
set size to 80
          
        end tell
        
        
set object text to “ぴよまるさんだよ〜”
        
        
–left/right/center alignment の定義はない
        
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

2015/10/26 ASOCによるファイルの移動

Cocoaの機能を用いてファイルを移動(move)するじっけんです。

Pure AppleScriptであればFinder経由でmove… to …with replacingで強制移動。do shell script経由でmvしてもいいですし、それほど大変な内容ではない「ファイルの移動」。

これを、Cocoaの機能(NSFileManager)経由で書いて、共有フォルダの内容を(処理後に)処理終了フォルダへ移動させようとしたところ、エラーが出て行えませんでした。正確にいえば・・・移動できることもあれば、移動できないこともありました。

ただ、Pure AppleScriptで書くとなんてことはない処理なので、Pure AppleScript版にルーチンだけ差し替えてそのまま使いましたが、NSFileManagerでなぜうまく処理できなかったのかをUS AppleのAppleScript Users ML上で質問。

ShaneとML上でやりとりして、「移動先に同名のファイルが存在していたから」という、ちょっと恥ずかしい初歩的な原因が判明。移動先フォルダにすでに同じ名前のファイルが存在していたら、削除するというあたりの処理を教えてもらいました。

一応、3回トライするように書き変えてみたものがこれです。NSFileManagerについては、US AppleのCocoa Dev MLでいろいろと揉めた形跡を見つけており「NSFileManagerで埒があかない場合には、NSFileHandle経由でファイルをreadしてmove先にwriteしろ」とかいう、体育会系の回答を見つけており、そういう手段をとらずにすんで本当に助かりました(^ー^;;;

AppleScript名:ファイルの移動テスト v1.3
– Created 2015-10-26 by Takaaki Naganoya
– Modified 2015-10-26 by Shane Stanley
– Modified 2015-10-26 by Takaaki Naganoya

– ネットワークごしにコピーされたファイルの取得と移動に関するテスト

use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set inFolAlias to choose folder

set pdfList to getFilePathList(inFolAlias, “.pdf”) of me
–>  {”/Users/xxxxxxx/Desktop/XXXXXPDF/00064452.PDF”, “/Users/xxxxxxx/Desktop/XXXXXPDF/00064453.PDF”, “/Users/xxxxxxx/Desktop/XXXXXPDF/00064455.PDF”}

my moveFilesWithPOSIXstrList(pdfList, “~/Pictures/DonePDF”)

–POSIX pathのリストを指定フォルダに移動
on moveFilesWithPOSIXstrList(aFileList, toFolStr)
  set pathString to current application’s NSString’s stringWithString:toFolStr
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
set defM to current application’s NSFileManager’s defaultManager
  
  
repeat with i in aFileList
    if (defM’s isReadableFileAtPath:i) as boolean = true then
      set fromPath to (current application’s |NSURL|’s fileURLWithPath:i)
      
      
set fileName to fromPath’s lastPathComponent()
      
set newPathStr to (newPath’s stringByAppendingPathComponent:fileName)
      
set toPath to (current application’s |NSURL|’s fileURLWithPath:newPathStr)
      
set hitF to false
      
      
repeat 3 times
        set {theResult, theError} to (defM’s moveItemAtURL:fromPath toURL:toPath |error|:(reference))
        
        
–試してダメだった場合
        
if (theResult as boolean) = false then
          log {“Error: Something wrong with file moving…”, (theError’s |description|() as text), toPath}
          
if (toPath’s checkResourceIsReachableAndReturnError:(missing value)) as boolean then – it already exists, so try deleting
            –いったんmove先のファイルを削除
            (
defM’s removeItemAtURL:toPath |error|:(missing value))
          end if
        else
          –moveが成功した場合
          
set hitF to true
          
exit repeat
        end if
      end repeat
      
      
if hitF = false then
        tell current application
          display dialog “Serious error occured in moving files….”
        end tell
        
return
      end if
    else
      log {“Can not get originate file”} –move元のファイルが存在していなかった場合
    end if
  end repeat
end moveFilesWithPOSIXstrList

–ASOCで指定フォルダのファイルパス一覧取得(拡張子指定つき)
on getFilePathList(aFol, aExt)
  set aPath to current application’s NSString’s stringWithString:(POSIX path of aFol)
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set nameList to (aFM’s contentsOfDirectoryAtPath:aPath |error|:(missing value))
  
set anArray to current application’s NSMutableArray’s alloc()’s init()
  
  
repeat with i from 1 to nameList’s |count|()
    set j to (nameList’s objectAtIndex:(i - 1)) as text
    
if (j ends with aExt) and (j does not start with “.”) then –exclude invisible files
      set newPath to (aPath’s stringByAppendingString:j)
      (
anArray’s addObject:newPath)
    end if
  end repeat
  
  
return anArray as list
end getFilePathList

★Click Here to Open This Script 

2015/10/24 シリアルコードの生成と検証

オープンソースのSerialKeyGeneratorをもとに作成した「serialKeyGenKit」フレームワークを用いて、シリアルコードの生成(Generation)と検証(Validation)を行うAppleScriptです。

ソフトウェアの販売時などに、シリアルコードを発行することがあります。Mac App Storeのソフトウェア販売ではあまり見られませんが(自社ストア販売バージョンからMac App Store販売バージョンへのアップグレードでOmniGraffleあたりで見かけました)、Mac App Store以外でオンライン販売するような場合には必要になってきます。

キーの重複がなく、偽造されにくく、必要な情報を含んでいるようなシリアルコード体系が理想的です。しかも、使用する文字はA〜Z、0〜9の文字だけで、「XXXXX-XXXXX-XXXXX-XXXXX-XXXXX」のフォーマットで・・・・

そんなシリアルコードを手軽かつ高速に生成できるのがSerialKeyGeneratorです。シークレットキーをもとに乱数要素や日時の要素を勘案したシリアルコードを生成してくれます。

仕事で何度かシリアルコードの作成を行ったことがありますが、なかなかこれが大変でした。「SerialKeyGenerator」は非常に簡単なシリアルコードを生成するためのものですが、シリアルコードによって動作許可する機能を作ったり、指定日時まで動作許可するコードだったりと・・・それだけで相当の手間になりました。

また、流失したシリアルコードについてはオンラインで失効手続きを行えるようにしたりと、本気で作り出すと「ソフトウェア本体よりもでかい処理」になったりします(頭痛が、、、)。

例によって、serialKeyGenKit.frameworkをOS X 10.10以降用にビルドしておきましたので、興味のある方は~/Library/Frameworksフォルダに入れてお試しください。

–> Download Framework Binary

AppleScript名:SerialKeyGeneratorサンプル1
– Created 2015-10-24 18:27:16 +0900 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “serialKeyGenKit” –danielvy/SerialKeyGenerator
–https://github.com/danielvy/SerialKeyGenerator

set aGen to current application’s SerialKeyGenerator’s alloc()’s initWithSecret:“Piyomaru”
–>  (SerialKeyGenerator)

set aList to {}
repeat with i from 1 to 10
  set aRes to (aGen’s generateSerialWithSequence:i |data|:10)
  
set the end of aList to (aRes as text)
end repeat

aList
–>  {”1CHH8-BJY89-TR9Z9-AKSTL-70JZF”, “4KXCF-LS6P5-7BKYN-CUMPY-NM072″, “41GO2-OGZ3T-83YP9-2LS4J-9W3MI”, “CA3WV-C7FU7-PSPJ3-LNGT7-N6AJT”, “3OG0B-MCFUM-7YKHT-EE533-LNJEJ”, “4SKWQ-9G8XE-ZCE6K-APSAL-R0T8S”, “CTEZT-H4AQQ-BM15H-FH2DG-P7K7O”, “4BZ1X-2OHKF-5FWND-7SZVA-EBR89″, “BDKRI-9JU7T-G6N20-YPU9K-6FXQW”, “9EWW5-O3FMV-SDEZA-77JZE-OY8FL”}

★Click Here to Open This Script 

AppleScript名:SerialKeyGeneratorサンプル2
– Created 2015-10-24 18:27:16 +0900 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “serialKeyGenKit” –danielvy/SerialKeyGenerator
–https://github.com/danielvy/SerialKeyGenerator

–シリアルコードの生成(エンコード)

–シークレットキー「Piyomaru」をもとにシリアルコードジェネレータを生成
set aGen to current application’s SerialKeyGenerator’s alloc()’s initWithSecret:“Piyomaru”
–>  (SerialKeyGenerator)

–指定個数のシリアルコードを生成。生成するたびに毎回シリアルコードは異なる
set anArray to (aGen’s generateSerials:10 start:1 |data|:10) as list
–>  {”0YR0Q-Y5FZP-A25EI-TK3YI-78L5U”, “7VZSX-S87LJ-812L7-A2XC6-Q9DBQ”, “C3HYG-H4HPP-FPP6A-1PH1L-MVVF0″, “B7FHO-AQ4E0-Y0AQG-YYFVX-XSEWA”, “0C4GP-M46PY-BD7J9-878SG-FSZP3″, “5OLK7-C3R3R-IVKX5-7FUIT-GJA07″, “2KA8T-PFIC4-PII60-QBRWN-ZPJWE”, “325M7-8KR60-2X1G8-EF7OA-UP06I”, “CIH21-H6H1O-31AA4-12ZSD-0ZBT3″, “8NA54-0W8R5-0VI34-X1L5F-5E0GS”}

–シリアルコードの検証(デコード)

–シークレットキー「Piyomaru」をもとにシリアルコードジェネレータを生成
set bGen to current application’s SerialKeyGenerator’s alloc()’s initWithSecret:“Piyomaru”

set bRes to bGen’s decodeSerial:(contents of first item of anArray)

set aDate to bRes’s |date| as date
–>  date “2015年10月24日土曜日 18:37:25″
set aSeq to bRes’s sequence as integer
–>  1
set aData to bRes’s |data| as integer
–>  10

★Click Here to Open This Script 

2015/10/23 RFKeychain経由でKeychainアクセス

オープンソースのRFKeychain(By Rheinfabrik)をframework化したもの(rfKeychainKit.framework)を呼び出して、キーチェーンへのアクセスを行うAppleScriptです。

Keychainについては、かつてはKeychain AccessというAppleScript専用のヘルパーアプリが存在していましたが、いまはshell commandの「security」が用意されているので、そちら経由でアクセスしてくれという状況です。

OS X標準搭載のそれらヘルパーアプリのメンテナンス状況は正直言って期待できないので、AppleScriptがScriptring Bridge対応したタイミングで、Apple純正ヘルパーアプリ群への依存度を下げるための布石が必要だと思っていました。

たまたま見つけたRFKeychainですが、正直機能が足りているとも思えないので(すでに登録されているキーチェーン項目を検索するような機能がない)、ほかにもいろいろ探してみたほうがよさそうです。

例によって、フレームワークをOS X 10.10以降用にビルドしたものを用意しておきました。興味のある方は~/Library/Frameworksフォルダに入れてためしてみてください。

→ Download Framework Binary

AppleScript名:ASOCでRFKeychain経由でKeychainアクセス
– Created 2015-10-23 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “rfKeychainKit” –rheinfabrik/RFKeychain
–https://github.com/rheinfabrik/RFKeychain

–Register Password
set aRes to (current application’s RFKeychain’s setPassword:“piyopiyo” account:“piyomaru” service:“piyocast.com” accessGroup:“other”) as boolean
–> true

–Get Password
set bRes to (current application’s RFKeychain’s passwordForAccount:“piyomaru” service:“piyocast.com”) as text
–>  ”piyopiyo”

–Delete Password
set cRes to (current application’s RFKeychain’s deletePasswordForAccount:“piyomaru” service:“piyocast.com” accessGroup:“other”) as boolean
–>  true

★Click Here to Open This Script 

2015/10/23 プロセス情報を取得

Cocoaの機能を用いてプロセス情報を取得するAppleScriptです。

プロセス情報を取得する方法については、シェルのpsコマンドを利用する方法やSystem Events.app経由で取得するものなどさまざまなものがありますが、CocoaのAPIで取得したことがなかったので調査してみました。

・・・Cocoa経由でもプロセスのハングアップ(Zombie)状態を取得できるのでは? と、期待していたのですが、あまり詳細なものは取れないことがわかりました。もう少し低位の(ハードウェアに近い)レイヤーのAPIを使う必要がありそうです。

Adobeの「CCLibrary」のCPUアーキテクチャが変な値(-1)を返してくるのが不思議なところです。

AppleScript名:ASOCでプロセス情報を取得
– Created 2015-10-23 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set runningApplications to (current application’s NSWorkspace’s sharedWorkspace()’s runningApplications()) as list

repeat with i in runningApplications
  
  set aName to (i’s localizedName()) as text
  
set anIcon to (i’s icon())
  
set anBundleID to (i’s bundleIdentifier()) as text
  
set anBundleURL to (i’s bundleURL())
  
  set tmpArch to (i’s executableArchitecture())
  
if tmpArch = 16777223 then
    set anArch to “X86_64″
  else if tmpArch = 7 then
    set anArch to “I386 “
  else
    set anArch to “Another Arch (PPC? or Error)”
  end if
  
  set anLaunchDate to (i’s launchDate())
  
set anFinishLaunch to (i’s isFinishedLaunching())
  
set aProcID to (i’s processIdentifier())
  
set anOwnMenubar to (i’s ownsMenuBar())
  
  log {aName, tmpArch, anArch}
  
–> (* {”CCLibrary”, -1, “Another Arch (PPC?)”} *)
end repeat

★Click Here to Open This Script 

2015/10/22 アプレットのアイコンをDockに出さない

Cocoaの機能を用いて、Dockにアイコン非表示状態のAppleScriptアプレットにする方法です。

一番有名なのは、Info.plistに”LSBackgroundOnly”=”1″のエントリを作成する方法ですが、Cocoaの機能を用いて、アプレットの起動後にアイコンを非表示状態にすることが可能です。

通常のAppleScript Appletを前提にして話をします。

本記事中のプログラムリストは、アプレット(Applet)に書き出した状態で実行してください。Script Editor上で実行しても意味がありません。

export_to_applet.png

export_to_applet2.png

exported_applet.png

通常のAppleScript Appletでは、Cocoa-AppleScript Applet(OS X 10.7で採用になったもの)と異なり、起動時の細かいイベントハンドラは利用できないため、Appletが起動してコードが実行されるまでの間、「ちょっとの間だけ」Dock上にアイコンが表示されます。

cocoa_applescript_applet.png

プロセスの隠し方が2通りあります。

 NSApplicationActivationPolicyAccessory:display dialog実行可能
 NSApplicationActivationPolicyProhibited:display dialog実行不可。display notificationやsayコマンドなどは実行可能

それぞれ、用途に応じて使ってみてください。また、状態を途中で変更することも可能で、通常のアプレットのようにDock表示状態に戻すこともできます。

AppleScript名:アプレットのアイコンをDockに出さない
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

–Dockアイコン非表示、dialogは出せる
current application’s NSApp’s setActivationPolicy:(current application’s NSApplicationActivationPolicyAccessory)
repeat with i from 1 to 10
  tell current application
    display dialog (i as text) giving up after 1 with icon 1 buttons {“OK”}
  end tell
end repeat
quit

★Click Here to Open This Script 

AppleScript名:アプレットのアイコンをDockに出さない2
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

–Dockアイコン非表示、dialogも出ない
current application’s NSApp’s setActivationPolicy:(current application’s NSApplicationActivationPolicyProhibited)
repeat with i from 1 to 10
  tell current application
    display notification (i as text)
    
delay 1
  end tell
end repeat
quit

★Click Here to Open This Script 

AppleScript名:アプレットのアイコンをDockに出さない→出す
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

–Dockアイコン非表示、dialogは出せる
current application’s NSApp’s setActivationPolicy:(current application’s NSApplicationActivationPolicyAccessory)
repeat with i from 1 to 10
  tell current application
    display dialog (i as text) giving up after 1 with icon 1 buttons {“OK”}
  end tell
end repeat

–通常状態
current application’s NSApp’s setActivationPolicy:(current application’s NSApplicationActivationPolicyRegular)
repeat with i from 1 to 10
  tell current application
    display dialog (i as text) giving up after 1 with icon 1 buttons {“OK”}
  end tell
end repeat

★Click Here to Open This Script 

2015/10/22 指定ファイルのアイコン画像を取得する

Cocoaの機能を用いて、指定ファイルのアイコン画像を取得するAppleScriptです。

本来やりたい処理は、「指定ファイルや指定フォルダにバッジをつける」というものですが、

 〇慊螢侫.ぅ襪らアイコン画像を取得
 ⊆萋世靴寝菫にバッジのイメージを重ね合わせる
 9臉した画像をカスタムアイコンとして,離侫.ぅ襪棒瀋蠅垢

というやりかたでできそうだと考え、そのために調査を行ったものです。

AppleScript名:ASOCで指定ファイルのアイコン画像を取得する
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aFile to POSIX path of (choose file)
set aPath to current application’s NSString’s stringWithString:aFile
set aWS to current application’s NSWorkspace’s sharedWorkspace()
set iconImage to aWS’s iconForFile:aPath
(*)
–>  (NSImage) “,
“,
“,
“,
“,
“,
“,
“,
“,
“,
“,
“,
“,
“,

)>
*)

★Click Here to Open This Script 

2015/10/22 辞書.appの指定名称の辞書でキーワード検索

オープンソースのプログラムDictionaryKit(By Mattt Thompson)をフレームワークに入れた「dictKit」を介して、OS X内蔵の辞書でキーワード検索を行うAppleScriptです。

DictionaryKitの内部機能を直接AppleScriptから呼ぶことはできませんが、DictionaryKitのプログラムを突っ込んだFramework「dictKit.framework」を作成し、これをインストールしてAppleScriptから呼べるようにしました。

注意点:DictionaryKitの説明にもあるのですが、OS XのPrivate APIを呼んでいるため、本プログラム(dictKit)を用いて作ったアプリケーションをMac App Store向けに申請することはできません。

でも、超〜便利なんで(^ー^;;; 日常的なScriptで使わない手はありません。

例によって、dictKitのバイナリをOS X 10.10以降用にビルドしておきましたので、興味のある方は~/Library/Frameworksフォルダに入れておためしください。

–> Download Framework Binary

AppleScript名:ASOCで辞書.appで検索可能な辞書名称一覧を取得する
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “dictKit” –mattt/DictionaryKit
–https://github.com/mattt/DictionaryKit

set dSet to current application’s TTTDictionary’s availableDictionaries()
set dList to dSet’s allObjects()
set dNameList to {}
repeat with i in dList
  set the end of dNameList to (i’s |name|()) as text
end repeat
dNameList
–>  {”뉴에이스 영한사전 / 뉴에이스 한영사전“, “Apple 用語辞典”, “Multidictionnaire de la langue française”, “राजपाल हिन्दी शब्दकोश“, “Dizionario italiano da un affiliato di Oxford University Press”, “Oxford-Hachette French Dictionary”, “NE Ordbok”, “牛津英汉汉典”, “Oxford Thesaurus of English”, “スーパー大辞林”, “Oxford Dictionary of English”, “Oxford American Writer’s Thesaurus”, “Norsk Ordbok”, “Gran Diccionario Oxford - Español-Inglés Inglés-Español”, “Wikipedia”, “Duden-Wissensnetz deutsche Sprache”, “Толковый словарь русского языка”, “뉴에이스 국어사전“, “Prisma woordenboek Nederlands”, “New Oxford American Dictionary”, “Dicionário de Português licenciado para Oxford University Press”, “Oxford German Dictionary”, “Diccionario General de la Lengua Española Vox”, “ウィズダム英和辞典 / ウィズダム和英辞典”, “Arkadaş Türkçe Sözlük”, “พจนานุกรมไทย ฉบับทันสมัยและสมบูรณ์“, “汉语规典”}

★Click Here to Open This Script 

AppleScript名:ASOCで辞書検索じっけん
– Created 2015-10-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “dictKit” –mattt/DictionaryKit
–https://github.com/mattt/DictionaryKit

set aDictionary to current application’s TTTDictionary’s dictionaryNamed:“Apple 用語辞典”
set dRes to aDictionary’s |name|()
set dRes to dRes as text
–>  ”Apple 用語辞典”

set aTerm to “AppleScript”
set hitEntryList to (aDictionary’s entriesForSearchTerm:aTerm) as list
if hitEntryList = {missing value} then return “” –ヒットしなかった場合

repeat with i in hitEntryList
  set j to contents of i
  
  
set headW to (j’s headword)
  
set headW to headW as text
  
–>  ”AppleScript”
  
  
set aText to (j’s |text|)
  
set aText to aText as text
  
(*)
  –>  ”AppleScript
OS X に内蔵されたスクリプト言語です。AppleScript 言語のコマンドを使用すれば、“メール”、Safari、“カレンダー”など、さまざまなアプリケーションで繰り返しの作業や複雑な作業を自動化できます。
*)

  
end repeat

★Click Here to Open This Script 

2015/10/21 ステガノグラフィーを用いて画像に情報を埋め込む

オープンソースのステガノグラフィーのプログラム「ISStego」(By Isaac Stevao Sena氏)を用いて、PNG画像に文字情報を埋め込む/取り出すAppleScriptです。

ISStegoは普通にObjective-Cで書かれたGUIベースのアプリケーションだったので、そのままではAppleScriptから呼び出せませんでした。

そこで、中身をそのままそっくり移し替えた新規フレームワーク「stegLib.framework」をでっちあげてビルドし、AppleScriptから呼び出してみました(フレームワークをはじめて作ってみましたが、えっらい簡単で驚きました)。

PNG画像にUTF-8の文字情報(日本語文字列)を埋め込んで別のPNG画像に書き出し、書き出した画像からUTF-8の文字情報を取り出す実験を行ってみました。エンコードもデコードもうまく行っているようなので、うまく処理できていると思います。

ステガノグラフィーについて初めて聞いたのは20年ぐらい前のことと記憶していますが、こんなに手軽に使えるようになっていたとは驚きです。

Twitterにプログラムを投稿するのに、(140文字制限を回避するため)文字を画像化して投稿しているのを見て、「そこまでやるなら、画像にプログラムの文字データを埋め込めばいいのに」と思い、「ステガノグラフィーで埋め込めばいいんじゃないか?」ということで、埋め込めるようになったのですが、肝心のTwitterクライアントから画像をダウンロードする手段がなかったのがダメダメでした(Webブラウザ経由ならOKです)。

custf11.png
▲ステガノグラフィー処理前の画像

custf1_stego.png
▲ステガノグラフィーによって文字情報を埋め込んだ画像(本当に埋め込んであります^ー^;)

stegLib.framework(ISStegoをFramework化したもの)のバイナリを例によってOS X 10.10以降用にビルドしておきましたので、興味のある方は~/Library/Frameworksに入れて使ってみてください。

–> Download Framework

AppleScript名:ASOCで画像にステガノグラフィーで情報を埋め込む
– Created 2015-10-21 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “stegLib” –ISStegoをフレームワーク化
–https://github.com/isena/ISStego

set aFile to POSIX path of (choose file of type {“public.image”})
set encString to “長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software”

set aFilePath to current application’s NSString’s stringWithString:aFile
set aExt to aFilePath’s pathExtension()

set newPath to aFilePath’s stringByDeletingPathExtension()
set newPath2 to newPath’s stringByAppendingString:“_stego”
set newPath3 to newPath2’s stringByAppendingPathExtension:aExt

set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL
set strData to current application’s NSString’s stringWithString:encString

set aEncimage to current application’s ISStegoEncoder’s alloc()’s init()’s stegoImageForImage:aImage |data|:strData |error|:(missing value)
my saveImageRepAtPathAsPNG(aEncimage, newPath3)

–画像を指定パスにPNG形式で保存
on saveImageRepAtPathAsPNG(anImage, outPath)
  
  
–画像のRaw画像を作成
  
set imageRep to anImage’s TIFFRepresentation()
  
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep
  
  
–書き出しファイルパス情報を作成
  
set pathString to current application’s NSString’s stringWithString:outPath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
  
–書き出し
  
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
  
return aRes –成功ならtrue、失敗ならfalseが返る
  
end saveImageRepAtPathAsPNG

★Click Here to Open This Script 

AppleScript名:ASOCで画像にステガノグラフィーで埋め込まれた文字列を取り出す
– Created 2015-10-21 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “stegLib” –ISStegoをフレームワーク化
–https://github.com/isena/ISStego

set aFile to POSIX path of (choose file of type {“public.image”})
set aFilePath to current application’s NSString’s stringWithString:aFile
set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL

set aDecodedData to current application’s ISStegoDecoder’s alloc()’s init()’s decodeStegoImage:aImage |error|:(missing value)
set resStr to current application’s NSString’s alloc()’s initWithData:aDecodedData encoding:(current application’s NSUTF8StringEncoding)
–>  (NSString) “長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software”

★Click Here to Open This Script 

2015/10/21 指定フォルダに指定アイコン画像をつける[Update]

Cocoaの機能を用いて、指定フォルダに指定アイコン(カスタムアイコン)をつけるAppleScriptです。

前回掲載したときには、フォルダにカスタムアイコンがついたりつかなかったりで、不思議に思っておりました。

どうしてもこの処理は使ってみたかったので、いろいろ調査して問題を解決しました。

えーー、最初は「パスの書き方の問題か?」と考えて試していたのですが、Shaneから「ちょっと、そこ何言ってるのかわかんない」とツッコミが入り。再検証したところ、フォルダへのPOSIX pathの記述の問題(末尾にスラッシュが入る or 入らない問題)ではないことが判明。

再々調査してみたところ、フォルダにカスタムアイコンがつかない場合がある原因は、

「いちどカスタムアイコンを付けたフォルダに別のカスタムアイコンをつける場合には、いったん前のカスタムアイコンを削除する必要がある」

ことのようです。さらに、Cocoaの機能のみならずAppleScriptならではの「Finderへのリフレッシュ指令」を出すなど細やかな処理を追加。

custf1.png
custf2.png

さて、どうなりますやら、、、

AppleScript名:指定フォルダに指定アイコン画像をつける v3
– Created 2015-10-21 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set anIconPath to POSIX path of (choose file of type {“com.apple.icns”, “public.tiff”} with prompt “Choose Icon File”)
set aFolder to POSIX path of (choose folder with prompt “Choose Folder”)
setCustomIcon(anIconPath, aFolder) of me

on setCustomIcon(aPath, aFolder)
  set aFolderPath to current application’s NSString’s stringWithString:aFolder
  
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aPath
  
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL
  
  
set aSW to current application’s NSWorkspace’s sharedWorkspace()
  
aSW’s setIcon:(missing value) forFile:aFolder options:0 –Erase
  
tell application “Finder”
    update ((POSIX file aFolder) as alias) –Refresh State
  end tell
  
  
aSW’s setIcon:aImage forFile:aFolderPath options:0 –Write
  
tell application “Finder”
    update ((POSIX file aFolder) as alias) –Refresh State
  end tell
end setCustomIcon

★Click Here to Open This Script 

AppleScript名:指定フォルダからカスタムアイコンを削除する v3
– Created 2015-10-21by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aFolder to POSIX path of (choose folder with prompt “Choose Target Folder”) –カスタムアイコン削除対象のフォルダ

on removeCustomIcon(aFolder)
  set aSW to current application’s NSWorkspace’s sharedWorkspace()
  
aSW’s setIcon:(missing value) forFile:aFolder options:0 –Erase
  
tell application “Finder”
    update ((POSIX file aFolder) as alias) –Refresh State
  end tell
end removeCustomIcon

★Click Here to Open This Script 

2015/10/20 PDFの各種情報を取得する

Cocoaの機能を用いて、PDFの各種情報を取得するAppleScriptです。

PDFのParse自体はAppleScriptだけでは行えませんが、こうした情報の取得や、PDFの暗号化/復号化ぐらいであればAppleScriptだけで(他のアプリケーションを併用せずに)実行可能です。

AppleScript名:ASOCでPDFの各種情報を取得する
– Created 2015-10-20 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “QuartzCore”

set aPath to POSIX path of (choose file of type {“com.adobe.pdf”} with prompt “Select PDF”)
set aURL to current application’s |NSURL|’s fileURLWithPath:aPath
set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL

set pCount to aPDFdoc’s pageCount() –ページ数
–>  1

set aMajorVersion to aPDFdoc’s majorVersion() –バージョン(メジャーバージョン)
–> 1

set aMinorVersion to aPDFdoc’s minorVersion() –バージョン(マイナーバージョン)
–> 3

set aRoot to aPDFdoc’s outlineRoot()
–>  missing value

set anAttr to (aPDFdoc’s documentAttributes()) as record
–> (NSDictionary) {Creator:”Pages”, Producer:”Mac OS X 10.11.1 Quartz PDFContext”, ModDate:(NSDate) 2015-10-20 07:45:55 +0000, Title:”testPDF”, CreationDate:(NSDate) 2015-10-20 07:45:55 +0000}

set aCreator to anAttr’s Creator()
–>  ”Pages”

set aProducer to anAttr’s Producer()
–>  ”Mac OS X 10.11.1 Quartz PDFContext”

set aTitle to anAttr’s Title()
–>  ”testPDF”

set aCreationDate to anAttr’s CreationDate() –PDF作成年月日
–>  date “2015年10月20日火曜日 16:45:55″

set aModDate to anAttr’s ModDate() –PDF変更年月日
–>  date “2015年10月20日火曜日 16:45:55″

set anEncF to aPDFdoc’s isEncrypted() –暗号化されている(パスワードが設定されている)か?
–>  false

set anLockF to aPDFdoc’s isLocked() –ロックされているか?
–>  false

set aCopyF to aPDFdoc’s allowsCopying() –テキストのコピーを許可されているか?
–>  true

set aPrintF to aPDFdoc’s allowsPrinting() –印刷を許可されているか?
–>  true

–PDFのサイズを取得する(単位:Point)
set aPage to aPDFdoc’s pageAtIndex:0
set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxMediaBox)
set aSize to |size| of aBounds
–>  {width:595.28, height:841.89}

★Click Here to Open This Script 

2015/10/19 指定ファイルに指定アイコン画像をつける

Cocoaの機能を用いて、指定ファイルに指定アイコン(カスタムアイコン)をつけるAppleScriptです。

アイコンの変更などという、わりと誰にでもわかりやす〜い効果が得られるものです。Pure AppleScriptだと逆立ちしてもできない(Classic Mac OSの時代にはできた気がする)処理も、AppleScriptObjCだと簡単に実現できます。

常駐型のAppletでフォルダを監視して処理させるような場合に、監視フォルダ内に書類が入ってきて処理を行うとフォルダのアイコンが変化してユーザーに「処理中」であることを視覚的にフィードバックする、とかいうのがわりといい使い道だと思います。

# 処理中のファイル数をアプレットにバッジで表示するのもけっこういいです

指定ファイルに対していわゆる「カスタムアイコン」をつけます。おまけでカスタムアイコンを削除するものも用意しておきました。

指定するアイコン画像については、ICNSファイル、TIFF画像のほか、PNGなども問題なく設定できるようですが、表示のリフレッシュタイミングがいまひとつ「God Only Knows」だったりするので、そのあたりどーにかならないものかと。

AppleScript名:指定ファイルに指定アイコン画像をつける
– Created 2015-10-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aPath to POSIX path of (choose file of type {“com.apple.icns”, “public.tiff”} with prompt “Choose Icon File”) –アイコンファイル
set aFile to POSIX path of (choose file with prompt “Choose Target File”) –設定対象のファイル

set aURL to current application’s |NSURL|’s fileURLWithPath:aPath
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL

set aSW to current application’s NSWorkspace’s sharedWorkspace()
aSW’s setIcon:aImage forFile:aFile options:0

★Click Here to Open This Script 

AppleScript名:指定ファイルからカスタムアイコンを削除する
– Created 2015-10-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aFile to POSIX path of (choose file with prompt “Choose Target File”) –設定対象のファイル
set aSW to current application’s NSWorkspace’s sharedWorkspace()
aSW’s setIcon:(missing value) forFile:aFile options:0

★Click Here to Open This Script 

2015/10/18 PDFメディアサイズの取得(単位:Point)

選択したPDF書類のページのサイズをPointで取得するAppleScriptです。

ページの取得方式にいろいろあるので、ひととおり調べてみたところ(実験には、Shane Stanleyの「Everyday AppleScriptObjC」を使用)・・・すべて同じ結果が返ってきました。それぞれどのように取得しているか、調べておきたいところです(図になっていないものか)。

OS X 10.11上で確認および10.11の機能(Enumのbridge)を使っていますが、OS X 10.10上では「current application’s kPDFDisplayBoxMediaBox」などと書いてあるものを0(数値)に書き換えれば動きます。

AppleScript名:PDFメディアサイズの取得(単位:Point)
– Created 2015-10-18 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “QuartzCore”

–PDFを選択
set aFile to choose file of type {“com.adobe.pdf”}

set aFile to POSIX path of aFile
set theURL to current application’s |NSURL|’s fileURLWithPath:aFile
set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:theURL
set aPage to aPDFdoc’s pageAtIndex:0

–PDFのサイズを取得する(単位:Point)
set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxMediaBox) –0
set aSize to |size| of aBounds
–>  {width:612.0, height:792.0}

set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxCropBox) –1
set aSize to |size| of aBounds
–>  {width:612.0, height:792.0}

set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxBleedBox) –2
set aSize to |size| of aBounds
–>  {width:612.0, height:792.0}

set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxTrimBox) –3
set aSize to |size| of aBounds
–>  {width:612.0, height:792.0}

set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxArtBox) –4
set aSize to |size| of aBounds
–>  {width:612.0, height:792.0}

★Click Here to Open This Script 

2015/10/17 iWorkアプリがアップデート、AppleScript対応機能が強化される

AppleのiWorkアプリケーション(Keynote、Pages、Numbers)がアップデートされ、Keynote v6.6、Pages v5.6、Numbers v3.6になりました。それぞれ、AppleScript関連機能が強化されています。

AppleのSal SoghoianがUSのAppleScript Users MLに投稿し、それぞれの解説ページへのリンクを紹介しています。

Keynote
Updates to export options:
PDF image quality

Pages
Updates to export options:
image quality
EPUB metadata: publisher, language, genre

Numbers
Transpose table command:
Updates to export options:
image quality
exclude summary worksheet option for exporting to Excel

英語で書かれていますが、しっかりと解説されており納得の行くレベルです。アプリケーション自体の機能では、Pagesでドキュメント内リンクが作れるようになってほしいところです(PDF書き出ししたときに、リンクで書類内を行き来できないのが辛い)。

2015/10/14 テキストとリストの変換

Cocoaの機能を用いて、listとtextの相互変換を行うAppleScriptです。

List -> Text

リストをそのままテキストにするもの(できるけど)ではなく、{”a”,”b”,”c”} のようなリストを、”a–> b–> c”のようにデリミタ(区切り)文字を介して連結する処理です。最初はそれだけの目的のために作ったルーチンでした。

この「項目間を→でつなぐ」という目的で作ったサブルーチン(retArrowText)が便利で他の用途に転用しまくったため、すっかり自分ローカルの方言になってしまいました。今後は「retStrFromArrayWithDelimiter」を使っていくつもりです。

Text -> List

テキストを指定デリミタ(改行など)で区切ってリストにするものです。ついでなので作っておきました。自分ローカルで「parseByDelim」と呼んでいたもので、こちらの名前はそれほどおかしくないので、このまま行こうかと。

AppleScript名:ASOCでテキストとリストの変換
– Created 2015-10-14 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aList to {“あああああ”, “いいいいいいいい”, “ううううううううううう”, “えええええええええええ”, “おおおおおおおおおお”}
set aRes to my retStrFromArrayWithDelimiter(aList, return)
(*
“あああああ
いいいいいいいい
ううううううううううう
えええええええええええ
おおおおおおおおおお”
*)

set bList to my parseByDelim(aRes, return)
–>  {”あああああ”, “いいいいいいいい”, “ううううううううううう”, “えええええええええええ”, “おおおおおおおおおお”}

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as text
end retStrFromArrayWithDelimiter

on retArrowText(aList, aDelim) –自分のASでよく使うハンドラ名称なので、同じものを用意
  return my retStrFromArrayWithDelimiter(aList, aDelim)
end retArrowText

–テキストを指定デリミタでリスト化
on parseByDelim(aData, aDelim)
  set aText to current application’s NSString’s stringWithString:aData
  
set aList to aText’s componentsSeparatedByString:aDelim
  
return aList as list
end parseByDelim

★Click Here to Open This Script 

2015/10/13 数字以外を削除して返す

与えられた文字列のうち、数字以外を削除して返すAppleScriptです。

正規表現で数字以外をヌルに置換して返します。スペースを許容するものと、スペースと改行を許容するものも作っておきました。

後で加工することを考えると、地味にスペースも取り出せると処理が楽だったので、、、

AppleScript名:ASOCで数字以外を削除して返す
– Created 2015-10-13 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aStr to "<< 98158999992
>>"

set bStr to returnNumberCharsOnly(aStr)
–>  "98158999992"

set cStr to returnNumberCharsAndSpaceOnly(aStr)
–> " 98158999992 "

set dStr to returnNumberCharsAndSpaceAndReturnOnly(aStr)
–>
(*
" 98158999992
"
*)

on returnNumberCharsOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberCharsOnly

on returnNumberCharsAndSpaceOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9 ]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberCharsAndSpaceOnly

on returnNumberCharsAndSpaceAndReturnOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9
]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  return anNSString as text
end returnNumberCharsAndSpaceAndReturnOnly

★Click Here to Open This Script 

2015/10/11 ZipZap frameworkを使ってZipアーカイブ内の情報を取得

オープンソースのZipZapフレームワーク(By Pixelglow Software)を利用して、選択したZipアーカイブ中の情報を取得するAppleScriptです。

たまたまCocoa dev MLの過去ログを漁っていたら、ZipZapフレームワークを見つけました。GitHubのサイトはキーワード検索がいまひとつで、以前に検索したときにはひっかかってこなかったものです(ひととおり、めぼしいのは調べたので)。

それはともかく、GitHubのサイトからClone in DesktopでMacにXcodeプロジェクトをクローンして、Xcode 7.0.1でプロジェクトをビルド。生成したフレームワークをAppleScriptから呼び出すテストを行ってみたものです。

ほぼ、READMEに書いてある通り書いてそのまま動きました。ヘッダーファイルに書いてあるいくつかのプロパティも試してみたところ納得の結果が(READMEどおりに書いて動かないものも、他にいろいろみかけますが・・・本プロジェクトは実に素直でした)。

さまざまなプロパティをAppleScriptの型にcastしてログ表示しているため、OS X 10.11用(AppleScript version 2.5が必要)になっていますが、castしたりlog表示しなければOS X 10.10でも動きます(安全のために10.11専用に)。

例によって、OS X 10.10以降用にビルドしたZipZapフレームワークを置いておきます。興味のある方はお試しください(~/Library/Frameworks/にインストール)。

–> Download Framework Binary (OS X 10.10 or later)

AppleScript名:ASOCでZipZap frameworkを使ってZipアーカイブ内の情報を取得
– Created 2015-10-11 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “ZipZap”
–https://github.com/pixelglow/zipzap

set aPath to POSIX path of (choose file of type {“public.zip-archive”})
set oldArchive to current application’s ZZArchive’s archiveWithURL:(current application’s |NSURL|’s fileURLWithPath:aPath) |error|:(missing value)
–>  (ZZArchive)

set entryCount to oldArchive’s entries()’s |count|()
–>  180 –this zip archive includes 180 file or folders inside

set firstArchEntry to oldArchive’s entries()’s firstObject()
–>  (ZZOldArchiveEntry)

set aList to oldArchive’s entries() as list

repeat with i in aList
  set uSize to i’s uncompressedSize() as real
  
set cSize to i’s compressedSize() as real
  
set comF to i’s compressed() as boolean
  
set encF to i’s encrypted() as boolean
  
set modD to i’s lastModified() as date
  
set chkSum to i’s crc32() as text –The CRC32 code of the entry file: 0 for new entries.
  
set aFileMode to i’s fileMode() as text – The UNIX file mode for the entry: 0 for new or non-UNIX entries. This includes the file type bits.
  
set aFileName to i’s fileName() as text
  
  
log {aFileName, aFileMode, chkSum, modD, encF, comF, cSize, uSize}
  
–> 21:28:01.817 (* {”ZXingObjC.framework/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.818 (* {”ZXingObjC.framework/Headers”, “41453d”, “2.393740531E+9″, date “2015年10月10日土曜日 10:07:10″, false, false, 24.0, 24.0} *)
  
–> 21:28:01.820 (* {”ZXingObjC.framework/Versions/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:10″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.821 (* {”ZXingObjC.framework/Versions/3.1.0/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.822 (* {”ZXingObjC.framework/Versions/3.1.0/Headers/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
  
–set aData to (i’s newDataWithError:false)–Uncompressed raw data
  
–log aData
end repeat

★Click Here to Open This Script 

2015/10/08 Excelデータを組み立てて書き出し(フォント指定、カラー指定)

オープンソースのExcelデータ書き出しフレームワーク「JXLS」(By David Hoerl)を利用して、Excelのない環境でもExcelデータを作成するAppleScriptです。

デフォルトのままではあまりにも味気なかったので、フォント名、フォントサイズ、カラーを指定してみたものです。

サンプルがほとんど存在していないので手探り状態でしたが、なんとかなりました。

OS XのFinder上でもXLSファイルのプレビュー機能があるため、類似のフレームワークはOS X自体に搭載していそうです(というより、機能があるからプレビューできているんでしょう)。

xls.png

AppleScript名:ASOCでExcelファイル生成テスト v2
– Created 2015-10-08 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “JXLS”

set aFile to POSIX path of (choose file name)
set filePath to current application’s NSString’s stringWithString:aFile

set workBook to current application’s JXLSWorkBook’s new()
set workSheet to workBook’s workSheetWithName:“ぴよぴよシート”
workSheet’s setWidth:1000 forColumn:0 defaultFormat:(missing value)

repeat with i from 0 to 64
  set aCell to (workSheet’s setCellAtRow:i column:0 toString:(current application’s NSString’s stringWithString:(“ぴよまる “ & (i as text))))
  (
aCell’s setFontName:“HiraKakuStd-W8″)
  (
aCell’s setFontHeight:320) –this is point * 20
  (
aCell’s setFontColorIndex:i)
end repeat

workBook’s writeToFile:filePath

★Click Here to Open This Script 

2015/10/08 Excelデータを組み立てて書き出し

オープンソースのExcelデータ書き出しフレームワーク「JXLS」(By David Hoerl)を利用して、Excelのない環境でもExcelデータを作成するAppleScriptです。

正直、Excelデータを書き出せるNumbers.appがあるので、そこまで頑張らなくてもよさそうな気配がしていますが、たまたま「Excelデータを読むフレームワーク」を探していたら見つけたものです(読み込む方は、iOS用のみだったという)。

無人島に流されてExcelがない極限環境であっても、AppleScriptだけでExcelデータを生成できます。

何も考えずに、サンプル中に書かれていたObjective-CのプログラムをAppleScriptで再現してみたものですが、出来上がったExcel書類(のフォント)がちょっと気持ち悪いです。フォントについては、しかるべきもの(ヒラギノとか)を指定する必要性を感じます。

excel1.png

OS X 10.10以降用にビルドしたJXLSフレームワークを置いておきます。興味のある方はお試しください(~/Library/Frameworks/にインストール)。

→ Download Framework (Binary)

AppleScript名:ASOCでExcelファイル生成テスト
– Created 2015-10-08 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “JXLS”

set aFile to POSIX path of (choose file name)
set filePath to current application’s NSString’s stringWithString:aFile

set workBook to current application’s JXLSWorkBook’s new()

set workSheet to workBook’s workSheetWithName:“ぴよぴよシート”
workSheet’s setWidth:1000 forColumn:0 defaultFormat:(missing value)

repeat with i from 0 to 10
  set aCell to (workSheet’s setCellAtRow:i column:0 toString:(current application’s NSString’s stringWithFormat_(“ぴよまる %d”, i + 1)))
  (
aCell’s setHorizontalAlignment:1) —-HALIGN_LEFT
  (
aCell’s setIndentation:(0 + i)) —– INDENT_0
end repeat

workBook’s writeToFile:filePath

★Click Here to Open This Script 

2015/10/06 XML-RPCのテスト

オープンソースのXML-RPCフレームワークを利用して、Web上のXML-RPCのサービスを呼び出すAppleScriptです。

AppleScriptにはcall soapやcall xmlrpc命令などが標準で実装されており、割と便利に使っています。

ただし、複雑な処理を行った場合に問題が見られました。たとえばWordPressに対して新規記事作成をリクエストした場合に、call xmlrpc命令自体が実行途中で100%クラッシュするなど、信頼性については疑問符がつき、安定性については「出たとこ勝負」なヤケッパチ感が漂っておりました。

AppleScriptの処理系がSOAPやXML-RPCの命令を実装したのは比較的早く、Mac OS X登場後間もないタイミングであったと記憶しています。ただし、この「早すぎた登場」にのちのち苦しめられることになります。

のちにAppleがOS XのIntel移行+64bitへの移行を決定。これに伴い、Carbon系の機能を使っているプログラムは事実上アップデートされないことになりました。

AppleScriptの処理系自体はIntel対応→Cocoa化→64bit化→マルチスレッド化+Scripting Bridge対応など進化して行ったのですが、call xmlrpcの機能モジュールについては「Carbon APIを使っているためアップデートしない(=バグ修正しない)」との明確な回答がAppleのエンジニアからありました。

XML-RPCの利用頻度自体はそれほど高くないため、致命的な問題にはなってはいないものの「いつか、Apple標準のcall xmlrpc命令の代わりになるものを見つけなくては」という問題意識は持っていました。

そんな中、オープンソースのXML-RPCのフレームワークをいくつか見つけ、AppleScriptから呼び出す実験を実施。その中で同期通信の機能を持っていたEric Czarny氏とNikolay Kasyanov氏のフレームワークにたどりつきました。

いろいろ試行錯誤して、AppleScriptからこのオープンソースのXML-RPCフレームワークを呼び出して、インターネット上のサービスを呼び出して使えることを確認したのが本AppleScriptです。Script Editor+ASObjC Explorer 4+OS X 10.11.0、Script Editor+OS X 10.10.5上での動作を確認しています。

XML-RPC frameworkについて、OS X 10.10以降をターゲットOSにしてビルドしたものも用意しておきました。興味のある方はおためしを(~/Library/Frameworks/にインストール)。

→ Download Framework(binary)

AppleScript名:ASOCでXML-RPCのテスト v3
– Created 2015-10-06 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “XMLRPC”
–XMLRPC.framework
–https://cocoapods.org/pods/xmlrpc
–Cocoa XML-RPC Framework © 2011 Divisible by Zero
–v2.3.4

set aRes to (my callXMLRPC(“http://yubin.senmon.net/service/xmlrpc/”, “yubin.getMaxFetchCount”, missing value)) as integer
–>  100

set bRes to (my callXMLRPC(“http://yubin.senmon.net/service/xmlrpc/”, “yubin.getVersion”, missing value)) as text
–> “15.09a”

on callXMLRPC(paramURL, aMethod, aParamList)
  
  
set aURL to current application’s |NSURL|’s URLWithString:paramURL
  
set aReq to current application’s XMLRPCRequest’s alloc()’s initWithURL:aURL
  
aReq’s setMethod:aMethod withParameter:aParamList
  
set aRes to current application’s XMLRPCConnection’s sendSynchronousXMLRPCRequest:aReq |error|:(missing value)
  
  
set errF to (aRes’s isFault()) as boolean
  
  
if errF = true then
    set xmlRPCres to faultCode of aRes
    
–set xmlRPCbody to faultString of aRes
  else
    set xmlRPCres to aRes’s object()
    
–set xmlRPCbody to aRes’s body()
  end if
  
  
return xmlRPCres
  
end callXMLRPC

★Click Here to Open This Script 

2015/10/05 キー入力チェック

Cocoaの機能を用いてキー入力チェックを行うAppleScriptです。Shane Stanleyが2年前に記述したScriptの強化版です。

AppleScriptの処理系自体にはキースキャンの機能はないため、

 ‖召離▲廛螢院璽轡腑鵑竜’修鰺用する
 ▲機璽疋僉璽謄の追加命令(Scripting Addition、OSAX)の機能を利用する
 shell scriptの機能を利用する
 Xcode上でAppleScriptを記述して、Cocoaの機能や他のObjective-Cなどの機能を呼び出す

というあたりが定番でしたが、OS X 10.10から、

 Script Editor上で記述するAppleScriptで、Cocoaの機能を呼び出す

ことができるようになったため、比較的かんたんに(追加アプリやファイルのインストールなしに)実現できるようになってきました。

ただし、ここで言う「キー入力チェック」の対象となるキーは、「Caps」「Shift」「Control」「Option」「Command」「fn」などのいわゆる「装飾キー」と呼ばれる種類のキーです。

key1.png

AppleScriptのアプレットにおいて、起動時に何かのキーを押していると通常とは異なる機能を実行するような、そういう地味な用途に用いられるものです。

key2.png

とりあえず、Script Editor上でログ表示させると、これら装飾キーの入力状況をログ表示します。最初のバージョンでは同時に1つのキー判定しかしていませんでしたが、本Scriptでは対象となる装飾キーの複数同時入力の検出をサポートしています。

AppleScript名:キー入力チェック
– Created 2013-10-14 by Shane Stanley
– Modified 2015-10-05 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit” – for NSEvent

set chkList to {“fn”, “”, “”, “Command”, “Option”, “Control”, “Shift”, “Caps”}

repeat 100 times
  set theKey to current application’s NSEvent’s modifierFlags() as integer
  
set aBin to binaryEncode(theKey) of me
  
set detectStr to text 9 thru 16 of aBin
  
set detectList to characters of detectStr
  
set aList to {}
  
set aCount to 1
  
repeat with i in detectList
    set j to contents of i
    
if j = “1″ then
      set jj to contents of item aCount of chkList
      
set the end of aList to jj
    end if
    
set aCount to aCount + 1
  end repeat
  
  
log aList
  
delay 0.5
end repeat

–0〜2^32範囲の10進数を2進数の文字列に変換して返す
on binaryEncode(aNum)
  if aNum < 0 or 67108864 < aNum then return false
  
set bitStr to “”
  
  
repeat with i from 31 to 0 by -1
    try
      set aRes to aNum div (2 ^ i)
      
set aNum to aNum mod (aRes * (2 ^ i))
    on error
      set aRes to 0
    end try
    
    
set aRes to aRes as integer
    
set bitStr to bitStr & (aRes as string)
  end repeat
  
  
return bitStr
end binaryEncode

★Click Here to Open This Script 

2015/10/04 マウスカーソルの強制移動とクリック

Cocoaの機能を用いて、画面上の指定座標にマウスカーソルを移動させてクリックを行うAppleScriptです。

AppleのドキュメントによればAPI(CGPostMouseEvent)自体はOS X 10.6でDeprecatedになっているはずですが、OS X 10.11上でも動作します。

GUI Scriptingでは手の出ない処理(実際にマウスカーソルを動かさないと応答しないタイプのアプリケーションの操作、主にAdobe系)のために補助的に用いることになるでしょう。

また、GUI Scriptingについても、本Scriptについても、「標準のScripting機能では手が出ない機能を呼び出す」ための手段であり、何から何までGUI Scriptingで座標指定してクリックしまくるべきではない(速度、確実さ)ということを明記しておきます。

追記:10.12でも動きました
追記:10.13ではついに動かなくなりました。別の方法を模索

AppleScript名:ASOCでマウスの強制移動とクリック
– Created 2015-10-04 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ApplicationServices”
use framework “Quartz”

my clickAt(100, 10)

on clickAt(newX, newY)
  
  
set pt to current application’s CGPointZero
  
set x of pt to newX
  
set y of pt to newY
  
  
current application’s CGPostMouseEvent(pt, 1, 1, 1)
  
current application’s CGPostMouseEvent(pt, 1, 1, 0)
  
end clickAt

★Click Here to Open This Script 

2015/10/03 UniversalDetectorで文字コード判定

オープンソースの文字コード判別フレームワーク「UniversalDetector」の機能を用いて与えられたテキストファイルの文字コードを判定するAppleScriptです。

たまたまGitHubでUniversalDetectorを見つけたので、ダウンロードしてビルドしてAppleScriptから呼び出して試してみました。AppleScriptで自動判定したもの(左側)との比較を行った結果がこれです(↓)。

btable.png

日本語のテキストに限定して試してみると、なかなかつらいです。AppleScriptだけで判定したほうが良好な結果が出ています。

AppleScript名:UniversalDetectorで文字コード判定
– Created 2015-10-03 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “UniversalDetector”
–https://github.com/JanX2/UniversalDetector

set aPath to (POSIX path of (choose file))
set aStr to current application’s NSString’s stringWithString:aPath
set aDetector to current application’s UniversalDetector’s new()
aDetector’s analyzeContentsOfFile:aStr
set aStr to current application’s NSString’s localizedNameOfStringEncoding:(aDetector’s encoding())

–>  (NSString) “日本語(EUC)”
–>  (NSString) “日本語(ISO 2022-JP)”
–>  (NSString) “日本語(Shift JIS)”
–>  (NSString) “Unicode(UTF-8)”
–>  (NSString) “キリル文字(Windows)” –NG。本当はUTF-16 no BOM
–>  (NSString) “中国語(GB 18030)”–NG。本当はUTF-16BE
–>  (NSString) “Unicode(UTF-16)”

set bStr to aDetector’s MIMECharset()

–>  (NSString) “EUC-JP”
–>  (NSString) “ISO-2022-JP”
–>  (NSString) “Shift_JIS”
–>  (NSString) “UTF-8″
–>  (NSString) “windows-1251″–NG
–>  (NSString) “gb18030″–NG
–>  (NSString) “UTF-16″

set aNum to (aDetector’s confidence()) * 100
–>  100.0–”EUC-JP”
–>  100.0–”ISO-2022-JP”
–>  100.0–”Shift_JIS”
–>  100.0–”UTF-8″
–>  5.271286144853–UTF-16 no BOM
–>  100.0–NGだが100%といっている
–>  100.0– “UTF-16″

★Click Here to Open This Script 

2015/10/03 文字エンコーディングを自動判別して日本語テキストファイル読み込み v1.2.1

Cocoaの機能と人間の知恵を総動員して未知の文字エンコーディングのテキストファイルに対して、文字エンコーディングを推測して「日本語の」テキストとして読み取るAppleScriptです。

未知といっておきながら、対象としているのは「UTF-8」「シフトJIS」「EUC」「ISO-2022JP」「UTF16(BOMなし)」、「UTF16(無表記)」「UTF-16BE」「UTF-16LE」です。メインフレームのEBCDICコードとかは想定していませんごめんなさいごめんなさい(誰に謝る?)。

「UTF-8」「シフトJIS」「EUC」「ISO-2022JP」については、判断方法が割と確立しているので安全に判定と読み取りが行えています。

問題は「それ以外の皆さん」(とくに「UTF16(無表記)」「UTF-16BE」「UTF-16LE」)です。

それぞれについて、文字コードチェックを総当たりで行い、問題がないものを採用するというのが順当なところですが、「問題があると判定されつつも問題がないパターン」「問題がないと判定されつつも問題があるパターン」のてんこもり。困ったところです。

解決策1:NSLinguisticTaggerに聞く

テキストを渡すと言語を判定してくれるNSLinguisticTaggerに聞いてみました。文字化けしていたら日本語として判定できないだろうという考えです。

サンプルのテキストはテクニカル系の記事(PC Watchの記事、SJISで11KB)と、ザ・近代文学ともいえる「坊ちゃん」(SJISで210KB)です。「坊ちゃん」のテキストを喰わせて「日本語」と判定できなかったらかなり問題ですが、そこは大丈夫でした。問題はアルファベットや数字が多いテクニカル系の記事で、NSLinguisticTaggerでは日本語として判定されませんでした(残念!)。

解決策2:行数と単語数をカウント

今度は、AppleScriptが持っている(最低限の)形態素解析能力を利用します(固有名詞を「連絡先」アプリや漢字変換辞書から引いてこないのがダメ)。OS X 10.6から、それ以前の「文字種類が変わったところで単語とみなす」というアホな単語切り分けをあらため、少しはマシな単語切り分けをするようになってきました(Mecabの機能を利用しているもよう。辞書固定だけど)

文字化けして謎の文字ばかり出てきた場合には、ほぼ1文字=1単語ぐらいに認識されるはずなので、経験的に言って「行数が1行の場合には文字化けしている」「単語数が多すぎる場合には文字化けしている」と言っても過言ではないでしょう。

これらを、多数決的に「UTF16(無表記)」「UTF-16BE」「UTF-16LE」「UTF16(BOMなし)」の処理結果を寄せ集めて判定するようにしてみました。

その結果がこちらです。

table1.png

v1.1の弱点を埋めようとして改良したv1.2において、逆に認識文字コードが減ってしまいました。ただし、認識順を調整するのではなしに「UTF16(無表記)」「UTF-16BE」「UTF-16LE」を総当たりでチェックして、その結果を評価すれば全部判定できるのでは? という気づきにつながりました(失敗は成功のマザー)。

手元に用意したサンプルの範囲では、ヒット率が100%。ぜひ多くの方々に使っていただいて、「ダメだった」パターンを集めてフィードバックしたいところです。こうして強化していけば、「文字コード判定のためだけにわざわざテキストエディタを操作する」とかいうアホな状況を回避できるものと思われます。

一応、El Capitan的にはEnumのBridgeが利くようになって、NSShiftJISStringEncodingといった定数をそのまま「current application’s NSShiftJISStringEncoding」などと書いています。ただ、数字の桁数がやたらと多いEnumは変数に入れたりした瞬間に指数表示になる(アホすぎる!)ので、変数にも代入できずに直接書いています。

AppleScript名:文字エンコーディングを自動判別してファイル読み込み v1.2.1
– Created 2014-12-28 by Takaaki Naganoya
– Modified 2014-12-29 by Shane Stanley
– Modified 2015-10-03 by Takaaki Naganoya
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”

set aPath to POSIX path of (choose file)
set aRes to readJapanesTextFileWithGuessingEncoding(aPath) of me

–Read Japanese text with detecting its text encoding
on readJapanesTextFileWithGuessingEncoding(aPOSIXpath as string)
  
  
–ISO2022JP check
  
set aNSData to current application’s NSData’s dataWithContentsOfFile:aPOSIXpath
  
set aDataLength to aNSData’s |length|()
  
if aDataLength > 1024 then set aDataLength to 1024
  
  
–0×1B check
  
set anNSString to current application’s NSString’s stringWithString:(character id 27) – 0×1B
  
set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set theRange to aNSData’s rangeOfData:theData options:0 range:(current application’s NSMakeRange(0, aDataLength))
  
  
–found 0×1B in aNSData
  
if |length| of theRange = 1 and location of theRange < aDataLength then
    set aStr to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSISO2022JPStringEncoding)) –21
    
if aStr is not equal to missing value then return (aStr as text) – ISO2022JP
  end if
  
  
–EUC
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSJapaneseEUCStringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
–UTF-8
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF8StringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
–SHift JIS
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSShiftJISStringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
  
  
–UTF-16BE/LE/無印Unicodeは多数決を取る
  
set resValue1 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16BigEndianStringEncoding)) as text
  
set sample1 to getTextSample(resValue1) of me
  
set lang1 to specifyLanguageOfText(sample1) of me
  
set para1 to length of (paragraphs of sample1)
  
set words1 to length of (words of sample1)
  
  
set resValue2 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16LittleEndianStringEncoding)) as text
  
set sample2 to getTextSample(resValue2) of me
  
set lang2 to specifyLanguageOfText(sample2) of me
  
set para2 to length of (paragraphs of sample2)
  
set words2 to length of (words of sample2)
  
  
set resValue3 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUnicodeStringEncoding)) as text
  
set sample3 to getTextSample(resValue3) of me
  
set lang3 to specifyLanguageOfText(sample3) of me
  
set para3 to length of (paragraphs of sample3)
  
set words3 to length of (words of sample3)
  
  
–文字および文法的に見て「日本語」ならそれを返す
  
if lang1 = “ja” then return resValue1
  
if lang2 = “ja” then return resValue2
  
if lang3 = “ja” then return resValue2
  
  
  
–文字化けしたときには、日本語の「Word」として認識されづらく、Paragraphも少ない(1とか)なので条件で除外する
  
if para1 is not equal to 1 then
    if (words1 words2) or (words1 words3) then
      return resValue1
    end if
  end if
  
  
if para2 is not equal to 1 then
    if (words2 words1) or (words2 words3) then
      return resValue2
    end if
  end if
  
  
if para3 is not equal to 1 then
    if (words3 words1) or (words3 words2) then
      return resValue3
    end if
  end if
  
  
  
  
–おまけ(未確認)
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1251StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1252StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1253StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1254StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1250StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
return false
  
end readJapanesTextFileWithGuessingEncoding

on specifyLanguageOfText(aStr)
  set aNSstring to current application’s NSString’s stringWithString:aStr
  
set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage)
  
set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0
  
tagger’s setString:aNSstring
  
set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return aLanguage as text
end specifyLanguageOfText

on getTextSample(aText)
  set aLen to length of aText
  
if aLen < 1024 then
    set bLen to aLen
  else
    set bLen to 1024
  end if
  
return (text 1 thru bLen of aText)
end getTextSample

★Click Here to Open This Script 

2015/10/02 続・指定フォルダのファイルパス一覧取得(拡張子指定つき)

Cocoaの機能を利用して指定フォルダ内のファイル(POSIX path)一覧を(拡張子を指定しつつ)リストで取得するAppleScriptの、Shane Stanleyによる「もっとCocoa的なやり方でファイル一覧を条件抽出してみた」バージョンです(Thanks!!)。

OS X 10.11ではScripting Bridgeの機能が強化(バグ修正?)され、Cocoaのファイルパス(NSURL)が、AppleScriptのfileにCastされるようになりました。その機能を用いてcastするものです。OS X 10.11では、結果がfileのlistで返ってきます。

AppleScript名:ASOCで指定フォルダのファイルパス一覧取得(拡張子指定つき)v2(10.10, 10.11)
– Created 2015-10-01 by Takaaki Naganoya
– Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aExt to "pdf" – no dot
set aFol to choose folder
set fList to getFilePathList(aFol, aExt) of me
–>  {file "Macintosh HD:Users:me:Desktop:ASObjCExtras_scripting_guide.pdf"}

on getFilePathList(aFol, aExt)
  considering numeric strings
    if AppleScript’s version < "2.5" then
      – only need to create URL if before 10.11; otherwise bridge does it for us
      
set aFol to current application’s class "NSURL"’s fileURLWithPath:(POSIX path of aFol)
    end if
  end considering
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aFol includingPropertiesForKeys:{} options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
  
set thePred to current application’s NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt}
  
set anArray to urlArray’s filteredArrayUsingPredicate:thePred
  
return anArray as list – URLs pre-10.11, files under 10.11
end getFilePathList

★Click Here to Open This Script 

ただ、OS X 10.10.x上で実行すると、NSURLのlistが返ってくるので、OS X 10.10.x向けには、BridgePlusを併用して、このように(↓)書くことになるかと。

「OS X 10.10との互換性維持問題」については、どの程度考慮すべきかなかなか悩ましいところです。

AppleScript名:ASOCで指定フォルダのファイルパス一覧取得(拡張子指定つき)v2.1
– Created 2015-10-01 by Takaaki Naganoya
– Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering
– Modified 2015-10-01 by Takaaki Naganoya –Optimized for 10.10.x

use AppleScript version "2.4" –for OS X 10.10.x
use scripting additions
use framework "Foundation"
use BridgePlus : script "BridgePlus"
load framework

set aExt to "pdf" – no dot
set aFol to choose folder
set fList to getFilePathList(aFol, aExt) of me
–>  {file "Macintosh HD:Users:me:Desktop:ASObjCExtras_scripting_guide.pdf"}

on getFilePathList(aFol, aExt)
  set aFol to current application’s class "NSURL"’s fileURLWithPath:(POSIX path of aFol)
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aFol includingPropertiesForKeys:{} options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
  
set thePred to current application’s NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt}
  
set anArray to urlArray’s filteredArrayUsingPredicate:thePred
  
return (ASify from anArray) as list
end getFilePathList

★Click Here to Open This Script