オンラインマガジンApp Engineer Journal “猛者”(モサ)に「Appleに関するウワサ話を実際に検証(上)」「Appleに関するウワサ話を実際に検証(下)」を寄稿しました。
現在のスライド上のshapeオブジェクトのうち一番上のものに他のものの幅をそろえる
Keynoteの現在のスライド上のshapeオブジェクトのうち、一番上のものに他のものの幅をそろえるAppleScriptです。


いっそ、Shapeオブジェクトのboundsをすべて取得して、横長か縦長かを計算し、自動で基準オブジェクトを上にするか左のものにするかを判定してもよいのですが、少しやりすぎな感じもするので、現状のままにしてあります。
| AppleScript名:現在のスライド上のshapeオブジェクトのうち一番上のものに他のものの幅をそろえる |
| — Created 2018-05-25 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html tell application "Keynote" tell front document tell (current slide) — すべてのshapeオブジェクトの座標{x,y}を返す set pList to position of every shape — shapeオブジェクトの全座標を昇順ソートして最もX座標値が小さいものを返す set mostLeftPos to first item of sort2DList(pList) of me — 一番X座標値が小さい(=左にある)オブジェクトを特定 set mostLeftObj to first item of (every shape whose position is equal to mostLeftPos) set mostLeftProp to properties of mostLeftObj –> (*class:shape, opacity:100, parent:slide 5 of document id 253165F1-0596-4E72-B9E3-2AB6D6084125, reflection showing:false, background fill type:color fill, position:32, 160, object text:, width:56, rotation:0, reflection value:0, height:467, locked:false*) set mostLeftHeight to height of mostLeftProp set mostLeftWidth to width of mostLeftProp — 「一番左」以外のshapeオブジェクトへの参照を取得して一気にオブジェクトのwidthをそろえる set otherShape to a reference to (every shape whose position is not equal to mostLeftPos) set width of otherShape to mostLeftWidth end tell end tell end tell on sort2DList(aList) load framework set sortIndexes to {1} –Key Item id: begin from 0 set sortOrders to {true} –ascending = true set sortTypes to {"compare:"} set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list return resList end sort2DList |
Finderで選択中のPDFを古い順に連結する v2
Finder上で選択中のファイルのうちPDFだけを作成日付で古い順に連結するAppleScriptです。

間違ってPDF以外のファイルを選択してしまった場合でも、それについては無視します。
こんな風にmacOS標準装備のScript Menuに入れて利用しています。

| AppleScript名:Finderで選択中のPDFを古い順に連結する v2 |
| — Created 2018-05-26 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSPredicate : a reference to current application’s NSPredicate property NSFileManager : a reference to current application’s NSFileManager property NSURLPathKey : a reference to current application’s NSURLPathKey property NSMutableArray : a reference to current application’s NSMutableArray property NSSortDescriptor : a reference to current application’s NSSortDescriptor property NSURLIsPackageKey : a reference to current application’s NSURLIsPackageKey property NSURLIsDirectoryKey : a reference to current application’s NSURLIsDirectoryKey property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey property NSURLContentModificationDateKey : a reference to current application’s NSURLContentModificationDateKey property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles –set inFiles to (choose file of type {"pdf"} with prompt "Choose your PDF files:" with multiple selections allowed) tell application "Finder" set inFiles to selection as alias list end tell if inFiles = {} then return –指定のAlias listのうちPDFのみ抽出 set filRes1 to filterAliasListByUTI(inFiles, "com.adobe.pdf") of me –選択中のファイルのうちの1つから親フォルダを求め、出力先ファイルパスを組み立てる set outPathTarg to POSIX path of (first item of filRes1) set pathString to current application’s NSString’s stringWithString:outPathTarg set newPath to (pathString’s stringByDeletingLastPathComponent()) as string set destPosixPath to newPath & "/" & ((current application’s NSUUID’s UUID()’s UUIDString()) as string) & ".pdf" combinePDFsAndSaveIt(filRes1, destPosixPath) of me on combinePDFsAndSaveIt(inFiles, destPosixPath) set inFilesSorted to my filesInListSortFromOldToNew(inFiles) — make URL of the first PDF set inNSURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of item 1 of inFilesSorted) set theDoc to current application’s PDFDocument’s alloc()’s initWithURL:inNSURL — loop through the rest set oldDocCount to theDoc’s pageCount() set inFilesSorted to rest of inFilesSorted repeat with aFile in inFilesSorted set inNSURL to (current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFile)) set newDoc to (current application’s PDFDocument’s alloc()’s initWithURL:inNSURL) set newDocCount to newDoc’s pageCount() repeat with i from 1 to newDocCount set thePDFPage to (newDoc’s pageAtIndex:(i – 1)) — zero-based indexes (theDoc’s insertPage:thePDFPage atIndex:oldDocCount) set oldDocCount to oldDocCount + 1 end repeat end repeat set outNSURL to current application’s |NSURL|’s fileURLWithPath:destPosixPath (theDoc’s writeToURL:outNSURL) end combinePDFsAndSaveIt on filesInListSortFromOldToNew(aliasList) set keysToRequest to {NSURLPathKey, NSURLIsPackageKey, NSURLIsDirectoryKey, NSURLContentModificationDateKey} set valuesNSArray to NSMutableArray’s array() repeat with i in aliasList set oneNSURL to (|NSURL|’s fileURLWithPath:(POSIX path of i)) (valuesNSArray’s addObject:(oneNSURL’s resourceValuesForKeys:keysToRequest |error|:(missing value))) end repeat set theNSPredicate to NSPredicate’s predicateWithFormat_("%K == NO OR %K == YES", NSURLIsDirectoryKey, NSURLIsPackageKey) set valuesNSArray to valuesNSArray’s filteredArrayUsingPredicate:theNSPredicate set theDescriptor to NSSortDescriptor’s sortDescriptorWithKey:(NSURLContentModificationDateKey) ascending:true set theSortedNSArray to valuesNSArray’s sortedArrayUsingDescriptors:{theDescriptor} — extract just the paths and convert to an AppleScript list return (theSortedNSArray’s valueForKey:(NSURLPathKey)) as list end filesInListSortFromOldToNew –Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す on filterAliasListByUTI(aList, targUTI) set newList to {} repeat with i in aList set j to POSIX path of i set tmpUTI to my retUTIfromPath(j) set utiRes to my filterUTIList({tmpUTI}, targUTI) if utiRes is not equal to {} then set the end of newList to j end if end repeat return newList end filterAliasListByUTI –指定のPOSIX pathのファイルのUTIを求める on retUTIfromPath(aPOSIXPath) set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value) if theResult = true then return theValue as string else return theResult end if end retUTIfromPath –UTIリストが指定UTIに含まれているかどうか演算を行う on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
Finderで選択中のファイルのうち、指定UTIに含まれるものを返す
Finder上で選択中のファイルのうち、指定UTIに含まれるもの(下位階層のUTIも含む)を返すAppleScriptです。

