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

タグ: 10.15savvy

Excel__Numbersセルアドレスの相互変換

Posted on 12月 3 by Takaaki Naganoya

ExcelやNumbersで使われているセルのアドレス表記方法「A1形式」と数値の相互変換を行うAppleScriptです。

一応、自分でも昔に書いたルーチンを使い回していますが、26進数と10進数との間の変換で桁が増えたときの処理に難があって、上限値を設けてその間であれば変換できる、という感じになっていました。

もともと、このルーチンはExcel 2008でVBAの処理系を搭載しないことになったのを好機ととらえ、AppleScriptをエンコードしてExcelの隠しワークシート上に格納しておいて外部から実行する「ExcelAS」プロジェクトのために作成したものです。

実際に調布のMicrosoftでデモを行なって、US Microsoftに掛け合ってもらったものの、次バージョンでVBAの処理系を復活させることになって、(Visual BASIC互換の)「REALbasic」のエンジンを書いていたエンジニアをMSがヘッドハント。常識的に考えればVBAの廃止自体がおかしな決定だったので、その隙を狙えるかも? と企画して作ったものの、残念な結果になってしまいました。ただ、現在に至るもMac上のVBAの処理系、とくにエディタは作りが残念(Retina解像度に合ってないとか、日本語入力できないとか、フォームが使えないとか)なので、もうちょっとなんとかならないものかと思ってしまいます。

話をアドレス変換ルーチンに戻しましょう。実際に、そんなに大きな値の相互変換はしていないので問題視していませんでしたが、変換ルーチンに上限値のしばりがあるのはうっとおしいとは思っていました。ただ、ExcelASプロジェクトの頓挫により、アドレス変換処理を書き換えるほどのインセンティブがなかったので、ながらく放置状態に。

そこで、定期的に行なっているChatGPTによるAppleScript記述実用性チェックの「お題」としてこのセルアドレスの相互変換を行わせてみました。

ちゃんと動いているように見えます。こういうデータ変換系のプログラムは、割とChatGPTで書かせるのは「アリ」だと思います。本ルーチンの注意点は、Excelアドレス(カラム名指定)はアルファベット大文字で記述する必要があるということです。小文字のアルファベットで記述すると本バージョンではエラーになります。

ただ、アプリケーションの詳細なコントロールを行わせると、首をひねってしまうような書き方を返してきます。

AppleScript名:Excel__Numbersセルアドレスの相互変換.scpt
— 数値 → A1形式
set result1 to numberToCell(2024, 5) — "BYV5"
display dialog "Number to Cell: " & result1

— A1形式 → 数値
set result2 to cellToNumber("BYV5") — {2024, 5}
display dialog "Cell to Number: Column: " & item 1 of result2 & ", Row: " & item 2 of result2

— 数値からセルアドレス(A1形式)への変換
on numberToCell(columnNumber, rowNumber)
  set columnAddress to ""
  
set tempNumber to columnNumber
  
  
— 列番号をA-Z形式に変換
  
repeat while tempNumber > 0
    set remainder to (tempNumber – 1) mod 26
    
set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress
    
set tempNumber to (tempNumber – 1) div 26
  end repeat
  
  
— A1形式のアドレスを返す
  
return columnAddress & rowNumber
end numberToCell

— セルアドレス(A1形式)から数値への変換
on cellToNumber(cellAddress)
  set columnPart to ""
  
set rowPart to ""
  
  
— 列部分と行部分を分離
  
repeat with char in cellAddress
    if char is in "0123456789" then
      set rowPart to rowPart & char
    else
      set columnPart to columnPart & char
    end if
  end repeat
  
  
— 列部分を数値に変換
  
set columnNumber to 0
  
repeat with i from 1 to length of columnPart
    set char to character i of columnPart
    
set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  end repeat
  
  
— 数値を返す
  
return {columnNumber, (rowPart as integer)}
end cellToNumber

★Click Here to Open This Script 

Posted in Number Text | Tagged 10.10savvy 10.11savvy 10.12savvy 10.13savvy 10.14savvy 10.15savvy 11.0savvy 12.0savvy 13.0savvy 14.0savvy 15.0savvy Excel Numbers | Leave a comment

Keynoteで選択中のtext itemの冒頭のフォントを太くする v2

Posted on 11月 1 by Takaaki Naganoya

Keynote書類で選択中のテキストアイテムのうち、各行の冒頭からマークの文字までの間を太文字にするAppleScriptです。

v1を改良し、さまざまな区切り記号に対応させるべく、改修を行なってみたものです。

当初は、各テキストアイテムの内部テキストを解析して、共通記号文字を計算して自動で認識処理を行なってみようかと考えていました。統計処理を行なって共通で登場する文字をピックアップさせることを検討していました。

ただ、これだと複数の選択アイテムで別々の区切り文字を採用している場合に対応できません。

統計処理を行わず、技術的にもっとレベルを下げ、「ゆらぎ」検出のためのオーソドックスな、ゆらぎ表記列挙リストを作って、ひたすらループで処理するように改変。


▲処理前 Keynoteの書類上でテキストアイテムを選択


▲処理後 各テキストアイテムで、指定の記号より前の部分の文字を太くした

なお、本Scriptは書式変更ターゲット文字のピックアップ性能を向上させたものであり、欧文フォントの処理を考慮したものにはなっていません。フォントファミリー内のウェイトを上げたフォントを求めるという処理を行なっています。

fFamilyCount = 2

の場合には、「ヒラギノ角ゴProN W3」を「ヒラギノ角ゴProN W6」に変更する処理を行います。

fFamilyCount > 4

の場合には、「ヒラギノ角ゴシック Wn」のウェイトを上げています。

もしも、利用中のMacにウェイトが多数含まれているフォントをインストールして、Keynote書類上でそのフォントを指定している場合には、ウェイトを上げたフォントを求める処理で、文字を太くするよう処理されることでしょう。

AppleScript名:選択中のtext itemの冒頭のフォントを太くする(フォントのWeightを変更)v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/11/01
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

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

property NSFont : a reference to current application’s NSFont
property NSFontManager : a reference to current application’s NSFontManager

–セパレータリスト、表記ゆらぎ対応(ゆらぎ表記個数は可変)
property separatorList : {{":", ":"}, {"mm", "㎜"}, {"cm", "cm"}}

tell application "Keynote"
  tell front document
    set aSel to selection
    
    
    
–Keynote上の選択中のオブジェクトでループ
    
repeat with i in aSel
      set j to contents of i
      
set tmpClass to class of j
      
      
      
–選択中のオブジェクトがテキストアイテムの場合に…….
      
if tmpClass = text item then
        set objText to object text of j
        
set fontName to font of object text of j
        
set fontSize to size of object text of j
        
        
        
–フォントを太らせる(ウェイトを上げる)
        
set fFamilyCount to countFontsInItsFamily(fontName) of me
        
if fFamilyCount = 2 then
          set newFont to incrementFontWeight(fontName, 1) of me
        else if fFamilyCount > 4 then
          set newFont to incrementFontWeight(fontName, 4) of me
        end if
        
        
set aCount to 1
        
set tList to splitByLInes(objText) of me
        
        
        
–行ごとにParseした行ごとのテキストでループ
        
repeat with ii in tList
          set jj to contents of ii
          
          
set anOffset to 0
          
          
–セパレータでループ
          
repeat with iii in separatorList
            –セパレータの「ゆらぎ」表記を考慮してループ
            
repeat with iiii in iii
              set jjjj to contents of iiii
              
set anOffset to offset of jjjj in jj
              
              
if anOffset is not equal to 0 then
                exit repeat
              end if
            end repeat
            
            
if anOffset is not equal to 0 then exit repeat
            
          end repeat
          
          
if anOffset is not equal to 0 then
            try
              set font of characters 1 thru (anOffset – 1) of paragraph aCount of object text of j to newFont
            end try
          end if
          
          
set aCount to aCount + 1
          
        end repeat
      end if
    end repeat
  end tell
end tell

–テキストを行ごとにParse
on splitByLInes(someText) — free to a good home
  set theString to current application’s NSString’s stringWithString:someText
  
set theList to theString’s componentsSeparatedByCharactersInSet:(current application’s NSCharacterSet’s newlineCharacterSet())
  
return theList as list
end splitByLInes

–フォントを太らせる。欧文フォントは考慮していない(別の方法で行う)
on incrementFontWeight(psFontName, incNum)
  set aFont to current application’s NSFont’s fontWithName:psFontName |size|:9.0
  
–> (NSCTFont) "HiraginoSans-W0 9.00 pt. P [] (0x12870af00) fobj=0x11b1e90d0, spc=1.98"
  
  
set fontM to current application’s NSFontManager’s sharedFontManager()
  
  
repeat incNum times
    set aFont to fontM’s convertWeight:true ofFont:aFont
  end repeat
  
  
return (aFont’s fontName()) as string
end incrementFontWeight

–指定フォントのファミリーに属するフォント数を取得
on countFontsInItsFamily(aPSName)
  set aFont to current application’s NSFont’s fontWithName:(aPSName) |size|:9.0
  
set aFamily to aFont’s familyName()
  
set fMan to current application’s NSFontManager’s sharedFontManager()
  
set fList to fMan’s availableMembersOfFontFamily:aFamily
  
return length of (fList as list)
end countFontsInItsFamily

★Click Here to Open This Script 

Posted in Font Text | Tagged 10.15savvy 11.0savvy 12.0savvy 13.0savvy 14.0savvy 15.0savvy Keynote | Leave a comment

iCalendarファイルの作成

Posted on 9月 20 by Takaaki Naganoya

オープンソースのプロジェクト「iCal4ObjC」をFramework化してAppleScriptから呼び出し、iCalendarファイル(.ics)をデスクトップに作成するテストコードです。実行には、iCalendarKit.framework(macOS 10.15以降用にUniversal Binaryでビルド)を必要とします。また、macOS標準搭載のスクリプトエディタ上では動作せず、Script DebuggerないしSDから書き出したEnhanced Appletとして動かす必要があります。

–> DownloadiCalendarKit.framework (To ~/Library/Frameworks)

本Scriptの実行結果です。

AppleScript名:iCal4ObjCのじっけん(iCalendarファイルの作成).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/09/20
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

use AppleScript
use framework "Foundation"
use framework "iCalendarKit" –https://github.com/cybergarage/iCal4ObjC
use scripting additions

set ical to current application’s CGICalendar’s alloc()’s init()

–Add an object
set icalObj to current application’s CGICalendarObject’s alloc()’s initWithProdid:"//CyberGarage//iCal4ObjC//EN"

–Add a component
set icalComp to current application’s CGICalendarComponent’s alloc()’s initWithType:"VTODO"
icalObj’s addComponent:icalComp

