set dx to x1 – x0 set dy to y1 – y0 set lineLength to (dx * dx + dy * dy) ^ 0.5
if lineLength = 0 then if x0 ≥ 0 and x0 < widthCount and y0 ≥ 0 and y0 < heightCount then set theLine to item (y0 + 1) of (canvas of spd) set newLine to replaceCharAt(theLine, x0 + 1, drawChar) set item (y0 + 1) of (canvas of spd) to newLine end if
return (canvas of spd) end if
set nx to –dy / lineLength set ny to dx / lineLength
set halfThickness to (thickness – 1) / 2 if halfThickness < 0 then set halfThickness to 0
set x to x0 set y to y0
set dxAbs to absNum(dx) of me set dyAbs to absNum(dy) of me set sx to signNum(dx) of me set sy to signNum(dy) of me set err to dxAbs – dyAbs
set (drawnPositions of spd) to {}
repeat set (drawXCoords of spd) to {} repeat with t from –halfThickness to halfThickness set pxF to x + nx * t set pxInt to pxF as integer if pxInt ≥ 0 and pxInt < widthCount then if (drawXCoords of spd) does not contain pxInt then set end of (drawXCoords of spd) to pxInt end if end if end repeat
set pyInt to y as integer if pyInt ≥ 0 and pyInt < heightCount then set theLine to item (pyInt + 1) of (canvas of spd) set (lineChars of spd) to characters of theLine
repeat with pxInt in (drawXCoords of spd) set posKey to (pxInt as string) & "," & (pyInt as string)
if (drawnPositions of spd) does not contain posKey then set item (pxInt + 1) of (lineChars of spd) to drawChar set end of (drawnPositions of spd) to posKey end if
end repeat
set newLine to (lineChars of spd) as string set item (pyInt + 1) of (canvas of spd) to newLine end if
if x = x1 and y = y1 then exit repeat
set e2 to 2 * err if e2 > –dyAbs then set err to err – dyAbs set x to x + sx end if
if e2 < dxAbs then set err to err + dxAbs set y to y + sy end if end repeat
return (canvas of spd) end drawLine
on replaceCharAt(str, pos, char) if pos < 1 or pos > (length of str) then return str set prefix to text 1 thru (pos – 1) of str set suffix to text (pos + 1) thru -1 of str return prefix & char & suffix end replaceCharAt
on absNum(n) if n < 0 then return –n return n end absNum
on signNum(n) if n > 0 then return 1 if n < 0 then return -1 return 0 end signNum
— 描画処理 (1行ずつ文字を生成) repeat with y from 1 to canvasHeight set currentLine to "" repeat with x from 1 to canvasWidth — 円の方程式を使い、中心からの距離を計算 set distSquared to ((x – centerX) * aspectRatio) ^ 2 + (y – centerY) ^ 2
— 現在の座標が円の内側または円周上にあるか判定 if distSquared ≤ radiusNum ^ 2 then set currentLine to currentLine & "■" else set currentLine to currentLine & " " end if end repeat — 1行分の文字列と改行を出力に追加 set (outputText of spd) to (outputText of spd) & currentLine & " " end repeat
return contents of (outputText of spd) end aaFillCircle
— 描画処理 (1行ずつ文字を生成) repeat with y from 1 to canvasHeight set currentLine to "" repeat with x from 1 to canvasWidth — 円の方程式を使い、中心からの距離を計算 set distSquared to ((x – centerX) * aspectRatio) ^ 2 + (y – centerY) ^ 2
— 現在の座標が円周上にあるか判定 if (distSquared > (radiusNum – lineWidth) ^ 2) and (distSquared < (radiusNum + lineWidth) ^ 2) then set currentLine to currentLine & "■" else set currentLine to currentLine & " " end if end repeat — 1行分の文字列と改行を出力に追加 set (outputText of spd) to (outputText of spd) & currentLine & " " end repeat return contents of (outputText of spd) end aaDrawCircleLine
— 次のトークン範囲へ進む set nextIndex to (currentIndex’s location) + (currentIndex’s |length|()) if nextIndex ≥ textLength then exit repeat set currentIndex to tokenizer’s tokenRangeAtIndex:nextIndex end repeat
return tokenList –> {"私", "の", "名前", "は", "長野", "谷", "です"}
— — AppDelegate.applescript — statusMenuFromXIB — — Created by Takaaki Naganoya2 on 2025/03/27. — —
script AppDelegate property parent : class "NSObject"
— IBOutlets property theWindow : missing value property theStatMenu : missing value –xib上で作っておいたメニュー。Cocoa Binding
on applicationWillFinishLaunching:aNotification set theIcon to current application’s NSImage’s imageNamed:(current application’s NSImageNameComputer) set statusItem to (current application’s NSStatusBar’s systemStatusBar())’s statusItemWithLength:(current application’s NSVariableStatusItemLength) statusItem’s setTitle:("PIYOMARU") statusItem’s setImage:theIcon statusItem’s setHighlightMode:true statusItem’s setMenu:theStatMenu
statusItem’s popUpStatusItemMenu:theStatMenu end applicationWillFinishLaunching:
on applicationShouldTerminate:sender — Insert code here to do any housekeeping before your application quits return current application’s NSTerminateNow end applicationShouldTerminate:
Dock Menuを表示するAppleScriptアプリです。探すと意外と情報がまとまっていないので、掲載しておきます。
Dock Menuについては、スクリプトエディタやスクリプトメニュー、アプレットなどで動作する通常のAppleScriptでは利用できませんが、Xcode上で作成するアプリやCocoa AppleScript Applicationでは利用できます。このあたりは、どのぐらいAppleScriptの実行環境がアプリのイベントをAppleScript側に提供しているかどうかによります。
— — CocoaAppletAppDelegate.applescript — Cocoa-AppleScript Applet — — Copyright 2011 {Your Company}. All rights reserved. —
— This application delegate emulates the OSA script applet by loading "main.scpt" from the — "Scripts" folder in the application resources and invoking the traditional run/open/reopen/quit — handlers in response to Cocoa application delegate methods being called. — — This is provided in source form so that you may customize or replace it if your needs go — beyond the basic applet handlers. — — Some of these methods must guard against re-entrancy, because invoking the main.scpt — handler may end up invoking the event handler inherited from the current application, — which calls the application delegate’s method again.
script CocoaAppletAppDelegate property parent : class "NSObject" property mainScript : missing value — the applet’s main.scpt property didOpenFiles : false — true = the application opened documents during startup property isOpeningFiles : false — re-entrancy guard: true = in the process of opening files property isReopening : false — re-entrancy guard: true = in the process of re-opening property isQuitting : false — re-entrancy guard: true = in the process of quitting
on applicationWillFinishLaunching:aNotification — Insert code here to initialize your application before any files are opened
— Emulate an OSA Applet: Load the main script from the Scripts resource folder. try set my mainScript to load script (path to resource "main.scpt" in directory "Scripts") on error errMsg number errNum — Perhaps this should silently fail if it can’t load the script; that way, a Cocoa applet — can just have Cocoa classes and no main.scpt. display alert "Could not load main.scpt" message errMsg & " (" & errNum & ")" as critical end try end applicationWillFinishLaunching:
on applicationDidFinishLaunching:aNotification — Insert code here to do startup actions after your application has initialized
if mainScript is missing value then return
— Emulate an OSA Applet: Invoke the "run" handler.
— If we have already opened files during startup, don’t invoke the run handler. if didOpenFiles then return
try tell mainScript to run on error errMsg number errNum if errNum is not -128 then display alert "An error occurred while running" message errMsg & " (" & errNum & ")" as critical end if end try
— TODO: Read the applet’s "stay open" flag and quit if it’s false or unspecified. — For now, all Cocoa Applets stay open and require the run handler to explicitly quit, — which is arguably more correct for a Cocoa application, anyway. (* if not shouldStayOpen then quit end if *) end applicationDidFinishLaunching:
on applicationShouldHandleReopen:sender hasVisibleWindows:flag — Insert code here to perform actions in response to a "reopen" event
if mainScript is missing value then return true
— Guard against re-entrancy. if not isReopening then set isReopening to true
— Emulate an OSA Applet: Invoke the "reopen" handler. If there isn’t one, let the application object — handle reopen (this is different from an OSA applet, which would do nothing if there is no handler; — this way, the application will perform the usual "create untitled document" behavior by default). try tell mainScript to reopen set isReopening to false
return false on error errMsg number errNum if errNum is not -128 then display alert "An error occurred while reopening" message errMsg & " (" & errNum & ")" as critical end if end try
set isReopening to false end if
return true end applicationShouldHandleReopen:hasVisibleWindows:
on |application|:sender openFiles:filenames — Insert code here to perform actions in response to an "open documents" event
— Remember that we opened files, to avoid invoking the "run" handler later. set didOpenFiles to true
— Guard against re-entrancy. if not isOpeningFiles and mainScript is not missing value then set isOpeningFiles to true
try — Convert all the filenames from NSStrings to script strings set theFilenameStrings to {} repeat with eachFile in filenames set theFilenameStrings to theFilenameStrings & (eachFile as text) end repeat
tell mainScript to open theFilenameStrings set isOpeningFiles to false
tell sender to replyToOpenOrPrint:(current application’s NSApplicationDelegateReplySuccess) on error errMsg number errNum if errNum = -128 then tell sender to replyToOpenOrPrint:(current application’s NSApplicationDelegateReplyCancel) else display alert "An error occurred while opening file(s)" message errMsg & " (" & errNum & ")" as critical tell sender to replyToOpenOrPrint:(current application’s NSApplicationDelegateReplyFailure) end if end try
set isOpeningFiles to false else tell sender to replyToOpenOrPrint:(current application’s NSApplicationDelegateReplyFailure) end if end |application|:openFiles:
on applicationShouldTerminate:sender — Insert code here to do any housekeeping before your application quits
— Guard against re-entrancy. if not isQuitting and mainScript is not missing value then set isQuitting to true
— Emulate an OSA Applet: Invoke the "quit" handler; if the handler returns, it has fully — handled the quit message and we should not quit, otherwise, it calls "continue quit", — which returns error -10000. try tell mainScript to quit set isQuitting to false
return current application’s NSTerminateCancel on error errMsg number errNum — -128 means there is no quit handler — -10000 means the handler did "continue quit" if errNum is not -128 and errNum is not -10000 then display alert "An error occurred while quitting" message errMsg & " (" & errNum & ")" as critical end if end try
set isQuitting to false end if
return current application’s NSTerminateNow end applicationShouldTerminate:
–Dock Menu Enabled on applicationDockMenu:(aNotification) set aMenu to current application’s NSMenu’s alloc()’s init() set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:"Dock Menuだよ" action:"actionHandler:" keyEquivalent:"") (aMenuItem’s setTarget:me) (aMenu’s addItem:aMenuItem) return aMenu end applicationDockMenu:
on actionHandler:sender set aTag to (tag of sender) as string set aTitle to (title of sender) as string
display dialog (aTitle as string) end actionHandler: end script
–画面上で選択しておいたオブジェクトのうち、text itemのみを抽出(念のため) repeat with i in aSelList set j to contents of i set aClass to class of j if aClass is text item then set the end of bSelList to j end if end repeat
set cSelList to sortIWorkObjectsByPositionAndRetObjRef(bSelList, {"positionX", "positionY"}, {true, true}) of iWorkObjSort
–章トビラ上のテキストアイテム(複数可)をループしつつ、中のテキストを行ごとに分解してリスト化 –(連結前にあらかじめX座標をもとにソートしておいたほうがいい??) set textList to {} repeat with i in cSelList set tmpCon to object text of i set tmpList to paragraphs of tmpCon set textList to textList & tmpList end repeat –return textList
–章トビラのページの情報を取得 tell current slide set curSlideNum to slide number set curSlideLayout to name of base layout end tell
–章トビラの次のページの情報を取得(ここが必ず記事トビラであるという前提のもとに処理) tell slide (curSlideNum + 1) set nextSlideLayout to name of base layout end tell
set targSlideList to {} repeat with i from (curSlideNum + 1) to sCount tell slide i set tSTheme to name of base layout if tSTheme = curSlideLayout then –章トビラを検出したら処理終了 exit repeat else if tSTheme = nextSlideLayout then –扉+1ページのスライド(記事カバー)を検出したら記録 set the end of targSlideList to i end if end tell end repeat –return targSlideList
set iCount to 1 repeat with i in targSlideList try set tmpT to contents of item iCount of textList tell slide i set object text of default title item of it to tmpT end tell set iCount to iCount + 1 on error return end try end repeat end tell end tell
–ライブラリとしてバンドル形式のAppleScript書類に組み込んでいたものをBlog掲載用に展開した script iWorkObjSort property parent : AppleScript use AppleScript use framework "Foundation" use framework "AppKit" use scripting additions
script spd property aaSel : {} end script
–Keynote上のiWork ObjをXY座標でソートして結果を返す(App Obj情報はitem noだけ) on sortIWorkObjectsByPosition(aaSel, sortLabelLIst, sortDirectionList) tell application "Keynote" set aVer to version if aVer < "12.0" then return
tell front document set posList to {} set aCount to 1
repeat with ii in aaSel set jj to contents of ii set bClass to class of jj
tell jj set {posX, posY} to position
try set tmpStr to object text as string on error set tmpStr to "" end try end tell
set the end of posList to {positionX:posX, positionY:posY, objID:aCount, myStr:tmpStr}
set aCount to aCount + 1 end repeat
–座標データをもとにソート set sortedList to sortRecListByLabel(posList, sortLabelLIst, sortDirectionList) of me
end tell end tell
return sortedList end sortIWorkObjectsByPosition
–Keynote上のiWork ObjをXY座標でソートして結果を返す(App Objだけ返す) on sortIWorkObjectsByPositionIncludingObjRef(aaSel, sortLabelLIst, sortDirectionList) tell application "Keynote" set aVer to version if aVer < "12.0" then return
tell front document set posList to {} set aCount to 1
repeat with ii in aaSel set jj to contents of ii set bClass to class of jj
tell jj set {posX, posY} to position
try set tmpStr to object text as string on error set tmpStr to "" end try end tell
set the end of posList to {positionX:posX, positionY:posY, objID:aCount, myStr:tmpStr}
set aCount to aCount + 1 end repeat
–座標データをもとにソート set sortedList to sortRecListByLabel(posList, sortLabelLIst, sortDirectionList) of me
–データを返す配列にiWork Object への参照を含める set sCount to 1 repeat with i from 1 to (length of aaSel) set tmpID to objID of contents of item i of sortedList set tmpObj to contents of item tmpID of aaSel set (item tmpID of sortedList) to (item tmpID of sortedList) & {objRef:tmpObj} end repeat end tell end tell
return sortedList end sortIWorkObjectsByPositionIncludingObjRef
–Keynote上のiWork ObjをXY座標でソートして結果を返す(App Obj入りのリストを返す) on sortIWorkObjectsByPositionAndRetObjRef(aaSel, sortLabelLIst, sortDirectionList) tell application "Keynote" set aVer to version if aVer < "12.0" then return
tell front document set posList to {} set aCount to 1
repeat with ii in aaSel set jj to contents of ii set bClass to class of jj
tell jj set {posX, posY} to position
try set tmpStr to object text as string on error set tmpStr to "" end try end tell
set the end of posList to {positionX:posX, positionY:posY, objID:aCount, myStr:tmpStr}
set aCount to aCount + 1 end repeat
–座標データをもとにソート set sortedList to sortRecListByLabel(posList, sortLabelLIst, sortDirectionList) of me
–データを返す配列にiWork Object への参照を含める set sCount to 1 set retList to {} repeat with i from 1 to (length of aaSel) set tmpID to objID of contents of item i of sortedList set tmpObj to contents of item tmpID of aaSel set the end of retList to tmpObj end repeat end tell end tell
return retList end sortIWorkObjectsByPositionAndRetObjRef
–リストに入れたレコードを、指定の属性ラベルの値でソート on sortRecListByLabel(aRecList as list, aLabelStr as list, ascendF as list) set aArray to current application’s NSArray’s arrayWithArray:aRecList
set aCount to length of aLabelStr set sortDescArray to current application’s NSMutableArray’s new() repeat with i from 1 to aCount set aLabel to (item i of aLabelStr) set aKey to (item i of ascendF) set sortDesc to (current application’s NSSortDescriptor’s alloc()’s initWithKey:aLabel ascending:aKey) (sortDescArray’s addObject:sortDesc) end repeat
return (aArray’s sortedArrayUsingDescriptors:sortDescArray) as list end sortRecListByLabel
set bValList to {} repeat with i in valList set j to contents of i set aClass to class of j
if aClass = date then set j to incremenetYearOf(j) of me end if
set the end of bValList to j end repeat
repeat with i from 1 to aLen set aVal to contents of item i of bValList set aCell to contents of item i of cellList
ignoring application responses set value of aCell to aVal end ignoring end repeat
end tell end tell end tell
on incremenetYearOf(aDate) set {bYear, bMonth, bDate} to {year of aDate, month of aDate, day of aDate} set bYear to bYear + 1 set {year of aDate, month of aDate, day of aDate} to {bYear, bMonth, bDate} return aDate end incremenetYearOf
on decremenetYearOf(aDate) set {bYear, bMonth, bDate} to {year of aDate, month of aDate, day of aDate} set bYear to bYear – 1 set {year of aDate, month of aDate, day of aDate} to {bYear, bMonth, bDate} return aDate end decremenetYearOf
— Retina用のスケールファクターを取得 set retinaF to (current application’s NSScreen’s mainScreen()’s backingScaleFactor()) as real
— 画像を読み込む set imageURL to current application’s NSURL’s fileURLWithPath:imagePath set imageData to current application’s NSImage’s alloc()’s initWithContentsOfURL:imageURL
— 論理サイズ(points単位)を取得("size"は予約語なのでエスケープ) set imageSize to imageData’s |size|() set {w_pt, h_pt} to {imageSize’s |width|, imageSize’s |height|}
— リサイズ後の幅(文字数)を指定し、論理サイズに基づいてスケール計算 set newWidth to 80 set scaleFactor to newWidth / w_pt set newHeight to round (h_pt * scaleFactor * 0.55) — 文字の縦横比調整
— ピクセル単位のサイズに変換(Retina対応) set pixelWidth to newWidth * retinaF set pixelHeight to newHeight * retinaF set pixelSize to current application’s NSMakeSize(pixelWidth, pixelHeight)
— 新しいピクセルサイズでNSImageを作成し、元画像を描画 set resizedImage to current application’s NSImage’s alloc()’s initWithSize:pixelSize resizedImage’s lockFocus() current application’s NSGraphicsContext’s currentContext()’s setImageInterpolation:(current application’s NSImageInterpolationHigh) imageData’s drawInRect:{{0, 0}, pixelSize} fromRect:{{0, 0}, imageSize} operation:(current application’s NSCompositingOperationCopy) fraction:1.0 resizedImage’s unlockFocus()
— リサイズ後の画像からNSBitmapImageRepを取得 set resizedRep to current application’s NSBitmapImageRep’s imageRepWithData:(resizedImage’s TIFFRepresentation())
— 各ピクセルをASCII文字に変換(Retina対応のため、retinaFごとにサンプリング) set asciiArt to "" set stepX to retinaF as integer set stepY to retinaF as integer
repeat with y from 0 to (pixelHeight – 1) by stepY repeat with x from 0 to (pixelWidth – 1) by stepX set pixelColor to (resizedRep’s colorAtX:(x * retinaF) y:(y * retinaF))
set r to pixelColor’s redComponent() set g to pixelColor’s greenComponent() set b to pixelColor’s blueComponent() set brightness to (r + g + b) / 3
set charIndex to round (brightness * ((count of asciiChars) – 1)) set asciiArt to asciiArt & (character (charIndex + 1) of asciiChars) end repeat set asciiArt to asciiArt & linefeed end repeat
tell workspace document 1 set xWSprojPath to path close end tell end tell
–delay 1
tell application "Xcode" open ((POSIX file xWSprojPath) as alias) end tell
—オープン中のファイル名(余計な文字列つき)を取得 tell window 1 set aStr to name end tell
–Xcode Project書類のパスを取得 tell document 1 set aPrjPath to path of it end tell end tell
set a1Str to parseFileNameFromXCodeWindowName(aStr, targString) of me if a1Str does not end with ".applescript" then return
set pathString to current application’s NSString’s stringWithString:(aPrjPath) set parentFol to (pathString’s stringByDeletingLastPathComponent()) as string
set aList to retFullPathUnderAFolderWithRecursiveFilterByFileName(parentFol, a1Str) of me if length of aList > 1 then set aRes to first item of (choose from list aList) else set aRes to first item of aList end if
return aRes –> "/Users/me/Documents/testXC162/testXC162/AppDelegate.applescript"
on parseFileNameFromXCodeWindowName(aStr, aDelim) set aCount to retFrequency(aStr, aDelim) of me set aRes to parseByDelim(aStr, aDelim) of me return item 2 of aRes end parseFileNameFromXCodeWindowName
–指定文字列内の指定キーワードの出現回数を取得する on retFrequency(origText, aKeyText) set aRes to parseByDelim(origText, aKeyText) of me return ((count every item of aRes) – 1) end retFrequency
on parseByDelim(aData, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set dList to text items of aData set AppleScript’s text item delimiters to curDelim return dList end parseByDelim
on retFullPathUnderAFolderWithRecursiveFilterByFileName(aFol, aFileName) set anArray to current application’s NSMutableArray’s array() set aPath to current application’s NSString’s stringWithString:aFol set dirEnum to current application’s NSFileManager’s defaultManager()’s enumeratorAtPath:aPath
repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat
set thePred to current application’s NSPredicate’s predicateWithFormat_("lastPathComponent == %@", aFileName) set bArray to anArray’s filteredArrayUsingPredicate:thePred
return bArray as list end retFullPathUnderAFolderWithRecursiveFilterByFileName
–Check Handler existence set existsHandler to (me’s respondsToSelector:nameOfTargetHandler) as boolean if existsHandler = true then –Call handler set a1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate()
set aRes to (my performSelector:nameOfTargetHandler withObject:(aList of spd))
set b1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set c1Dat to b1Dat – a1Dat else error "Handler does not exists" end if
set the end of resList to {nameOfTargetHandler, c1Dat} end repeat
return resList –> {{"returnDuplicatesOnly1:", 0.065470099449}, {"returnDuplicatesOnly2:", 2.39611697197}, {"returnDuplicatesOnly3:", 0.038006067276}}
–Cocoa Scripting最速? on returnDuplicatesOnly1:aList set arrayOne to current application’s NSArray’s arrayWithArray:aList set setOne to current application’s NSCountedSet’s alloc()’s initWithArray:(arrayOne) set arrayTwo to (arrayOne’s valueForKeyPath:"@distinctUnionOfObjects.self") set setTwo to current application’s NSCountedSet’s alloc()’s initWithArray:(arrayTwo) setOne’s minusSet:setTwo return setOne’s allObjects() as list –>{3, 6, 4} end returnDuplicatesOnly1:
–1より遅い on returnDuplicatesOnly2:(aList as list) set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set bList to (aSet’s allObjects()) as list
set dupList to {} repeat with i in bList set aRes to (aSet’s countForObject:i) if aRes > 1 then set the end of dupList to (contents of i) end if end repeat
return dupList end returnDuplicatesOnly2:
–リスト中から重複項目をリストアップする(Vanilla AS高速化版) on returnDuplicatesOnly3:(aList) script spd property aList : {} property dList : {} end script
copy aList to (aList of spd) set aCount to length of (aList of spd)
set (dList of spd) to {}
repeat aCount times set anItem to contents of (first item of (aList of spd)) set (aList of spd) to rest of (aList of spd)
if {anItem} is in (aList of spd) then if {anItem} is not in (dList of spd) then –ここを追加した (v3) set the end of (dList of spd) to anItem end if end if