Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

タグ: 10.13savvy

display location Script Library

Posted on 8月 25, 2019 by Takaaki Naganoya

指定の緯度・経度情報の場所を4つの異なる表示倍率の地図でダイアログ表示するAppleScriptライブラリ+呼び出しサンプルです。

–> Download display location.scptd (To ~/Library/Script Libraries/)

サンプルScriptでは、指定のIPアドレスの位置情報をipinfo.io上で調べて表示しています。

本ライブラリは、掲載サンプルのように「display multiple map」コマンドを提供するもので、地図.appに頼らずにAppleScriptだけで簡単な地図表示UIを利用できるようにします。

AppleScript名:display location sample
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/25
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
use dispLoc : script "display location"

property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSJSONSerialization : a reference to current application’s NSJSONSerialization
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding

set anIP to "193.228.57.200"
set locList to getGeoLocationByIPinfo(anIP) of me

display multiple map main message "侵略場所の表示" sub message "今回の地球侵略の目的地は、地球上の以下の場所になります" with location locList with size {900, 600}

–http://ipinfo.io/developers
on getGeoLocationByIPinfo(myIP)
  set aURL to "http://ipinfo.io/" & myIP
  
set aRes to callRestGETAPIAndParseResults(aURL, 10) of me
  
  
if aRes = missing value then
    error "Network Error"
  end if
  
set aInfo to loc of aRes
  
set aPos to offset of "," in aInfo
  
set aLatitude to text 1 thru (aPos – 1) of aInfo
  
set aLongitude to text (aPos + 1) thru -1 of aInfo
  
  
return {aLatitude, aLongitude}
end getGeoLocationByIPinfo

on callRestGETAPIAndParseResults(reqURLStr as string, timeoutSec as integer)
  set tmpData to (do shell script "curl -X GET \"" & reqURLStr & "\"")
  
set jsonString to NSString’s stringWithString:tmpData
  
set jsonData to jsonString’s dataUsingEncoding:(NSUTF8StringEncoding)
  
set aJsonDict to NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
if aJsonDict = missing value then return false
  
return (aJsonDict as record)
end callRestGETAPIAndParseResults

★Click Here to Open This Script 

Posted in geolocation GUI JSON Network sdef URL | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

choose multiple path Script Library

Posted on 8月 25, 2019 by Takaaki Naganoya

NSPathControlで複数のファイルパス入力ダイアログを表示して選択パスを受け付けるAppleScript Librariesです。

–> Download choosePathLib.scptd(~/Library/Script Libraries)

AppleScript名:choose path のサンプル
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/24
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use choosePath : script "choosePathLib"

set mesList to {"移動元1", "移動先1", "移動元2", "移動先2"}
set defaultLocList to {"~/Movies", "~/Desktop", "~/Documents", "~/Library"}

set cRes to choose multiple path main message ¬
  "メインメッセージ" sub message ¬
  
"サブメッセージ" with titles mesList ¬
  
with default locations defaultLocList

–> {alias "Macintosh HD:Users:me:Desktop:mathfuncs.png", alias "Macintosh HD:Users:me 1:Desktop:PDF Page composer test.scpt", alias "Macintosh HD:Users:me:Desktop:dTEST.pdf", alias "Macintosh HD:Users:me:Desktop:aTEST2.pdf"}

★Click Here to Open This Script 

Posted in dialog File path GUI | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

displayTextView Script Library

Posted on 8月 24, 2019 by Takaaki Naganoya

テキストビューでテキストを表示するAppleScriptライブラリです。

–> Download displayTextView.scptd (To ~/Library/Script Libraries)

表示するテキスト、フォント名、サイズ、テキストビューの幅と高さを指定してアラートダイアログで表示を行います。ただそれだけです。

AppleScript名:display text view library sample AppleScript
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/24
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use radioLib : script "displayTextView"

set aStr to do shell script "cal 2019"

display text view aStr main message "Main Message" sub message "Sub Message" with properties {font name:"Courier", size:13, width:600, height:600}

★Click Here to Open This Script 

Posted in GUI OSA sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

JavaScriptCore経由で関数計算を行うcalcLibASをアップデート

Posted on 8月 23, 2019 by Takaaki Naganoya

関数計算機能をAppleScriptに提供するAppleScriptライブラリ「calcLibAS」をアップデートしてみました。

変更点:
 ・sdefを書いたので、各種関数が予約語で呼び出せるようになった

だけです。

–> Download calcLibASv1.5 (To ~/Library/Script Libraries/)

さまざまな関数計算の機能をAppleScriptに提供するモジュールと比べてもサポート関数の数が多く、さらに本ライブラリは単にJavaScriptCoreの関数計算機能を変換しているだけなので、ライブラリ内で計算は一切していません。

技術的に何も見るべき点がなく、高度なテーマに一切挑戦していないのに、大量の数値関数の機能を提供しているのが本ライブラリの特徴です。志の低さでは他に類を見ないレベルですが、実際に稼働して役に立っています。

本来はCephes Math Library(関数36個ぐらい)あたりをラッピングしようと考えていたのですが、JavaScriptCore経由でJavaScript(おそらくCephes Math Libraryをラッピング)の関数を呼び出してもほぼ同数の関数が使えることが判明したため、3時間ぐらいで作ってみたのがはじまりです。当初のバージョンはJXAで記述した計算ルーチンを呼び出していましたが、JXAが頻繁にクラッシュしたため、JavaScriptCoreを呼び出すように変更・高速化(最初のバージョンから28倍速)しました。

ハンドラ呼び出しとsdefによる予約語を通じて関数計算した場合で、計算精度などに差は出ていないことを内部の検証コマンドで確認してあります。

メンテナンスしやすいように、sdefからの呼び出しサービスを行うライブラリと実際の計算(呼び出し)を行うCoreライブラリの2つの部品に分けています。機能本体部分にsdefで定義した予約語を使うと、メンテナンスも何もできなくなるというapplescript-stdlibを反面教師とし、さらにsdefからの呼び出し部分がパラメータのチェックや例外処理への対応などで容易に機能がふくれあがっていくため、メンテナンス性を確保するためにこのような構造にしました。

log関数については、すでにAppleScriptビルトインで、まったく異なる働きを行うlogコマンド(スクリプトエディタ/Script Debuggerのログ表示機能でログ表示)があるので、重複を避けるためにsdef定義でlogarithmと表記するようにしました。

roundも同様にsdef定義でroundNumと表記しています。

実際に、三角関数やatan2などの関数を使い出していますが、精度や挙動、実行速度などに前バージョンから差異はありません。AppleScript用語の予約語がついて呼びやすくなっただけです。

AppleScript名:Every Functions
— Created 2019-08-20 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use calSub : script "calcLibAS"

set a001 to abs -10
set a002 to acos -1
set a003 to acosh 10
set a004 to asin 10
set a005 to asinh 10
set a006 to atan 10
set a007 to atan2 {10, 20}
set a008 to atanh 10
set a009 to cbrt 3
set a010 to ceil 0.95
set a011 to clz32 1
set a012 to cos 1
set a013 to cosh 1
set a014 to exp 1
set a015 to expm1 -1
set a016 to floor 45.95
set a017 to fround 1.337
set a018 to hypot {3, 4, 5}
set a019 to lmul {2, 5}
set a020 to logarithm 10
set a021 to log10 2
set a022 to log1p 1
set a023 to log2 3
set a024 to max {1, 2, 3, 4, 6, 2, 10}
set a025 to min {1, 2, 3, 4, 6, 2, 10, 0}
set a026 to pow {7, 2}
set a027 to rnd –random number
set a028 to roundNum 5.95
set a029 to sign 10
set a030 to sin (pi / 2)
set a031 to sinh 1
set a032 to sqrt 2
set a033 to tan 30
set a034 to tanh 10
set a035 to trunc 13.37

set aList to {a001, a002, a003, a004, a005, a006, a007, a008, a009, a010, a011, a012, a013, a014, a015, a016, a017, a018, a019, a020, a021, a022, a023, a024, a025, a026, a027, a028, a029, a030, a031, a032, a033, a034, a035}

return test() of calSub –Check function to calc from sdef and each handlers excepting random numbers

★Click Here to Open This Script 

AppleScript名:Calc direction from place A to B
— Created 2019-08-20 by Takaaki Naganoya
— 2017-2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use script "calcLibAS"

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)
  set deltaLong to (longitude of coord2) – (longitude of coord1)
  
set yComponent to sin deltaLong
  
set xComponent to (cos (latitude of coord1)) * (sin (latitude of coord2)) – (sin (latitude of coord1)) * (cos (latitude of coord2)) * (cos deltaLong)
  
  
set radians to (atan2 {yComponent, xComponent}) as real
  
set degreeRes to (radToDeg(radians) of me)
  
  
return degreeRes
end calcDirectionBetweenTwoPlaces

on radToDeg(aRadian)
  return aRadian * (180 / pi)
end radToDeg

★Click Here to Open This Script 

AppleScript名:日本測地系から世界測地系への座標変換.scpt
— Created 2018-07-13 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use math : script "calcLibAS"

set jpLat to 42.16593046887
set jpLng to 142.771877437246

set {wdLat, wdLng, wdH} to JapanGeodeticSystem’s convertIntoWgs(jpLat, jpLng)
–>  {​​​​​42.168504277889, ​​​​​142.768075650137, ​​​​​61.914452206343​​​}

–https://altarf.net/computer/ruby/3347
–日本測地系から世界測地系に換算
script JapanGeodeticSystem
  –ラジアン(度)
  
property rdNum : pi / 180
  
  
–日本測地系の定数(ベッセル楕円体)
  
property rJP : 6.377397155E+6 –赤道半径
  
property fJP : 1 / 299.1528128 –扁平率
  
property e2JP : (2 * fJP) – (fJP * fJP) –第一離心率
  
  
–世界測地系の定数(WGS84)
  
property rWS : 6.378137E+6 –赤道半径
  
property fWS : 1 / 298.257223563 –扁平率
  
property e2WS : (2 * fWS) – (fWS * fWS) –第一離心率
  
  
–並行移動量(m)
  
property dxNum : -148
  
property dyNum : 507.0
  
property dzNum : 681.0
  
  
–楕円体高
  
property heightNum : 0
  
  
  
–日本測地系から世界測地系に変換する
  
on convertIntoWgs(aLat, aLong)
    set {x, y, z} to llh2xyz(aLat, aLong, heightNum, rJP, e2JP, rdNum) of me
    
    
set x to x + dxNum
    
set y to y + dyNum
    
set z to z + dzNum
    
    
set {lat1, lng1, h1} to xyz2llh(x, y, z, rWS, e2WS, rdNum) of me
    
return {lat1, lng1, h1}
  end convertIntoWgs
  
  
  
–座標系の変換(緯度経度 -> xyz)
  
on llh2xyz(latLocal, lngLocal, hLocal, aLocal, e2Local, rdLocal)
    set latLocal to latLocal * rdLocal
    
set lngLocal to lngLocal * rdLocal
    
    
set sbNum to sin latLocal
    
set cbNum to cos latLocal
    
    
set rnLocal to aLocal / (sqrt (1 – e2Local * sbNum * sbNum))
    
    
set xLocal to (rnLocal + hLocal) * cbNum * (cos lngLocal)
    
set yLocal to (rnLocal + hLocal) * cbNum * (sin lngLocal)
    
