Archive for the '10.13 savvy' Category

2017/08/09 AppleScript Release Notesが更新される(macOS 10.13 High Sierra)

AppleのWebをチェックしてみたら、macOS 10.13のAppleScript 2.7の変更点についても新たに追加されていたことを見つけました(昨日見たときには10.12への言及のみでした)。

macOS Version AppleScript JXA
10.10 2.4 1.0
10.11 2.5 1.1
10.12 2.5 1.1
10.13 2.7 1.1

10.13 Changes

macOS High Sierraでは、セキュリティに関する若干の改良や修正が行われた、とのこと。

・AppleScriptObjCで、method family deductionのための完全なルールを使用するようになった。このため、 +[NSCharacterSet newlineCharacterSet]のようなメソッドをクラッシュせずに呼べるようになった。

macOS 10.12上で問題になっている点といえば、AppleScriptドロップレットにファイルをドラッグ&ドロップしたときに、ファイルの拡張属性「com.apple.quarantine」の影響を受けて、ユーザーに安全確認を問い合わせていないファイルについてはドロップレット側でも処理しない、という問題。

また、これに付随してドロップレットにドラッグ&ドロップしたファイルの処理が複数回Openハンドラを呼び出されて実行される、ということが一番問題になっていました。

→ com.apple.quarantineがドロップレットに与える影響

同じ処理をmacOS 10.13 Public Betaで行なってみると、

 (1)ドロップレットにドロップしたファイルが複数回のopenハンドラ呼び出しに分割されて処理される状況は変わっていない

 (2)あきらかにヤバそうなファイル(未署名のアプリケーション。xattrコマンドで調べるとcom.apple.quarantine属性がついている)をドロップすると、(実行するわけでもないのに)起動したときと同じ警告ダイアログが出て処理が停止する

 (3)(2)のヤバいファイルをドロップした直後(いったん終了して)もう一度、安全なファイルをドロップしてもDock上でバウンドを繰り返す(起動中アニメーション)ものの、起動しないケースがある

といった様子です。

macOS 10.13 Public Betaでは、

・sayコマンドで日本語の特定の文字列(もげる、捥げる)を日本語音声で読み上げると一部の文字が抜ける(iOSでも同様)

のバグは未修正です。

2017/07/19 SQL LibでmacOS上の各種SQLite DBの情報を確認する

Shane Stanleyの「SQL Lib」を用いてmacOS上のアプリケーションが使用しているSQLite DBの内容を確認してみるAppleScriptです。

