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

カテゴリー: OSA

Bundle IDで指定したアプリケーションのSDEF内容を表示(OSADictionary)

Posted on 8月 9, 2022 by Takaaki Naganoya

指定のBundle IDのアプリケーションのAppleScript用語辞書(sdef)から、Xincludeを解消して、外部参照していた内容を展開してHTMLに変換してWkWebViewで表示するAppleScriptです。

–> dispAppScriptDict.scptd(Bundle Script with Script Library in its bundle)

AppleScript用語辞書シリーズで、sdefの外部参照をXML系のサービスを利用して展開していましたが、OSAKitのOSADictionaryで展開できるという噂を聞きつけ、調査して試してみました。

参照した情報は、こちらのページです。

XML系のOSの機能を利用したときには発生していなかった現象ですが、Bundle IDで指定したアプリケーションが本Script実行時に起動されました。

Adobe系のアプリケーションは未検証ですが、本ScriptでAdobe系アプリケーション(InDesign、Illustrator、Photoshop)の用語辞書を、スクリプトエディタに近い状態で表示できれば、辞書の展開も大丈夫というところでしょうか。

# 辞書内容をHTMLではなくXMLとして取得したら、Xincludeは展開されていなかったので、このやり方ではダメということなんでしょう>辞書部品の外部参照の解消
# OSAKit.frameworkそのものをFinder上でこじ開けてみると、cssとxsltが存在していることがわかるので、このあたりの手順で辞書の展開を行っているようなのですが、、、

本来自分がやりたいのは、こんな用語辞書の表示ではないので、とりあえず「試してみた」というところでしょうか。

AppleScript名:Bundle IDで指定したアプリケーションのSDEFからXPathで指定したClassにアクセス(OSADictionary).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/09
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use framework "OSAKit"
use webD : script "webDialogLib"
use scripting additions

set targAppBundleID to "com.apple.iWork.Keynote" –SDEFを取り出すターゲットのアプリケーションのBundle ID

set thePath to POSIX path of (path to application id targAppBundleID)

set aSDEFname to retAppSdefNameFromBundleIPath(thePath, "OSAScriptingDefinition") of me
if aSDEFname = false then return

if aSDEFname does not end with ".sdef" then set aSDEFname to aSDEFname & ".sdef"
set sdefFullPath to thePath & "Contents/Resources/" & aSDEFname

–https://github.com/LeoNatan/Apple-Runtime-Headers/blob/
–5e50ad05dfd7d7b69fc2e0e685765fc054166b3c/macOS/Frameworks/OSAKit.framework/OSADictionary.h
set aDict to current application’s OSADictionary’s alloc()’s initWithContentsOfFile:sdefFullPath |error|:(missing value)
if aDict = missing value then return

aDict’s parse()
set aHTML to aDict’s html() as string

set paramObj to {myMessage:"AppleScript用語辞書の表示テスト", mySubMessage:"OSADictionaryで読み込んだsdefをHML化してWkWebViewで表示", htmlStr:aHTML, htmlPath:"", jsDelimiters:{"", ""}, viewSize:{600, 400}}

–webD’s browseStrWebContents:paramObj –for debug
webD’s displayWebDialog(paramObj)