set zLocal to (rnLocal * (1 – e2Local) + hLocal) * sbNum
    
    
return {xLocal, yLocal, zLocal}
  end llh2xyz
  
  
  
–座標系の変換(xyz -> 緯度経度)
  
on xyz2llh(x, y, z, a, e2, rdLocal)
    set bda to sqrt (1 – e2)
    
set p to sqrt (x * x + y * y)
    
set t to atan2 {z, p * bda}
    
set stNum to sin (t)
    
set ctNum to cos (t)
    
set b to atan2 {z + e2 * a / bda * stNum * stNum * stNum, p – e2 * a * ctNum * ctNum * ctNum}
    
    
set l to atan2 {y, x}
    
set sb to sin (b)
    
set rn to a / (sqrt (1 – e2 * sb * sb))
    
set h to p / (cos (b)) – rn
    
set l1 to b / rdLocal
    
set l2 to l / rdLocal
    
return {l1, l2, h}
  end xyz2llh
  
end script

★Click Here to Open This Script 

AppleScript名:Circulate Finder windows
— Created 2014-11-17 by Takaaki Naganoya
— Modified 2019-08-18 by Takaaki Naganoya
— 2014-2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit" — for NSScreen
use calLib : script "calcLibAS"

property aNum : 300
property aOffset : 0
property maxWin : 6
property winList : {}
property randList : {}
property winSize : 300

–Initialize
set winList to {}
set randList to {}

repeat maxWin times
  tell application "Finder"
    activate
    
set aWin to make new Finder window
    
    
tell aWin
      set toolbar visible to false
      
set sidebar width to 0
      
set statusbar visible to false
      
set position to {100, 100}
      
set bounds to {100, 100, 100 + winSize, 100 + winSize}
    end tell
    
    
set the end of winList to aWin
    
set the end of randList to {random number from 0 to 400, random number from 0 to 400, random number from 1 to 360}
    
  end tell
end repeat

–Main
repeat with i from 1 to 360 by 6
  
  
repeat with ii from 1 to maxWin
    
    
set aWinObj to contents of item ii of winList
    
set {aRandX, aRandY, aRandDegree} to item ii of randList
    
    
set aDeg to i + aRandDegree
    
    
set aSinNum to (sin aDeg) as real
    
set aCosNum to (cos aDeg) as real
    
    
set x to ((aNum * aSinNum) + aNum) * 2 + aOffset
    
set y to (aNum * aCosNum) + aNum + aOffset
    
    
ignoring application responses
      tell application "Finder"
        tell aWinObj
          set position to {(x as integer) + aRandX, (y as integer) + aRandY}
        end tell
      end tell
    end ignoring
    
  end repeat
  
end repeat

–Sweep
tell application "Finder"
  repeat with i in winList
    tell i
      close
    end tell
  end repeat
end tell

★Click Here to Open This Script 

AppleScript名:2点間の距離を求める(地球を球体として計算)
— Created 2019-08-22 by Takaaki Naganoya
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use script "calcLibAS"

property earth_radius : 6378140

set aPoint to {lat:35.7398693, long:139.6474103}
set bPoint to {lat:31.5719562, long:130.56257084}
set aRes to calcDistanceBetweenTwoPoint(aPoint, bPoint) of me

on calcDistanceBetweenTwoPoint(aPoint, bPoint)
  set lat1 to lat of aPoint
  
set lng1 to long of aPoint
  
set lat2 to lat of bPoint
  
set lng2 to long of bPoint
  
  
–緯度経度をラジアンに変換
  
set rlat1 to lat1 * pi / 180
  
set rlng1 to lng1 * pi / 180
  
  
set rlat2 to lat2 * pi / 180
  
set rlng2 to lng2 * pi / 180
  
  
— 2点の中心角(ラジアン)を求める
  
set a to (sin rlat1) * (sin rlat2) + (cos rlat1) * (cos rlat2) * (cos rlng1 – rlng2)
  
set rr to acos a
  
  
–2点間の距離(メートル)
  
set distance to earth_radius * rr
  
  
return distance
end calcDistanceBetweenTwoPoint

★Click Here to Open This Script 

Posted in Number sdef | Tagged 10.12savvy 10.13savvy 10.14savvy Finder | 6 Comments

画面上の指定座標にマウスカーソルを強制移動させてクリック

Posted on 8月 22, 2019 by Takaaki Naganoya

マウスカーソルを指定座標に強制的に移動させて、マウスクリック(プレス)を行う補助アプリケーション+呼び出しAppleScriptです。

# ご注意:マウスカーソルの移動やクリックを行うのは、本来のAppleScriptの処理ではありません
# ご注意:他のマシン上で同じ動作を再現することが(初心者には)難しいため、おすすめしません

# 本ツールはCodeSignしてMac App Storeで近日リリースする予定です

必要悪! 画面上の部品や座標をクリックする機能

マウスカーソルの強制移動とクリックは、AppleScriptではなるべく避けるべき操作ですが、ごく一部の操作を実行するため、ごくごくまれに必要になることがあります。

macOS標準装備のAppleScript専用のツール「System Events」に「click」コマンドがあり、指定のGUI部品か、あるいは画面上の座標をクリックするようになっています。

ただし、これはあくまで「指定のGUI部品や指定座標をクリックしたというメッセージ」を対象(アプリケーション)に送るというものであり、実際にマウスカーソルを移動させてクリックを実行するものではありません。

強制マウス操作ツールの歴史

それでも、アプリケーションがAppleScriptに対して機能を解放していない機能を呼び出す必要があって、かつ、メニューやボタンのクリックなどで実行できないような場合には、止むを得ず指定座標のクリックをごくまれに行うことがあります(1年に1度ぐらいの頻度)。


▲強制的にマウスカーソルを移動させてクリックする支援ツールの変遷

これまで、Framework呼び出しでこれらの動作を行ってきましたが、macOS 10.14で(SIPを解除しないかぎり)スクリプトエディタ上ではサードパーティのFrameworkを呼べなくなりました(AppleScriptドロップレット上ではバンドル内のFrameworkを呼べます)。

呼び出し側から一番簡単に利用できる方法は、指定座標のクリック機能を持つアプリケーションをXcode上でAppleScriptで作成しておき、sdefを定義して、AppleScript対応アプリケーションをAppleScriptで作るものです(豆腐をすりつぶして「ひろうす」を作るようなこの迂遠さ。Google翻訳で絶対に伝わらないニュアンス。パンをすりつぶしてパンを作るような、、、)。

そのため、いままでFrameworkで運用してきたプログラムを、アプリケーション化してsdefを付加し、スクリプタブルなバックグラウンドアプリケーション(Dockに表示されない、メニューやウィンドウが表示されない)にする必要が出てきます(まんまとAppleにタダ働きさせられているような気がするので気分はよくありませんが)。

自分ではほとんど使わないマウス強制移動&クリックツールを作ってみた

そこで、sdef(AppleScript用語辞書)をつけたライブラリやアプリケーションを作る方向で調査を行っていました。実際にパラメータの受け渡しをどのように行えるのか、どのあたりでハマるのか、どのぐらいの作業量になるのか。

その1つの到達点として、この補助アプリケーション「mouseClick」を作ってみました。バックグラウンド実行専用のため、起動してもDockにアイコンは表示されません(これを知らないユーザーがバックグラウンド起動専用のアプリケーションに、Mac App Sroreでいちゃもんをつけているのを見かけて、遠い目になりました)。

–> Download mouseClick.app (To /Applications)

※ このツールは、AppleScriptからコマンドで操作する専用のものであり、画面上には何も表示されません。

簡単なAppleScriptでマウスカーソルの移動とクリックを実行できます。初回実行時はシステム環境設定の「セキュリティとプライバシー」>「プライバシー」>「アクセシビリティ」でmouseClickに「コンピュータの制御を許可」しておく必要があります(管理者権限が必要、2回目以降は操作不要)。

forceClickでは、画面の左上を原点とした座標系を使用しています。

呼び出し側と実行側をすべてAppleScriptで組めるようになったわけで、Classic MacOS時代からこの手の「指定座標の強制クリック系ソリューション」を(止むを得ず)使ってきた身からするとなかなか感慨深いものがあります。

参考文献:
objective c 入門 CocoaアプリケーションにAppleScriptサポートを追加するにはどうすればよいですか?

AppleScript名:force click sample
tell application "mouseClick"
  force click at {4, 4} –click apple menu
end tell

★Click Here to Open This Script 

Posted in GUI Scripting list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy 10.15savvy | 2 Comments

Script Editor, Script Debuggerから選択範囲の情報を取得

Posted on 8月 19, 2019 by Takaaki Naganoya

スクリプトエディタ(Script Editor)およびScript Debuggerの最前面の書類から選択範囲の情報を取得するAppleScriptです。

スクリプトエディタとScript Debuggerで動く共通のツールをAppleScriptで作ってみたら、結果が異なりました。両エディタで同じ範囲を選択してみても、


▲Script Editor上で選択(左)、Script Debugger上で選択(右)

Script Editorでは、character range of selectionを実行すると、{文字開始位置, 文字終了位置}を返してきます。

一方、Script Debuggerでは、character range of selectionを実行すると、{文字開始位置, 選択文字長}を返してきます。

この違いにより、両エディタで異なる結果が得られたのでした。

選択中のテキスト(contents of selection)をそのまま取得して処理するのはよくあるパターンです。選択範囲を数値で取得するケースは(個人的に)あまりありませんでした。

これらのエディタ上で選択中のAppleScriptソースを取得して、そのままコンパイル(構文確認)して変数のみ抽出して変数名の一覧リストが欲しかったのですが、部分的にコンパイル(構文確認)しただけではエラーになる例が多い(ライブラリを呼び出している場合とか)ので、ファイル全体をコンパイル(構文確認)したのちに、エディタ上の選択範囲に該当するデータを抽出するように変更してみました。


▲選択範囲からAppleScript構文色分け情報をもとに変数のみ列挙して返すAppleScriptを実行。このために両エディタ対応を調べていた

AppleScript名:Ecript Editorの選択範囲情報を取得.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/19
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
tell application "Script Editor"
  tell front document
    set {cStart, cEnd} to character range of selection –{start pos, end pos}
    
return {cStart, cEnd}
    
–> {516, 1334}
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:Script Debuggerの選択範囲情報を取得
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/19
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
tell application "Script Debugger"
  tell front document
    set {cStart, cNums} to character range of selection –{start pos, length}
    
return {cStart, cStart + cNums – 1}
    
–> {516, 1335}
  end tell
end tell

★Click Here to Open This Script 

Posted in list Text | Tagged 10.12savvy 10.13savvy 10.14savvy Script Debugger Script Editor | Leave a comment

checkboxLibをアップデート(3)sdefにサンプルドキュメントを入れる

Posted on 8月 15, 2019 by Takaaki Naganoya

AppleScript Libraries(共有ライブラリ。以下ASLと略)にsdef(Script辞書)をつけて、AppleScriptや他のOSA言語との間で共通して呼び出し可能なライブラリを書くシリーズの続きです。

単なるASLにsdefを付けて、各種OSA言語からの呼び出しに対応するようにしてみました。さらに、パラメータの省略や別表記のゆらぎを許容するようにしてみました。

