Archive for 11月, 2015

2015/11/27 Cocoaオブジェクトのクラス名を文字列で取得

OS X標準装備のScript Editor上で、Cocoaオブジェクトのクラス名をAppleScriptから文字列で取得する実験です。

最初に、文字列で指定したクラス名のオブジェクト(インスタンス)を生成するテストをNSClassFromStringを用いて実施してみました。クラスを文字列で動的に指定して、alloc()してinit()することで実際のインスタンスを生成できることを確認。

次に、Cocoaオブジェクトからクラス名を文字列で取得するテストを|class|()メソッドで実施。

これらの結果をふまえて、文字列で指定したクラス名のインスタンスを生成し、生成したインスタンスのクラス名を文字列で取得するという実験を実施。なるほどと思う点もありつつ、新たな発見が得られた点もあります。

AppleScript名:ASOCで文字列で指定したクラス名からインスタンスを生成
– Created 2015-11-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aClass to current application’s NSClassFromString(“NSString”)
set anInstance to aClass’s alloc()’s init()
–>  (NSString) “”

set aClass to current application’s NSClassFromString(“NSMutableArray”)
set anInstance to aClass’s alloc()’s init()
–>  (NSArray) {}

★Click Here to Open This Script 

AppleScript名:ASOCで指定Cocoaオブジェクトのクラス名を文字列で取得
– Created 2015-11-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set a to current application’s NSString’s alloc()’s init()
set b to (current application’s NSStringFromClass(a’s |class|())) as text
–> “__NSCFConstantString”

set a to current application’s NSArray’s alloc()’s init()
set c to (current application’s NSStringFromClass(a’s |class|())) as text
–> “__NSArray0″

set a to current application’s NSArray’s arrayWithArray:{1, 2, 3, 4}
set c to (current application’s NSStringFromClass(a’s |class|())) as text
–> “__NSArrayI”

set a to current application’s NSMutableArray’s alloc()’s init()
set c to (current application’s NSStringFromClass(a’s |class|())) as text
–> “__NSArrayM”

★Click Here to Open This Script 

AppleScript名:ASOCで指定クラス名のインスタンスを生成してクラス名を文字列で取得
– Created 2015-11-27 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

generateInstanceAndCheckIt(“NSString”) of me
–> “__NSCFConstantString”

generateInstanceAndCheckIt(“NSArray”) of me
–> “__NSArray0″

generateInstanceAndCheckIt(“NSMutableArray”) of me
–> “__NSArrayM”

generateInstanceAndCheckIt(“NSByteCountFormatter”) of me
–> “NSByteCountFormatter”

generateInstanceAndCheckIt(“NSData”) of me
–> “_NSZeroData”

generateInstanceAndCheckIt(“NSDate”) of me
–> “__NSDate”

generateInstanceAndCheckIt(“NSIndexSet”) of me
–> “_NSCachedIndexSet”

generateInstanceAndCheckIt(“NSMutableAttributedString”) of me
–> “NSConcreteMutableAttributedString”

generateInstanceAndCheckIt(“NSCountedSet”) of me
–> “NSCountedSet”

generateInstanceAndCheckIt(“NSDataDetector”) of me
–> “NSDataDetector”

generateInstanceAndCheckIt(“NSDateFormatter”) of me
–> “NSDateFormatter”

generateInstanceAndCheckIt(“NSDecimalNumber”) of me
–> “NSDecimalNumber”

generateInstanceAndCheckIt(“NSDictionary”) of me
–> “__NSDictionary0″

on generateInstanceAndCheckIt(aClassName as string)
  set a to current application’s NSClassFromString(aClassName)
  
set b to a’s alloc()’s init()
  
set c to (current application’s NSStringFromClass(b’s |class|())) as text
  
return c
end generateInstanceAndCheckIt

★Click Here to Open This Script 

2015/11/26 動的にテキストビューを表示

動的にNSTextViewを作成してログ表示するAppleScriptです。

textview1.png

Script Editor上でControl+Command+Rで、ASObjC Explorer 4上では「Run in Foreground」をチェックして実行する必要があります。

AppleScript名:ASOCでテキストビューを表示
– Created 2015-11-25 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aWidth to 400
set aHeight to 600
set aColor to current application’s NSColor’s colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0
set aTitle to “テキストビューのじっけん/TextView Test”
set outText to “ぴよまるソフトウェア / Piyomaru Software “

set aScroll to current application’s NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
set aView to current application’s NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))

set aStr to current application’s NSMutableString’s alloc()’s init()

aView’s setRichText:true
aView’s useAllLigatures:true
aView’s setTextColor:(current application’s NSColor’s cyanColor())

aView’s setBackgroundColor:aColor
aScroll’s setDocumentView:aView
aView’s enclosingScrollView()’s setHasVerticalScroller:true

set aWin to makeWinWithView(aScroll, aWidth, aHeight, aTitle, 0.8)
aWin’s makeKeyAndOrderFront:(missing value)
aWin’s makeFirstResponder:aView

repeat with i from 1 to 100
  set bStr to (current application’s NSMutableString’s stringWithString:(outText & (i as string) & return))
  
set aStr to (bStr’s stringByAppendingString:aStr)
  (
aView’s setString:aStr)
end repeat

my closeWin:aWin

–make Window for Input
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle, alphaV)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
set aBacking to current application’s NSTitledWindowMask –NSBorderlessWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
– Window
  
set aWin to current application’s NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
aWin’s setBackgroundColor:(current application’s NSColor’s whiteColor())
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(current application’s NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setAlphaValue:alphaV –append
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s makeKeyAndOrderFront:(me)
  
  
– Set Custom View
  
aWin’s setContentView:aView
  
  
return aWin
  
end makeWinWithView

–close win
on closeWin:aWindow
  delay 5
  
repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

★Click Here to Open This Script 

2015/11/19 度量衡の変換

オープンソースの「DDUnitConverter」(By Dave DeLong)を用いて、度量衡(measurement unit)の変換を行うAppleScriptです。AppleScriptから呼び出すために、DDUnitConverterをフレームワーク化した「ddUnitConversionKit」を作成しています。

もともと、AppleScriptには内蔵の度量衡変換機能があり、

AppleScript名:インチからセンチへの変換
set a to 1
set a to a as inches
–> inches 1.0

set b to a as centimeters
–> centimeters 2.54

set c to a as meters
–> meters 0.0254

set d to a as kilometers
–> kilometers 2.54E-5

★Click Here to Open This Script 

とか、

AppleScript名:液体の容積の単位変換
–液体の容積の単位変換
set a to 10 as liters
–> liters 10.0

set b to a as gallons
–> gallons 2.641720372842

set c to a as quarts
–> quarts 10.566881491367

★Click Here to Open This Script 

ぐらいは簡単にできます。AppleScriptがサポートしている度量衡は、長さ、重さ、温度、液体の容積です。

ただ、mmの下のμmとか、オングストロームとか、そういう単位には対応していませんし、重量でいえばKgに対応していてもt(トン)の単位はサポートしていなかったりと、日常的な度量衡の単位の世界でも不十分な感じが否めません(数値の有効桁数が10桁と小さいことも影響?)。

Cocoaの世界で度量衡変換機能について調べてみたところ、km→m→cm→mmといった変換はしてくれるものの、他の単位への変換は行ってくれていなかったりして、標準機能だけではいまひとつな印象です。

AppleScript名:NSLengthFormatterのじっけん
– Created 2015-11-18 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://dev.classmethod.jp/references/ios8-new-formatter/

set aLengthFormatter to current application’s NSLengthFormatter’s alloc()’s init()
set aMeters to 5000
set aRes to (aLengthFormatter’s stringFromMeters:aMeters) as text
–>  "5 km"
set bRes to (aLengthFormatter’s stringFromMeters:500) as text
–>  "500 m"
set cRes to (aLengthFormatter’s stringFromMeters:0.5) as text
–>  "50 cm"
set dRes to (aLengthFormatter’s stringFromMeters:0.005) as text
–>  "5 mm"
set eRes to (aLengthFormatter’s stringFromMeters:("0.000005" as real)) as text
–>  "0.005 mm"

set res2 to aLengthFormatter’s getObjectValue:(missing value) forString:aRes errorDescription:(missing value)
–>  false

set res3 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMillimeter)) as text
–>  "5,000 mm"
set res4 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitCentimeter)) as text
–>  "5,000 cm"
set res5 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMeter)) as text
–>  "5,000 m"
set res6 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitKilometer)) as text
–>  "5,000 km"
set res7 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitInch)) as text
–>  "5,000 in"
set res8 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitFoot)) as text
–>  "5,000 ft"
set res9 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitYard)) as text
–>  "5,000 yd"
set res10 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMile)) as text
–>  "5,000 mi"

