頭のいいタイマー割り込み(on idle)実行のAppleScriptを追求してみました。
AppleScript開闢(かいびゃく)以来、すでに20年以上の時間が経過しているので、on idleによるタイマー割り込み処理なんて、探せばサンプルが山のように出てくるものです。
AppleScript名:timer interrupt |
property targetTime : "9:37:00" property timerInterval : 30 on run set timerInterval to 30 end run on idle set curTime to current date set cString to time string of curTime if cString ≥ targetTime then display dialog "It’s time to take off!" buttons {"OK"} default button 1 giving up after 30 quit end if return timerInterval end idle |
これが基礎的な内容で、このScriptをScript Editor上でアプリケーション(アプレット)形式で、「ハンドラの実行後に終了しない」をオンにして書き出すとタイマー実行アプレットが出来上がります(3分間クッキング)。
ただ、実行時刻のパラメータがプログラム内に直打ちなのが気になります。知能レベルが低い感じがします。
そこで、実行時刻のパラメータの外部供給ということを考え出すわけですが、
(1)設定ファイルから読み込み
(2)アプレット自身のコメント(File Comment)から読み込み
(3)ファイル名自体から読み込み
(4)コマンドラインから実行し、実行時にパラメータ(argv)を指定
などの方法を考えつきます(20世紀にすでにさんざんやった内容)。ただし、全角数字を半角に変換したり、ファイル名の場合には時刻セパレータの「:」がmacOS上ではファイル名に使えない文字(ディレクトリ・セパレータ)だったり、Finderが管理しているファイル名はUnicodeのNormalize方式が異なる(処理しやすいようにNormalizeし直さないとダメ)など割と頭の痛い問題がいろいろあります。
そこで利用したいのが、CocoaのDataFormatter。自然言語風に書かれた「10時41分」(全角数字入り)といった文字列から日時データをピックアップします。
そうして書いたのがこれ(↓)です。
ファイル名に書かれた時刻から実行時刻を拾ってタイマー実行します。けっこう頭がいい感じがします。
実際に、こうした処理の延長線上にTanzakuで行なっているファイル名から取得した文字列に対する形態素解析&コマンドピックアップの処理があります。
AppleScript名:10時42分 |
use AppleScript version "2.5" use scripting additions use framework "Foundation" property targTime : missing value property timerInterval : 1 on run set timerInterval to 1 –Get filename from this applet set myPath to path to current application tell application "System Events" set myName to name of myPath end tell –Validate filename as a natural language format date by using NSDataDetector set dList to getDatesIn(myName) of me repeat while dList = {} set myName to text returned of (display dialog "There is no time elements in my filename. Input the target time in x時xx分" default answer "午後5時45分") set dList to getDatesIn(myName) of me end repeat set targDate to first item of dList set targTime to time string of targDate display notification targTime end run on idle set curTime to current date set curTimeStr to time string of curTime if curTimeStr ≥ targTime then activate display dialog "It’s time to take off!" buttons {"OK"} default button 1 giving up after 30 quit end if return timerInterval end idle on getDatesIn(aString) set anNSString to current application’s NSString’s stringWithString:aString set {theDetector, theError} to current application’s NSDataDetector’s dataDetectorWithTypes:(current application’s NSTextCheckingTypeDate) |error|:(reference) set theMatches to theDetector’s matchesInString:anNSString options:0 range:{0, anNSString’s |length|()} set theResults to theMatches’s valueForKey:"date" return theResults as list end getDatesIn |