AppleScriptの書類を読み込んでNSAttributedStringに変換し、書式情報にもとづいてNSDictionary in NSArrayに変換。この状態でデータ抽出などを行なっていたのですが、このデータをもとにNSAttributedStringに再構成するAppleScriptです。
本Scriptの通しの処理内容としては、読み込んだAppleScriptを書式情報をもとに分解して、再構成するという……大豆から豆腐を作って、豆腐を崩して豆を得る、みたいな内容です。
NSAttributedStringを再構成する部分の処理を書いていなかったので、必要に迫られて書いてみました。
AppleScript構文色分け設定情報をもとに処理するため、色分け設定で複数の構文要素で同じ色を指定している場合にはエラーを返します。単にNSAttributedStringを解釈して再構成する、といった処理であればAppleScript構文色分け設定へのアクセス自体は必要ないところですが、すでに不可分なレベルで組み込まれているため、現状ではそのままです。
いっそ、こうした処理をする前にplistをバックアップし、必要な情報を書き込んだplistを設定ファイルとして使用するといった処理を行った方がいいのかもしれません。これまでは、「そんな処理はとても行えない」と判断していましたが、よくよく考えればとくに苦労せずに実現できそうです。
AppleScript名:AS書類を書式で分解して再構成.scptd |
— – Created by: Takaaki Naganoya – Created on: 2025/01/12 — – Copyright © 2025 Piyomaru Software, All Rights Reserved — use AppleScript version "2.8" use scripting additions use framework "Foundation" use framework "AppKit" property NSFont : a reference to current application’s NSFont property NSColor : a reference to current application’s NSColor property |NSURL| : a reference to current application’s |NSURL| property NSString : a reference to current application’s NSString property OSAScript : a reference to current application’s OSAScript property NSDictionary : a reference to current application’s NSDictionary property NSUnarchiver : a reference to current application’s NSUnarchiver property NSMutableDictionary : a reference to current application’s NSMutableDictionary property NSFontAttributeName : a reference to current application’s NSFontAttributeName property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName property asCol : {} set asCol to getAppleScriptSourceColors() of me –AppleScript構文色分け設定をplistから読み込む set aFile to POSIX path of (choose file of type {"com.apple.applescript.script", "com.apple.applescript.script-bundle"}) set aURL to |NSURL|’s fileURLWithPath:(aFile) set theScript to current application’s OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value) set styledText to theScript’s richTextSource() –Styled TextをDictionarry in Listに set sRes to getAttributeRunsFromAttrStringRBO(styledText) of styleTextToDict –Dictionarry in ListをStyled Textに再構成 set bRes to retAttributedStringFromAttrDict(sRes) of attrDictToAttrStr script styleTextToDict use AppleScript use framework "Foundation" use framework "AppKit" use scripting additions property parent : AppleScript –Styled Textを on getAttributeRunsFromAttrStringRBO(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 aCount to 0 repeat until (startIndex = theLength) set {theAtts, theRange} to theStyledText’s attributesAtIndex:startIndex longestEffectiveRange:(reference) inRange:{startIndex, theLength – startIndex} –String set aText to (thePureString’s substringWithRange:theRange) as string set strLen to (length of aText) –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 –Range set the end of (styleList of aSpd) to {stringVal:aText, atrIndex:aCount, colorStr:colStrForFind, colorVal:colList, fontName:aDFontName as string, fontSize:aDFontSize} set startIndex to current application’s NSMaxRange(theRange) set aCount to aCount + 1 end repeat return (styleList of aSpd) end getAttributeRunsFromAttrStringRBO –NSColorからRGBの値を取り出す on retColListFromNSColor(aCol, aMAX as integer) using terms from scripting additions 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 end using terms from 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 –aMaxValを最大値とする数値でNSColorを作成して返す on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval end script script attrDictToAttrStr use AppleScript use framework "Foundation" use framework "AppKit" use scripting additions property parent : AppleScript –書式つきテキストを組み立てる(メイン側) on retAttributedStringFromAttrDict(attrRes) script aSpd property styleList : {} end script set (styleList of aSpd) to {} —for output set allAttrStr to NSMutableAttributedString’s alloc()’s init() repeat with i in attrRes set j to contents of i set tmpAttrStr to makeRTFfromParameters(stringVal of j, fontName of j, fontSize of j, colorVal of j) of me (allAttrStr’s appendAttributedString:tmpAttrStr) end repeat return allAttrStr end retAttributedStringFromAttrDict –書式つきテキストを組み立てる(パーツ組み立て用サブ側) on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aColorList as list) –Font & Size set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize set aKey1 to (NSFontAttributeName) –Color copy aColorList to {rCol, gCol, bCOl} set aVal2 to makeNSColorFromRGBAval(rCol, gCol, bCOl, 255, 255) of asCol set aKey2 to (NSForegroundColorAttributeName) set keyList to {aKey1, aKey2} set valList to {aVal1, aVal2} set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList –Text set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary return attrStr end makeRTFfromParameters –aMaxValを最大値とする数値でNSColorを作成して返す on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval end script –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) using terms from scripting additions 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 end using terms from 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 |