総仕上げで、Script用語辞書の中にドキュメントをHTMLで表記し、サンプルScriptをワンクリックでスクリプトエディタに転送されるようにしてみましょう。

最近、AppleScript用語辞書の中に表や資料が記載されているものがあります。それらは、sdef中にdocumentationタグで書かれているものです。documentationタグ内にはhtmlタグが記載されており、この中にHTMLで書かれたコンテンツが格納されています(ただ漫然と文字列で書いてあるだけですけれども)。

ここに、applescript://リンクつきのサンプルが掲載されていることもあるのですが、なぜかApple純正アプリケーションではサンプルそのものが間違っていたりして驚かされます(動作確認ぐらいしようよ)。また、見た目がスクリプトエディタのデフォルト色分けそのままで美しくありません。

そこで、本Blog掲載時に使用しているHTML書き出しプログラムを使用して、applescript://リンクつきのサンプルを掲載してみましょう。

ずいぶん見やすくなりましたし、サンプルがすぐに試せるのはいいと思います。

これによってsdefのサイズが大きくなってしまいました(2–> 10 KB)。sdefはAppleScript記述・構文確認時のテンプレートとしても、実行時のデータとしても使われるので、サイズが大きくなるとこれをparseするのに余計な時間がかかるため、あまり大きくしたくないという開発側の事情もあります。


▲InDesign CCの巨大なAppleScript用語辞書。たぶん、Adobeはまともにメンテナンスできていない

巨大な用語辞書を持つアプリケーションでは、改行コードすら削除してサイズを小さくしようとしているぐらいであり、フレンドリーなドキュメントを内包することが唯一にして無二のソリューション「ではない」ことも知っておくべきでしょう(実行速度低下というデメリットもあるので)。

ただ、sdefから改行コードを削除してサイズを小さくするというのは、CPUの実行速度が遅かった頃のノウハウであり、いまでも本当にそれが必要なのかは疑問です。実際、Keynote、Pages、Numbersなど比較的あたらしめの(それほど機能が多くない)アプリケーションでは「まっとうに読める。改行つき、インデントつき」sdefが格納されています。

Posted in sdef | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

checkboxLibをアップデート(2)

Posted on 8月 15, 2019 by Takaaki Naganoya

AppleScript Libraries(共有ライブラリ。以下ASLと略)にsdef(Scirpt辞書)をつけて、AppleScriptや他のOSA言語との間で共通して呼び出し可能なライブラリを書くシリーズの続きです。

単なるASLでは、AppleScript側からしか呼び出せません。そこで、sdefを書いて指定することで、より運用性を高められるのではないかと考え、実際に簡単な(素朴な内容の)ライブラリで実験してみました。

–> Download checkboxLib_v3.scptd(To ~/Library/Script Libraries)

コマンドが1つだけ。パラメータがいくつか。AppleScript側から呼び出す場合にはパラメータの省略ができるが、JXA側からは省略できないといった状態のライブラリで、普通に使っている分には問題を感じませんでした。

一方で、sdefについて調べはじめるといろいろ情報が集まってくるもので、ここ数日で急速にsdef記述のためのノウハウがたまってきました。sdefをいままでに一度も書いたことがないわけではありませんが、必要最低限の情報だけ集めて書いてオシマイという程度の「割り切った関係」というのでしょうか。それほど真剣に付き合ったことはなかったわけです。

一応、研究用にすべてのアプリケーションのsdefファイルは取り出して参照できるように収集していますが、カラスが光りものを集めて埋めておくのとほとんど差はありませんでした。HTMLに書き出したsdefについては、バージョン間の差異を検出するために有効活用していますが、sdefそのものを見せられてもあまり実用性がありませんでした。

sdefを書くことが要求仕様に出される案件がほとんどないので(1件だけあったかも)、Scripter側でも「別に普通にハンドラ呼べばいいだろ」というぐらいの認識であり、sdefを年がら年中書いているSctipterというのはほとんどいないように見えます(海外でも)。

予約語に「ゆらぎ」を許容する

いちいち予約語を正確にすべて覚えている人などいません。書いた本人ですら「こういう書き方でも認識すればいいのに」と考えがちです。そこで、入力時に別表記で入力しても、構文確認(コンパイル)時に正しい予約語に変換するSynonymを定義しておきましょう。

チェックボックスの形状を「standard」と「flat」の予約語で指定できるようにしてありますが、「standard」という予約語がすぐに思い出せないとスクリプトエディタ上で用語を確認する必要があります(そもそも、スクリプトを書くときに用語辞書を表示させないことなどないのですが)。

そこで、コマンドのパラメータ指定部分で、

<parameter name="checkbox type" type="checkbox types" code="COLC" description="checkbox type"/>

タイプに「checkbox types」を指定。この定数checkbox typesの定義部分に、同一視する単語を列挙しておきます。

<enumeration name="checkbox types" code="enu1">
	 <enumerator name="standard" code="cstd" description="Standard Checkbox">
		<synonym name="checkbox"/>
		<synonym name="normal"/>
		<synonym name="as usual"/>
</enumerator>

checkbox typeの指定パラメータ(定数)に、「checkbox」「normal」「as usual」などが書かれても、これらを「standard」と同一視して、構文確認時に「standard」に書き換えます。


▲実際にスクリプトエディタ上でSynonymが表示されている(Synと省略)

パラメータの省略許容指定(optional)

現在のバージョン(v2)のcheckboxLibでは、パラメータの省略をAppleScript側では行えます。JXAやその他のOSA言語では行えません。

パラメータを指定したくない、あるいは無指定時にはデフォルト値で処理してくれるのがベストです。逆に、省略を許容しないコマンドなんて悪夢です。

そこで、省略可能を指示する「optional」をsdefに書いてみました。

<command name="choose checkbox" code="LCCBCCKB" description="Display checkbox list with an alert dialog">
	<parameter name="main message" type="text" code="CMMS" description="Main title of an alert dialog"/>
	<parameter name="sub message" type="text" optional="yes" code="CSMS" description="Sub title of an alert dialog"/>
	<parameter name="with columns" type="integer" optional="yes" code="CSCS" description="Column number of display checkbox"/>

	<parameter name="with titles" code="COLL" description="Titles of every checkbox">
		<type type="text" list="yes"/>
            </parameter>
	<parameter name="checkbox type" type="checkbox types" optional="yes" code="COLC" description="checkbox type"/>
	<parameter name="return type" type="return types" optional="yes" code="COLR" description="return data type"/>
</command>

これで、AppleScriptからでもJXAからでも(省略可能な)パラメータを省略できるようになりました。

コマンドのパラメータで「[」「]」で囲まれているのが省略可能なものです(左:AppleScript、右:JavaScript)

AppleScript名:check box sample 4_e
— Created 2019-08-12 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"

set tList to {"Carrot", "Burdock", "Radish", "Apple", "Cabbage", "Lettuce", "Potato", "Garlic", "Komatsuna", "Bok choy", "Shiitake mushroom", "Hen of the Woods"}
set cRes to choose checkbox main message "Select Vegetables" with titles tList

★Click Here to Open This Script 

JavaScript名:sample_jxa_5
// Created 2019-08-12 by Takaaki Naganoya
// 2019 Piyomaru Software
var app = Application.currentApplication()
app.includeStandardAdditions =
true
var alib = Library("checkboxLib")

var array = ["Carrot", "Burdock", "Radish", "Apple", "Cabbage", "Lettuce", "Potato", "Garlic", "komatsuna", "Bok choy", " Shiitake mushroom", "Hen of the Woods"]

alib.chooseCheckbox(
{
    mainMessage:"Select Vegetables",
    withTitles:array
  }
)

★Click Here to Open This Script 

Posted in JXA sdef | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | 1 Comment

checkboxLibをアップデート

Posted on 8月 13, 2019 by Takaaki Naganoya

昨日作ったAppleScriptライブラリ「checkboxLib」をアップデートしてみました。

–> Download checkboxLib_v2.scptd(To ~/Library/Script Libraries)

JXAからの呼び出しに対応(1)〜data typeの記述を正しく

昨日のバージョンは問題が見つかっていました。AppleScriptから呼び出す分には問題がなかったのですが、JXAから呼び出すとエラーになっていました。

sdef(AppleScript用語辞書)をつけたライブラリは、AppleScriptで記述しつつも従来のOSAXのような運用が可能で、とりわけ他のOSA言語からも使える共有モジュールとして運用できる点が重要です。

今日明日ですぐに必要になるわけではありませんが、AppleScriptで記述したライブラリにsdefさえ添付しておけば、JXA側からも呼び出せる共有モジュールとして運用できる「ことになっています」。それがOSA(Open Scripting Architecture)上でのAppleScript Librariesの設計思想です。

そのため、JXA側からの呼び出しもテストしていたのですが、なかなかお題目どおりには行かず、ちょっとMacScripter.netのBBSで相談して、対処を行ってみました。

sdefを書くにあたっては、既存のアプリケーションの膨大なsdefのストックがあるので、それを参考にしていました(たまに記述が間違っているものがあって困ります)。

その中で、データタイプにAppleScriptでしか利用できない「list」というタイプを指定していたのが問題でした。つまり、AppleScript側からの呼び出しだけで検証していては、AppleScriptからの呼び出し時だけ正常に動く「バグ」を抱えたままの状態である可能性を否定できません。他のOSA言語からの呼び出しも検証しておかないと、潜在バグのあぶり出しが行えません。

 <parameter name="with titles" type="list" code="COLL" description="Titles of every path"/>

これをShaneのアドバイスどおりに書き換えて、

 <parameter name="with titles" code="COLL" description="Titles of every checkbox">
      <type type="text" list="yes"/>
 </parameter>

と、修正。これで、JXA側からも呼び出せるようになりました。

AppleScript名:check box sample 4_e
— Created 2019-08-12 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"

set tList to {"Carrot", "Burdock", "Radish", "Apple", "Cabbage", "Lettuce", "Potato", "Garlic", "Komatsuna", "Bok choy", "Shiitake mushroom", "Hen of the Woods"}

set cRes to choose checkbox main message "Select Vegetables" sub message "Select vegetables you like" with columns 2 with titles tList checkbox type standard return type data

★Click Here to Open This Script 

JavaScript名:sample_jxa_4
// Created 2019-08-12 by Takaaki Naganoya
// 2019 Piyomaru Software
var app = Application.currentApplication()
app.includeStandardAdditions =
true
var alib = Library("checkboxLib")

var array = ["Carrot", "Burdock", "Radish", "Apple", "Cabbage", "Lettuce", "Potato", "Garlic", "komatsuna", "Bok choy", " Shiitake mushroom", "Hen of the Woods"]

alib.chooseCheckbox(
{
    mainMessage:"Select Vegetables",
    subMessage:
"Select vegetables you like",
    withColumns:
2,
    withTitles:array,
    checkboxType:
"standard",
    returnType:
"item number"
  }
)

★Click Here to Open This Script 

JXAからの呼び出しに対応(2)〜enumをそのまま処理しない

とりあえず予定していた機能は実現できたわけですが、sdefにenum(定数)を定義して使ってみたくなりました。パラメータをダイレクトパラメータ(文字列、数字など)のみで指定するだけは不満が出てきそうです。

かくして、「こんな感じかな?」と手探りでenumを定義してみたのですが、例によってAppleScript側ではエラーにならないのに、JXA側ではエラーになりました。

