指定のrecord in listからTag CloudっぽいRTFファイルをデスクトップに生成するAppleScriptです。
以前からTag Cloudを出力するフレームワークやObjective-Cのプログラムを探していたのですが、なかなか具合のいいものがありませんでした。
動作原理を考えたら割と簡単そうだったので、仕方なく自分で作ることに。
作ってみて「そんなに難しくない」ことはわかりましたが、まだまだ自分が望むようなものにはなっていません。とりあえず「まあそんなもんだよね」という程度のものです。
set tagList to {{tagname:”AirServer”, tagcount:2}, {tagname:”App Store”, tagcount:1}, {tagname:”Calendar”, tagcount:3}, {tagname:”Contacts”, tagcount:1}, {tagname:”CotEditor”, tagcount:27}, {tagname:”Dictionary”, tagcount:9}, {tagname:”Dock”, tagcount:7}, {tagname:”Evernote”, tagcount:2}, {tagname:”Finder”, tagcount:20}, {tagname:”HelpViewer”, tagcount:2}, {tagname:”HoudahSpot”, tagcount:1}, {tagname:”iBooks”, tagcount:1}, {tagname:”Image Events”, tagcount:1}, {tagname:”iTunes”, tagcount:12}, {tagname:”JeditΩ”, tagcount:3}, {tagname:”Keynote”, tagcount:14}, {tagname:”Mac Blu-ray Player”, tagcount:1}, {tagname:”MacDown”, tagcount:3}, {tagname:”Mail”, tagcount:6}, {tagname:”Maps”, tagcount:3}, {tagname:”mi”, tagcount:2}, {tagname:”Numbers”, tagcount:8}, {tagname:”Pages”, tagcount:2}, {tagname:”Preview.app”, tagcount:2}, {tagname:”QuickTime Player”, tagcount:8}, {tagname:”Reminders”, tagcount:1}, {tagname:”Safari”, tagcount:13}, {tagname:”Script Debugger”, tagcount:1}, {tagname:”Script Editor”, tagcount:7}, {tagname:”Sorting”, tagcount:5}, {tagname:”Spell check”, tagcount:3}, {tagname:”System Events”, tagcount:6}, {tagname:”Terminal”, tagcount:4}, {tagname:”TextEdit”, tagcount:12}, {tagname:”Twitter”, tagcount:1}, {tagname:”Xcode”, tagcount:2}}
という入力から、
というタグクラウドのRTFをデスクトップに書き出します。処理時間は開発環境(MacBook Pro Retina 2012 Core i7 2.66GHz)で0.08秒ぐらいです。
本当は、こんな1次元で連続した内容ではなく、2次元で各タグを分離したオブジェクトとして平面上に配置し、かつ、大きな文字の内容を中心部に配置するとか、間を詰めるために縦方向に回転させたタグも入れるとか、そういう感じの処理を(自動で)行いたいところなので、このレベルだと「ただタグとして並んでいるだけ」で満足できません。
最終的には、日本語のテキストを形態素解析して固有名詞のみ抽出し、出現頻度の高いものをタグクラウドで並べることで内容を把握しやすくする、といった処理を行いたいところです。
AppleScript名:Tag CloudっぽいRTFの作成 |
— Created 2018-06-06 by Takaaki Naganoya — 2018 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 NSUUID : a reference to current application’s NSUUID property NSColor : a reference to current application’s NSColor property NSString : a reference to current application’s NSString property Board2D : a reference to current application’s Board2D property Pathfinder : a reference to current application’s Pathfinder property NSDictionary : a reference to current application’s NSDictionary property NSLiteralSearch : a reference to current application’s NSLiteralSearch property NSMutableArray : a reference to current application’s NSMutableArray 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 NSDocumentTypeDocumentAttribute : a reference to current application’s NSDocumentTypeDocumentAttribute set tagList to {{tagname:"AirServer", tagcount:2}, {tagname:"App Store", tagcount:1}, {tagname:"Calendar", tagcount:3}, {tagname:"Contacts", tagcount:1}, {tagname:"CotEditor", tagcount:27}, {tagname:"Dictionary", tagcount:9}, {tagname:"Dock", tagcount:7}, {tagname:"Evernote", tagcount:2}, {tagname:"Finder", tagcount:20}, {tagname:"HelpViewer", tagcount:2}, {tagname:"HoudahSpot", tagcount:1}, {tagname:"iBooks", tagcount:1}, {tagname:"Image Events", tagcount:1}, {tagname:"iTunes", tagcount:12}, {tagname:"JeditΩ", tagcount:3}, {tagname:"Keynote", tagcount:14}, {tagname:"Mac Blu-ray Player", tagcount:1}, {tagname:"MacDown", tagcount:3}, {tagname:"Mail", tagcount:6}, {tagname:"Maps", tagcount:3}, {tagname:"mi", tagcount:2}, {tagname:"Numbers", tagcount:8}, {tagname:"Pages", tagcount:2}, {tagname:"Preview.app", tagcount:2}, {tagname:"QuickTime Player", tagcount:8}, {tagname:"Reminders", tagcount:1}, {tagname:"Safari", tagcount:13}, {tagname:"Script Debugger", tagcount:1}, {tagname:"Script Editor", tagcount:7}, {tagname:"Sorting", tagcount:5}, {tagname:"Spell check", tagcount:3}, {tagname:"System Events", tagcount:6}, {tagname:"Terminal", tagcount:4}, {tagname:"TextEdit", tagcount:12}, {tagname:"Twitter", tagcount:1}, {tagname:"Xcode", tagcount:2}} set targFontName to "Courier-Bold" –PostScript Name set tagArray to current application’s NSMutableArray’s arrayWithArray:tagList set aMax to (tagArray’s valueForKeyPath:"@max.tagcount") as list of string or string –as anything set aMin to (tagArray’s valueForKeyPath:"@min.tagcount") as list of string or string –as anything set strList to tagArray’s valueForKey:"tagname" set strAll to retArrowText(strList, " ") of me set strAll to " " & strAll & " " set anAttr to current application’s NSMutableAttributedString’s alloc()’s initWithString:strAll repeat with i in tagList set aName to (tagname of i) as string set aNum to (tagcount of i) as number if aNum > (aMax * 0.8) then set aFontSize to 48 set aColor to current application’s NSColor’s redColor() else if aNum > (aMax * 0.6) then set aFontSize to 36 set aColor to current application’s NSColor’s orangeColor() else if aNum > (aMax * 0.4) then set aFontSize to 22 set aColor to current application’s NSColor’s greenColor() else set aFontSize to 16 set aColor to current application’s NSColor’s blackColor() end if set aFont to (current application’s NSFont’s fontWithName:targFontName |size|:aFontSize) –Caution: Call by Reference markCharOfAttributedString(anAttr, strAll, " " & aName & " ", aColor, aFont) of me end repeat –結果のRTFをデスクトップ上に書き出す。ファイル名はUUID.rtf set targFol to current application’s NSHomeDirectory()’s stringByAppendingPathComponent:"Desktop" set aRes to my saveStyledTextAsRTF(targFol, anAttr) –指定のAttributed String内で指定文字列が含まれる箇所に指定の色をつける(結果はメイン側に参照渡し) on markCharOfAttributedString(anAttr, origStr, aTargStr, aColor, aFont) set rList to searchWordWithRange(origStr, aTargStr) of me repeat with ii in rList (anAttr’s addAttribute:(NSForegroundColorAttributeName) value:aColor range:ii) (anAttr’s addAttribute:(NSFontAttributeName) value:aFont range:ii) end repeat end markCharOfAttributedString –指定の文字列をAttributed Stringに変換して任意のフォントを一括指定 on changeAttrStrsFontAttribute(aStr, aFontPSName, aFontSize) set tmpAttr to NSMutableAttributedString’s alloc()’s initWithString:aStr set aRange to current application’s NSMakeRange(0, tmpAttr’s |length|()) set aVal1 to NSFont’s fontWithName:aFontPSName |size|:aFontSize tmpAttr’s beginEditing() tmpAttr’s addAttribute:(NSFontAttributeName) value:aVal1 range:aRange tmpAttr’s endEditing() return tmpAttr end changeAttrStrsFontAttribute –スタイル付きテキストを指定フォルダ(POSIX path)にRTFで書き出し on saveStyledTextAsRTF(targFol, aStyledString) set bstyledLength to aStyledString’s |string|()’s |length|() set bDict to NSDictionary’s dictionaryWithObject:"NSRTFTextDocumentType" forKey:(NSDocumentTypeDocumentAttribute) set bRTF to aStyledString’s RTFFromRange:(current application’s NSMakeRange(0, bstyledLength)) documentAttributes:bDict set theName to (NSUUID’s UUID()’s UUIDString()) set thePath to NSString’s stringWithString:targFol set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:"rtf" return (bRTF’s writeToFile:thePath atomically:true) as boolean end saveStyledTextAsRTF –指定テキストデータ(atargText)内に、指定文字列(aSearchStr)が含まれる範囲情報(NSRange)をすべて取得する on searchWordWithRange(aTargText, aSearchStr) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:NSLiteralSearch range:aRange set aLoc to (detectedRange’s location) –CAUTION !!!! Sometimes aLoc returns not NSNotFound (-1) but a Very large number if (aLoc > 9.999999999E+9) or (aLoc = (current application’s NSNotFound)) then exit repeat hitArray’s addObject:detectedRange set aNum to aLoc as integer set bNum to (detectedRange’s |length|) as integer set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordWithRange –リストを指定デリミタをはさんでテキスト化 on retStrFromArrayWithDelimiter(aList, aDelim) set anArray to current application’s NSArray’s arrayWithArray:aList set aRes to anArray’s componentsJoinedByString:aDelim return aRes as list of string or string end retStrFromArrayWithDelimiter on retArrowText(aList, aDelim) –自分のASでよく使うハンドラ名称なので、同じものを用意 return my retStrFromArrayWithDelimiter(aList, aDelim) end retArrowText –テキストを指定デリミタでリスト化 on parseByDelim(aData, aDelim) set aText to current application’s NSString’s stringWithString:aData set aList to aText’s componentsSeparatedByString:aDelim return aList as list end parseByDelim |