このところSQL Libを用いて、いろいろと基礎的な操作を試しています。Shane Stanleyから「基礎的な操作ってどんなんだよ?!」とツッコミが入っていろいろやりとりをしつつ、自分でも試していたら急に全体像がくわしく見えてきました。Google翻訳の精度が上がって、わりと日本語の文章でも微妙なニュアンスが伝わるようで、チョットコワイデス(^ー^;;

SQL Libについては、AppleScriptのレベルで日常的な検索や更新、作成や削除などはひととおりできるようで、少し込み入った操作や取得になると内蔵のFMDBASフレームワークに(Cocoaのオブジェクトを経由して)アクセスすることになるようです。

なので、SQLiteのバージョン取得などもSQL Libに通常のAppleScriptのハンドラ呼び出しで行うのではなく、内蔵のFMDBASフレームワークに問い合わせを行うことになるのだとか(do shell scriptコマンド経由でもいいんですが)。

macOS上のアプリケーションの多くはSQLite DBを利用しており、直接データを読めると便利なケースもありそうです。Notes、Safari、Calendarが有名ですが、ほかにもあるでしょう(探せばきっといっぱいある)。もしも、Mail.appもSQLiteを使っているのであればSQLite経由でデータを取れたほうが便利なケースもありそうです。SpotlightのIndex DBとかも。

AppleScriptなどの言語を使っているユーザーはSQLと相性がいいとか悪いとかいう話をすれば、きっと「関係ない」と思っている人が多いことでしょう。ただ、SQLiteの形式になっている既存のデータであるとか、巨大なデータ配布物に問い合わせを行う場合にはどうしても避けて通れない存在であるため、なるべくフレンドリーなインタフェース経由で操作したいところです。

AppleScriptでも巨大なデータ(10万レコード以上のrecordとかlist)を扱うようになってくると、やはりデータベースの併用を視野に入れる必要が出てきます。FileMaker ProはものすごくAppleScriptにフレンドリーな存在ですが、SQLiteならOS標準装備なうえにFileMaker Proよりもベンチマーク上では倍ぐらいのパフォーマンスが出るようなので、使わない手はないことでしょう。

とりあえず、指定データベース上のテーブル名の取得と、テーブルのスキーマ定義の取得のあたりを(Shaneに聞きつつ)まとめてみました。各アプリケーションが利用しているSQLite DBのスキーマについてはOSのアップデートなどで変更になる場合もありそうですから、呼び出す前にスキーマの照合ぐらいはしておいたほうがよさそうだと思ったもので。

AppleScript名:SQL LibでmacOS上の各種SQLite DBの情報を確認する
– Created 2017-07-18 by Shane Stanley
– Modified 2017-07-19 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use sqlLib : script “SQLite Lib” version “1.0.0″
use BridgePlus : script “BridgePlus”
–http://piyocast.com/as/archives/4731

–Notes
set aDBpath to (POSIX path of (path to library folder from user domain)) & “Containers/com.apple.Notes/Data/Library/Notes/NotesV6.storedata”
set db1Res to retTableNames(aDBpath) of me
–>  {”ZATTACHMENT”, “ZNOTEBODY”, “ZOFFLINEACTION”, “Z_PRIMARYKEY”, “Z_METADATA”, “ZFOLDER”, “Z_MODELCACHE”, “ZACCOUNT”, “ZNOTE”}

–Safari
set bDBpath to (POSIX path of (path to library folder from user domain)) & “Safari/History.db”
set db2Res to retTableNames(bDBpath) of me
–>  {”history_items”, “sqlite_sequence”, “history_visits”, “history_tombstones”, “metadata”, “history_client_versions”}

–Calendar
set cDBpath to (POSIX path of (path to library folder from user domain)) & “Calendars/Calendar Cache”
set db3Res to retTableNames(cDBpath) of me
–> {”ZATTACHMENT”, “ZATTENDEE”, “ZCHANGEREQUESTDEPENDENCY”, “ZCOMMENT”, “ZDIFF”, “ZERROR”, “ZICSELEMENTPROPERTIES”, “ZLOCATION”, “ZMESSAGECONTENTS”, “ZPERSISTENTOPERATION”, “ZRECURRENCEEXCEPTION”, “ZRECURRENCESET”, “ZSEARCHPROPERTY”, “Z_METADATA”, “Z_MODELCACHE”, “ZCALENDARITEM”, “ZNODE”, “ZSUBSCRIPTIONINFO”, “ZALARM”, “ZCALENDARUSERADDRESS”, “ZCHANGEREQUEST”, “ZDEFAULTALARMSET”, “ZMESSAGE”, “ZPUBLICATION”, “ZSHAREE”, “Z_PRIMARYKEY”}

–Get Schema Definition of each Table(Safari Histrory)
repeat with i in db2Res
  set aRes to retDBSChema(bDBpath, i)
  
log aRes
  
–> {{sql:”CREATE TABLE history_client_versions (client_version INTEGER PRIMARY KEY,last_seen REAL NOT NULL)”, rootpage:540, type:”table”, name:”history_client_versions”, tbl_name:”history_client_versions”}, …..
  
end repeat

on retTableNames(aDBpath)
  set theDb to sqlLib’s makeNewDbWith:aDBpath
  
theDb’s openReadOnly()
  
set aRes to theDb’s doQuery:“select name from sqlite_master where type = ’table’;”
  
set bRes to (current application’s SMSForder’s arrayByFlattening:aRes) as list
  
theDb’s |close|()
  
return bRes
end retTableNames

on retDBSChema(aDBpath, aTableName)
  set theDb to sqlLib’s makeNewDbWith:aDBpath
  
theDb’s openReadOnly()
  
  
set x to theDb’s underlyingFMDatabase()’s getSchema()
  
set theResult to current application’s NSMutableArray’s array()
  
  
repeat while x’s next() as boolean
    theResult’s addObject:(x’s resultDictionary())
  end repeat
  
  
theDb’s |close|()
  
return theResult as list
end retDBSChema

★Click Here to Open This Script 

2017/07/16 ASOCでcolor popup buttonを作成

動的にWindow+View+popup buttonを作成し、色選択を行うpopup menuを作成するAppleScriptです。

color_popup.png

Script Editor上でControl-Command-Rと操作することで実行できます。アプレットとして保存して実行してもOKです。

color_popup2.png

いくつか候補がある色のうちからどれかを選ぶといった処理は割とあるのですが、色のプレビューを行うインタフェースはAppleScriptのデフォルトのコマンドでは用意されていないので、ちょっと作ってみました。

たとえば、テキストエディット上で資料の文章をチェックを行なっているような場合、見直す必要のある箇所に赤く色をつけておいて、赤くマークした箇所のみAppleScriptで抽出するとかいう処理は便利にやっています(ものすごく効率がいい)。赤以外でもマークした箇所を抽出するとかいったら、本Scriptのような部品を利用して「どの色でマークした箇所を抽出しようか」文章中の色付き部分を全部スキャンしたうえで色選択という処理ができるわけです。

Script EditorおよびASObjC Explorer 4上での実行は確認できていますが、Script Debugger 6.0.5 試用版ではクラッシュします。

1枚のみのWindowを作成する場合にはNSWindowControllerを用いる必要はないようですが、ためしにNSWindowControllerを省いたScriptも作って試してみたところ・・・安定性がやや損なわれるようでした。結局、NSWindowControllerがあったほうがよいのでは???

指定色でNSImageを作成してmenu itemに設定していますが、macOS 10.13ではこれが正方形でないとおもいどおりのサイズでメニューに表示されませんでした。

color_popup1013.png
▲本ScriptをmacOS 10.13で動かしたときのイメージ(10.12上で再現)

color_popup1013b.png
▲macOS 10.13上のpopup menu上で大きくColor部分を表示するときには、imageの縦横サイズを同じに?

AppleScript名:ASOCでcolor popup buttonを作成
– Created 2017-07-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “Carbon” – AEInteractWithUser() is in Carbon
–http://piyocast.com/as/archives/4724

property windisp : false
property wController : false –いらなかったかも?

if current application’s AEInteractWithUser(-1, missing value, missing value) is not equal to 0 then return

set ap1List to {{65535, 0, 65535}, {0, 32896, 16448}, {0, 32896, 65535}, {19702, 31223, 40505}}

set aButtonMSG to “OK”
set aSliderValMSG to “Select Color”
set aVal to getPopupValues(ap1List, 65535, aButtonMSG, aSliderValMSG, 20) of me

on getPopupValues(ap1List, aColMax, aButtonMSG, aSliderValMSG, timeOutSecs)
  
  
set (my windisp) to true
  
  
set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 360, 100))
  
  
–Labelをつくる
  
