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

macOS 15でも変化したText to Speech環境

Posted on 10月 9, 2024 by Takaaki Naganoya

macOS 15では、大幅にText To Speech環境が変わりました。従来のTTS音声キャラクタにくわえて、Speechify社の「Eloquence Text to Speech」のOEM供給を受けた(?)TTS音声が多数追加されているようです。

# Eloquenceという名前のTTSが、オープンソース系とか複数存在しているのでOEMというわけでもなさそう?

# よく見たら、macOS 13でもEloquenceのTTS Voiceが存在していることを確認。気づいただけだったのか。

EloquenceによるTTS音声は、何かの言語専用というわけでなく複数言語に対応しているようです(1つで複数言語対応というわけではなく、複数言語バージョンが提供されている模様)。com.apple.eloquenceではじまるIDのTTSキャラクタがOEM供給を受けているものだと見ています。

# オープンソース系の(for Android)Eloquenceだとサポートする言語が少なかったりして(日本語はなかった)、このいろんな言語をサポートしているEloquence TTSはいったい何なんだろうかと、、、、

これらをAppleScriptのsayコマンドで指定することはできませんが、システム設定で読み上げキャラクタに指定しておけば、デフォルト音声を用いての読み上げで利用できそうです(Siri系のTTSキャラクタはこうして利用できていました)。

TTSキャラクタについては、macOSのメジャーアップデートごとに増加しており、macOS 15では209に達しています(macOS 11では50、macOS 13では174)。

AppleScript名:現在利用可能なTTSボイスIDの一覧(macOS 15)..scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/06/09
—
–  Copyright © 2020 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 aSynth to current application’s NSSpeechSynthesizer’s availableVoices() as list
–> macOS 15 (209)
— {"com.apple.speech.synthesis.voice.Agnes", "com.apple.speech.synthesis.voice.Albert", "com.apple.speech.synthesis.voice.Alex", "com.apple.voice.compact.it-IT.Alice", "com.apple.voice.compact.en-US.Allison", "com.apple.voice.enhanced.en-US.Allison", "com.apple.voice.compact.sv-SE.Alva", "com.apple.voice.compact.fr-CA.Amelie", "com.apple.voice.premium.fr-CA.Amelie", "com.apple.voice.compact.ms-MY.Amira", "com.apple.voice.compact.de-DE.Anna", "com.apple.voice.compact.en-US.Ava", "com.apple.voice.enhanced.en-US.Ava", "com.apple.voice.premium.en-US.Ava", "com.apple.speech.synthesis.voice.BadNews", "com.apple.speech.synthesis.voice.Bahh", "com.apple.speech.synthesis.voice.Bells", "com.apple.speech.synthesis.voice.Boing", "com.apple.speech.synthesis.voice.Bruce", "com.apple.speech.synthesis.voice.Bubbles", "com.apple.voice.compact.he-IL.Carmit", "com.apple.speech.synthesis.voice.Cellos", "com.apple.voice.enhanced.fr-CA.Chantal", "com.apple.voice.compact.id-ID.Damayanti", "com.apple.voice.compact.en-GB.Daniel", "com.apple.voice.enhanced.en-GB.Daniel", "com.apple.voice.compact.bg-BG.Daria", "com.apple.speech.synthesis.voice.Deranged", "com.apple.eloquence.de-DE.Eddy", "com.apple.eloquence.en-GB.Eddy", "com.apple.eloquence.en-US.Eddy", "com.apple.eloquence.es-ES.Eddy", "com.apple.eloquence.es-MX.Eddy", "com.apple.eloquence.fi-FI.Eddy", "com.apple.eloquence.fr-CA.Eddy", "com.apple.eloquence.fr-FR.Eddy", "com.apple.eloquence.it-IT.Eddy", "com.apple.eloquence.ja-JP.Eddy", "com.apple.eloquence.ko-KR.Eddy", "com.apple.eloquence.pt-BR.Eddy", "com.apple.eloquence.zh-CN.Eddy", "com.apple.eloquence.zh-TW.Eddy", "com.apple.voice.compact.nl-BE.Ellen", "com.apple.voice.compact.en-US.Evan", "com.apple.voice.enhanced.en-US.Evan", "com.apple.eloquence.de-DE.Flo", "com.apple.eloquence.en-GB.Flo", "com.apple.eloquence.en-US.Flo", "com.apple.eloquence.es-ES.Flo", "com.apple.eloquence.es-MX.Flo", "com.apple.eloquence.fi-FI.Flo", "com.apple.eloquence.fr-CA.Flo", "com.apple.eloquence.fr-FR.Flo", "com.apple.eloquence.it-IT.Flo", "com.apple.eloquence.ja-JP.Flo", "com.apple.eloquence.ko-KR.Flo", "com.apple.eloquence.pt-BR.Flo", "com.apple.eloquence.zh-CN.Flo", "com.apple.eloquence.zh-TW.Flo", "com.apple.speech.synthesis.voice.Fred", "com.apple.speech.synthesis.voice.GoodNews", "com.apple.eloquence.de-DE.Grandma", "com.apple.eloquence.en-GB.Grandma", "com.apple.eloquence.en-US.Grandma", "com.apple.eloquence.es-ES.Grandma", "com.apple.eloquence.es-MX.Grandma", "com.apple.eloquence.fi-FI.Grandma", "com.apple.eloquence.fr-CA.Grandma", "com.apple.eloquence.fr-FR.Grandma", "com.apple.eloquence.it-IT.Grandma", "com.apple.eloquence.ja-JP.Grandma", "com.apple.eloquence.ko-KR.Grandma", "com.apple.eloquence.pt-BR.Grandma", "com.apple.eloquence.zh-CN.Grandma", "com.apple.eloquence.zh-TW.Grandma", "com.apple.eloquence.de-DE.Grandpa", "com.apple.eloquence.en-GB.Grandpa", "com.apple.eloquence.en-US.Grandpa", "com.apple.eloquence.es-ES.Grandpa", "com.apple.eloquence.es-MX.Grandpa", "com.apple.eloquence.fi-FI.Grandpa", "com.apple.eloquence.fr-CA.Grandpa", "com.apple.eloquence.fr-FR.Grandpa", "com.apple.eloquence.it-IT.Grandpa", "com.apple.eloquence.ja-JP.Grandpa", "com.apple.eloquence.ko-KR.Grandpa", "com.apple.eloquence.pt-BR.Grandpa", "com.apple.eloquence.zh-CN.Grandpa", "com.apple.eloquence.zh-TW.Grandpa", "com.apple.speech.synthesis.voice.Hysterical", "com.apple.voice.compact.ro-RO.Ioana", "com.apple.eloquence.fr-FR.Jacques", "com.apple.voice.compact.pt-PT.Joana", "com.apple.voice.enhanced.en-US.Joelle", "com.apple.speech.synthesis.voice.Junior", "com.apple.voice.compact.th-TH.Kanya", "com.apple.voice.compact.en-AU.Karen", "com.apple.voice.enhanced.en-GB.Kate", "com.apple.speech.synthesis.voice.Kathy", "com.apple.voice.compact.ja-JP.Kyoko", "com.apple.voice.enhanced.ja-JP.Kyoko", "com.apple.voice.compact.hr-HR.Lana", "com.apple.voice.compact.sk-SK.Laura", "com.apple.voice.compact.hi-IN.Lekha", "com.apple.voice.compact.uk-UA.Lesya", "com.apple.voice.compact.vi-VN.Linh", "com.apple.voice.compact.pt-BR.Luciana", "com.apple.voice.compact.ar-001.Maged", "com.apple.voice.premium.en-GB.Malcolm", "com.apple.voice.compact.hu-HU.Mariska", "com.apple.voice.compact.zh-TW.Meijia", "com.apple.voice.compact.el-GR.Melina", "com.apple.voice.compact.ru-RU.Milena", "com.apple.voice.compact.en-IE.Moira", "com.apple.voice.enhanced.en-IE.Moira", "com.apple.voice.compact.es-ES.Monica", "com.apple.voice.compact.ca-ES.Montserrat", "com.apple.voice.enhanced.en-US.Nathan", "com.apple.voice.enhanced.en-US.Noelle", "com.apple.voice.compact.nb-NO.Nora", "com.apple.speech.synthesis.voice.Organ", "com.apple.voice.compact.ja-JP.Otoya", "com.apple.voice.enhanced.ja-JP.Otoya", "com.apple.voice.compact.es-MX.Paulina", "com.apple.speech.synthesis.voice.Princess", "com.apple.speech.synthesis.voice.Ralph", "com.apple.eloquence.de-DE.Reed", "com.apple.eloquence.en-GB.Reed", "com.apple.eloquence.en-US.Reed", "com.apple.eloquence.es-ES.Reed", "com.apple.eloquence.es-MX.Reed", "com.apple.eloquence.fi-FI.Reed", "com.apple.eloquence.fr-CA.Reed", "com.apple.eloquence.it-IT.Reed", "com.apple.eloquence.ja-JP.Reed", "com.apple.eloquence.ko-KR.Reed", "com.apple.eloquence.pt-BR.Reed", "com.apple.eloquence.zh-CN.Reed", "com.apple.eloquence.zh-TW.Reed", "com.apple.voice.compact.en-IN.Rishi", "com.apple.eloquence.de-DE.Rocko", "com.apple.eloquence.en-GB.Rocko", "com.apple.eloquence.en-US.Rocko", "com.apple.eloquence.es-ES.Rocko", "com.apple.eloquence.es-MX.Rocko", "com.apple.eloquence.fi-FI.Rocko", "com.apple.eloquence.fr-CA.Rocko", "com.apple.eloquence.fr-FR.Rocko", "com.apple.eloquence.it-IT.Rocko", "com.apple.eloquence.ja-JP.Rocko", "com.apple.eloquence.ko-KR.Rocko", "com.apple.eloquence.pt-BR.Rocko", "com.apple.eloquence.zh-CN.Rocko", "com.apple.eloquence.zh-TW.Rocko", "com.apple.voice.compact.en-US.Samantha", "com.apple.voice.enhanced.en-US.Samantha", "com.apple.eloquence.de-DE.Sandy", "com.apple.eloquence.en-GB.Sandy", "com.apple.eloquence.en-US.Sandy", "com.apple.eloquence.es-ES.Sandy", "com.apple.eloquence.es-MX.Sandy", "com.apple.eloquence.fi-FI.Sandy", "com.apple.eloquence.fr-CA.Sandy", "com.apple.eloquence.fr-FR.Sandy", "com.apple.eloquence.it-IT.Sandy", "com.apple.eloquence.ja-JP.Sandy", "com.apple.eloquence.ko-KR.Sandy", "com.apple.eloquence.pt-BR.Sandy", "com.apple.eloquence.zh-CN.Sandy", "com.apple.eloquence.zh-TW.Sandy", "com.apple.voice.compact.da-DK.Sara", "com.apple.voice.compact.fi-FI.Satu", "com.apple.eloquence.de-DE.Shelley", "com.apple.eloquence.en-GB.Shelley", "com.apple.eloquence.en-US.Shelley", "com.apple.eloquence.es-ES.Shelley", "com.apple.eloquence.es-MX.Shelley", "com.apple.eloquence.fi-FI.Shelley", "com.apple.eloquence.fr-CA.Shelley", "com.apple.eloquence.fr-FR.Shelley", "com.apple.eloquence.it-IT.Shelley", "com.apple.eloquence.ja-JP.Shelley", "com.apple.eloquence.ko-KR.Shelley", "com.apple.eloquence.pt-BR.Shelley", "com.apple.eloquence.zh-CN.Shelley", "com.apple.eloquence.zh-TW.Shelley", "com.apple.voice.compact.zh-HK.Sinji", "com.apple.voice.compact.en-US.Susan", "com.apple.voice.enhanced.en-US.Susan", "com.apple.voice.compact.en-ZA.Tessa", "com.apple.voice.compact.fr-FR.Thomas", "com.apple.voice.compact.sl-SI.Tina", "com.apple.voice.compact.zh-CN.Tingting", "com.apple.voice.compact.en-US.Tom", "com.apple.voice.enhanced.en-US.Tom", "com.apple.speech.synthesis.voice.Trinoids", "com.apple.speech.synthesis.voice.Whisper", "com.apple.voice.compact.nl-NL.Xander", "com.apple.voice.compact.tr-TR.Yelda", "com.apple.voice.compact.ko-KR.Yuna", "com.apple.speech.synthesis.voice.Zarvox", "com.apple.voice.enhanced.en-US.Zoe", "com.apple.voice.premium.en-US.Zoe", "com.apple.voice.compact.pl-PL.Zosia", "com.apple.voice.compact.cs-CZ.Zuzana"}

