| AppleScript名:Wikipediaの任意の項目の本文に入っているURLがリンク切れになっていないかどうかチェック v2 |
| — Created 2017-03-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" –https://www.mediawiki.org/wiki/API:Main_page/ja set aKeyword to "AppleScript" set aStr to getBody(aKeyword) of me –ものすごく大甘な転送検出 if aStr begins with "#転送" then set bStr to detectForwarding(aStr) of me –転送先のキーワードで再度処理 set aStr to getBody(bStr) of me end if set aRes to extractURLsAndValidateThem(aStr) of me –> {safeURL:27, forwardedURL:19, brokenURL:0, brokenURLs:{}} on detectForwarding(aStr) if aStr begins with "#転送" then set aRes to parseByDelim(aStr, {"[[", "]]"}) of me –> {"#転送 ", "MacOS", ""} return item 2 of aRes –エラーチェックはやっていない。大甘 else return aStr end if end detectForwarding on extractURLsAndValidateThem(aStr) set urlList to extractLinksFromNaturalText(aStr) of me as list set okList to {} set fwList to {} set ngList to {} repeat with i in urlList set j to contents of i set aTarg to j’s absoluteString() as string set {exRes, headerRes, aData, resURL} to checkURLResourceExistence(j, 30) of me if exRes = false then –URL取得時に連続するスペースをURLの一部として誤解して取得するケースがあるので、クリーニングしてリトライ set bStr to cleaningURLStr(aTarg) of me if bStr = false then –クリーニング対象文字列がなかった。本当にダメだった set the end of ngList to aTarg else –リトライ(タイムアウト条件も緩和) set bURL to (current application’s |NSURL|’s URLWithString:bStr) set {exRes, headerRes, aData, resURL} to checkURLResourceExistence(bURL, 60) of me if exRes = false then –やっぱりダメでした。ごめんなさい(T_T) set the end of ngList to bStr else if resURL is not equal to bStr then –URLがForwardされていた set the end of fwList to bStr else –OKだった(リクエストしたURLとリプライURLが同じ、そこに何かの同名のファイルが存在した) set the end of okList to bStr end if end if else if resURL is not equal to aTarg then –URLがForwardされていた set the end of fwList to aTarg else –OKだった(リクエストしたURLとリプライURLが同じ、そこに何かの同名のファイルが存在した) set the end of okList to aTarg end if end repeat set resList to {safeURL:length of okList, forwardedURL:length of fwList, brokenURL:length of ngList, brokenURLs:ngList} return resList end extractURLsAndValidateThem on cleaningURLStr(aStr) set anOffset to offset of "%20" in aStr if anOffset = 0 then return false set bStr to text 1 thru (anOffset – 1) of aStr return bStr end cleaningURLStr on getBody(aKeyword) –set reqURLStr to "https://en.wikipedia.org/w/api.php"–English Version set reqURLStr to "https://jp.wikipedia.org/w/api.php" –Japanese Version set aRec to {action:"query", titles:aKeyword, |prop|:"revisions", rvprop:"content", |format|:"json"} –set aRec to {action:"query", titles:"AppleScript|Mac OS X|Objective-C", |prop|:"revisions", rvprop:"content", |format|:"json"} set aURL to retURLwithParams(reqURLStr, aRec) of me set aRes to callRestGETAPIAndParseResults(aURL) of me set aRESTres to (json of aRes) –> {query:{pages:{2954:{pageid:2954, title:"AppleScript", revisions:{{contentformat:"text/x-wiki", *:"{{Infobox プログラミング言語|名前 = AppleScript ……., contentmodel:"wikitext"}}, ns:0}}}, batchcomplete:""} –最初にヒットしたものだけを返す(同じ名前の項目が複数存在した場合でも) set aRes to (aRESTres’s valueForKeyPath:"query.pages") set aKeyStr to (aRes’s allKeys()’s firstObject()) as string set aKeyPath to aKeyStr & ".revisions.*" set aBody to (aRes’s valueForKeyPath:aKeyPath)’s firstObject() as string return aBody end getBody –GET methodのREST APIを呼ぶ on callRestGETAPIAndParseResults(aURL) set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL) aRequest’s setHTTPMethod:"GET" aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData) aRequest’s setHTTPShouldHandleCookies:false aRequest’s setTimeoutInterval:60 aRequest’s setValue:"application/json" forHTTPHeaderField:"Accept" set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value) set resList to aRes as list set bRes to contents of (first item of resList) set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding) set jsonString to current application’s NSString’s stringWithString:resStr set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value) –Get Response Code & Header set dRes to contents of second item of resList if dRes is not equal to missing value then set resCode to (dRes’s statusCode()) as number set resHeaders to (dRes’s allHeaderFields()) as record else set resCode to 0 set resHeaders to {} end if return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders} end callRestGETAPIAndParseResults on retURLwithParams(aBaseURL, aRec) set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec set aKeyList to (aDic’s allKeys()) as list set aValList to (aDic’s allValues()) as list set aLen to length of aKeyList set qList to {} repeat with i from 1 to aLen set aName to contents of item i of aKeyList set aVal to contents of item i of aValList set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal) end repeat set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL aComp’s setQueryItems:qList set aURL to (aComp’s |URL|()’s absoluteString()) as text return aURL end retURLwithParams on urlencodeStr(aStr) set aString to current application’s NSString’s stringWithString:aStr set aString to (aString’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s URLQueryAllowedCharacterSet())) as text return aString end urlencodeStr — 指定URLにファイル(画像など)が存在するかチェック –> {存在確認結果(boolean), レスポンスヘッダー(NSDictionary), データ(NSData), 最終的なURLの文字列} on checkURLResourceExistence(aURL, timeOutSec as real) set aRequest to (current application’s NSURLRequest’s requestWithURL:aURL cachePolicy:(current application’s NSURLRequestUseProtocolCachePolicy) timeoutInterval:timeOutSec) set aRes to (current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)) set dRes to (first item of (aRes as list)) set bRes to (second item of (aRes as list)) if bRes = missing value then set hRes to {} set aResCode to -1 –error return {false, hRes, dRes, missing value} else set resURL to ((|URL| of bRes)’s |absoluteURL|()’s absoluteString()) as string end if –set resURL to ((|URL| of bRes)’s |absoluteURL|()’s absoluteString()) as string if bRes is not equal to missing value then set hRes to (bRes’s allHeaderFields()) set aResCode to (bRes’s statusCode()) as integer else set hRes to {} set aResCode to -1 –error end if return {(aResCode = 200), hRes, dRes, resURL} end checkURLResourceExistence on extractLinksFromNaturalText(aString) set anNSString to current application’s NSString’s stringWithString:aString set {theDetector, theError} to current application’s NSDataDetector’s dataDetectorWithTypes:(current application’s NSTextCheckingTypeLink) |error|:(reference) set theMatches to theDetector’s matchesInString:anNSString options:0 range:{0, anNSString’s |length|()} set theResults to theMatches’s valueForKey:"URL" return theResults as list end extractLinksFromNaturalText on parseByDelim(aData, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set dList to text items of aData set AppleScript’s text item delimiters to curDelim return dList end parseByDelim |
投稿者: Takaaki Naganoya
配列に添字的なデータを指定してアクセス
AppleScriptのリスト(list)型変数に対して、一般的な配列の添字的なパラメータを指定して値の設定や取得を行うAppleScriptです。
一般的なプログラミング言語には必ず存在する配列変数、AppleScriptにも当然存在しており、リスト型(list)変数と呼ばれています。
一般的な配列変数と異なる点は3点ほど。
・配列要素が1からはじまる(item 0はない)
・配列要素への間接アクセスは可能なものの、item x of aListのように一般的な配列添字とは異なる記述を行う
・配列要素として各種GUIアプリケーションのオブジェクトやScriptオブジェクトを突っ込める
といったところでしょうか。あとは、条件抽出とかソートなどの機能は備わっていないので、昨今ではCocoaの機能を呼び出してNSArrayに変換してからこのような処理を行なっています(要素数が少ない(1万以下)場合には、AppleScriptだけでループ処理で条件抽出したほうが速い)。
ないものをない、と嘆くだけならアホでもできるので、配列添字的なアクセスがしたいのなら作ってしまえばいいじゃないか、ということで作ったのがこれです。
「Safariで現在見えている表を抽出してCSV書き出しv3」などの処理に使っています。多分、この処理は本ルーチンが存在していたからできたものです。
| AppleScript名:配列に添字的なデータを指定してアクセス |
| — Created 2017-09-30 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aList to make2DBlankArray(3, 4) of me set aList to setItemByXY(2, 3, aList, "@") of me set aRes to getItemByXY(2, 3, aList, "") of me return aList –> {{"", "", ""}, {"", "", ""}, {"", "@", ""}, {"", "", ""}} on getItemByXY(aX, aY, aList, aBlankItem) try set aContents to contents of (item aX of item aY of aList) on error set aContents to aBlankItem end try return aContents end getItemByXY on setItemByXY(aX, aY, aList, aContents) set (item aX of item aY of aList) to aContents return aList end setItemByXY –空白の2D Array を出力する on make2DBlankArray(curLen, curMax) set outArray to {} repeat curMax times set aList to {} repeat curLen times set the end of aList to "" end repeat set the end of outArray to aList end repeat return outArray end make2DBlankArray |
配列の複数の要素を取得する
配列変数の要素を範囲指定して取得するAppleScriptです。
AppleScriptネイティブの配列変数であるリスト型変数であれば、
set aList to {1,2,3,4,5}
set bList to item 3 thru -1 of aList
--> {3, 4, 5}
のように1はじまりのインデックスを範囲指定して取得することになります。ここで紹介するのはCocoaのオブジェクトであるNSArrayから(0はじまりのインデックスで)範囲指定して要素を取り出す書き方です。
| AppleScript名:配列の複数の要素を取得する |
| — Created 2015-09-02 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set anArray to current application’s NSArray’s arrayWithArray:{1, 2, 3} –> (NSArray) {1, 2, 3} –複数の要素を取得する set anInd to current application’s NSIndexSet’s indexSetWithIndexesInRange:(current application’s NSMakeRange(1, 2)) –> (NSIndexSet) <NSIndexSet: 0x600000431140>[number of indexes: 2 (in 1 ranges), indexes: (1-2)] set aRes to (anArray’s objectsAtIndexes:anInd) as list of string or string –> {2, 3} |
配列の要素を順番に取得する
Cocoaの機能を用いて配列(NSArray)の要素を順番に取得するAppleScriptです。
Objective-CなどではEnumeratorを用いると配列からの順次要素取り出しの速度が上がるようですが、AppleScriptではEnumeratorを用いてもループ速度が上がったりしません。AppleScriptの普通のループを行ったほうが高速です。
どうしてもEnumeratorを使わなくてはならない場面にだけ、仕方なく使う感じでしょうか。
| AppleScript名:配列の要素を順番に取得する |
| — Created 2015-09-02 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set anArray to current application’s NSArray’s arrayWithArray:{1, 2, 3} –> (NSArray) {1, 2, 3} –要素を順番に取得する set anEnum to anArray’s objectEnumerator() –> (__NSFastEnumerationEnumerator) <__NSFastEnumerationEnumerator: 0x6000002c1180> repeat set aValue to anEnum’s nextObject() if aValue = missing value then exit repeat log aValue as list of string or string end repeat |
配列の要素を逆順に取得する
| AppleScript名:配列の要素を逆順に取得する |
| — Created 2015-09-02 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set anArray to current application’s NSArray’s arrayWithArray:{1, 2, 3} –> (NSArray) {1, 2, 3} –要素を逆順に取得する set revEnum to anArray’s reverseObjectEnumerator() –> (__NSArrayReverseEnumerator) <__NSArrayReverseEnumerator: 0x610000a3c600> repeat set aValue to revEnum’s nextObject() if aValue = missing value then exit repeat log aValue as list of string or string end repeat |
数値リストで指定数よりも大きな要素のみを抽出
| AppleScript名:数値リストで指定数よりも大きな要素のみを抽出 |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aList to {8, 2, 7, 3, 9, 1, 6, 4} set theArray to current application’s NSArray’s arrayWithArray:aList set thePred to current application’s NSPredicate’s predicateWithFormat:"self >= 4" set bList to (theArray’s filteredArrayUsingPredicate:thePred) as list –> {8, 7, 9, 6, 4} set thePred to current application’s NSPredicate’s predicateWithFormat:"self > 4" set cList to (theArray’s filteredArrayUsingPredicate:thePred) as list –> {8, 7, 9, 6} |
指定数ではない要素のみを抽出
| AppleScript名:指定数ではない要素のみを抽出 |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set theArray to current application’s NSArray’s arrayWithArray:{8, 2, 7, 3, 9, 1, 6, 4} set thePred to current application’s NSPredicate’s predicateWithFormat:"(self != 2) AND (self != 4)" set bList to (theArray’s filteredArrayUsingPredicate:thePred) as list –> {8, 7, 3, 9, 1, 6} |
指定文字列ではじまる要素のみ抽出
| AppleScript名:指定文字列ではじまる要素のみ抽出 |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "Apple", "microsoft", "google"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self BEGINSWITH ’a’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"adobe"} |
指定文字列ではじまる要素のみ抽出(大文字、小文字を問わず)
| AppleScript名:指定文字列ではじまる要素のみ抽出(大文字、小文字を問わず) |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "Apple", "microsoft", "google"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self BEGINSWITH[cd] ’A’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"adobe", "Apple"} |
指定文字列ではじまる要素のみ抽出(ワイルドカード使用)
1Dリスト(1次元配列)に入っているデータを、Cocoaのオブジェクトに変換してワイルドカードで指定要素を抽出するAppleScriptです。
割と短く書けるので、幅広く使いたくなるところですが……処理速度がそれほど速くありません。これだと、AppleScriptのリスト(配列)型変数をループで条件判定して抽出したほうが速く処理できそうです。
データ件数が増えた場合にはAppleScriptネイティブの配列とCocoaの配列(NSArray)で速度比較して、Cocoaのオブジェクトを使って高速になる条件はどこかにあると思われますが、少なくとも要素数が5個ぐらいの「おかわいらしい」サイズの配列変数だとAppleScriptネイティブのオブジェクトを使って地道にループで判定したほうが高速です。
| AppleScript名:指定文字列ではじまる要素のみ抽出(ワイルドカード使用) |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "Apple", "microsoft", "google"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self LIKE ’Ap*’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"Apple"} |
| AppleScript名:指定文字列ではじまる要素のみ抽出(ワイルドカード使用、レコード) |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aRecList to {{aName:"adobe", anID:1}, {aName:"Apple", anID:2}, {aName:"microsoft", anID:3}, {aName:"google", anID:4}} set stringArray to current application’s NSArray’s arrayWithArray:aRecList set thePred to current application’s NSPredicate’s predicateWithFormat:"aName LIKE ’Ap*’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {{aName:"Apple", anID:2}} |
指定リストから、Regexpで要素を抽出
| AppleScript名:指定リストから、Regexpで要素を抽出 |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "22", "microsoft", "99"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self MATCHES ’\\\\d\\\\d’" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"22", "99"} |
指定リストから、文字数で要素を抽出
| AppleScript名:指定リストから、文字数で要素を抽出 |
| — Created 2017-10-29 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set stringArray to current application’s NSArray’s arrayWithArray:{"adobe", "22", "microsoft", "99"} set thePred to current application’s NSPredicate’s predicateWithFormat:"self.length > 5" set bList to (stringArray’s filteredArrayUsingPredicate:thePred) as list –> {"microsoft"} |
配列を逆順に(OLD Style AS)
AppleScriptネイティブの配列変数であるlist型変数を逆順にするAppleScriptです。
配列(list)の要素数が5,000以下ぐらいだと普通に変数に保持して、このように逆順に変換して配列に代入するのが一番速いでしょう。
配列(list)の要素数が5,000以上ぐらいだとscriptオブジェクト内に格納したpropertyに保持して、このように逆順に変換してpropertyに代入するのが一番速いでしょう。
Cocoaの配列変数(NSArray、NSMutableArray)に格納して速度面での優位性が生まれてくるのは、要素数が1万とか数十万アイテムぐらいになった場合です。
Cocoa Scriptingで予想外にパフォーマンスが出ないケースというのは、たいてい配列処理で件数が少なすぎて逆効果だったという場合が多いので、ネイティブのAppleScriptのlist型変数の各種処理も重要です。
| AppleScript名:配列を逆順に(OLD Style AS) |
| — Created 2017-07-30 by Takaaki Naganoya — 2017 Piyomaru Software set aList to {1, 2, 3, 4, 5, 6} set revArray to reverse of aList –> {6, 5, 4, 3, 2, 1} |
複数キーによるソートテスト3.1(OLD Style AppleScript)
OLD Style AppleScriptによる2D Listの複数キーによるソートを行うAppleScriptです。