★Click Here to Open This Script 

AppleScript名:NSMassFormatterのじっけん
– Created 2015-11-18 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://dev.classmethod.jp/references/ios8-new-formatter/

set aMasFormatter to current application’s NSMassFormatter’s alloc()’s init()
set aKilloGrams to 60.0
set aRes to (aMasFormatter’s stringFromKilograms:aKilloGrams) as text
–>  "60 kg"
set a2Res to (aMasFormatter’s stringFromKilograms:(0.5)) as text
–>  "500 g"
set a3Res to (aMasFormatter’s stringFromKilograms:(5000000)) as text
–>  "5,000,000 kg"
set a4Res to (aMasFormatter’s stringFromKilograms:("0.0005" as real)) as text
–>  "0.5 g"

set bRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitGram)) as text
–>  "60 g"
set cRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitKilogram)) as text
–>  "60 kg"
set dRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitOunce)) as text
–>  "60 oz"
set eRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitPound)) as text
–>  "60 lb"
set fRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitStone)) as text
–>  "60 st"

set gRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitGram)) as text
–>  "g"
set hRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitKilogram)) as text
–>  "kg"
set iRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitOunce)) as text
–>  "oz"
set jRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitPound)) as text
–>  "lb"
set kRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitStone)) as text
–>  "st"

set res01 to aMasFormatter’s getObjectValue:(missing value) forString:fRes errorDescription:(missing value)
–>  false

set res02 to (aMasFormatter’s stringFromKilograms:80) as text
–>  "80 kg"

set res03 to aMasFormatter’s unitStyle()
–>  2 = NSFormattingUnitStyleMedium

★Click Here to Open This Script 

そこで、冒頭に紹介したようにDDUnitConverterを導入してみたわけですが、これはこれで問題がないわけでもありません。本来、通貨同士の変換をサポートしており、通貨レートの更新機能を持っているのですが、実際に呼び出してみると更新されていない雰囲気が濃厚です(呼び出し方を間違っているのか?)。

なので、「通貨レート以外」の度量衡変換にのみ用いるのが安全な使い方なのかもしれない、というところです。

例によって、OS X 10.10以降用にビルドしたバイナリを用意しておきましたので、興味のある方はアーカイブを展開したあとで、~/Library/Frameworksに入れておためしください。

–> Download ddUnitConversionKit.framework binary

AppleScript名:DDUnitConverterのじっけん1
– Created 2015-11-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ddUnitConversionKit” –davedelong/DDUnitConverter
–https://github.com/davedelong/DDUnitConverter

–enums in DDVelocityUnitConverter.h
property DDVelocityUnitCentimetersPerHour : 0
property DDVelocityUnitCentimetersPerMinute : 1
property DDVelocityUnitCentimetersPerSecond : 2
property DDVelocityUnitFeetPerHour : 3
property DDVelocityUnitFeetPerMinute : 4
property DDVelocityUnitFeetPerSecond : 5
property DDVelocityUnitInchesPerHour : 6
property DDVelocityUnitInchesPerMinute : 7
property DDVelocityUnitInchesPerSecond : 8
property DDVelocityUnitKilometersPerHour : 9
property DDVelocityUnitKilometersPerMinute : 10
property DDVelocityUnitKilometersPerSecond : 11
property DDVelocityUnitKnots : 12
property DDVelocityUnitLight : 13
property DDVelocityUnitMach : 14
property DDVelocityUnitMetersPerHour : 15
property DDVelocityUnitMetersPerMinute : 16
property DDVelocityUnitMetersPerSecond : 17
property DDVelocityUnitMilesPerHour : 18
property DDVelocityUnitMilesPerMinute : 19
property DDVelocityUnitMilesPerSecond : 20
property DDVelocityUnitFurlongsPerFortnight : 21

–時速100kmを秒速kmに変換
set aVal to ((current application’s DDUnitConverter’s velocityUnitConverter())’s convertNumber:100 fromUnit:(DDVelocityUnitKilometersPerHour) toUnit:(DDVelocityUnitKilometersPerSecond)) as real
–>  0.027777777778

★Click Here to Open This Script 

AppleScript名:DDCurrencyUnitConverterのじっけん
– Created 2015-11-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ddUnitConversionKit” –davedelong/DDUnitConverter
–https://github.com/davedelong/DDUnitConverter