★Click Here to Open This Script 

AppleScript名:AVSpeechSynthesisVoiceのIDを取得_macOS15.0.scpt
— Created 2018-02-15 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.8"
use scripting additions
use framework "Foundation"
use framework "AVFoundation"

set aList to (current application’s AVSpeechSynthesisVoice’s speechVoices()’s valueForKey:"identifier") as list
–macOS 13 (190)
–> {"com.apple.voice.compact.ar-001.Maged", "com.apple.voice.compact.bg-BG.Daria", "com.apple.voice.compact.ca-ES.Montserrat", "com.apple.voice.compact.cs-CZ.Zuzana", "com.apple.voice.compact.da-DK.Sara", "com.apple.eloquence.de-DE.Sandy", "com.apple.eloquence.de-DE.Shelley", "com.apple.ttsbundle.siri_Helena_de-DE_compact", "com.apple.eloquence.de-DE.Grandma", "com.apple.eloquence.de-DE.Grandpa", "com.apple.eloquence.de-DE.Eddy", "com.apple.eloquence.de-DE.Reed", "com.apple.voice.compact.de-DE.Anna", "com.apple.ttsbundle.siri_Martin_de-DE_compact", "com.apple.eloquence.de-DE.Rocko", "com.apple.eloquence.de-DE.Flo", "com.apple.voice.compact.el-GR.Melina", "com.apple.ttsbundle.siri_Gordon_en-AU_compact", "com.apple.voice.compact.en-AU.Karen", "com.apple.ttsbundle.siri_Catherine_en-AU_compact", "com.apple.voice.premium.en-GB.Malcolm", "com.apple.voice.enhanced.en-GB.Daniel", "com.apple.ttsbundle.Oliver-premium", "com.apple.voice.enhanced.en-GB.Kate", "com.apple.eloquence.en-GB.Rocko", "com.apple.eloquence.en-GB.Shelley", "com.apple.ttsbundle.Oliver-compact", "com.apple.voice.compact.en-GB.Daniel", "com.apple.ttsbundle.siri_Martha_en-GB_compact", "com.apple.eloquence.en-GB.Grandma", "com.apple.eloquence.en-GB.Grandpa", "com.apple.eloquence.en-GB.Flo", "com.apple.eloquence.en-GB.Eddy", "com.apple.eloquence.en-GB.Reed", "com.apple.eloquence.en-GB.Sandy", "com.apple.ttsbundle.siri_Arthur_en-GB_compact", "com.apple.voice.enhanced.en-IE.Moira", "com.apple.voice.compact.en-IE.Moira", "com.apple.voice.compact.en-IN.Rishi", "com.apple.voice.premium.en-US.Zoe", "com.apple.voice.premium.en-US.Ava", "com.apple.voice.enhanced.en-US.Samantha", "com.apple.voice.enhanced.en-US.Evan", "com.apple.voice.enhanced.en-US.Zoe", "com.apple.voice.enhanced.en-US.Joelle", "com.apple.voice.enhanced.en-US.Susan", "com.apple.voice.enhanced.en-US.Nathan", "com.apple.voice.enhanced.en-US.Tom", "com.apple.voice.enhanced.en-US.Noelle", "com.apple.eloquence.en-US.Flo", "com.apple.speech.synthesis.voice.Albert", "com.apple.speech.synthesis.voice.Bahh", "com.apple.speech.synthesis.voice.Fred", "com.apple.speech.synthesis.voice.Hysterical", "com.apple.voice.compact.en-US.Allison", "com.apple.speech.synthesis.voice.Organ", "com.apple.speech.synthesis.voice.Cellos", "com.apple.voice.compact.en-US.Evan", "com.apple.speech.synthesis.voice.Zarvox", "com.apple.eloquence.en-US.Rocko", "com.apple.eloquence.en-US.Shelley", "com.apple.speech.synthesis.voice.Princess", "com.apple.eloquence.en-US.Grandma", "com.apple.eloquence.en-US.Eddy", "com.apple.speech.synthesis.voice.Bells", "com.apple.eloquence.en-US.Grandpa", "com.apple.speech.synthesis.voice.Trinoids", "com.apple.speech.synthesis.voice.Kathy", "com.apple.eloquence.en-US.Reed", "com.apple.speech.synthesis.voice.Boing", "com.apple.speech.synthesis.voice.GoodNews", "com.apple.speech.synthesis.voice.Whisper", "com.apple.speech.synthesis.voice.Bruce", "com.apple.speech.synthesis.voice.Deranged", "com.apple.ttsbundle.siri_Nicky_en-US_compact", "com.apple.speech.synthesis.voice.BadNews", "com.apple.ttsbundle.siri_Aaron_en-US_compact", "com.apple.speech.synthesis.voice.Bubbles", "com.apple.voice.compact.en-US.Susan", "com.apple.voice.compact.en-US.Tom", "com.apple.speech.synthesis.voice.Agnes", "com.apple.voice.compact.en-US.Samantha", "com.apple.eloquence.en-US.Sandy", "com.apple.speech.synthesis.voice.Junior", "com.apple.voice.compact.en-US.Ava", "com.apple.speech.synthesis.voice.Ralph", "com.apple.voice.compact.en-ZA.Tessa", "com.apple.eloquence.es-ES.Shelley", "com.apple.eloquence.es-ES.Grandma", "com.apple.eloquence.es-ES.Rocko", "com.apple.eloquence.es-ES.Grandpa", "com.apple.eloquence.es-ES.Flo", "com.apple.eloquence.es-ES.Sandy", "com.apple.voice.compact.es-ES.Monica", "com.apple.eloquence.es-ES.Eddy", "com.apple.eloquence.es-ES.Reed", "com.apple.eloquence.es-MX.Rocko", "com.apple.voice.compact.es-MX.Paulina", "com.apple.eloquence.es-MX.Flo", "com.apple.eloquence.es-MX.Sandy", "com.apple.eloquence.es-MX.Eddy", "com.apple.eloquence.es-MX.Shelley", "com.apple.eloquence.es-MX.Reed", "com.apple.eloquence.es-MX.Grandma", "com.apple.eloquence.es-MX.Grandpa", "com.apple.eloquence.fi-FI.Shelley", "com.apple.eloquence.fi-FI.Grandma", "com.apple.eloquence.fi-FI.Grandpa", "com.apple.eloquence.fi-FI.Sandy", "com.apple.voice.compact.fi-FI.Satu", "com.apple.eloquence.fi-FI.Eddy", "com.apple.eloquence.fi-FI.Rocko", "com.apple.eloquence.fi-FI.Reed", "com.apple.eloquence.fi-FI.Flo", "com.apple.voice.premium.fr-CA.Amelie", "com.apple.voice.enhanced.fr-CA.Chantal", "com.apple.eloquence.fr-CA.Shelley", "com.apple.eloquence.fr-CA.Grandma", "com.apple.eloquence.fr-CA.Grandpa", "com.apple.eloquence.fr-CA.Rocko", "com.apple.eloquence.fr-CA.Eddy", "com.apple.eloquence.fr-CA.Reed", "com.apple.voice.compact.fr-CA.Amelie", "com.apple.eloquence.fr-CA.Flo", "com.apple.eloquence.fr-CA.Sandy", "com.apple.eloquence.fr-FR.Grandma", "com.apple.eloquence.fr-FR.Flo", "com.apple.eloquence.fr-FR.Rocko", "com.apple.eloquence.fr-FR.Grandpa", "com.apple.eloquence.fr-FR.Sandy", "com.apple.eloquence.fr-FR.Eddy", "com.apple.voice.compact.fr-FR.Thomas", "com.apple.ttsbundle.siri_Dan_fr-FR_compact", "com.apple.eloquence.fr-FR.Jacques", "com.apple.ttsbundle.siri_Marie_fr-FR_compact", "com.apple.eloquence.fr-FR.Shelley", "com.apple.voice.compact.he-IL.Carmit", "com.apple.voice.compact.hi-IN.Lekha", "com.apple.voice.compact.hr-HR.Lana", "com.apple.voice.compact.hu-HU.Mariska", "com.apple.voice.compact.id-ID.Damayanti", "com.apple.eloquence.it-IT.Eddy", "com.apple.eloquence.it-IT.Sandy", "com.apple.eloquence.it-IT.Reed", "com.apple.eloquence.it-IT.Shelley", "com.apple.eloquence.it-IT.Grandma", "com.apple.eloquence.it-IT.Grandpa", "com.apple.eloquence.it-IT.Flo", "com.apple.eloquence.it-IT.Rocko", "com.apple.voice.compact.it-IT.Alice", "com.apple.ttsbundle.siri_Hattori_ja-JP_premium", "com.apple.ttsbundle.siri_O-Ren_ja-JP_premium", "com.apple.voice.enhanced.ja-JP.Kyoko", "com.apple.voice.enhanced.ja-JP.Otoya", "com.apple.voice.compact.ja-JP.Kyoko", "com.apple.ttsbundle.siri_Hattori_ja-JP_compact", "com.apple.voice.compact.ja-JP.Otoya", "com.apple.ttsbundle.siri_O-Ren_ja-JP_compact", "com.apple.voice.compact.ko-KR.Yuna", "com.apple.voice.compact.ms-MY.Amira", "com.apple.voice.compact.nb-NO.Nora", "com.apple.voice.compact.nl-BE.Ellen", "com.apple.voice.compact.nl-NL.Xander", "com.apple.voice.compact.pl-PL.Zosia", "com.apple.eloquence.pt-BR.Reed", "com.apple.voice.compact.pt-BR.Luciana", "com.apple.eloquence.pt-BR.Shelley", "com.apple.eloquence.pt-BR.Grandma", "com.apple.eloquence.pt-BR.Grandpa", "com.apple.eloquence.pt-BR.Rocko", "com.apple.eloquence.pt-BR.Flo", "com.apple.eloquence.pt-BR.Sandy", "com.apple.eloquence.pt-BR.Eddy", "com.apple.voice.compact.pt-PT.Joana", "com.apple.voice.compact.ro-RO.Ioana", "com.apple.voice.compact.ru-RU.Milena", "com.apple.voice.compact.sk-SK.Laura", "com.apple.voice.compact.sv-SE.Alva", "com.apple.voice.compact.th-TH.Kanya", "com.apple.voice.compact.tr-TR.Yelda", "com.apple.voice.compact.uk-UA.Lesya", "com.apple.voice.compact.vi-VN.Linh", "com.apple.ttsbundle.siri_Yu-Shu_zh-CN_compact", "com.apple.ttsbundle.siri_Li-Mu_zh-CN_compact", "com.apple.voice.compact.zh-CN.Tingting", "com.apple.ttsbundle.Sin-ji-premium", "com.apple.voice.compact.zh-HK.Sinji", "com.apple.ttsbundle.Mei-Jia-premium", "com.apple.voice.compact.zh-TW.Meijia", "com.apple.speech.synthesis.voice.Alex"}

