Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

Skimがv1.7.8でopen locationコマンドを削除

Posted on 1月 14 by Takaaki Naganoya

オープンソースのPDFビューワー「Skim」がバージョン1.7.8において「open location」コマンドを削除しました。

open locationコマンドは標準装備されているものであり、Skim側で実装しなくても問題ないという結論に至ったのかもしれません。

なお、オープンできる(Skimが応答する)URLはhttps://のみであり、http://については応答しないのもv1.7.6から変わっていません。

ただ、これまでにSkimは何度も「トラブルを起こしたコマンドをいったん削除してあとあと再実装」という動きをしているので、再実装される可能性は否定できません。しらんけど。

Posted in URL | Tagged 13.0savvy 14.0savvy 15.0savvy Skim | Leave a comment

選択範囲の値を取得して、冒頭の値の新しい数値を指定すると以下自動加算

Posted on 1月 14 by Takaaki Naganoya

Numbers上で選択範囲のデータに対して一括で数値を加算するAppleScriptです。

Numbers上で台割(PDFに対して付加するTOC用データ)を管理しているところに、実際の電子書籍の記事が増えて、各記事のノンブル(ページ番号)を変更する必要があるわけですが……これに、当初は「+18で」みたいなScriptを運用していたのですが、暗算で差分を計算していたものの、この仕様だと使いにくかったのです。

そこで、新たなページ数を入力すると、AppleSript側で差分を計算して後の選択範囲に対して加算するようにしてみました。


▲初期状態


▲PDFを参照して新版の「おくづけ」は552ページになっていることを確認 ここで、本Scriptを実行


▲差分(増分)を暗算で計算して入力するのではなく、最初のページの変更後のページ数が何か、を入力。Script側で差分を自動計算


▲実行後の状態

巨大なScriptも役立ちますが、こういう「ちょっとした」サイズのScriptもまた役に立ちます。

AppleScript名:選択範囲の値を取得して、冒頭の値の新しい数値を指定すると以下自動加算.scpt
set sNum to text returned of (display dialog "Input New First Num" default answer "")
tell application "Numbers"
  tell front document
    tell active sheet
      tell table 1
        set mySelectedRanges to value of every cell of selection range
        
set cellList to cell of selection range
        
        
set addNum to sNum – (first item of mySelectedRanges)
        
        
        
set iCount to 0
        
set newList to {}
        
repeat with i in cellList
          set tmpVal to value of i
          
set the end of newList to tmpVal + addNum
        end repeat
        
        
repeat with i from 1 to (length of cellList)
          tell item i of cellList
            set value to item i of newList
          end tell
        end repeat
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

Posted in Number | Tagged 13.0savvy 14.0savvy 15.0savvy Numbers | Leave a comment

スタイルつきテキストでスタイルつきテキストを検索 v1.1

Posted on 1月 13 by Takaaki Naganoya

スタイルつきテキストの中をスタイルつきテキストで検索するAppleScriptです。フォント、サイズ、色の属性を考慮して文字とこれらの属性値が合っている場合に合致しているものとみなします。

最初のバージョンはChatGPTに書かせたもので、実際に動かしてみたら激遅だったので、2パスで検索することで高速化してみました。オリジナルより100倍以上速くなっているはずです。

Step1: 検索対象文字列、検索文字列の両方をテキスト化して、テキストベースで出現情報を計算
Step2: 出現情報をもとにスタイルつきテキスト(NSAttributedString)の書式情報の照合を行い、合致するものを出力

という処理に変更しました。ChatGPTが出力してきたAppleScriptは、1文字ずつチェック範囲を変更しながら書式情報とテキスト情報の照合を行うという「脳筋処理」だったので、少なく見積もっても100倍。データ量が増えれば増えるほど高速化の度合いが上昇します。

AppleScript名:find Styled Text in Styled Text_v1.1.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/01/12
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—

use AppleScript
use framework "Foundation"
use scripting additions

property NSString : a reference to current application’s NSString
property NSLiteralSearch : a reference to current application’s NSLiteralSearch
property NSMutableArray : a reference to current application’s NSMutableArray

— サンプルデータ
set targetText to "これはサンプルテキストです。サンプルは重要です。サンプルだよー。サンプルサンプル"
set searchText to "サンプル"

— 属性付き文字列の作成
set targetAttributedString to current application’s NSMutableAttributedString’s alloc()’s initWithString:targetText
set searchAttributedString to current application’s NSMutableAttributedString’s alloc()’s initWithString:searchText

— 属性を設定 (例: フォントと色)
set targetFont to current application’s NSFont’s fontWithName:"HiraginoSans-W2" |size|:13
set targetColor to current application’s NSColor’s redColor()
set searchFont to current application’s NSFont’s fontWithName:"HiraginoSans-W2" |size|:13
set searchColor to current application’s NSColor’s redColor()

— 属性を追加
targetAttributedString’s addAttribute:(current application’s NSFontAttributeName) value:targetFont range:{0, targetAttributedString’s |length|()}
targetAttributedString’s addAttribute:(current application’s NSForegroundColorAttributeName) value:targetColor range:{0, targetAttributedString’s |length|()}
searchAttributedString’s addAttribute:(current application’s NSFontAttributeName) value:searchFont range:{0, searchAttributedString’s |length|()}
searchAttributedString’s addAttribute:(current application’s NSForegroundColorAttributeName) value:searchColor range:{0, searchAttributedString’s |length|()}

— 属性付き検索を実行
set matches to searchAttributedStringWithAttributes(targetAttributedString, searchAttributedString) of me
–> {{location:3, |length|:4}, {location:14, |length|:4}, {location:24, |length|:4}, {location:32, |length|:4}, {location:36, |length|:4}}

— NSAttributedStringの属性付き検索を行うハンドラー(複数一致対応)
on searchAttributedStringWithAttributes(targetAttributedString, searchAttributedString)
  set targText to targetAttributedString’s |string|() as string
  
  
set searchAttributes to searchAttributedString’s attributesAtIndex:0 effectiveRange:(missing value)
  
set searchString to searchAttributedString’s |string|() as string
  
  
–テキストベースで検索
  
set strRangeList to searchWordRanges(targText, searchString) of me
  
–あとは、検索箇所の文字書式をループで照合する
  
  
set matList to {} — 結果を格納するリスト
  
  
— ループで対象の文字列が含まれる位置の書式情報を検索
  
repeat with i in strRangeList
    set j to contents of i
    
set tmpLoc to location of j
    
set tmpLen to |length| of j
    
    
— 対象範囲の属性を取得
    
set targetAttributes to (targetAttributedString’s attributesAtIndex:(tmpLoc) effectiveRange:(current application’s NSMakeRange(tmpLoc, tmpLen)))
    
    
if (targetAttributes = searchAttributes) then
      set the end of matList to {location:(tmpLoc as integer), |length|:(tmpLen as integer)} — 属性が一致した場合
    end if
  end repeat
  
  
return matList — 一致したすべての範囲を返す
end searchAttributedStringWithAttributes

–プレーンテキストベースで検索文字列の出現情報を返す(複数対応)
on searchWordRanges(aTargText as string, aSearchStr as string)
  set aStr to NSString’s stringWithString:aTargText
  