結局、ライブラリ側のパラメータ受信部分でenumをそのまま処理せず、いったん文字列に変換して処理するようにしてみました。

いずれも、AppleScript側だけだとエラーになりませんでしたが、JXA側からの呼び出しもできるようにしておけば、他のOSA言語やObjective-C/Swiftなどの言語からの呼び出し時にも問題が出ないことでしょう。現状でJXAの存在意義はその程度です。

JXAからのライブラリ呼び出しについては、現行バージョンでもパラメータの省略時にエラーが出るのですが、「パラメータの省略はできないもの」と割り切っても問題はなさそうです。

最終的にsdefは上記(↑)のようになりました。enumの宣言部分の書き方がこなれていなかったので、その部分を修正。このsdefをスクリプトエディタでレンダリングすると、このようになります。

■参考文献リンク
Technical Note TN2106 Scripting Interface Guidelines

Posted in JXA OSA sdef | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | 1 Comment

checkboxで項目選択するありふれたScriptにsdefをつけてみる

Posted on 8月 12, 2019 by Takaaki Naganoya

アラートダイアログにcheckboxを表示して、項目選択するAppleScriptにsdef(AppleScript用語辞書)をつけてみました。

内容は、先日書いた「アラートダイアログ上にcheckboxを表示 v2」そのものです。この手のScriptは、機能の割に行数が多くて、そんなに難しくない(単にCocoaの仕様にもとづいて書いているだけ)んですが、コード量が多いことで難しそうに見えてしまうとしたら残念です。sdefをつけて英語っぽい記法で簡潔に呼び出せると有用性がどのぐらい増すのか実験してみました。

–> Download checkboxLib.scptd(with sdef)

Step 1:普通に動作するAppleScriptをバンドル形式で保存

アラートダイアログ上にcheckboxを表示 v2が動作しているのを確認します。また、フラットな(バンドルではない)AppleScript(拡張子:.scpt)の場合には、バンドルScript(拡張子:.scptd)に変換します。

また、この際にバンドルIDをきっちり設定しましょう。

Step 2:sdefファイルを作成する

テキストエディタでsdefファイルを書いてみましょう。他のAppleScript対応アプリケーションのsdefファイルを参考にします。構文色分け機能のあるテキストエディタの場合(CotEditorなど)、XMLを指定しておくと色分けされるので間違いが少なくなることでしょう。

こんな感じに書いてみました。コマンド1つに、パラメータが4つ。sdefファイルを書いて、AppleScriptバンドル内(/Contents/Resources フォルダ)にコピーし、スクリプトエディタ上やScript Debugger上でsdefの名称(拡張子は省略)を「スクリプティング定義」の欄に記載します(textを「(text)」と書いていますが、「text」と書くのが正しいので念のため)。

このような変更を行った場合には、保存してスクリプトエディタ/Script Debuggerをいったん終了させると間違いがなくていい感じです。

Step 3:sdefに記述した予約語でハンドラを記述する


sdefファイルに記載した予約語がAppleScriptライブラリ内ですぐに使用できるようになります。ただし、呼び出し部分にだけ使うようにしないと、メンテナンス性が下がりまくる(作者以外誰も読めなくなる)ので注意が必要です。ライブラリ本体の機能をライブラリのsdefで定義した予約語を使いまくって、作者以外誰もメンテナンスできない状態になっているライブラリの実例がこちらで確認できます(applescript-stdlib)。

これで、sdefに記載した予約語を使ってScriptを呼び出せるようになりました。エラーになるようなら、いったんスクリプトエディタ/Script Debuggerを終了させるとよいでしょう(sdefが不完全な場合もありますが)。

— Created 2019-08-12 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"