–macOS 15 (222)
–> {"com.apple.voice.compact.ar-001.Maged", "com.apple.voice.compact.bg-BG.Daria", "com.apple.voice.compact.ca-ES.Montserrat", "com.apple.voice.compact.cs-CZ.Zuzana", "com.apple.voice.compact.da-DK.Sara", "com.apple.eloquence.de-DE.Sandy", "com.apple.eloquence.de-DE.Shelley", "com.apple.ttsbundle.siri_Helena_de-DE_compact", "com.apple.eloquence.de-DE.Grandma", "com.apple.eloquence.de-DE.Grandpa", "com.apple.eloquence.de-DE.Eddy", "com.apple.eloquence.de-DE.Reed", "com.apple.voice.compact.de-DE.Anna", "com.apple.ttsbundle.siri_Martin_de-DE_compact", "com.apple.eloquence.de-DE.Rocko", "com.apple.eloquence.de-DE.Flo", "com.apple.voice.compact.el-GR.Melina", "com.apple.ttsbundle.siri_Gordon_en-AU_compact", "com.apple.voice.compact.en-AU.Karen", "com.apple.ttsbundle.siri_Catherine_en-AU_compact", "com.apple.voice.premium.en-GB.Malcolm", "com.apple.voice.enhanced.en-GB.Daniel", "com.apple.voice.enhanced.en-GB.Kate", "com.apple.eloquence.en-GB.Rocko", "com.apple.eloquence.en-GB.Shelley", "com.apple.voice.compact.en-GB.Daniel", "com.apple.ttsbundle.siri_Martha_en-GB_compact", "com.apple.eloquence.en-GB.Grandma", "com.apple.eloquence.en-GB.Grandpa", "com.apple.eloquence.en-GB.Flo", "com.apple.eloquence.en-GB.Eddy", "com.apple.eloquence.en-GB.Reed", "com.apple.eloquence.en-GB.Sandy", "com.apple.ttsbundle.siri_Arthur_en-GB_compact", "com.apple.voice.enhanced.en-IE.Moira", "com.apple.voice.compact.en-IE.Moira", "com.apple.voice.compact.en-IN.Rishi", "com.apple.voice.premium.en-US.Zoe", "com.apple.voice.premium.en-US.Ava", "com.apple.voice.enhanced.en-US.Samantha", "com.apple.voice.enhanced.en-US.Evan", "com.apple.ttsbundle.siri_Nicky_en-US_premium", "com.apple.voice.enhanced.en-US.Ava", "com.apple.voice.enhanced.en-US.Zoe", "com.apple.voice.enhanced.en-US.Joelle", "com.apple.voice.enhanced.en-US.Susan", "com.apple.voice.enhanced.en-US.Allison", "com.apple.speech.synthesis.voice.Bruce", "com.apple.voice.enhanced.en-US.Nathan", "com.apple.voice.enhanced.en-US.Tom", "com.apple.speech.synthesis.voice.Agnes", "com.apple.voice.enhanced.en-US.Noelle", "com.apple.eloquence.en-US.Flo", "com.apple.speech.synthesis.voice.Bahh", "com.apple.speech.synthesis.voice.Fred", "com.apple.speech.synthesis.voice.Albert", "com.apple.speech.synthesis.voice.Hysterical", "com.apple.voice.compact.en-US.Allison", "com.apple.speech.synthesis.voice.Organ", "com.apple.speech.synthesis.voice.Cellos", "com.apple.voice.compact.en-US.Evan", "com.apple.speech.synthesis.voice.Zarvox", "com.apple.eloquence.en-US.Rocko", "com.apple.eloquence.en-US.Shelley", "com.apple.speech.synthesis.voice.Princess", "com.apple.eloquence.en-US.Grandma", "com.apple.eloquence.en-US.Eddy", "com.apple.speech.synthesis.voice.Bells", "com.apple.eloquence.en-US.Grandpa", "com.apple.speech.synthesis.voice.Kathy", "com.apple.speech.synthesis.voice.Trinoids", "com.apple.eloquence.en-US.Reed", "com.apple.speech.synthesis.voice.Boing", "com.apple.speech.synthesis.voice.Whisper", "com.apple.speech.synthesis.voice.GoodNews", "com.apple.speech.synthesis.voice.Deranged", "com.apple.ttsbundle.siri_Nicky_en-US_compact", "com.apple.speech.synthesis.voice.BadNews", "com.apple.ttsbundle.siri_Aaron_en-US_compact", "com.apple.speech.synthesis.voice.Bubbles", "com.apple.voice.compact.en-US.Susan", "com.apple.voice.compact.en-US.Tom", "com.apple.voice.compact.en-US.Samantha", "com.apple.eloquence.en-US.Sandy", "com.apple.speech.synthesis.voice.Junior", "com.apple.voice.compact.en-US.Ava", "com.apple.speech.synthesis.voice.Ralph", "com.apple.voice.compact.en-ZA.Tessa", "com.apple.eloquence.es-ES.Shelley", "com.apple.eloquence.es-ES.Grandma", "com.apple.eloquence.es-ES.Rocko", "com.apple.eloquence.es-ES.Grandpa", "com.apple.eloquence.es-ES.Flo", "com.apple.eloquence.es-ES.Sandy", "com.apple.voice.compact.es-ES.Monica", "com.apple.eloquence.es-ES.Eddy", "com.apple.eloquence.es-ES.Reed", "com.apple.eloquence.es-MX.Rocko", "com.apple.voice.compact.es-MX.Paulina", "com.apple.eloquence.es-MX.Flo", "com.apple.eloquence.es-MX.Sandy", "com.apple.eloquence.es-MX.Eddy", "com.apple.eloquence.es-MX.Shelley", "com.apple.eloquence.es-MX.Grandma", "com.apple.eloquence.es-MX.Reed", "com.apple.eloquence.es-MX.Grandpa", "com.apple.eloquence.fi-FI.Shelley", "com.apple.eloquence.fi-FI.Grandma", "com.apple.eloquence.fi-FI.Grandpa", "com.apple.eloquence.fi-FI.Sandy", "com.apple.voice.compact.fi-FI.Satu", "com.apple.eloquence.fi-FI.Eddy", "com.apple.eloquence.fi-FI.Rocko", "com.apple.eloquence.fi-FI.Reed", "com.apple.eloquence.fi-FI.Flo", "com.apple.voice.premium.fr-CA.Amelie", "com.apple.voice.enhanced.fr-CA.Chantal", "com.apple.eloquence.fr-CA.Shelley", "com.apple.eloquence.fr-CA.Grandma", "com.apple.eloquence.fr-CA.Grandpa", "com.apple.eloquence.fr-CA.Rocko", "com.apple.eloquence.fr-CA.Eddy", "com.apple.eloquence.fr-CA.Reed", "com.apple.voice.compact.fr-CA.Amelie", "com.apple.eloquence.fr-CA.Flo", "com.apple.eloquence.fr-CA.Sandy", "com.apple.eloquence.fr-FR.Grandma", "com.apple.eloquence.fr-FR.Flo", "com.apple.eloquence.fr-FR.Rocko", "com.apple.eloquence.fr-FR.Grandpa", "com.apple.eloquence.fr-FR.Sandy", "com.apple.eloquence.fr-FR.Eddy", "com.apple.voice.compact.fr-FR.Thomas", "com.apple.ttsbundle.siri_Dan_fr-FR_compact", "com.apple.eloquence.fr-FR.Jacques", "com.apple.ttsbundle.siri_Marie_fr-FR_compact", "com.apple.eloquence.fr-FR.Shelley", "com.apple.voice.compact.he-IL.Carmit", "com.apple.voice.compact.hi-IN.Lekha", "com.apple.voice.compact.hr-HR.Lana", "com.apple.voice.compact.hu-HU.Mariska", "com.apple.voice.compact.id-ID.Damayanti", "com.apple.eloquence.it-IT.Eddy", "com.apple.eloquence.it-IT.Sandy", "com.apple.eloquence.it-IT.Reed", "com.apple.eloquence.it-IT.Shelley", "com.apple.eloquence.it-IT.Grandma", "com.apple.eloquence.it-IT.Grandpa", "com.apple.eloquence.it-IT.Flo", "com.apple.eloquence.it-IT.Rocko", "com.apple.voice.compact.it-IT.Alice", "com.apple.ttsbundle.siri_Hattori_ja-JP_premium", "com.apple.ttsbundle.siri_O-Ren_ja-JP_premium", "com.apple.voice.enhanced.ja-JP.Kyoko", "com.apple.voice.enhanced.ja-JP.Otoya", "com.apple.eloquence.ja-JP.Eddy", "com.apple.eloquence.ja-JP.Reed", "com.apple.eloquence.ja-JP.Shelley", "com.apple.voice.compact.ja-JP.Kyoko", "com.apple.eloquence.ja-JP.Grandma", "com.apple.eloquence.ja-JP.Rocko", "com.apple.eloquence.ja-JP.Grandpa", "com.apple.ttsbundle.siri_Hattori_ja-JP_compact", "com.apple.voice.compact.ja-JP.Otoya", "com.apple.eloquence.ja-JP.Sandy", "com.apple.ttsbundle.siri_O-Ren_ja-JP_compact", "com.apple.eloquence.ja-JP.Flo", "com.apple.eloquence.ko-KR.Rocko", "com.apple.eloquence.ko-KR.Grandma", "com.apple.eloquence.ko-KR.Grandpa", "com.apple.eloquence.ko-KR.Eddy", "com.apple.eloquence.ko-KR.Sandy", "com.apple.voice.compact.ko-KR.Yuna", "com.apple.eloquence.ko-KR.Reed", "com.apple.eloquence.ko-KR.Flo", "com.apple.eloquence.ko-KR.Shelley", "com.apple.voice.compact.ms-MY.Amira", "com.apple.voice.compact.nb-NO.Nora", "com.apple.voice.compact.nl-BE.Ellen", "com.apple.voice.compact.nl-NL.Xander", "com.apple.voice.compact.pl-PL.Zosia", "com.apple.eloquence.pt-BR.Reed", "com.apple.voice.compact.pt-BR.Luciana", "com.apple.eloquence.pt-BR.Shelley", "com.apple.eloquence.pt-BR.Grandma", "com.apple.eloquence.pt-BR.Grandpa", "com.apple.eloquence.pt-BR.Rocko", "com.apple.eloquence.pt-BR.Flo", "com.apple.eloquence.pt-BR.Sandy", "com.apple.eloquence.pt-BR.Eddy", "com.apple.voice.compact.pt-PT.Joana", "com.apple.voice.compact.ro-RO.Ioana", "com.apple.voice.compact.ru-RU.Milena", "com.apple.voice.compact.sk-SK.Laura", "com.apple.voice.compact.sl-SI.Tina", "com.apple.voice.compact.sv-SE.Alva", "com.apple.voice.compact.th-TH.Kanya", "com.apple.voice.compact.tr-TR.Yelda", "com.apple.voice.compact.uk-UA.Lesya", "com.apple.voice.compact.vi-VN.Linh", "com.apple.eloquence.zh-CN.Eddy", "com.apple.eloquence.zh-CN.Shelley", "com.apple.ttsbundle.siri_Yu-Shu_zh-CN_compact", "com.apple.eloquence.zh-CN.Grandma", "com.apple.eloquence.zh-CN.Reed", "com.apple.eloquence.zh-CN.Grandpa", "com.apple.eloquence.zh-CN.Rocko", "com.apple.ttsbundle.siri_Li-Mu_zh-CN_compact", "com.apple.eloquence.zh-CN.Flo", "com.apple.voice.compact.zh-CN.Tingting", "com.apple.eloquence.zh-CN.Sandy", "com.apple.voice.compact.zh-HK.Sinji", "com.apple.eloquence.zh-TW.Shelley", "com.apple.eloquence.zh-TW.Grandma", "com.apple.eloquence.zh-TW.Grandpa", "com.apple.eloquence.zh-TW.Sandy", "com.apple.eloquence.zh-TW.Flo", "com.apple.eloquence.zh-TW.Eddy", "com.apple.eloquence.zh-TW.Reed", "com.apple.voice.compact.zh-TW.Meijia", "com.apple.eloquence.zh-TW.Rocko", "com.apple.speech.synthesis.voice.Alex"}