–enums in DDCurrencyUnitConverter.h
property DDCurrencyUnitEuro : 0
property DDCurrencyUnitJapaneseYen : 1
property DDCurrencyUnitUKPoundSterling : 2
property DDCurrencyUnitUSDollar : 3
property DDCurrencyUnitAlgerianDinar : 4
property DDCurrencyUnitArgentinePeso : 5
property DDCurrencyUnitAustralianDollar : 6
property DDCurrencyUnitBahrainDinar : 7
property DDCurrencyUnitBotswanaPula : 8
property DDCurrencyUnitBrazilianReal : 9
property DDCurrencyUnitBruneiDollar : 10
property DDCurrencyUnitCanadianDollar : 11
property DDCurrencyUnitChileanPeso : 12
property DDCurrencyUnitChineseYuan : 13
property DDCurrencyUnitColombianPeso : 14
property DDCurrencyUnitCzechKoruna : 15
property DDCurrencyUnitDanishKrone : 16
property DDCurrencyUnitHungarianForint : 17
property DDCurrencyUnitIcelandicKrona : 18
property DDCurrencyUnitIndianRupee : 19
property DDCurrencyUnitIndonesianRupiah : 20
property DDCurrencyUnitIranianRial : 21
property DDCurrencyUnitIsraeliNewSheqel : 22
property DDCurrencyUnitKazakhstaniTenge : 23
property DDCurrencyUnitKoreanWon : 24
property DDCurrencyUnitKuwaitiDinar : 25
property DDCurrencyUnitLibyanDinar : 26
property DDCurrencyUnitMalaysianRinggit : 27
property DDCurrencyUnitMauritianRupee : 28
property DDCurrencyUnitMexicanPeso : 29
property DDCurrencyUnitNepaleseRupee : 30
property DDCurrencyUnitNewZealandDollar : 31
property DDCurrencyUnitNorwegianKrone : 32
property DDCurrencyUnitRialOmani : 33
property DDCurrencyUnitPakistaniRupee : 34
property DDCurrencyUnitNuevoSol : 35
property DDCurrencyUnitPhilippinePeso : 36
property DDCurrencyUnitPolishZloty : 37
property DDCurrencyUnitQatarRiyal : 38
property DDCurrencyUnitRussianRuble : 39
property DDCurrencyUnitSaudiArabianRiyal : 40
property DDCurrencyUnitSingaporeDollar : 41
property DDCurrencyUnitSouthAfricanRand : 42
property DDCurrencyUnitSriLankaRupee : 43
property DDCurrencyUnitSwedishKrona : 44
property DDCurrencyUnitSwissFranc : 45
property DDCurrencyUnitThaiBaht : 46
property DDCurrencyUnitTrinidadAndTobagoDollar : 47
property DDCurrencyUnitTunisianDinar : 48
property DDCurrencyUnitUAEDirham : 49
property DDCurrencyUnitPesoUruguayo : 50
property DDCurrencyUnitBolivarFuerte : 51
property DDCurrencyUnitSDR : 52

–最初に通貨レートの更新を行う必要があるが、実行しても変わらないのはなぜ????
set aConv to current application’s DDUnitConverter’s currencyUnitConverter()
aConv’s refreshExchangeRates()
set aVal to (aConv’s convertNumber:100 fromUnit:(DDCurrencyUnitUSDollar) toUnit:(DDCurrencyUnitJapaneseYen))
–>  (NSNumber) 1.006839721743

★Click Here to Open This Script 

2015/11/18 簡易日本語形態素解析のじっけん

日本語のテキストのかんたんな形態素解析(Morphological Analysis)を行うAppleScriptです。

日本語の形態素解析は、欠くことのできない重要な要素技術であるため、さまざまなプログラム(道具)を評価していきたいところです。

OS X 10.6以降、AppleScript自体の「words of」の機能が日本語のテキストにもまともに対応し、OS内蔵のMecabを使ってparseするように変わったようです。確証はないのですが、どうもほぼ同時にspotlightのインデックス作成のためにOS Xに導入されたMecabの機能を利用するようになったもよう。

ただし、AppleScriptで日本語のテキストに対してwords ofを実行した場合、読点「、」や句読点「。」はなぜか読み飛ばすため、これが気に入らないケースも出てきます。

さらに、OS X内蔵の形態素解析エンジンも、AppleScriptからはいじくりにくい(Blocks構文の記述が必要なので呼べない)ため、他の道具をいろいろさがしてみたくなります。

Mecabの作者の工藤 拓氏が作られた、JavaScriptだけで書かれた分かち書きソフトウェア「TinySegmenter」を、さらにiOS向けにObjective-Cで書き直した「TinySegmenter.m」(By Tatsuya Tobioka)を、私がMac用にほんの少しだけ書き直して(ARC環境下でビルドおよび実行できるよう、deallocのハンドラの内容をすべてコメントアウトしただけ)、Framework化した「JparseKit.framework」をでっちあげました(開発とかいうレベルではなく、単なる作業。数分で終わった)。

この、JparseKitを呼び出してみたのがこのAppleScriptです。

AppleScriptのwords of(たぶんMecab)の結果と並べてみましたが、ほとんど一緒です。辞書を持たないタイプの分かち書きエンジンらしいのですが、かなり驚きの出力結果が得られます。ただし、口語体の文章には弱い(原理上、ひらがなだけで書かれた文章にも弱そう)とのことなので気を付ける必要があります。

# 逆に、ASのwords ofが使っているロジックがこのTinySegmenterっぽいものである、という可能性も否定できなくなってきました、、、

呼び出しているObjective-Cのファイルも1つだけなので、ASで書き直して手を入れて使ったほうが(AddressBookから姓名を抽出して、形態素解析のために併用するとか)よさそうな気もします。

例によって、OS X 10.10以降用にビルドしたバイナリを用意しておきましたので、興味のある方はアーカイブを展開したあとで、~/Library/Frameworksに入れておためしください。

–> Download jparseKit.framework binary

AppleScript名:TinySegmenterのじっけん
– Created 2015-11-18 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “JparseKit” –tnantoka/TinySegmenter.m
–https://github.com/tnantoka/TinySegmenter.m

set aSegmenter to current application’s TinySegmenter’s alloc()’s init()
set a1SegList to (aSegmenter’s segment:“これはテストですよ”) as list
–>  {”これ”, “は”, “テスト”, “です”, “よ”}
set a2SegList to words of “これはテストですよ”
–>  {”これ”, “は”, “テスト”, “です”, “よ”}

set b1SegList to (aSegmenter’s segment:“私の名前は長野谷です。”) as list
–>  {”私”, “の”, “名前”, “は”, “長野”, “谷”, “です”, “。”}
set b2SegList to words of “私の名前は長野谷です。”
–>  {”私”, “の”, “名前”, “は”, “長野”, “谷”, “です”}

set c1SegList to (aSegmenter’s segment:“このプログラムは、AppleScriptで記述してあります。”) as list
–>  {”この”, “プログラム”, “は”, “AppleScript”, “で”, “記述”, “し”, “て”, “あり”, “ます”, “。”}
set c1SegList to words of “このプログラムは、AppleScriptで記述してあります。”
–>  {”この”, “プログラム”, “は”, “AppleScript”, “で”, “記述”, “し”, “て”, “あり”, “ます”}

★Click Here to Open This Script 

2015/11/18 PEGKitのじっけん

オープンソースのプロジェクト「PEGKit」(By Todd Ditchendorf)を用いて、プログラムの文字列をparseする実験を行ったAppleScriptです。

PEGKitはParsing Expression Grammar toolkitであり、「定義された文法にもとづいて文字列をparseする」ものです。プログラミング言語や数式のparseを行う目的で作られたもの、と自分は理解しています。日本語や英語のような自然言語のparseを行うものではありません。

数式のparseを行うためのチュートリアルがこちらに存在しています。

何か目的があって首を突っ込んだわけではないのですが、数式のparseを行うサンプルを読んでいると、「少ない労力で文字列をparseするルールを定義できそう」という印象を受けます。

本ScriptはPEGKitのTokenizerのサンプル(Objective-C)をAppleScriptに翻訳したものであり、PEGKitの働きを端的に把握できるよい例だと思います。

“2 != -47. /* comment */ Blast-off!! ‘Woo-hoo!’ // comment”

という、なんとなくプログラミング言語っぽい文字列を文法要素ごとにparseして、それがstringなのかsymbolなのかnumberなのかwordなのかといった文法上の区分を認識しつつ出力し、明らかにコメントっぽい部分は読み飛ばすという動きをしています。