set a1TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(30, 60, 80, 20))
  
a1TF’s setEditable:false
  
a1TF’s setStringValue:“Color:”
  
a1TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set a1Button to current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 60, 200, 20)) pullsDown:false
  
a1Button’s removeAllItems()
  
  
set a1Menu to current application’s NSMenu’s alloc()’s init()
  
  
set iCount to 0
  
repeat with i in ap1List
    copy i to {r1, g1, b1}
    
    
set nsCol to makeNSColorFromRGBAval(r1, g1, b1, aColMax, aColMax) of me
    
set anImage to makeNSImageWithFilledWithColor(64, 16, nsCol) of me
    
    
set aTitle to “col_test_” & (iCount as string)
    
set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:aTitle action:“actionHandler:” keyEquivalent:“”)
    (
aMenuItem’s setImage:anImage)
    (
aMenuItem’s setEnabled:true)
    (
a1Menu’s addItem:aMenuItem)
    
    
set iCount to iCount + 1
  end repeat
  
  
a1Button’s setMenu:a1Menu
  
  
  
–Buttonをつくる
  
set bButton to (current application’s NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 10, 140, 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:a1Button
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた(いらない?)
  
set aWin to (my makeWinWithView(aView, 300, 100, aSliderValMSG))
  
  
set wController to current application’s NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 100
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.01
    
set aCount to aCount - 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to a1Button’s titleOfSelectedItem() as string
  else
    set s1Val to false
  end if
  
  
return s1Val
  
end getPopupValues

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 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)
  
  
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:

–Popup Action Handler
on actionHandler:sender
  set aTag to tag of sender as integer
  
set aTitle to title of sender as string
end actionHandler:

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 current application’s NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa
  