★Click Here to Open This Script 

Posted in Text to Speech | Tagged 15.0savvy | Leave a comment

Pages書類の内容を伏せ字に v2

Posted on 10月 5, 2024 by Takaaki Naganoya

現在オープン中の最前面のPages書類の内容を伏せ字に置き換えるAppleScriptの改良版です。電子書籍「Pages+AppleScriptで本をつくろう!」のために作成したScriptの改良版です。

–> Download Script Bundle With library

実行にはライブラリ「dynamicClicker」が必要なため、上記リンクからAppleScriptバンドル書類をダウンロードして実行してください。

Pagesの書類上のオブジェクトは、

のようになっており(iWork Scripting Book with AppleScriptより引用)、shapeとtext itemの区別ができないという「頭のおかしな仕様」になっていますが、オブジェクトのclassを求めれば、だいたいは区別できる状況です。

group itemについてはメニューを強制操作して(なくなるまで永久ループで)グループ解除を行い、そののちにshapeとtableについては伏せ字処理を行います。

image、chart、movieなどのオブジェクトについては伏せ字処理を行いませんが、そのあたりは処理したいユーザーの趣味次第でしょう。

AppleScript名:全ページを伏せ字に v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/10/02
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

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

tell application "Pages"
  tell front document
    set pCount to count every page
    
repeat with p from 1 to pCount
      tell page p
        –ひたすらグループ化されたアイテムを解除する。多重にグループ化が可能なので、ひたすら繰り返す
        
repeat
          set gList to every group
          
if gList = {} then exit repeat
          
set gRes to ungroupPagesItems(gList) of me
        end repeat
        
        
–通常処理
        
set aList to every iWork item
        
        
repeat with i in aList
          set j to contents of i
          
set tmpClass to class of j
          
          
if tmpClass = shape then
            set aText to object text of j
            
set mText to maskStrings(aText) of me
            
set object text of j to mText
            
          else if tmpClass = table then
            tell j
              set tmpW to width
              
set tmpH to height
              
set tumeF to false
              
set cColumn to count every column
              
              
if tmpW = 0 or tmpH = 0 then
                —
              else
                set aRatio to tmpW / tmpH
                
                
if aRatio < 0.125 then set tumeF to true
                
if cColumn = 1 then set tumeF to true
              end if
            end tell
            
            
–表がツメでない場合にのみ処理
            
if tumeF = false then
              tell j
                set aTitle to ""
                
try
                  set aTitle to name of it
                  
set mText to maskStrings(aTitle) of me
                  
set name of it to mText
                end try
                
                
set cellList to every cell
                
repeat with ii in cellList
                  set jj to contents of ii
                  
set aValue to (value of jj) as string
                  
set mText to maskStrings(aValue) of me
                  
set value of jj to mText
                end repeat
                
              end tell
              
            end if
          end if
          
        end repeat
        
      end tell
    end repeat
  end tell
end tell

–Pagesで選択中のアイテムをグループ解除する
on ungroupPagesItems(gList as list)
  set appName to "Pages" –Application Name
  
set aList to {"配置", "グループ解除"} –Localized Menu Titles (menu title structure to "Ungroup")
  
  
tell application "Pages"
    tell front document
      set selection to gList
    end tell
  end tell
  
  
set aRes to clickSpecifiedMenuElement(appName, aList) of dLib
  
return aRes
end ungroupPagesItems

–指定したルールのとおりの文字種の並びになっているか?
on maskStrings(aStr)
  set aList to characters of aStr
  
  
set chkList to {}
  
repeat with i from 1 to (length of aList)
    set j1 to contents of item i of aList
    
    
set tmpStr to j1
    
    
set j2 to (my chkNumeric:j1)
    
set j3 to (my chkAlphabetCapt:j1)
    
set j4 to (my chkAlphabetSmall:j1)
    
    
if j2 = true then
      set tmpStr to "9"
    else if j3 = true then
      set tmpStr to "Z"
    else if j4 = true then
      set tmpStr to "z"
    else
      set tmpStr to "あ"
    end if
    
    
set the end of chkList to tmpStr
  end repeat
  
return chkList as string
end maskStrings

— アルファベット大文字か
on chkAlphabetCapt:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabetCapt:

— アルファベット小文字か
on chkAlphabetSmall:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabetSmall:

–数字のみか
on chkNumeric:checkString
  set digitCharSet to current application’s NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric:

–アルファベットと数字のみか
on chkAlphaNumeric:checkString
  set alnumCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()
  
set ret to my chkCompareString:checkString baseString:alnumCharSet
  
return ret as boolean
end chkAlphaNumeric:

–アルファベットと数字と記号のみか
on chkAlphaNumericSymbol:checkString
  set muCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()’s mutableCopy()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkAlphaNumericSymbol:

–記号のみか
on chkSymbol:checkString
  set muCharSet to current application’s NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSymbol:

–全角文字が存在するか
on chkMultiByteChar:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set aRes to aStr’s canBeConvertedToEncoding:(current application’s NSASCIIStringEncoding)
  
return (aRes as boolean)
end chkMultiByteChar:

on chkCompareString:checkString baseString:baseString
  set aScanner to current application’s NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

on chkCompareString:checkString characterSet:baseSet
  set anNSString to current application’s NSString’s stringWithString:checkString
  
set theRange to anNSString’s rangeOfCharacterFromSet:baseSet
  
return (|length| of theRange = 0) as boolean
end chkCompareString:characterSet:

★Click Here to Open This Script 

Posted in Object control | Tagged 13.0savvy 14.0savvy 15.0savvy Pages | Leave a comment

Pages書類の内容を伏せ字に

Posted on 10月 3, 2024 by Takaaki Naganoya

現在オープン中の最前面のPages書類の内容を伏せ字に置き換えるAppleScriptです。

新刊「Pages+AppleScriptで本をつくろう!」の作成のために書いたものです。Pages書類を付録として電子書籍に添付する場合に、あくまでデザインテンプレートとしての利用を見込んでいるため、本文がそのまま入っていると困るわけです、私が。

そんなわけで、せっかく作ったPages書類の内容を伏せ字にして、ダミー書類化するためのAppleScriptが必要になったわけです。

一応、テキストを伏せ字にするAppleScriptは作ってあったので、これをPages書類相手に処理するよう書き換えたものがこれです。


▲処理前


▲処理後

ただし、すべてのPages書類内のオブジェクトに対応していません。groupオブジェクトについては、メニュー操作を行えばグループ解除を行えなくもないですが、未着手です。

ちょっと気をつけて処理したのが「表」の内部セルに入っている値です。空欄だと値(value)がmissing valueになるので、そこは触らないほうがよかったかもしれません。

自分だけの事情になりますが、ページ左右端に「ツメ」と呼ばれるマークを「表」オブジェクトを用いて記入しているため、この「ツメ」に相当する「表」については無視するようにしています。

AppleScript名:全ページを伏せ字に.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/10/02
—
–  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 "Pages"
  tell front document
    set pCount to count every page
    
repeat with p from 1 to pCount
      tell page p
        set aList to every iWork item
        
        
repeat with i in aList
          set j to contents of i
          
set tmpClass to class of j
          
          
if tmpClass = shape then
            set aText to object text of j
            
set mText to maskStrings(aText) of me
            