例によって、OS X 10.10以降用にビルドしたバイナリを用意しておきましたので、興味のある方はアーカイブを展開したあとで、~/Library/Frameworksに入れておためしください。

–> Download PEGKit framework binary

AppleScript名:PEGKitのじっけん
– Created 2015-11-18 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “PEGKit” –itod/pegkit
–https://github.com/itod/pegkit

set s to “2 != -47. /* comment */ Blast-off!! ’Woo-hoo!’ // comment”
set t to current application’s PKTokenizer’s tokenizerWithString:s

set anEOF to current application’s PKToken’s EOFToken()

repeat
  set tok to (t’s nextToken())
  
if tok = anEOF then exit repeat
  
  
set aVal to tok’s stringValue()
  
–set bVal to tok’s floatValue() –??? — -[PKToken floatValue]: unrecognized selector sent to instance 0×7f87c818
  
set cVal to tok’s debugDescription()
  
log {aVal, cVal} –Cocoa logging is available in only ASObjC Explorer 4
  
  
– (* {(NSString) “2″, (NSString) “Number «2»“} *)
  
– (* {(NSString) “!=”, (NSString) “Symbol «!=»“} *)
  
– (* {(NSString) “-47″, (NSString) “Number «-47»“} *)
  
– (* {(NSString) “.”, (NSString) “Symbol «.»“} *)
  
– (* {(NSString) “Blast-off”, (NSString) “Word «Blast-off»“} *)
  
– (* {(NSString) “!”, (NSString) “Symbol «!»“} *)
  
– (* {(NSString) “!”, (NSString) “Symbol «!»“} *)
  
– (* {(NSString) “’Woo-hoo!’”, (NSString) “Quoted String «’Woo-hoo!’»“} *)
  
end repeat

★Click Here to Open This Script 

2015/11/16 ローマ数字エンコーダー

Cocoaの機能を用いた数値→ローマ数字エンコーダのAppleScriptです。

動作検証のために、1〜9999までの数字(ローマ数字の有効桁数内)をローマ数字にエンコードして、以前に掲載したローマ数字→数値デコーダーを呼び出して比較しています。

AppleScript名:ASOCローマ数字エンコーダー v2
– Created 2015-11-16 by Takaaki Naganoya
– Modified 2017-05-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://stackoverflow.com/questions/14762282/how-to-convert-a-roman-numeral-to-an-nsnumer
–http://piyocast.com/as/archives/3840

repeat with i from 1 to 9999
  set aRes to (my numberToRomanNumerals:i)
  
set bRes to roman2arabic(aRes) of me
  
if i is not equal to bRes then log i
end repeat

–Roman Number String Encoder
on numberToRomanNumerals:aNum
  if (aNum < 0 or aNum > 3999) then return "" –条件が間違っていたので直した(2017/5/18)
  
  
set r_ones to {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}
  
set r_tens to {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}
  
set r_hunds to {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}
  
set r_thouds to {"M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM", "MMMMMMMMM"}
  
  
set ones to aNum mod 10
  
set tens to (aNum - ones) mod 100
  
set hundreds to (aNum - tens - ones) mod 1000
  
set thou to (aNum - hundreds - tens - ones) mod 10000
  
  
set tens to tens / 10
  
set hundreds to hundreds / 100
  
set thou to thou / 1000
  
  
set rNum to current application’s NSString’s stringWithString:""
  
  
if thou > 0 then set rNum to rNum’s stringByAppendingString:(item thou of r_thouds)
  
if hundreds > 0 then set rNum to rNum’s stringByAppendingString:(item hundreds of r_hunds)
  
if tens > 0 then set rNum to rNum’s stringByAppendingString:(item tens of r_tens)
  
if ones > 0 then set rNum to rNum’s stringByAppendingString:(item ones of r_ones)
  
  
return rNum as text
end numberToRomanNumerals:

–Roman Number String Decoder
on roman2arabic(str)
  – Piero Garzotto (http://scriptbuilders.net/files/romannumerals1.0.html)
  
local str, r, i
  
set r to 0
  
repeat with i from 1 to count str
    set r to r + (item (offset of (item i of str) in "mdclxvi") of ¬
      {1000, 500, 100, 50, 10, 5, 1}) * (((((offset of ¬
      (
item (i + 1) of (str & "@")) in "mdclxvi@") (offset of ¬
      (
item i of str) in "mdclxvi")) as integer) * 2) - 1)
  end repeat
  
return r
end roman2arabic

★Click Here to Open This Script 

2015/11/13 MIKMIDIでMIDIデバイス一覧を取得

MIDIで接続されたデバイス一覧を取得するAppleScriptです。

まず、MIDIデバイスとMacの接続を行うわけですが、これについては安価なUSB-MIDI I/Fが市販されているため、こうしたものを利用するのが手軽でよいでしょう。自分はRolandのUM-ONEを試してみました。

top_l_resized.png

UM-Oneは専用のデバイスドライバをインストールすれば使えるようになります。

次に、AppleScriptからMIDIにアクセスする方法を模索することになります。現時点では3つの方法を見つけています。

1つめは、Apple純正のCoreMIDIを利用する方法。CのAPIなのでAppleScript-Cocoa Bridgeには手に負えない箇所が出てきそうですし、仕様を読んでいると何から何まで自分で記述しないといけないようなので、ちょっとウンザリします。

2つめは、オープンソースのフレームワーク「MIDIKit」(By Randy Weinstein)を利用する方法。いろいろAppleScriptからこづき回してみたところ、接続確認やMIDIデバイスのオンライン状態は調べられたものの、それ以上のことができません。たとえば、MIDIデバイスの名称(name)をAppleScriptから取得しようとするとすべてmissing valueが返ってくるなど、相性の悪さを感じました(日本語環境なのでなおさら未検証だったりするのかも)。

3つめが、今回紹介する同じくオープンソースのフレームワーク「MIKMIDI」(By Andrew Madsen)を利用する方法です。

midistudio.png
▲実験時の機器構成をOS X標準装備の「Audio MIDI設定」アプリで確認したところ。IAC Driverに「GarageBand」という名前のポートを宣言している。

自分がいろいろ試した中では、MIKMIDIが一番各種情報にアクセスしやすい印象を持っています。まだ、MIDI機器の接続状態を調べたぐらいなので、指定のデバイスにメッセージを送ったりできているレベルではありませんが、いろいろ調べてみるとできそうな感じがします。

img_3175.jpg
▲LAN経由でMIDI音源(Sound Canvas for iOS)をつないでみた。まだ、AppleScriptからメッセージを送れてはいない状況

AppleScript名:MIKMIDIでデバイス一覧を取得
– Created 2015-11-13 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “MIKMIDI” –mixedinkey-opensource/MIKMIDI
–https://github.com/mixedinkey-opensource/MIKMIDI

set availableMIDIDevices to current application’s MIKMIDIDeviceManager’s sharedDeviceManager()’s availableDevices()
(*
–>  (NSArray) {(MIKMIDIDevice) <MIKMIDIDevice: 0×7f8a5e972a80> IAC Driver:
Entities: {
GarageBand:
Sources: {
<MIKMIDISourceEndpoint: 0×7f8a63a65610> IAC Driver GarageBand,
}
Destinations: {
<MIKMIDIDestinationEndpoint: 0×7f8a61bbc130> IAC Driver GarageBand,
},
}, (MIKMIDIDevice) <MIKMIDIDevice: 0×7f8a5e8d4320>ネットワーク:
Entities: {
}, (MIKMIDIDevice) <MIKMIDIDevice: 0×7f8a638a5fc0> Bluetooth:
Entities: {
}, (MIKMIDIDevice) <MIKMIDIDevice: 0×7f8a59e16360> UM-ONE:
Entities: {
<MIKMIDIEntity: 0×7f8a59ed8990> UM-ONE:
Sources: {
<MIKMIDISourceEndpoint: 0×7f8a61d47950> 新しい外部装置,
}
Destinations: {
<MIKMIDIDestinationEndpoint: 0×7f8a5ecadcf0> 新しい外部装置,
},
}}
*)

set aCount to availableMIDIDevices’s |count|()
–> 4

set availableVDevices to current application’s MIKMIDIDeviceManager’s sharedDeviceManager()’s virtualSources()
–>  (NSArray) {(MIKMIDISourceEndpoint) IAC Driver GarageBand, (MIKMIDISourceEndpoint) 新しい外部装置}

★Click Here to Open This Script 

2015/11/13 iWorkアプリがアップデート。AppleScript関連の機能変更はなし

AppleのiWorkアプリケーションのアップデートがリリースされました。

Keynote 6.6→6.6.1、Pages 5.6→5.6.1、Numbers 3.6→3.6.1

AppleScript用語辞書ベースでの変更点はありません。

2015/11/11 文字列のURLエンコード、デコード

Cocoaの機能を用いてURLエンコード/デコードを行うAppleScriptです。

AppleScript名:ASOCで文字列のURLエンコード、デコード
– Created 2015-11-11 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aText to "ぴよまるソフトウェア"

set bText to retURLencodedStrings(aText) of me
–> "%E3%81%B4%E3%82%88%E3%81%BE%E3%82%8B……"(省略)

set cText to retURLdecodedStrings(bText) of me
–>  "ぴよまるソフトウェア"

on retURLencodedStrings(aText)
  set aStr to current application’s NSString’s stringWithString:aText
  
set encodedStr to aStr’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s alphanumericCharacterSet())
  