return aColor
end makeNSColorFromRGBAval

–指定サイズの画像を作成し、指定色で塗ってファイル書き出し
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  set anImage to current application’s NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  

  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to current application’s NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  

  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  

  
anImage’s unlockFocus()
  

  
return anImage
end makeNSImageWithFilledWithColor

★Click Here to Open This Script 

2017/07/14 macOS 10.13=AppleScript 2.7

一般公開されたmac OS 10.13 Public Betaを見るかぎり、AppleScriptの処理系がバージョンアップされてバージョン2.7になっています。

macOS Version AppleScript JXA
10.10 2.4 1.0
10.11 2.5 1.1
10.12 2.5 1.1
10.13 2.7 1.1

 「おいおい、バージョン2.6はどこに行ったんだ?」(10.12ではバージョン2.5)

というところですが、詳細は不明です。それとなく「リリースノート出す気あんの?」と聞いてみたらその意向はあるようです。このあたりは、オフィシャルで公開情報が出てくるまで待つしかありません。

macOS 10.12ではmacOS自体のセキュリティ系の機能とAppleScriptバージョン2.5の処理系の整合性が取れていなかった(とくに、droplet処理時)ので、このあたりの整合性を取り戻すのが(Apple的な)急務ということになるでしょう。

また、新規に導入されたファイルシステム「APFS」「戦場の絆」プレイヤー的にはAPFSDSと見間違える)の影響もあるので、そのあたりの「穴埋め」も行っていることでしょう(ファイルシステム上に存在しない情報を取得する命令については、ヌル文字列を返してくる)。

macOS 10.12まではファイル情報を取得するinfo for命令でfile creatorとfile typeの情報を取得できていました(廃止されたとか言われていたのに)が、macOS 10.13+APFSではそもそもそんな管理項目が存在しないので、何も返ってこなくなります。

このあたり、ファイルの種別判定部分はmacOS 10.13+AppleScript 2.7+APFSでは書き換えが必要になるはずです。事実、Piyomaru Script Assistantでそういうパーツが出てきています。

APFSの仕様ではタイムスタンプがナノ秒単位になっていますが、Finder経由でタイムスタンプを取得すると結果はAppleScriptのdate型。FinderやSystem Events経由では秒以下の情報を取得できないことを確認しています。Cocoa経由で取得するにしても、どのように扱うことになるのか興味のあるところです。

Cocoaの呼び出し関連では、Blocks構文を要求するAPIをバージョン2.5までのAppleScriptでは呼べていないので、これがものすごくフラストレーション源になっています。あと、ASOCを書いていて腹が立つのは、

  「精度指定の数値をパラメータに要求するようなAPIが呼べない」

ことです。このあたり、なんとかならないものなのか。あと、AppleScript自体の数値(number)型の有効桁数が少なすぎて変数に入れられないEnumとかあるので、number型の有効桁数を拡張するとか、倍精度(有効桁数の多い)の数値型を新設するとかしてほしいところです。

また、Swiftで書かれたFrameworkの呼び出しが、自分はできていないので(ProjectにBridgingHeaderを追加すれば呼べるといった声もありますが)、このあたりなんとかならないものかと思っています。

sayコマンドで日本語音声を指定して特定の文字列を読ませても正しく読み上げが行われないバグは直っていません。バグレポートを書いてテスト用のコードまでAppleに提出していますが、「もげる」「捥げる」という文字を読ませると不完全な結果しか返ってきません。iOS上でも同様です。ASのsayコマンドではなくCocoaのレベルで問題が出ているようですが、これが音声データそのものに問題があるとしたら、音声データのライセンス提供元との調整になるはず。

ほかには、Script Menuから呼び出すAppleScriptに対して制限がきつすぎる(書類のオープン/クローズなどを行うと処理を止められる)点についてバグレポートしていますが、このあたりはScript Editorのアップデートが行われていないため不明です。

スクリプトメニューからのAppleScript実行処理自体は/usr/bin/osascriptコマンドで行なっているので/usr/bin/osascript次第?

2017/07/04 Mac App Storeでアプリケーション「Double PDF」を販売開始

Mac App StoreでMac用アプリケーション「Double PDF」(1,080円)の販売を開始しました。すべてAppleScriptで書いたアプリケーションです。

dpdf1.png