set bStr to NSString’s stringWithString:aSearchStr
  
  
set hitArray to NSMutableArray’s alloc()’s init()
  
set cNum to (aStr’s |length|()) as integer
  
  
set aRange to current application’s NSMakeRange(0, cNum)
  
  
repeat
    set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange
    
set aLen to (detectedRange’s |length|) as number
    
    
if aLen = 0 then exit repeat
    
    
hitArray’s addObject:detectedRange
    
    
set aNum to (detectedRange’s location) as number
    
set bNum to (detectedRange’s |length|) as number
    
    
set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum))
  end repeat
  
  
return hitArray
end searchWordRanges

★Click Here to Open This Script 

Posted in RTF search | Tagged 13.0savvy 14.0savvy 15.0savvy NSColor NSFont NSLiteralSearch NSMutableArray NSMutableAttributedString NSString | Leave a comment

スタイルつきテキストでスタイルつきテキストを検索

Posted on 1月 13 by Takaaki Naganoya

スタイルつきテキストの中をスタイルつきテキストで検索するAppleScriptです。フォント、サイズ、色の属性を考慮して文字とこれらの属性値が合っている場合に合致しているものとみなします。

たかだか3Kバイトごときの文字量のスタイルつきテキストから検索を行うのに、M2 Airで2・3秒ぐらいかかります。

属性値をDictionary in Arrayとして解釈して検索を行うよりも、大幅に処理に時間がかかるようです。

1文字ずつ開始位置をズラして文字&書式の再照合を行っているので、アホみたいに処理時間がかかります。Cocoaの機能を使って処理しているのに、Pagesに問い合わせるよりも時間がかかっている雰囲気です。

本ScriptはChatGPTに書かせたもので、おそらく処理に時間がかかって「無駄」になるものと見込んでいました。

スタイルつきテキストに対してスタイルつきテキストによる検索を行うのは、予想どおりものすごく負荷が大きくなるようで……本Scriptは残念ながら作り捨てになりそうです。

もう少し頭を使って、文字だけで出現位置チェックを行い、出現位置情報をもとに書式の照合を行うようにすれば、10倍ぐらい高速に処理できそうです。

AppleScript名:find Styled Text in Styled Text.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/01/12
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—

use AppleScript
use framework "Foundation"
use scripting additions

— 使用例
set targetText to "これはサンプルテキストです。サンプルは重要です。サンプルだよー。"
set searchText to "サンプル"

— 属性付き文字列の作成
set targetAttributedString to current application’s NSMutableAttributedString’s alloc()’s initWithString:targetText
set searchAttributedString to current application’s NSMutableAttributedString’s alloc()’s initWithString:searchText

— 属性を設定 (例: フォントと色)
set targetFont to current application’s NSFont’s fontWithName:"HiraginoSans-W2" |size|:13
set targetColor to current application’s NSColor’s redColor()
set searchFont to current application’s NSFont’s fontWithName:"HiraginoSans-W2" |size|:13
set searchColor to current application’s NSColor’s redColor()

— 属性を追加
targetAttributedString’s addAttribute:(current application’s NSFontAttributeName) value:targetFont range:{0, targetAttributedString’s |length|()}
targetAttributedString’s addAttribute:(current application’s NSForegroundColorAttributeName) value:targetColor range:{0, targetAttributedString’s |length|()}
searchAttributedString’s addAttribute:(current application’s NSFontAttributeName) value:searchFont range:{0, searchAttributedString’s |length|()}
searchAttributedString’s addAttribute:(current application’s NSForegroundColorAttributeName) value:searchColor range:{0, searchAttributedString’s |length|()}

— 属性付き検索を実行
set matches to searchAttributedStringWithAttributes(targetAttributedString, searchAttributedString) of me
–> {{location:3, |length|:4}, {location:14, |length|:4}, {location:24, |length|:4}}

— NSAttributedStringの属性付き検索を行うハンドラー(複数一致対応、変数名変更)
on searchAttributedStringWithAttributes(targetAttributedString, searchAttributedString)
  — 検索対象の全長を取得
  
set targetLength to targetAttributedString’s |length|()
  
set searchLength to searchAttributedString’s |length|()
  
  
— 検索する属性辞書を取得
  
set searchAttributes to searchAttributedString’s attributesAtIndex:0 effectiveRange:(missing value)
  
set searchString to searchAttributedString’s |string|() as string
  
  
— 結果を格納するリスト
  
set matches to {}
  
  
— ループで対象の文字列を検索
  
set currentIndex to 1
  
  
repeat while (currentIndex + searchLength ≤ targetLength)
    — 対象範囲の属性辞書を取得
    
set targetAttributes to targetAttributedString’s attributesAtIndex:currentIndex effectiveRange:(missing value)
    
    
— 対象範囲の文字列を取得
    
set targetRange to (current application’s NSMakeRange(currentIndex, searchLength))
    
set targetSubstring to (targetAttributedString’s attributedSubstringFromRange:(targetRange))’s |string|()
    
    
— 属性と文字列の一致を確認
    
if (targetSubstring as string = searchString) and (targetAttributes = searchAttributes) then
      set end of matches to {location:currentIndex, |length|:searchLength}
    end if
    
    
— 次の位置に進む
    
set currentIndex to currentIndex + 1
  end repeat
  
  
return matches — 一致したすべての範囲を返す
end searchAttributedStringWithAttributes

★Click Here to Open This Script 

Posted in RTF | Tagged 13.0savvy 14.0savvy 15.0savvy NSMutableAttributedString | Leave a comment

AS書類を書式で分解して再構成

Posted on 1月 12 by Takaaki Naganoya

AppleScriptの書類を読み込んでNSAttributedStringに変換し、書式情報にもとづいてNSDictionary in NSArrayに変換。この状態でデータ抽出などを行なっていたのですが、このデータをもとにNSAttributedStringに再構成するAppleScriptです。

本Scriptの通しの処理内容としては、読み込んだAppleScriptを書式情報をもとに分解して、再構成するという……大豆から豆腐を作って、豆腐を崩して豆を得る、みたいな内容です。

NSAttributedStringを再構成する部分の処理を書いていなかったので、必要に迫られて書いてみました。

AppleScript構文色分け設定情報をもとに処理するため、色分け設定で複数の構文要素で同じ色を指定している場合にはエラーを返します。単にNSAttributedStringを解釈して再構成する、といった処理であればAppleScript構文色分け設定へのアクセス自体は必要ないところですが、すでに不可分なレベルで組み込まれているため、現状ではそのままです。

いっそ、こうした処理をする前にplistをバックアップし、必要な情報を書き込んだplistを設定ファイルとして使用するといった処理を行った方がいいのかもしれません。これまでは、「そんな処理はとても行えない」と判断していましたが、よくよく考えればとくに苦労せずに実現できそうです。

AppleScript名:AS書類を書式で分解して再構成.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/01/12
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.8"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSFont : a reference to current application’s NSFont
property NSColor : a reference to current application’s NSColor
property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property OSAScript : a reference to current application’s OSAScript
property NSDictionary : a reference to current application’s NSDictionary
property NSUnarchiver : a reference to current application’s NSUnarchiver
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSFontAttributeName : a reference to current application’s NSFontAttributeName
property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString
property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName

property asCol : {}

set asCol to getAppleScriptSourceColors() of me –AppleScript構文色分け設定をplistから読み込む

set aFile to POSIX path of (choose file of type {"com.apple.applescript.script", "com.apple.applescript.script-bundle"})
set aURL to |NSURL|’s fileURLWithPath:(aFile)
set theScript to current application’s OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
set styledText to theScript’s richTextSource()

–Styled TextをDictionarry in Listに
set sRes to getAttributeRunsFromAttrStringRBO(styledText) of styleTextToDict

–Dictionarry in ListをStyled Textに再構成
set bRes to retAttributedStringFromAttrDict(sRes) of attrDictToAttrStr

script styleTextToDict
  use AppleScript
  
use framework "Foundation"
  
use framework "AppKit"
  
use scripting additions
  
property parent : AppleScript
  
  
–Styled Textを
  
on getAttributeRunsFromAttrStringRBO(theStyledText)
    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
    
set aCount 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
      
set strLen to (length of aText)
      
      
–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()) * 255
        
set aGreen to (aColor’s greenComponent()) * 255
        
set aBlue to (aColor’s blueComponent()) * 255
        
        
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
      
      
–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
      
      
–Range
      
set the end of (styleList of aSpd) to {stringVal:aText, atrIndex:aCount, colorStr:colStrForFind, colorVal:colList, fontName:aDFontName as string, fontSize:aDFontSize}
      
set startIndex to current application’s NSMaxRange(theRange)
      
      
set aCount to aCount + 1
    end repeat
    
    
return (styleList of aSpd)
    
  end getAttributeRunsFromAttrStringRBO
  
  
–NSColorからRGBの値を取り出す
  
on retColListFromNSColor(aCol, aMAX as integer)
    using terms from scripting additions
      set aRed to round ((aCol’s redComponent()) * aMAX) rounding as taught in school
      
set aGreen to round ((aCol’s greenComponent()) * aMAX) rounding as taught in school
      
set aBlue to round ((aCol’s blueComponent()) * aMAX) rounding as taught in school
    end using terms from
    
if aRed > aMAX then set aRed to aMAX
    
if aGreen > aMAX then set aGreen to aMAX
    
if aBlue > aMAX then set aBlue to aMAX
    
    
return {aRed, aGreen, aBlue}
  end retColListFromNSColor
  
  
–aMaxValを最大値とする数値でNSColorを作成して返す
  
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
  
end script

script attrDictToAttrStr
  use AppleScript
  
use framework "Foundation"
  
use framework "AppKit"
  
use scripting additions
  
property parent : AppleScript
  
  
–書式つきテキストを組み立てる(メイン側)
  
on retAttributedStringFromAttrDict(attrRes)
    script aSpd
      property styleList : {}
    end script
    
    
set (styleList of aSpd) to {} —for output
    
    
set allAttrStr to NSMutableAttributedString’s alloc()’s init()
    
    
repeat with i in attrRes
      set j to contents of i
      
set tmpAttrStr to makeRTFfromParameters(stringVal of j, fontName of j, fontSize of j, colorVal of j) of me
      
      (
allAttrStr’s appendAttributedString:tmpAttrStr)
    end repeat
    
    
return allAttrStr
  end retAttributedStringFromAttrDict
  
  
–書式つきテキストを組み立てる(パーツ組み立て用サブ側)
  
on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aColorList as list)
    –Font & Size
    
set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize
    
set aKey1 to (NSFontAttributeName)
    
    
–Color
    
copy aColorList to {rCol, gCol, bCOl}
    
set aVal2 to makeNSColorFromRGBAval(rCol, gCol, bCOl, 255, 255) of asCol
    
set aKey2 to (NSForegroundColorAttributeName)
    
    
set keyList to {aKey1, aKey2}
    
set valList to {aVal1, aVal2}
    
set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList
    
    
–Text
    
set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary
    
return attrStr
  end makeRTFfromParameters
  
  
  
–aMaxValを最大値とする数値でNSColorを作成して返す
  
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
  
end script

–AppleScriptの構文色分けのカラー値をRGBで取得する
on getAppleScriptSourceColors()
  — get the plist info as a dictionary
  
set thePath to NSString’s stringWithString:"~/Library/Preferences/com.apple.applescript.plist"
  
set thePath to thePath’s stringByExpandingTildeInPath()
  
set theInfo to NSDictionary’s dictionaryWithContentsOfFile:thePath
  
  
— extract relevant part and loop through
  
set theArray to (theInfo’s valueForKey:"AppleScriptSourceAttributes") as list
  
  
set colList to {}
  
  
repeat with i from 1 to count of theArray
    set anEntry to item i of theArray
    
    
set colorData to NSColor of anEntry
    
set theColor to (NSUnarchiver’s unarchiveObjectWithData:colorData)
    
    
set {rVal, gVal, bVal} to retColListFromNSColor(theColor, 255) of me
    
    
set fontData to NSFont of anEntry
    
set theFont to (NSUnarchiver’s unarchiveObjectWithData:fontData)
    
    
set aFontName to theFont’s displayName() as text
    
set aFontSize to theFont’s pointSize()
    
    
set aColRec to {redValue:rVal, greenValue:gVal, blueValue:bVal, fontName:aFontName, fontSize:aFontSize}
    
    
set the end of colList to aColRec
  end repeat
  
  
return colList
end getAppleScriptSourceColors

–NSColorからRGBの値を取り出す
on retColListFromNSColor(aCol, aMAX as integer)
  using terms from scripting additions
    set aRed to round ((aCol’s redComponent()) * aMAX) rounding as taught in school
    
set aGreen to round ((aCol’s greenComponent()) * aMAX) rounding as taught in school
    
set aBlue to round ((aCol’s blueComponent()) * aMAX) rounding as taught in school
  end using terms from
  
  
if aRed > aMAX then set aRed to aMAX
  
if aGreen > aMAX then set aGreen to aMAX
  
if aBlue > aMAX then set aBlue to aMAX
  
  
return {aRed, aGreen, aBlue}
end retColListFromNSColor

★Click Here to Open This Script 

Posted in Color file Font OSA RTF | Tagged 13.0savvy 14.0savvy 15.0savvy NSAttributedString NSColor NSDictionary NSFont NSMutableAttributedString NSMutableDictionary NSString NSUnarchiver NSURL OSAScript | Leave a comment

OSAScriptViewのじっけん#2

Posted on 1月 9 by Takaaki Naganoya

OSAScriptViewの実験の続編です。#1ではSingle Windowのアプリを作って実験してみました(モノ自体は作ってあったので)。macOS 15.3 beta+Xcode 16.2でテストしました。

#2ではDocumentベースのアプリを作って、そこにOSAScriptViewを載せました。余計なテキストフィールドが載っているのは、いろいろ野望があるためです。

–> Download Fake Script Editor

#1と同様にコピペでAppleScriptを入力して、実際に動かして、結果を受け取れます。

ただし、この段階ですでに問題山積の状態です。Compile操作を行うと、ひさしぶりのビーチボール表示になって返ってきません。

Run Scriptはできるのに、Compile(Check Syntax)動作で落ちます。

この段階でかなり「どうすんの、これ?」という状態です。普通に部品を並べて普通につないで動かしたらクラッシュするというのは……

Posted in AppleScript Application on Xcode | Tagged 13.0savvy 14.0savvy 15.0savvy OSAScriptView | Leave a comment

OSAScriptViewのじっけん#1

Posted on 1月 9 by Takaaki Naganoya

OSASCriptViewを試してみましょう。自前でScript Editorをどの程度作れるのかという確認作業です。Xcode 16.2+macOS 15.3betaで確認を行なっています。

–> Download Xcode Project osascript_test

とはいえ、これは2017年にすでに調査してありました。OSASCriptControllerとOSAScriptViewをCocoa Bindingでつないで、さらにいくつかの必要なボタンをOSASCriptControllerにつないで、簡単なAppleScript記述+実行のテストプロジェクトを作成。

この実行環境は、AppleScriptライブラリを認識して呼び出せますし、OSの構文色分け設定を認識します。

ただし、Apple純正のスクリプトエディタ同様、Cocoa Objectのログ表示は行えません。

また、かなり致命的な問題なのですが、バンドル形式のAppleScriptはこの状態では編集・実行できません。

Appleが配布していたサンプルコードで、AppleScriptObjCが出たての頃にスクリプトエディタをASOCで組んだプロジェクトを見かけたのですが、それを探して編集するのが手っ取り早そうです。ただ、あれもバンドル形式のAppleScript書類を編集・実行できなかった記憶があります。

Posted in AppleScript Application on Xcode OSA | Tagged 13.0savvy 14.0savvy 15.0savvy OSAScriptController OSAScriptView | Leave a comment

NSObjectのクラス名を取得 v2.1

Posted on 1月 6 by Takaaki Naganoya

いろいろ調べて、NSObjectのクラス名を正確に文字列として取得するAppleScriptのXcode Projectのアップデート版です。

上のテキストフィールドにAppleScriptで各種Objectの生成を書いて「Exec」ボタンをクリックすると、それを実行して解釈プログラムに渡して下のテキストフィールドに表示します。

前バージョンでは値をNSObjectのdescriptionそのままでしたが、ChatGPTに「NSObjectをAppleScript形式で、文字列として返すAppleScriptFormatterというプログラムを書け」と指示したら、わりとちゃんと動くObjective-Cのコードを吐き出してきました。内容を再帰でさらっているようです。

とりあえず、叩き台を作ってみたのでいろいろなCocoa Objectのデータを突っ込んでためしてみるかというところでしょう。

–> Download Xcode Project runtime test_v2_1

Posted in AppleScript Application on Xcode | Leave a comment

NSObjectのクラス名を取得 v2

Posted on 1月 6 by Takaaki Naganoya

いろいろ調べて、NSObjectのクラス名を正確に文字列として取得するAppleScriptのXcode Projectです。

上のテキストフィールドにAppleScriptで各種Objectの生成を書いて「Exec」ボタンをクリックすると、それを実行して解釈プログラムに渡して下のテキストフィールドに表示します。

Script Debuggerのない世界が来ても大丈夫なように、いろいろ調査を行なっていますが、なくなると割とダメージが大きいのがCocoa Object(NSObject)のログ表示です。

# 個人的には、デバッグ機能は全部いらないので、結果表示とFramework呼び出しのあたりを実現したい

これまでにも何度か調査したことがあったのですが、Mac系開発者の知り合いに聞いてみたところ、Objective-C Runtime系のAPIを使えば取れるのでは? とのこと。

最終的には、エディタ的なものになるのかもしれませんが、とりあえず実行結果がNSObjectだったときに備えて、そのクラス名を正確に取得できるようにしてみました。

過去に、既知のクラスであればループでclassOfで調べてクラス名を取得するAppleScriptを書いたことはありましたが、未知のクラスだと手も足も出ませんでした。本プロジェクトでは、対応可能です。

–> Download runtime test_v2(Xcode Project)

クラス名はなんとか文字列として取得できていますが、値についてはまだNSObjectのdescriptionを取得しているだけです。本プロジェクトの叩き台はChatGPTに問い合わせて書いてみた(ただ、山のように修正する必要があった)ものなので、案外ヒントぐらいはChatGPTに聞いてみるといいのかもしれません。処理内容については、データを文字列で表現するというありきたりなものなので。

Posted in AppleScript Application on Xcode | Leave a comment

指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップしてダイアログでプレビュー_v4

Posted on 1月 2 by Takaaki Naganoya

指定フォルダ以下の画像(種別問わず)をすべてピックアップして、それぞれMD5チェックサムを計算し、重複しているものをピックアップしてデータとして出力するAppleScriptです。実行にはScript Debuggerを必要とします。今後は、ScriptableなライブラリをXcodeで1本作って、そこにAppleScriptから呼び出すのに便利なFrameworkを突っ込みまくるようにするのかも? 

–> Download Script Bundle within framework and library

前バージョンのScriptでは指定フォルダ直下の画像だけをピックアップするようになっていました、Spotlight検索でサブディレクトリ以下もすべて画像収集するように変更し、本Scriptだけで重複画像のブラウズができるようになっています。NSOutlineView+NSImageでブラウズするダイアログの部品はedama2さんから提供していただいています。

AppleScript名:指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップしてダイアログでプレビュー_v4.scptd
— Created 2015-10-01 by Takaaki Naganoya
— Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering
— Modified 2018-12-01 by Takaaki Naganoya
— Modified 2024-12-19 by Takaaki Naganoya
— Modified 2025-01-01 by Takaaki Naganoya
— Modified 2025-01-02 by Takaaki Naganoya
use AppleScript
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash
use outImageV : script "visLib" –NSOUtlineView+NSImageView Lib by edama2
use mdLib : script "Metadata Lib" version "2.0.0"

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSPredicate : a reference to current application’s NSPredicate
property NSCountedSet : a reference to current application’s NSCountedSet
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property NSString : a reference to current application’s NSString
property NSFileManager : a reference to current application’s NSFileManager
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor

script spd
  property fList : {}
  
property fRes : {}
  
property md5List : {}
  
property fmdList : {}
  
property dupRes : {}
  
property outList : {}
end script

set aFol to POSIX path of (choose folder)
–set aFol to POSIX path of (path to pictures folder)

set (fRes of spd) to mdLib’s searchFolders:{aFol} searchString:("(kMDItemContentTypeTree CONTAINS %@)") searchArgs:{"public.image"}

–すべての画像のMD5チェックサムを計算
set (md5List of spd) to {}
set (fmdList of spd) to {}

repeat with i in (fRes of spd)
  set j to contents of i
  
set md5Res to (current application’s FileHash’s md5HashOfFileAtPath:(j)) as string
  
set the end of (md5List of spd) to md5Res
  
set the end of (fmdList of spd) to {filePath:j, md5:md5Res}
end repeat

–チェックサムが重複している画像を取り出す
set fmdArray to NSArray’s arrayWithArray:(fmdList of spd)

set (dupRes of spd) to returnDuplicatesOnly((md5List of spd)) of me
set (outList of spd) to {}
set procMDs to {}
set aRecord to {}

repeat with i in (dupRes of spd)
  set j to contents of i
  
  