return encodedStr as text
end retURLencodedStrings

on retURLdecodedStrings(aURLencodedStr)
  set aStr to current application’s NSString’s stringWithString:aURLencodedStr
  
set aDecoded to aStr’s stringByRemovingPercentEncoding()
  
return aDecoded as text
end retURLdecodedStrings

★Click Here to Open This Script 

2015/11/11 Safariでアクセス中のページが設定しているCookieの値を求める

Safariでアクセス中のページ(最前面のページ)で設定しているCookieの値を求めるAppleScriptです。

Safariの各種コントロールを日々行っていますが、Cookieの値を見て処理を分岐できると便利そうなケースがあったため、一応調べてみました。結局、そのページでは有用な情報はCookieから取得することはできなかったのですが、いつかどこかで有用な用途があるのでは? と考え掲載しておきます。

Cookieの値をURLデコードするように変更しました。

AppleScript名:Safariでアクセス中のページが設定しているCookie値を求める
– Created 2015-11-11by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
tell application "Safari"
  set dCount to count every document
  
if dCount = 0 then return
  
  
tell front document
    set aRes to do JavaScript "document.cookie"
  end tell
end tell
set bRes to retURLdecodedStrings(aRes) of me

set cookieList to parseByDelim(bRes, ";") of me
return cookieList

on parseByDelim(aData, aDelim)
  set aStr to current application’s NSString’s stringWithString:aData
  
set aDelimStr to current application’s NSString’s stringWithString:aDelim
  
set delimArray to aStr’s componentsSeparatedByString:aDelimStr
  
set aList to delimArray as list
  
return aList
end parseByDelim

on retURLencodedStrings(aText)
  set aStr to current application’s NSString’s stringWithString:aText
  
set encodedStr to aStr’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s alphanumericCharacterSet())
  
return encodedStr as text
end retURLencodedStrings

on retURLdecodedStrings(aURLencodedStr)
  set aStr to current application’s NSString’s stringWithString:aURLencodedStr
  
set aDecoded to aStr’s stringByRemovingPercentEncoding()
  
return aDecoded as text
end retURLdecodedStrings

★Click Here to Open This Script 

2015/11/09 Safariと同じUser Agent文字列を組み立てる

Cocoaの機能を用いて、SafariのUser Agent名が返す文字列と同じものを生成するAppleScriptです。

さまざまな用途のために、AppleScriptでカスタムWebブラウザを作ることがあります。その際に、Safariと同じUser Agent名をWebサーバー側に返すことができるとメリットがあります。正確にいえば、Safariのフリをしてブラウズを行うことで、さまざまなトラブルを回避できます。

取得にあたっては、Safariを起動してSafariからUser Agent名を取るのではなく、WebKitが返すUser Agent情報に(未起動状態の)SafariのバージョンやビルドNo.をつないで生成しています。ビルドNo.についてはメジャーNo.の下3桁だけが出力されており、少々不思議なところですが、実物のSafariと合うように調整しています。

一応本ルーチンが正常に文字列を生成できているかのテストのために、SafariからUser Agent名を取得して比較を行い、同一の文字列が生成できていることを確認しています(実際に使うときには削除)。

AppleScript名:SafariのUser Agent文字を組み立てる
– Created 2015-11-09 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Webkit”

set aRes to getSafariUserAgentString() of me
–>  ”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.6 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.6″

–ほんまもんのSafariからUser Agentを取得してテスト
tell application “Safari”
  tell document 1
    set dRes to do JavaScript “navigator.userAgent”
    
–>  ”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.6 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.6″
  end tell
end tell

return (aRes = dRes)
–>  true

–Safariと同じUser Agentの文字列を取得する
on getSafariUserAgentString()
  set aBundle to current application’s NSBundle’s bundleWithIdentifier:“com.apple.Safari”
  
set aVer to (aBundle’s infoDictionary()’s objectForKey:“CFBundleShortVersionString”) as text
  
–>  ”9.0.2″
  
  
set aBuildNo to (aBundle’s infoDictionary()’s objectForKey:“CFBundleVersion”) as text
  
–>  ”11601.3.6″
  
set {v1, v2, v3} to parseVersionNumber(aBuildNo) of me
  
set aV1 to current application’s NSString’s stringWithString:v1
  
set bV1 to aV1’s substringFromIndex:2 –3 characters from tail –?????
  
–> “601″
  
  
set bStr to retStrFromArrayWithDelimiter({bV1, v2, v3}, “.”) of me
  
  
set aWebView to current application’s WebView’s alloc()’s init()
  
set aRes to (aWebView’s stringByEvaluatingJavaScriptFromString:“navigator.userAgent”) as text
  
–>  ”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.6 (KHTML, like Gecko)”
  
  
return (aRes & ” Version/” & aVer & ” Safari/” & bStr)
  
end getSafariUserAgentString

–バージョン番号文字列からメジャーバージョンを取り出し数値として返す
on parseVersionNumber(a)
  set aStr to current application’s NSString’s stringWithString:a
  
set aRes to (aStr’s componentsSeparatedByString:“.”)
  
set bRes to aRes’s allObjects()
  