set tList to {"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}

set cRes to choose checkbox main message "項目選択" sub message "適切なものを以下からえらんでください" with columns 2 with titles tList

★Click Here to Open This Script 

Step 4:パラメータ省略時に対応できるようにハンドラを書き換え

ただ、これだけだと「毎回パラメータをすべて指定しないと動かない」という間抜けライブラリになってしまいます。

そこで、パラメータの型宣言+省略時パラメータの指定を行えば省略に対応できます。パラメータ指定部はすべて省略指定に対応できるように書いておきましょう。

こんなところでしょうか。パラメータのうち必須でないものの省略を許容するためには、sdefでoptionalの指定を行うことも必要です。

この手の「1回書いたらあんまり書き換えないし、使い回しするにはコード量が多くてめんどくさい」処理については、sdefをつけたライブラリにしておくといいのかもしれません。全部が全部、すべてそういう形式にするわけにもいきませんが、自分で予約語を拡張できるようになっているので、使ってみるとよいでしょう。

この段階になって、ライブラリ>Script Library(~/Library/Script Libraries)フォルダに入れてスクリプトの書き換えなどを行っていると、前回書き換えた内容が再オープン時に反映されないといった現象が発生することがあります。書き換えた、保存したはずなのに元に戻っているというのは、ライブラリのキャッシュを別途行っているためということだと理解しました。

なので、ライブラリの書き換えを行うさいには、テキスト形式などで別途ソースを保存しておくことを強くおすすめします。ここだけ、怪奇現象っぽい挙動に直面するところですが、焦らず慌てず作業すれば「単なる作業」なので、難しくありません。

AppleScript名:check box sample 2
— Created 2019-08-12 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"

set tList to {"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}

set cRes to choose checkbox main message "項目選択" sub message "適切なものを以下からえらんでください" with columns 2 with titles tList
set cRes to choose checkbox main message "項目選択" sub message "適切なものを以下からえらんでください" with titles tList
set cRes to choose checkbox main message "項目選択" with titles tList
set cRes to choose checkbox with titles tList
set cRes to choose checkbox

★Click Here to Open This Script 

Posted in dialog GUI sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

MailCore2でメールのeml形式ファイルを読み込んでリンクURL抽出

Posted on 8月 11, 2019 by Takaaki Naganoya

Mail.appからメールを書き出ししたeml形式のファイルをMailCore2 Frameworkで読み込んで、本文(HTML)中に記載されているリンクURLを抽出するAppleScriptです。

eml形式ファイルは、Mail.appからドラッグ&ドロップでメールを書き出したファイルです。書き出し後のファイルはMail.appの管轄ではなく、メールデータはFinderの専門外。AppleScriptではこのeml形式ファイルへのアクセスは一切できず、eml形式ファイルが相手では手も足も出ませんでした。

macOS 10.10でAppleScriptの主要ランタイムでCocoaの機能が利用できるようになり、これまでにアクセスできなかったデータ形式にアクセスできるようになりました。その典型例がこのemlファイルです。

メールの各種データへのアクセスを行えるMailCore2.frameworkを使えば、簡単にこのemlファイル内の各種情報にアクセスできます。

各種Frameworkに甘やかされまくって、HTMLを自力でparseするとかいったことは一切努力しようとしていない今日このごろ。MailCore2でメール本文をいいようにparseし、HTMLReader Frameworkで解釈したHTMLからリンクをひとまかせで抽出しています。

–> Download MailCore.framework
–> Download HTMLReader.framework

–> Downdload emlLinkExtracter (Code-Signed AppleScript Applet with Frameworks within its bundle)

AppleScript名:MailCore2でメールのeml形式ファイルを読み込んでリンクURL抽出
— Created 2017-01-18 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "MailCore" –https://github.com/MailCore/mailcore2
use framework "HTMLReader" –https://github.com/nolanw/HTMLReader

–emlファイルを選択して読み込み
set aPath to POSIX path of (choose file of type {"com.apple.mail.email"})
set fileContents to current application’s NSData’s dataWithContentsOfFile:aPath options:(current application’s NSDataReadingMappedIfSafe) |error|:(missing value)
if fileContents = missing value then return

–メール本文をHTML化
set aParser to current application’s MCOMessageParser’s messageParserWithData:fileContents
set aBody1 to current application’s NSString’s stringWithString:(aParser’s htmlBodyRendering())
set aData to aBody1’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
set aHTML to current application’s HTMLDocument’s documentWithData:aData contentTypeHeader:"text/html"

–HTMLからリンクURLを抽出
set aTextArray to ((aHTML’s nodesMatchingSelector:"a")’s textContent) as list –リンク文字
set aLinkArray to ((aHTML’s nodesMatchingSelector:"a")’s attributes’s valueForKeyPath:"href") as list –URL
–> {"http://peatix.com", … "https://peatix.com/contact"}

★Click Here to Open This Script 

Posted in file | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

アラートダイアログ上にcheckboxを表示 v2

Posted on 8月 11, 2019 by Takaaki Naganoya

アラートダイアログ上にチェックボックスで選択肢の入力を求めるAppleScriptです。


▲macOS 10.14上のLight Mode(Left)、Dark Mode(Right)

ラジオボタンで項目選択を行うのと同じぐらい、チェックボックスで項目選択を行うのは「よくある処理」です。ただ、それだけのためにXcode上でAppleScriptのプログラムを作るのは大袈裟なのと、できることはなるべく普通のAppleScript(Xcode上ではない)のランタイム環境上でできたほうがよいとの考えから、こうして箱庭UIをちまちま作っているものです。

本AppleScriptは、スクリプトエディタ上、スクリプトメニュー、AppleScriptアプレット、Script Debugger上などのランタイム環境で動作します。他のAppleScriptのバンドル中に入れてAppleScript Librariesとして呼び出して使うことを前提に整備してあります。

チェックした項目の番号がリストで返ってきます。各項目番号は1始まり(1-based index)です。


▲「?」ボタン(Help Button)をクリックすると、すべてのチェックボックスをオン/オフにするかを指定できる(ないと不便そうだったので)

ボタンのタイプはいくつか変更して試していますが、このあたりは最近のOSアップデートでいろいろ変更が加わっており、実際に指定しても有意な結果が得られない(なんで存在するのかよくわからない)ものもあり、実際に指定して試してみることをおすすめします。

本Scriptにはいくつか制約事項があります。選択肢の個数が奇数の場合にうやむやにする処理はつけていません。また、選択肢の文字数が長い場合への対処も一切していません。このあたりは真面目にプログラムを組む際には問題になってくることでしょう。


▲NSButtonTypeOnOff


▲NSButtonTypePushOnPushOff


▲NSButtonTypeRadio


▲NSButtonTypeSwitch


▲NSButtonTypeToggle(クリックすると遅れてステートが変化する。なにこれ?)

実際には、ライブラリ化してこんな風に呼び出して使うことを想定しています。

— Created 2019-08-07 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"

set paramObj to {myMessage:"Select target Item", mySubMessage:"適切なものを以下からえらんでください", mySuppression:"", myColNum:2, matrixTitleList:{"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}}
set aRes to dispCheckBoxMain(paramObj) of checkLib
–> {1, 2}

★Click Here to Open This Script 

AppleScript名:アラートダイアログ上にcheckboxを表示 v2
— Created 2019-08-07 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSView : a reference to current application’s NSView
property NSAlert : a reference to current application’s NSAlert
property NSButton : a reference to current application’s NSButton
property NSOnState : a reference to current application’s NSOnState
property NSOffState : a reference to current application’s NSOffState
property NSMutableArray : a reference to current application’s NSMutableArray
property NSButtonTypeSwitch : a reference to current application’s NSButtonTypeSwitch
property NSRunningApplication : a reference to current application’s NSRunningApplication

property theResult : 0
property returnCode : 0
property bArray : {} –Checkbox button object array

on run
  set paramObj to {myMessage:"Select target Item", mySubMessage:"適切なものを以下からえらんでください", mySuppression:"", myColNum:2, matrixTitleList:{"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}}
  
  
–my chooseItemByCheckBox:paramObj –for Debugging
  
my performSelectorOnMainThread:"chooseItemByCheckBox:" withObject:(paramObj) waitUntilDone:true
  
return my sort1DNumList:theResult ascOrder:true
  
–> {1, 3, 5, 7, 9, 11}
end run

on chooseItemByCheckBox:(paramObj)
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set aMatList to (matrixTitleList of paramObj) as list
  
set aLen to length of aMatList
  
set aSupMes to mySuppression of paramObj
  
  
set colNum to (myColNum of paramObj) as integer
  
set rowNum to (aLen div colNum) + (aLen mod colNum)
  
  
set aButtonCellWidth to 150
  
set aButtonCellHeight to 24
  
  
set viewWidth to aButtonCellWidth * colNum
  
set viewHeight to aButtonCellHeight * rowNum
  
  
–define the matrix size where you’ll put the radio buttons
  
set matrixRect to current application’s NSMakeRect(0.0, 0.0, viewWidth, viewHeight)
  
set aView to NSView’s alloc()’s initWithFrame:(matrixRect)
  
  
set aCount to 1
  
set bArray to current application’s NSMutableArray’s new()
  
repeat with y from 1 to rowNum
    repeat with x from 1 to colNum
      if aCount ≤ aLen then
        set j to contents of item aCount of aMatList
        
set tmpB to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum) * aButtonCellHeight, aButtonCellWidth, aButtonCellHeight)))
        
        (
tmpB’s setTitle:j)
        (
tmpB’s setShowsBorderOnlyWhileMouseInside:true)
        (
tmpB’s setTag:(aCount))
        (
tmpB’s setTarget:me)
        (
tmpB’s setAction:("clicked:"))
        (
tmpB’s setButtonType:(NSButtonTypeSwitch))
        
        (
bArray’s addObject:tmpB)
        
      end if
      
      
set aCount to aCount + 1
    end repeat
  end repeat
  
  
–Select the first radio button item
  
–(tmpArray’s objectAtIndex:0)’s setState:(current application’s NSOnState)
  
set theResult to {}
  
  (
aView’s setSubviews:bArray)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aView
    
    
–for Help Button
    
its setShowsHelp:(true)
    
its setDelegate:(me)
    
    
–for suppression check box ( No use for this case? )
    
if (aSupMes as string) is not equal to "" then
      its setShowsSuppressionButton:(true) –「今後このメッセージを表示しない」チェックボックスを表示
      
set suppressionB to its suppressionButton
      
suppressionB’s setTitle:(aSupMes)
    else
      its setShowsSuppressionButton:(false)
    end if
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
  
  
set theResult to (tmpArray’s valueForKeyPath:"status") as list
end chooseItemByCheckBox:

on doModal:aParam
  set (my returnCode) to aParam’s runModal()
end doModal:

on clicked:aParam
  set aTag to (tag of aParam) as integer
  
if aTag is not in (theResult as list) then
    set the end of theResult to aTag
  else
    set theResult to my deleteItem:aTag fromList:theResult
  end if
end clicked:

on deleteItem:anItem fromList:theList
  set theArray to NSMutableArray’s arrayWithArray:theList
  
theArray’s removeObject:anItem
  
return theArray as list
end deleteItem:fromList:

–1D List(数値)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート
on sort1DNumList:theList ascOrder:aBool
  tell current application’s NSSet to set theSet to setWithArray_(theList)
  
tell current application’s NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(missing value, true)
  
set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor}
  
return (sortedList) as list
end sort1DNumList:ascOrder:

–Help Button Clicked Event Handler
on alertShowHelp:aNotification
  set aRes to display dialog "Do you change all checkbox state?" buttons {"All Off", "All On", "Cancel"} default button 3 with icon 1
  
set bRes to (button returned of aRes) as string
  
  
if bRes = "All Off" then
    set bLen to bArray’s |count|()
    
set theResult to {}
    
repeat with i from 0 to bLen
      ((bArray’s objectAtIndex:i)’s setState:(current application’s NSOffState))
    end repeat
    
  else if bRes = "All On" then
    set bLen to bArray’s |count|()
    
set theResult to {}
    
repeat with i from 0 to bLen
      ((bArray’s objectAtIndex:i)’s setState:(current application’s NSOnState))
      
set the end of theResult to i + 1
    end repeat
  end if
  
  
return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする
end alertShowHelp:

★Click Here to Open This Script 

Posted in GUI list | Tagged 10.12savvy 10.13savvy 10.14savvy NSAlert NSButton NSButtonTypeSwitch NSMutableArray NSOffState NSOnState NSRunningApplication NSView | 1 Comment

式評価(eval)を行う

Posted on 8月 7, 2019 by Takaaki Naganoya

文字列で与えられた計算式の評価(計算)を行うAppleScriptです。

計算式の評価(Eval)を行うといえば、AppleScriptではrun scriptで計算式の文字列を実行するとか、

set aStr to "4 + 5 – 2^3"
set aRes to run script aStr

★Click Here to Open This Script 

bcコマンドに計算を依頼するのが一般的です。

set aStr to "4 + 5 – 2^3"
set yC to string id 92
set aCMD to "echo \" scale=10; " & aStr & "\" | bc"
set aRes to do shell script aCMD

★Click Here to Open This Script 

CocoaのNSExpressionによる式評価を試してみましたが、「**」でべき乗計算を行う形式はあまり見かけないように思います。
→ 調べてみたら、他のプログラミング言語ではこっちが一般的だったので訂正(^ー^; Basic系はべき乗記号(^)でしょうか。

run scriptコマンドでAppleScriptのコマンドを実行して結果を取得できますが、ユーザーから入力させられたり他のファイルからコマンド文字列を取ってくるような仕様になっている場合には、危険なコマンドを仕込まれる危険性があるので、AppleScriptのコマンドが文字列中に入っていないかを事前にチェックするとよいと思われます。

→ 指定のAppleScriptテキストを構文確認して指定の構文要素が入っていないかチェック

AppleScript名:式評価(eval)を行う
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/07
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"

property NSExpression : a reference to current application’s NSExpression

set aStr to "4 + 5 – 2**3"
set d1Res to calcEval(aStr) of me
–> 1.0

–式評価(Evaluate)
on calcEval(aStr)
  –https://nshipster.com/nsexpression/
  
set anExp to NSExpression’s expressionWithFormat:aStr
  
set valList to anExp’s expressionValueWithObject:(missing value) context:(missing value)
  
return valList as real
end calcEval

★Click Here to Open This Script 

Posted in Number | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSExpression | Leave a comment

標準偏差を求める v2

Posted on 8月 7, 2019 by Takaaki Naganoya

1次元配列から標準偏差を求めるAppleScriptです。

Numbersで検算してみたら結果が異なりました。元になっているSwiftのプログラムとは計算結果が合っているので、そういうこと(Cocoaの計算機能+変数型による差異)なんでしょうか。

AppleScript名:標準偏差を求める v2
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/07
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"

property NSExpression : a reference to current application’s NSExpression
property NSMutableArray : a reference to current application’s NSMutableArray

set aList to {14.0, 37.0, 18.5, 59.0, 100}
set d1Res to calcStddev(aList) of me
–> 122.708110069451

set a2List to {1, 2, 3, 4, 4, 5, 9, 11}
set d2Res to calcStddev(a2List) of me
–> 3.218598297396

–標準偏差を計算する
on calcStddev(aList)
  –https://nshipster.com/nsexpression/
  
set anArray to NSMutableArray’s arrayWithArray:aList
  
set anExp to NSExpression’s expressionForFunction:"stddev:" arguments:{(NSExpression’s expressionForConstantValue:anArray)}
  
set valList to anExp’s expressionValueWithObject:(missing value) context:(missing value)
  
return valList as real
end calcStddev

★Click Here to Open This Script 

Posted in list Number | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSExpression NSMutableArray | Leave a comment

アラートダイアログ上にRadio Buttonを表示 v4a

Posted on 8月 7, 2019 by Takaaki Naganoya

アラートダイアログ上にRadio Buttonを表示して項目選択するAppleScriptです。

普通にラジオボタンで項目選択できるようになりました。

表示列数を指定できるようにしておきましたが、選択項目の余りが発生すると処理に矛盾が発生するため、キリのいい(割り切れる)列数を指定してください(短時間で作った試作品なので、そこまで気合は入れていません)。

AppleScript名:アラートダイアログ上にRadio Buttonを表示 v4a
— Created 2019-08-07 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSView : a reference to current application’s NSView
property NSAlert : a reference to current application’s NSAlert
property NSButton : a reference to current application’s NSButton
property NSRadioButton : a reference to current application’s NSRadioButton
property NSButtonTypeRadio : a reference to current application’s NSButtonTypeRadio
property NSRunningApplication : a reference to current application’s NSRunningApplication

property theResult : 0
property returnCode : 0

set paramObj to {myMessage:"Select target Item", mySubMessage:"適切なものを以下からえらんでください", myColNum:2, matrixTitleList:{"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}}

–my chooseItemByRadioButton:paramObj –for Debugging
my performSelectorOnMainThread:"chooseItemByRadioButton:" withObject:(paramObj) waitUntilDone:true
return (theResult as integer)

on chooseItemByRadioButton:(paramObj)
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set aMatList to (matrixTitleList of paramObj) as list
  
set aLen to length of aMatList
  
  
set colNum to (myColNum of paramObj) as integer
  
set rowNum to (aLen div colNum) + (aLen mod colNum)
  
  
set aButtonCellWidth to 150
  
set aButtonCellHeight to 24
  
  
set viewWidth to aButtonCellWidth * colNum
  
set viewHeight to aButtonCellHeight * rowNum
  
  
–define the matrix size where you’ll put the radio buttons
  
set matrixRect to current application’s NSMakeRect(0.0, 0.0, viewWidth, viewHeight)
  
set aView to NSView’s alloc()’s initWithFrame:(matrixRect)
  
  
set aCount to 1
  
set tmpArray to current application’s NSMutableArray’s new()
  
repeat with y from 1 to rowNum
    repeat with x from 1 to colNum
      if aCount ≤ aLen then
        set j to contents of item aCount of aMatList
        
set tmpB to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum) * aButtonCellHeight, aButtonCellWidth, aButtonCellHeight)))
        
        (
tmpB’s setTitle:j)
        (
tmpB’s setShowsBorderOnlyWhileMouseInside:true)
        (
tmpB’s setTag:(aCount))
        (
tmpB’s setTarget:me)
        (
tmpB’s setAction:("clicked:"))
        (
tmpB’s setButtonType:(current application’s NSButtonTypeRadio))
        
        (
tmpArray’s addObject:tmpB)
        
      end if
      
      
set aCount to aCount + 1
    end repeat
  end repeat
  
  
–Select the first radio button item
  (
tmpArray’s objectAtIndex:0)’s setState:(current application’s NSOnState)
  
set theResult to 1
  
  (
aView’s setSubviews:tmpArray)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aView
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
end chooseItemByRadioButton:

on doModal:aParam
  set (my returnCode) to aParam’s runModal()