–指定パスからアプリケーションのInfo.plist中の属性値を返す
on retAppSdefNameFromBundleIPath(appPath as string, aKey as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:(aKey)
  
if aRes = missing value then return false
  
set asRes to aRes as string
  
  
return asRes as string
end retAppSdefNameFromBundleIPath

★Click Here to Open This Script 

(Visited 28 times, 1 visits today)
Posted in dialog OSA sdef | Tagged 10.15savvy 11.0savvy 12.0savvy | Leave a comment

AS Publisher v18–> v19

Posted on 11月 7, 2021 by Takaaki Naganoya

とくに新しいわけでもなんでもありませんが、「スクリプトエディタでオープン中のScriptをリンクつきのHTMLとして書き出すAppleScript」である「AS Publisher」の機能改修版です。前バージョンまではURLエンコーディング処理にpythonを呼び出して処理していましたが、Cocoaの機能を呼び出すように書き換えました。

# v18に処理のミスがあり、そのミスがOS側で「こういう間違いが多いから通しておこう」と見逃されていたのが厳密に処理されるようになったため、ミスの部分を修正しておきました

AppleScriptのリストをBlogなどに掲載する場合、WordPressやMarkdownの構文自動認識フォーマットを使って掲載されているものを見かけますが、そもそも「return return」(改行コードを返す)といった記述が許可されており、それらがきちんと構文色分けされているAppleScriptにおいて、単なるキーワードによる構文自動認識フォーマットが役立つわけがありません(知らずによく実装したもんですわ>オリジナル版を作った人)。

それ以前に「必要があったので」作ったAppleScriptでもあります。手元に残っている最古のバージョンは2005年の4月1日のタイムスタンプになっていますが、おそらくそれ以前から作っていたものでしょう。

# retMacOSpathList ハンドラで、ファイルパスをやたらとCastしている箇所がありますが、Mac OS X 10.5より前のAppleScriptではファイルパスの文字列のエンコーディングに問題を抱えていた(AppleScript側の文字列とのエンコーディング/ノーマライズの不整合)ので、その対策です。ただし、不必要なぐらい無駄な処理をしているので、参考にはなりません。Mac OS X初期の試行錯誤を強いられていた時代の遺物とでも思ってください

本Scriptおよびその派生版は、macOS標準装備のScript Menuに入れて実行することを想定しています。AppleScriptからスクリプトエディタを操作する場合に、Mac OS X 10.4の時代ではあまり動作が安定せず、もう少し後のバージョンのOSになるまで(10.5ぐらい?)、たいへんスリリングな(クラッシュが頻発する)Scriptingを強いられていました。

いまはそのあたりは安定していますが、ごく初期においては挙動が怪しい部分があったということです(その時期で知識が止まっている人はそういう認識のまま)。

話を戻しましょう。

AppleScriptのプログラムをBlogなどに掲載する際に、自分はこういう道具を作って使用しています。巨大なリストを掲載する場合には記事の文字数が膨大になってしまい、掲載をあきらめたこともありましたが、ほんのごく一部です。

このScriptをもとに、自分が使いやすいように(色指定とか)変更してみてもよいでしょう。

「動けばいい」ぐらいの割り切りで、秘伝のタレに継ぎ足してメンテナンスしてきましたが、HTMLタグで書式制御するよりはCSSで制御したほうがシンプルにできてよさそうな感じもします。

ファイル処理も、とくに「ここまでやる必要ってあったっけ?」という感想を持ってしまいます。なにぶん、2006年ごろに作ったものなので、自分で自分のプログラムを見ても違和感がものすごいですね。「OSの処理に対する不信感」がそこかしこに漂っています、、、、

AppleScript名:AS Publisher v19.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2014/11/09
–  Modified on: 2021/11/07
—
–  Copyright © 2006-2021 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property quotChar : string id 34

property headerCol : "0000CC" –"0000CC" –ヘッダー部分(濃い色)
property bodyBackCol : "EEFFFF" –"EEFFFF" –Script本文下地(薄い色)
property footerCol : "66FFFF" –"66FFFF" –スクリプトリンク部分

set a to path to me

set pName to "com.apple.ScriptEditor2"

using terms from application "Script Editor"
  tell application id pName
    if (count every document) = 0 then
      display dialog "スクリプトをエディタでオープンした状態で実行してください。" buttons {"OK"} default button 1 with icon 1
      
return
    end if
    
    
set aP to path of front document
    
if aP = "" then
      display dialog "スクリプトを保存してから実行してください。" buttons {"OK"} default button 1 with icon 1
      
return
    end if
    
    
tell front document
      set aInfo to properties
      
set curLang to name of language of aInfo –現在のOSA言語の名称を取得する
    end tell
    
    
–OSA Language名称をもとに色セットを変更する
    
changeColor(curLang) of me
    
    
set c to name of front document
    
    
set aF to retMacOSpathList(aP) of me
    
set htmlFilePath to retHTMLpath(aF) of me
    
    
set contText to contents of front document
    
set encText to makeEncodedScript(contText) of me
    
    
set newLinkText to "applescript://com.apple.scripteditor?action=new&script=" & encText
    
–set insLinkText to "applescript://com.apple.scripteditor?action=insert&script=" & encText
    
–set apndLinkText to "applescript://com.apple.scripteditor?action=append&script=" & encText
    
    
set comText to description of front document
    
    
set textList to every attribute run of front document
    
set textList_ref to a reference to textList
    
    
set colorList to color of every attribute run of front document
    
set colorList_ref to a reference to colorList
    
    
set aTest to contents of item 2 of textList
    
set asciiTest to id of aTest
  end tell
end using terms from

set tabChar to string id 9

–set TIDsList to {{"&", "&amp;"}, {">", "&gt;"}, {"<", "&lt;"}, {"¥"", "&quot;"}}
set TIDsList to {{"\\", "\"}, {"’", "’"}, {"&", "&amp;"}, {">", "&gt;"}, {"<", "&lt;"}, {"  ", "  "}, {string id 13, string id 10}, {string id 13, "<br>"}, {string id 10, "<br>"}, {"\"", "&quot;"}}
–set TIDsList to {{"&", "&amp;"}, {">", "&gt;"}, {"<", "&lt;"}, {"¥"", "&quot;"}}

set TIDsList_ref to a reference to TIDsList

set dataOut to {}
set dataOut_ref to a reference to dataOut

set iCounter to 1
repeat with i in textList_ref
  set j to contents of i
  
  
set curDelim to AppleScript’s text item delimiters
  
repeat with eachItem in TIDsList_ref
    set AppleScript’s text item delimiters to contents of item 1 of eachItem
    
set j to every text item of j
    
set AppleScript’s text item delimiters to contents of item 2 of eachItem
    
set j to j as string
  end repeat
  
set AppleScript’s text item delimiters to curDelim
  
  
set cText to RBG2HTML(item iCounter of colorList_ref) of me
  
  
set the end of dataOut_ref to "<font color=" & cText & ">" & j & "</font>"
  
set iCounter to iCounter + 1
end repeat

set htmlHeader to "<table width=" & quotChar & "100%" & quotChar & " border=" & quotChar & "0" & quotChar & "cellspacing=" & quotChar & "2" & quotChar & " cellpadding=" & quotChar & "2" & quotChar & ">
<tr>
<td bgcolor=\"#" & headerCol & "\"><font color=" & quotChar & "#FFFFFF" & quotChar & ">" & curLang & "名:" & c

if comText is not equal to "" then
  set comText to "<br><font size=" & quotChar & "2" & quotChar & ">【コメント】 " & comText & "</font><br>"
end if

set htmlHeader2 to "</font></td>
</tr>
<tr>
<td bgcolor=\"#" & bodyBackCol & "\"><font size=\"3\">"

set htmlFooter1 to "</font></td>
</tr>
<tr>
<td bgcolor=\"#" & footerCol & "\"><p><font size=\"2\"><a href=\"" & newLinkText & "\">★Click Here to Open This Script</a> </font></p>
</td>
</tr>
</table>
"

set dataText to htmlHeader & comText & htmlHeader2 & (dataOut as text) & htmlFooter1
set dataText to dataText as Unicode text

–set dDir to (path to desktop as text) & "index.html"
–write_to_file(dataText, htmlFilePath, false) of me
–saveInEncoding(dataText, htmlFilePath, "UTF8") of me –UTF8
write_to_file_Safely(dataText, htmlFilePath) of me

tell application id "com.apple.ScriptEditor2"
  display dialog "HTML書き出し完了" buttons {"OK"} default button 1 with icon 1 giving up after 1
  
return
end tell

on retHTMLpath(aF)
  tell application "Finder"
    –set aF to retMacOSpathList(aP) of me
    
set afA to aF as alias
    
set aInfo to info for afA
    
set aExt to name extension of afA
    
    
set aFileName to name of afA
    
set aFileName to aFileName as text
    
set aFileName to aFileName as Unicode text
    
    
set aFileName_rev to reverse of (every character of aFileName) as text
    
set parentF to ((parent of afA) as alias) as text
    
set htmlFileName to name of afA
    
set htmlFileName to htmlFileName as text
    
set htmlFileName to htmlFileName as Unicode text
    
    
    
if aExt is not equal to "" then
      set htmlFileNameText to ((reverse of (items ((length of aExt) + 2) thru -1 of aFileName_rev)) as text) & ".html"
    else
      set htmlFileNameText to (aFileName as text) & ".html"
    end if
    
set htmlFileNameFullPath to parentF & htmlFileNameText
  end tell
  
return htmlFileNameFullPath
end retHTMLpath

on makeEncodedScript(contText)
  (*

  set aList to every paragraph of contText
  set aClass to class of aList
  if aClass = list then
    set aLen to length of aList
  else
    set aLen to 1
  end if
  
  set aaList to {}
  
  set delim to AppleScript’s text item delimiters
  set AppleScript’s text item delimiters to "//piyomaru_replacement_temp//"
  set bList to aList as text
  set AppleScript’s text item delimiters to delim
  
  set aaList to (encodeURL(bList) of me) as Unicode text
  
  set search_string to "//piyomaru_replacement_temp//" as Unicode text
  set replacement_string to "%0A" as Unicode text
set bList to replace_chars(aaList, search_string, replacement_string) of me
*)

  
  
set aaList to (encodeURL(contText) of me) as Unicode text
  
  
return aaList
end makeEncodedScript

–RGB値からHTMLの色指定に変換
on RBG2HTML(RGB_values)
  — NOTE: this sub-routine expects the RBG values to be from 0 to 65536
  
set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
  
set the the hex_value to ""
  
repeat with i from 1 to the count of the RGB_values
    set this_value to (item i of the RGB_values) div 256
    
if this_value is 256 then set this_value to 255
    
set x to item ((this_value div 16) + 1) of the hex_list
    
set y to item (((this_value / 16 mod 1) * 16) + 1) of the hex_list
    
set the hex_value to (the hex_value & x & y) as string
  end repeat
  
return ("#" & the hex_value) as string
end RBG2HTML

–安全なファイルの書き出し
on write_to_file_Safely(this_data, target_file)
  tell current application
    set finalPath to target_file
    
    
–テンポラリフォルダに一度書き出して、ターゲットのパスに移動  
    
set tmpFol to path to temporary items from system domain
    
set tmpName to do shell script "date +%Y%m%d%H%M%S"
    
set tmpPath to (tmpFol as string) & tmpName
    
    
–テンポラリのパスにファイル書き出し
    
try
      set the target_file to the tmpPath as text
      
set this_data to this_data as Unicode text
      
      
set the open_target_file to open for access file target_file with write permission
      
set eof of the open_target_file to 0 –つねにoverwrite mode(appendではなくて)
      
write this_data to the open_target_file starting at eof as «class utf8»
      
close access the open_target_file
      
    on error error_message
      try
        close access file target_file
      end try
      
return error_message
    end try
    
    
–ファイルの移動を行う
    
set tFilePOSIX to quoted form of POSIX path of target_file
    
set fPathPOSIX to quoted form of POSIX path of finalPath
    
set sText to "mv " & tFilePOSIX & " " & fPathPOSIX
    
try
      do shell script sText
    on error error_message
      return error_message
    end try
    
    
return true
  end tell
end write_to_file_Safely

on replace_chars(this_text, search_string, replacement_string)
  set AppleScript’s text item delimiters to the search_string
  
set the item_list to every text item of this_text
  
set AppleScript’s text item delimiters to the replacement_string
  
set this_text to the item_list as string
  
set AppleScript’s text item delimiters to ""
  
return this_text
end replace_chars

on encodeURL(origStr as string)
  set aStr to current application’s NSString’s stringWithString:origStr
  
set encodedStr to aStr’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s alphanumericCharacterSet())
  
return encodedStr as string
end encodeURL

on retMacOSpathList(aFile)
  set aPath to POSIX file aFile
  
set aPath to aPath as alias
  
set aPath to aPath as string
  
set aPath to aPath as Unicode text
  
set aliasFileList to aPath
  
return aliasFileList
end retMacOSpathList

–ファイルの追記ルーチン「write_to_file」
–追記データ、追記対象ファイル、boolean(trueで追記)
on write_to_file(this_data, target_file, append_data)
  tell current application
    try
      set the target_file to the target_file as text
      
set the open_target_file to open for access file target_file with write permission
      
if append_data is false then set eof of the open_target_file to 0
      
write this_data to the open_target_file starting at eof
      
close access the open_target_file
      
return true
    on error error_message
      try
        close access file target_file
      end try
      
return error_message
    end try
  end tell
end write_to_file

on changeColor(aLang)
  if aLang = "AppleScript" then
    set headerCol to "0000CC" –"0000CC" –ヘッダー部分(濃い色)
    
set bodyBackCol to "EEFFFF" –"EEFFFF" –Script本文下地(薄い色)
    
set footerCol to "66FFFF" –"66FFFF" –スクリプトリンク部分
    
  else if aLang = "JavaScript" then
    set headerCol to "804000" –"0000CC" –ヘッダー部分(濃い色)
    
set bodyBackCol to "E2D3D3" –"EEFFFF" –Script本文下地(薄い色)
    
set footerCol to "E7AC53" –"66FFFF" –スクリプトリンク部分
  end if
end changeColor

★Click Here to Open This Script 

(Visited 251 times, 1 visits today)
Posted in OSA Text | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy Script Editor Script Menu | 15 Comments

OSADictionaryViewの情報がない

Posted on 10月 12, 2020 by Takaaki Naganoya

macOS 10.10以降、通常のAppleScriptでもCocoaオブジェクトへのアクセスが許可されたため、macOSの中に存在するAppleScript系の機能への理解が深まりました。

正確にいえばOS X 10.6でXcode上のCocoa AppleScriptアプリケーション内でCocoaの機能が利用できたわけですが、やはり通常のAppleScriptの中で利用できると理解の度合いが違います。

そうしたCocoaなどのmacOSのAPIは数多くあり、今日ではPDF関連の処理など専用のアプリケーションを使わずにたいていの処理ができるようになり、Web上のREST APIを自在に呼び出せるようになり、各種画像フィルタ処理や機械学習までAppleScriptから呼び出せるようになりました。Cocoaの機能が呼べなかった時代に戻れと言われたら途方に暮れてしまうレベルで日常的な風景になりました。

そんなmacOS側の機能に、AppleScript系の機能が用意されています。

大きく分けると、

①Cocoa系のOSAKit。AppleScriptを実行したりOSAコンポーネント情報を取得するなどの機能。AppleScriptから日常的によく使っています。

②AppKit内のNSAppleScript。AppleScriptの実行を行うための部品と、プロセス間通信のAppleEventsまわりの機能です。このあたりはAppleScriptからは手が出ません。

③Carbon系のOpenScripting。AppleScript言語処理系そのものといってよいでしょう。まったく手が出ません。

などの機能の所在がわかっています。Xcode上から調べるとヘッダーファイルも調査できて、どのようなメソッドが揃っているかも確認できます。

これらの他に、割とメジャーそうな機能なのにヘッダーファイルも何も一切公開されていないオブジェクトがあります。

それが、AppleScript用語辞書の表示関連のOSADictionaryViewとOSADictionaryControllerです。

これについては、不思議と情報が何もありません。あたりをつけて、「おそらくPathかURLをコントローラーに渡して初期化するとViewに表示するんだろう」と試しているのですが、まったく歯が立ちません。


▲macOS 10.14.6+Xcode 11.3.1の組み合わせで、OSADictionaryViewをドラッグ&ドロップで部品配置すると、その瞬間にXcodeがクラッシュ(事前にプロジェクトにOSAKit.frameworkをinclude)。この環境にはNSBrowserなど同様の瞬間クラッシュを引き起こす部品がある。macOS 10.15上では修正されているため、10.14上での対処は行わないとAppleから明言されました

とりあえずは、いつものアラートダイアログ上でOSADictionaryViewを表示して、指定のsdefファイルを表示するレベルからはじまって、GUIアプリケーション上でSDEF表示機能を実装するところがゴール地点でしょうか。失敗を重ねながら何度も調査やテストを行うことになります。

OSADictionaryView/OSADictionaryControllerの情報があったところで、これが使い物になるのかどうかという疑問があります。

OSADictionaryViewが使えたとして、それはsdefファイルのパスなりURLを渡して表示させるようなものになると想像されますが、このsdefに外部のファイルをincludeするような記述ができるようになったことで、「対象アプリケーションが実際に起動しないとAppleScript用語辞書全体を取得することができない」という状況に。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
	<!-- We override some standard commands to add several optional properties. -->
	<suite name="Standard Suite" code="????" description="Common classes and commands for all applications.">
		<xi:include href="file://localhost/System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite/node()[not((self::command and (@name = 'open')) or (self::class and (@name = 'window')))])"/>

▲最近のMicrosoft Officeアプリケーションでは、sdefのサイズ縮小のためかxi:includeの記述が見られる

Adobeのアプリケーションには、sdefファイルを起動後にプログラムで生成しているものもあるため、起動前の状態でsdefファイル単独でブラウズできてもあまり意味がないケースが生じてしまいます。

つまり、Viewを単体で利用できても不十分かつ部分的なAppleScript用語辞書しか表示できないのではないか? という疑問を持つわけです。


▲1:17秒あたりでToolbar上のコマンドからAppleScript用語辞書の表示を行わせています。これは、Script Editorに辞書の表示を行わせる処理です

実際、スクリプトエディタに指定アプリケーションのAppleScript用語辞書を表示するような命令は行えるので、結局はそちらを使うことになるのではないかと考えるものです。苦労して使い方を突き止めたとしても、実用性がなかったら残念なことです。そして、その可能性がきわめて高そうな気配がしているのです。

(Visited 66 times, 1 visits today)
Posted in GUI OSA | Tagged 10.14savvy 10.15savvy 11.0savvy | Leave a comment

osascript系のAppleScriptランタイムを区別する

Posted on 1月 18, 2020 by Takaaki Naganoya

AppleScriptのランタイム環境が何であるかを区別できるようになりました。

それらのうち、/usr/bin/osascriptを呼び出しているランタイム環境について、さらに細分化して個別に識別するために、ランタイム環境そのものと親プロセスが何であるかをAppleScriptで調査してみました。

結論からいえば、親プロセスが「bash」ならTerminalからosascriptコマンドで起動されたと判断してよさそう。その他は、実行されたScriptの置かれているパスを求めて、macOS標準装備のScript Menuかアプリケーション内部のScript Menuかを見分けるぐらいでしょうか。

これを判定したプログラム自体は、別に技術的にすごいとか機密の塊とかいうことはなくて、「清書してなくて、きたない。無駄に長い。掲載されているプログラムを見ても何も感じない」ことから掲載していません。実験用のテストプログラムでも、ちょっと近年稀に見るぐらいひどい出来です。内容は、単にランタイムプログラムのプロセスIDを取得して、そのプロセスIDをもとにpsコマンドで親プロセスを求めて、コマンドからいろいろ情報を抜いてくるというだけのものです。

Script Menu

ランタイムのパラメータ:/usr/bin/osascript -P /Users/me/Library/Scripts/Finder/pTEST.scptd
親プロセス:/System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService

与えられているScriptが特定フォルダ(/Users/me/Library/Scripts/)以下にあるものかどうか、という識別は可能。ちょっと、根拠が弱そうです。

CotEditor内のScript Menu

ランタイムのパラメータ:/usr/bin/osascript -sd -T 14534 -P /Users/me/Library/Application Scripts/com.coteditor.CotEditor/010)M-pM^_M^MM^NM-pM^_M^SM^\AppleScriptM-cM^AM-(M-cM^AM^WM-cM^AM-&M-hM-'M-#M-iM^GM^H/0020)M-pM^_M^SM^\M-fM-'M^KM-fM^VM^GM-gM-"M-:M-hM-*M^MM-cM^AM^WM-cM^AM-&M-eM-.M^_M-hM-!M^LM-cM^AM^WM-cM^@M^AM-pM^_M^SM^DM-fM^VM-0M-hM-&M^OM-fM^[M-8M-iM-!M^^M-cM^AM-+M-gM-5M^PM-fM^^M^\M-cM^BM^RM-eM^GM-:M-eM^JM^[.@r.scpt
親プロセス:/System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService

親プロセスはScript Menuと同じですが、こちらも実行しているScriptのパスが/Users/me/Library/Application Scripts/com.coteditor.CotEditor/以下であること。これも、識別のための根拠が弱いです。

Terminal経由でosascriptコマンド実行

ランタイムのパラメータ:osascript /Users/me/Desktop/pTEST.scptd
親プロセス:-bash

これは、親プロセスが-bashであることから、明確に区別できます。Terminal.appではなくbashなんですね。

Terminal経由で/usr/bin/osascript(フルパス指定)でコマンド実行

ランタイムのパラメータ:/usr/bin/osascript /Users/me/Desktop/pTEST.scptd
親プロセス:-bash

フルパスで指定すると何か変わってくるかとも思いましたが、とくに変化はありませんでした。

Program AS Style runtime name Parent Process Name Script Path
Script Editor Script/Scriptd Script Editor
Script Editor Cocoa-AppleScript Applet CocoaApplet
Script Editor Applet applet
Script Debugger Script/Scriptd Script Debugger
Script Debugger Applet (Enhanced) FancyDroplet
ASOBjC Explorer 4 Script/Scriptd ASOBjC Explorer 4
Automator Workflow Automator
Automator Applet Application Stub
Script Menu Script/Scriptd osascript …com.apple.foundation.UserScriptService /Users/me/Library/Scripts/ ほか
CotEditor Script osascript …com.apple.foundation.UserScriptService /Users/me/Library/Application Scripts/com.coteditor.CotEditor/
Terminal.app (osascript) Script/Scriptd osascript bash
(Visited 128 times, 1 visits today)
Posted in OSA shell script | Tagged 10.14savvy | Leave a comment

AppleScriptを実行中のランタイムプログラム名を取得する

Posted on 1月 18, 2020 by Takaaki Naganoya

AppleScriptのランタイムプログラム名を取得するAppleScriptです。AppleScript自身が「何によって」実行されているか、その実行プログラム名を取得するものです。

AppleScriptには何種類かランタイム環境が存在し、ランタイム環境ごとに若干の動作が変わってくることが知られています。

ランタイム環境ごとにどこが違うといえば、Finderからのselectionを取得できるとかできないとか(AppleScript Studioがこれに該当。もうありませんけれども)、GUI Scriptingの権限の認証を得られるとか得られないとか。ウィンドウを動的に生成して表示したときに最前面に表示できるとかできないとか(Script Menuがこれに該当)。明示的にメインスレッドで実行する機能がないとか(Script Debuggerがこれに該当)。そういうところです(ほかにもあるかもしれない)。

過去に作ったAppleScriptを確認していたところ、プロセス名を取得するだけの使えないプログラムだと思っていたものが、実は「ランタイムプログラムのプログラム名」を取得できるというスゲーものであることを再発見しました。

ながらく、ランタイムプログラム名をAppleScript側から取得する必要性を感じていたため、この機会に調べてみることに。プログラム自体は些細な(↓)ものです。

AppleScript名:ランタイム環境名の表示
— Created 2015-09-08 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set procInfo to current application’s NSProcessInfo’s processInfo()
set aName to procInfo’s processName() as string
display dialog aName

★Click Here to Open This Script 

Script Editor上で実行


–> “Script Editor”

Script Debugger上で実行


–> “Script Debugger”

ASObjC Explorer 4上で実行


–> “ASObjC Explorer 4”

Automator上で実行


–> “Automator”
これには驚きました。特別のランタイムプログラムが使われているのか、それとも単に親プロセスとしてのAutomatorが返ってきているのかは不明ですが、識別できるということには意義がありそうです。

Script Menu上で実行


–> “osascript”
これは、よく知られていることなのでとくに驚きはありません。テストを実施したのはmacOS 10.14.6上で、Script Menuは「スクリプトメニュー」という別アプリケーション(/System/Library/CoreServices/ にある)に変更になったOSバージョンですが、ランタイムにosascriptを使い続けていることを確認することになりました(それ以前のOSと挙動が同じなのでそうだと思っていましたけれども)。

Folder Action上で実行




–> “osascript”
Folder Actionは、macOS標準搭載のフォルダ監視機能です。監視対象のフォルダにファイルが追加されたり、移動されたり、フォルダそのものがオープンしたりするとその対象ファイル/フォルダで指定のAppleScriptを実行します。よく、ドラッグ&ドロップで処理を受け付けたり、ネットワーク経由でファイルを受信した場合にAppleScriptを実行するような使われ方をします。
Folder Action Disptcherが実行しているとばかり思っていたのですが、実際に確認したらosascriptでした。ちなみに、Folder ActionはmacOS 10.11でフルに書き換えられてそれ以前とは別物になっています。以前は数秒に一度対象フォルダをチェックする方式でしたが、10.11以降はFSEventsを利用して随時監視対象フォルダへの変更を受け付けます。

Switch Control上で実行



–> “osascript”
障害者向けの機能としてmacOSに標準装備されている、フローティングパレットからAppleScriptを呼び出せる機能である「Switch Control」。手を使わずに操作したり、他のコントローラで操作するような標準的ではない使い方をサポートするための機構ですが、普通に普通の人が使っても役立ちます。 
Switch ControlでAppleScriptを実行する場合のランタイムプログラムはosascriptです。

CotEditor上で実行


–> “osascript”
これは、CotEditorのソースを読んで確認してありました。ここだけ割と手抜き実装ですが、それでも複数のOSA言語に対応できたりと機能的には悪くはありません。むしろ、osascript側のランタイム環境が他の環境よりも一段落ちることに問題が、、、、GUI Scriptingの権限を取得できないこととか、このCotEditorのメニューから実行するとREST APIが呼び出せないとか。同じosascript系でもScript Menuのほうが制約が少ないのは、おそらくアプリケーション自体に許可されている条件の違いによるものでしょう。

FileMaker Pro上でスクリプトステップ「AppleScriptを実行」を実行


–> “FileMaker Pro”
FileMaker Proはランタイムアプリケーションが廃止され、FileMaker Pro AdvancedもFileMaker Proに一本化されたので、v19以降はFileMaker Proは「FileMaker Pro」というランタイムのみでしょう。v19でもFileMaker Pro自体はSandbox化されていないため、微妙にセキュリティ上の制約が少ない=自由度の高いランタイム環境として残っていくことでしょう。

Script EditorからApplet書き出しして実行


–> “applet”
取得できたらいいなぐらいの気持ちで試してみたものの、これが識別できるのはうれしい誤算です。書き出したAppleScript Applet名は「Appletでランタイム名を取得」であったため、この「applet」というものとは異なります(ねんのため)。

AutomatorからApplet書き出しして実行


–> “Application Stub”
見たことのない名前が、、、、やっぱり、これも別ランタイムなんですね、、、、

Script DebuggerからApplet(Enhanced)で書き出しして実行


–> “FancyDroplet”
Appleの標準ランタイムとはあきらかに別物(Enhanced)なので、たぶん別の名前がついているだろうとは思っていましたが、そういう名前でしたか。名前が予想外だったので驚かされましたが、識別できることに意義があります。

Cocoa-AppleScript Appletを実行


–> “CocoaApplet”
Script Editor上で作成できる、通常のAppleScriptとXcode上で作成するCocoa-Applicationの中間的な性格を持つ「Cocoa-AppleScript Applet」でランタイムプログラム名を取得したらこうなりました。

もちろん、実行プログラム名はまったく別の「ランタイム名を表示するだけのCocoa-AppleScript Applet」というものです。

ショートカットで「AppleScriptを実行」アクションを実行


–> “MacHelper”

macOS 12で搭載されたショートカット.app(Shortcuts.app)および不可視プロセスのAppleScriptの補助専用アプリケーション「Shortcuts Events.app」上で、アクション「AppleScriptを実行」でAppleScriptを実行するときのランタイム名は、「MacHelper」です。意外なところで、ユーザーディレクトリ以下にインストールされたAppleScriptライブラリをこのMacHelper環境は認識します。

RedSweater Software「FastScripts」からAppleScriptを実行

red sweater softwareによるメニュー常駐型Script Menuソフトウェア「FastScripts」から実行したときのランタイム名は「FascScripts Script Runner」です。

Knurling Group「Service Station」からAppleScriptを実行

Knurling Groupによるコンテクストメニューのカスタマイズ・ソフトウェア「Service Station」から実行したときのランタイム名は「osascript」です。

ランタイム名が得られることで実現できること

これらのほか、各アプリケーション内でAppleScript呼び出し機能を有するもの(ファイルメーカー、Mail.appなど)でランタイムプログラム名を取得すると有益な情報が得られることでしょう。

これは、地球上にいる人類が観測衛星を打ち上げて「ここは銀河系だ」と観測できるぐらいすごいことなので、割と意義深いものです。実行中のAppleScriptが、「いま、何のプログラムによって自分自身が実行されている」かという情報を取得できます。

ランタイムプログラムの名称取得については、いくつかのAppleScript実行方法を試してみましたが、得られる名前に違いがないことを確認しています。

直接AppleScriptを動かす方法に加え、間接的にAppleScriptを動かす方法も試してみましたが、同じ結果が得られました。

つまり、動的にOSAScriptViewを生成して実行しようが、NSAppleScriptで実行しようが、AppleScriptの「run script」コマンドで実行しようが、取得されるランタイム名には差がありません。

これで、ランタイム環境のプロセスの親プロセスの情報が取得できると、Terminal.app上から起動したosascriptコマンドで呼び出したのか、Script Menu上から呼び出したのかという状況をAppleScript側で認識できることになることでしょう。

ランタイム環境を識別した上で、各環境で実行できない処理を行わないとか、ランタイム環境ごとに処理を分岐できるようになることでしょう。

ちょうど、Edama2さんと「ランタイム環境ごとに若干の挙動の違いが見られるし、利用できるCocoaの機能にも違いがあるから、ランタイム環境ごとに認識コードでも振ってみようか」などと相談していたので、渡りに船でした。

(Visited 118 times, 1 visits today)
Posted in OSA | Tagged 10.13savvy 10.14savvy 10.15savvy Automator CotEditor Script Debugger Script Editor | Leave a comment

AppleScript, my(me), it

Posted on 1月 8, 2020 by Takaaki Naganoya

Script Object関連の調べ物をしていて、AppleのWebサイト掲載のReferenceを見ていたら、サンプルをまじえて説明されていたので、理解が深まりました。

AppleScript:トップレベルObject。不変
my(me):現在のScript Object。可変
it:現在のアプリケーションObject。可変

AppleScript > my(me) ≧ it

というレベルになっていることもよく理解できました。

ただ、サンプルが自分的にいまひとつわかりやすくなかったので、自分用に書き換えてみました。バージョン取得ではなく、「名前を取得」しないといまひとつ分からないんじゃないでしょうか。

AppleScript名:testScript
me
–> «script»–実行中のAppleScript書類(Script Object)

AppleScript
–> «script AppleScript»

it
–> «script»–current target object

tell application "Finder"
  it
  
–> application "Finder"–current target object
  
  
–testMe() –> error "Finderでエラーが起きました: testMeを続けることができません。" number -1708
  
testMe() of me
  
testMe() of aTEST of me
  
testMe() of bTEST of aTEST of me
end tell

on testMe()
  set aName to name of me
  
–> "testScript"
  
display dialog aName –Name of this AppleScript document file
end testMe

script aTEST
  on testMe()
    set aName to name of me
    
–> "aTEST"
    
display dialog aName –Name of this script object (aTEST)
  end testMe
  
  
script bTEST
    on testMe()
      set aName to name of me
      
–> "bTEST"
      
display dialog aName –Name of this script object (bTEST)
    end testMe
  end script
end script

★Click Here to Open This Script 

(Visited 147 times, 1 visits today)
Posted in OSA | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | Leave a comment

指定文字列のAppleScriptを実行してエラー詳細を取得

Posted on 1月 1, 2020 by Takaaki Naganoya

指定文字列のAppleScriptをコンパイル(構文確認、中間コードへのコンパイル)、実行してエラーの詳細を取得するAppleScriptです。

AppleScript名:指定文字列のAppleScriptを実行してエラー詳細を取得.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/01/01
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set asSourceString to "set a to 123
beepz"
–This AppleScript text has an error

set asObj to current application’s NSAppleScript’s alloc()’s initWithSource:(asSourceString)

–AppleScriptオブジェクトがコンパイル(構文確認、中間コードへの解釈)ずみかどうかをチェック
set isCompiledF1 to asObj’s isCompiled()
–> false

–コンパイル(構文確認)してエラー確認
set isCompiledF2 to asObj’s compileAndReturnError:(reference)
–> {true, missing value}

set exeRes1 to asObj’s executeAndReturnError:(reference)
–> {<NSAppleEventDescriptor: null()>, missing value}–No error

–> {missing value, (NSDictionary) {NSAppleScriptErrorMessage:"beepz変数は定義されていません。", NSAppleScriptErrorBriefMessage:"beepz変数は定義されていません。", NSAppleScriptErrorNumber:-2753, NSAppleScriptErrorRange:(NSConcreteValue) NSRange: {13, 5}}}

★Click Here to Open This Script 

(Visited 49 times, 1 visits today)
Posted in OSA | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAppleScript | Leave a comment

display text fields Library v1.3

Posted on 12月 31, 2019 by Takaaki Naganoya

「display text fields」AppleScriptライブラリをv1.3にアップデートしました。

–> Download display text fields_v13 (To ~/Library/Script Libraries/)

v1.3ではテキストフィールドの最大横幅の計算を修正し、フィールド数が増えたときにダイアログ上から項目がはみ出さないようにScroll Viewをつけるようにしました。

本来目的としていた用途に使ってみたらイマイチだった点を修正した格好です。AppleScriptで取得した各種アプリケーションのオブジェクトのプロパティ情報をダイアログ上で一覧表示して確認するというのが、自分がこのライブラリを作った目的です。

以下は、サンプルスクリプト「文字列で指定したAppleScriptの実行結果をテキストで取得する v2」についての説明です。

割とえげつない処理をしていますが、作りためておいたルーチンを引っ張り出してきただけなので、書くのにさほど時間はかけていません。

こうしたAppleScriptのプロパティ値をparseするには、スクリプトエディタの結果欄を文字列として取得するか(GUI Scripting経由でやったことがあります)、こうしてメモリ上にスクリプトエディタ+結果表示用のビューを生成してメモリ上でAppleScriptを実行して結果をテキストで取得するということになると思います。前者だとGUI Scriptingの実行権限が必要になるため、Cocoaの機能を利用したほうが手軽という状況です。

(途中で入れ替えた)v2では、macOS 10.15対応、ランタイム環境によってはうまく動かない「as anything」の使用をやめるなどの変更を加えました。

AppleScript名:文字列で指定したAppleScriptの実行結果をテキストで取得する v2.scpt
— Created 2016-01-08 by Takaaki Naganoya
— 2016 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "OSAKit"
use framework "AppKit"
use tfLib : script "display text fields"

property OSAScript : a reference to current application’s OSAScript
property NSTextView : a reference to current application’s NSTextView
property OSAScriptView : a reference to current application’s OSAScriptView
property OSAScriptController : a reference to current application’s OSAScriptController

property myRes : ""

–OSのメジャーバージョンを数値で取得
set osVer to system attribute "sys2"

if osVer ≥ 15 then
  set srcStr to "tell application \"Music\"
  set aSel to first item of selection
  set aRes to (properties of aSel)
end tell"
else
  set srcStr to "tell application \"iTunes\"
  set aSel to first item of selection
  set aRes to (properties of aSel)
end tell"
end if

my performSelectorOnMainThread:"getResultStringFromScript:" withObject:(srcStr) waitUntilDone:true

set aRes to getListFromText(myRes) of me

set aList to {}
set bList to {}
set aLen to length of aRes

repeat with i from 1 to aLen
  set {aCon, bCon} to contents of item i of aRes
  
set the end of aList to aCon
  
set the end of bList to bCon
end repeat

confirm text fields main message "Track Info" sub message "Properties about selected track" key list aList value list bList

–Get AppleScript’s Result as string
on getResultStringFromScript:paramObj
  set srcStr to paramObj as string
  
set myRes to ""
  
  
set targX to 500 –View Width
  
set targY to 200 –View Height
  
  
set osaCon to OSAScriptController’s alloc()’s init()
  
set osaView to OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
  
set resView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
resView’s setRichText:true
  
resView’s useAllLigatures:true
  
  
osaCon’s setScriptView:osaView
  
osaCon’s setResultView:resView
  
  
osaView’s setString:srcStr
  
osaCon’s runScript:(missing value)
  
  
set myRes to resView’s |string|() as string
end getResultStringFromScript:

–スクリプトエディタのresult欄に返ってきたテキストをリストに変える
on getListFromText(aText)
  
  
script getListFromTextO
    property aaText : ""
    
property gList : {}
    
property outList : {}
    
property aG : ""
    
property valList : {}
  end script
  
  
copy aText to (aaText of getListFromTextO)
  
  
set (gList of getListFromTextO) to {}
  
set (outList of getListFromTextO) to {}
  
set (aG of getListFromTextO) to ""
  
set (valList of getListFromTextO) to {}
  
  
if (aaText of getListFromTextO) does not start with "{" and (aaText of getListFromTextO) does not end with "}" then
    return {}
  end if
  
  
set aLen to length of (aaText of getListFromTextO)
  
set (aG of getListFromTextO) to text 2 thru -2 of (aaText of getListFromTextO)
  
set (gList of getListFromTextO) to characters of (aG of getListFromTextO)
  
  
  
set sPos to 2 –1文字目は\"{\"なので2文字目からスキャンを開始する
  
set ePos to 2
  
  
set imdF to false –Immediate Data Flag(文字列中を示すダブルクォート内の場合にはtrueになる)
  
set listF to 0 –stacking段数が入る
  
  
set attrF to true –属性ラベルスキャン時にtrue、データ末尾スキャン時にfalse
  
  
  
repeat with i in (gList of getListFromTextO)
    
    
set j to contents of i
    
    
if attrF = true and imdF = false and listF = 0 then
      
      
–属性値部分の末尾検出
      
if j = ":" then
        if text sPos thru sPos of (aaText of getListFromTextO) = " " then
          set sPos to sPos + 1
        end if
        
set anOut to text sPos thru ePos of (aaText of getListFromTextO)
        
set sPos to ePos + 1
        
set the end of (valList of getListFromTextO) to anOut
        
set attrF to false –データのスキャンを開始する
        
set imdF to false
        
set listF to 0
      end if
      
    else if imdF = false and listF = 0 and j = "," then
      
      
–データ部分の末尾検出
      
set anOut to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
      
set sPos to ePos + 1
      
set the end of (valList of getListFromTextO) to anOut
      
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
      
set (valList of getListFromTextO) to {}
      
      
set attrF to true –次が属性値ラベルであることを宣言
      
set imdF to false
      
set listF to 0
      
    else if j = "{" then
      if imdF = false then
        set listF to listF + 1 –1段スタックにpush
      end if
    else if j = "}" then
      if imdF = false then
        set listF to listF – 1 –1段スタックからpop
      end if
    else if j = "\"" then
      if imdF = true then
        set imdF to false
      else
        set imdF to true
      end if
    end if
    
    
set ePos to ePos + 1
    
  end repeat
  
  
–ラストのデータ部分を出力
  
try
    set the end of (valList of getListFromTextO) to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
    
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
  on error
    false
  end try
  
  
return contents of (outList of getListFromTextO)
  
end getListFromText

★Click Here to Open This Script 

(Visited 61 times, 1 visits today)
Posted in dialog GUI OSA | Tagged 10.13savvy 10.14savvy 10.15savvy iTunes NSTextView OSAScript OSAScriptController OSAScriptView | Leave a comment

AppleScriptのプログラムの実行を(プログラム的に内部から)止める

Posted on 10月 5, 2019 by Takaaki Naganoya

どこでもプログラムを止める方法についてです。

一般的には、メインのrunハンドラ(記述されていない暗黙のrunハンドラ内)でreturnコマンドを実行すると、実行を終了します。スクリプトエディタ上で実行した場合には、基本的にそういう動作です(「ハンドラの実行後に終了しない」にチェックを入れてアプレット書き出しした「Stay Open Applet」ではアプレットは終了しませんが、実行中の処理自体は止まります)。runハンドラからサブルーチン(ハンドラ)を呼び出している場合には、returnコマンドを実行するとrunハンドラ側に戻ってくるだけです。

# Cocoaの機能を使ってタイマーオブジェクト(NSTimer)を作成して定期的に処理呼び出しするように宣言するとか、ノーティフィケーション宣言してメモリ上にオブジェクトを作ってイベントを受信するとか、そういうScriptを実行した場合にはメモリ上にオブジェクトが常駐しているかぎり実行は止まりません(この場合、スクリプトエディタを終了させるとオブジェクトも消えて動作が完全停止)

以前に、AppleScriptの実行を止めるためにさまざまな方法で、「止めるためのアクション」を検出する方法について紹介したことがあります。

ただ、ユーザーの停止要求を受け付けても、その場ですぐに止められるかどうかは別問題です。止めるためにループで条件を検出(キー入力や特定フォルダ内のファイル/フォルダの存在確認)などを行い、止めるために全力を尽くしていました。

どこでも好きなタイミングで、メインループのような場所でもなく、呼び出されたサブルーチン内などで好きに止めたい、という場合の方法をまとめてみました。

簡単にいえば、エラーを起こして止めることになるわけですが、ダイアログでCancelボタンを押したのと同じ(害のない)エラーコードを指定します。

AppleScript名:abort script
repeat 10 times
  display dialog "TEST" buttons {"OK"} default button 1
  
error number -128
  
–> error "ユーザによってキャンセルされました。" number -128 from «script» to item
end repeat

★Click Here to Open This Script 

AppleScript名:abort script 2
on run
  display dialog "run"
  
sub1() of me
end run

on sub1()
  display dialog "sub1"
  
sub2() of me
end sub1

on sub2()
  display dialog "sub2"
  
error number -128 –ここで止まる
  
–> error "ユーザによってキャンセルされました。" number -128 from «script» to item
end sub2

★Click Here to Open This Script 

(Visited 205 times, 1 visits today)
Posted in OSA System | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

pickup color Script Library

Posted on 8月 31, 2019 by Takaaki Naganoya

指定した複数の色からどれかを選ぶコマンドを提供するAppleScriptライブラリ+呼び出しサンプルScriptです。

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

使い道があるんだかないんだか微妙ですが、本来であれば何らかの画像を入力して、画像内の色をポスタライズして色数を減らし、その上で本ライブラリのようなインタフェースを用いて色選択。元画像のうち選択色の占めるエリアをダイアログ上で点滅表示……という処理が行いたいところです。

アラートダイアログのアイコン表示部分は、本来なら実行をリクエストしたアプリケーションのアイコンが表示されますが、選択色のプレビュー領域に使ってみました。このアイコン表示は最前面のアプリケーションのアイコンが入るべきという「ルール」があるわけですが、最前面のアプリケーションが何であるかは分かりきっています。

別の運用方法でもっと便利になるのであれば、そういうことを試してみてもいいでしょう。


▲本来は、指定画像中の色を検出して、選択した色が表示されているエリアのみ点滅表示させたい。Xcode上で作ればできそう、、、、

また、Frameworkを呼び出してNSImageから色名をダイナミックに生成するという処理も、ライブラリとして運用するために取り外していますが、これも取り外したくはない部品です。

本来やりたい処理のすべてができているわけではないので、本ライブラリはまだまだ試作品レベルです。

色データを8ビットの整数値で与えるか、16ビットの整数値で与えるかをEnum「max255」「max65535」で表現していますが、もう少しスマートに表現したいところです。

AppleScript名:pickup color sample
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/31
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use colPic : script "pickup color"

set ap1List to {{65535, 0, 65535}, {0, 32896, 16448}, {65535, 65531, 2689}, {0, 32896, 65535}, {8608, 65514, 1548}, {46003, 46003, 46003}, {19702, 31223, 40505}}

set cRes to pickup color ap1List main message "Color Dialog" sub message "Choose a color from popup button" color max max65535

★Click Here to Open This Script 

(Visited 49 times, 1 visits today)
Posted in Color GUI OSA Script Libraries sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

display YouTube Script Library

Posted on 8月 25, 2019 by Takaaki Naganoya

アラートダイアログ上で指定URLのYouTubeムービーを再生表示するAppleScriptライブラリ+呼び出しサンプルです。

用途はお察しですが、あまり実用性をねらったものではありません。

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

この、「display youtube」という用語が微妙にGoogleの商標を侵害していそうなので、用語辞書内で説明して逃げを打っていますがどんなもんでしょうか。

display youtubeコマンドにURLを指定すると、

https://www.youtube.com/watch?v=XXXXXXXX

という表記のURLを、ライブラリ内部で、

https://www.youtube.com/embed/XXXXXXXX

と書き換えて表示しています。また、組み込み再生用のオプションと、高解像度表示用のオプションを追加で指定しています。

AppleScript名:display youtube 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 scripting additions
use utbLib : script "display youtube"

set aURL to "https://www.youtube.com/watch?v=GP_tVXTYdmY"
display youtube main message "Replay Movie" sub message "My Senjo No Kizuna replay movie on YouTube" with URL aURL with size {600, 400}

set bURL to "https://www.youtube.com/embed/GP_tVXTYdmY"
display youtube main message "Replay Movie" sub message "My Senjo No Kizuna replay movie on YouTube" with URL bURL with size {900, 600}

★Click Here to Open This Script 

(Visited 46 times, 1 visits today)
Posted in dialog GUI OSA sdef URL | Tagged 10.12savvy 10.13savvy 10.14savvy | 1 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 

(Visited 61 times, 1 visits today)
Posted in GUI OSA sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a 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

(Visited 159 times, 1 visits today)
Posted in JXA OSA sdef | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | 1 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 

(Visited 46 times, 1 visits today)
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 

(Visited 108 times, 1 visits today)
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

Handle diff v2

Posted on 7月 3, 2019 by Takaaki Naganoya

Script Debugger上でオープン中の2つのAppleScript書類のうち、名称が同じハンドラ(サブルーチン)の内容同士を比較して、お互いに合っているかどうかをチェックするAppleScriptです。

アプリケーション書き出しして、Script Debuggerのスクリプトメニューに入れて実行します(AppleScript書類のままだと、Myriad Tables Lib内のフレームワークが呼べないため)。


▲本Scriptはスクリプトエディタの環境設定で行うAppleScriptの構文色分け設定色が「RGBカラー」でないとエラーになります。CMYKとかグレースケールカラーで指定して、そのままRGBに変換されずに保持される(CMYK色はアクセスしているうちにRGBに変換されるが、グレースケールは保持される)ため、色空間の判定を行ってRGB色に変換してから処理する必要があります(自分用メモ)

スクリプトエディタ上で設定する構文色分け設定をもとに、AppleScriptの構文要素を考慮したハンドラ一覧を作成し、2つのAppleScript書類の間に共通して存在するハンドラ名のハンドラ(サブルーチン)のAppleScriptソースを取得。インデント(tab)を削除したのちに比較を実行。

共通名称のハンドラすべてをチェックして、結果を表インタフェースで表示します。初版(v1)では実行するたびに1つのハンドラをチェックしていたのですが、あまりにかったるいので即座にループですべて調べてまとめて結果を表示するようにしました(v2)。

–> download executable archive (mainly for macOS 10.14 or later)

ただし、1つのAppleScript書類内にScript Object(JavaScriptでいうところのClosureみたいなもの)で論理分割された同名のハンドラが複数回登場するパターンは想定していません。複数検出するとエラーになります。

とくにScript Debuggerを対象にせずスクリプトエディタを対象にしてもよいのですが、些細な変更で実現できるため、興味のある方はやってみてください。あと、本Scriptは必要に迫られまくって作ったものなので、動作でおかしい箇所があったらぜひぜひご指摘を。

個人的には、ハンドラ名称を構文要素を考慮しつつ取得している一方で、ハンドラの内容は単なる文字列検索で取り出しているというあたりにアンバランスさを感じます。ただ、趣味のScriptではないので若干の手抜きを(^ー^;;

macOS 10.14.5上のスクリプトエディタで、構文色分け情報を何回設定しても「黒」になるという現象に遭遇したのですが、他のユーザー環境上での再現性については未知数であるため、まだレポートできない状況です。

→ その後、本ツールは強化されて、構文色分け設定にRGB以外の色が設定してあってもRGBに変換して処理する機能や、構文色分け設定を参照したコメント除去機能や、各種書式情報の取得を3倍高速化するカラーキャッシュなどの機能を実装したプログラムに(必要に迫られて)成長しました。

AppleScript名:Handle diff v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/07/02
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.5" — Sierra (10.12) or later (maybe 10.11 is OK but not confirmed)
use framework "Foundation"
use scripting additions
use framework "OSAKit"
use script "Myriad Tables Lib" version "1.0.9" –https://www.macosxautomation.com/applescript/apps/Script_Libs.html

property NSArray : a reference to current application’s NSArray
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 NSCountedSet : a reference to current application’s NSCountedSet

–構文色分け設定に重複色がないかチェック
set cList to getAppleScriptSourceColors() of me
set cRes to chkASLexicalFormatColorConfliction(cList) of me –構文色分けの重複色チェック
if cRes = false then error "There is some duplicate(s) color among AppleScript’s lexical color settings"

–Script Debugger上でオープン中の2つのAppleScript書類のパスを取得
set dList to retTwoPathList() of me
if dList = false then return

copy dList to {d1Path, d2Path}

–各AppleScript書類のハンドラ名称一覧を取得する
set hList1 to retHandlerNamesFromAppleScriptSource(d1Path as alias) of me
set hList2 to retHandlerNamesFromAppleScriptSource(d2Path as alias) of me

–2つのAppleScript書類のハンドラの共通項目(名称のみ)を抽出する
set resList to returnDuplicatesOnly(hList1 & hList2) of me
if resList = {} then
  –共通のハンドラ(サブルーチン)が指定の2つのScriptに存在していなかった
  
display dialog "There is no common handler between the scripts." buttons {"OK"} default button 1
  
return
end if

–各AppleScript書類のソースを取得して、指定のハンドラのテキストを取得する
set s1Source to getASsourceFor(d1Path as alias) of me
set s2Source to getASsourceFor(d2Path as alias) of me

if (s1Source = false) or (s2Source = false) then
  display dialog "Error occured in getteing AS source" buttons {"OK"} default button 1
  
return
end if

set outList to {}
repeat with i in resList
  set resHandler to contents of i
  
set s1Source to extractHandlerSourceOnly(s1Source, resHandler) of me
  
set s2Source to extractHandlerSourceOnly(s2Source, resHandler) of me
  
set compareF to (s1Source is equal to s2Source) as boolean
  
set the end of outList to {resHandler, compareF}
end repeat

–結果表示
tell me to activate
display table with data outList with prompt "Handler contents compare results" column headings {"Handler name", "Match?"} with title "Handler Diff Results"

–指定のハンドラの内容を抽出する(コメントぐらいは結果から削除してもいいような気もする)
–Script Objectの使用は考慮していない。1つのAppleScript書類からScript Objectで論理分割された同名のハンドラが複数検出されるケースは想定していない
on extractHandlerSourceOnly(wholeScript as string, handlerName as string)
  –インデント文字(Tab)をすべて削除
  
set targScript to repChar(wholeScript, tab, "") of me
  
  
–"on"ではじまるハンドラと仮定して抽出
  
set handlerStr to extractStrFromTo(targScript, "on " & handlerName, "end " & handlerName) of me
  
if handlerStr = false then
    –"to"ではじまるハンドラと仮定して抽出
    
set handlerStr to extractStrFromTo(targScript, "to " & handlerName, "end " & handlerName) of me
    
if handlerStr = false then return false
  else
    return handlerStr
  end if
end extractHandlerSourceOnly

on retHandlerNamesFromAppleScriptSource(aFile)
  set aRec to getAttrRecFromASPath(aFile) of me
  
set cList to getAppleScriptSourceColors() of me
  
  
set targAttr to contents of item 7 of cList –ハンドラあるいは変数
  
set tmpCoStr to ((redValue of targAttr) as string) & " " & ((greenValue of targAttr) as string) & " " & ((blueValue of targAttr) as string)
  
  
set ontoColItem to contents of item 3 of cList –スクリプティング予約語(on/to)
  
set ontoCoStr to ((redValue of ontoColItem) as string) & " " & ((greenValue of ontoColItem) as string) & " " & ((blueValue of ontoColItem) as string)
  
  
  
–変数あるいはハンドラ名称をリストアップ(variables & handler)
  
set tmp1Array to NSArray’s arrayWithArray:aRec
  
set thePred0 to NSPredicate’s predicateWithFormat_("colorStr == %@", tmpCoStr)
  
set dArray to (tmp1Array’s filteredArrayUsingPredicate:thePred0) as list
  
  
–改行を含むデータをリストアップ(text data contains return)
  
set thePred1 to NSPredicate’s predicateWithFormat_("stringVal CONTAINS %@", return)
  
set eArray to ((tmp1Array’s filteredArrayUsingPredicate:thePred1)’s valueForKeyPath:"itemIndex") as list
  
  
set the beginning of eArray to 0 –ハンドラ宣言部がTopに来る場合に備える
  
  
–"on"(ハンドラ宣言)の項目をリストアップ 文字と色で抽出
  
set thePred2 to NSPredicate’s predicateWithFormat_("stringVal == %@ && colorStr == %@ ", "on", ontoCoStr)
  
set fArray to ((tmp1Array’s filteredArrayUsingPredicate:thePred2)’s valueForKeyPath:"itemIndex") as list
  
  
–"to"(ハンドラ宣言ないしは代入対象指定) の項目をリストアップ文字と色で抽出
  
set thePred3 to NSPredicate’s predicateWithFormat_("stringVal == %@ && colorStr == %@ ", "to", ontoCoStr)
  
set gArray to ((tmp1Array’s filteredArrayUsingPredicate:thePred3)’s valueForKeyPath:"itemIndex") as list
  
  
  
set handlerList to {}
  
  
–on ではじまるハンドラの抽出
  
repeat with i in eArray –改行を含むテキストのアイテム番号リスト
    set j to (contents of i) as integer
    
repeat with ii in fArray –"on"の項目リスト
      set jj to (contents of ii) as integer
      
      
set handlerStr to missing value
      
      
if (j + 1) = jj then
        set handlerStr to stringVal of (item (jj + 2) of (aRec as list))
      else if (j + 2) = jj then
        set handlerStr to stringVal of (item (jj + 2) of (aRec as list))
      end if
      
      
if handlerStr is not in {"error", missing value} and handlerStr is not in handlerList then
        set the end of handlerList to handlerStr
      end if
      
    end repeat
  end repeat
  
  
  
–to ではじまるハンドラの抽出
  
repeat with i in eArray –改行を含むテキストのアイテム番号リスト
    set j to (contents of i) as integer
    
repeat with ii in gArray –"to"の項目リスト
      set jj to (contents of ii) as integer
      
      
set handlerStr to missing value
      
      
if (j + 1) = jj then
        set handlerStr to stringVal of (item (jj + 2) of (aRec as list))
      else if (j + 2) = jj then
        set handlerStr to stringVal of (item (jj + 2) of (aRec as list))
      end if
      
      
if handlerStr is not in {"error", missing value} and handlerStr is not in handlerList then
        set the end of handlerList to handlerStr
      end if
      
    end repeat
  end repeat
  
  
return handlerList
end retHandlerNamesFromAppleScriptSource

–ソースを取得してコンパイル(構文確認)する方式から、URL(fileURL)を指定してコンパイル(構文確認)する方式に変更した
on getAttrRecFromASPath(aFile)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFile)
  
set theScript to OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
  
  
if theScript is equal to missing value then
    — handle error
    
error "Compile Error"
  else
    –set sourceText to theScript’s source() –No Use
    
set styledSourceText to theScript’s richTextSource()
  end if
  
  
set attrRes to getAttributeRunsFromAttrString(styledSourceText) of me
  
return attrRes
end getAttrRecFromASPath

–指定AppleScriptファイルのソースコードを取得する(実行専用Scriptからは取得できない)
— Original Created 2014-02-23 Shane Stanley
on getASsourceFor(anAlias as {alias, string})
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
set theScript to OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
  
  
if theScript is equal to missing value then
    — handle error
    
error "Compile Error"
  else
    set sourceText to theScript’s source()
  end if
  
  
return sourceText as string
end getASsourceFor

–Attributed StringをDictionary化
on getAttributeRunsFromAttrString(theStyledText)
  script aSpd
    property styleList : {}
  end script
  
  
set (styleList of aSpd) to {} —for output
  
  
set thePureString to theStyledText’s |string|() –pure string from theStyledText
  
  
set theLength to theStyledText’s |length|()
  
set startIndex to 0
  
set itemCount to 1
  
  
repeat until (startIndex = theLength)
    set {theAtts, theRange} to theStyledText’s attributesAtIndex:startIndex longestEffectiveRange:(specifier) inRange:{startIndex, theLength – startIndex}
    
    
–String  
    
set aText to (thePureString’s substringWithRange:theRange) as string
    
    
–Color
    
set aColor to (theAtts’s valueForKeyPath:"NSColor")
    
if aColor is not equal to missing value then
      set aSpace to aColor’s colorSpace()
      
      
set aRed to (aColor’s redComponent()) * 255
      
set aGreen to (aColor’s greenComponent()) * 255
      
set aBlue to (aColor’s blueComponent()) * 255
      
      
set colList to {aRed as integer, aGreen as integer, aBlue as integer} –for comparison
      
set colStrForFind to (aRed as integer as string) & " " & (aGreen as integer as string) & " " & (aBlue as integer as string) –for filtering
    else
      set colList to {0, 0, 0}
      
set colStrForFind to "0 0 0"
    end if
    
    
–Font
    
set aFont to (theAtts’s valueForKeyPath:"NSFont")
    
if aFont is not equal to missing value then
      set aDFontName to aFont’s displayName()
      
set aDFontSize to aFont’s pointSize()
    end if
    
    
set the end of (styleList of aSpd) to {stringVal:aText, colorStr:colStrForFind, colorVal:colList, fontName:aDFontName as string, fontSize:aDFontSize, itemIndex:itemCount}
    
set startIndex to current application’s NSMaxRange(theRange)
    
    
set itemCount to itemCount + 1
  end repeat
  
  
return (styleList of aSpd)
  
end getAttributeRunsFromAttrString

–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

–NSColorからRGBの値を取り出す
on retColListFromNSColor(aCol, aMAX as integer)
  set aRed to round ((aCol’s redComponent()) * aMAX) rounding as taught in school
  
set aGreen to round ((aCol’s greenComponent()) * aMAX) rounding as taught in school
  
set aBlue to round ((aCol’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}
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
  
log aRes
  
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

on retTwoPathList()
  tell application "Script Debugger"
    set dList to name of every document
    
set dResList to choose from list dList with prompt "Select two documents" with multiple selections allowed
    
if dResList = false then return false
    
if length of dResList is not equal to 2 then
      display dialog "Please Select two documents to compare handler contents" buttons {"OK"} default button 1 with icon 1 with title "Selection Error"
      
return false
    end if
    
    
set dPathList to {}
    
repeat with i in dResList
      set j to contents of i
      
tell document j
        set tmpPath to (file spec) as string –HFS path string
      end tell
      
      
set the end of dPathList to tmpPath
    end repeat
  end tell
  
  
return dPathList
end retTwoPathList

–Written By Philip Aker
–文字置換ルーチン
on repChar(origText as string, targStr as string, repStr as string)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

–指定文字と終了文字に囲まれた内容を抽出
on extractStrFromTo(aParamStr, fromStr, toStr)
  set theScanner to current application’s NSScanner’s scannerWithString:aParamStr
  
set anArray to current application’s NSMutableArray’s array()
  
  
repeat until (theScanner’s isAtEnd as boolean)
    set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(specifier)
    
theScanner’s scanString:fromStr intoString:(missing value)
    
set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(specifier)
    
if theValue is missing value then set theValue to "" –>追加
    
theScanner’s scanString:toStr intoString:(missing value)
    
anArray’s addObject:theValue
  end repeat
  
  
if anArray’s |count|() is not equal to 1 then return false
  
  
return first item of (anArray as list)
end extractStrFromTo

★Click Here to Open This Script 

(Visited 40 times, 1 visits today)
Posted in Color OSA Record Text | Tagged 10.12savvy 10.13savvy 10.14savvy NSArray NSCountedSet NSDictionary NSPredicate NSString NSUnarchiver OSAScript Script Debugger | Leave a comment

ASの実行結果をNumbersの表に出力する

Posted on 4月 5, 2019 by Takaaki Naganoya

文字列で与えたAppleScriptを実行し、その実行結果をテキストで取得したうえにラベルと値に分割してNumbersの「表」に組み立てるAppleScriptです。

仕様書の作成とかテストデータの評価とかそういう仕事を行うさいに、プログラムコード(AppleScriptが出力するrecordとかlistとか)が読めない人向けに確認してもらうために作成したものです。

Numbersに出力すること自体にはさほど意味はありませんが(ExcelでもREST API経由でGoogle Spread Sheetに出力したっていいわけで)、とりあえずプログラムの結果出力になじみのない方々に計算結果を見ていただくためのものです。

AppleScriptの実行結果をスクリプトエディタではなくOSAScriptControllerなどから受け取る部品などが揃ってきたので、こういう加工も割とすぐにできていい感じです。

ちなみに、Numbersの表のセルに対して直接AppleScriptからデータを突っ込んでいますが、これはあらかじめ出力するデータ数が少ないことが見込まれているためです。多い場合(100件前後がひとつの基準に)には、CSVファイルに書き出してNumbersにオープンさせることになるでしょう。

例によって、Numbersの表セルに対してデータを突っ込むさいには非同期モードで実行して速度を稼いでいます。

AppleScript名:ASの実行結果をNumbersの表に出力する
— Created 2019/04/05 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "OSAKit"
use framework "AppKit"
use bLus : script "BridgePlus"

property NSString : a reference to current application’s NSString
property NSThread : a reference to current application’s NSThread
property OSAScript : a reference to current application’s OSAScript
property NSTextView : a reference to current application’s NSTextView
property OSAScriptView : a reference to current application’s OSAScriptView
property OSAScriptController : a reference to current application’s OSAScriptController

property SMSForder : a reference to current application’s SMSForder

property theResult : "" –result

set origStr to "
tell application \"Numbers\"
  tell front document
    properties
  end tell
end tell
"

my performSelectorOnMainThread:"execASandReturnString:" withObject:origStr waitUntilDone:true
set aStr to (my theResult)

set aList to my getListFromText:aStr

makeNewNumbersDocumentAndTable(length of aList, 2) of me
fillCurrentTable(aList) of me

–リストに入れたレコードを、指定の属性ラベルの値で抽出
on filterRecListByLabel(aRecList as list, aPredicate as string)
  –ListからNSArrayへの型変換
  
set aArray to current application’s NSArray’s arrayWithArray:aRecList
  
  
–抽出
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
  
–NSArrayからListに型変換して返す
  
set bList to filteredArray as list
  
return bList
end filterRecListByLabel

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

–listの共通項を返す
on getSameItemsInLists:(aList as list) withList:(bList as list)
  
  
–ASオブジェクトをCocoaオブジェクトに変換
  
set aArray to current application’s NSArray’s arrayWithArray:aList
  
set bArray to current application’s NSArray’s arrayWithArray:bList
  
  
— まとめる
  
set allSet to current application’s NSMutableSet’s setWithArray:aArray
  
allSet’s addObjectsFromArray:bArray
  
  
–重複する要素のみ抜き出す
  
set duplicateSet to current application’s NSMutableSet’s setWithArray:aArray
  
duplicateSet’s intersectSet:(current application’s NSSet’s setWithArray:bArray)
  
  
–重複部分だけを返す
  
set resArray to duplicateSet’s allObjects()
  
  
set resList to resArray as list
  
  
return resList
end getSameItemsInLists:withList:

–スクリプトエディタのresult欄に返ってきたテキストをリストに変える
on getListFromText:aText
  
  
script getListFromTextO
    property aaText : ""
    
property gList : {}
    
property outList : {}
    
property aG : ""
    
property valList : {}
  end script
  
  
copy aText to (aaText of getListFromTextO)
  
  
set (gList of getListFromTextO) to {}
  
set (outList of getListFromTextO) to {}
  
set (aG of getListFromTextO) to ""
  
set (valList of getListFromTextO) to {}
  
  
if (aaText of getListFromTextO) does not start with "{" and (aaText of getListFromTextO) does not end with "}" then
    return {}
  end if
  
  
set aLen to length of (aaText of getListFromTextO)
  
set (aG of getListFromTextO) to text 2 thru -2 of (aaText of getListFromTextO)
  
set (gList of getListFromTextO) to characters of (aG of getListFromTextO)
  
  
  
set sPos to 2 –1文字目は\"{\"なので2文字目からスキャンを開始する
  
set ePos to 2
  
  
set imdF to false –Immediate Data Flag(文字列中を示すダブルクォート内の場合にはtrueになる)
  
set listF to 0 –stacking段数が入る
  
  
set attrF to true –属性ラベルスキャン時にtrue、データ末尾スキャン時にfalse
  
  
  
repeat with i in (gList of getListFromTextO)
    
    
set j to contents of i
    
    
if attrF = true and imdF = false and listF = 0 then
      
      
–属性値部分の末尾検出
      
if j = ":" then
        if text sPos thru sPos of (aaText of getListFromTextO) = " " then
          set sPos to sPos + 1
        end if
        
set anOut to text sPos thru ePos of (aaText of getListFromTextO)
        
set sPos to ePos + 1
        
set the end of (valList of getListFromTextO) to anOut
        
set attrF to false –データのスキャンを開始する
        
set imdF to false
        
set listF to 0
      end if
      
    else if imdF = false and listF = 0 and j = "," then
      
      
–データ部分の末尾検出
      
set anOut to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
      
set sPos to ePos + 1
      
set the end of (valList of getListFromTextO) to anOut
      
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
      
set (valList of getListFromTextO) to {}
      
      
set attrF to true –次が属性値ラベルであることを宣言
      
set imdF to false
      
set listF to 0
      
    else if j = "{" then
      if imdF = false then
        set listF to listF + 1 –1段スタックにpush
      end if
    else if j = "}" then
      if imdF = false then
        set listF to listF – 1 –1段スタックからpop
      end if
    else if j = "\"" then
      if imdF = true then
        set imdF to false
      else
        set imdF to true
      end if
    end if
    
    
set ePos to ePos + 1
    
  end repeat
  
  
–ラストのデータ部分を出力
  
try
    set the end of (valList of getListFromTextO) to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
    
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
  on error
    return false
  end try
  
  
return contents of (outList of getListFromTextO)
end getListFromText:

on execASandReturnString:(srcStr as string)
  
  
set targX to 500 –View Width
  
set targY to 200 –View Height
  
  
  
if srcStr = missing value or srcStr = "" then
    –Error
    
display dialog "Error in reading script source…." buttons {"OK"} default button 1 with icon 1
    
return
  end if
  
  
–Make AppleScript Controller & Script Editor View
  
set osaCon to OSAScriptController’s alloc()’s init()
  
set osaView to OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
  
–Make Result View
  
set resView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
resView’s setRichText:true
  
resView’s useAllLigatures:true
  
  
–Connect OSAScriptController to Editor View & Result View
  
osaCon’s setScriptView:osaView
  
osaCon’s setResultView:resView
  
  
–Set AppleScript Source to Editor View & Execute it
  
osaView’s setString:srcStr
  
osaCon’s runScript:(missing value)
  
  
–Get AppleScript’s Result as string
  
set aRes to resView’s |string|() as list of string or string –as anything
  
  
set my theResult to aRes –Return the result as string
  
end execASandReturnString:

on fillCurrentTable(aList)
  set aLen to length of aList
  
set aWidth to length of first item of aList
  
  
tell application "Numbers"
    tell front document
      tell active sheet
        tell table 1
          repeat with i from 1 to aLen
            tell row (i + 1)
              set aRowList to contents of item i of aList
              
repeat with ii from 1 to aWidth
                tell cell ii
                  set aTmpData to contents of item ii of aRowList
                  
ignoring application responses
                    set value to aTmpData
                  end ignoring
                end tell
              end repeat
            end tell
          end repeat
        end tell
      end tell
    end tell
  end tell
end fillCurrentTable

on makeNewNumbersDocumentAndTable(aHeight, aWidth)
  tell application "Numbers"
    make new document
    
    
tell front document
      tell active sheet
        delete every table
      end tell
    end tell
    
    
tell front document
      tell active sheet
        set tRes to make new table with properties {row count:aHeight, column count:aWidth}
        
return tRes
      end tell
    end tell
  end tell
end makeNewNumbersDocumentAndTable

★Click Here to Open This Script 

(Visited 98 times, 1 visits today)
Posted in OSA Record | Tagged 10.12savvy 10.13savvy 10.14savvy NSString NSTextView NSThread Numbers OSAScript OSAScriptController OSAScriptView | Leave a comment

as anything

Posted on 4月 3, 2019 by Takaaki Naganoya

as anythingについてまとまった情報がなかったので、まとめておきました。結論めいたものはとくになく、ただ、手持ちの情報を並べてみただけの内容なのでご容赦ください。「これはこうあるべき!」とかいう提言とかは一切ありません。

割と最近なas anythingとの遭遇

つい最近まで、ながらく存在自体を知らなかったのが、このanythingという予約語です。

AppleScriptの用語辞書をASObjC Explorer 4で書いて試していたとき、パラメータの型に「any」というものが存在していることには気づいていましたが、それでも「anything」という予約語があることには気づきませんでした。

本格的に知ったのは、applescript-stdlibを漁っていたときです。

同ライブラリはトリッキーなScriptの記述方法の見本市みたいになっていて、内容自体の完全理解についてはサジを投げた状態でしたが、見たことのない記述にいろいろ行き当たりました(もっと読みやすく書いてほしかった ^ー^;;)。

delegateの呼び出し先にscriptオブジェクト内部のハンドラを指定したりと、「そんな書き方できるんだ。やらんけど」と、まるで古文書をひもとくような感覚(これを見ていると、こーゆー風にblocks構文をAppleScriptでも記述できればいいのに、と思います)。

そこで見つけた「as anything」表記。これは一体なんなんでしょう?

いい加減に使えてとても便利なas anything

実際に動かしてみたところ、「あーー、この機能昔から欲しかったわー」という内容でした。anonymous classとでもいうのでしょうか。castするときにclass名を指定しないワイルドカードなclassと理解しました。

「as anything」でAppleScriptのデータ型はそのまま、AppleScriptのデータ型にcast可能なCocoaのデータはAppleScriptのデータ型に変換。変換不能なCocoaのデータ型についてはそのまま、という処理をしてくれます。

# ただし要素数が1つのNSArrayをas anythingでAppleScript Objetに変換すると、listではなく中身のデータが取り出されてしまう(型が合わなくなる)ので、注意が必要とのこと(Thanks Shane!)
# なので、あらかじめNSArrayが返ってくることがわかっている場合には、as list。NSArrayか他のデータ(missing valueとか)が返ってくる場合には、as {missing value, list} などとするとよいでしょう

BridgePlus的にいえば、「ASify without BridgePlus」といったところでしょうか。CocoaとAppleScriptの間でデータをやりとりするのにえっらく都合がよかったのです。かくして、「as anything」を愛用しまくるスタイルが確立。

ただ、anythingは言語仕様のはざまで埋もれかけていた「枝葉末節」の中の一番の「枝葉」ともいうべき、言語仕様の極北。AppleScript Language Guideにも記載されていないほどの枝葉仕様。

AppleScriptObjCのプログラム中に書くと、予約語が用意されていないためか「as anything」が「as list of string or string」などと解釈されてしまいます(動作自体はanythingと同じ)。

anythingについては、Apple側がわりとぞんざいに仕様を放置していたきらいがあります。問題が起こらないかぎり放っておこう、と。as «class isot»のようにある日突然(Mac OS X 10.5で)消えてなくなったりしないかちょっと不安に感じたこともありましたが、一応まがりなりにも予約語が割り振られているので(生Apple Eventを記述させられないので)、そんなに簡単に消えないとは思います。

主要開発環境で足並みそろわず

雑に放置していたAppleに対して、この問題に正面から向き合っていた集団が存在します。それが、Script DebuggerのメーカーであるLate Night Softwareです。

macOS 10.12や10.13上ではあいかわらずASOCのプログラムでは「as anything」が「as list of string or string」と解釈されますが、macOS 10.14で対応に差が出ました。

Script Debugger上では「anything」が「any」と解釈され、スクリプトエディタ上では「anything」と解釈されます。

macOS 10.14上でのスクリプトエディタで「as anything」が「as list of string or string」のように化けないのはいいと思います。ただ、Script DebuggerのメーカーであるLate Night Software側ではこれに「any」という別の予約語を割り振ったようで、、、、足並みがそろっていません。

一応、macOS 10.14上のスクリプトエディタv2.11上で「as anything」と記述したScriptを、同じくmacOS 10.14上のScript Debuggerに持っていくと「as any」と表示されます。いったん中間コードにコンパイルされたものは問題がないようです。

問題になるのは、Blogなどに掲載されている文字の状態のAppleScriptで、anythingについてはコンパイル(構文確認)時に気をつける必要がありそうです(メイン環境が10.14に移行していないのでちょっとまだ他人事)。

困ったときの古文書だより

一応、現代AppleScriptのルーツの資料とされている「AppleScriptLanguageGuide 1.3.7」(1999/5/5)のPDFを確認してみると、けっこう悩ましい内容が記述されています。

自分はanythingをclassか何かだと思っていたのですが、そこには定数(constants)だと書かれています。AppleScript version 1.3.7のころには、missing value(不定値)みたいな運用が行われていたようです。

AppleのEngineering Teamの見解は?

匿名希望の方がApple Engineering Teamに問い合わせしたところ「そんなマイナーな予約語は使うな」という返答であったとか。その一方でmacOS 10.14で「anything」の「list or list of string」への解釈化けが抑止されたりしているわけで、いまひとつわかりにくいというのが現状です。

(Visited 56 times, 1 visits today)
Posted in OSA | Tagged 10.12savvy 10.13savvy 10.14savvy Script Debugger Script Editor | Leave a comment

Xcodeで最前面のAS sourceを構文確認

Posted on 3月 27, 2019 by Takaaki Naganoya

Xcodeで編集中のAppleScriptのプログラムを構文確認(コンパイルと表記されている、構文チェックと中間コードへの変換チェック、省略表記の展開など)するAppleScriptです。

本ScriptはXcode 9.2+macOS 10.12.6でテストしたものです。macOS 10.14+Xcode 10.2で実行したところ、file documentのnameに「– Edited」という入っていてはいけない文字列が入っていたり(それはWindowのtitleであってdocumentのnameじゃないだろう、、、、)、AppleScriptからXcodeを(データ書き込み)操作するとXcodeがクラッシュしたりと、まともに動作していない印象です。

Xcode 10.1+macOS 10.13.6で動かしたぶんには、Xcode上の表示は更新されていないものの、プロジェクト内の他のファイルをいったん表示させたあとに再度Scriptを表示させると書き換わっていました。Xcode 10.2+macOS 10.14.4の組み合わせでおかしな動きを行なっているようです。

XcodeのテキストエディタはAppleScriptの構文色分けを反映して表示しませんし、編集中にコンパイル(構文確認)するための機能がありません。インデント合わせやtellブロックやifブロックのネスティングの確認なども行えないため、記述のための最低限の機能を備えておらず、まともにプログラムを書くのであればScript Debuggerの併用は必須といえます。

先日のmacOS Nativeのミーティングにて、プレーンテキストエディタであるCotEditor上に記述したテキストのAppleScriptをコンパイル(構文確認)し、実際に実行して結果をCotEditor上の新規書類に出力するデモを実施。

このデモ内容は、はるかかなた昔から行なってきたものであり、CotEditorにかぎらず、あまねくどんなテキストエディタに対しても実行できるものです。macOS標準搭載のテキストエディットに対してすら同様のScriptを実行できます。

……と、振り返っていたときに、冒頭の「機能が致命的に足りない」Xcodeのテキストエディタのことを思い出したのです。

Xcodeのテキストエディタは(AppleScriptにとっては)致命的に機能が足りない欠陥品ですが、欠陥品には欠陥品なりの扱いをすればよいのではないかと気づきました。Xcodeに対してAppleScriptを実行することで、ソースを取得し、AppleScriptでAppleScriptをコンパイルし、Xcodeに書き戻してやればよいのではないか、と。

ずいぶんと昔に書いたXcode操作のScriptに若干のルーチンを足して動かしてみたところ、想像どおりうまく動きました。

ただし、少々のテストを行なっただけなので、実際にもっと使い込んでみる必要性を感じます。また、Xcode側が不可思議な挙動を行うため、Xcode上でAppleScriptを記述する場合には、依然としてScript Debugger必須です。

ちなみに、XcodeのAppleScriptサポート機能はいまひとつ不思議な挙動を行います。tellブロックでオブジェクト(documentとか)をくくり、その内側でオブジェクトに対する操作を行おうとするとエラー。tellブロックを正常に認識せず、tellブロック内でもそのオブジェクトへの参照を「of it」のように書く必要があります(実は、CotEditorもこのタイプ)。

最近、そのような不思議な挙動を行うアプリケーションがいくつか見られたため、「はいはい。君はof itが必要な人なんだね」と乗り切りましたが、これに気づかないと永遠にXcodeのまともなScriptは書けません。要注意です。

AppleScript名:最前面のAS sourceを構文確認.scptd
— Created 2018-05-19 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "OSAKit"

property OSAScript : a reference to current application’s OSAScript
property OSALanguage : a reference to current application’s OSALanguage
property OSALanguageInstance : a reference to current application’s OSALanguageInstance

property targX : 1024 –View Width
property targY : 2048 –View Height

tell application "Xcode"
  –最前面のWindowの情報を取得
  
set winProp to properties of front window
  
set aDoc to document of winProp –Xcode のworkspace document(xcodeproj)
  
–> workspace document "WKWebViewDemo.xcodeproj" of application "Xcode"
  
  
set docProp to properties of aDoc
  
set xcodeDocPath to path of docProp
  
–> "/Users/me/Documents/Objective-C/WKWebViewDemo_MAC-master/WKWebViewDemo.xcodeproj"
  
  
set aFileDoc to name of winProp
  
–> "ViewController.m"
  
  
try
    set aDoc to file document aFileDoc
    
–> source document "ViewController.m" of application "Xcode"
  on error
    –Storyboard/Xib file/info.plist/Assetsなどを表示中の場合にはエラーになる
    
return false
  end try
  
  
set aDocPath to path of aDoc
  
–> "/Users/me/Documents/Objective-C/WKWebViewDemo_MAC-master/WKWebViewDemo/ViewController.m"
end tell

if aDocPath does not end with ".applescript" then
  display notification "Front Xcode document does not seem an AppleScriptObjC source"
  
return
end if

set theSource to read ((POSIX file aDocPath) as alias) as «class utf8»
set aRes to retComiledAppleScriptString(theSource, "AppleScript") of me

tell application "Xcode"
  tell aDoc
    set text of it to aRes
  end tell
end tell

–Compile AppleScript Source
on retComiledAppleScriptString(aStr as string, osalangName as string)
  set osaCon to current application’s OSAScriptController’s alloc()’s init()
  
set osaView to current application’s OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
osaCon’s setScriptView:osaView
  
osaCon’s setLanguage:(OSALanguage’s languageForName:osalangName)
  
osaView’s setString:aStr
  
osaCon’s compileScript:(missing value) –Compile(構文確認)
  
  
set aRes to (osaView’s |string|()) as string
  
return aRes
end retComiledAppleScriptString

★Click Here to Open This Script 

(Visited 87 times, 1 visits today)
Posted in OSA Raw AppleEvent Code Text | Tagged 10.12savvy OSALanguage OSALanguageInstance OSAScript OSAScriptController OSAScriptView Xcode | 1 Comment

Finder上で選択中のAppleScriptの行数をカウントする

Posted on 2月 8, 2019 by Takaaki Naganoya

Finder上で選択中のAppleScript書類の行数や種別を取得して表UIで表示するAppleScriptです。

Myriad Tables Libを用いて結果を表UIで表示しています。

当初はAppleScript書類からソースを取得するのに/usr/bin/osadecompileコマンドを使っていたのですが、OSAKit経由で処理したほうが高速な印象があります。

–> Download Executable archive for macOS 10.14 (include Myriad Tables Lib)

macOS 10.14上で動作させるためには、Script Debugger上で本Scriptをオープンするか、本Scriptをバンドル形式で保存し、バンドル内(/Contents/Resources/Script Libraries フォルダ)にMyriad Tables Libを入れ、AppleScriptアプレットとして書き出す必要があります。

また、初回実行時には「セキュリティ」の承認ダイアログが表示されるため、これをOKする必要があります。AppleScriptアプレットはFinder上でアイコンをダブルクリックすると「Finder上で選択中のアイテム」を拾えないため(その瞬間、Finder上での選択アイテムはアプレット自身になってしまうため)、DockやmacOS標準装備のスクリプトメニューに登録して起動する必要があります。

AppleScript名:Finder上で選択中のAppleScriptの行数をカウントする v2.scpt
— Created 2019-02-04 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "OSAKit"
use script "Myriad Tables Lib" version "1.0.8" –https://www.macosxautomation.com/applescript/apps/Script_Libs.html#MyriadTablesLib

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
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 NSURLIsPackageKey : a reference to current application’s NSURLIsPackageKey
property NSURLIsDirectoryKey : a reference to current application’s NSURLIsDirectoryKey
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey

–Finder上で選択中のファイルのうちAppleScript書類のみ抽出
tell application "Finder"
  set inFiles to selection as alias list
  
if inFiles = {} then return
end tell
set filRes1 to filterAliasListByUTIList(inFiles, {"com.apple.applescript.script", "com.apple.applescript.script-bundle"}) of me
if filRes1 = {} then return

–AppleScript書類の種別判定および行数カウント
set outList to {}
repeat with i in filRes1
  set aName to (NSString’s stringWithString:i)’s lastPathComponent() as string
  
set sInfo to detectScriptIsPureASorASOC(i) of me
  
set sText to scriptSource of getASsourceFor(i) of me
  
set sNum to count every paragraph of sText
  
set sUTI to retUTIfromPath(i) of me
  
if sUTI = "com.apple.applescript.script" then
    set sKind to "Script"
  else if sUTI = "com.apple.applescript.script-bundle" then
    set sKind to "Script Bundle"
  else
    set sKind to "Other"
  end if
  
  
set the end of outList to {aName, sInfo, sKind, sNum}
end repeat

–結果を表UIで表示する
tell script "Myriad Tables Lib"
  set aDispBounds to my makeInitialBounds:1200 withHeight:500
  
set theTable to make new table with data outList column headings {"script name", "ASOC", "Script Kind", "lines"} with title "AppleScript Line Count" with prompt "Your Selected Scripts" with row numbering and empty selection allowed –and can add and delete
  
modify table theTable initial position aDispBounds column widths pattern {1, 2, 3, 4} with hidden cancel button
  
modify columns in table theTable user date format {user format full, user format full} entry alignment align left
  (
display table theTable)
end tell

–Alias listから指定UTI Listに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTIList(aList as list, targUTIList as list)
  set outList to {}
  
repeat with i in targUTIList
    set j to contents of i
    
set aRes to filterAliasListByUTI(aList, j) of me
    
if aRes is not equal to {} then
      set outList to outList & aRes
    end if
  end repeat
  
return outList
end filterAliasListByUTIList

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList as list, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(specifier) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

on makeInitialBounds:(aTWidth as integer) withHeight:(aTHeight as integer)
  set aDispBounds to current application’s NSScreen’s mainScreen()’s frame()
  
if class of item 1 of aDispBounds = record then
    –macOS 10.10/10.11/10.12
    
set aWidth to (width of |size| of aDispBounds)
    
set aHeight to (height of |size| of aDispBounds)
  else
    –macOS 10.13 or later?
    
set aWidth to (item 1 of item 2 of aDispBounds)
    
set aHeight to (item 2 of item 2 of aDispBounds)
  end if
  
  
set xPos to (aWidth div 2) – (aTWidth div 2)
  
set yPos to (aHeight div 2) – (aTHeight div 2)
  
  
return {xPos, yPos, aTWidth, aTHeight}
end makeInitialBounds:withHeight:

–指定AppleScriptファイルがPure ASかASOCかを判定して返す
on detectScriptIsPureASorASOC(aFile)
  set sRes to getASsourceFor(aFile) of me
  
set sName to scriptKind of sRes –Name
  
set sText to scriptSource of sRes –Source
  
if sText = "" or sText = missing value then return missing value
  
  
if sName = "AppleScript" then
    if sText contains "use framework \"Foundation\"" then
      return true –ASOC
    else
      return false –Pure AppleScript
    end if
  else
    –JXAなど他のOSA言語の場合
    
return sName
  end if
end detectScriptIsPureASorASOC

–指定AppleScriptファイルのソースコードを取得する(実行専用Scriptからは取得できない)
on getASsourceFor(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:(aPOSIXPath)
  
set theScript to current application’s OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
  
set scriptName to theScript’s |language|()’s |name|() as string
  
set theSource to theScript’s source() as text
  
return {scriptKind:scriptName, scriptSource:theSource}
end getASsourceFor

★Click Here to Open This Script 

(Visited 158 times, 3 visits today)
Posted in file File path GUI OSA | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSArray NSPredicate NSString NSURL OSAScript | Leave a comment

Post navigation

  • Older posts

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

Google Search

Popular posts

  • AppleScriptによるWebブラウザ自動操縦ガイド
  • macOS 13, Ventura(継続更新)
  • ドラッグ&ドロップ機能の未来?
  • macOS 12.x上のAppleScriptのトラブルまとめ
  • PFiddlesoft UI Browserが製品終了に
  • macOS 12.3 beta 5、ASの障害が解消される(?)
  • SF Symbolsを名称で指定してPNG画像化
  • 新刊発売:AppleScriptによるWebブラウザ自動操縦ガイド
  • macOS 12.3 beta4、まだ直らないASまわりの障害
  • macOS 12.3上でFinder上で選択中のファイルをそのままオープンできない件
  • Safariで表示中のYouTubeムービーのサムネイル画像を取得
  • macOS 12のスクリプトエディタで、Context Menu機能にバグ
  • Pixelmator Pro v2.4.1で新機能追加+AppleScriptコマンド追加
  • 人類史上初、魔導書の観点から書かれたAppleScript入門書「7つの宝珠」シリーズ開始?!
  • CotEditor v4.1.2でAppleScript系の機能を追加
  • macOS 12.5(21G72)がリリースされた!
  • UI Browserがgithub上でソース公開され、オープンソースに
  • Pages v12に謎のバグ。書類上に11枚しか画像を配置できない→解決
  • 新発売:AppleScriptからSiriを呼び出そう!
  • iWork 12.2がリリースされた

Tags

10.11savvy (1102) 10.12savvy (1243) 10.13savvy (1391) 10.14savvy (586) 10.15savvy (434) 11.0savvy (274) 12.0savvy (174) 13.0savvy (34) CotEditor (60) Finder (47) iTunes (19) Keynote (97) NSAlert (60) NSArray (51) NSBezierPath (18) NSBitmapImageRep (21) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (18) NSImage (42) NSJSONSerialization (21) NSMutableArray (62) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (118) NSURL (97) NSURLRequest (23) NSUTF8StringEncoding (30) NSUUID (18) NSView (33) NSWorkspace (20) Numbers (55) Pages (36) Safari (41) Script Editor (20) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • Clipboard
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • drive
  • 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
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • 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)
  • 未分類

アーカイブ

  • 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