以前掲載したソートルーチンの速度比較で、2D ArrayのソートでOLD Style AppleScript版はSingle Keyのルーチンでしたが、本来であればこのMulti-Keyのルーチンで比較を行うべきでした。
ASOC版はMulti-Keyのソートルーチンなので、2.0 vs 0.3 secondsというところ。
| AppleScript名:複数キーによるソートテスト3.1 |
| –複数キーによるソートテスト3(複数キーを許容。キー数無制限) script orig property aList : {} end script –テストデータ作成 set aList of orig to {} repeat 10000 times –3次まですべてのキーを使ったソートが発生するよう、1次、2次キーは乱数範囲をわざと狭くしてある set the end of aList of orig to {"a", random number from 1 to 10, random number from 1 to 10, random number from 1 to 100} end repeat set sDat to current date –ソート時間計測(開始時刻) –item 2をPrimary key、item 3とitem 4をサブキーにして降順ソート set resList to multiKeySortDescending(aList of orig, {2, 3, 4}) of multiKeySort set eDat to current date –ソート時間計測(終了時刻) return (eDat – sDat) –複数キーによるソート script multiKeySort script spd property bList : {} –1次キーでソートした結果が入る property cList : {} –1次キーでソートした結果のうち、1次キーで同じ値が連続する範囲が入る {{1,3},{10,20}} property dList : {} –2次キーで再ソートする対象の一部のリストが入る(ワーク用) property eList : {} –2次キーで再ソートした結果のリストが入る(ワーク用) end script –複数キー(Primary, Secondary……)による降順ソート。キーは指定用のリストに入れる –falseが返ってきたらエラー on multiKeySortDescending(aList, keyList) –Initialize –set aList of spd to {} set bList of spd to {} –■■■■ ここからパラメータのチェック ■■■■ –型チェック set aLen to length of keyList if class of keyList is not equal to list then return false –キー値のリストがlistではなかった場合error end if –ソート対象の2D Listの要素数を取得 set tmpLen to length of first item of aList repeat with i in keyList if i > tmpLen then return false –キー値として指定した内容が、ソート対象のリストの要素数よりも大きかった場合error end if end repeat –キー指定内容で重複がないかチェック set dupList to detectDuplicates(keyList) of me if dupList is not equal to {} then return false –指定したキーで重複があったらerror end if –キー指定内容に0が入っていないかチェック if 0 is in keyList then return false –■■■■ パラメータのチェックここまで ■■■■ set firstKeyNo to first item of keyList –1次キーで2D Listをソート(降順) set bList of spd to shellSortListDescending(aList, firstKeyNo) of me –複数キーによるソート検証および実行ループ repeat with iii from 1 to aLen – 1 set cList of spd to {} set dList of spd to {} set eList of spd to {} –n次キーの値が連続する箇所を探す set curData to missing value set sucF to false –データ連続箇所検出中フラグ(false=非連続、true=連続中) set biginItem to 0 set endItem to 0 set itemC to 0 repeat with i in bList of spd set thisData to item (item iii of keyList) of i –n次キー –現在の値と前の値が等しい(連続箇所を検出した、あるいは連続箇所の中にいる) if curData = thisData then if sucF = false then set biginItem to itemC set sucF to true else if sucF = true then –連続箇所の検索継続中、何もしない end if else –現在の値と前の値が等しくない(連続していない、あるいは連続箇所の末尾を検出した) if sucF = true then set the end of cList of spd to {biginItem, itemC} set sucF to false end if set curData to thisData end if set itemC to itemC + 1 end repeat –n次キーの連続状態の検出中のままリスト末尾に来た場合には、最終データを出力する if sucF = true and curData = thisData then set the end of cList of spd to {biginItem, itemC} end if –n次キーによる重複箇所がない場合には、n次キーによるソート結果をそのまま返す if cList of spd = {} then return bList of spd end if –n+1次キーによる部分ソートし直し repeat with i in cList of spd set {tmpB, tmpE} to i copy items tmpB thru tmpE of (bList of spd) to (dList of spd) set (eList of spd) to shellSortListDescending((dList of spd), (item (iii + 1) of keyList)) of me set tmpCounter to 1 repeat with ii from tmpB to tmpE copy item tmpCounter of (eList of spd) to item ii of (bList of spd) set tmpCounter to tmpCounter + 1 end repeat end repeat end repeat return (bList of spd) end multiKeySortDescending –リスト中から重複項目をリストアップする on detectDuplicates(aList) set aCount to length of aList set duplicationList to {} repeat aCount times set anItem to contents of (first item of aList) set aList to rest of aList if anItem is in aList then set the end of duplicationList to anItem end if end repeat return duplicationList end detectDuplicates –シェルソートで入れ子のリストを降順ソート on shellSortListDescending(aSortList, aKeyItem) script oBj property list : aSortList end script set len to count oBj’s list’s items set gap to 1 repeat while (gap ≤ len) set gap to ((gap * 3) + 1) end repeat repeat while (gap > 0) set gap to (gap div 3) if (gap < len) then repeat with i from gap to (len – 1) set temp to oBj’s list’s item (i + 1) set j to i repeat while ((j ≥ gap) and (contents of item aKeyItem of (oBj’s list’s item (j – gap + 1)) < item aKeyItem of temp)) set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1) set j to j – gap end repeat set oBj’s list’s item (j + 1) to temp end repeat end if end repeat return oBj’s list end shellSortListDescending end script |
NSPoint(座標)を作成する
| AppleScript名:NSPoint(座標)を作成する |
| — Created 2017-06-22 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aPoint to current application’s NSMakePoint(100, 100) –> {x:100.0, y:100.0} |
Crayon Pickerの色をKeynote上に赤、青、その他で判定して表にする
「クレヨンピッカー」の色を赤、青、その他で判定してKeynoteの表にプロットするAppleScriptです。