ical’s addObject:icalObj

— Add a property
set icalProp to current application’s CGICalendarProperty’s alloc()’s init()
icalProp’s setName:"SUMMARY"
icalProp’s setValue:"Write report"
icalComp’s addComponent:icalProp

set outPath to POSIX path of (path to desktop) & (do shell script "uuidgen") & ".ics"

ical’s writeToFile:outPath

★Click Here to Open This Script 

Posted in Calendar | Tagged 10.15savvy 11.0savvy 12.0savvy 13.0savvy 14.0savvy 15.0savvy | Leave a comment

国民の祝日を求める v7

Posted on 7月 17 by Takaaki Naganoya

日本のカレンダーにおける国民の祝日(休日)を、dateオブジェクトのリストで求めるAppleScriptです。

2020〜2021年のイレギュラーな休日変更に対応してみました。

# 何か不具合や不足分があったらおしらせください
# 某・呪われた手帳メーカー系の仕事には不十分かもしれないので、不幸にもその案件に関わった方はメーカー支給の祝祭日データを利用してください

こうした高度なカレンダー計算AppleScriptは、「Newt On Project」の直系の遺産です。自然言語で曜日や日数の指定を行う上で、休日の計算は欠かせないものでした。

休日に関しては政府がCSVファイルで配布しているものもありますが、来年や再来年、5年後のカレンダーを扱いたいといった場合に、自前で計算できないと話になりません。そうした処理に備える意味でも、自前で計算できる「意義」はあります。

AppleScript名:国民の祝日を求める v7.scpt
use AppleScript
use scripting additions
use framework "Foundation"

(*

本バージョンのテーマ:
東京オリンピック(2020/2021年)関連の超イレギュラーな休日調整に対応

*)

set aList to retHolidayRec(2020) of me
–> {{date "2020年1月1日 水曜日 0:00:00", "元旦"}, {date "2020年1月13日 月曜日 0:00:00", "成人の日"}, {date "2020年2月11日 火曜日 0:00:00", "建国記念日"}, {date "2020年2月23日 日曜日 0:00:00", "天皇誕生日"}, {date "2020年2月24日 月曜日 0:00:00", "振替休日"}, {date "2020年3月20日 金曜日 0:00:00", "春分の日"}, {date "2020年5月3日 日曜日 0:00:00", "憲法記念日"}, {date "2020年5月4日 月曜日 0:00:00", "みどりの日"}, {date "2020年5月5日 火曜日 0:00:00", "こどもの日"}, {date "2020年5月6日 水曜日 0:00:00", "振替休日"}, {date "2020年7月22日 水曜日 0:00:00", "海の日"}, {date "2020年7月24日 金曜日 0:00:00", "スポーツの日"}, {date "2020年8月10日 月曜日 0:00:00", "山の日"}, {date "2020年9月21日 月曜日 0:00:00", "敬老の日"}, {date "2020年9月22日 火曜日 0:00:00", "秋分の日"}, {date "2020年11月3日 火曜日 0:00:00", "文化の日"}, {date "2020年11月23日 月曜日 0:00:00", "勤労感謝の日"}}

–国民の祝日を求める(属性つき)
on retHolidayRec(aYear as integer)
  –固定の祝日
  
if aYear < 2020 then
    set holidayList to {{"1/1", "元旦"}, {"2/11", "建国記念日"}, {"4/29", "昭和の日"}, {"5/3", "憲法記念日"}, {"5/4", "みどりの日"}, {"5/5", "こどもの日"}, {"11/3", "文化の日"}, {"11/23", "勤労感謝の日"}}
    
  else if aYear = 2020 then
    set holidayList to {{"1/1", "元旦"}, {"2/11", "建国記念日"}, {"5/3", "憲法記念日"}, {"5/4", "みどりの日"}, {"5/5", "こどもの日"}, {"11/3", "文化の日"}, {"11/23", "勤労感謝の日"}}
    
  else if aYear = 2021 then
    set holidayList to {{"1/1", "元旦"}, {"2/11", "建国記念日"}, {"5/3", "憲法記念日"}, {"5/4", "みどりの日"}, {"5/5", "こどもの日"}, {"11/3", "文化の日"}, {"11/23", "勤労感謝の日"}}
    
  else
    –2022年から
    
set holidayList to {{"1/1", "元旦"}, {"2/11", "建国記念日"}, {"5/3", "憲法記念日"}, {"5/4", "みどりの日"}, {"5/5", "こどもの日"}, {"11/3", "文化の日"}, {"11/23", "勤労感謝の日"}}
  end if
  
  
  
–天皇誕生日の計算
  
set curEmpBD to getCurEmpBitrthday(aYear) of me
  
if curEmpBD is not equal to false then
    set the end of holidayList to {curEmpBD, "天皇誕生日"}
  end if
  
  
set the end of holidayList to {get_specifiedDay(aYear, 1, 2, 2), "成人の日"} –成人の日–1月の第2月曜日
  
  
–令和2年(2020年)及び3年(2021年)における「国民の祝日」の移動について
  
if aYear = 2020 then
    set the end of holidayList to {"7/ 22", "海の日"}
  else if aYear = 2021 then
    set the end of holidayList to {"7/ 23", "海の日"}
  else
    set the end of holidayList to {get_specifiedDay(aYear, 7, 2, 3), "海の日"} –海の日–7月の第3月曜日
  end if
  
  
  
set the end of holidayList to {get_specifiedDay(aYear, 9, 2, 3), "敬老の日"} –敬老の日–9月の第3月曜日
  
  
–令和2年(2020年)及び3年(2021年)における「国民の祝日」の移動について
  
if aYear = 2020 then
    set the end of holidayList to {"7/24", "スポーツの日"}
  else if aYear = 2021 then
    set the end of holidayList to {"7/23", "スポーツの日"}
    
  else if (aYear < 2000) then
    set the end of holidayList to {"10/10", "体育の日"} –体育の日–10月10日
  else if (aYear < 2020) then
    set the end of holidayList to {get_specifiedDay(aYear, 10, 2, 2), "体育の日"} –体育の日–10月の第2月曜日
  else
    set the end of holidayList to {get_specifiedDay(aYear, 10, 2, 2), "スポーツの日"} –スポーツの日–10月の第2月曜日
  end if
  
  
–令和2年(2020年)及び3年(2021年)における「国民の祝日」の移動について
  
if aYear = 2020 then
    set the end of holidayList to {"8/10", "山の日"}
  else if aYear = 2021 then
    set the end of holidayList to {"8/8", "山の日"}
  else if aYear ≥ 2016 then
    set the end of holidayList to {"8/11", "山の日"} –山の日– 8月11日
  end if
  
  
  
set the end of holidayList to {"3/" & get_ShunbunNoHi(aYear), "春分の日"} –春分の日
  
set the end of holidayList to {"9/" & get_ShuubunNoHi(aYear), "秋分の日"} –秋分の日
  
  
  
  
set holiDate to {}
  
repeat with i in holidayList
    set holiD to date (aYear & "/" & (item 1 of i) as text)
    
set holiNum to weekday of holiD as number
    
    
–元日以外を対象とする(元旦に振替休日なし)–> いや、ある(汗)
    
–if ((item 1 of i) as text) is not "1/1" then
    
–振替休日付加処理
    
if holiNum = 1 then –祝祭日が日曜日だったら
      –日付を動かすのではなく、振替休日を追加する
      
set holiD_furikae to holiD + (1 * days)
      
set the end of holiDate to {holiD_furikae, "振替休日"}
    end if
    
–end if
    
set the end of holiDate to {holiD, item 2 of i}
    
  end repeat
  
  
  
–重複した休日が発生した場合の再振替処理  
  
–基本ルール:  振替休日を後に送る
  
–        「振替休日」が重複リストに入っていないかどうかをチェックし、振替休日の再配置を行う
  
set itemNum to 1
  
set holiDateDup to detectDuplicatesFromNestedList(holiDate, itemNum) of me
  
  
set huriList to {}
  
repeat with i in holiDateDup
    set iCount to length of i
    
repeat with ii in i
      set {aDate, aDateName} to ii
      
if aDateName = "振替休日" then
        set the end of huriList to contents of ii
      end if
    end repeat
  end repeat
  
  
set holiDate to shellSortListAscending(holiDate, 1) of me
  
set holiDateList to spritOrderedItemFromNestedList(holiDate, 1) of me
  
  
repeat with i in huriList
    set {aDate, aName} to i
    
set j to contents of i
    
set offsetDate to 1
    
repeat
      set bDate to aDate + (offsetDate * days)
      
if bDate is not in holiDateList then
        exit repeat
      end if
      
set offsetDate to offsetDate + 1
    end repeat
    
    
set iCount to 1
    
repeat with ii in holiDate
      set jj to contents of ii
      
if jj = j then
        –「複数要素一括削除サブルーチン」などという高機能すぎるサブルーチンを使用。ちょっともったいない
        
set holiDate to itemsDelete(holiDate, {iCount}) of me
      end if
      
set iCount to iCount + 1
    end repeat
    
    
set the end of holiDate to {bDate, "振替休日"}
    
  end repeat
  
  
  
–秋分の日と敬老の日の「間の日」の休日判定処理
  
–参考文献:
  
–http://ja.wikipedia.org/wiki/秋分の日
  
–国民の祝日に関する法律第3条第3項に規定する休日(例)
  
set septDL to {}
  
set the end of septDL to "9/" & get_ShuubunNoHi(aYear) of me –秋分の日
  
set the end of septDL to get_specifiedDay(aYear, 9, 2, 3) –敬老の日 –9月の第3月曜日
  
set septDL to shellSort(septDL) of me
  
if septDL = {"9/21", "9/23"} then
    set kokuminShukujitu to (aYear as string) & "/9/22"
    
set kokuminShukujitu to date kokuminShukujitu
    
set the end of holiDate to {kokuminShukujitu, "国民の祝日"}
  end if
  
  
  
–重複を解消
  
set holiDate to removeDuplicates(holiDate) of me
  
  
–最後に、並べ替えを行って仕上げ
  
set holiDate to shellSortListAscending(holiDate, 1) of me
  
  
return holiDate
end retHolidayRec

–春分の日を求める
–2000年から2099年の間まで計算可能
on get_ShunbunNoHi(aYear)
  set a to 20.69115
  
set b to (aYear – 2000) * 0.2421904
  
set c to round ((aYear – 2000) / 4) rounding toward zero
  
set d to round (a + b – c) rounding toward zero
  
return d
end get_ShunbunNoHi

–秋分の日を求める
–2000年から2099年の間まで計算可能
on get_ShuubunNoHi(aYear)
  set a to 23.09
  