return bRes as list
end parseVersionNumber

–リストを指定デリミタをはさんでテキスト化
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

★Click Here to Open This Script 

2015/11/09 ムービーからオーディオのみ抽出してm4aで保存 v2

指定のQuickTimeムービーからオーディオのみ抽出してm4a(MPEG-4 Audio)で保存するAppleScriptです。

Shane Stanleyから「外部のFrameworkを使わなくても、AppleScriptだけで処理できる」バージョンを教えてもらいました。なるほど、たしかに外部のFrameworkを利用しなくてもexportできることを確認しました。

本Scriptは2本ともForegroundで実行する必要があるため、Script EditorでCommand-Control-Rで実行します。ASObjC Explorer 4では、「Run in Foreground」にチェックを入れて実行します。

AppleScript名:ASOCでムービーからオーディオのみ抽出してM4Aで保存 v2a
– Created 2015-11-09 by Shane Stanley
use AppleScript version “2.3.1″
use scripting additions
use framework “Foundation”
use framework “AVFoundation”

set aFile to POSIX path of (choose file of type {“com.apple.quicktime-movie”} with prompt “Choose a QuickTime movie to export as MP4 audio”)
set anNSURL to current application’s class “NSURL”’s fileURLWithPath:aFile
set outNSURL to anNSURL’s URLByAppendingPathExtension:“m4a”

set theAsset to current application’s AVAsset’s assetWithURL:anNSURL
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:(current application’s AVAssetExportPresetAppleM4A)
theSession’s setOutputURL:outNSURL
theSession’s setOutputFileType:(current application’s AVFileTypeAppleM4A)
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
current application’s NSTimer’s scheduledTimerWithTimeInterval:2.0 target:me selector:“checkSession:” userInfo:theSession repeats:true

on checkSession:theTimer
  set theSession to theTimer’s userInfo()
  
set theProgress to theSession’s status() as integer
  
if theProgress > 2 then
    theTimer’s invalidate()
    
if theProgress = (current application’s AVAssetExportSessionStatusCompleted) as integer then
      display dialog “Done”
    else if theProgress = (current application’s AVAssetExportSessionStatusFailed) as integer then
      display dialog “Failed”
    else if theProgress = (current application’s AVAssetExportSessionStatusCancelled) as integer then
      display dialog “Cancelled”
    end if
  end if
end checkSession:

★Click Here to Open This Script 

AppleScript名:ASOCでムービーからオーディオのみ抽出してM4Aで保存 v2b
– Created 2015-11-09 by Shane Stanley
– Modified 2015-11-09 by Takaaki Naganoya
use AppleScript version “2.3.1″
use scripting additions
use framework “Foundation”
use framework “AVFoundation”

property expStat : false

set aFile to POSIX path of (choose file of type {“com.apple.quicktime-movie”} with prompt “Choose a QuickTime movie to export as MP4 audio”)
set anNSURL to current application’s class “NSURL”’s fileURLWithPath:aFile
set outNSURL to anNSURL’s URLByAppendingPathExtension:“m4a”

set theAsset to current application’s AVAsset’s assetWithURL:anNSURL
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:(current application’s AVAssetExportPresetAppleM4A)
theSession’s setOutputURL:outNSURL
theSession’s setOutputFileType:(current application’s AVFileTypeAppleM4A)
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
current application’s NSTimer’s scheduledTimerWithTimeInterval:1.0 target:me selector:“checkSession:” userInfo:theSession repeats:true

repeat
  delay 0.01
  
if my expStat is not equal to false then exit repeat
end repeat

return my expStat
–>  ”Done”

on checkSession:theTimer
  set theSession to theTimer’s userInfo()
  
set theProgress to theSession’s status() as integer
  
if theProgress > 2 then
    theTimer’s invalidate()
    
if theProgress = (current application’s AVAssetExportSessionStatusCompleted) as integer then
      set my expStat to “Done”
    else if theProgress = (current application’s AVAssetExportSessionStatusFailed) as integer then
      set my expStat to “Failed”
    else if theProgress = (current application’s AVAssetExportSessionStatusCancelled) as integer then
      set my expStat to “Cancelled”
    end if
  end if
end checkSession:

★Click Here to Open This Script 

2015/11/09 ムービーからオーディオのみ抽出してm4aで保存

Cocoaの機能を用いて、指定のQuickTimeムービーから音声のみ抽出してM4A(MPEG-4 Audio)で保存して指定のメタデータを付与するAppleScriptです。

Alex Nichol氏の「MP4Audio」をFramework化した「mp4AudioExportKit」を作って、それをAppleScriptから呼び出しています。

ただ、ビルド時に「それはもうdeprecatedだよー」というwarningが大量に出ているので、OS X 10.12以降で使えるかどうかは未知数です。

meta2.png
▲出力した音声データ(audiotest1.m4a)のmetadataをTerminal.app上で確認したところ。たしかに指定のデータが入っている

本Scriptでは、常識的な処理をひととおり試しているだけです。Sampling Rateを変更したりといったことは行っていません。

例によって、OS X 10.10以降用にビルドしたバイナリをあげておきますので、興味のある方は、アーカイブを展開して~/Library/Frameworksに入れてお試しください。

→ Download mp4AudioExportKit.framework

AppleScript名:MP4Audioのじっけん(ムービーからオーディオのみ抽出してM4Aで保存)
– Created 2015-11-09 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “mp4AudioExportKit” –unixpickle/MP4Audio
–https://github.com/unixpickle/MP4Audio

–Open Original Movie
set aFile to POSIX path of (choose file of type {“com.apple.quicktime-movie”} with prompt “Choose a QuickTime movie to export as MP4 audio”)
set aPath to current application’s NSString’s stringWithString:aFile
set aMovie to current application’s ANMovie’s alloc()’s initWithFile:aPath

–Select Export File Name
set bFile to POSIX path of (choose file name with prompt “Input Export file name”)
set bPath to current application’s NSString’s stringWithString:bFile
if (bPath’s hasSuffix:“.m4a”) as boolean = false then
  set bPath to bPath’s appendString:“.m4a”
end if

–Export as MP4 audio
with timeout of 3600 seconds
  aMovie’s exportAACToFile:bPath
  
aMovie’s |close|()
end timeout

–Add Metadata
set aMetaData to current application’s ANMetadata’s alloc()’s init()
aMetaData’s setTitle:“戦場の絆ポータブル リプレイムービーNY音声編(1)”
aMetaData’s setAlbum:“戦場の絆ポータブル”
aMetaData’s setYear:“2015″
aMetaData’s setArtist:“Bandai Namco Entertainment”
aMetaData’s setTrackNumber:(current application’s ANMetadataTrack’s alloc()’s initWithTrackNumber:5 tracks:12)

set bMovie to current application’s ANMovie’s alloc()’s initWithFile:bPath
bMovie’s setMovieMetadata:aMetaData
bMovie’s |close|()

★Click Here to Open This Script 

2015/11/07 Systemのアラートサウンド名称を取得して鳴らす v2

Cocoaの機能を無理やり使って、Systemに入っている警告音の名称一覧を取得して鳴らすAppleScriptです。