Finderでfileのkindを指定してフィルタ参照でしぼりこむ方法もありますが、ファイル数が増えると処理速度が大幅に低下するのと、UTIで指定できたほうが便利なので作っておきました。
| AppleScript名:Finderで選択中のファイルのうち、指定UTIに含まれるものを返す |
| — Created 2018-05-26 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey property |NSURL| : a reference to current application’s |NSURL| property NSPredicate : a reference to current application’s NSPredicate property NSArray : a reference to current application’s NSArray tell application "Finder" set aSel to selection as alias list end tell if aSel = {} then its return set filRes1 to filterAliasListByUTI(aSel, "com.adobe.pdf") of me –> {"/Users/me/Pictures/annotation_origin.pdf"} set filRes2 to filterAliasListByUTI(aSel, "public.image") of me –> {"/Users/me/Pictures/スクリーンショット 2017-11-06 20.05.30.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.35.08.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.33.53.png", "/Users/me/Pictures/スクリーンショット 2017-09-26 16.46.29.png"} set filRes3 to filterAliasListByUTI(aSel, "public.item") of me –> {"/Users/me/Pictures/スクリーンショット 2017-11-06 20.05.30.png", "/Users/me/Pictures/annotation_origin.pdf", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.35.08.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.33.53.png", "/Users/me/Pictures/スクリーンショット 2017-09-26 16.46.29.png"} –Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す on filterAliasListByUTI(aList, targUTI) set newList to {} repeat with i in aList set j to POSIX path of i set tmpUTI to my retUTIfromPath(j) set utiRes to my filterUTIList({tmpUTI}, targUTI) if utiRes is not equal to {} then set the end of newList to j end if end repeat return newList end filterAliasListByUTI –指定のPOSIX pathのファイルのUTIを求める on retUTIfromPath(aPOSIXPath) set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value) if theResult = true then return theValue as string else return theResult end if end retUTIfromPath –UTIリストが指定UTIに含まれているかどうか演算を行う on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
現在のスライド上のshapeオブジェクトのうち一番左のものに他のものの高さをそろえる
Keynoteの現在のスライド上のshapeオブジェクトのうち、一番左のものに他のものの高さをそろえるAppleScriptです。


| AppleScript名:現在のスライド上のshapeオブジェクトのうち一番左のものに他のものの高さをそろえる |
| — Created 2018-05-25 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html tell application "Keynote" tell front document tell (current slide) — すべてのshapeオブジェクトの座標{x,y}を返す set pList to position of every shape — shapeオブジェクトの全座標を昇順ソートして最もX座標値が小さいものを返す set mostLeftPos to first item of sort2DList(pList) of me — 一番X座標値が小さい(=左にある)オブジェクトを特定 set mostLeftObj to first item of (every shape whose position is equal to mostLeftPos) set mostLeftProp to properties of mostLeftObj –> (*class:shape, opacity:100, parent:slide 5 of document id 253165F1-0596-4E72-B9E3-2AB6D6084125, reflection showing:false, background fill type:color fill, position:32, 160, object text:, width:56, rotation:0, reflection value:0, height:467, locked:false*) set mostLeftHeight to height of mostLeftProp set mostLeftWidth to width of mostLeftProp — 「一番左」以外のshapeオブジェクトへの参照を取得して一気にオブジェクトのHeightをそろえる set otherShape to a reference to (every shape whose position is not equal to mostLeftPos) set height of otherShape to mostLeftHeight end tell end tell end tell on sort2DList(aList) load framework set sortIndexes to {0} –Key Item id: begin from 0 set sortOrders to {true} –ascending = true set sortTypes to {"compare:"} set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list return resList end sort2DList |
ディスプレイを回転させる
指定のディスプレイを回転(表示方向を変更)させるAppleScriptです。
ディスプレイの表示方向の変更には、fb-rotateというコマンドラインツールを用いています。
fb-rotateをバンドル内に内蔵して呼び出すことが多く、AppleScript Librariesとして呼び出してもよいでしょう。
–> AppleScript Bundle file with fb-rotate

▲0°(MacBook Air 11)

▲90°(MacBook Air 11)

▲180°(MacBook Air 11)

▲270°(MacBook Air 11)
| AppleScript名:ディスプレイを回転させる |
| — Created 2016-03-11 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –fb-rotate –http://modbookish.lefora.com/topic/3513246/A-Unix-Utility-to-Change-the-Primary-Display-on-OSX/#.VuIe82OFlro –ディスプレイの情報を取得(基本情報) getDisplayList() of me –> {{dispID:"0x4248387", dispWidth:1920, dispHeight:1200, mainD:true}, {dispID:"0x424b104", dispWidth:1920, dispHeight:1200, mainD:false}, {dispID:"0x1b557a25", dispWidth:1920, dispHeight:1080, mainD:false}} –メインディスプレイを回転させる rotateMainDisplayToDegree(0) of me –いったんこれを実行すると、構成によってはメインディスプレイが他のIDのものに変わる可能性がある –ディスプレイの詳細情報を取得 getDisplayInformation() of me –> {{dispID:"0x4248387", dispWidth:1920, dispHeight:1200, dispX1:0, dispY1:0, dispX2:1920, dispY2:1200, mainD:true, rotationDegree:0, cousorExists:false}, {dispID:"0x424b104", dispWidth:1920, dispHeight:1200, dispX1:-1920, dispY1:0, dispX2:0, dispY2:1200, mainD:false, rotationDegree:0, cousorExists:true}, {dispID:"0x1b557a25", dispWidth:1080, dispHeight:1920, dispX1:1920, dispY1:-362, dispX2:3000, dispY2:1558, mainD:false, rotationDegree:270, cousorExists:false}} on getDisplayInformation() set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate" try set aRes to (do shell script (quoted form of aPath) & " -i") on error return false end try set aList to paragraphs of aRes set aaList to contents of (items 2 thru -2 of aList) set a to contents of last item of aList set {b, c} to separateStrByAChar(a, ":") of me set {b1, c1} to separateStrByAChar(c, ",") of me set mouseX to returnNumberCharsOnly(b1) as number set mouseY to returnNumberCharsOnly(c1) as number set recList to {} repeat with i in aaList set j to contents of i –Parse Result by space character set aStr to (current application’s NSString’s stringWithString:j) set aLine to (aStr’s componentsSeparatedByString:" ") (aLine’s removeObject:"") set bList to aLine as list –> {"3", "0x4248387", "1920×1200", "0", "0", "-1920", "-1200", "0", "[main]"} –Display ID set anID to contents of item 2 of bList –Resolution set aResol to contents of item 3 of bList set dParseRes to separateStrByACharAndReturnNumList(aResol, "x") of me if dParseRes = "" then exit repeat –Error copy dParseRes to {aWidth, aHeight} –Display_Bounds set dX1 to (contents of item 4 of bList) as number set dY1 to (contents of item 5 of bList) as number set dX2 to (contents of item 6 of bList) as number set dY2 to (contents of item 7 of bList) as number –Rotation set aDeg to (contents of item 8 of bList) as number –Mouse Cursor Detection set mouseF to (dX1 ≤ mouseX) and (mouseX ≤ dX2) and (dY1 ≤ mouseY) and (mouseY ≤ dY2) –Main Display (Menu) set aMain to contents of last item of bList if (contents of last item of bList) contains "main" then set aMainF to true else set aMainF to false end if set the end of recList to {dispID:anID, dispWidth:aWidth, dispHeight:aHeight, dispX1:dX1, dispY1:dY1, dispX2:dX2, dispY2:dY2, mainD:aMainF, rotationDegree:aDeg, cousorExists:mouseF} end repeat return recList end getDisplayInformation –指定IDのディスプレイを指定角度(0, 90, 180, 270のいずれか)に回転させる on rotateADisplayToDegree(aDispID as string, aDegree as integer) if aDegree is not in {0, 90, 180, 270} then return false set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate" try set aRes to (do shell script (quoted form of aPath) & " -d " & aDispID & " -r " & (aDegree as string)) on error return false end try end rotateADisplayToDegree –メインディスプレイを指定角度(0, 90, 180, 270のいずれか)に回転させる on rotateMainDisplayToDegree(aDegree as integer) if aDegree is not in {0, 90, 180, 270} then return false set mainID to getMainDispID() of me set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate" try set aRes to (do shell script (quoted form of aPath) & " -d " & mainID & " -r " & (aDegree as string)) on error return false end try end rotateMainDisplayToDegree –メインディスプレイのIDを取得する on getMainDispID() set dList to getDisplayList() of me set dDict to current application’s NSArray’s arrayWithArray:dList set aRes to filterRecListByLabel1(dDict, "mainD == true") of me set aMainD to contents of first item of aRes set mainID to dispID of aMainD return mainID end getMainDispID –実行中のMacに接続されているディスプレイの一覧を取得する on getDisplayList() set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate" try set aRes to (do shell script (quoted form of aPath) & " -l") on error return false end try set aList to paragraphs of aRes set aaList to contents of (items 2 thru -1 of aList) set recList to {} repeat with i in aaList set j to contents of i set bList to words of j set anID to contents of item 1 of bList set aResol to contents of item 2 of bList set dParseRes to separateStrByACharAndReturnNumList(aResol, "x") of me if dParseRes = "" then exit repeat –Error copy dParseRes to {aWidth, aHeight} set aMain to contents of last item of bList if j ends with "]" then set aMainF to true else set aMainF to false end if set the end of recList to {dispID:anID, dispWidth:aWidth, dispHeight:aHeight, mainD:aMainF} end repeat recList end getDisplayList –"1920×1200" といった文字列を"x"でparseしてパラメータを分ける。結果は文字列のリストで返す on separateStrByAChar(aStr as string, aChar as string) if aStr does not contain aChar then return "" if length of aChar is not equal to 1 then return "" if aStr = "" or (length of aStr < 3) then return "" set aPos to offset of aChar in aStr set partA to text 1 thru (aPos – 1) of aStr set partB to text (aPos + 1) thru -1 of aStr return {partA, partB} end separateStrByAChar –"1920×1200" といった文字列を"x"でparseしてパラメータを分ける。結果は整数のリストで返す on separateStrByACharAndReturnNumList(aStr as string, aChar as string) if aStr does not contain aChar then return "" if length of aChar is not equal to 1 then return "" if aStr = "" or (length of aStr < 3) then return "" set aPos to offset of aChar in aStr set partA to (text 1 thru (aPos – 1) of aStr) as number set partB to (text (aPos + 1) thru -1 of aStr) as number return {partA, partB} end separateStrByACharAndReturnNumList –リストに入れたレコードを、指定の属性ラベルの値で抽出 on filterRecListByLabel1(aRecList as list, aPredicate as string) set aArray to current application’s NSArray’s arrayWithArray:aRecList set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate set bList to filteredArray as list return bList end filterRecListByLabel1 –数字とプラスマイナスの符号のみ返す 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 |
OS X 10.11.5+Safari 9.1.1以降で、新たなAS制限機能が増える
macOS 10.11.5+Safari 9.1.1以降で、新たなAppleScriptの制限機能が増えました。Safariに対してdo javascriptコマンドによるコマンド実行が可能でしたが、これがデフォルト設定では禁止状態になったということです。
macOS 10.12.x系では、macOS 10.12.6+Safari 11.1にて、macOS 10.13.x系ではmacOS 10.13.5+Safari 11.1.1上にて確認しています。
■デフォルトでdo javascriptコマンドによる制御がオフに
これ以前のmacOSではデフォルトでオンになっていたので、一回オンにする作業が必要になりました(管理者パスワード必要)。

・STEP1 「開発」メニューをオンに
Safariの「環境設定」>「詳細」で、「メニューバーに”開発”メニューを表示」をオンにします。これで、Safariのメニューバーに「開発」メニューが表示されます。
・STEP2 「開発」メニューから「AppleEventからのJavaScriptを許可」「スマート検索フィールドからのJavaScriptを許可」の2つの項目をオンに(管理者パスワード必要)

| AppleScript名:最前面のウィンドウのタイトルを取得する |
| tell application "Safari" set aRes to do JavaScript "document.title;" in front document display dialog aRes end tell |

▲デフォルト状態

▲「開発」メニューからJavaScriptの実行を許可した状態
Contactsに登録してある自分の写真をPNGでデスクトップに保存する
住所録(Contacts.app)に登録してある自分の写真をPNG形式でデスクトップに保存するAppleScriptです。
住所録情報については、Contacts.appに直接アクセスして処理することも可能ですが、ここではAddressBook.frameworkを用いた方法をご紹介します。
| AppleScript名:Contactsに登録してある自分の写真をPNGでデスクトップに保存する |
| — Created 2016-04-02 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AddressBook" set imgData to current application’s ABAddressBook’s sharedAddressBook()’s |me|()’s imageData() set aDesktopPath to (current application’s NSProcessInfo’s processInfo()’s environment()’s objectForKey:("HOME"))’s stringByAppendingString:"/Desktop/" set savePath to aDesktopPath’s stringByAppendingString:((current application’s NSUUID’s UUID()’s UUIDString())’s stringByAppendingString:".png") saveTIFFDataAtPathAsPNG(imgData, savePath) of me –NSImageを指定パスにPNG形式で保存 on saveTIFFDataAtPathAsPNG(anImage, outPath) –set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:anImage 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 saveTIFFDataAtPathAsPNG |
CMD-D: Down-Home Scripting Boot Camp 2018を開催
Sal Soghoianが主催するイベント「CMD-D: Down-Home Scripting Boot Camp」の2018年版が10月15〜17日の3日間、ジョージア州のHilton Garden Innで行われることが発表されました。
講師はSal SoghoianとRay Robertson。3日間みっちりAppleScriptのセミナーを初心者から経験者向けの内容の解説を行うようです。
指定パスの所属するドライブ名を取得する v2
指定パスの所属するドライブ名を取得するAppleScriptです。
ドライブ名さえ求めてしまえば、Finderに問い合わせてそれが起動ドライブ(startup = true)かどうか確認できるため、起動ドライブ以外であれば外付けディスクやファイルサーバーであるかの判定も行えます。
| AppleScript名:指定パスの所属するドライブ名を取得する v2 |
| — Created 2017-09-03 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property |NSURL| : a reference to current application’s |NSURL| property NSURLVolumeNameKey : a reference to current application’s NSURLVolumeNameKey set aPath to POSIX path of (choose folder) set dRes to retDiskNameOfTheFolder(aPath) of me on retDiskNameOfTheFolder(aPath) set aURL to |NSURL|’s fileURLWithPath:aPath set aVlomeName to "" set {aRes, driveName} to aURL’s getResourceValue:(reference) forKey:(NSURLVolumeNameKey) |error|:(missing value) return driveName as string end retDiskNameOfTheFolder |
Previewでオープン中のファイルのパスを求める(macOS 10.12限定)
Preview.appでオープン中の画像のファイルパスをすべてPOSIX pathで求めるAppleScriptです。

▲大昔にあった「日本語AppleScript」(Japanese Dialect)を擬似的に書いたRTFを画像化したもの。AppleScriptがいまでも日本語で書けるとかいうデモではありません(大事なことなので書いておきました)
Preview.appでオープン中の画像のパスをためしに求めてみたところ(macOS 10.12.6)、実際のファイルが、
/Users/me/Desktop/image.png
であるものが、
/Users/me/Library/Containers/com.apple.Preview/Data/Desktop/image.png
と返ってきました。一時的に、ライブラリフォルダの下にコピーしてオープンしているのでしょうか。そういう「舞台裏」をそのまま見せてしまうのはどうかと思います。オリジナルのファイルパスをそのまま返せばいいのに。
そこで、Preview.appから返ってきたパスを加工してオリジナルのパスを求めてみました。
ファイルサーバー上にある画像や外部HDD上にある画像などについては検証していないので、それについては、別途パスを求め直す必要があることでしょう。
macOS 10.13.5beta上でためしてみたら、こちらでは直っていました。そーーですよねーーーーー、10.12上の仕様の方がおかしいですよねーーー(ーー;;
| AppleScript名:Previewでオープン中のファイルのパスを求める |
| — Created 2018-05-21 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Preview" set dList to path of every document –> {"/Users/me/Library/Containers/com.apple.Preview/Data/Desktop/スクリーンショット 2018-02-28 14.01.09.png", "/Users/me/Library/Containers/com.apple.Preview/Data/Desktop/スクリーンショット 2018-02-28 14.01.11.png"} end tell set mePath to POSIX path of (path to home folder) set origStr to mePath & "Library/Containers/com.apple.Preview/Data" set outPathList to {} repeat with i in dList set j to contents of i set the end of outPathList to repChar(j, origStr, (text 1 thru -2 of mePath)) of me end repeat return outPathList on repChar(origText as string, targStr as string, repStr as string) set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr} set temp to text items of origText set AppleScript’s text item delimiters to repStr set res to temp as text set AppleScript’s text item delimiters to txdl return res end repChar |
noteのオンラインマガジン「猛者」に新規Noteを寄稿
App Engineer Journal “猛者”(モサ)というオンラインマガジンに「Appleに関するウワサ話と付き合う方法(下)」を寄稿しました。
Xcodeで表示中のソースの選択中の範囲のテキストを取得する v3
Xcodeで編集中のテキストの選択中の範囲のテキストを取得するAppleScriptです。
Xcode v9.2+macOS 10.12.6およびXcode v9.3.1+macOS 10.13.5betaで動作を確認しています。
Xcode上で編集中のソーステキストの選択範囲(selected character range)を取得し、さらに実際に選択範囲のテキストを取得しています。

Xcode上でソーステキストではなくXibファイルやplistなどの他のファイルを選択中の場合にはfalseを返します。
また、本Scriptでは個別に独立したWindow上に表示中のテキストについては無視します。
常識的なMacのテキスト編集系のGUIアプリケーションであれば、
①指定パスのテキストをオープンできる
②テキストを指定パスに保存できる
③表示中のテキストの選択範囲のテキストを取得できる
④表示中のテキストの選択範囲の内容を書き換えることができる
という動作は期待したいところですが、Xcodeについては①②が怪しく(Workspace Documentに新規テキストを追加するとかできそうもない)、③はなんとかなったものの、④ができるかどうか試行錯誤してみないとわからない、といったところです(パスを取得できているので、Xcodeを経由しないで直接ファイルを書き換えれば不可能ではなさそうですが、、、)。
AppleScript対応アプリケーションが標準でそなえているopen/close/quit/count/delete/exists/make/moveなどのコマンドをのぞくと、XcodeのAppleScript用語辞書に掲載されているコマンドは、build、clean、stop、run、testの5つだけ。archiveとかのproduct(ビルド後に生成されるバイナリ)を操作するための命令は用意されていません(わざと?)。
| AppleScript名:表示中のソースの選択中の範囲のテキストを取得する v3 |
| — Created 2018-05-19 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Xcode" tell front file document try set selRange to selected character range if selRange = {} or selRange = missing value then return false –No Selection or other copy selRange to {aSelBegin, aSelEnd} set aText to text of it set aSelText to text aSelBegin thru aSelEnd of aText on error return "" –No Selection or other end try return aSelText end tell end tell –> (* " property parent : class \"NSObject\" property NSTimer : class \"NSTimer\"" *) |
Xcodeでオープン中のソースコードのパスを求める
Xcodeでオープン中のソースコードのファイルパスを求めるAppleScriptです。
Xcode v9.2+macOS 10.12.6、Xcode v9.3.1+macOS 10.13.5betaで確認しました。
おおまかにいえば、Xcodeは大きくわけて2種類の書類を扱っています。1つは、拡張子「.xcodeproj」のXcodeプロジェクト(Workspace)書類。

そして、個別のソースコード書類(SwiftとかObjective-CとかAppleScriptとか)。

そんなわけで、普通のGUIアプリケーションとはdocumentの概念がやや異なり、少々めんどくさい上にXcodeのAppleScript用語辞書に載っている用例自体も「え、そんな書き方を推奨するの?」という、なんとも不思議な仕上がりになっていますが、まあいいんでしょう。
ちなみに、本ScriptはXcodeのメインウィンドウ上でソースコードを表示する場合と、個別のウィンドウで表示する場合に対応しています。

また、Xcodeのウィンドウ上でXibファイルやInfo.plistやアイコンのAssetsなどソースコード書類以外のものを表示している場合には、エラートラップをかけてfalseを返すようにしています。

▲XcodeのAppleScript用語辞書に書かれている記述例。Workspace Documentのオープン完了待ちをpropertyを確認しつつループで待つという仕様。そんなとこ、非同期実行してドーする、という不思議感満載
| AppleScript名:Xcodeでオープン中のソースコードのパスを求める |
| — Created 2018-05-19 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Xcode" –最前面のWindowの情報を取得 set winProp to properties of front window set aDoc to document of winProp –Xcode のworkspace document(xcodeproj) –> workspace document "WKWebViewDemo.xcodeproj" of application "Xcode" set docProp to properties of aDoc set xcodeDocPath to path of docProp –> "/Users/me/Documents/Objective-C/WKWebViewDemo_MAC-master/WKWebViewDemo.xcodeproj" set aFileDoc to name of winProp –> "ViewController.m" try set aDoc to file document aFileDoc –> source document "ViewController.m" of application "Xcode" on error –Storyboard/Xib file/info.plist/Assetsなどを表示中の場合にはエラーになる return false end try set aDocPath to path of aDoc –> "/Users/me/Documents/Objective-C/WKWebViewDemo_MAC-master/WKWebViewDemo/ViewController.m" end tell |
Keynoteスライドの末尾にQRコードのスライドを追加
指定の連絡先情報のQRコード画像を作成して、現在オープン中のKeynoteのスライドの末尾に追加するAppleScriptです。

このAppleScriptでは、ただ固定の文字列をQRコード画像化していますが、Contacts(連絡先)から自分の連絡先の情報を取得して、そこからQRコード画像を作成すると、より「AppleScriptらしい」自動処理になると思います。
さらに、このKeynoteのスライドからPDFを書き出して、Slide Shareに自動アップロードし、そのURLもQRコード画像の中に入れると文句のつけようがありません。
AppleScriptによる自動化で「単なる1つのコマンドをScriptから呼び出すだけ」のものを大量に見かけますが、それだとほとんど意味がありません。複数のアプリケーションや複数のサービスを呼び出してそれらを連携させてはじめて「自動化する意味がある」内容になります。
| AppleScript名:Keynoteスライドの末尾にQRコードのスライドを追加 |
| — Created 2018-05-16 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "QuartzCore" –QRCodeを作成 set a to "MEMORY:Piyomaru Software NAME1:長野谷 隆昌 NAME2:ながのや たかあき TEL1:080-xxxx-xxxxx MAIL1:maro@piyocast.com TEL2:080-xxxx-xxxxx MAIL2:maro@xxxxxxxxx MECARD:N:長野谷,隆昌;SOUND:ながのや,たかあき;TEL:080-9999-9999;TEL:03-9999-9999;EMAIL:maro@piyocast.com;EMAIL:maro@xxxxx.xxxxx;NOTE:ぴよまる;;" set savedPath to makeQRCodeImageOnDesktop(a) of me set savedFile to (POSIX file savedPath) set savedAlias to savedFile as alias tell application "Keynote" tell front document set endSlide to make new slide at end set blankMaster to master slide "空白" –"Blank" in Japanese. This string is *localized* tell endSlide set base slide to blankMaster set thisImage to make new image with properties {file:savedAlias} end tell end tell end tell do shell script "rm -f " & quoted form of savedPath on makeQRCodeImageOnDesktop(aData) set aStr to current application’s NSString’s stringWithString:aData set strData to aStr’s dataUsingEncoding:(current application’s NSShiftJISStringEncoding) –シフトJISにエンコード set qrFilter to current application’s CIFilter’s filterWithName:"CIQRCodeGenerator" qrFilter’s setValue:strData forKey:"inputMessage" qrFilter’s setValue:"H" forKey:"inputCorrectionLevel" set anImage to qrFilter’s outputImage() set convImg to convCIimageToNSImage(anImage) of me –NSImageを拡大(アンチエイリアス解除で) set resizedImg to my resizeNSImageWithoutAntlialias:convImg toScale:6.0 –デスクトップに保存 set aDesktopPath to (current application’s NSProcessInfo’s processInfo()’s environment()’s objectForKey:("HOME"))’s stringByAppendingString:"/Desktop/" set savePath to aDesktopPath’s stringByAppendingString:((current application’s NSUUID’s UUID()’s UUIDString())’s stringByAppendingString:".png") saveNSImageAtPathAsPNG(resizedImg, savePath) of me return savePath as string end makeQRCodeImageOnDesktop on convCIimageToNSImage(aCIImage) set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithCIImage:aCIImage set tmpSize to aRep’s |size|() set newImg to current application’s NSImage’s alloc()’s initWithSize:tmpSize newImg’s addRepresentation:aRep return newImg end convCIimageToNSImage on convNSImageToCIimage(aNSImage) set tiffDat to aNSImage’s TIFFRepresentation() set aRep to current application’s NSBitmapImageRep’s imageRepWithData:tiffDat set newImg to current application’s CIImage’s alloc()’s initWithBitmapImageRep:aRep return newImg as string end convNSImageToCIimage –NSImageを指定パスにPNG形式で保存 on saveNSImageAtPathAsPNG(anImage, outPath) 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 saveNSImageAtPathAsPNG –NSImageを指定倍率で拡大(アンチエイリアス解除状態で)–By Shane Stanley on resizeNSImageWithoutAntlialias:aSourceImg toScale:imgScale set aSize to aSourceImg’s |size|() set aWidth to (aSize’s width) * imgScale set aHeight to (aSize’s height) * imgScale set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithBitmapDataPlanes:(missing value) pixelsWide:aWidth pixelsHigh:aHeight bitsPerSample:8 samplesPerPixel:4 hasAlpha:true isPlanar:false colorSpaceName:(current application’s NSCalibratedRGBColorSpace) bytesPerRow:0 bitsPerPixel:0 set newSize to {width:aWidth, height:aHeight} aRep’s setSize:newSize current application’s NSGraphicsContext’s saveGraphicsState() set theContext to current application’s NSGraphicsContext’s graphicsContextWithBitmapImageRep:aRep current application’s NSGraphicsContext’s setCurrentContext:theContext theContext’s setShouldAntialias:false theContext’s setImageInterpolation:(current application’s NSImageInterpolationNone) aSourceImg’s drawInRect:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) fromRect:(current application’s NSZeroRect) operation:(current application’s NSCompositeCopy) fraction:(1.0) current application’s NSGraphicsContext’s restoreGraphicsState() set newImg to current application’s NSImage’s alloc()’s initWithSize:newSize newImg’s addRepresentation:aRep return newImg end resizeNSImageWithoutAntlialias:toScale: |
noteのオンラインマガジン「猛者」に寄稿しています
App Engineer Journal “猛者”(モサ)というオンラインマガジンに寄稿しています。
現在のところ、
「WWDC18」
「Appleに関するウワサ話と付き合う方法(上)」
といった記事を寄稿しています。
MOSAはNPO法人としてさまざまな(主にApple系の)開発者を支援する団体として活動してきましたが、この初夏にしばりの強いNPO法人から任意団体への移行が計画されており、その話し合いの中にPiyomaru Softwareも加わっています(MOSA会員じゃないんですけど)。
1箇所から別の箇所の方位を求める v2
任意の緯度・経度情報から、別の箇所の緯度・経度情報の「方位」を計算するAppleScriptです。
v1では、Satimage OSAXのインストールが必要でしたが、自前でObjective-Cで書いた「atan2だけを計算するフレームワーク」に置き換えたものです。