set object text of j to mText
            
          else if tmpClass = group then
            
            
            
          else if tmpClass = table then
            tell j
              set tmpW to width
              
set tmpH to height
              
set tumeF to false
              
set cColumn to count every column
              
              
if tmpW = 0 or tmpH = 0 then
                —
              else
                set aRatio to tmpW / tmpH
                
                
if aRatio < 0.125 then set tumeF to true
                
if cColumn = 1 then set tumeF to true
              end if
            end tell
            
            
–表がツメでない場合にのみ処理
            
if tumeF = false then
              tell j
                set aTitle to ""
                
try
                  set aTitle to name of it
                  
set mText to maskStrings(aTitle) of me
                  
set name of it to mText
                end try
                
                
set cellList to every cell
                
repeat with ii in cellList
                  set jj to contents of ii
                  
set aValue to (value of jj) as string
                  
set mText to maskStrings(aValue) of me
                  
set value of jj to mText
                end repeat
                
              end tell
              
            end if
          end if
          
        end repeat
        
      end tell
    end repeat
  end tell
end tell

–指定したルールのとおりの文字種の並びになっているか?
on maskStrings(aStr)
  set aList to characters of aStr
  
  
set chkList to {}
  
repeat with i from 1 to (length of aList)
    set j1 to contents of item i of aList
    
    
set tmpStr to j1
    
    
set j2 to (my chkNumeric:j1)
    
set j3 to (my chkAlphabetCapt:j1)
    
set j4 to (my chkAlphabetSmall:j1)
    
    
if j2 = true then
      set tmpStr to "9"
    else if j3 = true then
      set tmpStr to "Z"
    else if j4 = true then
      set tmpStr to "z"
    else
      set tmpStr to "あ"
    end if
    
    
set the end of chkList to tmpStr
  end repeat
  
return chkList as string
end maskStrings

— アルファベット大文字か
on chkAlphabetCapt:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabetCapt:

— アルファベット小文字か
on chkAlphabetSmall:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabetSmall:

–数字のみか
on chkNumeric:checkString
  set digitCharSet to current application’s NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric:

–アルファベットと数字のみか
on chkAlphaNumeric:checkString
  set alnumCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()
  
set ret to my chkCompareString:checkString baseString:alnumCharSet
  
return ret as boolean
end chkAlphaNumeric:

–アルファベットと数字と記号のみか
on chkAlphaNumericSymbol:checkString
  set muCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()’s mutableCopy()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkAlphaNumericSymbol:

–記号のみか
on chkSymbol:checkString
  set muCharSet to current application’s NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSymbol:

–全角文字が存在するか
on chkMultiByteChar:checkString
  set aStr to current application’s NSString’s stringWithString:checkString
  
set aRes to aStr’s canBeConvertedToEncoding:(current application’s NSASCIIStringEncoding)
  
return (aRes as boolean)
end chkMultiByteChar:

on chkCompareString:checkString baseString:baseString
  set aScanner to current application’s NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

on chkCompareString:checkString characterSet:baseSet
  set anNSString to current application’s NSString’s stringWithString:checkString
  
set theRange to anNSString’s rangeOfCharacterFromSet:baseSet
  
return (|length| of theRange = 0) as boolean
end chkCompareString:characterSet:

★Click Here to Open This Script 

Posted in Object control Text | Tagged 13.0savvy 14.0savvy 15.0savvy Pages | Leave a comment

新刊電子書籍「Pages+AppleScriptで本をつくろう!」を刊行

Posted on 10月 3, 2024 by Takaaki Naganoya

電子書籍新刊「Pages+AppleScriptで本をつくろう!」を刊行しました。全370ページ、サンプルAppleScriptアーカイブつき。
→ 販売ページ

本書は、Appleのかんたんワープロ「Pages」の使い方を「本づくり」という観点からわかりやすくまとめたものです。

本という「お約束の塊」について、それぞれの部品をどのように作っているか、実例にもとづいてご紹介しています。本書を作ったときのPages書類を含め、用例をオマケとして添付しています。

Pagesはシンプルで強力な機能を備えていますが、シンプルであるがゆえに手間が増えてしまうケースがままあります。

これに対して、macOSのスクリプト言語である「AppleScript」を利用することで、手間のかかる作業を省ける構造になっています。

本書では、筆者がPagesを使って本を作るなかで、「どうしてもこれが必要」と感じた内容をまとめたAppleScriptを付録としてご提供しています。

本書をお買い求めいただくことで、どなたも同じ道具を使って手軽に電子書籍コンテンツを作る環境とノウハウを得られる、と自負するものです。

目次

準備編

1章

電子書籍の筆者になろう!

2章

本を作るために、Pagesになれよう!
Pagesで作る「本」とは?
Pagesのツールバー設定
Pagesの参考書
AppleScriptでパワーアップ

3章

Pagesの基本操作
テキスト
表
写真
図形
欄外の表記

実践編

4章

「本」を作る作業に慣れよう!
本を作る「作業」の流れ
Pages、4つのオキテ
PDF書き出し
Skim PDF Viewerの使い方

5章

本の部品を作る作業に慣れよう!
表紙
記事一覧でもある「目次」
読者へのあいさつ「まえがき」
仁義のための登録商標表記
記事本文ページ
記事を区切る「章トビラ」
本の名刺「奥付」
本の余韻を生む「裏表紙」
ページの左右を調整する「空白」

6章

Pagesのレイアウトに翻訳

7章

本は「顔」(表紙)が命
応用編

8章

頒布/配布方法を選ぼう

9章

作成した電子書籍を各種Book Storeへ
電子書籍をクリエーター天国のBOOTHで販売
電子書籍をAmazon Kindleで販売!
各電子書籍ストアの「検閲」

10章

Mac App Storeから取得
ユーザー辞書の作り方
表情豊かな、フォントをそろえよう!
フリーで利用できるイラスト/画像素材を活用しよう!
本の構造を知ろう!
プリンタで両面印刷してホチキス製本
コンビニのコピー機で出力してホチキス製本
付録AppleScriptについて
①PDF書き出し+結合
②ツメ操作
③パーソナル面付け
④PDFへのTOC追加
⑤テキストボックス操作
⑥表の列幅、行高さ調整
⑦フォント情報収集
⑧ファイル名(章)修正
⑨ファイル名(仮想ノンブル)修正
⑩PDF操作
筆者が刊行した電子書籍の仕様
Pagesのバージョン履歴

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

有害ではなくなっていたSpaces

Posted on 9月 30, 2024 by Takaaki Naganoya

Spacesは、macOS標準搭載の仮想デスクトップ機能であり、最大16個の仮想デスクトップを作れるようになっているほか、F3キーを押すと縮小表示を行うようになっているなど、ハード/ソフトともによく統合された機能です。

ただし、AppleScriptユーザー側からすると

「他の仮想デスクトップにアプリのウィンドウを置くとAppleScriptからアクセスできないカス機能」
「開発チームが他の機能のことを考慮していないクズ機能」

といった感想になります。

このため、さまざまな書籍で「AppleScriptとの互換性のない機能」のひとつとしてリストアップされ、AppleScript系の開発/運用現場では「安全のためにSpacesを使わないように」と注意するのが真っ先に行う恒例行事になっていました。

内蔵HDD/SSDの暗号化機能なみに、登場時にAppleScriptとの互換性検証が不十分なものについては「信用できない」として、以来、安全のために暗号化機能は極力使わないようにしてきました。

# HDDの暗号化機能が登場したときに、暗号化したHDDにAppleScriptからアクセスできないというバカみたいな不具合が発生。その後も、有効にするとeGPUが使えなくなるなど、この機能を作っている担当者だかチームのことが信じられません。

そして話はSpacesに戻ります。執筆中の電子書籍「Pages+AppleScriptで本をつくろう!」の注意点でSpacesについて言及し、確認のために「やっぱり今でも動かないのか?」と、試してみたら……他の仮想デスクトップ上に配置したPagesの書類の情報を取得できます。

「…………。」

何度試してみても、他の仮想デスクトップに配置したPages書類の情報を取得できます。

macOS 13.7.1と、macOS 10.13.7で試してみたところ、両方で動作しました。

このぐらいの範囲のmacOSで動くのであれば、さまざまな本でSpacesに関する「危険なので使用を推奨しない」という評価は取り下げる必要があることでしょう。

ただ、Pagesについては表示中のページから+6ページぐらいを超えるとオブジェクトのposition属性を取得できないといった不具合があり、これはmacOS 15で再テストしても発生が確認されています。

Posted in Bug news | Tagged 10.13savvy 15.0savvy Spaces | Leave a comment

Safari v18のtabのpidを取得

Posted on 9月 21, 2024 by Takaaki Naganoya

新たにリリースされたSafari v18(macOS 13/14/15用)で、各Tabに「pid」属性が新設されました。

各Webコンテンツのブラウズを行う処理プロセスを、独立したプロセスで行うことで、メモリの食いすぎでプロセスが止まったような場合にでも他のWebブラウジングに影響を与えない、というあたりにメリットがあったとか。


▲Safari v17とv18のAppleScript用語辞書(sdef)を比較したところ


▲SafariでYouTube上のムービーを再生しているところ


▲アクティビティモニタ上で該当するpidのプロセスを確認

pidがわかると、どういう「いいこと」があるのかが問題です。メモリの使用状況などを確認することはできますし、個別にプロセスをkillすることもできるわけですが、そこまでやるんだろうかと。そういうニーズがあって新設したのか、ちょっとわからないところです。

それはともかく、Safari(≒WebKit)系はゴミプロセスがメモリ上に残りまくるので(Mail.appもメッセージを表示するだけでゴミプロセスが残るし)、その点がちょっとどうなのかという点と、Webコンテンツ上の画像ボタンを文字認識しておかしな動作をしまくるので、そのあたりは勘弁してほしいところです。

AppleScript名:Safariのtabのpidを取得.scpt
tell application "Safari"
  tell window 1
    set aList to pid of every tab
    
–> {33892}
  end tell
end tell

★Click Here to Open This Script 

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

iWork Appsがv14.2にアップデート

Posted on 9月 20, 2024 by Takaaki Naganoya

iWork Apps(Keynote、Pages、Numbers)がバージョン14.2にアップデートしました。

すべてのアプリでAppleScript用語辞書への変更はありません。

Keynote 14.2では、macOS 15, Sequoia上でHDRコンテンツの表示をサポートしています。

バグの修正がうたわれていますが、Pagesのページ上のオブジェクトの情報を取得できる範囲が現在表示中の見開き+6ページに制限されるというアホな仕様は変わっていないことを確認しています。

Posted in news | Tagged Keynote Numbers Pages | Leave a comment

iCalendarファイルの作成

Posted on 9月 20, 2024 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

Script DebuggerがmacOS 15.x上で起動せず→起動