Shane Stanleyから、「Script中で使っているgetFilePathListFromPOSIXpathの仕様だと、OS X 10.11では動くが10.10ではエラーになるよ」との指摘があり、書き換え例(v2)がナイスな内容だったので、少し試してみました(v2.1)。

NSArrayの中に入っている全要素を加工しつつ別のArrayに出力する(しかもループしない)という書き方はスマートなので、ぜひ覚えておきたいと思います。

AppleScript名:ASOCでSystemのアラートサウンド名称を取得して鳴らす v2
– Created 2015-11-06 by Takaaki Naganoya
– Modified 2015-11-07 by Shane Stanley–Recovery the compatibility for OS X 10.10.x
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set sList to getSystemAlertSoundNames() of me
–>  {”Basso.aiff”, “Blow.aiff”, “Bottle.aiff”, “Frog.aiff”, “Funk.aiff”, “Glass.aiff”, “Hero.aiff”, “Morse.aiff”, “Ping.aiff”, “Pop.aiff”, “Purr.aiff”, “Sosumi.aiff”, “Submarine.aiff”, “Tink.aiff”}

repeat with i in sList
  tell (current application’s NSSound’s soundNamed:i) to play()
  
delay 0.5 –時間待ちしないと全部一緒に鳴るので(Let’s Challenge!)
end repeat

–Get System Alert FileName List
on getSystemAlertSoundNames()
  set aExt to “aiff” – no dot
  
set aFol to “/System/Library/Sounds”
  
set fList to getFileNameListFromPOSIXpath(aFol, aExt) of me
  
return fList
end getSystemAlertSoundNames

–Get File Name List from POSIX path and file Extensions
on getFileNameListFromPOSIXpath(aFol, aExt)
  set aFM to current application’s NSFileManager’s defaultManager()
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aFol
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aURL 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’s valueForKey:“lastPathComponent”) as list –便利!!
end getFileNameListFromPOSIXpath

★Click Here to Open This Script 

AppleScript名:ASOCでSystemのアラートサウンド名称を取得して鳴らす v2.1
– Created 2015-11-06 by Takaaki Naganoya
– Modified 2015-11-07 by Shane Stanley–Recovery the compatibility for OS X 10.10.x
– Modified 2015-11-07 by Takaaki Naganoya–NSArrayからvalueForKeyで加工しつつ一気にArrayで値を返す内容を検証
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set sList to getSystemAlertSoundNames() of me
–>  {”Basso”, “Blow”, “Bottle”, “Frog”, “Funk”, “Glass”, “Hero”, “Morse”, “Ping”, “Pop”, “Purr”, “Sosumi”, “Submarine”, “Tink”}

repeat with i in sList
  tell (current application’s NSSound’s soundNamed:i) to play()
  
delay 0.5 –時間待ちしないと全部一緒に鳴るので(Let’s Challenge!)
end repeat

–Get System Alert FileName List
on getSystemAlertSoundNames()
  set aExt to “aiff” – no dot
  
set aFol to “/System/Library/Sounds”
  
set fList to getFileNameListFromPOSIXpath(aFol, aExt) of me
  
return fList
end getSystemAlertSoundNames

–Get File Name List from POSIX path and file Extensions
on getFileNameListFromPOSIXpath(aFol, aExt)
  set aFM to current application’s NSFileManager’s defaultManager()
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aFol
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aURL 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
  
set bArray to (anArray’s valueForKey:“lastPathComponent”) –便利!!
  
set cArray to (bArray’s valueForKey:“stringByDeletingPathExtension”) –便利!!
  
return cArray as list
end getFileNameListFromPOSIXpath

★Click Here to Open This Script 

AppleScript名:ASOCでSystemのアラートサウンド名称を取得して鳴らす v2.2
– Created 2015-11-06 by Takaaki Naganoya
– Modified 2015-11-07 by Shane Stanley–Recovery the compatibility for OS X 10.10.x
– Modified 2015-11-07 by Takaaki Naganoya–NSArrayからvalueForKeyで加工しつつ一気にArrayで値を返す内容を検証
– Modified 2015-11-07 by Shane Stanley–Cooler processing
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set sList to getSystemAlertSoundNames() of me
–>  {”Basso”, “Blow”, “Bottle”, “Frog”, “Funk”, “Glass”, “Hero”, “Morse”, “Ping”, “Pop”, “Purr”, “Sosumi”, “Submarine”, “Tink”}

repeat with i in sList
  tell (current application’s NSSound’s soundNamed:i) to play()
  
delay 0.5 –時間待ちしないと全部一緒に鳴るので(Let’s Challenge!)
end repeat

–Get System Alert FileName List
on getSystemAlertSoundNames()
  set aExt to “aiff” – no dot
  
set aFol to “/System/Library/Sounds”
  
set fList to getFileNameListFromPOSIXpath(aFol, aExt) of me
  
return fList
end getSystemAlertSoundNames

–Get File Name List from POSIX path and file Extensions
on getFileNameListFromPOSIXpath(aFol, aExt)
  set aFM to current application’s NSFileManager’s defaultManager()
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aFol
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aURL 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
  
set bArray to (anArray’s valueForKeyPath:“lastPathComponent.stringByDeletingPathExtension”) –Cool !!
  
return bArray as list
end getFileNameListFromPOSIXpath

★Click Here to Open This Script 

2015/11/06 Systemのアラートサウンド名称を取得して鳴らす

Cocoaの機能を無理やり使って、Systemに入っている警告音の名称一覧を取得して鳴らすAppleScriptです。

sounds.png

そういう「OSの警告音一覧を取得する」といったサービスがあるのかと思って探していたら、どうも存在していない雰囲気なので、Cocoaの機能を使ってものすごく常識的かつ地道に/System/Library/Soundsの中に入っているaiffファイルのファイル名の一覧を取得というところに落ち着きました。

AppleScript名:ASOCでSystemのアラートサウンド名称を取得して鳴らす
– Created 2015-11-06 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set sList to getSystemAlertSoundNames() of me
–>  {"Basso", "Blow", "Bottle", "Frog", "Funk", "Glass", "Hero", "Morse", "Ping", "Pop", "Purr", "Sosumi", "Submarine", "Tink"}

repeat with i in sList
  tell (current application’s NSSound’s soundNamed:i) to play()
  
delay 0.5 –時間待ちしないと全部一緒に鳴るので(Let’s Challenge!)
end repeat

on getSystemAlertSoundNames()
  set sList to getSystemAlertSoundPathList() of me
  
set nameList to {}
  
repeat with i in sList
    set j to contents of i
    
set aPOSIX to POSIX path of j
    
set pathString to (current application’s NSString’s stringWithString:aPOSIX)
    
set aFileName to pathString’s lastPathComponent()
    
set aFileName2 to aFileName’s stringByDeletingPathExtension()
    
set the end of nameList to (aFileName2 as text)
  end repeat
  
  return nameList
end getSystemAlertSoundNames

–Get System Alert Path List
on getSystemAlertSoundPathList()
  set aExt to "aiff" – no dot
  
set aFol to "/System/Library/Sounds"
  
set fList to getFilePathListFromPOSIXpath(aFol, aExt) of me
  
return fList
end getSystemAlertSoundPathList

–Get File List from POSIX path and file Extensions
on getFilePathListFromPOSIXpath(aFol, aExt)
  set aFM to current application’s NSFileManager’s defaultManager()
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aFol
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aURL 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
end getFilePathListFromPOSIXpath