end doModal:

on clicked:aParam
  set aTag to tag of aParam
  
set theResult to aTag
end clicked:

★Click Here to Open This Script 

Posted in dialog GUI list | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAlert NSButton NSButtonTypeRadio NSRadioButton NSRunningApplication NSView | Leave a comment

アラートダイアログ上にRadio Buttonを表示 v3

Posted on 8月 7, 2019 by Takaaki Naganoya

アラートダイアログ上にラジオボタン的なUIを表示して選択するAppleScriptです。

–> Downdload calImageDialog (with Library within its bundle)

本当はRadio Button的なものを作りたかったのですが、NSMatrixがmacOS 10.8で非推奨というか事実上の廃止になったことを受けて、Radio Button的なものを作ってみたのですが、割と中途半端です(見た目はスゲーいいのに)。


▲macOS 10.14+Script Editor上の動き


▲macOS 10.14+Script Debugger上の動き

一応、ボタンの画像に1月分のカレンダー画像を割り当てており、機能と見た目のバランスを取ろうとしたのですが、Radio Buttonっぽい動きにはなっていません(残念!)。

あと、1年分のカレンダー画像を作成するのに不思議なぐらい時間がかかっています。

あんな素朴なcalコマンドにmacOS 10.13から当日のハイライト表示を消すための「-h」オプションが追加されていたとは、気づきませんでした。10.14で作って10.12上で動かなかったのでcalコマンドのオプションを条件分岐で変更するように初版から修正しました。

AppleScript名:アラートダイアログ上にRadio Buttonを表示 v3
— Created 2019-08-07 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use calImage : script "calImageKit"

property NSView : a reference to current application’s NSView
property NSAlert : a reference to current application’s NSAlert
property NSMatrix : a reference to current application’s NSMatrix
property NSButton : a reference to current application’s NSButton
property NSButtonCell : a reference to current application’s NSButtonCell
property NSRadioButton : a reference to current application’s NSRadioButton
property NSRadioModeMatrix : a reference to current application’s NSRadioModeMatrix
property NSRoundedBezelStyle : a reference to current application’s NSRoundedBezelStyle
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSAlertSecondButtonReturn : a reference to current application’s NSAlertSecondButtonReturn

property theResult : 0
property returnCode : 0

set paramObj to {myMessage:"Select target month", mySubMessage:"適切なものを以下からえらんでください", matrixTitleList:{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}}

–my chooseItemByRadioButton:paramObj–for Debugging

my performSelectorOnMainThread:"chooseItemByRadioButton:" withObject:paramObj waitUntilDone:true
return theResult

on chooseItemByRadioButton:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set aMatList to (matrixTitleList of paramObj) as list
  
set aLen to length of aMatList
  
  
  
set aButtonCellWidth to 104
  
set aButtonCellHeight to 104
  
  
set colNum to 4
  
set rowNum to 3
  
  
set targYear to 2019
  
  
set viewWidth to aButtonCellWidth * colNum
  
set viewHeight to aButtonCellHeight * rowNum
  
  
–create the radio button prototype
  
set aProto to NSButtonCell’s alloc()’s init()
  
aProto’s setTitle:"Options"
  
aProto’s setButtonType:(NSRadioButton)
  
  
–define the matrix size where you’ll put the radio buttons
  
set matrixRect to current application’s NSMakeRect(0.0, 0.0, viewWidth, viewHeight)
  
set aView to NSView’s alloc()’s initWithFrame:(matrixRect)
  
  
set aCount to 1
  
set tmpArray to current application’s NSMutableArray’s new()
  
repeat with y from 1 to rowNum
    repeat with x from 1 to colNum
      set j to contents of item aCount of aMatList
      
set tmpB to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum) * aButtonCellHeight, aButtonCellWidth, aButtonCellHeight)))
      
–(tmpB’s setTitle:j)
      
      
set tmpImage to makeSmallCalendarImage(targYear, aCount) of calImage
      (
tmpB’s setImage:(tmpImage))
      (
tmpB’s setShowsBorderOnlyWhileMouseInside:true)
      (
tmpB’s setTag:(aCount))
      (
tmpB’s setTarget:me)
      (
tmpB’s setAction:("clicked:"))
      (
tmpB’s setButtonType:(current application’s NSButtonTypeMomentaryPushIn))
      
      (
tmpArray’s addObject:tmpB)
      
set aCount to aCount + 1
    end repeat
  end repeat
  
  (
aView’s setSubviews:tmpArray)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aView
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
  
end chooseItemByRadioButton:

on doModal:aParam
  set (my returnCode) to aParam’s runModal()
end doModal:

on clicked:aParam
  set aTag to tag of aParam
  
set theResult to aTag
end clicked:

★Click Here to Open This Script 

Posted in Calendar dialog GUI Image | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAlert NSAlertSecondButtonReturn NSButton NSRoundedBezelStyle NSRunningApplication NSView | Leave a comment

アラートダイアログ上にpath control x2を表示 v2

Posted on 8月 3, 2019 by Takaaki Naganoya

アラートダイアログ上にPathcontrolを表示して、ファイルパス選択をドラッグ&ドロップで受け付けるAppleScriptの改良版です。

実行中にアピアランスのDark Mode/Light Modeへの変更が行われたときの対応を追加してみました。

実行途中でアピアランスの変更が行われると、OSが提供している部品をそのまま利用している分にはOSの管理下で色変更が行われますが、あとから色指定している部品はそのままです(↑)。上記の(↑)ように、割と違和感があるというか、実用上困る(そもそもアピアランス変更をそんな時に行う方がどうかしているとは思うのですが)ので、対処してみました。

部品はひととおり作ってあったので、組み合わせただけです。アピアランスの変更Notificationを受信する部品や、アピアランステーマを判定する部品などです。

部品の組み合わせ方にも些細なノウハウがあるので、一応やっておいたことには意義があると思っています。

AppleScript名:アラートダイアログ上にpath control x2を表示 v2
— Created 2019-08-02 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSView : a reference to current application’s NSView
property NSAlert : a reference to current application’s NSAlert
property NSColor : a reference to current application’s NSColor
property NSTextField : a reference to current application’s NSTextField
property NSPathControl : a reference to current application’s NSPathControl
property NSUserDefaults : a reference to current application’s NSUserDefaults
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSDistributedNotificationCenter : a reference to current application’s NSDistributedNotificationCenter

property theResult : 0
property returnCode : 0
property resList : {}
property aPathControl : missing value
property bPathControl : missing value

set paramObj to {myMessage:"ファイルの入出力フォルダ選択", mySubMessage:"どれか選択してください。", fromPathMes:"移動元:", toPathMes:"移動先:"}
my performSelectorOnMainThread:"chooseTwoPath:" withObject:paramObj waitUntilDone:true

return resList
–> {fromPathRes:"/Users/me/Desktop/keyn1.png", toPathRes:"/Users/me/Desktop/scriptmenu1.png"}

on chooseTwoPath:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set fromLabel to fromPathMes of paramObj
  
set toLabel to toPathMes of paramObj
  
  
—Dark Mode Notification受信開始
  
NSDistributedNotificationCenter’s defaultCenter()’s addObserver:me selector:"darkModeChanged:" |name|:"AppleInterfaceThemeChangedNotification" object:(missing value)
  
  
— create a view
  
set theView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 600, 60))
  
  
— create two path control & text field
  
set aPathControl to NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(100, 35, 700, 20))
  
set bPathControl to NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(100, 0, 700, 20))
  
  
–Set path control’s bg colors
  
set {aCol, bCol} to pathControlSrtringColor() of me
  
aPathControl’s setBackgroundColor:(aCol)
  
bPathControl’s setBackgroundColor:(bCol)
  
  
  
set aHome to current application’s |NSURL|’s fileURLWithPath:(current application’s NSHomeDirectory()) –initial dir
  
aPathControl’s setURL:aHome
  
bPathControl’s setURL:aHome
  
  
set a1TF to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 35, 100, 20))
  
set a2TF to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 100, 20))
  
a1TF’s setEditable:false
  
a2TF’s setEditable:false
  
a1TF’s setStringValue:fromLabel
  
a2TF’s setStringValue:toLabel
  
a1TF’s setDrawsBackground:false
  
a2TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
a2TF’s setBordered:false
  
  
theView’s setSubviews:{a1TF, aPathControl, a2TF, bPathControl}
  
  
— set up alert
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
its addButtonWithTitle:"Cancel"
    
its setAccessoryView:theView
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
  
  
set s1Val to (aPathControl’s |URL|’s |path|()) as string
  
set s2Val to (bPathControl’s |URL|’s |path|()) as string
  
  
set resList to {fromPathRes:s1Val, toPathRes:s2Val}
  
  
–Notification受信停止
  
NSDistributedNotificationCenter’s defaultCenter()’s removeObserver:me |name|:"AppleInterfaceThemeChangedNotification" object:(missing value)
end chooseTwoPath:

on doModal:aParam
  set (my returnCode) to aParam’s runModal()
end doModal:

–ダークモードの判定。ダークモード時:true、ライトモード時:falseが返る
on retLIghtOrDark()
  set curMode to (NSUserDefaults’s standardUserDefaults()’s stringForKey:"AppleInterfaceStyle") as string
  
return (curMode = "Dark") as boolean
end retLIghtOrDark

–aMaxValを最大値とする数値でNSColorを作成して返す
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

–Notification handler
on darkModeChanged:(aNotification)
  set {aCol, bCol} to pathControlSrtringColor() of me
  
aPathControl’s setBackgroundColor:(aCol)
  
bPathControl’s setBackgroundColor:(bCol)
end darkModeChanged:

on pathControlSrtringColor()
  set dMode to retLIghtOrDark() of me –Dark mode:true
  
if dMode = false then
    –Light Mode
    
set aCol to (NSColor’s cyanColor())
    
set bCol to (NSColor’s yellowColor())
  else
    –Dark Mode
    
set aCol to (makeNSColorFromRGBAval(0, 96, 65, 255, 255) of me)
    
set bCol to (makeNSColorFromRGBAval(93, 92, 0, 255, 255) of me)
  end if
  
  
return {aCol, bCol}
end pathControlSrtringColor

★Click Here to Open This Script 

Posted in Color dialog GUI Noification | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAlert NSColor NSDistributedNotificationCenter NSPathControl NSRunningApplication NSTextField NSUserDefaults NSView | Leave a comment

Keynoteの表の内容を回転(Transpose)

Posted on 8月 2, 2019 by Takaaki Naganoya

Keynoteでオープン中の書類の現在表示中のページ(スライド)上にある表のデータを回転(transpose)する、行列入れ替えするAppleScriptです。

–> Download tableTransposer (Code Signed Applet)

Numbersでは、指定の表データの縦横転置のためのコマンド「行と列を転置」(transpose)がありますが、Keynoteにはありません。

Keynoteの表データをコピーしてNumbersに持って行って転置してKeynoteに戻していますが、メニュー操作で一発で転置できるようにしてみたものです。

回転(転置)前にテーブルの縦横のセル数をカウントして、高さと幅が同じでない場合には処理を行いません。ただ、これでは明らかに使い勝手がよくありません。いっそ、表のセル数を変更して転置したデータ形状に表の方を合わせるべきです。