文字主体のPDF(電子ブックなど)やKeynoteなどのオフィス系アプリケーションで作成したPDFの差分チェック用ツールです。2つのPDFを同時にめくってチェックを行うのが基本的な機能で、差分を検出するために便利な機能が備わっています。

さて、なぜこのようなアプリケーションを作ったかという経緯についてご説明を。

同じデータ(Pages書類とかMarkdown書類とか)からPDFを作成するといっても、OSやアプリケーションのバージョンが変わると微妙に生成されるPDFは変わってきます(本当)。文字詰め、行間スペース、レイアウト順など、こまかいところは実に頻繁に変わります。

また、元データ自体に修正することがあるので、きちんと反映されているのか、修正点がよそに反映しないかどうかもPDF出力して、オリジナルと比較して確認したいところです。

こういう用途で真っ先に試してみるのは、Adobe Acrobat。PDFバージョン比較機能があるので試してみたところ、500ページぐらいのPDF本に対しては「微細な変化を検出しすぎる」こともあって、実務ではとても使えませんでした。とくに、不可視データの変化を検出しまくるので、Adobe Acrobatをこの用途に使うのはほぼ無理という判断に。

そこで、前のバージョンのOSで生成した本と現在のOS上で生成した本で変化が生じていないかをチェックするAppleScriptを書き、GUIまで作ってひととおり機能評価。SSDのマシンで動かした感じでは(MacBook Pro、MacBook Air)かなりいい印象でした。

dpdf0.png
▲開発最初期バージョンの画面。ここから周囲のみなさまのダメ出しによりいろいろ試行錯誤を

PDFを画像として評価して差分をチェックするのはGPUImage.frameworkで行なっています。GPUの強力な機能がAppleScriptからでも手軽に呼び出せています。

PDF本文テキストの差分を表示するのは、外部アプリケーション「BBEdit」「TextWrangler」。Mac App Storeに提出する際のチェックで引っかかって外しましたが、初期版ではFileMergeやVimdiffなどを操作してテキストの差分を表示する機能もありました(削ってしまいましたが)。

2text_diff_by_external_app_j_resized.png
▲外部アプリケーション(BBEdit)による文字差分のブラウズ

2text_diff_by_external_app_2_resized.png
▲途中のバージョンにあった、Vimdiffによる文字差分のブラウズ(廃止)

Adobe Acrobatよりも軽快に動作し、差分チェックを「ソートした本文文字」(PDF出力時にレイアウト順がよく変わるので)、「本文文字そのまま」「プレビュー画像としてチェック」などの方式をとりまぜてさまざまなケースに対応できるようにしてみました。

よろしくお買い求めください!(告知が続いたのはたまたま、、、)

2017/06/22 指定矩形内に含まれるデータをリストで返す v3

指定矩形座標内に指定座標が含まれるかどうかを判定するAppleScriptです。

NSPointInRectを見つけて、NSRectの中にNSPointが含まれるかどうかチェックできることがわかりました(汗)

→ 矩形座標(NSRect)同士の衝突判定はこちら

AppleScript名:指定矩形内に含まれるデータをリストで返す v3
– Created 2017-06-22 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4702

set aList to {{507, 162}, {338, 166}, {389, 166}, {448, 166}, {286, 110}, {504, 109}, {558, 108}, {341, 113}, {394, 115}, {447, 112}, {234, 107}, {611, 110}, {286, 58}, {501, 63}, {556, 58}, {337, 59}, {391, 60}, {448, 63}, {611, 58}}

set rangeList to {{500, 100}, {550, 180}} –{{x1,y1}, {x2,y2}}
set resList to withinRange(rangeList, aList) of me
–>  {{507, 162}, {504, 109}}

on withinRange(rangeList as list, targetList as list)
  set aRect to makeNSRect(rangeList) of me
  
  
set includedList to {}
  
repeat with i in targetList
    copy i to {x, y}
    
set aPoint to current application’s NSMakePoint(x, y)
    
set aRes to (current application’s NSPointInRect(aPoint, aRect)) as boolean
    
    
if aRes = true then
      set the end of includedList to contents of i
    end if
  end repeat
  
  
return includedList
end withinRange

on makeNSRect(aList as list)
  try
    copy aList to {{x1, y1}, {x2, y2}}
    
set xWidth to (x2 - x1)
    
set yHeight to (y2 - y1)
    