★Click Here to Open This Script 

2015/11/05 FontCollectionの名称一覧を取得する

Cocoaの機能を用いて、FontCollectionの名称一覧を取得するAppleScriptです。

そもそも、FontCollectionとは何か・・・ということになりますが、それは、Font Panelの一番左の列の・・・

fontpanel1.png

fontpanel2.png

これです。もうちょっと違うものを期待していたのですが、実にこれだけです(^ー^;

AppleScript名:ASOCでFontCollectionの名称一覧を取得する
– Created 2015-11-05 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “AppKit”

current application’s NSFontCollection’s allFontCollectionNames() as list
–>  {”com.apple.AllFonts”, “com.apple.UserFonts”, “com.apple.Favorites”, “com.apple.Recents”, “Army Font”, “Classic”, “Handwriting”, “PDF”, “Web”, “Windows Office Compatible”, “エコフォント”, “デジタル時計フォント”, “バーコード”, “ヒラギノ”, “ファン”, “モダン”, “レタリング風フォント”, “韓国語”, “古代エジプト文字”, “固定幅”, “手書き風フォント”, “中国語”, “等幅”, “日本語”, “発音記号”, “毛筆書体”}

★Click Here to Open This Script 

2015/11/03 QuartzComposerを任意のパラメータで表示

QuartzComposerのCompositionを任意のパラメータでレンダリングして表示するAppleScriptです。

Appleのサンプルコードに、QuartzComposerでグラフ表示するもの(QuartzComposerChart)があり、ScriptとComposerの組み合わせについては以前から注目していました。

qcchart_resized.png

Xcode上のCocoa AppleScriptアプリケーションでは同様にCompositionを呼び出して表示できることは(未確認ながら)、可能と思っていましたが・・・Script Editor上のAppleScriptから呼び出して表示することは、自分の知り得るかぎり誰も実現していませんでした。

chart_as_resized.png
▲本ScriptからQuartzComposerのCompositionをパラメータ指定しつつ表示したところ。データにはとくに意味はありません

もともとのAppleのサンプルプロジェクト「QuartzComposerChart」の中身を分析してAppleScriptに置き換え、Compositionで作られたグラフのパラメータをいろいろいじくってみました。

comp1.png

params.png

Scriptのバンドル内に収めたQTZファイル(Composition)を参照しているため、QTZファイルを含んだAppleScriptバンドルを以下からダウンロードできるようにしておきました。興味のある方はお試しください(掲載リストから「★Click Here to Open This Script」をクリックしてScript Editorに転送しただけでは、グラフは表示されません)。

–> Download script bundle including Composition

AppleScript名:QuartzComoserでグラフ表示てすと
– Created 2015-11-03 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
use framework “AppKit”

set chartData to current application’s NSMutableArray’s alloc()’s init()
chartData’s addObject:(current application’s NSMutableDictionary’s dictionaryWithObjectsAndKeys_(“練馬区”, “label”, 3, “value”, missing value))
chartData’s addObject:(current application’s NSMutableDictionary’s dictionaryWithObjectsAndKeys_(“青梅市”, “label”, 1, “value”, missing value))
chartData’s addObject:(current application’s NSMutableDictionary’s dictionaryWithObjectsAndKeys_(“中野区”, “label”, 2, “value”, missing value))

try
  set aPath to path to resource “Chart.qtz”
on error
  return
end try

set qtPath to current application’s NSString’s stringWithString:(POSIX path of aPath)

set aView to current application’s QCView’s alloc()’s init()
set qtRes to (aView’s loadCompositionFromFile:qtPath)

aView’s setValue:chartData forInputKey:“Data”
aView’s setValue:(current application’s NSNumber’s numberWithFloat:(0.5)) forInputKey:“Scale”
aView’s setValue:(current application’s NSNumber’s numberWithFloat:(0.1)) forInputKey:“Spacing”
aView’s startRendering() –レンダリング開始

set maXFrameRate to aView’s maxRenderingFrameRate()

set aWin to (my makeWinWithView(aView, 800, 800, “Composition Test”))

repeat with i from 1 to 10
  (aView’s setValue:(current application’s NSNumber’s numberWithFloat:(i / 10)) forInputKey:“Scale”)
  
delay 0.1
end repeat

repeat with i from 10 to 1 by -1
  (aView’s setValue:(current application’s NSNumber’s numberWithFloat:(i / 10)) forInputKey:“Scale”)
  
delay 0.1
end repeat

my closeWin:aWin
aView’s stopRendering() –レンダリング停止

–make Window for Input
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
set aBacking to current application’s NSTitledWindowMask –NSBorderlessWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
– Window
  
set aWin to current application’s NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
aWin’s setBackgroundColor:(current application’s NSColor’s whiteColor())
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(current application’s NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s makeKeyAndOrderFront:(me)
  
  
– Set Custom View
  
aWin’s setContentView:aView
  
  
return aWin
  
end makeWinWithView

–close win
on closeWin:aWindow
  delay 5
  
repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

★Click Here to Open This Script 

2015/11/03 NSErrorを生成する

CocoaのNSErrorをフルに生成するAppleScriptです。

よく出くわすわりにmissing valueなどで代用してまともに取り合うケースの少なかったNSErrorについて、ドキュメントにもとづいてAppleScriptから生成してみました。

AppleScript名:ASOCでCocoaのNSErrorを生成する
– Created 2015-10-10 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set errorDomain to “jp.piyomarusoft.appname”
set errorCode to 12345

set errorUserInfo to current application’s NSDictionary’s dictionaryWithObjects:{“Error Description”, “Error Suggestion”} forKeys:{current application’s NSLocalizedDescriptionKey, current application’s NSLocalizedRecoverySuggestionErrorKey}

set aError to current application’s NSError’s alloc()’s initWithDomain:errorDomain code:errorCode userInfo:errorUserInfo
–>  (NSError) Error Domain=jp.piyomarusoft.appname Code=12345 “Error Description” UserInfo={NSLocalizedDescription=Error Description, NSLocalizedRecoverySuggestion=Error Suggestion}

★Click Here to Open This Script 

2015/11/03 Foundationのバージョンを取得する

Cocoaの機能を用いて、Foundationのバージョンを求めるAppleScriptです。

Cocoaの各種ドキュメントを調べていたところ、Foundationのバージョンに依存する処理に行き当たり、Foundationのバージョン番号を調べる方法を確認しておいたものです。

AppleScript名:Foundationのバージョンを取得する
– Created 2015-10-29 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"

set aVer to current application’s NSFoundationVersionNumber
–>  1256.1

★Click Here to Open This Script 

2015/11/03 Syslogにログ出力

CocoaでSyslogにログ出力するAppleScriptです。

Shane StanleyによるNSLogの使用例です。出力時のパラメータのフォーマット指定が可能な点がsyslogコマンドより便利です。

syslog.png

AppleScript名:ASOCでSyslogにログ出力
– Created 2015-10-21 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

repeat with i from 1 to 10
  current application’s NSLog(“Bah! I can log %.2d to the Console as float %.2f or hex %X, too”, i, i as real, i)
end repeat

★Click Here to Open This Script