set b to (aYear – 2000) * 0.2421904
  
set c to round ((aYear – 2000) / 4) rounding toward zero
  
set d to round (a + b – c) rounding toward zero
  
return d
end get_ShuubunNoHi

–指定月の第x指定曜日に該当する日付を求める(mm/dd形式)
– 曜日の指定を数値(weekday of (current date) as number)で行えるようにした。
– 曜日を「日曜日」などの日本語ローカライズド文字列で指定するのをやめた
–パラメータ: 年, 月, 曜日番号, 順番
on get_specifiedDay(aYear as integer, aMonth as integer, Youbi as integer, orderNum as integer)
  set sDat to date ((aYear & "/" & aMonth & "/1") as text)
  
set eDat to getMlenInternational(aYear, aMonth) of me
  
  
set countNum to 0
  
  
repeat with i from 1 to eDat
    set aCal to date ((aYear & "/" & aMonth & "/" & (i as text)) as text)
    
set aWeekDayNum to weekday of aCal as integer
    
if Youbi = aWeekDayNum then
      set countNum to countNum + 1
      
if countNum is orderNum then
        set aCalText to (aMonth & "/" & i as text)
        
return aCalText
      end if
    end if
  end repeat
end get_specifiedDay

–指定日の月のみ返す
on getMonth(aDat as date)
  set bDate to month of aDat
  
return bDate as integer
end getMonth

–指定日の日付のみ返す
on getDate(aDat as date)
  set bDate to day of aDat
  
return bDate as integer
end getDate

–指定日の年のみ返す
on getYear(aDat as date)
  set bDate to year of aDat
  
return bDate as integer
end getYear

–現在のカレンダーで指定年月の日数を返す(getMlenから置き換えた)
on getMlenInternational(aYear, aMonth)
  set theNSCalendar to current application’s NSCalendar’s currentCalendar() — do *not* use initWithCalendarIdentifier:
  
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:1 hour:0 minute:0 |second|:0 nanosecond:0
  
set theResult to theNSCalendar’s rangeOfUnit:(current application’s NSDayCalendarUnit) inUnit:(current application’s NSMonthCalendarUnit) forDate:theDate
  
return |length| of theResult
end getMlenInternational

–リスト中から重複項目をリストアップする
on detectDuplicates(aList)
  set aCount to length of aList
  
  
set duplicationList to {}
  
repeat aCount times
    set anItem to contents of (first item of aList)
    
set aList to rest of aList
    
if anItem is in aList then
      set the end of duplicationList to anItem
    end if
  end repeat
  
  
return duplicationList
end detectDuplicates

–リストから重複部分を除外
on removeDuplicates(aList)
  set newList to {}
  
repeat with i from 1 to (length of aList)
    set anItem to item 1 of aList
    
set aList to rest of aList
    
if {anItem} is not in aList then set end of newList to anItem
  end repeat
  
return newList
end removeDuplicates

–シェルソート
on shellSort(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 shellSort

–シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h ≤ (n – 1)) then
      repeat with i from h to (n – 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j ≥ h) and ((contents of item keyItem of item (j – h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j – h + 1) of a)
          
set j to j – h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

–シェルソートで入れ子のリストを降順ソート
on shellSortListDecending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h ≤ (n – 1)) then
      repeat with i from h to (n – 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j ≥ h) and ((contents of item keyItem of item (j – h + 1) of a) < (item keyItem of v))
          set (item (j + 1) of a) to (item (j – h + 1) of a)
          
set j to j – h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListDecending

–入れ子のリスト中から重複項目をアイテム番号つきでリストアップする
on detectDuplicatesFromNestedList(aList, itemNum)
  set aCount to length of aList
  
copy aList to orig_aList
  
  
set duplicationList to {}
  
repeat aCount times
    set anItem to contents of (first item of aList)
    
set aList to rest of aList
    
    
–指定アイテムだけのリストを毎回再生成して存在確認を行う
    
set aaList to spritOrderedItemFromNestedList(aList, itemNum) of me
    
if (contents of (item itemNum of anItem)) is in aaList then
      set the end of duplicationList to anItem
    end if
    
  end repeat
  
  
–検出した重複データを元に、該当するデータをリストアップ
  
set detectList to {}
  
repeat with i in duplicationList
    set j to contents of (item itemNum of i)
    
set detectItem to {}
    
repeat with ii in orig_aList
      set jj to contents of (item itemNum of ii)
      
      
if jj = j then
        set the end of detectItem to (contents of ii)
      end if
    end repeat
    
set the end of detectList to detectItem
  end repeat
  
  
return detectList
end detectDuplicatesFromNestedList

–入れ子のリストの全要素から指定アイテム目の要素だけを取り出してリストで返す
on spritOrderedItemFromNestedList(aList, itemNum)
  set aaList to {}
  
repeat with i in aList
    set the end of aaList to contents of (item itemNum of i)
  end repeat
  
return aaList
end spritOrderedItemFromNestedList

–リスト中の指定要素を削除して返す
on itemsDelete(aList, delNumList)
  set delLen to length of delNumList
  
  
repeat with i from 1 to delLen
    
    
set newList to {}
    
set aLen to length of aList
    
    
set ii to item i of delNumList
    
    
if ii = 1 then
      set maeList to items 2 thru aLen of aList
      
set newList to maeList
      
    else if ii = aLen then
      set maeList to items 1 thru (aLen – 1) of aList
      
set newList to maeList
      
    else
      set maeList to items 1 thru (ii – 1) of aList
      
set atoList to items (ii + 1) thru -1 of aList
      
set newList to maeList & atoList
    end if
    
    
–アイテム指定の補正
    
set delNumList to adjustItemNo(ii, delNumList) of me
    
    
set aList to newList
  end repeat
  
  
return newList
end itemsDelete

–itemsDeleteのサブルーチン
–リストに対して複数アイテムの削除を行う場合に、1つ削除した後にはアイテム指定が
–狂ってしまうため、毎回削除するたびにアイテム指定の補正を行う
–paramNumとelemListの間でのパラメータの衝突は関知しない

–項目要素補正をリストに対して行う
on adjustItemNo(paramNum, elemList)
  –項目ゼロを指定してきた場合には、そのままelemListを戻す
  
if paramNum = 0 then return elemList
  
–プラス方向のレンジ外判定は行っていない。elemListのlengthよりも大きな値は関知しない
  
set retList to {}
  
repeat with i in elemList
    set j to contents of i
    
if j > paramNum then
      set ansNum to j – 1
    else
      set ansNum to j
    end if
    
set the end of retList to ansNum
  end repeat
  
  
return retList
end adjustItemNo

–現在のカレンダーで指定年月のdate objectを返す(年、月、日、時、分、秒)
on getDateInternationalYMDhms(aYear, aMonth, aDay, anHour, aMinute, aSecond)
  set theNSCalendar to current application’s NSCalendar’s currentCalendar()
  
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 getDateInternationalYMDhms

–現在のカレンダーで指定年月のdate objectを返す(年、月、日)
on getDateInternational(aYear, aMonth, aDay)
  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

–天皇誕生日の計算
on getCurEmpBitrthday(targYear)
  –昭和、平成、令和 の誕生日定義
  
set curEmperrorsBirthday to {{"4/29", {1926, 1988}}, {"12/23", {1989, 2018}}, {"2/23", {2020, 9999}}}
  
–浩宮氏が崩御の際には、崩御年を記入
  
  
set hitF to false
  
repeat with i in curEmperrorsBirthday
    copy i to {targDate, {beginYear, endYear}}
    
if targYear ≥ beginYear and targYear ≤ endYear then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
  
if hitF = false then
    return false
  end if
  
  
return targDate
end getCurEmpBitrthday

★Click Here to Open This Script 

Posted in Calendar | Tagged 10.15savvy 11.0savvy 12.0savvy 13.0savvy 14.0savvy 15.0savvy | Leave a comment

UI Browserがgithub上でソース公開され、オープンソースに

Posted on 10月 31, 2022 by Takaaki Naganoya

ちょっと驚きの展開です。Bill Cheesemanの引退にともない、その後の展開が不安視されていたUI Browserの新たな話が上がってきました。

たしかに、Bill Cheeseman引退後のUI Browserの「あり得る」ストーリーの1つとして、(v3.x系の)Open Source化は考えないではなかったのですが、まさかBill Cheeseman本人によりすべてSwiftで書き直されたもの(v4)が、あらためてオープンソース版として公開されるとは思いませんでした。

→ UI Browser 4 on github

公開されているのは、現行のUI Browser v3.0.2よりも新しい「v4」であり、完成したものではないようです。一応、興味があったのでProjectをダウンロードしてXcodeでビルドしてみましたが、UI Browser 4を起動することはできませんでした(ビルドは通ったが、起動途中で止まる)。

PFAssistiveFrameworkなどの心臓部分もすべてSwiftで描き直されているものの、「AccessibleElement.swift」が空行を含めてわずか570行程度であったりと、その機能から推測される(巨大な)コード規模とかけ離れた内容になっていることから、「手を付けられる範囲で手をつけただけ。完成品というレベルのものではない」という印象を受けます。

ただ、作り方が「ゼロから作り直した」のではなく、「C++のプログラムを順次翻訳している最中」に見えるため、これからも順次C++からSwiftに翻訳していくのかもしれませんし、そうではないのかもしれません。

v4が動くところまで行くのに、年単位で時間がかかりそうに見えます。

このようにちゃんと引き継ぎが行われるというのは、珍しいことであり……自分だったら、ある日いきなりBlogが消えておしまいでしょう。

Posted in news | Tagged 10.15savvy 11.0savvy 12.0savvy 13.0savvy UI Browser | Leave a comment

AS関連データの取り扱いを容易にする(はずの)privateDataTypeLib

Posted on 8月 22, 2022 by Takaaki Naganoya

AS関連データの取り扱いを簡単にすることを目的に書き出した、privateDatatypeLibです。

プログラムとデータを分離して、データ記述部分を外部ファイル(設定ファイルなど)に追い出したときに、どのようなデータかを表現するための道具として試作してみました。

macOS上のデータ記述子は、

などのさまざまなデータ識別方法が存在していますが、どれも(自分の)用途には合わなかったので、検討・試作をはじめてみました。Predicatesが一番近いものの、不十分なのでいろんなデータ型や用途に拡張。あくまで自分用なので「public」などの宣言はとくに不必要と考え、縮小して処理を行なっています。

とくに、ファイルパスの処理なんて定型処理しかしないのに、わざわざ何かの表現を行う必要があるのはナンセンスですし、日付関連も割と余計な記述が多いように感じています。