Posted on 9月 18, 2024 by Takaaki Naganoya

Script DebuggerがmacOS 15上で起動しない状況が続いています。

日本語ユーザー環境、英語ユーザー環境にかかわらずmacOS 15/macOS 15.1上でScript Debuggerが起動しません。

ちなみに、macOS 14.7ではユーザーディレクトリ下のFrameworkを実行できない問題も発生しており、macOS 14/15を信用せずにメイン環境をmacOS 13.7のままにとどめていますが、この判断が大正解のようです。

続報:
rm ~/Library/Preferences/.2xbG4@@Ght01%!020#u

rm ~/Library/Preferences/.2xbZ4@@Ght01%!010#u

rm ~/Library/Application\ Support/.1@xX4D@yyt02"!2&0#a

rm ~/Library/Application\ Support/.1@xX4D@yytT2"!2&1#a

とすることで、macOS 15.x上でもScript Debuggerが起動できました。実際には、Terminal上でこれをそのまま実行しても削除できなかったので、当該フォルダに移動してTerminal上でファイルを確認したうえで削除しました。

SDが起動できないと、Framework呼び出しを行なっているAppleScriptの実行や書き出しに支障が出るため、実に困ります。

ただ、SDのアップデートやメンテナンスが数少ない開発者によって支えられている以上、代替策も用意しておきたいところです。

Posted in Bug | Tagged 13.0savvy 14.0savvy 15.0savvy Script Debugger | Leave a comment

Finderのfileのkind(種類)の日本語ローカライズ内容がmacOS 14以降で変更されている件(続報)

Posted on 9月 17, 2024 by Takaaki Naganoya

FinderやSystem Eventsで扱っているファイルの種別(kind)属性情報が、macOS 14以降で変更になっていて困っている件、その後の続報です。

おそらく、多言語ローカライズを行なっている下請け業者(いろんなメーカーのローカライズを担当している多言語ローカライザー企業)へのApple側からの指示内容に何か変化があって、不必要な部分までローカライズ内容の統一(≒修正)が行われてしまったのだろう、と見立てていました。

実際に身の回りのマシンで調査したところ、おおよそその見立てで間違っていないようです。

もとになっている英語版の表記については割と一貫性があって、コロコロ方針が変わっているようには見えません。

しかし、日本語ローカライズされた属性値については不可解というか「これを指示した人間の知性を疑う」という変わりっぷりであり、そこまで想定していなかったUS Apple側の指示内容がいいかげんだった、という想像を裏付けるものとなっています。

ローカライズにおいては変更しても意味がないし、変更することで悪影響が出る部分もあるわけですが、そこまで細かくチェックしていないということなんでしょう。

Posted in Bug Localize | Tagged 14.0savvy 15.0savvy | Leave a comment

Script Debugger v8.0.8 ホームディレクトリ以下のFrameworkを実行できない障害が発生

Posted on 9月 16, 2024 by Takaaki Naganoya

# 訂正:Script Debugger自体を再起動したら動くようになりました。何をやってもmissing valueしか返らなくなってビビりました。

ユーザーディレクトリ下のCocoa FrameworkをロードしてAppleScriptから実行可能なScript DebuggerおよびそのEnhancesd Applet。最新版のv8.0.8で、ホームディレクトリ下に配置したこれらCocoa Frameworkの実行ができないことを確認しています。

ちょっと凝ったAppleScriptでバンドル内にFrameworkを入れて呼び出しているものについては、目下実行できない状況にあります。自分が確認したのはmacOS 14.7環境。呼び出したはいいものの結果にmissing valueが返ってきて、首をひねっていたところ、原因がScript Debuggerにあることを確認。

自分でビルドした野良Cocoa Frameworkや、Bridge Plusの内蔵Frameworkまで、みんな呼び出せない状況です(日本語ユーザー環境)。

画像の余白トリミングから2D Arrayの高速ソーティングなど、Framework呼び出しは日常的なAppleScriptの実行に欠かせないものです。

Posted in Bug | Tagged 14.0savvy Script Debugger | 3 Comments

Finderのファイルの「kind」のローカライズ内容がmacOS 14以降で変更に

Posted on 9月 14, 2024 by Takaaki Naganoya

Appleは何の発表もなく、重要な情報を変更することがあります。とくに、日本語ローカライズされた内容だと英語圏のユーザーの関心は薄いですし、Appleのエンジニアが「理解できない」ケースも見られます。日本語の単語分解(≒形態素解析)について、macOS 10.5あたりまで「文字種類が変わったら単語の切れ目」とかいう無茶苦茶なロジックで処理されていましたが、それを「そういうのじゃない」とことあるごとにレポートしてきましたが、理解されてきませんでした。

Finderが管理しているファイルの種別(kind属性)は、ローカライズされたものが返ってくることで知られていましたが、macOS 14でそれが変更されたことがわかりました(最近MacBook Air M2を追加して、macOS 14環境を真剣に使い始めたので)。