| AppleScript名:Crayon Pickerの色をKeynote上に赤、青、その他で判定して表にする |
| — Created 2018-02-27 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSColor : a reference to current application’s NSColor –Crayon Picker Color Data set crayonPickerList to {{0, 0, 0}, {6425, 6425, 6425}, {13107, 13107, 13107}, {19532, 19532, 19532}, {26214, 26214, 26214}, {32639, 32639, 32639}, {32896, 32896, 32896}, {39321, 39321, 39321}, {46003, 46003, 46003}, {52428, 52428, 52428}, {59110, 59110, 59110}, {65535, 65535, 65535}, ¬ {32896, 0, 0}, {32896, 16448, 0}, {32896, 32896, 0}, {16448, 32896, 0}, {0, 32896, 0}, {0, 32896, 16448}, {0, 32896, 32896}, {0, 16448, 32896}, {0, 0, 32896}, {16448, 0, 32896}, {32896, 0, 32896}, {32896, 0, 16448}, ¬ {65535, 0, 0}, {65535, 32896, 0}, {65535, 65535, 0}, {32896, 65535, 0}, {0, 65535, 0}, {0, 65535, 32896}, {0, 65535, 65535}, {0, 32896, 65535}, {0, 0, 65535}, {32896, 0, 65535}, {65535, 0, 65535}, {65535, 0, 32896}, ¬ {65535, 26214, 26214}, {65535, 52428, 26214}, {65535, 65535, 26214}, {52428, 65535, 26214}, {26214, 65535, 26214}, {26214, 65535, 52428}, {26214, 65535, 65535}, {26214, 52428, 65535}, {26214, 26214, 65535}, {52428, 26214, 65535}, {65535, 26214, 65535}, {65535, 28527, 53199} ¬ } tell application "Keynote" activate set newDoc to make new document with properties {document theme:theme "ホワイト"} — theme name is *Localized*. This is "White" in Japanese tell window 1 –set {x1, y1, x2, y2} to bounds set bounds to {0, 0, 1500, 900} end tell tell newDoc set blankSlide to master slide "空白" –master slide name is *Localized*. This is "Blank" in Japanese tell slide 1 set base slide to blankSlide delete every table set tRes to make new table tell tRes set row count to 12 set column count to 8 set background color of every cell to {65535, 65535, 65535} set header column count to 0 set header row count to 0 set footer row count to 0 repeat with i from 0 to (length of crayonPickerList) – 1 set a1Num to (i mod 12) + 1 set b1Num to ((i div 12) + 1) * 2 – 1 set b2Num to b1Num + 1 set aCol to contents of item (i + 1) of crayonPickerList tell column b1Num tell cell a1Num ignoring application responses set background color to aCol end ignoring end tell end tell —————————————————————————————————– copy aCol to {rCol, gCol, bCol} set aColor to makeNSColorFromRGBAval(rCol, gCol, bCol, 65535, 65535) of me set cdnStr to retColorIsRedOrBlueFromNSColor(aColor) of me –red, blue, other —————————————————————————————————– if cdnStr = "red" then set textCol to {65535, 0, 0} else if cdnStr = "blue" then set textCol to {0, 0, 65535} else set textCol to {0, 0, 0} end if tell column b2Num tell cell a1Num ignoring application responses set value to cdnStr set text color to textCol end ignoring end tell end tell end repeat end tell end tell end tell end tell on retColorIsRedOrBlueFromNSColor(aColor) set aColDomain to retColorDomainNameFromNSColor(aColor) of me if aColDomain is in {"magenta", "purple", "orange", "red"} then return "red" else if aColDomain is in {"green", "cyan", "blue"} then return "blue" else return "other" end if end retColorIsRedOrBlueFromNSColor on retColorDomainNameFromNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 set colName to "" if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "cyan" else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "magenta" end if end if return colName end retColorDomainNameFromNSColor on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval |
色が赤系統か青系統かを判定する
指定の色が赤系統か青系統かその他かを判定するAppleScriptです。
パラメータをRTFから取得するプログラムで、テキストを青、データベースから取得して差し込む値を赤、コメント類を黒などで記述するようにしてみたため、赤/青/その他を判定するプログラムを作成してみました。

