NSRangeの隣接検出を行うAppleScriptです。
NSRangeやNSRectの重なり検出機能はとても強力で、OLD Style AppleScriptの時代では考えられなかったほどの処理の柔軟性を得られています。
強力ではあるものの、機能が素朴であることもまた事実であります。AとBの2つのNSRangeが重なっていることしか検出できないのはつくづく残念です。
不満な点の筆頭に挙げられるのが、「隣接検出」機能がないことです。
たとえば、NSAttributedStringに対して書式を取得する処理を行うと、3点リーダー文字(「…」)や感嘆符(「!」)の箇所で、書式情報が変わっていないのに分割して取得されてしまいます。バグではないものの、あまり好ましくない挙動です。
こうした箇所は、Rangeとしては「隣接」しているわけで、同一書式のデータが「隣接」している場合には、続きのデータとしてまとめられた方がいいに決まっています。
そこで冒頭のNSRangeの隣接検出という話になるわけですが……NSRangeが1次元座標上の始点と終点の2つの情報で構成されているために、これらの情報を「拡張」します。
set aRange to current application’s NSMakeRange(10, 80)
というNSRangeを作ると、
–> {location:10, |length|:80}
始点(10)と、始点からの長さが80で、終点が90になります。
これを「拡張」すると、
–> {location:9, |length|:82}
となります。NSRangeが「隣接」は検出できなくても、重なり合いは検出できるため、「拡張」すれば、隣接時には「重なっている」と判定できることになります。
あとは、リストに入れたNSRangeのうち重なり合っているものをループで検出するルーチンを書けば、大量のNSRange同士の隣接を処理できることでしょう。
AppleScript名:NSRangeの拡張、隣接検出 |
— Created 2018-1-12 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aRange to current application’s NSMakeRange(10, 80) –original range –> {location:10, |length|:80} set bRange to extendRange(aRange) of me –Extended range –> {location:9, |length|:81} set cRange to current application’s NSMakeRange(90, 30) –compare target range –> {location:90, |length|:30} set aRes to current application’s NSIntersectionRange(aRange, cRange) –> {location:0, |length|:0}–Not adjacent set bRes to current application’s NSIntersectionRange(bRange, cRange) –> {location:90, |length|:1}–Adjacent –NSRangeの開始点とサイズを拡張 on extendRange(aRange) set aLoc to location of aRange set aLen to |length| of aRange if aLoc > 0 then set aLoc to aLoc – 1 end if set aLen to aLen + 2 set bRange to current application’s NSMakeRange(aLoc, aLen) return bRange end extendRange |