if j is not in procMDs then
    set aRes to filterDictArrayByLabel(fmdArray, "md5 == ’" & j & "’") of me
    
    
set tmpMD5 to filePath of (first item of aRes)
    
    
set tmpRes to {}
    
repeat with ii in aRes
      set jj to contents of ii
      
set idSrcURL to (current application’s NSURL’s fileURLWithPath:(filePath of jj))
      
set the end of tmpRes to {|name|:idSrcURL’s lastPathComponent(), fileURL:idSrcURL, isLeaf:true}
    end repeat
    
    
set aRec to {|name|:j, fileRes:"", isLeaf:false, children:tmpRes}
    
set aRecord’s end to aRec
    
set the end of procMDs to j
    
set the end of (outList of spd) to aRec
  end if
end repeat

–OutlineView+ ImageViewでダイアログ表示
set mainMes to "重複画像一覧"
set subMes to "指定フォルダ以下の重複画像は以下のとおりです"
set aRes to outImageV’s alert:mainMes informativeText:subMes treeData:(outList of spd) isExpand:true

–リストに入れたレコードを、指定の属性ラベルの値で抽出
on filterDictArrayByLabel(aArray, aPredicate as string)
  –抽出
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
return filteredArray
end filterDictArrayByLabel

–指定フォルダ以下のすべてのファイルを再帰で取得
on retFullpathsWithinAFolderWithRecursive(aFol)
  set anArray to NSMutableArray’s array()
  
set aPath to NSString’s stringWithString:aFol
  
set dirEnum to 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 as string)
  end repeat
  
  
return anArray as list
end retFullpathsWithinAFolderWithRecursive

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

on returnDuplicatesOnly(aList as list)
  set aSet to 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 returnDuplicatesOnly

★Click Here to Open This Script 

Posted in file Image | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

Script Debuggerのかわり、別のものを考える

Posted on 1月 2 by Takaaki Naganoya

Script Debuggerという強力なプレイヤーがいるために、スクリプト作成のためのツールを企画しても製品を実現するのは大変でした。でも、SDがディスコンになると、従来いろいろ検討してきたアイデアを実現できるかもしれません。

タイプ1:Automatorのようにブロック部品をつなぐ記述アプリ

大量にAutomatorのアクションを用意して、つないでプログラムを組む環境を作ることを考えたことがありました。Automatorそのものに突っ込んでよかったのですが、Apple純正のアクションを削除する方法がわからなかったのと、一般ユーザーがAutomatorを2つぐらいのアクションしかつないで使っていないことが分かって、ちょっと難しそうだと判断しました。

タイプ2:記述支援機能マシマシなエディタ

コンテクストメニュー経由で大量の補助Scriptを呼び出すエディタタイプを企画していました。ただ、それって普通にスクリプトエディタに組み込めばいいじゃない? ということで、Piyomaruスクリプトアシスタントを充実させました。

タイプ3:テキストでやりたいことを入力するとコードを入力するエディタ

ChatGPTみたいに、文章からコードを生成するエディタ。ありもののScriptライブラリを呼び出すタイプ。
LLMに各プログラムをどのように学習させられるかが不明。アイデアだけは検討してきた内容。

Posted in news | Tagged Script Editor | Leave a comment

Script Debuggerの開発と販売が2025年に終了

Posted on 1月 2 by Takaaki Naganoya

正月早々になかなか大きなニュースが入ってきました。AppleScriptの統合開発環境であるScript Debuggerの開発と販売の終了をLate Night Softwareが発表しました。

Script Debuggerはまだ2025年の6月まで購入可能とのことです。Appleが買収するしか継続の目がなさそうなのですが、Appleがそうするかどうかは不明です。

Script DebuggerはAppleScriptの統合開発環境ですが、上級者にはあまり役立たず、むしろ入門者が使うと役立つツールであることが問題だと思っていました。そのあたりの対処として、ライトユーザーへの訴求を行うべく価格の引き下げやLightモード動作(試用版の継続使用が可能に)が導入されたようですが、有効な手段にはなり得なかったようです。

ソフトウェア製品としてのScript Debuggerは、コア部分がC++で書かれているようで(推測)、思い切った構造の変更やインタフェースの改良を行いづらいところです。

実際に、30年続いたプロジェクトでもあり、大幅な書き換えは難しかったところでしょう。

まだ、どのように受け取るべきかが分からないため、速報ということで。

ただ、macOS 10.13あたりまでのスクリプトエディタ(10.15あたりまで?)では、バンドル内にDebugアイコンとか未使用のアイコンがたくさんあって、

「Apple純正のスクリプトエディタでデバッグ機能をつけていないのは、製品版(Script Debugger)に配慮した結果ですよ」

みたいな言い訳の痕跡(こんせき)を垣間見ることができ、それなりに担当者レベルでは敬意を払われてきた製品だと思います。

関連記事:Script Debuggerがフリーダウンロードで提供されることに

Posted in news | Tagged Script Debugger | Leave a comment

執筆中:AppleScript最新リファレンスver2.8対応(macOS 15対応アップデート)

Posted on 1月 1 by Takaaki Naganoya

「AppleScript最新リファレンスver2.8対応」をお買い上げの読者の方々に対して、アップデート版として提供されます。

ほとんどできているのですが、「AppleScript最新リファレンスver2.8対応」添付のPiyomaru Script Assistantに合わせて内容の調整を行なっています。macOS 15の登場によって変更になった箇所の情報を中心に内容を補っています。前バージョンからは60ページほど内容を追記しています。

同ツールは初版に添付することをねらっていましたが、macOSのバグ(とくにText To Speech系)の状況確認や対応に時間がかかっていました。

English Version is here.

English version will be updated as original version. At first, English version is devided 3 part. But English version did not make good sales as I expected, so #2 and #3 project will be canceled.

Posted in Books | Tagged 12.0savvy 13.0savvy 14.0savvy 15.0savvy | 1 Comment

執筆中:Cocoa Scripting Course #10 NSAttributedString

Posted on 1月 1 by Takaaki Naganoya

目下、執筆中なのがCocoa Scripting Courseの10巻、NSAttributedStringです。FoundationとAppKitに分かれて機能が分布しており、なかなか言及すべき内容が多いものです。

WebKitにも機能が分布していますが、ざっと見たかぎりではWebKitのNSAttributedStringはAppleScriptから呼び出せないものがほとんどのようなので、ここは無視してよいでしょう。

NSAttributedStringとHTML、そしてMarkdownとの間の変換機能などが最近のmacOSのアップデートで追加されているため、こちらもすぐには完成しないことでしょう。

Posted in Books | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

執筆中:スクリプトエディタ Scripting Book with AppleScript

Posted on 1月 1 by Takaaki Naganoya

あけましておめでとうございます。

目下執筆中なのが、「スクリプトエディタScripting Book with AppleScript」という本です。

AppleScriptでスクリプトエディタを操作してさまざまな処理を行うことをテーマに据えています。不可能を可能にする系の内容がぎっしり。割とカロリー高めな内容です。

