— Created 2019-06-29 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html
property NSView : a reference to current application’s NSView property NSAlert : a reference to current application’s NSAlert property NSColor : a reference to current application’s NSColor property NSTextField : a reference to current application’s NSTextField property NSTextView : a reference to current application’s NSTextView property NSScrollView : a reference to current application’s NSScrollView property NSRunningApplication : a reference to current application’s NSRunningApplication
–property theResult : 0 property returnCode : 0 property segRes : missing value
set segRes to missing value
tell application "CotEditor" if (count every document) = 0 then return –No Document tell front document set aText to contents of it set lineTerm to (line ending) end tell –改行コードの選択(ドキュメントの状態から取得) if lineTerm = LF then set aRet to ASCII character 10 –To avoid keyword conflict (string) else if lineTerm = CR then set aRet to ASCII character 13 else if lineTerm = CRLF then set aRet to (ASCII character 13) & (ASCII character 10) else set aRet to ASCII character 10 end if end tell
–事前にテキストから自動で数値部分を抽出して分析 set cArray to extractNumberFromText(aText) of me set aRes to (cArray’s valueForKeyPath:"@max.self")’s intValue() set bRes to (cArray’s valueForKeyPath:"@min.self")’s intValue() set cRes to (cArray’s valueForKeyPath:"@count")’s intValue()
–事前に数字の分布シミュレーションを計算 set tmpLen to count every character of (aRes as string) set theList to my findPattern:("[0-9]{" & tmpLen & "}") inString:aText set sampleStr to calculateNumFreq(cArray, "■", aRet, bRes, aRes, true) of me
set sampleStr to return & return & "テスト集計結果:" & return & return & sampleStr
–テキストからの数値抽出時のパラメータ取得 set paramObj to {myMessage:"テキスト内の数値の度数分布集計", mySubMessage:"集計対象の数値の範囲と、集計時のグラフ生成時の構成文字を指定してください", mes1:"最小値(min.)", mes1Default:(bRes as string), mes2:"最大値(max.)", mes2Default:(aRes as string), mes3:"出力文字", mes3Default:"絆", aSample:sampleStr}
–set segRes to my inputParametersFromAlertDialog:paramObj–for debugging my performSelectorOnMainThread:"inputParametersFromAlertDialog:" withObject:(paramObj) waitUntilDone:true if segRes = missing value then return –Cancel
–度数分布計算 set tmpLen to count every character of ((a2Res of segRes) as string) set theList to my findPattern:("[0-9]{" & tmpLen & "}") inString:aText set outStr to calculateNumFreq(cArray, a3Res of segRes, aRet, a1Res of segRes, a2Res of segRes, false) of me
–テキストエディタへの集計結果出力 tell application "CotEditor" tell front document set contents of it to (aText & aRet & aRet & "集計結果:" & aRet & aRet & outStr & aRet) end tell end tell
on inputParametersFromAlertDialog:paramObj –Receive Parameters set aMainMes to (myMessage of paramObj) as string –Main Message set aSubMes to (mySubMessage of paramObj) as string –Sub Message set mes1Label to (mes1 of paramObj) as string –Text Input field 1 Label set mes2Label to (mes2 of paramObj) as string –Text Input field 2 Label set mes3Label to (mes3 of paramObj) as string –Text Input field 3 Label set aTextInputString to (mes1Default of paramObj) as string –Text Input field 1 Default value set bTextInputString to (mes2Default of paramObj) as string –Text Input field 2 Default value set cTextInputString to (mes3Default of paramObj) as string –Text Input field 2 Default value set sampleString to (aSample of paramObj) as string — Create a view set theView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 500, 400)) — create two input field and their labels pairs –NSTextFields for Input set aTextInput to makeNSTextField(100, 70, 140, 20, true, (aTextInputString), true, true) of me set bTextInput to makeNSTextField(100, 35, 140, 20, true, (bTextInputString), true, true) of me set cTextInput to makeNSTextField(100, 0, 140, 20, true, (cTextInputString), true, true) of me –Labels set a1TF to makeNSTextField(0, 70, 100, 20, false, (mes1Label), false, false) of me set a2TF to makeNSTextField(0, 35, 100, 20, false, (mes2Label), false, false) of me set a3TF to makeNSTextField(0, 0, 100, 20, false, (mes3Label), false, false) of me –Sample Text View set aColor to NSColor’s colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.9 set tvScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 120, 500, 300)) set tvView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 120, 500, 380)) tvView’s setRichText:true tvView’s useAllLigatures:true tvView’s setTextColor:(NSColor’s cyanColor()) — tvView’s setFont:(current application’s NSFont’s fontWithName:"HiraginoSans-W1" |size|:16.0) tvView’s setBackgroundColor:aColor tvView’s setEditable:false tvScroll’s setDocumentView:tvView tvView’s enclosingScrollView()’s setHasVerticalScroller:true tvView’s setString:(sampleString) theView’s setSubviews:{a1TF, aTextInput, a2TF, bTextInput, a3TF, cTextInput, tvScroll} — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aMainMes its setInformativeText:aSubMes its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:theView end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode as number) = 1001 then set my segRes to missing value else set s1Val to (aTextInput’s integerValue()) as integer set s2Val to (bTextInput’s integerValue()) as integer set s3Val to (cTextInput’s stringValue()) as string –return {a1Res:s1Val, a2Res:s2Val, a3Res:s3Val}–old version’s way to return values set my segRes to {a1Res:s1Val, a2Res:s2Val, a3Res:s3Val} end if end inputParametersFromAlertDialog:
on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal:
on makeNSTextField(xPos as integer, yPos as integer, myWidth as integer, myHeight as integer, editableF as boolean, setVal as string, backgroundF as boolean, borderedF as boolean) set aNSString to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(xPos, yPos, myWidth, myHeight)) aNSString’s setEditable:(editableF) aNSString’s setStringValue:(setVal) aNSString’s setDrawsBackground:(backgroundF) aNSString’s setBordered:(borderedF) return aNSString end makeNSTextField
–与えられたテキストから数値部分を抽出して1D Arrayで返す on extractNumberFromText(aText) set aStr to current application’s NSString’s stringWithString:aText –set nonDigitCharacterSet to (current application’s NSCharacterSet’s decimalDigitCharacterSet())’s invertedSet() set nonDigitCharacterSet to (current application’s NSCharacterSet’s characterSetWithCharactersInString:"0123456789.,")’s invertedSet() set bArray to (aStr’s componentsSeparatedByCharactersInSet:nonDigitCharacterSet) –Sweep Blank Items load framework –BridgePlus set cArray to (current application’s SMSForder’s arrayByDeletingBlanksIn:(bArray))’s valueForKey:"intValue" return cArray –return as NSArray end extractNumberFromText
–正規表現でテキスト中から指定パターンに該当する箇所を抽出してリストで返す on findPattern:thePattern inString:theString set theOptions to ((current application’s NSRegularExpressionDotMatchesLineSeparators) as integer) + ((current application’s NSRegularExpressionAnchorsMatchLines) as integer) set theRegEx to current application’s NSRegularExpression’s regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value) set theFinds to theRegEx’s matchesInString:theString options:0 range:{location:0, |length|:length of theString} set theFinds to theFinds as list — so we can loop through set theResult to {} — we will add to this set theNSString to current application’s NSString’s stringWithString:theString repeat with i from 1 to count of items of theFinds set theRange to (item i of theFinds)’s range() set end of theResult to (theNSString’s substringWithRange:theRange) as integer end repeat return theResult end findPattern:inString:
–1D Listをユニーク化してソート on uniquifyAndSort1DList(theList as list, aBool as boolean) set aArray to current application’s NSArray’s arrayWithArray:theList set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self" set aDdesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:aBool selector:"compare:" set cArray to bArray’s sortedArrayUsingDescriptors:{aDdesc} set bList to cArray as list return bList end uniquifyAndSort1DList
–度数分布集計して文字グラフ出力 on calculateNumFreq(theList, outChar, aLineTerminator, aMin, aMax, zeroPaddingF) set theCountedSet to current application’s NSCountedSet’s alloc()’s initWithArray:theList set newArray to current application’s NSMutableArray’s new() set kList to uniquifyAndSort1DList(theList, false) of me –降順ソート set maxDigit to (count every character of (aMax as string)) repeat with i in kList if (i ≥ aMin) and (i ≤ aMax) then (newArray’s addObject:{theKey:i, theCount:(theCountedSet’s countForObject:i)}) end if end repeat set outStr to "" repeat with i in newArray as list set j to (current application’s NSDictionary’s dictionaryWithDictionary:i) set tmpStr to (j’s valueForKey:"theKey") if zeroPaddingF = true then –Zero Pagging set keyNumStr to numToZeroPaddingStr(tmpStr, maxDigit, "0") of me else –No Padding copy (tmpStr as string) to keyNumStr end if set outStr to outStr & keyNumStr & ":" set aNum to (j’s valueForKey:"theCount") repeat aNum times set outStr to outStr & outChar end repeat set outStr to outStr & aLineTerminator end repeat end calculateNumFreq
–整数の値に指定桁数ゼロパディングして文字列で返す on numToZeroPaddingStr(aNum as integer, aDigit as integer, paddingChar as text) set aNumForm to current application’s NSNumberFormatter’s alloc()’s init() aNumForm’s setPaddingPosition:(current application’s NSNumberFormatterPadBeforePrefix) aNumForm’s setPaddingCharacter:paddingChar aNumForm’s setMinimumIntegerDigits:aDigit set bNum to current application’s NSNumber’s numberWithInt:aNum set aStr to aNumForm’s stringFromNumber:bNum return aStr as text end numToZeroPaddingStr
|