Script Menuから実行させてみる場合には、コード署名してアプレット書き出しする必要があります。上記のリンクから、コード署名したアプレットをダウンロードして実行してみてください。

AppleScript名:表の内容を回転(Transpose)
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/05/16
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

set tName to getTargetTableName() of me
if tName = false then return

–Get Table Values as 2D List
set t1List to getValuesOfATableBy2DList(tName) of me

–Check Table width and height is same or not
set tRes to countElementsOf2DList(t1List) of me
if tRes = false then
  display notification "Table width and height is not same….."
  
return
end if

–Transpose 2D List
set t2List to transpose2DList(t1List) of me

–Set values to a table
setValuesToATableBy2DList(tName, t2List) of me

–Keynoteの現在の最前面の書類の現在のスライド上の指定名称の表に2D Listの値を入れる
on setValuesToATableBy2DList(tName, tList)
  tell application "Keynote"
    tell front document
      tell current slide
        tell table tName
          set rCount to count every row
          
set cCount to count every column
          
          
repeat with i from 1 to rCount
            tell row i
              repeat with ii from 1 to cCount
                tell cell ii
                  ignoring application responses –Sync Mode
                    set value of it to getItemByXY(ii, i, tList, "") of me
                  end ignoring
                end tell
              end repeat
            end tell
          end repeat
        end tell
      end tell
    end tell
  end tell
end setValuesToATableBy2DList

–Keynoteの現在の最前面の書類の現在のスライド上の指定名称の表から2D Listで値を取り出す
on getValuesOfATableBy2DList(tName)
  set a2Dlist to {}
  
tell application "Keynote"
    tell front document
      tell current slide
        tell table tName
          set rCount to count every row
          
repeat with i from 1 to rCount
            tell row i
              set tList to value of every cell
            end tell
            
set the end of a2Dlist to tList
          end repeat
        end tell
      end tell
    end tell
  end tell
  
return a2Dlist
end getValuesOfATableBy2DList

–処理対象となる表の名称を取得する
on getTargetTableName()
  tell application "Keynote"
    tell front document
      tell current slide
        set tCount to count every table
        
        
if tCount = 0 then
          display notification "There is no Table"
          
return false
          
        else if tCount > 1 then
          set tList to name of every table
          
          
set tRes to choose from list tList with prompt "Chose target Table"
          
if tRes = false then return false
          
set tName to first item of tRes
        else
          set tName to name of table 1
        end if
        
        
return tName
        
      end tell
    end tell
  end tell
end getTargetTableName

–2D ListをTransposeする
on transpose2DList(aList as list)
  load framework
  
return (ASify from (current application’s SMSForder’s colsToRowsIn:aList |error|:(missing value)))
end transpose2DList

—-リストに対して、一般的な配列添字っぽくアクセスするサブルーチン(ただし、要素は1はじまり)

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

–配列のサイズを数えるサブルーチン

–2D Listの要素数カウント
on countElementsOf2DList(aList)
  set aDim to getDimension given tArray:aList
  
if aDim is not equal to 2 then return false
  
  
set aHeight to count every item of aList
  
set aWidth to count every item of item 1 of aList
  
return {xWidth:aWidth, yHeight:aHeight}
end countElementsOf2DList

–指定Listの次元を再帰で取得する
on getDimension given tArray:aList as list : {}, curDim:aNum as integer : 1
  
  
set anItem to contents of first item of aList
  
set aClass to class of anItem
  
  
if aClass = list then
    set aNum to aNum + 1
    
set aRes to getDimension given tArray:anItem, curDim:aNum
  else
    return aNum
  end if
  
end getDimension

★Click Here to Open This Script 

Posted in list | Tagged 10.12savvy 10.13savvy 10.14savvy Keynote | Leave a comment

選択中のリストのテキスト(多分)をもとにKeynoteの表を作成 v2

Posted on 8月 1, 2019 by Takaaki Naganoya

Script Editor上で選択中の1D List(1次元配列)のテキストを評価してリストとして解釈し、それをもとにKeynoteの新規書類上に表を作成するAppleScriptの改良版です。

こんな感じ(↑)に、Script Editor上で1D List(1次元配列)のテキストが存在しているものを、資料化するためにKeynote上で表にすることがあり、その作業を自動化してみました。

スクリプトエディタ上の選択範囲のテキストをrun scriptコマンドで実際に実行(Evalのような使い方)して本物のAppleScriptのリストを作成して処理します。

ここがたいへんにセキュリティホールになりやすいので、実行前にテキストをAppleScriptとして構文確認を行い、危ない構文要素(コマンド類)が入っていないか、AppleScriptの構文的に中途半端でないかチェックを行います。

技術的にはMac OS X 10.4ないし10.5の時代に確立していた内容ではありますが、当時はスクリプトエディタをコントロールして構文色分け情報を取得していたので、macOS 10.10以降でCocoaの機能がAppleScriptから直接利用できるようになって、よりスマートに処理できるようになりました。

Mac OS X 10.4の時代には、plistの情報はテキストで記録されていたので、構文色分け設定を読むのは簡単でした。スクリプトエディタから書式つきテキスト情報(attribute runs)を取得して付け合わせを行っていました。途中でplistの内容がバイナリ化されてplistを読むことが難しくなったので、新規書類に「すべての構文要素が入った最低限度のAppleScript」を転送して構文確認を行い、attribute runsを取得して規定の場所の書式情報を取得することで、特定の構文要素の色分け情報を取得していました(一瞬で新規書類を作成して構文確認し、すぐに破棄するので目には見えない)。

–> Download selectedStrToKeynoteTable (Source AppleScript Bundle with Library)

–> Download selectedStrToKeynoteTableWithCodeSign(AppleScript Applet executable with Code Sign)

ただし、本ScriptをmacOS 10.14上で実行してみていろいろ問題を感じました。まずは、スクリプトエディタ/Script Debugger上で実行する分には何も問題はありません。ここは大事なので明記しておきます。

これ以外の実行環境で実行させると、とたんに首をひねりたくなるような挙動が見られます。Script Menuから実行することを前提に作ってみたわけですが………

普通にScriptとして保存して実行(署名なし、公証なし):初回実行時にオートメーション認証ダイアログが表示されて実行。数回同じScriptを実行すると実行されなくなる(!)

Appletとして保存して実行(署名なし、公証なし):実行時、毎回オートメーション認証ダイアログが表示されて実行。

Appletとして保存して実行(署名あり、公証なし):初回実行時、オートメーション認証ダイアログが表示されて実行。連続して実行するとダイアログ表示なし。しばらく時間を置いて実行するとダイアログ表示される。

macOS 10.14については2か月前から使い始めたので、公証についてもまだうまく行えていません(SD Nortaryで開発者IDが認識されない、、、)。こちら(公証)も試してみるべきなんでしょう。

公証関連については、実際に行っている方、失敗した方の意見をまとめておきたいので、本Blog併設のフォーラムにて(言語は英語でも何語でもOKなので)情報交換させてください。

AppleScript名:選択中のリストのテキスト(多分)をもとにKeynoteの表を作成 v2
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/07/31
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use dangerAS : script "checkDangerAS"

set aTargMasterSlide to "空白" –This string is *Localized* in Japanese. This is "Blank"

tell application "Script Editor"
  tell front document
    set bText to contents of selection
  end tell
end tell

if bText = "" then return

–指定のテキストをAppleScriptとして評価し、指定の構文要素に該当するものが含まれているかどうかチェック
set dRes to chkTargLexicalElementsFromCompiledScriptAttribute(bText, {9, 14}) of dangerAS
if dRes = missing value then
  –The selected text contains AppleScript lexical error
  
display dialog "選択中のテキストにAppleScriptの構文エラーが検出されました" default answer bText with title "Error" with icon 2
  
return
end if

if dRes = true then
  –The selected text contain danger AppleScript lexical element (maybe it is any command)
  
display dialog "選択中のテキストは実行に危険な文字列(AppleScriptコマンド)を含んでいるため、処理しませんでした" default answer bText with title "Error" with icon 2
  
return
end if

try
  set aRes to run script bText –Danger!! Take Care of.
  
set aClass to class of aRes
on error
  –The Evaluation error (some AppleScript lexical error)
  
display dialog "The contents of clipboard seems not to be an AppleScript list but " & (aClass as string) & return & bText with title "Error (1)" with icon 2
  
return
end try

if aClass is not equal to list then
  –The Evaluated result is not list
  
display dialog "The contents of clipboard seems not to be an AppleScript list but " & (aClass as string) & return & bText with title "Error (2)" with icon 2
  
return
end if

set aLen to length of aRes
set aDim to getDimension given tArray:aRes
if aDim > 1 then
  –Check List’s dimension (the taeget dimension is 1)
  
display dialog "選択中のテキストを評価したリスト(配列)の次元数が1ではなかったので、処理しませんでした" default answer bText with title "Dimension Error(3)" with icon 2
  
return
end if

tell application "Keynote"
  activate
  
set aDoc to (make new document with properties {document theme:theme "ホワイト", width:1024, height:768}) — –This string is *Localized* in Japanese. This is "White"
  
  
tell aDoc
    set masList to name of every master slide
    
if aTargMasterSlide is not in masList then return –多分ないと思うが、作成予定のマスタースライドが現在有効でない場合に処理打ち切り
    
    
set base slide of current slide to master slide aTargMasterSlide
    
    
tell current slide
      set aTable to make new table with properties {header column count:0, header row count:1, row count:2, column count:aLen, name:"Test Table"}
      
      
tell aTable
        repeat with y from 1 to 1
          tell row y
            repeat with x from 1 to aLen
              tell cell x
                set value to (item x of aRes) as string
              end tell
            end repeat
          end tell
        end repeat
      end tell
      
    end tell
  end tell
end tell

–指定Listの次元を再帰で取得する
on getDimension given tArray:aList as list : {}, curDim:aNum as integer : 1
  set anItem to contents of first item of aList
  
set aClass to class of anItem
  
  
if aClass = list then
    set aNum to aNum + 1
    
set aRes to getDimension given tArray:anItem, curDim:aNum
  else
    return aNum
  end if
end getDimension

★Click Here to Open This Script 

Posted in Code Sign Color list Notarization OSA regexp | Tagged 10.12savvy 10.13savvy 10.14savvy Keynote Script Editor | Leave a comment

指定のAppleScriptテキストを構文確認して指定の構文要素が入っていないかチェック

Posted on 7月 31, 2019 by Takaaki Naganoya

指定のテキストをAppleScriptとみなして構文確認して、指定の構文要素が入っていないかチェックするAppleScriptです。

AppleScriptにeval関数はないので、文字列として与えたAppleScriptをその場で実行する「run script」コマンドをevalがわりに使っています。

文字列をそのままrun scriptするのは(一応いろいろ保護機能はあるものの)、セキュリティ的にリスクの高い操作になってしまいます。


▲こんなのがrun scriptコマンドで実行されてしまったらと思うとゾッとします。ためしに実行してみたら、実行権限がないので実行できないエラーになりました

そこで、文字列をいったんAppleScriptとして評価(構文確認)し、コマンドなどの危険と思われる構文要素が入っていないかどうかチェックする処理を書いて使っています。

これら、「コマンド」および「追加コマンド」といった構文要素が入っていたらtrueを返します。

本Scriptをライブラリ化して組み込むことで、少ない記述量で対象の文字列をそのままrun scriptしてよいかどうか判定できるようにしています。