スクリプトエディタはMac OS X 10.3か4のときにスクリプタブルになり、従来のCarbonではなくCocoaで書き直されました。生産性を向上させるためにスクリプトエディタを操作するScriptingはその頃から行なってきたのですが、ノウハウの総量は巨大なものの、これを必要としているユーザーがどの程度いるのか? という懸念から、まとめることをためらっていました。

ただ、まとめずに放置しておいては、有用なノウハウも風化してしまうため、この機会にまとめてみることにしたものです。

目下、400ページほど書いてみましたが、これはAppleScriptコマンドリファレンスを含んだものであり、記事ページについては「数ページの箇所もあれば数十ページの章もあって、バランスがよくない」といった印象です。

いったん寝かせて放っておくと、いい感じに発酵して(角がとれて)マイルドな味わいになるかもしれません。

Posted in Books | Tagged 13.0savvy 14.0savvy 15.0savvy | 2 Comments

choose fileで指定したsdefを読み込み、sdef中のサンプル(用例)を個別にHTML書き出しする

Posted on 12月 30, 2024 by Takaaki Naganoya

スクリプトエディタから書き出したsdefファイルを選択すると、指定の書き出し先フォルダにsdef内のAppleScriptサンプルをHTML形式で書き出すAppleScriptです(最初のバージョンでHTMLの実体参照デコード処理をハードコーディングしていたのを、Cocoaの機能を利用するよう書き換えました)。

スクリプトエディタでAppleScript用語辞書を表示させた状態で、ファイル書き出しすると個別のsdefファイルとして保存できます。この状態のsdefにアプリのバージョン番号を付加して、バージョン履歴として保存しています。

こうして保存しておいたsdef内のサンプルAppleScriptをHTMLとして書き出します。Pixelmator Proに58本のサンプルScriptが入っていたので、けっこうな分量になります。それを手作業で取り出すのは手間なので、Scriptで取り出すことにしました。

それを収集するために作ったのが本Scriptです。

本来、スクリプトエディタで表示(xinclude解消+レンダリング)させたsdefを処理させるAppleScriptで、いちいちxincludeの展開を行わせるのは無意味なのですが、本Scriptはもともと「アプリのBundle IDを指定してsdefのパスを求めて処理する」ようになっていたため、仕様がとがりすぎて汎用性がいまひとつだったので、「スクリプトエディタで書き出したsdefを処理」するように書き換えたという経緯があるためです。説明したら余計にわからなくなったような、、、、

AppleScript名:choose fileで指定したsdefを読み込み、sdef中のサンプル(用例)を個別にHTML書き出しする v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/12/31
—
–  Copyright © 2022-2024 Piyomaru Software, All Rights Reserved
—

use AppleScript
use framework "Foundation"
use framework "AppKit"
use scripting additions

set sdefAlias to (choose file of type {"com.apple.scripting-definition"} with prompt "書き出したSDEFを選択")
set sdefFullPath to (POSIX path of sdefAlias)

–SDEF読み込み(Xincludeの展開が必要な状態)
tell current application
  set theXML to read sdefAlias as «class utf8»
end tell

–NSXMLDocumentの生成、Xincludeを有効に
set {theXMLDoc, theError} to current application’s NSXMLDocument’s alloc()’s initWithXMLString:theXML options:(current application’s NSXMLDocumentXInclude) |error|:(reference)

set aDocStr to (theXMLDoc’s XMLData)
set aDocStr2 to (current application’s NSString’s alloc()’s initWithData:(aDocStr) encoding:(current application’s NSUTF8StringEncoding)) as string

set sampleList to (extractStrFromTo(aDocStr2, "<html>", "</html>") of me)
set sampleCount to length of sampleList
if sampleCount = 0 then return

set outFol to POSIX path of (choose folder with prompt "Select Output Folder")

set aCount to 1

repeat with i in sampleList
  set j to (contents of i)
  
  
if j is not equal to "" then
    set j1 to decodeCharacterReference(j) of me
    
set j2 to "<!DOCTYPE html><html><meta charset=utf-8><title>" & (aCount as string) & "</title><body>" & j1 & "</body></html>"
    
    
set wPath to outFol & (aCount as string) & ".html"
    
set fRes to writeToFileAsUTF8(j2, wPath) of me
    
if fRes = false then error
    
    
set aCount to aCount + 1
  end if
end repeat

–指定パスからアプリケーションのScriptabilityをbooleanで返す
on retAppSdefNameFromBundleIPath(appPath as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:"OSAScriptingDefinition"
  
if aRes = missing value then return false
  
set asRes to aRes as string
  
  
return asRes as string
end retAppSdefNameFromBundleIPath

–指定文字と終了文字に囲まれた内容を抽出
on extractStrFromTo(aParamStr, fromStr, toStr)
  set theScanner to current application’s NSScanner’s scannerWithString:aParamStr
  
set anArray to current application’s NSMutableArray’s array()
  
  
repeat until (theScanner’s isAtEnd as boolean)
    set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference)
    
theScanner’s scanString:fromStr intoString:(missing value)
    
set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(reference)
    
if theValue is missing value then set theValue to "" –>追加
    
theScanner’s scanString:toStr intoString:(missing value)
    
anArray’s addObject:theValue
  end repeat
  
  
return (anArray as list)
end extractStrFromTo

on writeToFileAsUTF8(aStr, aPath)
  set cStr to current application’s NSString’s stringWithString:aStr
  
set thePath to POSIX path of aPath
  
set aRes to cStr’s writeToFile:thePath atomically:false encoding:(current application’s NSUTF8StringEncoding) |error|:(missing value)
  
return aRes as boolean
end writeToFileAsUTF8

–文字置換
on repChar(origText as string, targStr as string, repStr as string)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

–実体参照をデコード
on decodeCharacterReference(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF16StringEncoding)
  
set styledString to current application’s NSAttributedString’s alloc()’s initWithHTML:theData documentAttributes:(missing value)
  
set plainText to (styledString’s |string|()) as string
  
return plainText
end decodeCharacterReference

★Click Here to Open This Script 

Posted in file File path sdef XML | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

選択範囲のセルの数値がAscendingになっているかをチェック

Posted on 12月 26, 2024 by Takaaki Naganoya

Numbersで選択中のセルが1→2→3と、値が増加する形式(Ascending)になっているかをチェックするAppleScriptです。

書籍のページ(ノンブル)は、かならず1–>2–>3とページ数がかならず増加するようになっています。これが、途中で減るような値になっているとまずいので、そのチェックを行うようにしてみたものです。

本ScriptはNumbers v14.3でテストしていますが、もっと古いバージョンでも問題ないことでしょう。

AppleScript名:選択範囲のセルの数値がAscendingになっているかをチェック
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/12/25
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSString : a reference to current application’s NSString
property NSCharacterSet : a reference to current application’s NSCharacterSet

set curTable to getCurTable() of me
if curTable = "" then return

tell application "Numbers"
  tell curTable
    set cList to value of every cell of selection range
  end tell
end tell

copy cList to dList

set dList to shellSortAscending(dList) of me

if cList = dList then
  return true
else
  return false
end if

on getCurTable()
  tell application "Numbers"
    tell front document
      tell active sheet
        try
          set theTable to first table whose class of selection range is range
        on error
          return "" –何も選択されてなかった場合
        end try
        
        
return theTable
      end tell
    end tell
  end tell
