AppleScript名:ISO8601日付文字列を生成 v2 |
use AppleScript version "2.5" use scripting additions use framework "Foundation" set aDate to getDateInternational(2018, 12, 18, 9, 59, 35, "CET") –―year, month, date, hour, minute, second, time zone abbreviation. set bStr to retISO8601DateTimeString(aDate, "CET") as string –> "2018-12-18T09:59:35+01:00" –NSDate -> ISO8601 Date & Time String on retISO8601DateTimeString(targDate, timeZoneAbbreviation) set theNSDateFormatter to current application’s NSDateFormatter’s alloc()’s init() theNSDateFormatter’s setDateFormat:"yyyy-MM-dd’T’HH:mm:ssZZZZZ" — Five zeds to get a colon in the time offset (except with GMT). theNSDateFormatter’s setTimeZone:(current application’s NSTimeZone’s timeZoneWithAbbreviation:(timeZoneAbbreviation)) return (theNSDateFormatter’s stringFromDate:targDate) as text end retISO8601DateTimeString –Make a GMT Date Object with parameters from a given time zone. on getDateInternational(aYear, aMonth, aDay, anHour, aMinute, aSecond, timeZoneAbbreviation) set theNSCalendar to current application’s NSCalendar’s currentCalendar() theNSCalendar’s setTimeZone:(current application’s NSTimeZone’s timeZoneWithAbbreviation:(timeZoneAbbreviation)) set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:aDay hour:anHour minute:aMinute |second|:aSecond nanosecond:0 return theDate as date end getDateInternational |
カテゴリー: Text
date objectをRFC2822 date stringに変換
AppleScript名:date objectをRFC2822 date stringに変換 |
— Created 2017-12-19 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aDate to getDateInternational(2018, 2, 1) of me set bStr to rfc2822DateTimeString(aDate, "JST") as string –> "Thu, 01 Feb 2018 00:00:00 +0900" –date -> RFC2822 Date & Time String on rfc2822DateTimeString(targDate, timeZoneName as string) set theNSDateFormatter to current application’s NSDateFormatter’s alloc()’s init() theNSDateFormatter’s setDateFormat:"EEE, dd MMM yyyy HH:mm:ss Z" theNSDateFormatter’s setTimeZone:(current application’s NSTimeZone’s alloc()’s initWithName:timeZoneName) theNSDateFormatter’s setLocale:(current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:"en_US_POSIX") return (theNSDateFormatter’s stringFromDate:targDate) as text end rfc2822DateTimeString –Make Date Object from parameters on getDateInternational(aYear as integer, aMonth as integer, aDay as integer) set theNSCalendar to current application’s NSCalendar’s currentCalendar() set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:aDay hour:0 minute:0 |second|:0 nanosecond:0 return theDate as date end getDateInternational |
RFC822エンコーダー v0
AppleScript名:RFC822エンコーダー v0 |
— Created 2016-02-07 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" set aStr to "2016-02-06 11:00:00" set rfc822str to retRFC822StrFromDateStr(aStr) of me –> "Sat, 06 Feb 2016 11:00:00GMT" on retRFC822StrFromDateObj(aObj) set aFormat to "yyyy-MM-dd HH:mm:ss" set aTZ to "GMT" set bDate to retNSDateFromStringWithTimeZone(aStr, aFormat, aTZ) of me set aGMform to current application’s NSDateFormatter’s alloc()’s init() aGMform’s setDateFormat:"EEE, dd MMM yyyy HH:mm:ss" aGMform’s setTimeZone:(current application’s NSTimeZone’s timeZoneForSecondsFromGMT:0) set usLocale to current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:"GMT" aGMform’s setLocale:usLocale set theDate to aGMform’s stringFromDate:bDate set theDate to theDate’s stringByAppendingString:"GMT" return theDate as string end retRFC822StrFromDateObj on retRFC822StrFromDateStr(aStr) set aFormat to "yyyy-MM-dd HH:mm:ss" set aTZ to "GMT" set bDate to retNSDateFromStringWithTimeZone(aStr, aFormat, aTZ) of me set aGMform to current application’s NSDateFormatter’s alloc()’s init() aGMform’s setDateFormat:"EEE, dd MMM yyyy HH:mm:ss" aGMform’s setTimeZone:(current application’s NSTimeZone’s timeZoneForSecondsFromGMT:0) set usLocale to current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:"GMT" aGMform’s setLocale:usLocale set theDate to aGMform’s stringFromDate:bDate set theDate to theDate’s stringByAppendingString:" GMT" return theDate as string end retRFC822StrFromDateStr on retNSDateFromStringWithTimeZone(aText, aFormat, aTZ) set aStr to current application’s NSString’s stringWithString:aText set theNSDateFormatter to current application’s NSDateFormatter’s alloc()’s init() theNSDateFormatter’s setDateFormat:(current application’s NSString’s stringWithString:aFormat) theNSDateFormatter’s setTimeZone:(current application’s NSTimeZone’s timeZoneWithAbbreviation:(current application’s NSString’s stringWithString:aTZ)) return (theNSDateFormatter’s dateFromString:aStr) –as date end retNSDateFromStringWithTimeZone |
RFC822デコーダー v0
AppleScript名:RFC822デコーダー v0 |
— Created 2016-02-07 by Takaaki Naganoya — 2016 Piyomaru Software –http://stackoverflow.com/questions/1850824/parsing-a-rfc-822-date-with-nsdateformatter use AppleScript version "2.4" use scripting additions use framework "Foundation" set dateString to "Sun, 19 May 2002 15:21:36 GMT" –set dateString to "Tue, 01 Dec 2009 08:48:25 +0000" set aRes to rfc822StrDecode(dateString) of me –> date "2002年5月20日月曜日 0:21:36" –http://stackoverflow.com/questions/1850824/parsing-a-rfc-822-date-with-nsdateformatter on rfc822StrDecode(dateString) set aTZ to "GMT" set en_US_POSIX to current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:"en_US_POSIX" set dateFormatter to current application’s NSDateFormatter’s alloc()’s init() dateFormatter’s setLocale:en_US_POSIX dateFormatter’s setTimeZone:(current application’s NSTimeZone’s timeZoneWithAbbreviation:(current application’s NSString’s stringWithString:aTZ)) set aDate to missing value set RFC822String to (current application’s NSString’s stringWithString:dateString)’s uppercaseString() if (RFC822String’s rangeOfString:",")’s location() is not equal to (current application’s NSNotFound) then if aDate is equal to missing value then — Sun, 19 May 2002 15:21:36 GMT dateFormatter’s setDateFormat:"EEE, d MMM yyyy HH:mm:ss zzz" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — Sun, 19 May 2002 15:21 GMT dateFormatter’s setDateFormat:"EEE, d MMM yyyy HH:mm zzz" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — Sun, 19 May 2002 15:21:36 dateFormatter’s setDateFormat:"EEE, d MMM yyyy HH:mm:ss" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — Sun, 19 May 2002 15:21:36 dateFormatter’s setDateFormat:"EEE, d MMM yyyy HH:mm" set aDate to dateFormatter’s dateFromString:RFC822String end if else if aDate is equal to missing value then — 19 May 2002 15:21:36 GMT dateFormatter’s setDateFormat:"d MMM yyyy HH:mm:ss zzz" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — 19 May 2002 15:21 GMT dateFormatter’s setDateFormat:"d MMM yyyy HH:mm zzz" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — 19 May 2002 15:21:36 dateFormatter’s setDateFormat:"d MMM yyyy HH:mm:ss" set aDate to dateFormatter’s dateFromString:RFC822String end if if aDate is equal to missing value then — 19 May 2002 15:21 dateFormatter’s setDateFormat:"d MMM yyyy HH:mm" set aDate to dateFormatter’s dateFromString:RFC822String end if end if if aDate is equal to missing value then return false return aDate as date end rfc822StrDecode |
画像を文字認識して文字エリアを塗りつぶし v3
▲Original Image
▲Filtered Image(CIColorMonochrome)
▲Filtered Image(CIColorPosterize)
▲Result Image
AppleScript名:画像を文字認識して文字エリアを塗りつぶし v3 |
— Created 2017-11-19 by Takaaki Naganoya — Modified 2018-02-11 by Takaaki Naganoya –v3:画像の前処理を付加 use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" use framework "QuartzCore" use framework "AppKit" set retinaF to (current application’s NSScreen’s mainScreen()’s backingScaleFactor()) as real –> 2.0 (Retina) / 1.0 (Non Retina) set imgPath to POSIX path of (choose file of type {"public.image"}) set anImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:imgPath set aCIImage to convNSImageToCIimage(anImage) –モノクロ化フィルタ set bCIImage to monochromefilterACGImage(aCIImage) of me –2階調ポスタライズフィルタ set cCIImage to posterizefilterACGImage(bCIImage) of me –文字領域認識 set detectList to textDetect(cCIImage) of me –描画開始 anImage’s lockFocus() repeat with i in detectList set origX to (x of origin of i) / retinaF set origY to (y of origin of i) / retinaF set sizeX to (width of |size| of i) / retinaF set sizeY to (height of |size| of i) / retinaF set theRect to {{x:origX, y:origY}, {width:sizeX, height:sizeY}} set theNSBezierPath to current application’s NSBezierPath’s bezierPath (theNSBezierPath’s appendBezierPathWithRect:theRect) set rRnd to (random number from 1 to 10) / 10 set gRnd to (random number from 1 to 10) / 10 set bRnd to (random number from 1 to 10) / 10 set fillColor to (current application’s NSColor’s colorWithCalibratedRed:rRnd green:gRnd blue:bRnd alpha:0.6) fillColor’s |set|() –色設定 theNSBezierPath’s fill() –ぬりつぶし end repeat anImage’s unlockFocus() –描画ここまで set aUUIDstr to (current application’s NSUUID’s UUID()’s UUIDString()) as string set aPath to ((current application’s NSString’s stringWithString:imgPath)’s stringByDeletingLastPathComponent()’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:"png" set fRes to saveImageRepAtPathAsPNG(anImage, aPath) of me on openImageFile(imageFile) — imageFile: POSIX path 形式のファイルパス set fileURL to current application’s |NSURL|’s fileURLWithPath:imageFile return current application’s CIImage’s alloc()’s initWithContentsOfURL:fileURL end openImageFile –画像を指定パスにPNG形式で保存 on saveImageRepAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep –書き出しファイルパス情報を作成 set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() –書き出し set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)) return (myNewImageData’s writeToFile:newPath atomically:true) as boolean end saveImageRepAtPathAsPNG on textDetect(imageRef) — 検出器のオプションを NSDictonary で作成 set optDic1 to current application’s NSDictionary’s dictionaryWithObject:(current application’s CIDetectorAccuracyHigh) forKey:(current application’s CIDetectorAccuracy) set textDetector to current application’s CIDetector’s detectorOfType:(current application’s CIDetectorTypeText) context:(missing value) options:optDic1 — 文字エリア検出を実行 set optDic2 to current application’s NSDictionary’s dictionaryWithObject:true forKey:(current application’s CIDetectorReturnSubFeatures) set textArray to textDetector’s featuresInImage:imageRef options:optDic2 set fList to {} — 検出されたテキストの位置とサイズをログに出力 repeat with i from 1 to (count of textArray) set typeFace to item i of textArray set bList to (typeFace’s subFeatures()) repeat with ii in bList set aBounds to ii’s |bounds|() set aType to ii’s type() set the end of fList to aBounds end repeat end repeat return fList end textDetect on convCIimageToNSImage(aCIImage) set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithCIImage:aCIImage set tmpSize to aRep’s |size|() set newImg to current application’s NSImage’s alloc()’s initWithSize:tmpSize newImg’s addRepresentation:aRep return newImg end convCIimageToNSImage on convNSImageToCIimage(aNSImage) set tiffDat to aNSImage’s TIFFRepresentation() set aRep to current application’s NSBitmapImageRep’s imageRepWithData:tiffDat set newImg to current application’s CIImage’s alloc()’s initWithBitmapImageRep:aRep return newImg end convNSImageToCIimage –Posterizeフィルタ on posterizefilterACGImage(aCIImage) set aFilter to current application’s CIFilter’s filterWithName:"CIColorPosterize" aFilter’s setDefaults() aFilter’s setValue:aCIImage forKey:"inputImage" aFilter’s setValue:2 forKey:"inputLevels" set aOutImage to aFilter’s valueForKey:"outputImage" return aOutImage end posterizefilterACGImage –Monochromeフィルタ on monochromefilterACGImage(aCIImage) set aFilter to current application’s CIFilter’s filterWithName:"CIColorMonochrome" aFilter’s setDefaults() aFilter’s setValue:aCIImage forKey:"inputImage" aFilter’s setValue:1.0 forKey:"inputIntensity" set aOutImage to aFilter’s valueForKey:"outputImage" return aOutImage end monochromefilterACGImage |
RTF本文内の色を置換 v2
指定のRTF書類の本文中の色を置換するAppleScriptです。
指定のRTF書類内のカラーをざっくりとした色に分類し、同じくざっくりとした色名で置換対象を指定し(blue, green)、指定色(black)に色置換。結果をデスクトップ上に別名で保存します。
AppleScript名:RTF本文内の色を置換 v2 |
— Created 2018-01-13 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSData : a reference to current application’s NSData 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 NSPredicate : a reference to current application’s NSPredicate property NSDictionary : a reference to current application’s NSDictionary property NSMutableArray : a reference to current application’s NSMutableArray 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 targFilePath to POSIX path of (choose file of type {"public.rtf"}) set targColorNameList to {"blue", "green"} –replace target color names set toColor to NSColor’s blackColor() –to color set aRes to replaceRTFColorsByColorName(targFilePath, targColorNameList, toColor, 65535) of me –指定RTF書類本文中、名称で指定した色の該当箇所を指定色(NSColor)に置換する(複数色) on replaceRTFColorsByColorName(targFilePath as string, targColorNameList as list, toColor, aColorMax as integer) script spd property hitList : {} end script set (hitList of spd) to {} set aFilePath to NSString’s stringWithString:(targFilePath) set aData to NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value) set theStyledText to NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(missing value) |error|:(missing value) set attrList to getAttributeRunsFromAttrString(theStyledText, aColorMax) of me set attrArray to NSMutableArray’s arrayWithArray:attrList theStyledText’s beginEditing() —— repeat with ii in targColorNameList set jj to contents of ii set thePred to NSPredicate’s predicateWithFormat_("colorName == %@", jj) set (hitList of spd) to ((attrArray’s filteredArrayUsingPredicate:thePred)’s valueForKey:"rangeVal") as list repeat with i in (hitList of spd) (theStyledText’s addAttribute:(NSForegroundColorAttributeName) value:toColor range:(contents of i)) end repeat end repeat theStyledText’s endEditing() —— –Save RTF to desktop set targFol to current application’s NSHomeDirectory()’s stringByAppendingPathComponent:"Desktop" set aRes to saveStyledTextAsRTF(targFol, theStyledText) of me return aRes as boolean end replaceRTFColorsByColorName –AttributedStringを書式でlist of record化 on getAttributeRunsFromAttrString(theStyledText, aColorMax) 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} –String set aText to (thePureString’s substringWithRange:theRange) as string –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()) * aColorMax set aGreen to (aColor’s greenComponent()) * aColorMax set aBlue to (aColor’s blueComponent()) * aColorMax 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 –Color Name set cName to retColorName(aRed, aGreen, aBlue, aColorMax) of me –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 set the end of (styleList of aSpd) to {stringVal:aText, colorStr:colStrForFind, colorVal:colList, fontName:aDFontName as string, fontSize:aDFontSize, rangeVal:theRange, colorName:cName} set startIndex to current application’s NSMaxRange(theRange) end repeat return (styleList of aSpd) end getAttributeRunsFromAttrString –RGB値から色名称(だいたいの色)を計算する on retColorName(rCol as integer, gCol as integer, bCol as integer, aColMax as integer) set aCol to makeNSColorFromRGBAval(rCol, gCol, bCol, aColMax, aColMax) of me set hueVal to aCol’s hueComponent() as real set satVal to aCol’s saturationComponent() as real set brightVal to aCol’s brightnessComponent() as real if satVal ≤ 0.01 then set satVal to 0.0 if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "cyan" else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "magenta" end if end if return colName end retColorName 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 –スタイル付きテキストを指定フォルダ(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 |
rtf_rtfdからテキスト抽出
RTFないしRTFD(添付ファイルつきRTF)からテキストを抽出するAppleScriptです。
AppleScript名:rtf_rtfdからテキスト抽出 |
— Created 2018-02-10 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aFile to choose file of type {"com.apple.rtfd", "public.rtf"} set aRes to retTextFromRTF(aFile) of me on retTextFromRTF(aFile) set aFilePath to current application’s NSString’s stringWithString:(POSIX path of aFile) set anExt to (aFilePath’s pathExtension()) as string if anExt = "rtfd" then set aFilePath to aFilePath’s stringByAppendingString:"TXT.rtf" end if set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value) set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(missing value) |error|:(missing value) if theStyledText is not equal to missing value then return (theStyledText’s |string|()) as string else return false –Not RTF file end if end retTextFromRTF |
指定URLをロードしてtitleを取得
AppleScript名:指定URLをロードしてtitleを取得 |
— Created 2015-09-07 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "WebKit" property loadDone : false property theWebView : missing value set aURL to "https://www.youtube.com/watch?v=WuziqYptTyE" set aTitle to getPageTitle(aURL) –> "戦場の絆ポータブル【HD】鉱山都市 オンライン対戦 2015.09.04 – YouTube" on getPageTitle(aURL) –Check If this script runs in foreground if not (current application’s NSThread’s isMainThread()) as boolean then display alert "This script must be run from the main thread (Command-Control-R in Script Editor)." buttons {"Cancel"} as critical error number -128 end if set my loadDone to false set my theWebView to missing value openURL(aURL) set waitLoop to 1000 * 60 –60 seconds set hitF to false repeat waitLoop times if my loadDone = true then set hitF to true exit repeat end if current application’s NSThread’s sleepForTimeInterval:("0.001" as real) –delay 0.001 end repeat if hitF = false then return set jsText to "document.title" set x to ((my theWebView)’s stringByEvaluatingJavaScriptFromString:jsText) as text set my theWebView to missing value return x end getPageTitle –WebViewにURLを読み込む on openURL(aURL) set noter1 to current application’s NSNotificationCenter’s defaultCenter() set my theWebView to current application’s WebView’s alloc()’s init() noter1’s addObserver:me selector:"webLoaded:" |name|:(current application’s WebViewProgressFinishedNotification) object:(my theWebView) my (theWebView’s setMainFrameURL:aURL) end openURL –Web Viewのローディング完了時に実行 on webLoaded:aNotification set my loadDone to true end webLoaded: |
URLの妥当性チェック
AppleScript名:URLの妥当性チェック |
— Created 2015-09-06 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –http://stackoverflow.com/questions/1471201/how-to-validate-an-url-on-the-iphone set aRes1 to validateURL("http://www.apple.com/jp") –> true set aRes2 to validateURL("http.s://www.gmail.com") –> false set aRes3 to validateURL("https:.//gmailcom") –> false set aRes4 to validateURL("https://gmail.me.") –> false set aRes5 to validateURL("https://www.gmail.me.com.com.com.com") –> true set aRes6 to validateURL("http:/./ww-w.wowone.com") –> false set aRes7 to validateURL("http://.www.wowone") –> false set aRes8 to validateURL("http://www.wow-one.com") –> true set aRes9 to validateURL("http://www.wow_one.com") –> true set aRes10 to validateURL("http://.") –> false set aRes11 to validateURL("http://") –> false set aRes12 to validateURL("http://k") –> false return {aRes2, aRes3, aRes4, aRes5, aRes6, aRes7, aRes8, aRes9, aRes10, aRes11, aRes12} –> {false, false, false, true, false, false, true, true, false, false, false} –URLの妥当性チェック on validateURL(anURL as text) –set regEx1 to current application’s NSString’s stringWithString:"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+" set regEx1 to current application’s NSString’s stringWithString:"((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+" set predicate1 to current application’s NSPredicate’s predicateWithFormat_("SELF MATCHES %@", regEx1) set aPredRes1 to (predicate1’s evaluateWithObject:anURL) as boolean return aPredRes1 end validateURL |
画像にステガノグラフィーで埋め込まれた文字列を取り出す
オープンソースのステガノグラフィーのプログラム「ISStego」(By Isaac Stevao Sena氏)を用いて、JPEG画像に埋め込んだ文字情報を取り出すAppleScriptです。
ISStegoは普通にObjective-Cで書かれたGUIベースのアプリケーションだったので、そのままではAppleScriptから呼び出せませんでした。
そこで、中身をそのままそっくり移し替えた新規フレームワーク「stegLib.framework」をでっちあげてビルドし、AppleScriptから呼び出してみました。
JPEG画像にUTF-8の文字情報(日本語文字列)を埋め込んで別のPNG画像に書き出し、書き出した画像からUTF-8の文字情報を取り出す実験を行ってみました。エンコードもデコードもうまく行っているようなので、うまく処理できていると思います。
ステガノグラフィーについて初めて聞いたのは20年ぐらい前のことと記憶していますが、こんなに手軽に使えるようになっていたとは驚きです。
▲Original Image
▲Information Embedded Image
AppleScript名:画像にステガノグラフィーで埋め込まれた文字列を取り出す |
— Created 2015-10-21 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "stegLib" –https://github.com/isena/ISStego set aFile to POSIX path of (choose file of type {"public.png"}) set aFilePath to current application’s NSString’s stringWithString:aFile set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL set aDecodedData to current application’s ISStegoDecoder’s alloc()’s init()’s decodeStegoImage:aImage |error|:(missing value) set resStr to (current application’s NSString’s alloc()’s initWithData:aDecodedData encoding:(current application’s NSUTF8StringEncoding)) as string –> "長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software" |
画像にステガノグラフィーで情報を埋め込む
オープンソースのステガノグラフィー(steganography)のプログラム「ISStego」(By Isaac Stevao Sena氏)を用いて、JPEG画像に文字情報を埋め込むAppleScriptです。
ISStegoは普通にObjective-Cで書かれたGUIベースのアプリケーションだったので、そのままではAppleScriptから呼び出せませんでした。
そこで、中身をそのままそっくり移し替えた新規フレームワーク「stegLib.framework」をでっちあげてビルドし、AppleScriptから呼び出してみました。
JPEG画像にUTF-8の文字情報(日本語文字列)を埋め込んで別のPNG画像に書き出し、書き出した画像からUTF-8の文字情報を取り出す実験を行ってみました。エンコードもデコードもうまく行っているようなので、うまく処理できていると思います。
ステガノグラフィー(steganography)について初めて聞いたのは20年ぐらい前のことと記憶していますが、こんなに手軽に使えるようになっていたとは驚きです。
Twitterにプログラムを投稿するのに、(140文字制限を回避するため)文字を画像化して投稿しているのを見て、「そこまでやるなら、画像にプログラムの文字データを埋め込めばいいのに」と思い、「ステガノグラフィーで埋め込めばいいんじゃないか?」ということで、埋め込めるようになったのですが、肝心のTwitterクライアントから画像をダウンロードする手段がなかったのがダメダメでした(Webブラウザ経由ならOKです)。
▲Original Image
▲Information Embedded Image
AppleScript名:画像にステガノグラフィーで情報を埋め込む |
— Created 2015-10-21 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "stegLib" –https://github.com/isena/ISStego set aFile to POSIX path of (choose file of type {"public.jpeg"}) set encString to "長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software" set aFilePath to current application’s NSString’s stringWithString:aFile set aExt to "png" set newPath to aFilePath’s stringByDeletingPathExtension() set newPath2 to newPath’s stringByAppendingString:"_stego" set newPath3 to newPath2’s stringByAppendingPathExtension:aExt set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL set strData to current application’s NSString’s stringWithString:encString set aEncimage to current application’s ISStegoEncoder’s alloc()’s init()’s stegoImageForImage:aImage |data|:strData |error|:(missing value) my saveImageRepAtPathAsPNG(aEncimage, newPath3) –画像を指定パスにPNG形式で保存 on saveImageRepAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)) return (myNewImageData’s writeToFile:newPath atomically:true) as boolean end saveImageRepAtPathAsPNG |
Camel Case化
AppleScript名:Camel Case化 |
— Created 2015-12-24 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" camelCase("this is a pen") of me –> "thisIsAPen." on camelCase(aPhrase) set firstWord to current application’s NSString’s stringWithString:(word 1 of aPhrase) set firstWord to firstWord’s |lowercaseString|() set restOfPhrase to current application’s NSString’s stringWithString:(text from word 2 to -1 of aPhrase) set restOfPhrase to restOfPhrase’s capitalizedString()’s stringByReplacingOccurrencesOfString:space withString:"" set newPhrase to firstWord’s stringByAppendingString:restOfPhrase return (newPhrase’s stringByFoldingWithOptions:(current application’s NSDiacriticInsensitiveSearch) locale:(missing value)) as text end camelCase |
文字エンコーディングを自動判別してファイル読み込み v1.2.1
指定のテキストファイル(日本語テキストを想定)を、文字エンコーディングを自動判定して読み込むAppleScriptです。
これまで、日本語テキストファイルの文字エンコーディングを自動判定するのにテキストエディタをAppleScriptからコントロールして使っていましたが、それだと並列処理するAppleScriptの中で使用できないし、テキストエディタがない環境では実行することができません(ダウンロードすればいいだけの話ですが)。
さまざまな日本語テキストエディタのソースコードをながめて、文字コードの自動判定ロジックがわかってきたので、AppleScriptで実装してみました。さらに、独自の「文字化け判定ロジック」を考えたので、それを併用しています。
Step 1 伝統的な判定(勝ち抜け方式)
伝統的な文字コードの判定を順次行います。この、判定を行う順序が重要です。最初にISO2022JPのチェック、ついでEUC、UTF-8、シフトJISと、順次コード判定を行います。勝ち抜け方式で、妥当な文字エンコーディングとみなしたらそこで評価を打ち切ります。
Step 2 総当たり判定(全部評価してから考える)
UTF-16BE/LE/無印Unicodeについては、それぞれの文字エンコーディングで実際に評価してみて、文字化けしないものを採用します。独自ロジックにより文字化け状態をプログラム的に判断するのと、そのエンコーディングで読み込んだ結果をNSLinguisticTaggerで評価し、「ja」(日本語)と判定するかどうかの確認をすべてのエンコーディングで行なっています。
以上の2ステップでだいたい日本語テキストのエンコーディング自動判定ができています。
もし、寿司屋の湯のみ茶碗のように漢字で魚の名前を羅列した日本語テキストがUTF-16BEとかで書かれていたりすると自動判定できない可能性もありますが、青空文庫の日本語テキストやWebに掲載されているテクニカルな記事(アルファベットやカタカナの使用比率が高い)でテストしてみたところ、問題なく判定できています(実際に魚の名前のテキストを作って読み込んでみましたが、とくに問題はありませんでした)。
だいたい、日本語として意味をなしているようなテキストであれば、文字コードの自動判定はできているように思います。ただ、世間は広いので、本Scriptのロジックで判定できないようなケースもあるかもしれません。そのような時にはコメント欄やフォーラムへの報告をお願いいたします(対応するかどうかは別として。知り合いのテキストエディタ作者の方は、無償で公開しているソフトに文句を言われて「すぐに対応しろ!」だのと散々言われたそうで、、、、、、、)。
AppleScript名:文字エンコーディングを自動判別してファイル読み込み v1.2.1 |
— Created 2014-12-28 by Takaaki Naganoya — Modified 2014-12-29 by Shane Stanley — Modified 2015-10-03 by Takaaki Naganoya use AppleScript version "2.5" use scripting additions use framework "Foundation" set aPath to POSIX path of (choose file) set aRes to readJapanesTextFileWithGuessingEncoding(aPath) of me set bRes to aRes as string –Read Japanese text with detecting its text encoding on readJapanesTextFileWithGuessingEncoding(aPOSIXpath as string) –ISO2022JP check set aNSData to current application’s NSData’s dataWithContentsOfFile:aPOSIXpath set aDataLength to aNSData’s |length|() if aDataLength > 1024 then set aDataLength to 1024 –0x1B check set anNSString to current application’s NSString’s stringWithString:(character id 27) — 0x1B set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set theRange to aNSData’s rangeOfData:theData options:0 range:(current application’s NSMakeRange(0, aDataLength)) –found 0x1B in aNSData if |length| of theRange = 1 and location of theRange < aDataLength then set aStr to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSISO2022JPStringEncoding)) –21 if aStr is not equal to missing value then return (aStr as text) — ISO2022JP end if –EUC set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSJapaneseEUCStringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –UTF-8 set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF8StringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –SHift JIS set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSShiftJISStringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –UTF-16BE/LE/無印Unicodeは多数決を取る set resValue1 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16BigEndianStringEncoding)) as text –log resValue1 set sample1 to getTextSample(resValue1) of me set lang1 to specifyLanguageOfText(sample1) of me set para1 to length of (paragraphs of sample1) set words1 to length of (words of sample1) set resValue2 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16LittleEndianStringEncoding)) as text –log resValue2 set sample2 to getTextSample(resValue2) of me set lang2 to specifyLanguageOfText(sample2) of me set para2 to length of (paragraphs of sample2) set words2 to length of (words of sample2) set resValue3 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUnicodeStringEncoding)) as text –log resValue3 set sample3 to getTextSample(resValue3) of me set lang3 to specifyLanguageOfText(sample3) of me set para3 to length of (paragraphs of sample3) set words3 to length of (words of sample3) –文字および文法的に見て「日本語」ならそれを返す if lang1 = "ja" then return resValue1 if lang2 = "ja" then return resValue2 if lang3 = "ja" then return resValue2 –文字化けしたときには、日本語の「Word」として認識されづらく、Paragraphも少ない(1とか)なので条件で除外する if para1 is not equal to 1 then if (words1 ≤ words2) or (words1 ≤ words3) then return resValue1 end if end if if para2 is not equal to 1 then if (words2 ≤ words1) or (words2 ≤ words3) then return resValue2 end if end if if para3 is not equal to 1 then if (words3 ≤ words1) or (words3 ≤ words2) then return resValue3 end if end if return false (* –おまけ(未確認) set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1251StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1252StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1253StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1254StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1250StringEncoding)) if resValue is not equal to missing value then return resValue return false *) end readJapanesTextFileWithGuessingEncoding on specifyLanguageOfText(aStr) set aNSstring to current application’s NSString’s stringWithString:aStr set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage) set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0 tagger’s setString:aNSstring set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value) return aLanguage as text end specifyLanguageOfText on getTextSample(aText) set aLen to length of aText if aLen < 1024 then set bLen to aLen else set bLen to 1024 end if return (text 1 thru bLen of aText) end getTextSample |
UniversalDetectorで文字コード判定
UniversalDetector.frameworkを呼び出して指定のテキストファイルの文字コードを判定するAppleScriptです。
日本語のテキストで実験してみたところ、UTF-16系以外は正常に判定できています。日本語以外の言語を対象にした場合には使い手がありそうですが、日本語を対象にした場合には、「文字エンコーディングを自動判別してファイル読み込み v1.2.1」のほうが便利です。
–> UniversalDetector.framework
AppleScript名:UniversalDetectorで文字コード判定 |
— Created 2015-10-03 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "UniversalDetector" –https://github.com/JanX2/UniversalDetector set aPath to (POSIX path of (choose file)) set aStr to current application’s NSString’s stringWithString:aPath set aDetector to current application’s UniversalDetector’s new() aDetector’s analyzeContentsOfFile:aStr set aStr to current application’s NSString’s localizedNameOfStringEncoding:(aDetector’s encoding()) –> (NSString) "日本語(EUC)" –> (NSString) "日本語(ISO 2022-JP)" –> (NSString) "日本語(Shift JIS)" –> (NSString) "Unicode(UTF-8)" –> (NSString) "キリル文字(Windows)" –NG。本当はUTF-16 no BOM –> (NSString) "中国語(GB 18030)"–NG。本当はUTF-16BE –> (NSString) "Unicode(UTF-16)" set bStr to aDetector’s MIMECharset() –> (NSString) "EUC-JP" –> (NSString) "ISO-2022-JP" –> (NSString) "Shift_JIS" –> (NSString) "UTF-8" –> (NSString) "windows-1251"–NG –> (NSString) "gb18030"–NG –> (NSString) "UTF-16" set aNum to (aDetector’s confidence()) * 100 –> 100.0–"EUC-JP" –> 100.0–"ISO-2022-JP" –> 100.0–"Shift_JIS" –> 100.0–"UTF-8" –> 5.271286144853–UTF-16 no BOM –> 100.0–NGだが100%といっている –> 100.0– "UTF-16" return {aStr as string, bStr as string, aNum} |
base64エンコード、デコード v3
テキストのBase64エンコード/デコードを行うAppleScriptです。
このような基本的なデータ変換機能についてはAppleScript標準で持っていないため、Classic MacOS時代にはOSAX(Scripting Additions)で、Mac OS X時代になってからは他の言語処理系の機能を借りたり、Mac OS X用のOSAXを利用していたりしましたが、現在のmacOSではCocoaの機能を呼び出すのが一番手頃になってきました。
# サードパーティ製のOSAX(Scripting Additions)サポートはmacOS 10.14で廃止になりました。macOS標準搭載のStandard Additionsのみ利用可能です
AppleScript名:base64エンコード、デコード v3 |
— Created 2015-07-27 by Takaaki Naganoya — Updated 2015-07-28 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "ぴよまるソフトウェアPiyomaru Software" set theNSString to current application’s NSString’s stringWithString:aStr set theNSData to theNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set bStr to base64StringFromFileString(aStr) of me return bStr –> "44G044KI44G+44KL44K944OV44OI44Km44Kn44KiUGl5b21hcnUgU29mdHdhcmU=" –set aFilePath to POSIX path of (choose file) –base64StringFromFileAtPath(aFilePath) of me –Base 64 Decode on detaFromBase64String(aStr) set dataFrom64 to current application’s NSData’s alloc()’s initWithBase64EncodedString:aStr options:(current application’s NSDataBase64DecodingIgnoreUnknownCharacters) set aStr to current application’s NSString’s alloc()’s initWithData:dataFrom64 encoding:(current application’s NSUTF8StringEncoding) return aStr as text –stringではなくtext end detaFromBase64String –Base64 Encode on base64StringFromFileAtPath(aFilePath) set aDataFromFile to current application’s NSData’s dataWithContentsOfFile:aFilePath set aBase64EncStr to aDataFromFile’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileAtPath –Base64 Encode on base64StringFromFileString(aString) set bString to current application’s NSString’s stringWithString:aString set aData to bString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aBase64EncStr to aData’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileString |
デコードしたQRコードのメールデータの各フィールドを取り出す v2.2
AppleScript名:デコードしたQRコードのメールデータの各フィールドを取り出す v2.2 |
— Created 2016-12-12 by Shane Stanley — Modified 2016-12-14 by edama2 — Modified 2017-01-12 by Takaaki Naganoya use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "こんにちは、ぴよまるです MATMSG:TO:hiyoko@piyocast.com;SUB:たいとる;BODY:ほんぶん;; Takaaki Naganoya iPhoneから送信" set aDict to (parseStrByParamlabelAndTail(aStr, "MATMSG:", ":", ";") of me) set eMailAddrs to (aDict’s valueForKey:"TO") as string–> "hiyoko@piyocast.com" set aSubject to (aDict’s valueForKey:"SUB") as string –> "たいとる" set aBody to (aDict’s valueForKey:"BODY") as string –> "ほんぶん" on parseStrByParamlabelAndTail(aParamStr, aDataHeader, aParamLabel, aParamTail) set theScanner to current application’s NSScanner’s scannerWithString:aParamStr set aDict to current application’s NSMutableDictionary’s |dictionary|() —Skip over the data header set {theResult, theKey} to theScanner’s scanUpToString:aDataHeader intoString:(reference) if theResult as boolean = false then return false –Error: Data header is not present theScanner’s scanString:aDataHeader intoString:(missing value) repeat until (theScanner’s isAtEnd as boolean) — terminate check, return the result (aDict) to caller set {theResult, theKey} to theScanner’s scanUpToString:aParamLabel intoString:(reference) — skip over separator theScanner’s scanString:aParamLabel intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:aParamTail intoString:(reference) if theValue is missing value then set theValue to "" — skip over separator theScanner’s scanString:aParamTail intoString:(missing value) aDict’s setObject:theValue forKey:theKey end repeat return aDict end parseStrByParamlabelAndTail |
なろう系ルビタグを置換
AppleScript名:なろう系ルビタグを置換 |
— Created 2018-01-14 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" property NSString : a reference to current application’s NSString property NSScanner : a reference to current application’s NSScanner property NSMutableArray : a reference to current application’s NSMutableArray property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp set aStr to " 数多国ある西方諸国だが、元を辿ればとある一つの国へとつながっていた。それは幻晶騎士(シルエットナイト)の力により西方の地に覇をとなえた人類が作り上げた超巨大国家、その名を“ファダーアバーデン”という。 西方暦一二八九年の現在において西方諸国を構成する主要国家、“ジャロウデク王国”、“クシェペルカ王国”、“ロカール諸国連合”、“|孤独なる十一《イレブンフラッグス》”などの国々は、全てかの巨大国家が分裂してできた残滓なのである。" –set aStr to getEditorText() –"|○o○o○《XXXXX》" –> "XXXXX" set bRes to trimStrHeaderFromTo(aStr, "|", "《", "》") of me –"aaaaa○○○(XXXXX)" –> "XXXXX" set cStr to trimStrHeaderFromToForward(bRes, "(", ")") of me (* " 数多国ある西方諸国だが、元を辿ればとある一つの国へとつながっていた。それはシルエットナイトの力により西方の地に覇をとなえた人類が作り上げた超巨大国家、その名を“ファダーアバーデン”という。 西方暦一二八九年の現在において西方諸国を構成する主要国家、“ジャロウデク王国”、“クシェペルカ王国”、“ロカール諸国連合”、“イレブンフラッグス”などの国々は、全てかの巨大国家が分裂してできた残滓なのである。" *) –"|○o○o○《XXXXX》" –> "XXXXX" on trimStrHeaderFromTo(aParamStr, headerStr, fromStr, toStr) set theScanner to NSScanner’s scannerWithString:aParamStr set anArray to NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) set {theResult, theKey} to theScanner’s scanUpToString:headerStr intoString:(reference) theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:fromStr intoString:(reference) if theValue is missing value then set theValue to "" theScanner’s scanString:fromStr intoString:(missing value) anArray’s addObject:theValue end repeat if anArray’s |count|() = 0 then return aParamStr copy aParamStr to curStr repeat with i in (anArray as list) set curStr to repChar(curStr, i & fromStr, "") of me end repeat set curStr to repChar(curStr, toStr, "") of me return curStr end trimStrHeaderFromTo –"aaaaa○○○(XXXXX)" –> "XXXXX" on trimStrHeaderFromToForward(aParamStr, fromStr, toStr) set theScanner to NSScanner’s scannerWithString:aParamStr set anArray to NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference) set curLoc to (theScanner’s scanLocation()) + 1 –scan back to different kind of character set prevKind to detectCharKindMain(text (curLoc – 1) of aParamStr) of me repeat with i from curLoc – 2 to 1 by -1 set aStr to text i of aParamStr set curKind to detectCharKindMain(aStr) of me if prevKind is not equal to curKind then exit repeat end if end repeat try set tmpStr to text (i + 1) thru curLoc of aParamStr theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:fromStr intoString:(reference) if theValue is missing value then set theValue to "" theScanner’s scanString:fromStr intoString:(missing value) anArray’s addObject:tmpStr end try end repeat if anArray’s |count|() = 0 then return aParamStr copy aParamStr to curStr repeat with i in (anArray as list) set curStr to repChar(curStr, i, "") of me end repeat set curStr to repChar(curStr, toStr, "") of me return curStr end trimStrHeaderFromToForward on repChar(aStr, targStr, repStr) set aString to current application’s NSString’s stringWithString:aStr set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr set cString to bString as string return cString end repChar –文字種別判定 on detectCharKindMain(aStr) set s1Res to chkKanji(aStr) of me set s2Res to chkKatakana(aStr) of me set s3Res to chkHiragana(aStr) of me set s4Res to chkLineFeed(aStr) of me set s5Res to chkSpecialSign(aStr) of me set s6Res to chkAlphaNumeric(aStr) if s1Res = true then set curKind to "Kanji" else if s2Res = true then set curKind to "Katakana" else if s3Res = true then set curKind to "Hiragana" else if s4Res = true then set curKind to "Line Feed" else if s5Res = true then set curKind to "Sign" else if s6Res = true then set curKind to "Alpha Numeric" end if return curKind end detectCharKindMain on chkKanji(aChar) return detectCharKind(aChar, "[一-龠]") of me end chkKanji on chkHiragana(aChar) return detectCharKind(aChar, "[ぁ-ん]") of me end chkHiragana on chkKatakana(aChar) return detectCharKind(aChar, "[ァ-ヶ]") of me end chkKatakana on chkLineFeed(aChar) return aChar is in {string id 10, string id 13, string id 13 & string id 10} end chkLineFeed on chkSpecialSign(aChar) return aChar is in {"「", "」", "『", "』", "ー", "―", "〜", "~", "!", "?", "&", "/", "《", "》", "#", "…", "・", "♪", "。", "、", ".", "々", "“", "”", "*", "(", ")", "(", ")", " ", " ", "§", "【", "】", "■", "%", "≒"} end chkSpecialSign on chkAlphaNumeric(aChar) return detectCharKind(aChar, "[a-zA-Z0-9a-zA-Z0-9]") of me –半角全角英数字 end chkAlphaNumeric on detectCharKind(aChar, aPattern) set aChar to NSString’s stringWithString:aChar set searchStr to NSString’s stringWithString:aPattern set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch) if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then return false else return true end if end detectCharKind on getEditorText() tell application "CotEditor" if (count every document) = 0 then return false tell front document return contents end tell end tell end getEditorText |
asHTMLexportLib v2
指定のAppleScript書類をスクリプトエディタでオープンし、書式情報を読み取ってURLリンク付きのHTML(テキスト)を生成するAppleScriptです。AppleScript Librariesとして他のScriptから呼び出して利用しています。
オリジナルは2006年ごろに作成したもので、「秘伝のタレ」よろしくその時々のOSの変更を反映させて使い続けています。
AppleScriptの書式(とくに色情報)をHTML書き出し時にどのように反映させるかについては、いろいろと「流派」があり、
・スクリプトエディタ上の色情報を読み取ってそのままカラータグで展開する派
・CSSなどで構文要素ごとにスタイルを指定する派
で、本Scriptは前者の方式で書かれた最古のScriptの末裔です。書き出しHTMLが長くなるというデメリットはあるものの、構造の単純さが幸いしてわずかな修正でメンテナンスを継続できています。
当初、AppleScriptからスクリプトエディタをコントロールすると不具合が多く、他のAppleScript開発環境(Script Debugger)からの実行を余儀なくされていました。macOS 10.6あたりでずいぶん安定して利用できるようになってきた記憶があります(10.3とか10.4はいま思い出しても辛かった)。
HTMLに埋め込むURLスキーム「applescript:」からは、AppleScriptの新規作成、作成中のAppleScript書類のカーソル位置へのペースト、書類末尾へのペーストなどの動作を指定できますが、結局Blogに10年前からつけているURLリンクもそれほど認識されておらず(なぜ??)、新規作成のリンクのみ付加するように変更しました。
また、「applescript:」のURLリンクでは生成するAppleScript書類のファイル名をあらかじめ指定できるようになっているものの、古いバージョンのmacOS(Mac OS X)ではこの名称指定が仇となってURLリンクが認識されないという問題が発生するため、名称も指定していません。
一応、書き出し対象ファイルがAppleScriptかJavaScriptかを判定して、書き出し時のカラーリングを変更するようになっています。OSAScriptフレームワーク経由で書類から直接OSA言語の種別は取得できるものの、スクリプトエディタ自体から情報を取得しても手間はたいして変わらないので現状のようになっています。
AppleScript名:asHTMLexportLib |
use AppleScript version "2.4" use scripting additions use framework "Foundation" property quotChar : string id 34 property headerCol : "0000CC" –"0000CC" –ヘッダー部分(濃い色) property bodyBackCol : "EEFFFF" –"EEFFFF" –Script本文下地(薄い色) property footerCol : "66FFFF" –"66FFFF" –スクリプトリンク部分 property repMark : "_replacepoint_" on run set aPath to choose file of type {"com.apple.applescript.script", "com.apple.applescript.script-bundle"} set aRes to retScriptHTML(aPath) of me end run on retScriptHTML(aPath) –parameter is alias script spd property TIDsList : {} property dataOut : {} property textList : {} property colorList : {} end script set pName to "com.apple.ScriptEditor2" tell application id pName set asDoc to open aPath tell asDoc –front document set aInfo to properties set curLang to name of language of aInfo –現在のOSA言語の名称を取得する end tell –OSA Language名称をもとに色セットを変更する changeColor(curLang) of me set c to name of asDoc –front document set aF to aPath as string –retMacOSpathList(aPath) of me set contText to getContentsOfFile(asDoc) of me –front document set encText to makeEncodedScript(contText) of me set newLinkText to "applescript://com.apple.scripteditor?action=new&script=" & encText –set insLinkText to "applescript://com.apple.scripteditor?action=insert&script=" & encText –set apndLinkText to "applescript://com.apple.scripteditor?action=append&script=" & encText set comText to description of asDoc –front document set (textList of spd) to getAttributeRunOfFile(asDoc) of me —every attribute run of asDoc –front document set (colorList of spd) to getColorOfAttributeRunOfFile(asDoc) of me —color of every attribute run of asDoc –front document end tell set tabChar to string id 9 set (TIDsList of spd) to {{"\\", "\"}, {"’", "’"}, {"&", "&"}, {">", ">"}, {"<", "<"}, {" ", " "}, {string id 13, "<br>"}, {string id 10, "<br>"}, {"\"", """}} set (dataOut of spd) to {} set iCounter to 1 repeat with i in (textList of spd) set j to contents of i set curDelim to AppleScript’s text item delimiters repeat with eachItem in (TIDsList of spd) set AppleScript’s text item delimiters to contents of item 1 of eachItem set j to every text item of j set AppleScript’s text item delimiters to contents of item 2 of eachItem set j to j as string end repeat set AppleScript’s text item delimiters to curDelim set cText to RBG2HTML(item iCounter of (colorList of spd)) of me set the end of (dataOut of spd) to "<font color=" & cText & ">" & j & "</font>" set iCounter to iCounter + 1 end repeat set htmlHeader to "<table width=" & quotChar & "100%" & quotChar & " border=" & quotChar & "0" & quotChar & "cellspacing=" & quotChar & "2" & quotChar & " cellpadding=" & quotChar & "2" & quotChar & "> <tr> <td bgcolor=\"#" & headerCol & "\"><font color=" & quotChar & "#FFFFFF" & quotChar & ">" & curLang & "名:" & c if comText is not equal to "" then set comText to "<br><font size=" & quotChar & "2" & quotChar & ">【Comment】 " & comText & "</font><br>" end if set htmlHeader2 to "</font></td> </tr> <tr> <td bgcolor=\"#" & bodyBackCol & "\"><font size=\"3\">" set htmlFooter1 to "</font></td> </tr> <tr> <td bgcolor=\"#" & footerCol & "\"><p><font size=\"2\"><a href=\"" & newLinkText & "\">★Click Here to Open This Script</a> </font></p> </td> </tr> </table> " set dataText to htmlHeader & comText & htmlHeader2 & ((dataOut of spd) as text) & htmlFooter1 set dataText to dataText as Unicode text tell application id pName close asDoc without saving –close front document without saving end tell return dataText end retScriptHTML on makeEncodedScript(contText) set aList to every paragraph of contText set aClass to class of aList if aClass = list then set aLen to length of aList else set aLen to 1 end if set aaList to {} set delim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to repMark set bList to aList as text set AppleScript’s text item delimiters to delim set aaList to (retURLencodedStrings(bList) of me) as text set search_string to retURLencodedStrings(repMark) of me –"%5Freplacepoint%5F" as text set replacement_string to "%0D" as text set bList to replace_chars(aaList, search_string, replacement_string) of me return bList end makeEncodedScript –RGB値からHTMLの色指定に変換 on RBG2HTML(RGB_values) — NOTE: this sub-routine expects the RBG values to be from 0 to 65536 set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} set the the hex_value to "" repeat with i from 1 to the count of the RGB_values set this_value to (item i of the RGB_values) div 256 if this_value is 256 then set this_value to 255 set x to item ((this_value div 16) + 1) of the hex_list set y to item (((this_value / 16 mod 1) * 16) + 1) of the hex_list set the hex_value to (the hex_value & x & y) as string end repeat return ("#" & the hex_value) as string end RBG2HTML on replace_chars(this_text, search_string, replacement_string) set AppleScript’s text item delimiters to the search_string set the item_list to every text item of this_text set AppleScript’s text item delimiters to the replacement_string set this_text to the item_list as string set AppleScript’s text item delimiters to "" return this_text end replace_chars on retURLencodedStrings(aText) set aStr to current application’s NSString’s stringWithString:aText set encodedStr to aStr’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s alphanumericCharacterSet()) return encodedStr as text end retURLencodedStrings on changeColor(aLang) if aLang = "AppleScript" then set headerCol to "0000CC" –"0000CC" –ヘッダー部分(濃い色) set bodyBackCol to "EEFFFF" –"EEFFFF" –Script本文下地(薄い色) set footerCol to "66FFFF" –"66FFFF" –スクリプトリンク部分 else if aLang = "JavaScript" then set headerCol to "804000" –"0000CC" –ヘッダー部分(濃い色) set bodyBackCol to "E2D3D3" –"EEFFFF" –Script本文下地(薄い色) set footerCol to "E7AC53" –"66FFFF" –スクリプトリンク部分 end if end changeColor on getContentsOfFile(asDoc) tell application id "com.apple.ScriptEditor2" set aCon to (properties of asDoc) end tell return contents of aCon end getContentsOfFile on getAttributeRunOfFile(asDoc) tell application id "com.apple.ScriptEditor2" set aCon to (every attribute run of asDoc) end tell return aCon end getAttributeRunOfFile on getColorOfAttributeRunOfFile(asDoc) tell application id "com.apple.ScriptEditor2" set aCon to color of (every attribute run of asDoc) end tell return aCon end getColorOfAttributeRunOfFile |
2D ListをCSVに v3(サニタイズ処理つき)
AppleScript名:2D ListをCSVに v3(サニタイズ処理つき) |
— Created 2015-10-01 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aNewFile to choose file name set dataList to {{"0010", "ひよこタオルギフト", "200", "手に取ったとき、\"使うとき\"、ちょっと楽しくてかわいいひよこのタオル。", "●サイズ/H200㎜×W200㎜●素材/ひよこ羽毛100%●重量/170g●内容/5枚入り"}, {"0020", "ひよこホイッスル", "250", "今までにないデザインの、ひよこ型のホイッスル。ぴよ〜音を音階で吹き分けます。", "●サイズ/H60㎜×W40㎜×D10㎜●素材/プラスチック ●色/ひよこ色●重量/10g●付属品/首かけロープ付き ●型番/PIYO1"}} saveAsCSV(dataList, aNewFile) of me –2D List to CSV file on saveAsCSV(aList, aPath) –set crlfChar to (ASCII character 13) & (ASCII character 10) set crlfChar to (string id 13) & (string id 10) set LF to (string id 10) set wholeText to "" repeat with i in aList set newLine to {} –Sanitize (Double Quote) repeat with ii in i set jj to ii as text set kk to repChar(jj, string id 34, (string id 34) & (string id 34)) of me –Escape Double Quote set the end of newLine to kk end repeat –Change Delimiter set aLineText to "" set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to "\",\"" set aLineList to newLine as text set AppleScript’s text item delimiters to curDelim set aLineText to repChar(aLineList, return, "") of me –delete return set aLineText to repChar(aLineText, LF, "") of me –delete lf set wholeText to wholeText & "\"" & aLineText & "\"" & crlfChar –line terminator: CR+LF end repeat if (aPath as string) does not end with ".csv" then set bPath to aPath & ".csv" as Unicode text else set bPath to aPath as Unicode text end if write_to_file(wholeText, bPath, false) of me end saveAsCSV on write_to_file(this_data, target_file, append_data) tell current application try set the target_file to the target_file as text set the open_target_file to open for access file target_file with write permission if append_data is false then set eof of the open_target_file to 0 write this_data to the open_target_file starting at eof close access the open_target_file return true on error error_message try close access file target_file end try return error_message end try end tell end write_to_file on repChar(origText as text, targChar as text, repChar as text) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to targChar set tmpList to text items of origText set AppleScript’s text item delimiters to repChar set retText to tmpList as string set AppleScript’s text item delimiters to curDelim return retText end repChar |
CSVのParse 5(ASOC)
AppleScript名:CSVのParse 5(ASOC) |
–Created By Shane Stanley 2015/03/12 –Commented & Arranged By Takaaki Naganoya 2015/03/12 use scripting additions use framework "Foundation" set theString to "cust1,\"prod,1\",season 1, cust1,prod1,season2, cust2,prod1,event1,season1 cust2,prod3,event1,season 1" its makeListsFromCSV:theString commaIs:"," –> {{"cust1", "prod,1", "season 1"}, {"cust1", "prod1", "season2"}, {"cust2", "prod1", "event1", "season1"}, {"cust2", "prod3", "event1", "season 1"}} –CSV Parser ASOC ver (Translated from "ASObjCExtras.framework" Objective-C version) on makeListsFromCSV:theString commaIs:theComma set theRows to {} –最終的に出力するデータ(2D Listになる) set newLineCharSet to current application’s NSCharacterSet’s newlineCharacterSet() –改行キャラクタ set importantCharSet to current application’s NSMutableCharacterSet’s characterSetWithCharactersInString:("\"" & theComma) –カンマ importantCharSet’s formUnionWithCharacterSet:newLineCharSet set theNSScanner to current application’s NSScanner’s scannerWithString:theString theNSScanner’s setCharactersToBeSkipped:(missing value) –データ末尾を検出するまでループ repeat while (theNSScanner’s isAtEnd() as integer = 0) set insideQuotes to false set finishedRow to false set theColumns to {} set currentColumn to "" –すべての行を処理終了するまでループ(行内部の処理) repeat while (not finishedRow) set {theResult, tempString} to theNSScanner’s scanUpToCharactersFromSet:importantCharSet intoString:(reference) –log {"theResult", theResult, "tempString", tempString} if theResult as integer = 1 then set currentColumn to currentColumn & (tempString as text) –log {"currentColumn", currentColumn} –データ末尾検出 if theNSScanner’s isAtEnd() as integer = 1 then if currentColumn is not "" then set end of theColumns to currentColumn set finishedRow to true else –データ末尾ではない場合 set {theResult, tempString} to theNSScanner’s scanCharactersFromSet:newLineCharSet intoString:(reference) if theResult as integer = 1 then if insideQuotes then –ダブルクォート文字内の場合 set currentColumn to currentColumn & (tempString as text) else –ダブルクォート内ではない場合 if currentColumn is not "" then set end of theColumns to currentColumn set finishedRow to true end if else –行末文字が見つからない場合 set theResult to theNSScanner’s scanString:"\"" intoString:(missing value) if theResult as integer = 1 then –ダブルクォート文字が見つかった場合 if insideQuotes then –ダブルクォート文字内の場合 set theResult to theNSScanner’s scanString:"\"" intoString:(missing value) if theResult as integer = 1 then set currentColumn to currentColumn & "\"" else set insideQuotes to (not insideQuotes) end if else –ダブルクォート文字内ではない場合 set insideQuotes to (not insideQuotes) end if else –ダブルクォート文字が見つからなかった場合 set theResult to theNSScanner’s scanString:theComma intoString:(missing value) –カンマの検索 if theResult as integer = 1 then if insideQuotes then set currentColumn to currentColumn & theComma else set end of theColumns to currentColumn set currentColumn to "" theNSScanner’s scanCharactersFromSet:(current application’s NSCharacterSet’s whitespaceCharacterSet()) intoString:(missing value) end if end if end if end if end if end repeat if (count of theColumns) > 0 then set end of theRows to theColumns –行データ(1D List)をtheRowsに追加(2D List) end repeat return theRows end makeListsFromCSV:commaIs: |