また、緯度/経度のデータや座標データなども、もう少しなんとかならないかと思っています。

AppleScript名:privateDataTypeLib.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/22
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set aData to "100"
set dType to "@number"
set bData to "" –不要なケース多数。不要な場合にはヌル文字を指定
set mePath to path to me –実際には、呼び出し側で取得して指定。ライブラリ自体のパスを求めているのはテスト実行時のみ
set aRes to getParameterAndCalc(aData, dType, bData, mePath) of me

on getParameterAndCalc(aData, dType, bData, mePath)
  if dType = "@string" then
    return normalizeByNFC(aData) of me
    
  else if dType = "@number" then
    set tmpA to zenToHan(aData) of charConvKit of me –全角→半角変換
    
set a to detectOutNumStr(tmpA) of me –数字+関連・意外の文字を除外
    
return normalizeByNFC(a) of me
    
  else if dType = "@filepath.sub.foldername" then
    set aClass to class of aData –aliasだったらPOSIX pathに変換。file…はどうなんだか
    
if aClass = alias then set aData to POSIX path of aData
    
return aData & bData & "/"
    
  else if dType = "@file.comment" then
    set aStr to getFinderComment(POSIX path of mePath) of me
    
return normalizeByNFC(aStr) of me
    
  else if dType = "@file.name" then
    set aClass to class of aData
    
if aClass = alias then set aData to POSIX path of aData
    
set aStr to (current application’s NSString’s stringWithString:aData)’s lastPathComponent()’s stringByDeletingPathExtension()
    
return normalizeByNFC(aStr as string) of me
    
  else if dType = "@date.month" then
    set curDate to current date
    
set curMonth to month of curDate as number
    
return curMonth as string
    
  else
    return aData
  end if
end getParameterAndCalc

on normalizeByNFC(aStr)
  set aNSStr to current application’s NSString’s stringWithString:aStr
  
set aNFC to aNSStr’s precomposedStringWithCanonicalMapping()
  
return aNFC as string
end normalizeByNFC

–ANK文字列以外のものをそぎ落とす
on detectOutNumStr(testStr)
  set sList to characters of testStr
  
set aStr to ""
  
  
repeat with i in sList
    if detectOutNumChar(i) of me then
      set aStr to aStr & (i as string)
    end if
  end repeat
  
  
return aStr
end detectOutNumStr

on detectOutNumChar(testText)
  –Numeric + Special char
  
set ankChar to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "-", "+", "E", ","}
  
  
set _testChar to testText as Unicode text
  
  
ignoring case
    repeat with i in _testChar
      set j to contents of i
      
if j is not in ankChar then
        return false
      end if
    end repeat
  end ignoring
  
  
return true
end detectOutNumChar

–Finderコメントを取得
on getFinderComment(aPOSIX)
  set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIX
  
set aMetaInfo to current application’s NSMetadataItem’s alloc()’s initWithURL:aURL
  
set metaDict to (aMetaInfo’s valuesForAttributes:{"kMDItemFinderComment"}) as record
  
if metaDict = {} then return ""
  
set aComment to kMDItemFinderComment of (metaDict)
  
return aComment
end getFinderComment

script charConvKit
  — Created 2017-09-06 by Shane Stanley
  
— Modified 2017-09-06 by Takaaki Naganoya
  
use AppleScript
  
use framework "Foundation"
  
property parent : AppleScript
  
  
property NSString : a reference to current application’s NSString
  
property NSStringTransformFullwidthToHalfwidth : a reference to current application’s NSStringTransformFullwidthToHalfwidth
  
property NSStringTransformHiraganaToKatakana : a reference to current application’s NSStringTransformHiraganaToKatakana
  
property NSStringTransformLatinToHiragana : a reference to current application’s NSStringTransformLatinToHiragana
  
property NSStringTransformLatinToKatakana : a reference to current application’s NSStringTransformLatinToKatakana
  
property NSStringTransformToUnicodeName : a reference to current application’s NSStringTransformToUnicodeName
  
property NSStringTransformToXMLHex : a reference to current application’s NSStringTransformToXMLHex
  
  
–半角→全角変換
  
on hanToZen(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:true) as string
  end hanToZen
  
  
–全角→半角変換
  
on zenToHan(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:false) as string
  end zenToHan
  
  
–ひらがな→カタカナ変換
  
on hiraganaToKatakana(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformHiraganaToKatakana) |reverse|:false) as string
  end hiraganaToKatakana
  
  
–カタカナ→ひらがな変換
  
on katakanaToHiraganaTo(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformHiraganaToKatakana) |reverse|:true) as string
  end katakanaToHiraganaTo
  
  
–ローマ字→ひらがな変換
  
on alphabetToHiragana(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformLatinToHiragana) |reverse|:false) as string
  end alphabetToHiragana
  
  
–ひらがな→ローマ字変換
  
on hiraganaToalphabet(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformLatinToHiragana) |reverse|:true) as string
  end hiraganaToalphabet
  
  
–ローマ字→カタカナ変換
  
on alphabetToKatakana(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformLatinToKatakana) |reverse|:false) as string
  end alphabetToKatakana
  
  
–カタカナ→ローマ字変換
  
on katakanaToAlphabet(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformLatinToKatakana) |reverse|:true) as string
  end katakanaToAlphabet
  
  
–文字→Unicode Name変換
  
on characterToUnicodeName(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformToUnicodeName) |reverse|:false) as string
  end characterToUnicodeName
  
  
–Unicode Name→文字変換
  
on unicodeNameToCharacter(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformToUnicodeName) |reverse|:true) as string
  end unicodeNameToCharacter
  
  
–文字→XML Hex変換
  
on stringToXMLHex(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformToXMLHex) |reverse|:false) as string
  end stringToXMLHex
  
  
–XML Hex→文字変換
  
on xmlHexTostring(aStr)
    set aString to NSString’s stringWithString:aStr
    
return (aString’s stringByApplyingTransform:(NSStringTransformToXMLHex) |reverse|:true) as string
  end xmlHexTostring
end script

★Click Here to Open This Script 

Posted in Calendar file File path folder Library Number Text URL | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | 1 Comment

カギカッコのペア検出+エラーチェック

Posted on 8月 22, 2022 by Takaaki Naganoya

短い日本語の文章で、カギカッコ(「」)のペアがそろっているか、順番がきちんとしているか、個数が合っているかなどを検出するテスト用のAppleScriptです。

何回も同じようなScriptを書いてきたような気がします。

AppleScript名:カギカッコのペア検出+エラーチェック.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/22
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

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

set aStr to "「モーニング娘。」を表示した。「藤岡弘。」を表示。「藤岡弘。」。「藤岡弘。」"
–set aStr to "「モーニング娘。」を表示した。「藤岡弘。」を表示「。「藤岡弘。」。」「藤岡弘。」"

set kagikakkoList to {"「", "」"} –カギカッコ 開始文字、終了文字ペア。英語で言うところのダブルクォート(「“」, 「”」)
set aRes to pairKagikakkoCheckAndReturnPositionPairts(aStr, kagikakkoList) of me
–> {{1, 9}, {16, 21}, {26, 31}, {33, 38}}–正常な場合
–> false –カッコの対応についてエラーがある場合

on pairKagikakkoCheckAndReturnPositionPairts(aStr as string, kagikakkoList as list)
  set aList to {}
  
  
–カギカッコの開始文字、終了文字の位置をシーケンシャルにピックアップする
  
repeat with i in kagikakkoList
    set j to contents of i
    
set aRes to scanStrMultiple(aStr, j) of me
    
set the end of aList to aRes
  end repeat
  
–> {{1, 16, 26, 33}, {9, 21, 31, 38}}
  
  
–カギカッコの個数が合っていないかどうかチェック
  
if length of aList is not equal to length of kagikakkoList then error "Separator number error"
  
  
  
–ペアリスト作成前に、カギカッコの開始、修了の文字の個数が合っているかをチェック
  
set startLen to length of first item of aList
  
set endLen to length of second item of aList
  
if startLen is not equal to endLen then error "Separator pair number is not same"
  
  
  
–ペアリストを作成
  
set pairList to {}
  
repeat with i from 1 to (length of first item of aList)
    set item1Dat to contents of item i of (first item of aList)
    
set item2Dat to contents of item i of (second item of aList)
    
set the end of pairList to {item1Dat, item2Dat}
  end repeat
  
–> {{1, 9}, {16, 21}, {25, 32}, {27, 34}, {35, 40}}
  
  
  
–ペアリストのクロスチェック
  
repeat with i from 1 to ((length of pairList) – 1)
    set {itemA1, itemA2} to contents of item i of pairList
    
set {itemB1, itemB2} to contents of item (i + 1) of pairList
    
    
if itemA1 > itemA2 then return false
    
if itemA1 > itemB1 then return false
    
if itemA2 > itemB1 then return false
  end repeat
  
  
return pairList
end pairKagikakkoCheckAndReturnPositionPairts

on scanStrMultiple(aStr, targStr)
  set aStrLen to length of aStr
  
set tLen to (length of targStr)
  
set posOffset to 0
  
  
copy aStr to bStr
  
set aList to {}
  
  
repeat
    set aRes to offset of targStr in bStr
    
if aRes = 0 then exit repeat
    
    
if aRes is not in aList then
      set the end of aList to (aRes + posOffset)
      
set posOffset to posOffset + aRes
    end if
    
    
if posOffset ≥ aStrLen then exit repeat
    
    
set tPos to (aRes + tLen)
    
if tPos > length of bStr then
      set tPos to length of bStr
    end if
    
    
if (length of bStr) ≤ tLen then exit repeat
    
    
set bStr to text tPos thru -1 of bStr
  end repeat
  
  
return aList
end scanStrMultiple

–offset命令の実行を横取りする
on offset of searchStr in str
  set aRes to getOffset(str, searchStr) of me
  
return aRes
end offset

on getOffset(str, searchStr)
  set d to divideBy(str, searchStr)
  
if (count d) is less than 2 then return 0
  
return (length of item 1 of d) + 1
end getOffset

on divideBy(str, separator)
  set delSave to AppleScript’s text item delimiters
  
set the AppleScript’s text item delimiters to separator
  
set strItems to every text item of str
  
set the AppleScript’s text item delimiters to delSave
  
return strItems
end divideBy

★Click Here to Open This Script 

Posted in Natural Language Processing Text | Tagged 10.15savvy 11.0savvy 12.0savvy | Leave a comment

Bundle IDで指定したアプリケーションのSDEFからコマンドを抽出テスト(指定コマンドのコマンド属性取り出し)

Posted on 8月 13, 2022 by Takaaki Naganoya