end getCurTable

–入れ子ではないリストの昇順ソート
on shellSortAscending(aSortList)
  script oBj
    property list : aSortList
  end script
  
set len to count oBj’s list’s items
  
set gap to 1
  
repeat while (gap ≤ len)
    set gap to ((gap * 3) + 1)
  end repeat
  
repeat while (gap > 0)
    set gap to (gap div 3)
    
if (gap < len) then
      repeat with i from gap to (len – 1)
        set temp to oBj’s list’s item (i + 1)
        
set j to i
        
repeat while ((j ≥ gap) and (oBj’s list’s item (j – gap + 1) > temp))
          set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1)
          
set j to j – gap
        end repeat
        
set oBj’s list’s item (j + 1) to temp
      end repeat
    end if
  end repeat
  
return oBj’s list
end shellSortAscending

★Click Here to Open This Script 

Posted in list | Tagged 14.0savvy 15.0savvy Numbers | Leave a comment

ステータスメニューからアプリ本体を最前面に(改2)

Posted on 12月 24, 2024 by Takaaki Naganoya

GUIアプリのステータスメニュー上に置いたアイコン>メニューからアプリ本体のウィンドウをアクティブにできないという問題が発生していました。

macOS 13、14、15とずーーっとこの動作なので、全世界的に困らされている状況があって……久しぶりにXcodeでGUIアプリをAppleScriptで作って、この問題に例外なく自分も悩まされていました。macOS 15.2上ではこれで動いていたのですが、

-> ステータスメニューからアプリ本体を最前面に(改)

edama2さんから情報を教えていただき、ここで用いていた「activateIgnoringOtherApps」がmacOS 15.2でDeprecated扱いになったとのこと。

ただ、Appleのdocumentで紹介されていたNSApplicationのactivate()メソッドを使っても、この場合にはまともに動作しませんでした。代替手段を紹介しておきながら、それがまともに動かないというのはいかがなものでしょう。

昨今のWWDCでは、さっぱり地に足のついた情報が紹介されておらず、見るだけ時間の無駄といった印象を持っています。あてにならない大本営発表ばかりではなく、まともな情報を期待したいところですが、それは難しいところなのでしょうか。

一応、AppleScriptのactivateコマンドが動作するようになったので(macOS 14ではactivateでも最前面に持っていけませんでした)、そのように修正を行いました。

–> Download process Control test Project

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— process Control test
—
— Created by Takaaki Naganoya2 on 2024/11/01.
—
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
  
property NSMenu : a reference to current application’s NSMenu
  
property NSMenuItem : a reference to current application’s NSMenuItem
  
property NSStatusBar : a reference to current application’s NSStatusBar
  
property NSVariableStatusItemLength : a reference to current application’s NSVariableStatusItemLength
  
  
  
on applicationWillFinishLaunching:aNotification
    my initializeMenu:(aNotification)
  end applicationWillFinishLaunching:
  
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on clicked:aSender
    my activateMe:(me)
    
set aTag to (tag of aSender) as integer –Important!!
    
set aTitle to (title of aSender) as string
    
    
if aTag is in {41, 42, 43, 44, 45, 46} then
      –my activateMe:aSender
      
current application’s NSApplication’s |activate|
    else if aTag = 100 then
      display dialog "Clicked"
    end if
    
    
if aTitle = "Quit" then quit
  end clicked:
  
  
  
on activateMe:aSender
    –macOS 13から15.0あたりまでactivateができなかった(多分バグ)
    
–current application’s NSApplication’s |activate|
    
tell current application to activate
    
–theWindow’s makeKeyAndOrderFront:(me)
    
theWindow’s orderFrontRegardless()
  end activateMe:
  
  
  
–Status Menu Structure
  
on initializeMenu:aSender
    set aList to {"Piyomaru", "Software", "", "Function", {"1", "2", "3", "4", "5"}, "", "Quit"}
    
    
set aStatusItem to current application’s NSStatusBar’s systemStatusBar()’s statusItemWithLength:(current application’s NSVariableStatusItemLength)
    
    
aStatusItem’s setTitle:" TEST "
    
aStatusItem’s setHighlightMode:true
    
aStatusItem’s setMenu:(createMenu(aList) of me)
  end initializeMenu:
  
  
  
  
on createMenu(aList)
    set aMenu to current application’s NSMenu’s alloc()’s init()
    
set aCount to 10
    
    
set prevMenuItem to ""
    
    
repeat with i in aList
      set j to contents of i
      
set aClass to (class of j) as string
      
      
if j is equal to "" then
        set aMenuItem to (current application’s NSMenuItem’s separatorItem())
        (
aMenu’s addItem:aMenuItem)
      else
        if (aClass = "text") or (aClass = "string") then
          
          
if j = "Quit" then
            set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:j action:"clicked:" keyEquivalent:"")
          else
            set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:j action:"clicked:" keyEquivalent:"")
          end if
          
          (
aMenuItem’s setTag:aCount)
          (
aMenuItem’s setTarget:me)
          (
aMenu’s addItem:aMenuItem)
          
          
set aCount to aCount + 10
          
copy aMenuItem to prevMenuItem
          
          
        else if aClass = "list" then
          –Generate Submenu
          
set subMenu to current application’s NSMenu’s new()
          (
aMenuItem’s setSubmenu:subMenu)
          
          
set subCounter to 1
          
          
repeat with ii in j
            set jj to contents of ii
            
            
set subMenuItem1 to (current application’s NSMenuItem’s alloc()’s initWithTitle:jj action:"clicked:" keyEquivalent:"")
            (
subMenuItem1’s setTarget:me)
            (
subMenuItem1’s setTag:(aCount + subCounter))
            (
subMenu’s addItem:subMenuItem1)
            
            
set subCounter to subCounter + 1
          end repeat
          
        end if
        
      end if
      
    end repeat
    
    
return aMenu
  end createMenu
  
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode Bug | Leave a comment

CotEditor v5.0.7でwrite to consoleにオプションが追加される

Posted on 12月 23, 2024 by Takaaki Naganoya

オープンソースのテキストエディタ「CotEditor」の「write to console」コマンドにオプションが追加されました。

title(実行したAppleScript名の表記)と、timestamp表示の有無を指定できるようになっています。

ただし、これらのオプションが効くには条件があります。CotEditorの外部から、スクリプトエディタやScript Debuggerなどで実行したAppleScript内でCotEditorに対してwrite to consoleコマンドを実行した場合には、これらのオプションを指定していても、とくにtitle(ファイル名)については効きません。

CotEditorの内蔵スクリプトメニュー内で実行したAppleScriptにおいて「write to console」コマンドを実行した場合にはtitle(ファイル名)、timestamp(日時)の指定が有効です。

AppleScript名:コンソールテスト1.scpt
tell application "CotEditor"
  write to console "ぴよまるさんだよ" with title without timestamp
  
write to console "ぴよぴよさんだよ" with title and timestamp
end tell

★Click Here to Open This Script 

Posted in news Object control | Tagged 14.0savvy 15.0savvy CotEditor | Leave a comment

Cocoa Scripting Course用、タイトルの丸つき数字から表を編集 v2(複数スライド選択用)