| AppleScript名:色が赤系統か青系統かを判定する |
| — Created 2018-02-27 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSColor : a reference to current application’s NSColor set {rCol, gCol, bCol} to choose color set aColor to makeNSColorFromRGBAval(rCol, gCol, bCol, 65535, 65535) of me –Detect the color is red or blue (or other) set cdnStr to retColorIsRedOrBlueFromNSColor(aColor) of me –> "red" / "blue" / "ohter" on retColorIsRedOrBlueFromNSColor(aColor) set aColDomain to retColorDomainNameFromNSColor(aColor) of me if aColDomain is in {"magenta", "purple", "orange", "red"} then return "red" else if aColDomain is in {"green", "cyan", "blue"} then return "blue" else return "other" end if end retColorIsRedOrBlueFromNSColor on retColorDomainNameFromNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 set colName to "" if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "cyan" else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "magenta" end if end if return colName end retColorDomainNameFromNSColor on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval |
Terminalで指定コマンドのman pageを表示する
Terminal.appで指定コマンドのman pageを表示するAppleScriptです。
Terminal.appには
{appName:”Terminal”, appBundleID:”com.apple.Terminal”, urlScheme:{“telnet”, “ssh”, “x-man-page”}}
と、いろいろURL Schemeが定義されており、そのうちの1つ、x-man-pageのURL Shcemeを利用して表示させてみました。