アプリケーションのSDEF(AppleScript用語辞書)を解析して情報を取り出すシリーズの本命。指定コマンドの属性値を取り出すテスト用のAppleScriptです。

–> Download script with library

まだ、明確な成果が出ているわけではありませんが、こうしてアクセスして問題がないか、多くのアプリケーションの各コマンドで問題がないかを調査しているところです。

AppleScript名:Bundle IDで指定したアプリケーションのSDEFからコマンドを抽出テスト(指定コマンドのコマンド属性取り出し).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/2
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use xmlLib : script "piyoXML"
use scripting additions

script myDict
  property sdefDict : {}
end script

set (sdefDict of myDict) to {}
set aRes to parseSdefAndRetCommandStructure("com.apple.iWork.Keynote", "export") of me

on parseSdefAndRetCommandStructure(targAppBundleID, aTargCom)
  if (sdefDict of myDict) = {} then
    set aRes to parseSDEFandRetXMLStr(targAppBundleID) of me
    
set (sdefDict of myDict) to (xmlLib’s makeRecordWithXML:aRes)
  end if
  
  
set suitesList to ((sdefDict of myDict)’s valueForKeyPath:"dictionary.suite.command")
  
  
repeat with i in suitesList –SuitesでLoop
    set j to contents of i
    
    
try
      repeat with ii in j –CommandでLoop
        set jj to contents of ii
        
set tmpName to jj’s attributes’s |name|
        
        
if aTargCom is in (tmpName as list) then return jj
        
      end repeat
    on error
      return false
    end try
    
  end repeat
  
return false
end parseSdefAndRetCommandStructure

on pickUpFromToStr(aStr as string, s1Str as string, s2Str as string)
  set a1Offset to offset of s1Str in aStr
  
if a1Offset = 0 then return -1
  
set bStr to text (a1Offset + (length of s1Str)) thru -1 of aStr
  
  
set a2Offset to offset of s2Str in bStr
  
if a2Offset = 0 then return -2
  
  
set cStr to text 1 thru (a2Offset – (length of s2Str)) of bStr
  
  
return cStr as string
end pickUpFromToStr

–指定文字と終了文字に囲まれた内容を抽出
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
  
  
if anArray’s |count|() is not equal to 1 then return false
  
  
return first item of (anArray as list)
end extractStrFromTo

–SDEFをXincludeを考慮しつつ展開
on parseSDEFandRetXMLStr(targAppBundleID)
  set thePath to POSIX path of (path to application id targAppBundleID)
  
  
set aSDEFname to retAppSdefNameFromBundleIPath(thePath, "OSAScriptingDefinition") of me
  
if aSDEFname = false then return
  
  
if aSDEFname does not end with ".sdef" then set aSDEFname to aSDEFname & ".sdef"
  
set sdefFullPath to thePath & "Contents/Resources/" & aSDEFname
  
set sdefAlias to (POSIX file sdefFullPath) as alias –sdefのフルパスを求める
  
  
–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)
  
  
–XMLを文字データ化
  
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
  
  
return aDocStr2
end parseSDEFandRetXMLStr