こんな重要な変更は、気軽に行なってほしくないですし、変更したことを通達してほしいのですが(ーー;

以前からFinderのkindの内容については「ローカライズしてほしくないなぁ」と感じていましたが、このあたりのファイル種別については、UTI(com.image.pngなど)を利用するほうが、利用者の言語環境の変化を意識しなくていいですし、こうした些細なローカライズの変更の影響を受けなくてよいでしょう。

ただ、このあたりのやり方がいつも乱暴です>Apple
Release Notesもまともに書かなくなりましたし、どういうつもりなんだか。

Appleへの指摘事項として、Shortcutsで画像を扱うアクションが「写真」だったり「イメージ」だったり「画像」だったりと、用語のゆらぎが激しいという話があります。この点はAutomatorの登場時を彷彿とさせるものがあります。「これで使えというのには無理がある」「類似語の表記ゆらぎを吸収する仕組みが必要なのでは?」という指摘を行なっているのですが、そういう方向の努力として「種別」(Kind)のローカライズに手を入れた……と、考えられなくはありません。

それにしても、やっていることがお粗末すぎます。

AppleScript名:kind checker
tell application "Finder"
  set aSel to selection
  
set anItem to first item of aSel
  
  
properties of anItem
end tell

★Click Here to Open This Script 

Posted in file | Tagged Finder | Leave a comment

iWork Appsでオブジェクトの削除を安全に

Posted on 9月 14, 2024 by Takaaki Naganoya

iWork Apps(Keynote、Pages、Numbers)にはAppleScript系の機能でいろいろ勘弁してほしい仕様がありますが、その中でも最大のものが、書類内の各オブジェクトがIndexで管理されていることです。

Indexというのは、1からはじまる連番の数値です。

iWork Apps(Keynote、Pages、Numbers)のドキュメント上でオブジェクトの削除を行おうとすると、「地獄」を見ることになります。

iWork Appsの書類上でオブジェクトの削除を行うと、このIndex値が振り直されてしまうために、正しく「対象」を指し示すことが(途中から)できなくなってしまうのです。あるいは、まったく関係のない別のオブジェクトが削除されるとか。

これが、idで管理されていれば、何かのオブジェクトを削除されても影響はありません。何かUUID的な重複しないidが割り振られて、最初から最後まで(アプリケーションが起動してから終了するまで、あるいは書類がオープンされてからクローズされるまで)個別に識別されます。

対策

各オブジェクトを識別する場合に、それ専用の属性値を持たせることがあります。

Adobe InDesign:script label AppleScriptから設定・確認が可能なラベル(文字列)を設定できる

もともとある仕組みを本来の目的以外の用途に使うことができるケースもあります。

OmniGraffle:URL urlとかいいつつ、文字列だったらだいたいなんでも入った記憶が

そして、iWork Apps(Keynote、Pages、Numbers)。普段ほとんど使わなくて、AppleScriptから操作できて害のない属性値なんて便利なものがあるわけが……ありました。

Keynoteで使っている例は見かけましたが、他で使ったことのない「reflectin value」。つまり、「反射」属性。

PagesでもNumbersでも使ったことがありません。個人的には、Keynoteでも使ったことがないと思います。

選択状態にあるオブジェクトをもとに何らかの処理を行なって、選択していたオブジェクトを削除する場合に、普通に処理すると(オブジェクトがIndexで管理されているので)、地獄を見ます。

なので、削除対象のオブジェクトのreflection valueに100とか(1〜100のうち、0でないお好きな値を)を設定しておいて、ひととおり処理し終わったら、reflection valueが指定値になっているオブジェクトだけをフィルタ参照で削除する、といった対策が有効です。

実際のAppleScript

前処理Scriptで、最初にreflection valueが何か設定されているオブジェクトが存在しないことを確認したうえで、選択中のオブジェクトのreflection valueに100を設定し……

AppleScript名:削除_前処理.scptd
tell application "Pages"
  tell front document
    set reList to every iWork item whose reflection value is 100
    
if length of reList is not equal to 0 then return
    
    
set aSel to selection
    
repeat with i in aSel
      set j to contents of i
      
set reflection value of j to 100
    end repeat
  end tell
end tell

★Click Here to Open This Script 

処理を行なったあとで、reflection valueに100と設定されているオブジェクトを削除します。

AppleScript名:削除_後処理.scptd
tell application "Pages"
  tell front document
    tell current page
      set aSel to delete (every iWork item whose reflection value = 100)
    end tell
  end tell
end tell

★Click Here to Open This Script 

Posted in Object control | Tagged 13.0savvy 14.0savvy 15.0savvy Keynote Numbers Pages | Leave a comment

Pixelmator Proがv3.6.8でHDR画像をサポート

Posted on 9月 1, 2024 by Takaaki Naganoya

Pixelmator Proがv3.6.8でHDR画像のサポートを追加しました。

Pixelmator Pro 3.3.13–> 3.6.8

AppleScript用語辞書の比較で確認された変化は以下のとおりです。

・予約語「JPEG」の類義語として「JPG」を追加定義
・HDR画像の予約語を追加(OpenExr、HDR JPEG、HDR HEIC、HDR AVIF、HDR PNG)
・applicationのプロパティとして「load hdr content」を新設
・documentのプロパティとして「display hdr content」を新設

HDR対応について

Appleの公式資料によれば、現行機種はHDRに対応しているとのこと。

ただし、接続しているディスプレイによって、

「このディスプレイはHDRコンテンツをサポートしていません」(Mac mini M1+Apple Cinema Display)
「このディスプレイはHDRコンテンツのサポートが制限されています」(MacBook Air M2)

といったように、非対応/対応(不完全対応を含む)と状態が分かれるようです。

対応環境でPixelmator ProのHDRサポート状態を変更してHDR画像をオープンする実験は行なってみました。


▲Pixelmator Proの設定ウィンドウ HDRコンテンツのサポートが制限されている(MacBook Air M2)と表示


▲Pixelmator ProでサンプルのHDR JPEGをオープンしたところ

AppleScript名:HDR画像をオープン
tell application "Pixelmator Pro"
  set load hdr content to true
  
set aHDR2 to load hdr content
  
–> true
  
if aHDR2 = false then return
  
  
set aHDRfile to choose file
  
  
open aHDRfile
  
end tell

★Click Here to Open This Script 

HDR画像をオープンしても、HDR表示が行われるかどうかは別の管理になっている(documentのプロパティ)ので、そこも設定する必要があるようです。変更すると画面上でわずかに階調表現に変化が見られました(ちょっとだけ)。

AppleScript名:オープン中のHDR画像をHDR表示する
tell application "Pixelmator Pro"
  –環境チェック
  
set appHDR to load hdr content
  
if appHDR = false then return
  
  
–HDR画像の表示状態を変更
  
tell front document
    set display hdr content to true
    
set docHDR to display hdr content
  end tell
end tell

★Click Here to Open This Script 

Posted in Image Object control | Tagged 13.0savvy 14.0savvy 15.0savvy Pixelmator Pro | Leave a comment

新刊電子書籍「AppleScriptでたのしむ レトロ・グラフィック プログラム集」を刊行

Posted on 8月 31, 2024 by Takaaki Naganoya

電子書籍新刊「AppleScriptでたのしむ レトロ・グラフィック プログラム集」を刊行しました。全154ページ、サンプルAppleScriptアーカイブつき。
→ 販売ページ

1980年代や90年代の8/16ビットPCのBASICで描かせていた、三角関数による各種グラフィックスをAppleScriptで再現。ダイアログで表示するだけでなく、各種GUIアプリ(Keynote、Numbers、Pages、Excel、PowerPoint、Word、Pixelmator Pro)を操作して描画したり、画像書き出ししてAirDropでiOSデバイスに転送するようなサンプルを収録しています。

目次

1章 レトロ・グラフィックスの世界

懐かしのレトロCGの世界を再現
時代を経て感じる郷愁とも異なるテイスト
その昔、十数分かけて描いた三角関数グラフ
1秒以下で終了 vs 6分で終了
最新環境で動くAppleScriptにBASICのプログラムを移植
アップルスクリプトは、構文色分け必須の、色で要素を見分ける環境
最低限の知識でAppleScriptによるグラフィックを
AppleScript書類内に、実行に必要なライブラリを同梱
筆者の関数計算ライブラリ「calcLibAS」内蔵関数
コラム ポケコンエミュレータ“pockemul”

2章 早足で紹介するAppleScriptの世界

1994年から採用され続けている言語
GUIアプリを操作するために存在。搭載実行環境がとても多い
書き方は、アプリ内に存在する用語辞書を参照
本来の機能を利用するためにはシステム設定で許可する必要が
10.10以降でCocoaを直接呼べるようになったインタプリタ言語
GUI部品を直接操作してアプリを操作する強制操作機能が人気?
Web上のAPIを呼んでクラウド系の機能も利用
AS自体で予約語と機能を記述するライブラリ機能
コラム AppleScriptの世界の全体像 OS機能の最深部からGUIそのものの操作まで

3章 AppleScriptでグラフィックスを扱う

Cocoaの機能を呼び出してメモリ上で画像を作成
NSAlertの上にNSImageViewを作成しグラフィック表示
Cocoaのグラフィックス座標系”
主要なアプリケーションの座標系”
画像ファイルに書き出せば”
他のアプリにコピー&ペースト”
当時は存在していなかった透過画像”
パラメータを変えると動作が変わる”
コラム GUIアプリごとの応答速度の違い

4章 レトロ・グラフィックスプログラム集

スクリプトエディタでオープンして実行するだけ
必要なライブラリはバンドル内にすべて格納
掲載リストはグラフィックス描画にかかわる箇所のみ
How to use/ダイアログ表示AppleScript
How to use/ファイル出力AppleScript
How to use/ファイル出力+AirDrop AppleScript
How to use/クリップボード転送AppleScript
How to use/各種GUIアプリ操作AppleScript
OS標準搭載の13の実行環境およびサードパーティの数十の実行環境

線画テスト
円画テスト①
円画テスト②
サイクロイド曲線
バラ曲線
パスカルの蝸牛形
リサージュ曲線
ダイヤモンドパターン
アルキメデスの螺旋
メキシカンハット①
メキシカンハット②
メキシカンハット③
メキシカンハット④
コラム マシンごとの実行速度の違い

Posted in Books news | Tagged 13.0savvy 14.0savvy 15.0savvy Excel Keynote Numbers Pages Pixelmator Pro PowerPoint Word | Leave a comment

AppleScript入門③AppleScriptを使った「自動化」とは?

Posted on 8月 24, 2024 by Takaaki Naganoya

Windowsの開発者と話をしていて、「複数のGUIアプリを操作して自動化するという話が理解できない」と言われます。

 ファイル情報(選択中のファイル、選択中のフォルダ)をFinderから取得して
 spotlight機能を用いて選択中のフォルダ以下のPages書類を抽出し
 個別にPagesでオープンしてPDFを書き出し
 書き出したPDFをファイル名順にならべかえて連結し
 DropboxにREST API経由でアップロードして共有し
 得られた共有URLを指定の送付先にメール(Mail.app)で送信する

と、複数のGUIアプリを操作した自動化のワークフローは、普通にありえるものです。ありふれすぎています。

自動化のサイズ

ここで、ひとことに「自動化」といったときに、ユーザーごとに想定する「サイズ」がぜんぜん違うことに気づきます。

・(A)メニュー項目をいくつか連続して操作する「操作自動化」
・(B)1つの連続した操作を繰り返して実行する「作業自動化」
・(C)MacがタイマーでいくつかのScriptを実行してロボット動作する「業務自動化」

(A)<(B)<(c)と粒度の大きさが変わるところで、世間で言われる「自動化」というのは、ほぼ(A)の操作自動化のレベルと思われます。

自分が行なっているのは、(B)や(c)のレベルの自動化です。

(A)のレベルの「操作自動化」が悪いとは言いませんし、そういうレベルでも自動化に取り組むことには意義はあることでしょう。

ただ、(B)(c)と比べると成果として得られる「メリットが少ない」とは思います。操作を行うための心理的な障壁を下げる、という意味ではメリットがあるのかもしれませんが……。

(B)や(C)では、まとまった動作を放置状態のMacで行うものであり、人間が作業を眺めている必要はないものです。

放置状態で勝手に作業

(B「作業自動化」)や(C)「業務自動化」では、人間がいちいち指示する必要がないか、Scriptの動作を開始する場合にのみ対象フォルダなどのパラメータを指定するものです。

独立した作業なり業務を実行できるようにしておけば、実行するMacの台数を増やせば、それだけ同時にこなせる仕事が増やせます。

それだけ自動化してあれば、作業のためにアルバイトを雇う必要もありませんし、夜通し作業を行わせておいてもよいでしょう。

作業自動化や業務自動化に必要な「仕様書」

これらのまとまった作業を行うAppleScriptを作って運用する場合には、開発前に「仕様書」が必要になります。たいしたものでなくてもいいですが、どういった作業をどういう手順で行うのか、プログラムに書く前に人間の言葉でまとめておく必要はあるのです。

それは、箇条書きの文章で書いておいてもいいですし、画面キャプチャをまとめておいてもよいでしょう。

仕様書を書かないと、どこに向かって、どのように進んでいくのかを誰も理解していないという話になってしまいますし、それではScriptはおろか関与する人々が誰も「正しい作業」を理解できていないという話になってしまいます。

Posted in Beginner | Leave a comment

macOS 14で変更になったOSバージョン取得APIの返り値

Posted on 8月 24, 2024 by Takaaki Naganoya

macOSのバージョンを求める機能については、かならず複数の方法で取得できるように調査しています。

それは、Appleがバグを作る可能性が一番高い機能だからです(なんで懲りないんだろ?)。

OSバージョンを求めるのに、

・AppleScriptの標準装備コマンド「system info」で求める
–> {AppleScript version:”2.8″, AppleScript Studio version:”1.5.3″, system version:”13.6.9″, short user name:”XXXX”, long user name:”XXXXX XXXXX”, user ID:504, user locale:”ja_JP”, home directory:alias “Macintosh HD:Users:XXXX:”, boot volume:”Macintosh HD:”, computer name:”M1 mini”, host name:”m1mini.local”, IPv4 address:”192.168.0.99″, primary Ethernet address:”99:99:99:99:ZZ:99″, CPU type:”ARM64E”, CPU speed:missing value, physical memory:16384}

・AppleScriptの環境プロパティ「system attribute」を求める
set v1 to system attribute “sys1” –> 10
set v2 to system attribute “sys2” –> 4
set v3 to system attribute “sys3” –> 11

・shell commandで求める
–> sw_vers
–> sw_vers -productVersion

などに加えて、NSProcessInfos processInfo()’s operatingSystemVersion() を呼び出すという方法も加わりました。

ただ、これが最近おかしな挙動をするようになったのに気づいていろいろ調査してみたら、macOS 14になって返り値のフォーマットを変えたことが判明しました。ラベルつきの値(NSDictionary)で返してきたのが、ラベルなしの配列(NSArray)で返すように変わっています。macOS 10.13で座標系のデータをラベルなしで返すように変更してきたのと同様の変更が加えられています。

macOS 14.xの初期バージョンでは従来タイプの値を返してきたように記憶していますが、いつ変更したのやら。

AppleScript名:OSバージョンを求める.scpt
use AppleScript
use framework "Foundation"
use scripting additions

set pInfo to (current application’s NSProcessInfo’s processInfo()’s operatingSystemVersion())
–> {majorVersion:10, minorVersion:14, patchVersion:6}–10.14
–> {majorVersion:13, minorVersion:6, patchVersion:9}–13.6.9
–> {14, 6, 1}–14.6.1
–> {15, 1, 0}–15.0.1

★Click Here to Open This Script 

こういう基本的な情報を提供するAPIの仕様を変更することに、どういうインセンティブがあるのか不明です。変える価値があると判断したから変えたんでしょう。自分にはどういう理由なのか、さっぱり分かりません。

安全のためには、AppleScriptのビルトイン機能を使うか、OS内のplistを読み取って自分で処理するとかいった「対策」が必要なのでしょう。

Posted in System | Tagged 14.0savvy 15.0savvy | Leave a comment

AppleScript入門②AppleScriptを使う「考え方」

Posted on 8月 15, 2024 by Takaaki Naganoya

AppleScriptを使ったことのない人が、AppleScriptを使うときに、どのような考え方で問題を解決したらよいでしょうか?

(1)特定のアプリ上でのデータの作成/取得

AppleScriptの一番やりやすい作業は、アプリケーションの書類を大量に作成/チェックするというものです。

書類をともなうアプリで、AppleScriptに対応しているものは、AppleScriptによる書類作成やチェックの自動化が行える可能性が高いと考えてよいでしょう。

Word、Excel、PowerPoint、Pages、Numbers、Keynoteなどのオフィスアプリ。

InDesign、Illustrator、Photoshopといったクリエイティブ系のアプリ。

そうしたアプリを中心に作業を自動化したい、という話はとても「やりようがある」と考えます。難易度が低いわけではありませんが、何か困っていて解決したいことがある場合には、解決できる可能性が高い、ということです。

(2)Webブラウザやメーラーの操作

日常的に使う機会の多いWebブラウザやメーラーで行う作業をまとめて自動化することができます。

やや、難易度が高くなりますが……Webブラウザを操作して特定のWebサイトにログインして、データを取得し、ログアウトするという操作は実際にAppleScriptで行えるものの代表的なものです(Webサイト側の「作り方」によってうまく操作できないこともあります)。

メーラー関係の作業についても、大量のメールを、内容を変更しつつ送信するという作業はAppleScriptに適した作業です。ただし、日常的に利用しているメーラーが、Appleのメール.appである必要があります。他のメーラーではAppleScriptへの対応度が低いとかまったく対応していないケースがあるため、これ以外の選択肢がないといって差し支えないでしょう。

(3)AppleScriptだけでデータ処理

AppleScriptに特殊なデータを扱うような(他のGUIアプリのデータを、アプリなしで読み書きして操作するような)機能は用意されていません。

テキスト、画像、PDF、QuickTimeムービーといった一般的なデータであれば、AppleScriptだけで処理できる可能性は高いところです。とくに、PDFについてはmacOS 10.10以降でmacOSのAPI CocoaをAppleScriptから直接呼べるようになったために、ウォーターマークを追加する「以外」の操作であれば実際に処理できます。

Posted in Beginner | Leave a comment

AppleScript入門① AppleScriptってなんだろう?

Posted on 8月 15, 2024 by Takaaki Naganoya

当Blogでは、日々AppleScriptを書いている中で、「この情報は有用なので共有しておくべき」と考えたものを掲載し、すぐに使っていただけるようにして公開しています。

書き方、使い方、詳しい説明については、電子書籍にまとめて約90冊ほど出しています。

つまり、当BlogはAppleScriptが何であるかを理解していて、実際に書ける人に対して情報を発信する立場です。

ただ、ちょうど夏休みということもあり、ちょっとそのあたりについて書いてみることにしました。

AppleScriptってなに?

「macOS上で動くマクロ言語」とか言うと、何か理解できたような気になりますが……これだけでは何も説明わかりません。

macOS上の機能、各種GUIアプリの機能、shell scriptの機能など、さまざまな機能を呼び出して、データをやりとりする、インタプリタ型(逐次解釈実行型)のプログラミング言語です。

macOS上の大きな機能や小さな機能を呼び出せるようになっていて、とくにGUIアプリの操作や、GUIアプリの設定情報や、GUIアプリがオープンしている「書類」にアクセスして情報をとってきたり、設定したり……という操作が行えます。

AppleScriptがGUIアプリを操作する方法は、いくつか手段が用意されています。

(1)アプリ内の用語辞書を通じてやりとりする

AppleScriptがGUIアプリを操作するやりかたは、マウスカーソルを操作してメニューを選ぶといった方法ではありません(別途ありますが)。それでは、遅すぎるし、画面に表示されていなかったら操作できないですし、「できないこと」が多すぎます。

なので、あらかじめ「こういうコマンドを受け付けるよ!」というコマンドの一覧がAppleScriptに対して読める形でアプリ内に格納されています。ユーザーもこのコマンド一覧(用語辞書)を読んで、AppleScriptを書くことになります。

(2)GUI部品を操作してGUIアプリを操作する

「メニューのx番目の項目を選んでクリックする」といったGUI部品を操作するやりかたです。これはこれで便利ではあるものの、スピードが(1)にくらべて100倍以上遅いですし、毎回確実に動くAppleScriptをこの方法で書くのは、けっこう難しいです。

いまだと、システム設定.appを操作していろんなシステムの状態を変更するようなAppleScriptを動かしたいと考えているユーザーさんがけっこういて、そのための方法をいろいろ探してはいるんですけれど、システム設定.appで細部まですべて操作するのはかなり無理があるので(iOSっぽい作り方になったことが災いして、GUI部品の階層を追いきれない)、この(2)の方法があるからできるっしょ! と、安易に考えないほうがいいです。

先日、X(旧Twitter)上でMacにつながっている複数のディスプレイのうち、メインディスプレイを切り替えたり、画面の解像度を切り替えたいという人がいて、ちょっとやりとりしました。その彼は、この(2)の方法でなんとかなるんじゃないかと考えていたようですが、実際に自分でやってみたところ、それはできませんでした。

なので、かつて調べてあった「SwitchResX」を用いる記事を紹介したところ、「有料アプリを買うほどではない」とのことでした。事実上、SwitchResXを使う方法でしか実現できないのですが、どうするんでしょう?

(3)その他の手段をさがす

shell commandなどでディスプレイ解像度を取得・変更するものがあれば、それを呼び出すことになります。

Posted in Beginner | Leave a comment

デフォルトインストールされたフォント名を取得するAppleScript

Posted on 8月 3, 2024 by Takaaki Naganoya

macOSにインストールされているフォントの情報をsystem_profiler経由で取得し、各フォントのパス情報をもとに、/System/Library/Fonts以下に入っているものだけを抽出して、フォント名をリストアップするAppleScriptです。

Pages書類に含まれているフォントのうち、デフォルトインストールされたものではないものを抽出するために、OSにデフォルトインストールされたものだけを取得すべく、基礎情報を得るために書いてみたものです(現在執筆中の電子書籍「Pages+AppleScriptで本をつくろう!」の付録Scriptとして用意しました)。

事前に何か設定するといった必要はありません。スクリプトエディタやScript Debuggerで実行するだけです。

AppleScriptからフォントの存在するパス情報はなかなか取得しにくい、FontBook.appがAppleScript非対応になったので、ほぼ無理なのですが、system_profilerから取得すれば、それほど難しくありません。

実行所要時間は、

  M1 Mac mini (macOS 13.6):6秒
  M2 Mac mini(macOS 14.6):10秒
  M2 MacBook Air(macOS 14.6):15秒

ぐらいで、M1 Mac miniの速さが光ります。OSの違いから、macOS 13.6環境ではallFontsが1168、macOS 14.6環境では1603とフォント数がどうやら異なっているのですが(M2 miniも同じ)、フォント数を考慮してもM1 Mac miniの処理の速さが光ります。

もしくは、macOSのバージョンの違いにより、system_profilerの実行速度が大きく異なるとか? macOS 13.6環境と14.6環境にそれほど差があるものなんでしょうか。

無駄な処理も入っていますが、いろいろチェックしながら作ったもので、ベンチマーク用に作ったものではありません。

# M2 Airってなんでこんなに時間がかかるんだろう? 放熱台に乗せて処理しているのに。処理のほとんどの時間がsystem_profilerの実行で消費しています

AppleScript名:OSデフォルトインストールされたフォント名を取得.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/08/03
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

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

property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property NSPredicate : a reference to current application’s NSPredicate
property NSMutableArray : a reference to current application’s NSMutableArray
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSPropertyListFormat : a reference to current application’s NSPropertyListFormat
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property NSPropertyListImmutable : a reference to current application’s NSPropertyListImmutable
property NSPropertyListSerialization : a reference to current application’s NSPropertyListSerialization

script spd
  property sRes : missing value
  
property aSource : missing value
  
property bRes : missing value
  
property fontNames : {}
  
property fontPath : {}
  
property outList : {}
end script

–システムにインストールされているフォントの情報を全抽出
set sRes of spd to do shell script "system_profiler -xml SPFontsDataType"
set aSource of spd to first item of (readPlistFromStr(sRes of spd) of me)

–全フォント情報から、名称とパス情報を抽出
set bRes of spd to (((aSource of spd)’s valueForKeyPath:"_items"))
set fontNames of spd to ((bRes of spd)’s valueForKeyPath:"_name") as list
set fontPath of spd to ((bRes of spd)’s valueForKeyPath:"path") as list

–ループでOSデフォルトインストールされているフォントを抽出
set outList of spd to {}
set aCount to 1

repeat with i in (fontPath of spd)
  set j to contents of i
  
  
if j begins with "/System/Library/Fonts/" then
    –指定のフォントに複数のTypefaceが含まれていることを考慮し、情報を取り出す
    
set outItem to (((item aCount of (bRes of spd)))’s valueForKeyPath:"typefaces._name") as list
    
set the end of (outList of spd) to outItem
  end if
  
  
set aCount to aCount + 1
end repeat

–すべてのTypefaceを入れた入れ子の2D Listから1D Listに変換
set allFonts to FlattenList((outList of spd)) of me

–ドット(.)ではじまるフォントを除外
set outList to {}
repeat with i in allFonts
  set j to contents of i
  
if j does not start with "." then
    set the end of outList to j
  end if
end repeat

return outList

–stringのplistを読み込んでRecordに
on readPlistFromStr(theString)
  set aSource to NSString’s stringWithString:theString
  
set pListData to aSource’s dataUsingEncoding:(NSUTF8StringEncoding)
  
set aPlist to NSPropertyListSerialization’s propertyListFromData:pListData mutabilityOption:(NSPropertyListImmutable) format:(NSPropertyListFormat) errorDescription:(missing value)
  
return aPlist
end readPlistFromStr

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

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

–By Paul Berkowitz
–2009年1月27日 2:24:08:JST
–Re: Flattening Nested Lists
on FlattenList(aList)
  set oldDelims to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to {"????"}
  
set aString to aList as text
  
set aList to text items of aString
  
set AppleScript’s text item delimiters to oldDelims
  
return aList
end FlattenList

★Click Here to Open This Script 

Posted in Font | Tagged 12.0savvy 13.0savvy 14.0savvy 15.0savvy | Leave a comment

Post navigation

  • Older posts
  • Newer posts

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

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • 指定のWordファイルをPDFに書き出す
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • AppleScriptによる並列処理
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • macOS 14.xでScript Menuの実行速度が大幅に下がるバグ
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • Keynote/Pagesで選択中の表カラムの幅を均等割
  • macOS 15でも変化したText to Speech環境
  • デフォルトインストールされたフォント名を取得するAppleScript
  • macOS 15 リモートApple Eventsにバグ?
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • Keynoteで2階層のスライドのタイトルをまとめてテキスト化

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (194) 14.0savvy (147) 15.0savvy (132) CotEditor (66) Finder (51) iTunes (19) Keynote (117) 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 (55) 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
  • 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)
  • 未分類

アーカイブ

  • 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