| AppleScript名:Terminalで指定コマンドのman pageを表示する |
| set aCommandName to "ps" set aURL to "x-man-page://" & aCommandName open location aURL |
Finderの最前面のWindowで表示中のフォルダをTerminalでオープン
Finderの最前面のWindowで表示中のフォルダをTerminalでオープンするAppleScriptです。
| AppleScript名:Finderの最前面のWindowで表示中のフォルダをTerminalでオープン |
| tell application "Finder" set wCount to count every window if wCount = 0 then return tell front window set aTarg to target as alias end tell end tell set targPOSIX to quoted form of (POSIX path of aTarg) set aCom to "cd " & targPOSIX tell application "Terminal" set tCount to count (every window whose visible is true) if tCount = 0 then do script aCom else do script aCom in front window end if end tell |
ANSI Colorの色名称でTerminalの文字色を変更
ANSI Colorの名称一覧から名前をえらんで、Terminalの文字色を変更するAppleScriptです。
これにどの程度の意味があるのかさっぱり分からないのですが、ANSI Colorで文字色を指定する趣味の人もいるということで、世界の広さを感じます。

▲Select ANSI color name

▲Before

▲After
| AppleScript名:ANSI Colorの色名称でTerminalの文字色を変更 |
| — Created 2018-02-06 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" –Dark –set ansiColTable to {{colName:"Black", colVal:{0, 0, 0}}, {colName:"Red", colVal:{34166, 0, 712}}, {colName:"Green", colVal:{5182, 39392, 620}}, {colName:"Yellow", colVal:{34811, 35431, 1086}}, {colName:"Blue", colVal:{0, 0, 39429}}, {colName:"White", colVal:{49207, 49511, 49827}}, {colName:"Magenta", colVal:{41397, 0, 41833}}, {colName:"Cyan", colVal:{4997, 38685, 41818}}} –Light set ansiColTable to {{colName:"Black", colVal:{21352, 21356, 21351}}, {colName:"Red", colVal:{56616, 0, 1392}}, {colName:"Green", colVal:{7241, 55116, 1162}}, {colName:"Yellow", colVal:{57396, 58567, 2377}}, {colName:"Blue", colVal:{0, 0, 65416}}, {colName:"White", colVal:{49207, 49511, 49827}}, {colName:"Magenta", colVal:{56440, 0, 57441}}, {colName:"Cyan", colVal:{7416, 58001, 57206}}} set tmpColorList to filterAnAttribute(ansiColTable, "colName") of me set aTargColor to choose from list tmpColorList with prompt "choose ANSI color name" if aTargColor = {} or aTargColor = false then return set targColorName to contents of first item of aTargColor set aRes to filterListUsingPredicate(ansiColTable, "colName ==[c] %@", targColorName) if aRes = missing value then return set colList to colVal of aRes tell application "Terminal" set normal text color of window 1 to colList –set background color of window 1 to colList end tell on filterListUsingPredicate(aList as list, aPredicateStr as string, targStr as string) set setKey to current application’s NSMutableSet’s setWithArray:aList set aPredicate to current application’s NSPredicate’s predicateWithFormat_(aPredicateStr, targStr) set aRes to (setKey’s filteredSetUsingPredicate:aPredicate) return (aRes’s allObjects()) as list of string or string end filterListUsingPredicate on filterAnAttribute(aList as list, anAttr as string) set anArray to current application’s NSArray’s arrayWithArray:aList set valList to anArray’s valueForKeyPath:anAttr return valList as list of string or string –as anything end filterAnAttribute |