set a1Rect to {origin:{x:x1, y:y1}, |size|:{width:xWidth, height:yHeight}}
    
return a1Rect
  on error
    return missing value
  end try
end makeNSRect

★Click Here to Open This Script 

2017/06/22 指定矩形内に含まれるデータをリストで返す v2

指定矩形座標内に指定座標が含まれるかどうかを判定するAppleScriptです。

以前に掲載したPure AppleScript版から改修してCocoaの機能で書き直してみました。ただ、これで正しいのかどーかというのはいまひとつ確証がありません。

width=0, height=0のRectを作ってオーバーラップのチェックをしてみましたが、これではオーバーラップの検出ができなかったためにwidth=1, height=1にしてみました。

→ やっぱり計算内容に納得が行かなかったので作った改修版(v3)はこちら

AppleScript名:指定矩形内に含まれるデータをリストで返す v2
– Created 2017-06-22 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4701

set aList to {{507, 162}, {338, 166}, {389, 166}, {448, 166}, {286, 110}, {504, 109}, {558, 108}, {341, 113}, {394, 115}, {447, 112}, {234, 107}, {611, 110}, {286, 58}, {501, 63}, {556, 58}, {337, 59}, {391, 60}, {448, 63}, {611, 58}}

set rangeList to {{500, 100}, {550, 180}} –{{x1,y1}, {x2,y2}}
set resList to withinRange(rangeList, aList) of me
–>  {{507, 162}, {504, 109}}

on withinRange(rangeList, targetList)
  set aRect to makeNSRect(rangeList) of me
  
  
set includedList to {}
  
repeat with i in targetList
    set bRect to makeNSRectFromXY(i) of me
    
if bRect = missing value then error “Missing Data”
    
set aRes to detectRectanglesCollision(aRect, bRect) of me
    
if aRes = true then
      set the end of includedList to contents of i
    end if
  end repeat
  
  
return includedList
end withinRange

on makeNSRectFromXY(bList as list)
  try
    copy bList to {x, y}
    
set xWidth to 1
    
set yHeight to 1
    
set a1Rect to {origin:{x:x, y:y}, |size|:{width:xWidth, height:yHeight}}
    
return a1Rect
  on error
    return missing value
  end try
end makeNSRectFromXY

on makeNSRect(aList as list)
  try
    copy aList to {{x1, y1}, {x2, y2}}
    
set xWidth to (x2 - x1)
    
set yHeight to (y2 - y1)
    
set a1Rect to {origin:{x:x1, y:y1}, |size|:{width:xWidth, height:yHeight}}
    
return a1Rect
  on error
    return missing value
  end try
end makeNSRect

–NSRect同士の衝突判定
on detectRectanglesCollision(aRect, bRect)
  set a1Res to current application’s NSIntersectionRect(aRect, bRect)
  
return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}})
end detectRectanglesCollision

★Click Here to Open This Script 

2017/06/19 日の出、日没時刻を計算する

オープンソースのプロジェクト「EDSunriseSet」(By Ernesto García)をFramework化した「EDSunriseSet.framework」を呼び出して日の出、日没時刻を計算するAppleScriptです。

edsunriseset.png
▲もともとのGUI版サンプルプログラム

本AppleScriptのテストのためには、EDSunriseSet.frameworkを~/Library/Frameworksフォルダに入れておく必要があります。バイナリを用意しておきましたので、自己責任でおためしください。

→ Download Binary (26KB)

本Scriptは単にEDSunriseSetのサンプル中に書かれていたサンプルデータをそのまま利用したものであり、本来であればCoreLocationを呼び出して現在位置を取得し、システム設定からタイムゾーン情報を取得し位置情報から逆住所ジオコーダーで場所の住所情報を取得するといった処理になることでしょう。もちろん、任意の年月日の日付オブジェクトを作って指定するとか。

AppleScript名:日の出、日没時刻を計算する
– Created 2017-06-19 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “EDSunriseSet” –erndev/EDSunriseSet
–https://github.com/erndev/EDSunriseSet
–http://piyocast.com/as/archives/4696