–> trigonometry.framework (To ~/Library/Frameworks/)
北を0として、西に向かうとマイナス、東に向かうとプラスの値で角度(方位)を返します。この手の計算に必須のatan2関数がAppleScriptに標準装備されていないため、atan2を呼び出すだけの簡単なCocoa FrameworkをObjective-Cで記述して、呼び出してみました。
| AppleScript名:1箇所から別の箇所の方位を求める v2 |
| — Created 2018-05-10 by Takaaki Naganoya — 2017-2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "trigonometry" –(for atan2 calculation) use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html set coord1 to {latitude:35.73677496, longitude:139.63754457} –Nakamurabashi Sta. set coord2 to {latitude:35.78839012, longitude:139.61241447} –Wakoshi Sta. set dirRes1 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> -25.925429877542 set coord2 to {latitude:35.7227821, longitude:139.63860897} –Saginomiya Sta. set dirRes2 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 175.649833487804 set coord2 to {latitude:35.73590542, longitude:139.62986745} –Fujimidai Sta. set dirRes3 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> -96.385293928667 set coord2 to {latitude:35.73785024, longitude:139.65339321} –Nerima Sta. set dirRes4 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 85.959474671834 set coord2 to {latitude:35.71026838, longitude:139.81215754} –Tokyo Sky Tree set dirRes5 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 96.826542737106 –位置情報1から位置情報2の方角を計算。北が0度 on calcDirectionBetweenTwoPlaces(coord1, coord2) load framework –BridgePlus set deltaLong to (longitude of coord2) – (longitude of coord1) set yComponent to bPlus’s sinValueOf:deltaLong set xComponent to (bPlus’s cosValueOf:(latitude of coord1)) * (bPlus’s sinValueOf:(latitude of coord2)) – (bPlus’s sinValueOf:(latitude of coord1)) * (bPlus’s cosValueOf:(latitude of coord2)) * (bPlus’s cosValueOf:deltaLong) set radians to (current application’s calcAtan2’s atan2Num:yComponent withNum:xComponent) as real set degreeRes to (radToDeg(radians) of me) return degreeRes end calcDirectionBetweenTwoPlaces on radToDeg(aRadian) return aRadian * (180 / pi) end radToDeg |
指定のリスト中の指定要素が占める割合をパーセントで返す
指定List中の指定要素が占める割合をパーセントの数値で返すAppleScriptです。
ローカルのiTunesライブラリに入っている楽曲のアーティスト名を集計して、各アーティストがiTunes Music Storeで販売している楽曲のうち、どの程度の割合でApple Musicでも配信しているかを調査するAppleScriptを作成するために作成したものです。
| AppleScript名:指定のリスト中の指定要素が占める割合をパーセントで返す |
| use AppleScript version "2.4" use scripting additions use framework "Foundation" set aList to {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, true, true, false, true, true, true, true, true, true, true, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} set tPercent to calcOneItemsPercent(aList, true) of me –> 62 (%) –true/falseで構成されるlistのうち、指定要素が占める割合を%で計算。小数点以下を四捨五入 on calcOneItemsPercent(aList, targItem) set aLen to length of aList set theCountedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set tRes to (theCountedSet’s countForObject:targItem) if tRes < 1 then return 0 set pRes to (tRes / aLen) * 100 return (round pRes rounding as taught in school) end calcOneItemsPercent |
path control×2を作成 v2
Windowを作成して、その上に2つのNSPathControlを作成し、ドラッグ&ドロップでパス情報を取得するAppleScriptです。