–指定パスからアプリケーションのInfo.plist中の属性値を返す
on retAppSdefNameFromBundleIPath(appPath as string, aKey as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:(aKey)
  
if aRes = missing value then return false
  
set asRes to aRes as string
  
  
return asRes as string
end retAppSdefNameFromBundleIPath

★Click Here to Open This Script 

Posted in sdef System XML | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

Bundle IDで指定したアプリケーションのSDEF内容を表示(OSADictionary)

Posted on 8月 9, 2022 by Takaaki Naganoya

指定のBundle IDのアプリケーションのAppleScript用語辞書(sdef)から、Xincludeを解消して、外部参照していた内容を展開してHTMLに変換してWkWebViewで表示するAppleScriptです。

–> dispAppScriptDict.scptd(Bundle Script with Script Library in its bundle)

AppleScript用語辞書シリーズで、sdefの外部参照をXML系のサービスを利用して展開していましたが、OSAKitのOSADictionaryで展開できるという噂を聞きつけ、調査して試してみました。

参照した情報は、こちらのページです。

XML系のOSの機能を利用したときには発生していなかった現象ですが、Bundle IDで指定したアプリケーションが本Script実行時に起動されました。

Adobe系のアプリケーションは未検証ですが、本ScriptでAdobe系アプリケーション(InDesign、Illustrator、Photoshop)の用語辞書を、スクリプトエディタに近い状態で表示できれば、辞書の展開も大丈夫というところでしょうか。

# 辞書内容をHTMLではなくXMLとして取得したら、Xincludeは展開されていなかったので、このやり方ではダメということなんでしょう>辞書部品の外部参照の解消
# OSAKit.frameworkそのものをFinder上でこじ開けてみると、cssとxsltが存在していることがわかるので、このあたりの手順で辞書の展開を行っているようなのですが、、、

本来自分がやりたいのは、こんな用語辞書の表示ではないので、とりあえず「試してみた」というところでしょうか。

AppleScript名:Bundle IDで指定したアプリケーションのSDEFからXPathで指定したClassにアクセス(OSADictionary).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/09
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use framework "OSAKit"
use webD : script "webDialogLib"
use scripting additions

set targAppBundleID to "com.apple.iWork.Keynote" –SDEFを取り出すターゲットのアプリケーションのBundle ID

set thePath to POSIX path of (path to application id targAppBundleID)

set aSDEFname to retAppSdefNameFromBundleIPath(thePath, "OSAScriptingDefinition") of me
if aSDEFname = false then return

if aSDEFname does not end with ".sdef" then set aSDEFname to aSDEFname & ".sdef"
set sdefFullPath to thePath & "Contents/Resources/" & aSDEFname

–https://github.com/LeoNatan/Apple-Runtime-Headers/blob/
–5e50ad05dfd7d7b69fc2e0e685765fc054166b3c/macOS/Frameworks/OSAKit.framework/OSADictionary.h
set aDict to current application’s OSADictionary’s alloc()’s initWithContentsOfFile:sdefFullPath |error|:(missing value)
if aDict = missing value then return

aDict’s parse()
set aHTML to aDict’s html() as string

set paramObj to {myMessage:"AppleScript用語辞書の表示テスト", mySubMessage:"OSADictionaryで読み込んだsdefをHML化してWkWebViewで表示", htmlStr:aHTML, htmlPath:"", jsDelimiters:{"", ""}, viewSize:{600, 400}}

–webD’s browseStrWebContents:paramObj –for debug
webD’s displayWebDialog(paramObj)

–指定パスからアプリケーションのInfo.plist中の属性値を返す
on retAppSdefNameFromBundleIPath(appPath as string, aKey as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:(aKey)
  
if aRes = missing value then return false
  
set asRes to aRes as string
  
  
return asRes as string
end retAppSdefNameFromBundleIPath

★Click Here to Open This Script 

Posted in dialog OSA sdef | Tagged 10.15savvy 11.0savvy 12.0savvy | Leave a comment

新発売:AppleScript基礎テクニック集(24)フォント指定

Posted on 8月 7, 2022 by Takaaki Naganoya

電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第24巻、「フォント指定」です。PDF 34ページ。サンプルScriptのZipアーカイブを添付。

→ 販売ページ

macOS上でフォントは「PostScript Name」、「正式名称(Display Name)」で管理されており、どちらの指定も受け付けるアプリケーションもあれば、PostScript Nameだけを要求するアプリケーションもあるなどさまざまです。CocoaのAPIではPostScript Nameが利用されています。

また、フォント名を「ファミリー」と「スタイル」に分けて指定できるようにもなっており、個別に指定できるアプリケーションもありますが(Adobe InDesignなど)、これはごく一部です。

結局、アプリケーションごとに対応はまちまちですが、指定できることにはかわりありません。こうしたフォント指定について、フォント管理アプリケーションFont Bookを通じてさまざまなフォントの属性情報を取得する方法についてご紹介します。

目次

■AppleScriptにおけるフォント情報管理

フォント情報は「Font Book.app」で調べる
フォントを階層構造とコレクションで管理
これが、フォントの識別情報
AppleScriptに対応しているFont Book.app
Font Book上の選択中のフォントを取得
標準搭載、メニューからScriptを実行する機能

■Keynote/Pages/Numbersでフォント情報を指定

Keynote書類上のテキストアイテムのフォント指定
iWork apps全般では正式名称でもPS名でも可
Pagesでも正式名称/PostScript名でOK
Numbersでも正式名称/PostScript名でOK

■書式付きテキストをAppleScriptから生成

TextEditには特殊なオブジェクトで書式アクセス

■Font Book.app関連AppleScriptサンプル

FontBook.app自体のプロパティを取得
フォントライブラリ情報を取得
フォントコレクション情報を取得
フォントコンテナ情報を取得
選択中のアイテムを取得
フォントにアクセス①
フォントにアクセス②
フォントを削除

Posted in Books Font news PRODUCTS | Tagged 10.15savvy 11.0savvy 12.0savvy | Leave a comment

新発売:AppleScript基礎テクニック集(23)サブルーチン、ハンドラ

Posted on 8月 5, 2022 by Takaaki Naganoya

電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第23巻、「スクリプトメニューの使い方」です。PDF 35ページ。サンプルScriptのZipアーカイブを添付。

→ 販売ページ

AppleScriptのサブルーチンを構成する「ハンドラ」の記述方法は、普段使わないものも含めると、いろいろな書き方があります。

サブルーチンは、一度書いた有用な処理は何回でも使い回すことを目的に、使い回しやすいように清書したものです。記述量を減らすことができ、一度書いた内容は二度目からは書く必要がなく、他人が書いたサブルーチンを利用することで、生産性を大幅に上げられます。

サブルーチンの有効性を理解できたら、初級者から中級者にステップアップしたと言ってよいでしょう。

ふだんなにげなく使っていて、存在そのものを知っているのに、実際に調べてみると割と内容がてんこもりという、まさに「基礎」と呼ぶに値する内容です。

個人的には、サブルーチンのハンドラ記述は、あまりバリエーション豊富な記法を採用すべきではないと思っていて、本Blogに掲載のリストのように、極力単純な記法を採用しています。凝ったハンドラ記述をしたところで、生産性なんてこれっぽっちも向上しません。保証します。

ただ、海外で癖の強いScriptを書く連中がいて、とくにキーボードショートカットやファンクションキーからAppleScriptを呼び出すようなツールのコミュニティにいる連中の書くScriptは「なまり」がすごくて、読みにくくて頭痛がします。そうした際に、サブルーチン呼び出し記述部分を「解読」するためのスキルは、欠かせないものとなることでしょう。

目次

■AppleScriptのサブルーチン、ハンドラとは?

どの言語にもあるサブルーチン、ハンドラ
ハンドラ内の変数の取り扱い
tellブロック内で記述するハンドラ呼び出し①
tellブロック内で記述するハンドラ呼び出し②
イベントハンドラ①
イベントハンドラ②

■基礎的なハンドラ記述 on subHandler(param)

基礎的なハンドラ記述
ハンドラの情報を取得①
ハンドラの情報を取得②

■分割パラメータつきハンドラ記述 on subHandler:param

分割パラメータつきハンドラ記述

■パターン化位置パラメータつきハンドラ記述on hello(a, b, {length:l, bounds:{x, y, w, h}, name:n})

パターン化位置パラメータつきハンドラ記述

■ラベルつきハンドラ記述

パラメータの受け渡し方で2つに大別される
ラベル付きパラメータ

■予約語をオーバーライドしてハンドラ宣言

コマンド予約語をオーバーライド
オーバーライド可能な標準搭載の予約語
オーバーライドの有効範囲①
オーバーライドの有効範囲②
オプションすべてに対応するとけっこう大変

Posted in Books news | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

Bundle IDで指定したアプリケーションのSDEFからXPathで指定したClassにアクセス v2

Posted on 8月 2, 2022 by Takaaki Naganoya

Bundle IDで指定したアプリケーションのSDEF(AppleScript定義辞書)を、Xincludeを考慮しつつparseして、XPathで指定したクラスにアクセスするAppleScriptです。

KeynoteのAppleScript用語辞書の「open」コマンド、

を指定して本Scriptでデータを取り出すと、

のような出力が得られます。まだちょっと、属性値を取り出すところまで行っていませんが、つまり…指定コマンドのパラメータや、指定クラスがどのようなコマンドに応答するかなど、プログラム側からわかるようになることでしょう(多分)。

AppleScript名:Bundle IDで指定したアプリケーションのSDEFからXPathで指定したClassにアクセス v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/08/2
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

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

set targAppBundleID to "com.apple.iWork.Keynote" –SDEFを取り出すターゲットのアプリケーションのBundle ID
–set commandXPath to "//class[@name=’application’]/property"
–set commandXPath to "//command[@name=’open’]/direct-parameter"
–set commandXPath to "//class[@name=’document’]/property"
–set commandXPath to "//class[@name=’document’]/responds-to"
–set commandXPath to "//command[@name=’open’]" –Open Command–Open コマンド
set commandXPath to "//command[@name=’open’]/direct-parameter/type" –Open Command–Open コマンド

set aRes to parseSDEFandRetXPathData(targAppBundleID, commandXPath) of me
return aRes

–SDEFをXincludeを考慮しつつ展開
on parseSDEFandRetXPathData(targAppBundleID, commandXPath)
  set thePath to POSIX path of (path to application id targAppBundleID)
  
  
set aSDEFname to retAppSdefNameFromBundleIPath(thePath, "OSAScriptingDefinition") of me
  
if aSDEFname = false then return
  
  
if aSDEFname does not end with ".sdef" then set aSDEFname to aSDEFname & ".sdef"
  
set sdefFullPath to thePath & "Contents/Resources/" & aSDEFname
  
set sdefAlias to (POSIX file sdefFullPath) as alias –sdefのフルパスを求める
  
  
–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)
  
  
–XMLを文字データ化
  
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 dRes to my extractFrom:theXMLDoc matchingXPath:commandXPath
  
return dRes
end parseSDEFandRetXPathData

–指定のNSXMLDocumentから、指定のXPathでアクセスして内容を返す
on extractFrom:theNSXMLDocument matchingXPath:theQuery
  set attStrings to {} — where attributes will be stored
  
set theXMLOutput to current application’s NSXMLElement’s alloc()’s initWithName:"output" — found nodes added to this
  
  
set {theResults, theNSError} to (theNSXMLDocument’s nodesForXPath:theQuery |error|:(reference)) — query
  
  
if theResults is not missing value then
    repeat with anNSXMLNode in (theResults as list)
      anNSXMLNode’s detach() — need to detach first
      
if anNSXMLNode’s |kind|() as integer = current application’s NSXMLAttributeKind then — see if it’s an attribute or node
        set end of attStrings to (anNSXMLNode’s stringValue()) as {text, list, record}
      else
        (theXMLOutput’s addChild:anNSXMLNode) — add node
      end if
    end repeat
    
    
return (theXMLOutput’s XMLStringWithOptions:(current application’s NSXMLNodePrettyPrint)) as {text, list, record}
  else
    return missing value
  end if
end extractFrom:matchingXPath:

–指定パスからアプリケーションのInfo.plist中の属性値を返す
on retAppSdefNameFromBundleIPath(appPath as string, aKey as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:(aKey)
  
if aRes = missing value then return false
  
set asRes to aRes as string
  
  
return asRes as string
end retAppSdefNameFromBundleIPath

★Click Here to Open This Script 

Posted in sdef System XML | Tagged 10.15savvy 11.0savvy 12.0savvy Keynote | 1 Comment

2005年に作ったゲーム「length」

Posted on 7月 23, 2022 by Takaaki Naganoya

はるかかなた昔、2005年に作ったゲームのソースが出てきました。日本語でコメントを書いてあったのですが、文字化けしていて作った本人にも読めません。作ったまま忘れていたので、掲載しておきます。

# ユーザー名を求める処理だけMac OS X→OS X→macOSと推移してそのまま動作しなかったので、書き換えをおこなっています

ゲーム名は「length」です。指定の文字数のアルファベットを入力すると、システム辞書を検索して、そのアルファベットで始まる英単語を検索します。

ゲームルールは「Count Up」と「Count Down」の2種類があり、入力文字ではじまる英単語がだんだん増えていくように解答するのが「Count Up」、だんだん少なくなるように答えていくのが「Count Down」モードです。


▲ゲームタイトル表示


▲入力アルファベット数の選択。長くなるとヒットする単語が少なくなるので難しい。2か3ぐらいが適当?


▲ゲームルール選択。ヒットする単語数が少なくなっていくように答える「countDown」と、増えていくように答える「countUp」。countUpのほうが簡単


▲ゲームスタート


▲ここで文字入力


▲1単語だけヒットした


▲続いて文字入力


▲5単語ヒットした


▲424単語ヒット!


▲389単語ヒット! 前の答えよりも減ってしまった! Count up失敗!


▲Count Upに失敗したので、ゲームオーバー


▲ハイスコア入力

AppleScript名:length v0.5.scpt
【コメント】 ?uLeng???Q?[??v0.4?v
2005?N 9?? 11?? ???j?? 11:37:00 PM?Åc?o?[?W?????A?b?v

?uLeng???Q?[??v0.3?v
2005?N 9?? 11?? ???j?? 10:05:51 PM?Åc?o?[?W?????A?b?v


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property prefFileName : "jp.piyomarusoft.length"
property dataVer : 1.0
property emptyHscore : {{{0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}}, {{0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}, {0, "Piyomaru", "2005/9/5", {}}}}

display dialog ("Length GAME" & return & return & "version 1.0 By Piyomaru Software") buttons {"OK"} default button 1 giving up after 3 with title "Welcome!"

set lenList to {2, 3, 4, 5, 6, 7, 8}
set aRes to (choose from list lenList with prompt "please select the length of battle keyword" default items 3)
if aRes = false then return
set bRes to aRes as number
set histNum to {}
set histKeywords to {}
set scoreNum to 0
set ansHist to {}

set ruleList to {"Count Down", "Count Up"}
set ruleRes to (choose from list ruleList with prompt "Select Game Rule" default items "Count Up")
if ruleRes = false then return
set ruleRes to ruleRes as string

if ruleRes = "Count Down" then
  –Count Down
  
set prevNum to 9999999
else
  –Count Up
  
set prevNum to 0
end if

—ÉnÉCÉXÉRÉAÇÃämîFÇ®ÇÊÇ—ÉnÉCÉXÉRÉAèÓïÒÇÃê›íË
set hsList to writeHighScore(0, bRes, "", "", {}, ruleRes) of me
set highScore to item 1 of hsList
set greatPerson to item 2 of hsList

display dialog "GAME START" buttons {"OK"} default button 1 giving up after 2

—ÉÅÉCÉìÉãÅ[Év
repeat
  
  
—ÉLÅ[ÉèÅ[Éhì¸óÕÉãÅ[Évïîï™
  
repeat
    if length of ansHist is not equal to 0 then
      —í èÌèàóù
      
set aText to "History: [" & retArrowText(histNum) of me & "]" & return & return
    else
      —èââÒÇÃÇ›
      
set aText to ""
    end if
    
set titleText to "LENGTH GAME (" & ruleRes & " MODE) "
    
set mesText to ("SCORE:" & scoreNum as string) & return & return & aText & ("Input some keyword in English" & " ( Just " & bRes as string) & " characters.)"
    
set a to text returned of (display dialog mesText default answer "" with title titleText)
    
    
—ï∂éöéÌófiÇÉ`ÉFÉbÉN
    
set kRes to checkAN(a) of me
    
if kRes = false then
      display dialog "Wrong Character…." buttons {"OK"} default button 1
    else
      —í∑Ç≥ÇÉ`ÉFÉbÉN
      
if (length of a) is not equal to bRes then
        set tmpRes to (display dialog "Ooops!" & return & "The length of your keyword is not equal to " & aRes & "!" & return & "Try another keyword." buttons {"QUIT", "Again!"} default button 2 with title "Wrong Length")
        
        
if tmpRes = "QUIT" then
          display dialog "—Goodbye—" buttons {"OK"} default button 1 giving up after 3
          
return
        end if
      else
        —âflãéÇÃâÒìöÇ∆èdï°ÇµÇƒÇ¢Ç»Ç¢Ç©É`ÉFÉbÉN
        
if a is not in ansHist then
          exit repeat
        else
          set tmpRes to (display dialog "Ooops! " & a & " is already answerd! Try another word." buttons {"QUIT", "Again!"} default button 2 with title "Wrong Keyword")
          
          
if tmpRes = "QUIT" then
            display dialog "—Goodbye—" buttons {"OK"} default button 1 giving up after 3
            
return
          end if
        end if
      end if
    end if
  end repeat
  
  
–lookÉRÉ}ÉìÉhÇ≈ÉqÉbÉgÉLÅ[ÉèÅ[ÉhêîÇìæÇÈ
  
set ansRes to getHitWords(a) of me
  
  
—DZDZǩÇÁìñÇΩÇËîªíËÇ∆ǩǢÇÎÇ¢ÇÎ
  
if ruleRes = "Count Down" then
    –Count DownÇÃèÍçá
    
if ansRes < prevNum and ansRes is not equal to 0 then
      set scoreNum to scoreNum + 1
      
set prevNum to ansRes
    else
      —ÉQÅ[ÉÄÉIÅ[ÉoÅ[ÇÃèàóù
      
set tmpRes to (display dialog ("You lose!" & return & " SCORE:" & scoreNum as string) buttons {"OK"} default button 1)
      
      
—ÉnÉCÉXÉRÉAèàóù
      
if highScore < scoreNum then
        —ÉnÉCÉXÉRÉAÉâÅ[ÇÃñºëOÇÃéÊìæÇæÇØ
        
set greatPerson to recHighScore(scoreNum, highScore) of me
        
—é¿ç€Ç…ÉtÉ@ÉCÉãÇ…îΩâf
        
set aDate to do shell script "date +%Y/%m/%d"
        
set dummyList to writeHighScore(scoreNum, bRes, greatPerson, aDate, {ansHist, histNum}, ruleRes) of me
      end if
      
—èIóπ
      
return
    end if
  else
    –Count UpÇÃèÍçá
    
if ansRes > prevNum then
      set scoreNum to scoreNum + 1
      
set prevNum to ansRes
    else
      —ÉQÅ[ÉÄÉIÅ[ÉoÅ[ÇÃèàóù
      
set tmpRes to (display dialog ("You lose!" & return & " SCORE:" & scoreNum as string) buttons {"OK"} default button 1)
      
      
—ÉnÉCÉXÉRÉAèàóù
      
if highScore < scoreNum then
        —ÉnÉCÉXÉRÉAÉâÅ[ÇÃñºëOÇÃéÊìæÇæÇØ
        
set greatPerson to recHighScore(scoreNum, highScore) of me
        
—é¿ç€Ç…ÉtÉ@ÉCÉãÇ…îΩâf
        
set aDate to do shell script "date +%Y/%m/%d"
        
set dummyList to writeHighScore(scoreNum, bRes, greatPerson, aDate, {ansHist, histNum}, ruleRes) of me
      end if
      
—èIóπ
      
return
    end if
  end if
  
  
set the end of ansHist to a
  
set the end of histNum to ansRes
  
end repeat

—ï∂éöéÌófiÅiÉAÉãÉtÉ@ÉxÉbÉgÅjÇÃÉ`ÉFÉbÉN
on checkAN(aKeyword)
  set anList to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
  
set aKeyword to aKeyword as Unicode text
  
set aKeyword to aKeyword as string
  
set kList to characters of aKeyword
  
repeat with i in kList
    ignoring case
      if i is not in anList then
        return false
      end if
    end ignoring
  end repeat
  
return true
end checkAN

on recHighScore(scoreNum, highScore)
  if scoreNum > highScore then
    set highScore to scoreNum
    
set myShortName to word 1 of (do shell script "who am i")
    
set myHomeDirectory to do shell script "echo ~"
    
set theResponse to current application’s NSFullUserName() as string
    
–set getFullNameScript to "nicl . -read /users/" & myShortName & " realname"
    
–set theResponse to do shell script getFullNameScript
    
set myFullName to (characters 11 through (length of theResponse) of theResponse) as string
    
set pRes to text returned of (display dialog "Input Your Name:" default answer myFullName with title "You made high-score!!")
    
if pRes = false or pRes = "" then
      set greatPerson to "Anonymous"
    else
      set greatPerson to pRes as string
    end if
  end if
  
  
return greatPerson
  
end recHighScore

on retArrowText(aList)
  set aText to ""
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to " -> "
  
set aText to aList as text
  
set AppleScript’s text item delimiters to curDelim
  
return aText
end retArrowText

on getHitWords(a)
  set c to ""
  
set b to ""
  
try
    set b to do shell script "look " & a & " | wc -l"
    
set c to do shell script "look " & a
    
if (b as number) > 30 then
      set cList to paragraphs of c
      
      
if b as number > 300 then
        set limitNum to 300
      else
        set limitNum to b as number
      end if
      
      
set cItem to items 1 thru limitNum of cList
      
      
set curDelim to AppleScript’s text item delimiters
      
set AppleScript’s text item delimiters to ", "
      
set ccItem to cItem as string
      
set AppleScript’s text item delimiters to curDelim
      
      
set c to ccItem
    end if
    
display dialog b & " Hits!" & return & c
  on error
    display dialog "0 hits" buttons {"OK"} default button 1
    
return 0
  end try
  
return b as number
end getHitWords

—ó^ǶÇΩÉfÅ[É^Ç™ÉnÉCÉXÉRÉAÇ…äYìñÇ∑ÇÈèÍçáÇ…ÇÕÅAǪÇÃé|ï\é¶ÇµÇ¬Ç¬ÉfÅ[É^Ç…ãLò^Ç∑ÇÈ

—åãâ Ç∆ǵǃéwíËÉRÅ[ÉXÇÃÉnÉCÉXÉRÉAÉfÅ[É^Çï‘ǵǃÇ≠ÇÈÇÃÇ≈ÅA
—Ç∆ÇËdžǶÇ∏ÅAÉnÉCÉXÉRÉAÇ…Ç»ÇÁÇ»Ç≥ǪǧǻÉfÅ[É^Çì¸ÇÍǃåƒÇ—èoÇπÇŒ
—ÉnÉCÉXÉRÉAÇÃämîFÇ™çsǶÇÈ

on writeHighScore(aScore, aLength, aPerson, aDate, aHist, aRule)
  set pPath to path to library folder from user domain
  
set pPath to (pPath as string) & "Preferences:"
  
set pPath to pPath as Unicode text
  
set pFile to pPath & prefFileName
  
  
tell application "Finder"
    if file "jp.piyomarusoft.length" of alias pPath exists then
      —Ç∑Ç≈Ç…ê›íËÉtÉ@ÉCÉãÇ™ë∂ç›Ç∑ÇÈèÍçá
      
try
        set hScore to read alias pFile as list –anAliasÇ…ÇÕÉtÉ@ÉCÉãÉGÉCÉäÉAÉXÇ™ì¸Ç¡ÇƒÇ¢ÇÈ
      on error
        —âΩÇÁÇ©ÇÃÉtÉ@ÉCÉãä÷åWÇÃÉGÉâÅ[Ç™î≠ê∂ǵÇΩèÍçáÇ÷ÇÃëŒèà
        
set hScore to emptyHscore
      end try
    else
      —Ç‹Çæê›íËÉtÉ@ÉCÉãÇ™ë∂ç›ÇµÇ»Ç¢èÍçá
      
—ïœêîÇÃèâä˙âª
      
–item1 is count up, item2 is Count down
      
set hScore to emptyHscore
    end if
  end tell
  
  
–display dialog aRule
  
  
if aRule is "Count Up" then
    set iSel1 to 1
  else
    set iSel1 to 2
  end if
  
  
set realLength to (aLength – 1)
  
  
if (item 1 of item realLength of item iSel1 of hScore) < aScore then
    –display dialog "You made High-Score" buttons {"OK"} default button 1
    
set item realLength of item iSel1 of hScore to {aScore, aPerson, aDate, aHist}
    
set aRes to write_to_file(hScore, pFile, false) of me
    
if aRes = false then
      display dialog "File I/O Error!" buttons {"OK"} default button 1
      
return
    else
      (*
      –
ÉtÉ@ÉCÉãÉ^ÉCÉvÇèëÇ´ä∑ǶǃÅAÉeÉLÉXÉgÉGÉfÉBÉ^Ç≈äJÇ©ÇÍÇÈDZÇ∆ÇñhÇÆÇΩÇflÇÃÉeÉXÉg
      do shell script "sync"
      –set anAlias to pFile as alias
      tell application "Finder"
        –set kind of file pFile to ""
        –set file type of file pFile to ""
        –set file creator of file pFile to ""
      end tell
      *)

    end if
  end if
  
  
set retList to item realLength of item iSel1 of hScore
  
return retList
  
end writeHighScore

—ÉtÉ@ÉCÉãÇÃí«ãLÉãÅ[É`ÉìÅuwrite_to_fileÅv
—í«ãLÉfÅ[É^ÅAí«ãLëŒè€ÉtÉ@ÉCÉãÅAbooleanÅitrueÇ≈í«ãLÅj
on write_to_file(this_data, target_file, append_data)
  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 write_to_file

★Click Here to Open This Script 

Posted in GAME | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

新発売:AppleScript基礎テクニック集(22)スクリプトメニューの使い方

Posted on 7月 21, 2022 by Takaaki Naganoya

電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第22巻、「スクリプトメニューの使い方」です。PDF 33ページ。サンプルScriptのZipアーカイブを添付。

→ 販売ページ

macOSには「ジャンルごとに区分け」「アプリケーションごとに内容を切り替え」「フォルダ構造がそのまま階層メニューとして表示される」スクリプトメニューという、実行専用の機能を標準搭載しています。

決められたフォルダ以下の内容がそのままメニューに表示され、フォルダに入れたAppleScriptのファイル名やフォルダ名がそのままメニュー項目として表示され、選択したAppleScriptを実行できるようになっています。

ただ、漫然とAppleScriptをスクリプトメニューに入れただけでは、時間がたつと処理内容を忘れてしまいがちです。そこで、スクリプトメニューからAppleScriptを選択する際に装飾キー(Control)を押しておくとAppleScript書類の「説明」欄の内容をダイアログ表示するライブラリを本書執筆時に新規作成。これで、「何を入れたか忘れがち」なスクリプトメニュー生活が快適になります。

また、このスクリプトメニュー用のテンプレートを添付し、スクリプトエディタの「テンプレートから新規作成」でヘルプ表示対応のAppleScript書類を作成できます。

便利なスクリプトメニューを今日からはじめてみましょう! PDF 33ページ、サンプルScript Zipアーカイブ添付

目次

■階層メニュー型AppleScriptランチャー「スクリプトメニュー」

標準搭載、メニューからScriptを実行する機能
タイプ別、さまざまなAppleScript実行環境
OS標準搭載AppleScript実行環境の比較
スクリプトメニューの有効化
3段階で管理されるスクリプト・フォルダ
アプリケーション専用のスクリプトフォルダを作成
スクリプト実行中のインジケータ
スクリプト以外のものも入れられます
装飾キーを押しながらScriptを実行すると…

■スクリプトメニューを構成

スクリプトメニューを構成すること自体は簡単
階層フォルダを利用してファイル名を記述
パラメータを書き換えたスクリプトを複数用意

■スクリプトメニューならではの利用ノウハウ

間違ったオブジェクトの選択に備える
フローティングパレットを利用したほうがよい例も
ヘルプ機能がないことへの備え
AppleScriptでヘルプ表示を実装
テンプレートからヘルプつきスクリプトを新規作成
スクリプトメニューQ&A
機能強化版のシェアウェア「FastScripts 3」

Posted in Books news PRODUCTS | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

display text view Script Library v2.2をリリース

Posted on 7月 21, 2022 by Takaaki Naganoya

display text view Script Libraryをバージョンアップしました(v2.2)。いま書いているAppleScript基礎テクニック集の「スクリプトメニューの使い方」で本ライブラリの機能を利用しているために、サンプルScriptを記述したときにいろいろ問題を見つけました。

–> Download displayTextView (To ~/Library/Script Libraries/)

主に、日本語の一部の文字の連なりが組文字として表示されてしまうという問題で、

のように「ます」が「〼」、株式会社が1文字で表示されるという状況でした。

v2.2ではこれを修正したため、

のようになっています。

Posted in Library news | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

display text view Script Library v2.1をリリース

Posted on 7月 20, 2022 by Takaaki Naganoya

display text view Script Libraryを早速バージョンアップしました(v2.1)。

–> Download v2.1 displayTextView.scptd

ダイアログのボタンに「Cancel」と「OK」がついていましたが、「Cancelボタンはいらないよね」という話になって削除しました。

ヘルプボタンっぽいものがついていて、テストで実装したままになっていましたが、これを本ライブラリを使用しているメッセージを出すように文面を変更しました。

ThemeがLight Modeのときのテキストビューの背景色を黒から灰色に変更しました。

Posted in Library news | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

display text view Script Library v2.0をリリース

Posted on 7月 19, 2022 by Takaaki Naganoya

display text view Script Library v2.0をリリースしました。同ライブラリは、OSが提供するNSTextViewを用いて、大きな文字を、指定フォント、指定サイズ、指定色で表示/入力することが目的です。

→ display text view Script Library v2.0をダウンロード

本ライブラリのAppleScript用語辞書には、本Blog同様にURLリンクつきのサンプルAppleScriptを掲載してあります。

本ライブラリは、CotEditor PowerPackや、現在執筆中の「AppleScript基礎テクニック集(22)スクリプトメニューの使い方」にて、スクリプトメニューに収録したAppleScriptの使い方を説明するのに、AppleScriptの「説明」欄に書いておいた内容を、Controlキーなどを押しながらメニュー選択することで大きな文字で表示する、という用途のために改修したものです。

アラートダイアログをスクリプトメニューなどのGUIなしAppleScript実行環境から表示させたときに、ダイアログ自体が最前面に表示されない問題への対策を行ってあります。

また、以前のバージョンからの機能追加で、テキスト表示色の指定が行えるようになっています。

Posted in Library news PRODUCTS | Tagged 10.15savvy 11.0savvy 12.0savvy | Leave a comment

新発売:AppleScript基礎テクニック集(21)Cocoa Scripting

Posted on 7月 15, 2022 by Takaaki Naganoya

電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第21巻、「Cocoa Scripting」です。PDF 42ページ。サンプルScriptのZipアーカイブを添付。

→ 販売ページ

Cocoa Scriptingについては、既刊の「Cocoa Scripting Course」があり、同書の冒頭の入門部分を再編集したものが本書です。

macOS 10.10以降、すべてのAppleScriptの実行環境において、Cocoa呼び出しの機能がサポートされました。いわゆる、Cocoa-Bridgeされた言語になったのです。

Cocoaのすべての機能を呼び出せるわけではないですし、主にmacOSのFoundationとAppKitの範囲内ですが、一部の機能が呼び出せるだけでも機能は膨大で、かつ、これまでに無理やり間に合わせで組んでいたような内容が、本物を呼べるようになり、AppleScriptの世界に質と量と処理速度の面で大きな変化をもたらしました。

Cocoaのオブジェクトに特有の挙動……オブジェクトの生成に専用のメソッドを利用し、属性値を取り出すのにもメソッド呼び出しが必要。複数のオブジェクトが同じことを確認するのに、上位クラスで定義されている照合メソッドを呼び出す必要があるなど、実際に使ってみるとそんなに難しくはないと感じました(量が多くて面倒なだけで)。

目次

■Cocoa Scriptingとは?

Cocoa Scriptingは何のために?
Cocoa Scriptingってどういうもの?
Cocoa Scriptingの実際
Cocoa Scriptingの威力
Cocoa Scriptingのメリット
Cocoa Scriptingに必要なもの
Cocoa Scriptingまとめ
Cocoa Scripting9つの誓い

■Cocoa Scriptingに適したmacOSの選定

Cocoa Scripting環境の進化の歴史
Cocoa Scriptingに適したmacOS
参考資料:AppleScriptランタイム環境情報
SIP解除の是非

■Cocoa Scriptingのプログラミングスタイル

開発・実行環境のちがい
処理手順の違い
メインスレッド実行が必須な機能への対処
delegation, notification
実行環境の違いによる書き換え
AppleScriptでCocoaオブジェクトを呼び出すと…
サブルーチン記述
Objective-C風ハンドラにおけるme/my記述
クラス拡張(継承)
高速なCocoa Scriptを書くためには
アプリケーションとの相互乗り入れに注意
暗黙の型変換
一部のAppleScript内蔵コマンドで書き換えが必要
計算の優先順位を示すカッコを修正
オブジェクトの数え方
Application ScriptingとCocoa Scripting

Posted in Books news | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

新発売:AppleScript基礎テクニック集(20)コンパイル(構文確認)

Posted on 7月 14, 2022 by Takaaki Naganoya

電子書籍の新刊を発売しました。「AppleScript基礎テクニック集」の第20巻、「コンパイル(構文確認)」です。PDF 32ページ。

→ 販売ページ

スクリプトエディタのウィンドウに、思わせぶりに配置されている「コンパイル」コマンドのボタン。

この「コンパイル」というのは、世間一般的には、プログラム言語を実行コードに変換する作業です。SwiftやObjective-Cなどの言語で「コンパイル」といったら普通は実行コードへの変換です。

しかし、スクリプト言語で、かつインタプリタ(逐次実行)型言語であるAppleScriptにおいて、その意味は少し異なっています。AppleScriptのコンパイルとは、構文確認+中間コードへの変換です。

また、AppleScriptの実行処理系が演算の優先順位の指定を必要とした場合には、どこか適当な(正確ではなくあてずっぽうという意味で)場所にカッコを補います。

コンパイル時の構文チェックは、AppleScriptの最低限のお約束的な文法チェックだけなので、対象のアプリケーションのオブジェクト階層や、コマンドを実行する対象のオブジェクトが正しいか、といった厳密なチェックは行われません。実行して確認する必要があります。コンパイル(構文確認)の挙動は独特で、誰もが知っておくべき内容です。

目次

■コンパイル(構文確認)とは?

AppleScriptのコンパイル(構文確認)とは?
最低限の構文チェック
ライブラリ、Frameworkのチェック
OS(AppleScript)互換性チェック
実行環境チェック
中間コードへの置き換え
構文色分け設定にもとづいて書式適用

■コンパイル(構文確認)で行われる入力内容補完

コンパイル(構文確認)時に大/小文字を書き換え
空白文字,インデント文字の置き換え
if, tell, repeatなどのブロックの入力補完
特殊記号の置き換え
パラメータのboolean表記を置き換え
列挙パターン表記の置き換え ほか

■コンパイル(構文確認)で行われる演算優先順位を示すカッコの補足

演算優先順位を示すカッコを補う①
演算優先順位を示すカッコを補う②

■コンパイル(構文確認)で行われる正しいアプリケーション名への置き換え

実行環境にアプリケーションが存在しない場合
バンドルIDが同じで名称変更になった場合

Posted in Books news | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

Common Elements Libをv1.3aにアップデート

Posted on 7月 12, 2022 by Takaaki Naganoya

対象のキーワードの構成情報を分解して、2つのキーワードの共通要素をリストアップする「マッキー演算」を行うライブラリ「Common Elements Lib」をアップデートしました。

–> Common Elements Libをダウンロード(v1.3a)

マッキー演算とは、「槇原敬之」と「SMAP」の共通項を求め、結果に「世界に一つだけの花」をリストアップする処理です(ほかにも出てきますが)。

–> {“第58回NHK紅白歌合戦”, “木村拓哉”, “東京都”, “ニッポン放送”, “テレビ朝日”, “ミリオンセラー”, “大阪城ホール”, “インターネットアーカイブ”, “社長”, “ミュージックステーション”, “ケンタッキーフライドチキン”, “スポーツニッポン”, “日刊スポーツ”, “第42回NHK紅白歌合戦”, “リクルートホールディングス”, “エフエム東京”, “日本ゴールドディスク大賞”, “フジテレビジョン”, “J-POP”, “小倉博和”, “世界に一つだけの花”, “We are SMAP!”, “日本”, “日本武道館”, “ISBN”}

WikipediaのMedia APIを用いて問い合わせを行って計算を行います。そのため、(Wikipedia上における当該項目の記事内容の変化によって)実行時期によって演算結果に差が出ます。

アップデート理由は、前バージョンではインターネット接続確認を「http://www.google.com」に対して行っていたところに、このドメインに対してhttp経由でのアクセスが行えないようになったので、エラーを起こすようになりました。

このドメインにhttps経由でアクセスするよう変更しました。

Posted in Internet Library list PRODUCTS REST API | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy | Leave a comment

Post navigation

  • Older posts

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

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 13.6.5 AS系のバグ、一切直らず
  • CotEditorで2つの書類の行単位での差分検出
  • Apple純正マウス、キーボードのバッテリー残量取得
  • macOS 15, Sequoia
  • 初心者がつまづきやすい「log」コマンド
  • ディスプレイをスリープ状態にして処理続行
  • 指定のWordファイルをPDFに書き出す
  • Adobe AcrobatをAppleScriptから操作してPDF圧縮
  • メキシカンハットの描画
  • 与えられた文字列の1D Listのすべての順列組み合わせパターン文字列を返す v3(ベンチマーク用)
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • macOS 13 TTS環境の変化について
  • 2023年に書いた価値あるAppleScript
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • 可変次元のベクトルに対応したコサイン類似度計算
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • NaturalLanguage.frameworkでNLEmbeddingの処理が可能な言語をチェック

Tags

10.11savvy (1102) 10.12savvy (1243) 10.13savvy (1392) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (206) 13.0savvy (163) 14.0savvy (112) 15.0savvy (89) CotEditor (64) Finder (51) iTunes (19) Keynote (115) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (19) NSImage (41) NSJSONSerialization (21) NSMutableArray (62) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (117) NSURL (97) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (71) Pages (53) Safari (44) Script Editor (26) 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
  • 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
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • 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
  • 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)
  • 未分類

アーカイブ

  • 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