set cityRecList to {{kCityName:“Madrid”, kCityLatitude:(40.4165), kCityLongitude:(-3.70256), kCityTimeZone:“Europe/Madrid”}, {kCityName:“Beijing”, kCityLatitude:(39.9075), kCityLongitude:(116.39723), kCityTimeZone:“Asia/Shanghai”}, {kCityName:“Cupertino”, kCityLatitude:(37.3229978), kCityLongitude:(-122.0321823), kCityTimeZone:“America/Los_Angeles”}, {kCityName:“New York”, kCityLatitude:(40.7127837), kCityLongitude:(-74.0059413), kCityTimeZone:“America/New_York”}, {kCityName:“Tokyo”, kCityLatitude:(35.6894875), kCityLongitude:(139.6917064), kCityTimeZone:“Asia/Tokyo”}, {kCityName:“Sydney”, kCityLatitude:(-33.8674869), kCityLongitude:(151.2069902), kCityTimeZone:“Australia/Sydney”}}

set dList to {}

repeat with i in cityRecList
  set the end of dList to getSunriseSunset(i) of me
end repeat
return dList
–>  {{sunrise:date “2017年6月19日月曜日 13:44:22″, sunset:date “2017年6月20日火曜日 4:48:04″, cityname:”Madrid”}, {sunrise:date “2017年6月19日月曜日 5:45:35″, sunset:date “2017年6月19日月曜日 20:45:54″, cityname:”Beijing”}, {sunrise:date “2017年6月19日月曜日 21:47:30″, sunset:date “2017年6月20日火曜日 12:31:43″, cityname:”Cupertino”}, {sunrise:date “2017年6月19日月曜日 18:24:37″, sunset:date “2017年6月20日火曜日 9:30:19″, cityname:”New York”}, {sunrise:date “2017年6月19日月曜日 4:25:14″, sunset:date “2017年6月19日月曜日 18:59:52″, cityname:”Tokyo”}, {sunrise:date “2017年6月19日月曜日 5:59:28″, sunset:date “2017年6月19日月曜日 15:53:30″, cityname:”Sydney”}}

on getSunriseSunset(cityRec)
  set curLocale to current application’s NSLocale’s currentLocale()
  
set curDate to current application’s NSDate’s |date|()
  
  
set aTZ to current application’s NSTimeZone’s alloc()’s initWithName:(kCityName of cityRec)
  
set aSunrizeSunset to current application’s EDSunriseSet’s alloc()’s initWithDate:curDate timezone:aTZ latitude:(kCityLatitude of cityRec) longitude:(kCityLongitude of cityRec)
  
  
set aSunRiseDate to (aSunrizeSunset’s sunrise) as date
  
–>  date “2017年6月19日月曜日 4:25:14″
  
  
set aSunSetDate to (aSunrizeSunset’s sunset) as date
  
–>  date “2017年6月19日月曜日 18:59:52″
  
  
return {sunrise:aSunRiseDate, sunset:aSunSetDate, cityname:kCityName of cityRec}
end getSunriseSunset

★Click Here to Open This Script 

2017/06/08 指定PDFの最初のページからアノテーションを取得する

指定PDFの最初のページに添付されたアノテーション(Preview.app上ではマークアップと呼ばれる)を取得するAppleScriptです。

pdf_annotation1_resized.png

とりあえず、指定PDFの指定ページ上のアノテーションを取得して種類や大きさを取得できるようになりました。

日常的に利用しているPDFビューワーとしてはオープンソースのSkimがあり、むしろPreview.appよりもこちらの方を主に利用していますが、Skimで添付したアノテーションについては保存形式が異なる(外部保存?)ようで、本Scriptでは検知できませんでした。テストにはPreview.app上で編集して任意のアノテーション(マークアップ)を追加したPDFを用意する必要があります。

PDF上の指定ページ上のアノテーションを取得することはできるようになりましたが、取得することが目的ではなく、Script側からアノテーションを作成してPDFに添付することが最終目的です。アノテーションの作成についてはあまり情報が見つからず、ちょっと苦労させられています。

他のアプリケーションに依存しないでPDFの各種処理が行えることが望ましく(とくに、Adobe Acrobatが入っていない環境でも処理できることが望ましい)、アノテーションの添付はAppleScriptでCocoaの機能を利用して行うPDF処理としては「最後の難関」として残っています。ほかはひととおり他のアプリケーションなしでできています。

AppleScript名:指定PDFの最初のページからアノテーションを取得する
– Created 2017-06-08 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
–http://piyocast.com/as/archives/4679