パス情報をドラッグ&ドロップで受け付けるNSPathControlはXcode上でAppleScriptのアプリケーションを作成する場合にはよく使うGUI部品ですが、通常の(Script Editor上の)AppleScriptではあまり使っていませんでした。
AppleScriptでは、choose fileやchoose folderコマンドを複数回実行して複数のパス情報を取得するのが「いつものやり方」ですが、複数のフォルダを指定する場合で人為的なミスが許されない場合には、指定されたパス情報をあらためてダイアログで表示するなどの処理を入れていました。
受け付けた2つのパス情報は、とくにファイルであってもフォルダであってもかまわないのですが、Cocoaで取得したフォルダのPOSIX path情報は末尾にスラッシュがついていないため、AppleScriptのPOSIX pathとして使用する場合には末尾にスラッシュを補う必要があります。
AppleScript側からハンドラを強制的にMain Threadで実行しているため、Command-Control-Rで実行させる必要はありません。その一方で、Script Menuから呼び出した場合にはドラッグ&ドロップを受け付けることや、ボタンのクリックの受信ができません。
| AppleScript名:path control×2を作成 v2 |
| — Created 2018-05-09 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property windisp : false property wController : false property resList : {} set aButtonMSG to "OK" set aSliderValMSG to "処理対象フォルダと移動先の指定" set paramList to {aButtonMSG, aSliderValMSG} my performSelectorOnMainThread:"getPathControlValue:" withObject:paramList waitUntilDone:true return my resList on getPathControlValue:paramList copy paramList to {aButtonMSG, aSliderValMSG} set timeOutSecs to 180 –タイムアウト時間 set (my windisp) to true — Window表示中フラグ set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 600, 120)) –Labelをつくる set a1TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(20, 110, 80, 20)) set a2TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(20, 70, 80, 20)) a1TF’s setEditable:false a2TF’s setEditable:false a1TF’s setStringValue:"処理対象:" a2TF’s setStringValue:"移動後 :" a1TF’s setDrawsBackground:false a2TF’s setDrawsBackground:false a1TF’s setBordered:false a2TF’s setBordered:false –Ppopup Buttonをつくる set aPathControl to current application’s NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 110, 500, 20)) set bPathControl to current application’s NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 70, 500, 20)) aPathControl’s setBackgroundColor:(current application’s NSColor’s cyanColor()) bPathControl’s setBackgroundColor:(current application’s NSColor’s yellowColor()) set aHome to current application’s |NSURL|’s fileURLWithPath:(current application’s NSHomeDirectory()) aPathControl’s setURL:aHome bPathControl’s setURL:aHome –Buttonをつくる set bButton to (current application’s NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(200, 10, 180, 40))) bButton’s setButtonType:(current application’s NSMomentaryLightButton) bButton’s setBezelStyle:(current application’s NSRoundedBezelStyle) bButton’s setTitle:aButtonMSG bButton’s setTarget:me bButton’s setAction:("clicked:") bButton’s setKeyEquivalent:(return) aView’s addSubview:a1TF aView’s addSubview:a2TF aView’s addSubview:aPathControl aView’s addSubview:bPathControl aView’s addSubview:bButton aView’s setNeedsDisplay:true –NSWindowControllerを作ってみた set aWin to (my makeWinWithView(aView, 600, 160, aSliderValMSG)) set wController to current application’s NSWindowController’s alloc() wController’s initWithWindow:aWin wController’s showWindow:me set aCount to timeOutSecs * 10 set hitF to false repeat aCount times if (my windisp) = false then set hitF to true exit repeat end if delay 0.1 set aCount to aCount – 1 end repeat my closeWin:aWin if hitF = true then set s1Val to (aPathControl’s |URL|’s |path|()) as string set s2Val to (bPathControl’s |URL|’s |path|()) as string else set {s1Val, s2Val} to {false, false} end if set resList to {s1Val, s2Val} end getPathControlValue: on clicked:aSender set (my windisp) to false end clicked: –make Window for Display 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 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 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 setContentView:aView return aWin end makeWinWithView –close win on closeWin:aWindow repeat with n from 10 to 1 by -1 (aWindow’s setAlphaValue:n / 10) delay 0.02 end repeat aWindow’s |close|() end closeWin: |
searchTreeKitを呼び出して1D List抽出
PJTernarySearchTreeをCocoa Framework化したsearchTreeKitを呼び出して、高速にテキスト検索を行う(はずの)AppleScriptです。
–> SearchTreeKit.framework (To ~/Library/Frameworks/)
普通に1DのNSArrayにテキストを入れて絞り込みを行うよりもスピード面でメリットがあるのかは実測していないのでなんともいえません。PJTernarySearchTreeは検索フィールドの入力履歴からの候補語の検索などに利用するために作られた部品のようです。
| AppleScript名:SearchTreeKitのじっけん1(ファイル書き込み) |
| — Created 2018-05-08 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree set savePath to POSIX path of (path to desktop) & (do shell script "uuidgen") & "_test.tree" set aTree to current application’s PJTernarySearchTree’s alloc()’s init() aTree’s insertString:"http://www.peakji.com" aTree’s insertString:"http://www.peak-labs.com" aTree’s insertString:"http://www.facebook.com" aTree’s insertString:"http://www.face.com" aTree’s insertString:"http://blog.foo.com" aTree’s insertString:"http://blog.foo.com/bar" aTree’s insertString:"http://chinese.hello.com/ぴよー" aTree’s insertString:"http://chinese.hello.com/ぴよぴよー" aTree’s saveTreeToFile:savePath |
| AppleScript名:SearchTreeKitのじっけん2(ファイル読み込み) |
| — Created 2018-05-08 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree set savePath to POSIX path of (choose file) set aTree to current application’s PJTernarySearchTree’s treeWithFile:savePath set aRetrieved to (aTree’s retrievePrefix:"http://" countLimit:0) as list –return aRetrieved –> {"http://blog.foo.com", "http://blog.foo.com/bar", "http://chinese.hello.com/ぴよぴよー", "http://chinese.hello.com/ぴよー", "http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"} set bRetrieved to (aTree’s retrievePrefix:"http://" countLimit:2) as list –return bRetrieved –>{"http://blog.foo.com", "http://blog.foo.com/bar"} set cRetrieved to (aTree’s retrievePrefix:"http://www." countLimit:0) as list –return cRetrieved –> {"http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"} –Remove a string or object aTree’s removeString:"http://www.face.com" set dRetrieved to (aTree’s retrievePrefix:"http://www.fa." countLimit:0) as list –> {} |
| AppleScript名:SearchTreeKitのじっけん3(オブジェクトの追加と検索) |
| — Created 2018-05-09 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree set tagSearchTree to current application’s PJTernarySearchTree’s alloc()’s init() tagSearchTree’s insertString:"abcd" (tagSearchTree’s retrievePrefix:"abc") as list –> {"abcd"} tagSearchTree’s insertString:"def" tagSearchTree’s insertString:"ghi" tagSearchTree’s removeString:"abcd" set aList to (tagSearchTree’s retrievePrefix:"") as list –> {"def", "ghi"} |
