—
– 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