Posted on 12月 23, 2024 by Takaaki Naganoya

Keynote書類で、タイトルに入っている丸つき数字を取得して、同スライド内にある「表」の行数を追加し、追加したヘッダーカラムに丸つき数字を追加するAppleScriptです。Cocoa Scripting Courseで手間のかかるページの作業を効率化するために作成しました。

本ScriptはKeynote 14.3で作成していますが、とくにあたらしめの機能は使っていないため、かなり古いバージョンに対しても使えるはずです。


▲処理前


▲処理後 表の行数が変更されている

Keynoteの現在表示中のスライドからテキストを抽出し、そこから丸つき数字の文字だけを取り出します。

それぞれの丸つき数字文字を数値に変換し、最大値を求めます。この最大値と表の行数を比較。表で足りない行数を計算して、表に行を新規追加。カラムヘッダーに丸つき数字を補います。

こうした処理を選択中の複数のスライド(ページ)に対して実行します。

表の「中身」についても、実際にスライド上に配置しているので自動で抽出できてもよさそうですが、そこに時間をかけても仕方がないのでいまはこのままです。あとで、そういう処理ができるようになるかもしれません。

AppleScript名:Cocoa Scripting Course用、タイトルの丸つき数字から表を編集 v2(複数スライド選択用).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/12/23
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

tell application "Keynote"
  tell front document
    set sSel to selection
    
if class of first item of sSel is not equal to slide then return
    
    
repeat with curSlide in sSel
      set current slide to curSlide
      
      
tell current slide
        –タイトルから丸つき数字文字のみ抽出
        
set myTitle to object text of default title item
        
set numStr to holdNumberWithSignOnly(myTitle) of me
        
set numList to characters of numStr
        
        
–丸つき数字のうち最大のものを取得
        
set cList to {}
        
repeat with i in numList
          set j to decodeNumFromNumWithSign(i) of me
          
set the end of cList to j
        end repeat
        
        
set sList to shellSortDescending(cList) of me
        
set theLargestNum to first item of sList –最大値
        
        
        
–表の情報を取得
        
tell table 1
          set rCount to count every row
          
set tHeight to height of it
        end tell
        
        
–追加が必要な行数を算出
        
set addRows to theLargestNum + 2 – rCount
        
if addRows > 0 then
          tell table 1
            set row count to (rCount + addRows)
            
            
repeat with i from (rCount – 1) to (rCount + addRows – 2)
              tell row (i + 1)
                tell cell 1
                  set value to convNumToNumWithSign(i) of me
                end tell
              end tell
            end repeat
            
            
tell row -1
              tell cell 1
                set value to "返り値"
              end tell
            end tell
            
            
–Resize Heiight
            
set curRows to row count
            
set height to (tHeight / rCount) * curRows
          end tell
        end if
      end tell
    end repeat
  end tell
end tell

–文字列から丸つき数字のみ抽出
on holdNumberWithSignOnly(aStr as text)
  set aNSString to current application’s NSString’s stringWithString:aStr
  
  
return (aNSString’s stringByReplacingOccurrencesOfString:"[^\\U000024EA-\\U000024EA\\U00002460-\\U00002473\\U00003251-\\U000032BF\\U000024FF-\\U000024FF\\U00002776-\\U0000277F\\U000024EB-\\U000024F4\\U00002780-\\U00002789\\U0000278A-\\U00002793\\U000024F5-\\U000024FE]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, aNSString’s |length|()}) as text
end holdNumberWithSignOnly

–丸つき数字を数字に変換
on decodeNumFromNumWithSign(aStr as string)
  set numStr to "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿"
  
if numStr does not contain aStr then return false
  
using terms from scripting additions
    set bNum to offset of aStr in numStr
  end using terms from
  
return bNum
end decodeNumFromNumWithSign

–数字を丸つき数字に変換
on convNumToNumWithSign(aNum as number)
  if (aNum ≤ 0) or (aNum > 50) then return ""
  
set aStr to "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿"
  
set bChar to character aNum of aStr
  
return bChar
end convNumToNumWithSign

–入れ子ではないリスト(1D List)の昇順ソート
on shellSortAscending(aSortList)
  script oBj
    property list : aSortList
  end script
  
set len to count oBj’s list’s items
  
set gap to 1
  
repeat while (gap ≤ len)
    set gap to ((gap * 3) + 1)
  end repeat
  
repeat while (gap > 0)
    set gap to (gap div 3)
    
if (gap < len) then
      repeat with i from gap to (len – 1)
        set temp to oBj’s list’s item (i + 1)
        
set j to i
        
repeat while ((j ≥ gap) and (oBj’s list’s item (j – gap + 1) > temp))
          set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1)
          
set j to j – gap
        end repeat
        
set oBj’s list’s item (j + 1) to temp
      end repeat
    end if
  end repeat
  
return oBj’s list
end shellSortAscending

–入れ子ではないリスト(1D List)の降順ソート
on shellSortDescending(aSortList)
  script oBj
    property list : aSortList
  end script
  
set len to count oBj’s list’s items
  
set gap to 1
  
repeat while (gap ≤ len)
    set gap to ((gap * 3) + 1)
  end repeat
  
repeat while (gap > 0)
    set gap to (gap div 3)
    
if (gap < len) then
      repeat with i from gap to (len – 1)
        set temp to oBj’s list’s item (i + 1)
        
set j to i
        
repeat while ((j ≥ gap) and (oBj’s list’s item (j – gap + 1) < temp))
          set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1)
          
set j to j – gap
        end repeat
        
set oBj’s list’s item (j + 1) to temp
      end repeat
    end if
  end repeat
  
return oBj’s list
end shellSortDescending

★Click Here to Open This Script 

Posted in Text | Tagged 13.0savvy 14.0savvy 15.0 Keynote | Leave a comment

Post navigation

  • Older posts
  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • Numbersで選択範囲のセルの前後の空白を削除
  • macOS 26, Tahoe
  • macOS 15でも変化したText to Speech環境
  • KagiのWebブラウザ、Orion
  • Script Debuggerの開発と販売が2025年に終了
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • macOS 15 リモートApple Eventsにバグ?
  • NSObjectのクラス名を取得 v2.1
  • 2024年に書いた価値あるAppleScript
  • 有害ではなくなっていたSpaces
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • Xcode上のAppleScriptObjCのプログラムから、Xcodeのログ欄へのメッセージ出力を実行
  • (確認中)AppleScript Dropletのバグっぽい動作が解消?
  • AVSpeechSynthesizerで読み上げテスト
  • AppleScript Dropletのバグっぽい動作が「復活」(macOS 15.5β)
  • Apple、macOS標準搭載アプリ「写真」のバージョン表記を間違える
  • 指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップ
  • macOS 26, 15.5でShortcuts.app「AppleScriptを実行」アクションのバグが修正される
  • Numbersで選択中の2列のセルを比較して並べ直して書き戻す v2
  • Script Debuggerがフリーダウンロードで提供されることに

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (204) 14.0savvy (159) 15.0savvy (156) CotEditor (66) Finder (52) Keynote (119) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (56) Pixelmator Pro (20) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Newt On Project
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • Scripting Additions
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年10月
  • 2025年9月
  • 2025年8月
  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC