— Created 2017-12-08 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property NSFont : a reference to current application’s NSFont
property NSData : a reference to current application’s NSData
property NSColor : a reference to current application’s NSColor
property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property NSDictionary : a reference to current application’s NSDictionary
property NSPasteboard : a reference to current application’s NSPasteboard
property NSCountedSet : a reference to current application’s NSCountedSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSAttributedString : a reference to current application’s NSAttributedString
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSFontAttributeName : a reference to current application’s NSFontAttributeName
property NSKernAttributeName : a reference to current application’s NSKernAttributeName
property NSMutableParagraphStyle : a reference to current application’s NSMutableParagraphStyle
property NSLigatureAttributeName : a reference to current application’s NSLigatureAttributeName
property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString
property NSUnderlineStyleAttributeName : a reference to current application’s NSUnderlineStyleAttributeName
property NSParagraphStyleAttributeName : a reference to current application’s NSParagraphStyleAttributeName
property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName
–クリップボードの内容を文字列として取得
set aStr to (the clipboard) as string
if aStr = "" then
display dialog "No Data in Clipboard" buttons {"OK"} default button 1
return
end if
–クリップボードの内容をStyled Stringで取得して最頻出フォントを取得
set clipboardAttrStr to getClipboardASStyledText() of me
if clipboardAttrStr = missing value then
display dialog "Can not get clipboard as Styled String" buttons {"OK"} default button 1
return
end if
set attrList to getAttributeRunsFromAttrString(clipboardAttrStr) of me
set anArray to (NSArray’s arrayWithArray:attrList)’s valueForKeyPath:"fontName"
set aFontList to (countItemsByItsAppearance(anArray) of me)
set aFontName to theName of first item of aFontList
–クリップボードから取得した文字データについて処理
set aList to paragraphs of aStr –行ごとにparseしてlist化
set bList to {}
repeat with i in aList
set j to contents of i
if j ≠ {} then
set jList to words of j
if jList ≠ {} then
if contents of first item of jList = "property" then
set curLabel to contents of second item of jList
–行をAttributed Stringとして組み立てて、画面描画時の仕上がりサイズを取得
set anAssrStr to makeRTFfromParameters(j, aFontName, 16, -2, 16) of me
set aSize to anAssrStr’s |size|() –画面描画時のサイズを取得
if class of aSize = record then
set attrStrWidth to width of aSize
set attrStrHeight to height of aSize
else if class of aSize = list then –macOS 10.13.xのバグ回避
copy aSize to {attrStrWidth, attrStrHeight}
end if
set the end of bList to {aLabel:curLabel, aCon:j, aWidth:attrStrWidth}
end if
end if
end if
end repeat
if bList = {} then
display dialog "Error" buttons {"OK"} default button 1
return
end if
–複数キーでソート(書式つきテキストの仕上がりサイズ幅、文字コード順でソート)
set aArray to NSArray’s arrayWithArray:bList
set desc1 to NSSortDescriptor’s sortDescriptorWithKey:"aWidth" ascending:true
set desc2 to NSSortDescriptor’s sortDescriptorWithKey:"aLabel" ascending:true selector:"localizedCaseInsensitiveCompare:"
set bArray to aArray’s sortedArrayUsingDescriptors:{desc1, desc2}
–ソートしたlist of recordからaCon(元のproperty宣言行そのもの)を一括で取り出す
set dArray to (NSMutableArray’s arrayWithArray:bArray)’s valueForKeyPath:"aCon"
–listをデリミタつきのテキストに
set dStr to retStrFromArrayWithDelimiter(dArray, return) of me
set the clipboard to (dStr & return)
–1D Listを文字列長でソート v2
on sort1DListByIndicatedStringLength(aList as list, aSortKey as string, sortOrder as boolean)
set aArray to NSArray’s arrayWithArray:aList
set descLabel1 to NSString’s stringWithString:(aSortKey & ".length")
set descLabel2 to NSString’s stringWithString:aSortKey
set desc1 to NSSortDescriptor’s sortDescriptorWithKey:descLabel1 ascending:sortOrder
set desc2 to NSSortDescriptor’s sortDescriptorWithKey:descLabel2 ascending:true selector:"localizedCaseInsensitiveCompare:"
set bArray to aArray’s sortedArrayUsingDescriptors:{desc1, desc2}
return bArray as list
end sort1DListByIndicatedStringLength
–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList as list, aDelim as string)
set anArray to NSArray’s arrayWithArray:aList
set aRes to anArray’s componentsJoinedByString:aDelim
return aRes as text
end retStrFromArrayWithDelimiter
–書式つきテキストを組み立てる
on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aKerning as real, aLineSpacing as real)
set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize
set aKey1 to (NSFontAttributeName)
set aVal2 to NSColor’s blackColor()
set aKey2 to (NSForegroundColorAttributeName)
set aVal3 to aKerning
set akey3 to (NSKernAttributeName)
set aVal4 to 0
set akey4 to (NSUnderlineStyleAttributeName)
set aVal5 to 2 –all ligature ON
set akey5 to (NSLigatureAttributeName)
set aParagraphStyle to NSMutableParagraphStyle’s alloc()’s init()
aParagraphStyle’s setMinimumLineHeight:(aLineSpacing)
aParagraphStyle’s setMaximumLineHeight:(aLineSpacing)
set akey7 to (NSParagraphStyleAttributeName)
set keyList to {aKey1, aKey2, akey3, akey4, akey5, akey7}
set valList to {aVal1, aVal2, aVal3, aVal4, aVal5, aParagraphStyle}
set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList
set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary
return attrStr
end makeRTFfromParameters
— クリップボードの内容をNSAttributedStringとして取り出して返す
on getClipboardASStyledText()
set theNSPasteboard to NSPasteboard’s generalPasteboard()
set theAttributedStringNSArray to theNSPasteboard’s readObjectsForClasses:({NSAttributedString}) options:(missing value)
set theNSAttributedString to theAttributedStringNSArray’s objectAtIndex:0
return theNSAttributedString
end getClipboardASStyledText
–指定のNSAttributedStringから書式情報をlist of recordで取得
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
repeat until (startIndex = theLength)
set {theAtts, theRange} to theStyledText’s attributesAtIndex:startIndex longestEffectiveRange:(reference) inRange:{startIndex, theLength – startIndex}
set aText to (thePureString’s substringWithRange:theRange) as string
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}
set colStrForFind to (aRed as integer as string) & " " & (aGreen as integer as string) & " " & (aBlue as integer as string)
else
set colList to {0, 0, 0}
set colStrForFind to "0 0 0"
end if
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}
set startIndex to current application’s NSMaxRange(theRange)
end repeat
return (styleList of aSpd)
end getAttributeRunsFromAttrString
–1D Listをアイテムの出現頻度順でソートして返す
on countItemsByItsAppearance(aList as list)
set aSet to NSCountedSet’s alloc()’s initWithArray:aList
set bArray to NSMutableArray’s array()
set theEnumerator to aSet’s objectEnumerator()
repeat
set aValue to theEnumerator’s nextObject()
if aValue is missing value then exit repeat
bArray’s addObject:(NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"theName", "numberOfTimes"})
end repeat
set theDesc to NSSortDescriptor’s sortDescriptorWithKey:"numberOfTimes" ascending:false
bArray’s sortUsingDescriptors:{theDesc}
return bArray as list
end countItemsByItsAppearance
ASOCからclass名を抽出してpropertyとして展開 v4 – AppleScriptの穴 says:
[…] また、propertyを展開するときに、プロポーショナルフォントで画面描画した際の幅を実際に計算して、文字の描画幅のピクセル数順にソートしています。 […]