set aHFSPath to (choose file of type {“com.adobe.pdf”} with prompt “Choose a PDF with Annotation”)
set aPOSIX to POSIX path of aHFSPath
set aURL to (current application’s |NSURL|’s fileURLWithPath:aPOSIX)

set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
set pCount to aPDFdoc’s pageCount()

set firstPage to (aPDFdoc’s pageAtIndex:0)
–>  (PDFPage) PDFPage, label 1

set anoList to (firstPage’s annotations()) as list
(*
{(PDFAnnotationMarkup) Type: ’Highlight’, Bounds: (81, 624) [434, 53]
, (PDFAnnotationSquare) Type: ’Square’, Bounds: (50, 419) [212, 162]
, (PDFAnnotationSquare) Type: ’Square’, Bounds: (301, 107) [244, 484]
}
*)

repeat with i in anoList
  set aBounds to i’s |bounds|()
  
  
log aBounds
  
(* {origin:{x:80.79, y:624.4106}, size:{width:433.6944, height:52.8918}} *)
  
(* {origin:{x:50.05553, y:419.1671}, size:{width:212.27807, height:162.3308}} *)
  
(* {origin:{x:300.6213, y:106.8405}, size:{width:244.0961, height:484.4566}} *)
  
end repeat

★Click Here to Open This Script 

2017/06/07 macOS 10.13 High Sierra Frameworks

AppleのDeveloperサイト(ログイン不要エリア)にAPIリファレンス一覧のドキュメントが公開されていました。WWDC 2017で発表された内容が反映された、最新のβ版OSで利用できるAPIの一覧です。

その中で、追加や変更があったものの中で目にとまったものについて少し調べてみました。

Vision.framework

画像認識を行うフレームワークのようです。ただ、従来からCoreImageで同様の機能が用意されていたものと機能的に大差がないように見えます。CoreImageでは画像ファイルが認識対象でしたが、ビデオも対象になったことが変更点でしょうか。

MicrosoftのVision APIのように写真に写っている内容が何か、といった識別はしてくれないようです。現状ではCoreImageに毛が生えた程度、というところでしょうか。人物の顔認識はしてくれるものの、人物認識・人物識別ができるわけではないようです。

Core ML.framework

学習済みの機械学習モデルを「利用するための」フレームワーク。Vision Frameworkや自然言語処理機能(NSLinguisticTaggerとか)もこのCore MLの基盤の上に作られているもよう。

これ自体で機械学習を行ってモデルファイルを作る機能はなく、他のプログラムで学習したモデルをコンバートして利用する方向に専念しているらしく、取ってつけたようなやっつけ感でいっぱいです。

また、サポートしている機械学習モデル形式が偏っているというか、GoogleのTensorFlowのファイルをサポートしていないのはなぜだろーかという疑問があります。

ColorSync.framework

macOS 10.13で変更点があるような書き方がされているようですが、詳細はまだ掲載されていません。

2017/06/06 macOS 10.13 High Sierra

WWDC 2017のKeynoteにおいて、macOS 10.13「High Sierra」が発表になりました。

Apple File Systemの標準採用、Metal 2、より強化されたSiriなどが搭載されるようです。見た目や使い勝手が大幅に刷新されるということはないだろう、とその小幅な変更が施された名前からも期待できます。

新しい機能が搭載されるということは、例によってAppleがロクにテストも検証も修正もしないで新機能を出荷するということであり、とくにファイルシステム周りの変更は相当の混乱を生み出すことでしょう。しかも、10.13で発生したバグを10.13.xで解決しないまま10.14に移行するのはいつものことです。

それでも、ここ数年の停滞を払拭させるような試みが行われていることについては、評価に値するものと思っています。

AppleScriptが箱庭の世界の中だけでなく、Cocoa Frameworkを呼び出せるようになったために、OSの機能アップをタイムラグなしで享受できるようになりました。たとえば、プレビュー説明の文章を読んだだけでも日本語のNSSpellChecker辞書がOSレベルで提供されるようになることがうかがわれますし、強化されたGPUとGPUの機能を活かした(BNNSよりも整備された)機械学習フレームワークが提供されることも期待できます。

→ Core MLという形で提供されるようで。ただ、ドキュメント読むと学習用じゃなくて、学習ずみモデルを利用することに重点が置かれているもよう

まずは、実際に見て触って試してみないとなんとも言えません。