–> Download checkDanger(with Library in its bundle)


▲実際にテキストをAppleScriptとして評価して構文要素を検出し、このようにコマンド部分(AppleScriptのdo shell scriptコマンド)が入っていることを検知できる

AppleScript名:指定のAppleScriptテキストを構文確認して指定の構文要素が入っていないかチェック.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/07/31
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use framework "AppKit"
use framework "OSAKit"
use attrLib : script "asAttrRecLib"

property NSArray : a reference to current application’s NSArray
property OSANull : a reference to current application’s OSANull
property NSString : a reference to current application’s NSString
property OSAScript : a reference to current application’s OSAScript
property NSPredicate : a reference to current application’s NSPredicate
property NSDictionary : a reference to current application’s NSDictionary
property NSUnarchiver : a reference to current application’s NSUnarchiver
property OSALanguage : a reference to current application’s OSALanguage
property NSCountedSet : a reference to current application’s NSCountedSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property OSALanguageInstance : a reference to current application’s OSALanguageInstance

script spd
  property fArray : {}
  
property outList : {}
  
property resStr : {}
end script

on run
  set theSource to "do shell script \"rm -f *.*\""
  
set aRes to chkTargLexicalElementsFromCompiledScriptAttribute(theSource, {9, 14}) of me –{Command, External Command}
  
–> true : 指定の構文要素が入っていた
  
  
set theSource to "{{aName:\"piyoko\", aVal:100}, {aName:\"piyomaru\", aVal:80}, {aName:\"piyoo\", aVal:10}, {aName:\"Gundamo\", aVal:10}}"
  
set bRes to chkTargLexicalElementsFromCompiledScriptAttribute(theSource, {9, 14}) of me –{Command, External Command}
  
–> false : 指定の構文要素は入っていなかった
end run

–AppleScriptのソーステキストをコンパイルして、指定の構文要素が含まれているかチェックする
on chkTargLexicalElementsFromCompiledScriptAttribute(theSource as string, targLexicalElements as list)
  
  
–AppleScriptの構文色分け情報を取得
  
set ccRes to getAppleScriptSourceColors() of me
  
set cRes to chkASLexicalFormatColorConfliction(ccRes) of me –構文色分けの重複色チェック
  
if cRes = false then error "There is some duplicate(s) color among AppleScript’s lexical color settings"
  
  
–検索用の色情報を作成
  
set colTargList to {}
  
repeat with i in targLexicalElements
    set commentCol to contents of item i of ccRes –Variable and Sub-routine name
    
set searchVal to (redValue of commentCol as string) & " " & (greenValue of commentCol as string) & " " & (blueValue of commentCol as string) –for filtering
    
set the end of colTargList to searchVal
  end repeat
  
  
  
–与えられたテキストをAppleScriptとして評価し構文色分け情報をもとにStyle Runs的なDictionary化して返す
  
set aRitch to compileASSourcetextAndReturnStyledText(theSource) of me
  
  
  
–書式付きテキストからstyle runs的な書式リストを作成
  
set anAttrList to getAttributeRunsFromAttrString(aRitch) of attrLib
  
  
set bList to filterRecListByLabelAndSublist(anAttrList, "colorStr IN %@", colTargList) of me
  
  
return not (bList as list = {}) as boolean
  
end chkTargLexicalElementsFromCompiledScriptAttribute

on retDelimedText(aList, aDelim)
  set aText to ""
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set aText to aList as text
  
set AppleScript’s text item delimiters to curDelim
  
return aText
end retDelimedText

——-

–AppleScriptの構文色分けのカラー値をRGBで取得する
on getAppleScriptSourceColors()
  — get the plist info as a dictionary
  
set thePath to NSString’s stringWithString:"~/Library/Preferences/com.apple.applescript.plist"
  
set thePath to thePath’s stringByExpandingTildeInPath()
  
set theInfo to NSDictionary’s dictionaryWithContentsOfFile:thePath
  
  
— extract relevant part and loop through
  
set theArray to (theInfo’s valueForKey:"AppleScriptSourceAttributes") as list
  
  
set colList to {}
  
  
repeat with i from 1 to count of theArray
    set anEntry to item i of theArray
    
    
set colorData to NSColor of anEntry
    
set theColor to (NSUnarchiver’s unarchiveObjectWithData:colorData)
    
    
set {rVal, gVal, bVal} to retColListFromNSColor(theColor, 255) of me
    
    
set fontData to NSFont of anEntry
    
set theFont to (NSUnarchiver’s unarchiveObjectWithData:fontData)
    
    
set aFontName to theFont’s displayName() as text
    
set aFontSize to theFont’s pointSize()
    
    
set aColRec to {redValue:rVal, greenValue:gVal, blueValue:bVal, fontName:aFontName, fontSize:aFontSize}
    
    
set the end of colList to aColRec
  end repeat
  
  
return colList
end getAppleScriptSourceColors

–AppleScriptの構文色分けのカラー値をRGBで取得する
on getAppleScriptSourceNSColorsDict()
  — get the plist info as a dictionary
  
set thePath to NSString’s stringWithString:"~/Library/Preferences/com.apple.applescript.plist"
  
set thePath to thePath’s stringByExpandingTildeInPath()
  
set theInfo to NSDictionary’s dictionaryWithContentsOfFile:thePath
  
  
— extract relevant part and loop through
  
set theArray to (theInfo’s valueForKey:"AppleScriptSourceAttributes") as list
  
  
set aDict to NSMutableDictionary’s alloc()’s init()
  
  
repeat with i from 1 to count of theArray
    set anEntry to item i of theArray
    
    
set colorData to NSColor of anEntry
    
set theColor to (NSUnarchiver’s unarchiveObjectWithData:colorData)
    
    
set {rVal, gVal, bVal} to retColListFromNSColor(theColor, 255) of me
    
    
set fontData to NSFont of anEntry
    
set theFont to (NSUnarchiver’s unarchiveObjectWithData:fontData)
    
    
set aFontName to theFont’s displayName() as text
    
set aFontSize to theFont’s pointSize()
    
    
set colIndStr to (rVal as string) & " " & (gVal as string) & " " & (bVal as string)
    
set tmpColDat to {numList:{rVal, gVal, bVal}, strInd:colIndStr}
    
–(aDict’s addObject:tmpColDat forKey:theColor)
    (
aDict’s addObject:{rVal, gVal, bVal} forKey:theColor)
  end repeat
  
  
return aDict
end getAppleScriptSourceNSColorsDict

–NSColorからRGBの値を取り出す
on retColListFromNSColor(aCol, aMAX as integer)
  set aSpace to (aCol’s colorSpaceName()) as string
  
–set aSpace to (aCol’s type()) as integer
  
  
if aSpace is in {"NSDeviceRGBColorSpace", "NSCalibratedRGBColorSpace"} then
    copy aCol to cCol
  else
    –RGB以外の色空間の色は、RGBに変換
    
–CMYKとグレースケールは同一メソッドでRGBに変換できることを確認済み
    
set cCol to aCol’s colorUsingColorSpaceName:"NSCalibratedRGBColorSpace"
    
if cCol = missing value then error "Color Space Conversion Error (" & aSpace & " to NSCalibratedRGBColorSpace)"
  end if
  
  
set aRed to round ((cCol’s redComponent()) * aMAX) rounding as taught in school
  
set aGreen to round ((cCol’s greenComponent()) * aMAX) rounding as taught in school
  
set aBlue to round ((cCol’s blueComponent()) * aMAX) rounding as taught in school
  
  
if aRed > aMAX then set aRed to aMAX
  
if aGreen > aMAX then set aGreen to aMAX
  
if aBlue > aMAX then set aBlue to aMAX
  
  
return {aRed, aGreen, aBlue} as list
end retColListFromNSColor

–AS書式で配色に重複がないかどうかチェック
on chkASLexicalFormatColorConfliction(aList)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set bList to (anArray’s valueForKeyPath:"redValue.stringValue") as list
  
set cList to (anArray’s valueForKeyPath:"greenValue.stringValue") as list
  
set dList to (anArray’s valueForKeyPath:"blueValue.stringValue") as list
  
  
set colStrList to {}
  
repeat with i from 1 to (length of bList)
    set bItem to contents of item i of bList
    
set cItem to contents of item i of cList
    
set dItem to contents of item i of dList
    
set the end of colStrList to bItem & " " & cItem & " " & dItem
  end repeat
  
  
set aRes to returnDuplicatesOnly(colStrList) of me
  
  
if aRes is equal to {} then
    return true –重複が存在しなかった場合
  else
    return false –重複があった場合
  end if
end chkASLexicalFormatColorConfliction

on returnDuplicatesOnly(aList as list)
  set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bList to (aSet’s allObjects()) as list
  
  
set dupList to {}
  
repeat with i in bList
    set aRes to (aSet’s countForObject:i)
    
if aRes > 1 then
      set the end of dupList to (contents of i)
    end if
  end repeat
  
  
return dupList
end returnDuplicatesOnly

–テキスト形式のAppleScriptをコンパイルして書式付きテキスト(NSAttributedString)を返す
on compileASSourcetextAndReturnStyledText(theSource)
  — create a new AppleScript instance
  
set anOSALanguageInstance to OSALanguage’s languageForName:"AppleScript"
  
  
set theScript to OSAScript’s alloc()’s initWithSource:theSource fromURL:(missing value) languageInstance:anOSALanguageInstance usingStorageOptions:(OSANull)
  
set {theResult, theError} to theScript’s compileAndReturnError:(reference)
  
  
if theResult as boolean is false then
    — handle error
    
error "Compile Error"
  else
    set styledSourceText to theScript’s richTextSource()
  end if
  
  
return styledSourceText
end compileASSourcetextAndReturnStyledText

–文字置換
on repChar(origText as string, targChar as string, repChar as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

–リストに入れたレコードを、指定の属性ラベルの値で抽出。値が別途指定のリストの中に存在していることが条件
on filterRecListByLabelAndSublist(aRecList as list, aPredicate as string, aSubList as list)
  set aArray to NSArray’s arrayWithArray:aRecList
  
set aSubArray to NSArray’s arrayWithArray:aSubList
  
  
–抽出
  
set aPredicate to NSPredicate’s predicateWithFormat_(aPredicate, aSubArray)
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
  
return filteredArray as list
end filterRecListByLabelAndSublist

★Click Here to Open This Script 

Posted in Color OSA Text | Tagged 10.12savvy 10.13savvy 10.14savvy NSArray NSCountedSet NSDictionary NSMutableArray NSMutableDictionary NSPredicate NSString NSUnarchiver OSALanguage OSALanguageInstance OSANull OSAScript | 2 Comments

Post navigation

  • Older posts
  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AppleScriptによる並列処理
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • macOS 15でも変化したText to Speech環境
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • デフォルトインストールされたフォント名を取得するAppleScript
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • Script Debuggerの開発と販売が2025年に終了
  • macOS 15 リモートApple Eventsにバグ?
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • NSObjectのクラス名を取得 v2.1
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • 有害ではなくなっていたSpaces
  • Xcode上のAppleScriptObjCのプログラムから、Xcodeのログ欄へのメッセージ出力を実行

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (194) 14.0savvy (147) 15.0savvy (136) CotEditor (66) Finder (51) iTunes (19) Keynote (119) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (55) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC