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

月: 2020年10月

アプリケーションが扱えるデータ拡張子を取得

Posted on 10月 28, 2020 by Takaaki Naganoya

指定のアプリケーションが扱えるデータ拡張子を取得するAppleScriptです。

アプリケーションバンドル内のInfo.plistの、CFBundleDocumentTypesエントリの中のCFBundleTypeExtensionsを拾ってリストで返します。用途は、このアプリケーションに表示させるためのものです。

ただ、この標準的といいますか一般的な処理でこのデータを拾ってこれないアプリケーション(凝った処理をしているもよう)がかなりの数存在し、それらについては個別に対応処理を書かないとダメっぽいです。

だいたい、AppleのiWork Appsが全滅。BBEditも独自の記述をしているらしく、Pixelmator Proも少し凝った書き方をしているもよう(Pixelmator Proが「凝っていない」部分なんてないみたいですが)。個別にInfo.plistからエントリをたどって拡張子リストを作るしかなさそうです。

OS内、具体的に言えばNSApplicationとかNSBundleにそういうInfo.plistをあさってこなくても対応ドキュメントデータ型を渡してくれるようなサービスがありそうな気がとてもするのですが、なかなか見つかりそうにありません。

あまりに対応が大変だった場合には、機能を盛り込むことを断念するかもしれません。メタデータから拾ってこれたりすると楽でよいのですが……。


▲結局、できた模様

AppleScript名:アプリケーションが扱えるデータ拡張子を取得.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/28
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set aPath to POSIX path of (choose file of type {"com.apple.application-bundle"})
set aURL to (current application’s |NSURL|’s fileURLWithPath:aPath)
set exResList to getDocumentTypesExtensionsFromPath(aURL) of me

return exResList
–> {".INDD", ".INX", ".IDMS", ".INCD", ".INCX", ".ICML", ".INCA", ".ICMA", ".P65", ".T65", ".PMD", ".PMT", ".QXD", ".QXT", ".INDT", ".INDB", ".INDL", ".INLX", ".FLST", ".PRST", ".PDFS", ".joboptions", ".DCST", ".LNST", ".UDC", ".InDesignPlugin", ".PSET", ".SMRD", ".SMWT", ".IDML", ".IDPP", ".INDK", ".INLK", ".CSF", ".ASE", ".ACB", ".ACBL", ".IDPK", ".INJB", ".INRS", ".INCP", ".INDP", ".ICAP", ".IDAP", ".INMS", ".epub"}

on getDocumentTypesExtensionsFromPath(aURL)
  set aRes to getDocumentTypesFromAppURL(aURL) of me
  
  
set exRes to {}
  
repeat with i in (aRes as list)
    set j to (current application’s NSDictionary’s dictionaryWithDictionary:(contents of i))
    
set tmpExt to (j’s valueForKey:"CFBundleTypeExtensions")
    
    
if tmpExt is not equal to missing value then
      set tmpExt to tmpExt as list
      
repeat with ii in tmpExt
        set jj to "." & (contents of ii)
        
if (jj is not in exRes) and (jj is not equal to ".*") and (jj is not equal to ".???") then
          set the end of exRes to jj
        end if
      end repeat
    end if
  end repeat
  
  
return exRes
end getDocumentTypesExtensionsFromPath

on getDocumentTypesFromAppURL(aURL)
  set aBundle to current application’s NSBundle’s bundleWithURL:aURL
  
if aBundle = missing value then return {}
  
set aInfo to aBundle’s infoDictionary()
  
if aInfo = missing value then return {}
  
set aRes to aInfo’s objectForKey:"CFBundleDocumentTypes" –Document Types
  
if aRes = missing value then return {}
  
return aRes
end getDocumentTypesFromAppURL

★Click Here to Open This Script 

Posted in file File path | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy NSBundle NSDictionary NSURL | Leave a comment

Window表示とMenu表示を切り替える

Posted on 10月 26, 2020 by Takaaki Naganoya

Xcode上で記述するCocoa AppleScriptアプリケーションで、通常のWindow表示とステータスバーから呼び出すメニュー内に表示するスタイルの切り替えテストプログラムです。

macOS 10.14.6上でXcode 11.3.1を動かして確認しています。

–> Download toggleWindow.zip (Xcode Project Archive)

この機能は実際に使いたいと思っていたものの、なかなかうまく実装できていませんでした。

個人的に、GUIベースのアプリケーションを作っていると、環境設定まわりの機能を実際に組む段階でやたらと時間がかかって大変でした。

アプリケーションのメインウィンドウ上に表示している部品を環境設定ウィンドウにも同様に出す必要が出てくるわけで、その場合同じものを2度作ることは避けたいところです。通常表示している部品と、環境設定ウィンドウで表示する部品は同じものを使いまわしたいところです。

それをどのように共通化してGUI部品のかたまりを「使い回す」かについては、頭の痛い問題でした。なかなか過去形で表現するのがはばかられる状況ですが(未解決)、ここをクリアしないことには話になりません。

本テストプログラムでは、Window上に表示するビュー(NSView)とメニュー内に表示するビューに同じものを指定しています。これで、複数の場所に同じビューを使いまわしやすくなるだろうか、というところです。

NeXTstepにティアオフ・メニューという、メニューをドラッグ&ドロップするとメニューから切り離してフローティングパレットのように運用できる機能がありました。Macのアプリケーションでもこれを実装したものを見たことはありますが、使い勝手がいいかと言われると「それほどでも」といった印象でした

途中、NSMenuを閉じる処理で行き詰まっていたところ、Twitter上で@masakihoriさんに解決策を教えていただきました(aMenu’s cancelTracking())。ありがとうございます。

実際に、Window表示されているViewをメニューに入れてみたところ、いろいろ挙動が変わってくることを確認できました。ポップアップメニューについては操作できず、NSTabViewを配置して切り替えてみても、切り替えたことが内部のビューに通知されない様子。メニューに入れて使うべきではないと思われました。

テキストビューも、一応入力はできるもののコピー&ペーストなどの操作は行えません。もともと、メニューにテキストビューが入っていると違和感がすごいので、するべきではないでしょう。

セグメントビューについてはまともに使えますし、スライダーもまともに動作します。試してはいませんが、Date Picker(カレンダー表示)あたりが限界ではないでしょうか。WebViewもメニューに入れられると思いますが、どの程度インタラクティブに操作できるかについては未確認です。

本サンプルについて、当初はステータスバー上のステータスアイテムからPopoverを表示させようかと考えたのですが、menu bar extra(ステータスアイテム)からPopoverは表示できないんですね(Uni Detectorのときに実験してうまく行かず、github上で公開している人のコードも眺めてみましたが……上から下まで全部自前で作っているようでした)。

そのうえ、Appleからも「menu bar extra(ステータスアイテム)からPopoverを表示するんじゃねえ」と釘を刺されているとのことで、ステータスアイテムからメニューを表示、その中にカスタムビューを入れてみた次第です。

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— Toggle Window test
—
— Created by Takaaki Naganoya on 2020/10/26.
— Copyright © 2020 Takaaki Naganoya. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property theView : missing value
  
property aButton : missing value
  
  
property aFlag : true
  
property aStatusItem : missing value
  
  
property aMenu : missing value
  
property bMenuItem : missing value
  
  
on applicationWillFinishLaunching:aNotification
    aButton’s setTitle:"–> Status Menu"
    
set aFlag to true
    
theWindow’s setContentView:theView
  end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    — Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on clicked:aSender
    set aTag to (tag of aSender) as integer
    
    
if aTag = 100 then
      if aFlag = true then
        –通常Window表示→Menu表示
        
my makeStatusItem()
        
theWindow’s performClose:aSender
        
aButton’s setTitle:"–> Window"
      else
        –Popup表示→通常Window表示
        
        
bMenuItem’s setHidden:true
        
theView’s setHidden:true
        
aMenu’s cancelTracking()
        
        
theWindow’s setContentView:theView
        
theView’s setHidden:false
        
theWindow’s makeKeyAndOrderFront:aSender
        
        
current application’s NSStatusBar’s systemStatusBar()’s removeStatusItem:aStatusItem
        
        
aButton’s setTitle:"–> Status Menu"
        
        
–自分を最前面に
        
current application’s NSApp’s activateIgnoringOtherApps:true
      end if
      
      
set aFlag to not aFlag –Flip Flap
      
    else if aTag = 110 then
      display notification "Clicked 1"
      
    else if aTag = 120 then
      display notification "Clicked 2"
      
    else if aTag = 130 then
      display notification "Clicked 3"
      
    end if
    
    
  end clicked:
  
  
on actionHandler:aSender
    –Do nothing
  end actionHandler:
  
  
  
on makeStatusItem()
    –if aStatusItem = missing value then return
    
    
set aStatusItem to current application’s NSStatusBar’s systemStatusBar()’s statusItemWithLength:(current application’s NSVariableStatusItemLength)
    
    
aStatusItem’s setTitle:"🍎"
    
aStatusItem’s setHighlightMode:true
    
aStatusItem’s setDelegate:me
    
aStatusItem’s setAction:"statusclicked:"
    
    
set aMenu to current application’s NSMenu’s alloc()’s init()
    
    
set bMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:"" action:"actionHandler:" keyEquivalent:"")
    
bMenuItem’s setView:theView
    (
bMenuItem’s setTarget:me)
    (
aMenu’s addItem:bMenuItem)
    
    
aStatusItem’s setMenu:aMenu
  end makeStatusItem
  
  
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy | 2 Comments

CotEditor v3.9.7でAppleScriptコマンドを追加

Posted on 10月 23, 2020 by Takaaki Naganoya

CotEditor v3.9.7(macOS 10.1510.13以降対応)でAppleScript用語辞書にコマンドが追加されていました。

document中のselectionに対して処理を行うもので、英語のダブルクォート/シングルクォートをワープロ的なクォート開始文字とクォート終了文字に置き換えます。


▲smarten quotes実行前


▲smarten quotes実行後


▲straighten quotes実行前


▲straighten quotes実行後

AppleScript名:smarten quotes
tell application "CotEditor"
  tell front document
    smarten quotes selection
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:straighten quotes
tell application "CotEditor"
  tell front document
    straighten quotes selection
  end tell
end tell

★Click Here to Open This Script 


▲smarten quotes実行前


▲smarten quotes実行後

Posted in news | Tagged 10.15savvy 11.0savvy CotEditor | Leave a comment

Finderファイルタグの設定、取得、クリア

Posted on 10月 23, 2020 by Takaaki Naganoya

Finderタグの削除(クリア)を行うAppleScriptです。

AppleScript名:Finderファイルタグの設定、取得、クリア
–Created By Shane Stanley
–Modified By Takaaki Naganoya
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property |NSURL| : a reference to current application’s |NSURL|
property NSOrderedSet : a reference to current application’s NSOrderedSet
property NSURLTagNamesKey : a reference to current application’s NSURLTagNamesKey

set anAlias to (choose file)
clearTagsForPath(anAlias) of me –delete tags
set aRes to getTagsForPath(anAlias) of me –check

— clear all tags
on clearTagsForPath(anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
aURL’s setResourceValue:{} forKey:(NSURLTagNamesKey) |error|:(missing value)
end clearTagsForPath

— get the tags
on getTagsForPath(anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
set {theResult, theTags} to aURL’s getResourceValue:(reference) forKey:(NSURLTagNamesKey) |error|:(missing value)
  
if theTags = missing value then return {} — because when there are none, it returns missing value
  
return theTags as list
end getTagsForPath

— set the tags, replacing any existing
on setTagsForPath(tagList, anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
aURL’s setResourceValue:tagList forKey:(NSURLTagNamesKey) |error|:(missing value)
end setTagsForPath

— add to existing tags
on addTagsForPath(tagList, anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
— get existing tags
  
set {theResult, theTags} to aURL’s getResourceValue:(reference) forKey:(NSURLTagNamesKey) |error|:(missing value)
  
if theTags ≠ missing value then — add new tags
    set tagList to (theTags as list) & tagList
    
set tagList to (NSOrderedSet’s orderedSetWithArray:tagList)’s allObjects() — delete any duplicates
  end if
  
aURL’s setResourceValue:tagList forKey:(NSURLTagNamesKey) |error|:(missing value)
end addTagsForPath

★Click Here to Open This Script 

Posted in file Tag | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy | Leave a comment

Universal Binaryチェックツール「Uni Detector」をMac App Storeでリリース

Posted on 10月 21, 2020 by Takaaki Naganoya

Universal Binaryチェックツール「Uni Detector」をMac App Storeで無料リリースしました。macOS 10.13以降用です。私の作るものなので、すべてAppleScriptで記述してあります。

前作「うにばーさる」はPowerPCからIntelへの切り替え時に、AppleScript Studioで作りました。

「Uni Detector」はAppleScriptObjCで作成。いろいろこなれてきているのですが、商品にはなりそうにもなかったので(そんなにひんぱんにバイナリアーキテクチャを調べたい人はいない)宣伝用にフリー配布です。

# Macの販売店の店頭でデモするのには向いているかも?

バイナリ対応度を調べるだけのソフトウェアでは、一度試したらおしまいです。日常的にこのソフトウェアを使うと便利なよう、自分で使い込んでさまざまな機能を実装しました。アプリケーションのメタデータを読み込んで、しぼり込み検索してカテゴリごとのバイナリアーキテクチャ分布を調べられるようにしました。

また、Universalバイナリ対応のほかに「AppleScript対応度」の調査もこのアプリケーションの1つの大きなテーマにすえました。AppleScript対応度もカテゴリごとに調査できます。「Microsoft」や「Adobe」をキーワードに絞り込んで、アーキテクチャやAppleScript対応度を調査することも可能です。

Scriptableなアプリケーションの一覧を表示したり、選択中のアプリケーションのAppleScript用語辞書を表示させたり、とくに本Blog上のサンプルScriptを表示させる機能がよそには真似できないところでしょう。

一覧で選択したアプリケーション名をキーとして本Blogの記事を検索・表示させる「サンプルScript表示機能」。これだけのためにポップアップするミニWebブラウザを実装しています。

「Universal Binary」は、NeXT時代のMAB(Multi Architecture Binary)、FATバイナリを引き継いだもので、NEXTSTEP(正確には後継のOPENSTEP)時代にはx86(Intel)、68K(NeXT)、SPARC(Sun)、PA-RISC(HP)などの複数アーキテクチャ向けバイナリをまとめてパッケージ内に格納できていました。

当時は複数アーキテクチャ、複数環境をサポートするための技術と受け取っていましたが、Mac OS X上での使われ方は自社プラットフォームのCPU切り替えを円滑に行うためのもので……MAB/FATバイナリとはモノが同じでありながら運用の仕方が全然違いますね。

技術的には、ツールバー上のSegmented Controlで作ったボタンがmacOS 11.0上でどう見えるか、きちんと見えるのか、Betaのたびにコロコロ見え方が変わるので、そのあたりを回避したらどうなるのかとか、そういう実証試験を行なっています。

また、macOS 10.15以降でアプリケーションフォルダ(/Applications)の内容が、/Applicationsと/System/Applications/に分かれ、フォルダの内容をScriptから取得できないあたりで悩まされました。アプリケーションのアイコンをInfo.plist経由で取得できないケースも見られ(とくに、Apple純正アプリケーション)、そのあたりの対処も悩まされたところです(フリー配布なのに手間がかかりまくっていて大変です)。

Terminal.appのコントロールを行なったら一発リジェクトでしたが、スクリプトエディタのコントロールはいいんだ、へーという発見はありました(macOS 10.14で「execute」コマンドが削除されたので無害?)。アプリケーションのAppleScript用語辞書を表示させているだけなので、コントロールというレベルではありませんけれども。

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

Pixelmator Proでアイコン書き出しv2

Posted on 10月 19, 2020 by Takaaki Naganoya

Pixelmator Proで1024×1024 pixelの画像をmacOSのアプリケーションアイコン素材用に各サイズにリサイズして連続書き出しするAppleScriptです。

Pixelmator ProのAppleScriptプログラミングコンテスト優勝賞品Pixelmator Pro。非破壊画像処理を行い、GPUベースの高速な処理を行うPixelmator Proを実務的な画像処理に使うとどんな感じなのか、いろいろ調べていたらアイコン書き出し用の複数同時解像度書き出し機能などはついていなかったので、さくっと作ってみました。

Photoshopを操作して各種解像度書き出しを行うよりも高速に感じます(厳密にベンチマークを計測したわけではないんですけれども)。

AppleScript名:Pixelmator Proでアイコン書き出しv2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/19
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set resolList to {1024, 512, 256, 128, 64, 32, 16}
set aTargFileBase to (choose file name with prompt "Select Export base name") as string

tell application "Pixelmator Pro"
  if (exists of document 1) = false then
    display dialog "There is no document" buttons {"OK"} default button 1 with icon 1
    
return
  end if
  
  
tell the front document
    set aWidth to width
    
set aHeight to height
    
    
if {aWidth, aHeight} is not equal to {1024.0, 1024.0} then
      display dialog "Wrong Image Size (1024×1024 required)" buttons {"OK"} default button 1 with icon 2 with title "Size Error"
      
return
    end if
    
    
repeat with i in resolList
      resize image width i height i resolution 72 algorithm bilinear
      
export to file (aTargFileBase & "_" & (i as string) & "x" & (i as string) & ".png") as PNG
      
undo
    end repeat
  end tell
end tell

★Click Here to Open This Script 

Posted in file Image | Tagged 10.14savvy 10.15savvy 11.0savvy Pixelmator Pro | 1 Comment

Unicode Checker

Posted on 10月 16, 2020 by Takaaki Naganoya

Unicode Checkerはアップデートを定期的にチェックして、文字のUnicode上の詳細な仕様を確認するためによく使っています。記事作成時のバージョンは1.22です。

一度、Unicode CheckerのAppleScript対応度については紹介したことがあったような気がしましたが、いま探してみたら見つかりません。2018年初頭にBlogが吹き飛んだときに一緒にお星様になってしまったものと思われます。

Unicode Checker自体の機能は文字情報のデータベース的なものなので、AppleScriptから操作してまとまった処理(大量のデータ処理)を行わせる必要はあまりなさそうですが、単に1つの文字のデータを別のアプリケーションから取り出して、それをUnicode Checkerに情報表示させるなどの「ドミノ倒し」的な処理を行わせるような用途に使う感じでしょうか。

おそらく開発側も、「こういう(AppleScript対応の)機能もウチは作れるよ」というデモとしてこの機能を実装したものと思われます。

AppleScript名:current code pointを指定して文字表示
tell application "UnicodeChecker"
  set current code point to "あ"
end tell

★Click Here to Open This Script 

AppleScript名:findコマンドのじっけん
tell application "UnicodeChecker"
  set aRes to find codepoint "200B" with including unihan definitions –UTF-16
end tell

★Click Here to Open This Script 

AppleScript名:現在表示中の文字(code point)を取得する
tell application "UnicodeChecker"
  properties of current code point
  
–> {bidi mirrored:false, containing plane:plane id 0 of application "UnicodeChecker", id:12354, line break:"ID", assigned:true, canonical combining class description:"Not_Reordered", unicode name:"HIRAGANA LETTER A", assigned to abstract character:true, code point type:Graphic, class:code point, bidi class description:"Left_To_Right", script name:"Hiragana", general category description:"Other_Letter", bidi class:"L", containing block:block "Hiragana" of application "UnicodeChecker", general category:"Lo", name:"あ", canonical combining class:0}
end tell

★Click Here to Open This Script 

AppleScript名:UnicodeCheckerでUTF-8の文字コードを得る
tell application "UnicodeChecker"
  get escaped representation of (deXHTMLized representation of "あ")
  
–> "%E3%81%82"
end tell

★Click Here to Open This Script 

AppleScript名:IDNA representationのテスト
tell application "UnicodeChecker"
  set aRes to IDNA representation of "愛" using IDNA 2008
  
–> "xn--vgu"
  
  
set aRes to IDNA representation of "愛" using IDNA 2003
  
–> "xn--vgu"
end tell

★Click Here to Open This Script 

AppleScript名:deIDNAized representationのじっけん
set aStr to "愛"

tell application "UnicodeChecker"
  set aRes to IDNA representation of aStr using IDNA 2008
  
–> "愛"
  
  
set bRes to deIDNAized representation of aRes
  
–> "愛"
end tell

★Click Here to Open This Script 

AppleScript名:deXHTMLized representationのじっけん
set aStr to "愛"

tell application "UnicodeChecker"
  set aRes to XHTML representation of aStr
  
–> "愛"
  
  
set bRes to deXHTMLized representation of aRes
  
–> "愛"
end tell

★Click Here to Open This Script 

AppleScript名:XHTML representation ofのサンプル v2
set aStr to "愛"

tell application "UnicodeChecker"
  set aRes to XHTML representation of aStr
  
–> "愛"
  
  
set bRes to XHTML representation of aStr with use decimal entities
  
–> "愛"
  
  
set cRes to XHTML representation of aStr without use decimal entities
  
–> "愛"
  
  
set dRes to XHTML representation of aStr with named entities
  
–> "愛"
  
  
set eRes to XHTML representation of aStr with converting low ASCII
  
–> "愛"
  
  
set fRes to XHTML representation of aStr without converting low ASCII
  
–> "愛"
end tell

★Click Here to Open This Script 


▲自分の作ったツール(Uni Detector)の中から、指定アプリケーションのサンプルScriptを表示させる機能を実装したので、ツールのためにひととおりサンプルを掲載してみる予定

Posted in Text | Tagged 10.14savvy 10.15savvy 11.0savvy Unicode Checker | Leave a comment

macOS 10.15以降のカレンダーアプリケーション内に同梱された大量のAppleScriptを発見

Posted on 10月 15, 2020 by Takaaki Naganoya

たまたま、macOS 11.0Betaで特定のアプリケーションのアイコンを取得できない問題に直面し、その調査を行なっていたところ……カレンダーアプリケーションのバンドル内のResourcesフォルダに大量(32本)のAppleScriptが入っているのを見つけました。

見つけたのはmacOS 11.0Beta上ですが、10.15.7環境でもチェックしてみたところ同数のAppleScriptが入っていました。10.14.6ではみつかりません。10.15.x以降でこうなっているようです。

macOS 10.15はBetaの途中で「これは使い物にならない!」と見切りをつけ、テスト環境で様子を見ながらも本気では使い込んでこなかったので、いまごろ細かい変更点に気づきました(全力で10.15はパスして11.0に移行したいです)。


▲macOS 10.15.7のカレンダー内に入っているAppleScriptと11.0betaに入っているもののdiffをとってみた結果。違いはないもよう

拡張子がscptで、実行専用になっていません。つまり、中身が読めるわけです。

サンドボックス環境のアプリケーションが内部からこうしたAppleScriptを呼ぶ際には実行専用で、かつファイルを読み取り専用に設定しておく必要があります。読み取り&編集可能な状態なので、サンドボックス化されている「カレンダー」アプリケーションがこれらを内部で呼び出している可能性は低そうです。部品として入れるならハンドラ宣言を行なって、外部から呼び出しやすいようにするはずです。これらのAppleScriptをテンプレートとして読み込んで、変数内容を実際のデータに置換して実行するという方法もないことはありませんが、そこまでやらないでしょう(必要に迫られて、やったことありますけれども)。そういう使い方をするならテキスト形式で保存しておくとか、もっと「テンプレートらしく」書いておくことでしょう。書き換え部分を「%@」と書いておくとか。

よって、カレンダーアプリケーション内部でこれらのAppleScript群を呼び出している可能性はほとんどないと思います。

実際にScriptの内容を読んでみると、基礎的なカレンダーアプリケーションの操作を行う、地に足のついた実に質実剛健で良質なサンプルScript集という雰囲気でした。AppleのサンプルScriptにありがちな、冒頭に著作権と(訴訟回避の)お断り文言のオンパレードのテンプレートコメントが30行ぐらい書いてありそうなものではありません。

AppleScript名:addAttendees.scpt
–> Script creates an event and adds invitees. Please modify the email to test account before running the script
set theStartDate to (current date)
set hours of theStartDate to 15
set minutes of theStartDate to 0
set seconds of theStartDate to 0
set theEndDate to theStartDate + (1 * hours)
tell application "Calendar"
  tell calendar "calendar"
    make new event with properties {summary:"Apple Script Invitations", start date:theStartDate, end date:theEndDate, location:"one Infinite Loop"}
    
    
set theEvent to (first event where its summary = "Apple Script Invitations")
    
tell theEvent
      make new attendee at end of attendees with properties {display name:"test", email:"caltest_as1@icloud.com"}
    end tell
  end tell
end tell

★Click Here to Open This Script 

自分もCotEditorのサンプルAppleScriptパックを配布していますが、あれの飛び道具系(PowerPack)ではなく、基礎的なBasicPackの雰囲気です。

この手のサンプルScriptというと、AppleがmacOSに同梱している悪夢のようなApple純正サンプルスクリプト集があるわけですが(日本語環境で構文確認が通らないとか言語道断。しかも書き方が古臭い)、そういうテイストではありません。

「実務でAppleScriptを書いている人間」による簡素なテストコードといった雰囲気を感じます。

まるで、Apple社内で機能テストに使っているAppleScriptがそのままRelease版に残ってしまったような感じです。正確なところはわかりませんけれども。

意図して入れているのか、意図していないのかはまったく不明ですが、OSのアップデートで消去されないうちにバックアップをとっておくことをおすすめします。

このScriptを入れてあることが何かのメッセージなのかどうかは不明です。たいして意味はないでしょう。ただ、Apple社内もしくは外注にちゃんとまともなAppleScriptを書ける人間がいるぞ、という自己紹介的なものだと受け取っておきます。

カレンダーアプリケーションのAppleScript用語辞書内にこれらのAppleScriptサンプルを(本Blog掲載のAppleScriptのようにリンクつきで?)掲載しておけという指定を受けた部下が、その言葉の意味がわからずにそのままバンドル内に渡されたAppleScriptをファイルのまま入れてしまったというあたりが真相ではないかと思われます。

Posted in news | Tagged 10.15savvy 11.0savvy Calendar | Leave a comment

Xcode 12上でのCocoa AppleScriptアプリケーションのUniversalビルド状況

Posted on 10月 14, 2020 by Takaaki Naganoya

目下、最大の関心事はmacOS 11向けにXcode上のCocoa AppleScriptアプリケーションをApple Sillicon & IntelのUniversal Binaryでビルドする方法についてです。

まず、Xcode 12と言われるものは2系列存在しています。Xcode 12.1GMと呼ばれるものと、Xcode 12.2Beta 3です。

調査前には、「Xcode 12.1GMを使ってビルドするんじゃないの? GMだし」と思っていました。Mac App StoreはReleaseビルドのXcodeからのアプリケーション送信しか受け付けない仕様になっているため、Beta版の出来がいくらよくても、GM版、Release版が必須です。

ただ、Xcode 12.1GMでCocoa AppleScriptアプリケーションをUniversal Binaryでビルドしようとしても、出来上がるバイナリはIntel 64bit向けのみです。

だいたい、Xcode 12.1GM上ではビルドターゲットとして「macOS 11.0」を選択できません。

これまでにARM/IntelのUniversal Binaryビルドできたのは、Xcode 12.2Beta2。GM版ではどれもビルドできていません。

実際に、Xcode 12.2Beta3上でCocoa AppleScriptアプリケーションのプロジェクトをUniversal Binaryビルドできることが確認できました。

ただし、Xcode 12.2beta3上でも、既存のXcodeプロジェクトではUniversal Binaryビルドが行えず、新規作成したプロジェクト(コードはほぼからっぽの状態でテスト)でのみUniversal Binaryビルドできました。まだ、既存のプロジェクトのUniversal BinaryビルドができないあたりがBetaっぽいですが、注意を要するところです。

AppleScriptアプレットのUniversal Binary対応状況

スクリプトエディタから書き出したアプレットは、macOS 11.0Beta初期からUniversal Binaryで書き出されていることを確認しています。

AppleScript Studioランタイムが廃止に

その他、Mac OS X 10.6で廃止になった「AppleScript Studio」のランタイムがXcode上の開発テンプレート廃止後も実行のみサポートが継続されています。

これはAutomator登場初期に作られたAutomatorアクションがこのAppleScript Studioのランタイムを利用していたためです。

Automatorアクションの実行サポートのためにAppleScript Studioのランタイムが最新OS上でも維持され続けてきました。先日、ついにこのAppleScript Studioランタイムの将来的な廃止がAppleのWebサイトに掲載されていました。

AppleScript StudioランタイムのARM Binary(ここも、Xcode上で「ARM」という言葉を使わないようにいろいろ記述が変わっている)化を行なっているとは思えないので、おそらくARM/Intelの両方のCPUサポートを3〜4年ぐらい行い(AppleScript StudioランタイムはRosetta2で実行?)、Rosettaの廃止ライミングでAppleScript Studioランタイムも一緒に廃止するのでしょう。

AutomatorアクションのAppleScriptによる開発テンプレートはAppleScriptObjCベースのものに(とっくの昔に)変更になっています。AppleScriptObjCベースで開発していれば問題ありません。

Posted in news | Tagged 11.0savvy Xcode | Leave a comment

OSADictionaryViewの情報がない

Posted on 10月 12, 2020 by Takaaki Naganoya

macOS 10.10以降、通常のAppleScriptでもCocoaオブジェクトへのアクセスが許可されたため、macOSの中に存在するAppleScript系の機能への理解が深まりました。

正確にいえばOS X 10.6でXcode上のCocoa AppleScriptアプリケーション内でCocoaの機能が利用できたわけですが、やはり通常のAppleScriptの中で利用できると理解の度合いが違います。

そうしたCocoaなどのmacOSのAPIは数多くあり、今日ではPDF関連の処理など専用のアプリケーションを使わずにたいていの処理ができるようになり、Web上のREST APIを自在に呼び出せるようになり、各種画像フィルタ処理や機械学習までAppleScriptから呼び出せるようになりました。Cocoaの機能が呼べなかった時代に戻れと言われたら途方に暮れてしまうレベルで日常的な風景になりました。

そんなmacOS側の機能に、AppleScript系の機能が用意されています。

大きく分けると、

①Cocoa系のOSAKit。AppleScriptを実行したりOSAコンポーネント情報を取得するなどの機能。AppleScriptから日常的によく使っています。

②AppKit内のNSAppleScript。AppleScriptの実行を行うための部品と、プロセス間通信のAppleEventsまわりの機能です。このあたりはAppleScriptからは手が出ません。

③Carbon系のOpenScripting。AppleScript言語処理系そのものといってよいでしょう。まったく手が出ません。

などの機能の所在がわかっています。Xcode上から調べるとヘッダーファイルも調査できて、どのようなメソッドが揃っているかも確認できます。

これらの他に、割とメジャーそうな機能なのにヘッダーファイルも何も一切公開されていないオブジェクトがあります。

それが、AppleScript用語辞書の表示関連のOSADictionaryViewとOSADictionaryControllerです。

これについては、不思議と情報が何もありません。あたりをつけて、「おそらくPathかURLをコントローラーに渡して初期化するとViewに表示するんだろう」と試しているのですが、まったく歯が立ちません。


▲macOS 10.14.6+Xcode 11.3.1の組み合わせで、OSADictionaryViewをドラッグ&ドロップで部品配置すると、その瞬間にXcodeがクラッシュ(事前にプロジェクトにOSAKit.frameworkをinclude)。この環境にはNSBrowserなど同様の瞬間クラッシュを引き起こす部品がある。macOS 10.15上では修正されているため、10.14上での対処は行わないとAppleから明言されました

とりあえずは、いつものアラートダイアログ上でOSADictionaryViewを表示して、指定のsdefファイルを表示するレベルからはじまって、GUIアプリケーション上でSDEF表示機能を実装するところがゴール地点でしょうか。失敗を重ねながら何度も調査やテストを行うことになります。

OSADictionaryView/OSADictionaryControllerの情報があったところで、これが使い物になるのかどうかという疑問があります。

OSADictionaryViewが使えたとして、それはsdefファイルのパスなりURLを渡して表示させるようなものになると想像されますが、このsdefに外部のファイルをincludeするような記述ができるようになったことで、「対象アプリケーションが実際に起動しないとAppleScript用語辞書全体を取得することができない」という状況に。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
	<!-- We override some standard commands to add several optional properties. -->
	<suite name="Standard Suite" code="????" description="Common classes and commands for all applications.">
		<xi:include href="file://localhost/System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite/node()[not((self::command and (@name = 'open')) or (self::class and (@name = 'window')))])"/>

▲最近のMicrosoft Officeアプリケーションでは、sdefのサイズ縮小のためかxi:includeの記述が見られる

Adobeのアプリケーションには、sdefファイルを起動後にプログラムで生成しているものもあるため、起動前の状態でsdefファイル単独でブラウズできてもあまり意味がないケースが生じてしまいます。

つまり、Viewを単体で利用できても不十分かつ部分的なAppleScript用語辞書しか表示できないのではないか? という疑問を持つわけです。


▲1:17秒あたりでToolbar上のコマンドからAppleScript用語辞書の表示を行わせています。これは、Script Editorに辞書の表示を行わせる処理です

実際、スクリプトエディタに指定アプリケーションのAppleScript用語辞書を表示するような命令は行えるので、結局はそちらを使うことになるのではないかと考えるものです。苦労して使い方を突き止めたとしても、実用性がなかったら残念なことです。そして、その可能性がきわめて高そうな気配がしているのです。

Posted in GUI OSA | Tagged 10.14savvy 10.15savvy 11.0savvy | Leave a comment

Pixelmator Pro AppleScriptコンテストで優勝

Posted on 10月 11, 2020 by Takaaki Naganoya

LateNight Software主催の「Pixelmator Pro AppleScriptコンテスト」で優勝しました。応募作品はPixelmatorもぐらたたきゲームです。

応募するにあたって、まず最初に、「まともにPixelmator Proの機能を活用する」か「Pixelmator Proの機能を無視する」かの2つの方向のどちらを採用するかを考えました。

100行以内というレギュレーションがけっこう厳しかったので、前者のアプローチだとすぐに限界に達するように思われました。それ以前に、使いこなしてもいない、ほぼ初見のアプリケーションを相手に有用なAppleScriptを書くのはほぼ無理といってよいでしょう。実際に対象のアプリケーションを使いこなして、そのアプリケーションが想定しているワークフローをこなしてみて、自分の意図するデータを作って、その作業の中で不満に思ったり効率がよくない点をAppleScriptで補っていくのが「普通のAppleScript」の書かれ方でしょう。

短期間でコンテストに投稿するとなると、ウケ狙いでアプリケーション全体の機能を理解せず一部の機能に着目してまったく関係のない用途のものを作る必要があると判断しました。

もうちょっと使いこなすための期間が長ければ、Pixelmator Proの機能を使い込んで、Pixelmator Proならではのソリューションも出てきたと思います。

なので、Pixelmator Pro AppleScriptコンテストの賞品であるところのPixelmator Pro v1.8を使えれば、「本来こういうものがあるべき」というScriptを書くことも可能だと思われます。

告知ページには、

To celebrate the introduction of AppleScript support in Pixelmator Pro 1.8 I’m giving away three copies of Pixelmator Pro. 

と、明記されているので「Pixelmator Pro」(macOS版)が賞品だと思っていたのですが、なぜか送られてきたのが「Pixelmator Photo」(iOS版)のコードで、何か手違いが生じただけだと思いたいのですが、どんなものなんでしょう? → 報告したらちゃんとPixelmator Proのコードが届きました。ねんのため

Pixelmatorもぐら叩きゲームについて


◀︎開発中のFMバトラー(1999年)

1999年のMacWorldExpo/Tokyoでデモを行った「FMバトラー」で、すでに「まったくゲーム用ではないアプリケーション(FileMaker Pro)を使ってゲームを作るという経験がありました。

基本的には、Pixelmator Pro書類上に並べたレイヤーの表示状態を制御して、パラパラアニメを表示。その一方でModifier Keyのキースキャンを行なって、ユーザーからの操作を受け取っています。

レギュレーションに「Script Debugger上で動作すること」という項目があり、Modifier Keyのスキャンであれば最前面にいないScript Debuggerでも問題なくスキャンできるため、対応が可能でした。

プログラムは、とにかく短く書くことが課題で、初期段階ではキースキャン部分だけで20行を超えていたものを大幅に短くしています。

もぐら叩きの本体部分もモグラが3段階で迫ってくるという設定を作り、step 1とstep 2の状態でユーザーからの入力があったら「お手つき」的な失敗を行ったという処理をしています。step 3の状態でのみもぐらの撃退が可能で、そのことをデータで表現しています。

set moleList to {{"Mole1", false, 20}, {"Mole2", false, 10}, {"Mole3", true, 20}}

良くも悪くも「Pixelmator Proでゲームを作ろう」という着想自体がすべてであり、プログラム自体はそれほど複雑でも高尚でもありません。

–> Download Piyomaru Whack-3-moles Game(実行に必要なPixelmator Pro書類)

プログラム自体を掲載していてもあまり参考にならないとは思いますが、本来作りたかった「もぐらが同時に3匹出てくるもぐら叩きゲーム」は見てみたいので、より高度なバージョンに書き換えた人がいればぜひ見せてください(^ー^;

最後に、Pixelmator Proもぐらたたきのグラフィックについて。8bit時代のピコピコゲーム(この部分、Google翻訳で非日本語話者に意味が通じるのだろうか?)を彷彿とさせる簡単さで「たいした手数はかけていない」ことが伝わることを重視しています。Pixelmator Proは写真の加工など高い能力を持ったグラフィックソフトなわけですが、あえてグラフィックソフトらしい写実的かつ写真をベースとした生々しいもぐらの絵を使うことは避けました。

また、あからさまにゲームであることがわかるよう背景も単純な色とし、一般的なPixelmator Proの利用シーンとは異なる状況下にあることをユーザーに知らせるように設計しました。絵心のある人ならもっと凝ったグラフィックを描いて表示するはずですが、そういう作り込み要素を排することで「自分にも作れそうだ」という印象を持ってもらうことを重視しています。あと、生き物の殺生を思わせるような生々しい表現(流血とか)は避けています。

AppleScript名:Mole Game v1.1.1a.scpt
–  Created by: Takaaki Naganoya
–  Created on: 2020/09/29
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit" — for NSEvent

set aScore to 0
set aMiss to 0
set maxMole to 3 —change mole attack number
set delayCount to 300 –delay speed. Faster machine needs larger number.

tell application "Pixelmator Pro"
  activate
  
if (exists of document "Piyomaru Whack-3-moles Game") = false then
    display dialog "There is no Piyomaru document" buttons {"OK"} default button 1 with icon 1
    
return
  end if
  
  
tell document "Piyomaru Whack-3-moles Game"
    set visible of layer "Mole1" to false
    
set visible of layer "Mole2" to false
    
set visible of layer "Mole3" to false
    
set visible of layer "Mole3Hit" to false
    
set visible of layer "Mole3Miss" to false
    
    
repeat 10 times
      tell layer "Title"
        set its visible to true
        
set keyRes to keyscanWait(delayCount, true) of me
        
set its visible to false
        
set keyRes to keyscanWait(delayCount, true) of me
        
if keyRes = true then exit repeat
      end tell
    end repeat
    
    
delay 1
    
    
set moleList to {{"Mole1", false, 20}, {"Mole2", false, 10}, {"Mole3", true, 20}}
    
repeat maxMole times
      repeat with i in moleList
        copy i to {layerName, hitLogic, delayTime}
        
set visible of layer layerName to true
        
set keyRes to keyscanWait((random number from 1 to delayTime) * delayCount, hitLogic) of me
        
set visible of layer layerName to false
        
        
if keyRes = true then
          set hitF to true
          
set aScore to aScore + 1
          
beep
          
set visible of layer "Mole3Hit" to true
          
delay 1
          
set visible of layer "Mole3Hit" to false
          
exit repeat
        else if keyRes = false then
          set aMiss to aMiss + 1
          
repeat 3 times
            set visible of layer "Mole3Miss" to true
            
delay 0.5
            
set visible of layer "Mole3Miss" to false
            
delay 0.5
          end repeat
          
set keyRes to true –To Skip See off action
          
exit repeat
        end if
      end repeat
      
      
if keyRes is not equal to true then
        set aMiss to aMiss + 1
        
repeat 3 times
          set visible of layer "Mole3Miss" to true
          
delay 0.5
          
set visible of layer "Mole3Miss" to false
          
delay 0.5
        end repeat
      end if
    end repeat
    
    
display dialog "Score:" & (aScore as string) & return & "Miss:" & (aMiss as string) with title "GAME OVER" buttons {"OK"} default button 1 with icon 1
    
  end tell
end tell

on keyscanWait(delayLoop, hitLogic)
  repeat delayLoop times
    set commandStatus to not ((((current application’s NSEvent’s modifierFlags() as integer) div (current application’s NSShiftKeyMask as integer)) mod 2) = 0)
    
if commandStatus = true then return hitLogic
  end repeat
  
return missing value
end keyscanWait

★Click Here to Open This Script 

Posted in GAME | Tagged 10.15savvy Pixelmator Pro | 1 Comment

LAN上の別のMacでYouTubeムービー再生をハンズオーバー v2

Posted on 10月 8, 2020 by Takaaki Naganoya

Safariの最前面のウィンドウで再生中のYouTubeムービーの情報を取得し、LAN上の別のMacで再生を引き継ぐ(ハンズオーバーする)AppleScriptです。

macOS 10.13以降、リモートAppleEvents経由でGUIアプリケーションを直接操作する機能が復活しました(Mac OS X 10.7〜10.12ぐらいまでAppleScriptアプレット間のみリモート通信が許可されていた状態)。

メインマシンで再生中のYouTubeムービーを、LAN上の他のマシンに引き継がせてみました。再生を引き継がれる方のマシンでは、システム環境設定の「共有」で「リモートApple Events」の項目をオンにしています(自分のマシンではすべてこの項目をオンにしています)。

(1)リモートマシン上のユーザーのパスワード

AppleScript書類のコメント(Finderコメント)にパスワードを書いておくと、それを読み取って使用するようにしてみました。

(2)リモートマシン上のSafariの起動

リモートマシン上のアプリケーションの操作は、ただリモートマシン上のアプリケーションを指定すればOKなのですが、操作対象のアプリケーションが起動していない場合にはエラーになります。これは、とても困る仕様です。

そこで、リモートマシンのFinder経由でアプリケーションファイルをオープンすることで、リモートマシン上でSafariを起動します。オープン対象をapplication file “Safari”と指定するとエラーになりますが、application file id “com.apple.Safari”と指定するとエラーになりません。

(3)YouTubeで再生中の情報取得

以前調査しておいた内容をそのまま使っています。再生中ならPauseし、再生中の位置(時間)情報を取得し、文字列で指定するために加工してYouTubeのURLに追加しています。URLの加工部分は少々手抜きをしています。

とくに問題なく、メインマシンから他のマシン(macOS 10.15.7/macOS 11.0beta9)にLAN経由で再生をハンズオーバーできました。

実際に、コントロール先のマシン名(Bonjour名)をremoteMachineNameに、ユーザー名をremoteUserNameに、パスワードを実行するAppleScript書類のFinderコメントに書き込んで実行してください。スクリプトエディタ上でもスクリプトメニューからでも問題なく実行できています。

あとは、Safari上のYouTube再生をフルスクリーンで行えるとよいのですが、少し試した範囲ではできなかったので、また地道に調べておく感じでしょうか。

AppleScript名:LAN上の別のMacでYouTubeムービー再生をハンズオーバー v2.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/08
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

property |NSURL| : a reference to current application’s |NSURL|
property NSMetadataItem : a reference to current application’s NSMetadataItem

set remoteMachineName to "MacMini2014.local"
set remoteUserName to "maro"

–ScriptのCommentに書いておいたパスワードを拾って使う
set mePath to (path to me)

–FinderからCommentは拾えるが、メタデータ経由で取得する処理も試してみた
set remoteUserPass to getFinderComment(POSIX path of mePath) of me

tell application "Safari"
  if running then
    tell front document
      set aURL to URL
      
–最前面のウィンドウがYouTubeの場合のみ処理
      
if aURL does not start with "https://www.youtube.com/" then
        display notification "エラー: YouTubeを再生していないため、ハンズオーバーしませんでした"
        
return
      end if
      
      
–再生中のポジションを取得
      
set tRes to (do JavaScript "document.querySelector(’#movie_player video’).currentTime;")
      
      
–再生状況を取得
      
set pRes to (do JavaScript "document.querySelector(’#movie_player video’).paused;")
      
      
if pRes = false then
        –再生中であればPauseする
        
set aRes to (do JavaScript "document.querySelector(’#movie_player .ytp-play-button’).click();")
      end if
      
      
openYouTubeOnRemoteMachine(remoteUserName, remoteUserPass, remoteMachineName, tRes, aURL) of me
    end tell
  end if
end tell

–指定のリモートマシン上のSafariでYouTubeの指定ムービーの指定箇所からの再生を行う
on openYouTubeOnRemoteMachine(remoteUser, remotePass, remoteMachineLocal, newDuration, newURL)
  set remoteMachineName to "eppc://" & remoteUser & ":" & remotePass & "@" & remoteMachineLocal
  
  
–URLの加工。ちょっと手抜きをした
  
if newDuration is not 0 then
    set tText to retTimeText(newDuration) of me
    
if newURL contains "&" then
      set sepChar to "?"
    else
      set sepChar to "&"
    end if
    
    
set newURL to newURL & sepChar & "t=" & tText
  end if
  
  
using terms from application "Safari"
    tell application "Safari" of machine remoteMachineName
      if not running then
        –起動していなかったらあらためてSafariを起動
        
launchRemoteSafari(remoteMachineName) of me
      end if
      
      
try
        close every document
      end try
      
      
set aWin to make new document
      
      
tell aWin
        set URL to newURL
        
–フルスクリーン再生をためしてみたが、こういう書き方ではなかった模様(URLオープンを待つ必要もある)
        
–set aRes to (do JavaScript "document.querySelector(’#movie_player playFullscreen’).click();")
      end tell
      
    end tell
  end using terms from
end openYouTubeOnRemoteMachine

–リモートマシン上でSafariを起動する
on launchRemoteSafari(aMachine)
  using terms from application "Finder"
    tell application "Finder" of machine aMachine
      open application file id "com.apple.Safari"
    end tell
  end using terms from
end launchRemoteSafari

–数値を「h」「m」「s」でフォーマットして返す
on retTimeText(aTime)
  set aHour to aTime div 3600
  
set aMinute to (aTime – (aHour * 3600)) div 60
  
set aSeconds to (aTime mod 60)
  
  
set aString to ""
  
  
if aHour > 0 then
    set aString to aHour & "h"
  end if
  
  
if aMinute > 0 then
    set aString to aString & (aMinute as integer) & "m"
  end if
  
  
if aSeconds > 0 then
    set aString to aString & (aSeconds as integer as string) & "s"
  end if
  
  
return (aString as string)
end retTimeText

–Finderコメントをメタデータ経由で取得
on getFinderComment(aPOSIX)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIX
  
set aMetaInfo to 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

★Click Here to Open This Script 

Posted in Internet JavaScript Remote Control | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy Finder NSMetadataItem NSURL Safari | 14 Comments

Evernoteがv10.0でElectronベースのWebブラウザ的なアプリに

Posted on 10月 8, 2020 by Takaaki Naganoya

Evernoteがv10.0にアップデートして、内容がローカルのアプリケーションではなくWebブラウザ的な(Electron Frameworkを用いた)アプリケーションになりました。

Electron Frameworkを用いたアプリケーションの特徴で、まずAppleScriptには対応しておらず、実際にスクリプトエディタでEvernoteアプリケーションを調べ、AppleScriptからのコントロール機能が存在していないことを確認しました。

AppleScriptからこの手のデータ・スクラップ的なアプリケーションを操作するのであれば、MacJournal v7がいまならフリーで利用できます(Mariner Softwareから作者のDan Schempfに移管になりました)。

メモをとって(Appleの)デバイス間で共有するという目的であれば、macOS標準搭載の「メモ」もよくできているため、これに乗り換えてもよいでしょう。

MacJournalもメモもAppleScriptに対応しており、検索でデータの追加をAppleScriptから行なって、他のアプリケーションとの連携を行うことが可能です。個人的にはMacJournalを利用しており、これに満足しているので問題はありません。

自分のマシンでは、Evernoteは不要なのでアンインストールしておきます。それほど使っていたわけでもありませんが、Evernoteとはお別れです。

→ AppleScriptからのコントロール機能を残したEvernote Legacyが配布されているようです。アップデートした後でAppleScriptが使えなくなって対処ができない場合には、こちらを試してみてもよいでしょう

Posted in news | Tagged Evernote | Leave a comment

Mac App StoreでTable Dripper v1.1が公開に

Posted on 10月 7, 2020 by Takaaki Naganoya

Webブラウザで表示中の範囲にあるTableデータを書き出すアプリケーション「Table Dripper」の新バージョンv1.1の審査が終わって公開になりました。macOS 10.14以降に対応しています。

新バージョンでは、かねてよりお知らせしていたとおりWebブラウザ「Brave Browser」と「Vivaldi」のサポートを追加。さらに、表データ抽出時に行ヘッダーを削除して出力する機能と、表データのHTML書き出しをサポートしています。

Table Dripper v1.1サポートWebブラウザ:Safari、Google Chrome、Microsoft Edge、Brave Browser、Vivaldi

今回のMac App Storeの審査は5日ほど。新作を出したときと同じぐらいの期間がかかっています。普通、アップデート版の審査はあまり時間がかからないのですが、本アプリケーションはv1.0のリリース後にApple側から「Mac App Storeの基準に違反しているのでアップデートで修正しろ」と言われた経緯があります。

当然、Apple社内的には審査をゼロからやり直し、初版リリース時と同じぐらいの時間がかかる可能性も覚悟していました(10日はかかりすぎですが)。5日はだいたい標準的な審査時間ではないでしょうか(新作アプリケーションの審査期間としては)。

今回のv1.1で一番大変だったのは、表ヘッダーの削除機能です。

表の全セルの内容を取ってくるのは、HTMLReader.frameworkの機能に依存してそれほど手間をかけずにできるのですが、Tableタグで作られた表は人によって書き方がまちまちで、ヘッダー宣言して行ヘッダーを書いてあるパターンはむしろ少なく、ヘッダーセルの宣言だけで行ヘッダーが作られているケースの方が多いようでした。

# HTMLReader.framework作者のNolan Waiteには毎回、「こんなScriptを作ったよ!」「こんなアプリを公開したよ!」と報告しています。大変感謝しています。当然、Table Dripperの無料コードを送りつけて「よかったら使ってみて!」と押し付けています

日本語のWikipediaに掲載されている表は、構造が単純なものが多く、本アプリケーションによるデータの再利用や流用がやりやすい傾向にあります。

一方で、英語版Wikipediaに掲載されている表は、なぜかメチャクチャ凝ったものが多く、ヘッダー部分のみ抽出するのはけっこう骨が折れます。

tableタグによる表組をいくつかのパターンに分類し、簡単なものから難しいものまでレベル設定を行い、簡単な方から徐々にヘッダー除去できることを確認していきました。v1.1は複数行の行ヘッダーに対応しているものの、ヘッダー列やヘッダー行にcolspanやrowspanなどの宣言を行なっている箇所があると評価エラーになってしまうため、ヘッダーを除去しないでそのまま出力するようにしています。

目下、Xcode上で作成するAppleScript Cocoaアプリケーションは、自分の検証環境がmacOS 10.13以降なのでmacOS 10.13以降対応とするのが自分的な基準なのですが、本アプリケーションについては外部アプリケーション操作やその対応状況の検出などの処理が必要であり、macOS 10.14以降の対応となっています。

macOS 11.0のリリースが目前に控えており、10月なかばにはGM版のリリースが行われることが予想されています(最近GMリリースしないんですけど)。11.0が出た時点でXcode 12.2の正式版も出るはずなので(すごく不透明)、それでARM/Intel 64のUniversal Binary対応とmacOS 11.0上での動作確認したバージョンをひととおり出すことになりそうです。

全部AppleScriptで記述したアプリケーションなので、Universal Binary化も容易(CPU依存部分がゼロ)ですが、macOS 11.0のGUI仕様がBetaのたびにコロコロ変わる(バグなのかなー)ので、そのバグをどう回避するかというあたりで労力が変わってくると思われます。

Posted in PRODUCTS | Tagged Brave Browser Google Chrome Microsoft Edge Safari Vivaldi | Leave a comment

AppleScriptによるクリップボード処理

Posted on 10月 6, 2020 by Takaaki Naganoya

Classic Mac OSの頃は「しかたなく」クリップボードを使って行う処理がありましたが、最近(Mac OS X移行後)では極力使わないようにしています。文字コード変換、スタイル付きテキストのプレーンテキスト化などクリップボードを経由しないとできない処理がたくさんありました。画像の形式変換ですらクリップボードを経由して処理していた記憶があります。

仕方なく使っていましたが、「なんでこれしきの処理でクリップボードを経由しないといけない?」と不満だらけでした。クリップボードを経由する処理があるということは、人間がGUI経由で作業をしている裏で動かすScriptを作りにくくなるということです。クリップボード処理を多用していた頃のAppleScriptのプログラムは、絶対に人がマシンに手を触れないようにして動かす必要がありました(最前面のアプリケーションを変更してしまうと処理が破綻するなど)。

クリップボード経由の処理は確実さという意味で100%といえませんし、挙動が非同期っぽくて、値が反映されるまでに時間差があるため、クリップボードの内容変更をAppleScript側から監視して反映されるまでループで待つなどのケアが必要になります。

また、クリップボードを利用する方法によって100倍以上も差が出ます。遅い方法を選択すると、遅いばかりではなく信頼性もいまひとつです。

(1)Cocoa Scripting

Cocoaの機能を呼び出して、クリップボード(ペーストボード)の操作を行います。多彩な機能を呼び出すことができ、スピードも最速です。ただし、初回実行時のみ遅くなる傾向があるのと、HDD搭載機では極端に遅くなる場合がある(SSD必須)ので注意が必要です。

(2)AppleScript内蔵標準コマンドを利用

クリップボードにデータを入れる「set the clipboad」、クリップボードからデータを取り出す「the clipboard」、クリップボードの情報を取得する「clioboard info」などがあります。スピードも遅くないのですが、本コマンドでクリップボード内容を捕捉できるまでに(クリップボードの内容が反映されるまでに)若干時間がかかります。

(3)do shell scriptコマンド経由でpbcopyコマンドを実行

shell commandの「pbcopy」「pbpaste」を呼び出して実行します。可もなく不可もなく。スピードは(1)(2)にくらべると10倍以上遅いですが、問題にはなりにくいでしょう。ただ、これをあえて使う状況が考えられません。

(4)GUI Scripting経由でメニュー操作してコピー/ペースト

もっとも遅くて信頼性のない方法です。最速の①や②にくらべると、100倍以上も遅くなります。信頼性もなく、あまり多用できないため、本当に最後の最後に部分的に使うぐらいです。AppleScriptからは生成できないオブジェクトをアプリケーションの書類上で移動させる場合などに、仕方なくGUIを操作してコピー&目的の場所(別のページなど)でペーストを行うような感じでしょうか。それでも、各オブジェクトを逐一コピー&ペーストするのではなく、まとめてコピー&まとめてペーストすべきでしょう。コピー&ペーストの回数を減らすことが安全動作につながります。

その他、クリップボードを用いた処理を行う場合には、処理の最初にクリップボード内容を退避しておき、処理後に退避内容を戻すなどのケアも必要になります。


▲(c)秋本治、集英社

注:AppleScriptの書類形式が通常形式かバンドル書類形式かで実行速度に差が出ることはありません。ただし、アプリケーション内部のメニューやフォルダアクション、SwitchControlなどの各実行環境において「通常形式のみ。バンドル形式は受け付けない」といった制約が生じることはあります。実行速度については、Automatorやショートカット上のAppleScript実行アクションで動かすと、とりわけ遅くなります

AppleScript名:①ASOCでクリップボード操作.scpt
–Created 2015-08-03 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit" — for NSPasteboard

my restoreClipboard:{"ABC"}

–クリップボードに内容を設定する
on restoreClipboard:theArray
  — get pasteboard
  
set thePasteboard to current application’s NSPasteboard’s generalPasteboard()
  
  
— clear it, then write new contents
  
thePasteboard’s clearContents()
  
thePasteboard’s writeObjects:theArray
end restoreClipboard:

★Click Here to Open This Script 

AppleScript名:②set the clipboardコマンド.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/06
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set the clipboard to "ABC"

★Click Here to Open This Script 

AppleScript名:③do shell script経由でpbcopy.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/06
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

do shell script "echo ’ABC’ | pbcopy"

★Click Here to Open This Script 

AppleScript名:④GUI Scripting経由でメニュー操作.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/06
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

activate application "Safari"
tell application "System Events"
  tell process "Safari"
    click menu item "コピー" of menu 1 of menu bar item "編集" of menu bar 1
  end tell
end tell

★Click Here to Open This Script 

Posted in Clipboard | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy | Leave a comment

AppleScriptでリアルタイムキースキャンを行いCotEditor書類上にカーソル描画

Posted on 10月 4, 2020 by Takaaki Naganoya

Modifier Keyのリアルタイムキースキャンを行なって、CotEditor書類上に文字でカーソル描画するAppleScriptです。30 x 30 の文字数のテキストを作成し、CotEditor書類に随時転送することで書き換えています。

AppleScriptでキースキャンといえば、Script/Applet起動時にoptionやcontrolなどのmodifier keys(装飾キー)が押されているかどうかを確認して、動作内容を変更するような用途でした。AppleScriptでGUIを作るのが大変だとか、AppleScriptで気軽にGUIを呼び出せない時代には、割と使われてきた手段です。

そんな中、macOS 10.10以降でCocoaの機能が気軽に利用できるようになってきたことで、Cocoaのキースキャン機能が利用できるようになりました。前述のModifier KeysのスキャンはmacOS側のセキュリティ機構でも問題視していないようで、気軽に使えそうです。ちなみに、SHIFTキーの左右は区別できません。

先日Pixelmator Proで「もぐら叩きゲーム」を作った際にも、このModifier Keysのスキャンは利用しましたが、実際にどの程度使い物になるのか確認しておきたいと考え、AppleScriptからの操作が高速なアプリケーションで試してみることにしてみました。

CotEditorにテキストで描画した画面を転送し、毎回テキスト内容をすべて書き換えることで本格的なゲームの用途に使えるのではないかと考えました。自分ではほとんどゲームを作ったこともないので、別にゲームを量産するつもりはありませんが……。テトリスぐらいならCotEditorのメニューから呼び出すAppleScript内で実行できそうな感じがします。

→ 冗談半分でAppleScriptで作られたTetrisを探してみたら、見つかりました

CotEditorでなくても、他のエディタでも同様の操作はできると思います。

AppleScript名:KeyScan TEST v3.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/10/03
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit" — for NSEvent
use scripting additions

–Initialize
set curPosX to 1
set curPosY to 1
set curMax to 30

set rText to ""
repeat curMax times
  set rText to rText & "🛑"
end repeat

tell application "CotEditor"
  write to console "Real-time Keyscan test with Modifier Keys
  [ Control ]    : Move Left
  [ Shift ]    : Move Right
  [ Option ]    : Move Up
  [ Command ]  : Move Down

  [ Caps Lock ]  : Quit this script"
  
  
make new document
  
activate
end tell

–Main Loop
repeat
  set leftF to my checkModifier:"control"
  
set rightF to my checkModifier:"shift"
  
set upF to my checkModifier:"option"
  
set downF to my checkModifier:"command"
  
  
set quitF to my checkModifier:"caps"
  
  
if quitF = true then return
  
  
if leftF = true then
    if curPosX > 1 then
      set curPosX to curPosX – 1
    end if
  else if rightF = true then
    if curPosX ≤ curMax then
      set curPosX to curPosX + 1
    end if
  end if
  
  
if upF = true then
    if curPosY > 1 then
      set curPosY to curPosY – 1
    end if
  else if downF = true then
    if curPosY < curMax then
      set curPosY to curPosY + 1
    end if
  end if
  
  
  
–make display text
  
set aText to ""
  
repeat with i from 1 to curMax + 1
    if i = curPosX then
      set aText to aText & "🛑"
    else
      set aText to aText & "㍳"
    end if
  end repeat
  
  
  
set bText to ""
  
repeat with y from 1 to curMax
    if y = curPosY then
      set bText to bText & rText & return
    else
      set bText to bText & aText & return
    end if
  end repeat
  
  
my displayText(bText)
  
end repeat

–テキスト画面描画
on displayText(aText)
  tell application "CotEditor"
    tell front document
      set contents to aText
    end tell
  end tell
end displayText

–複数同時検出に対応
on checkModifier:keyName
  if keyName = "option" then
    set theMask to current application’s NSAlternateKeyMask as integer
  else if keyName = "control" then
    set theMask to current application’s NSControlKeyMask as integer
  else if keyName = "command" then
    set theMask to current application’s NSCommandKeyMask as integer
  else if keyName = "shift" then
    set theMask to current application’s NSShiftKeyMask as integer
  else if keyName = "caps" then
    set theMask to current application’s NSEventModifierFlagCapsLock as integer
  else if keyName = "num" then
    set theMask to current application’s NSEventModifierFlagNumericPad as integer
  else if keyName = "help" then
    set theMask to current application’s NSEventModifierFlagHelp as integer
  else if keyName = "fn" then
    set theMask to current application’s NSEventModifierFlagFunction as integer
  else
    return false
  end if
  
  
set theFlag to current application’s NSEvent’s modifierFlags() as integer
  
if ((theFlag div theMask) mod 2) = 0 then
    return false
  else
    return true
  end if
end checkModifier:

★Click Here to Open This Script 

Posted in System | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy CotEditor NSEvent | Leave a comment

Mac App StoreでTable Dripper v1.1が審査中

Posted on 10月 2, 2020 by Takaaki Naganoya

Mac App StoreにWebの表データ(tableタグで書かれた表)のインタラクティブ・スクレーパーである「Table Dripper」のバージョン1.1を申請し、目下審査中です。

データスクレイパーの多くは、定期巡回してまとめてサイトのデータを取ってくるものですが、Table DripperはWebブラウザで表示中の、いま目の前にある見えている表データを取り出すことに特化しています。

v1.0の審査は10日ぐらいかかったのですが、今回はもう少し早く結果が出て欲しいところです。

v1.0がAppleの承認を経て公開になったあとで、あとから「やっぱりこのアプリ、Mac App Storeの規約に反しているのでー」と言ってきたので、その部分に手を加えてアップデートしました。

temporary items folderにユーザーがアクセスできてしまうことを問題視したようです。他のアプリケーションの審査では指摘されていた項目ではあったものの、当時Mac App Storeの審査に1人で同時に3本ぐらい突っ込んでおり、他のレビューでは指摘されていた内容でした。

ちなみに、ダルそうに電話してきたApple側の担当者は「Table Dripper」という単語を読めませんでした(おかわいらしい!)。「Sandboxの仕様で話はわかるが、どう回避しろと?」と問えば、自分はそんなことは知らない、とのこと。

なるほどー、文字が読めない人間に電話させてくるのかー、知能のない人間を担当にして反論を封じるとはなかなか洒落たことをするものであります。言葉のわからないにゃんこちゃんに反論はできませんので。

これを、難しい専門用語で「サンドボックス環境」ならぬ「サンドバック担当」と呼びます。


▲起動時にDrip Folder(作業用の表データ書き込み先フォルダ)の選択を求められるようになりました。Sandboxの仕様上、動作を変えた部分


▲5つのWebブラウザをサポート。FireFoxやOperaはAppleScriptのサポートが弱い(do javascriptに相当するコマンドがない)ためにサポートできません


▲表データの解釈機能を大幅に強化。取り込み時に行ヘッダーを削除する機能を追加


▲表データをHTML形式でも取り込めるようにしました(CSVに解釈できない場合への対処)


▲行ヘッダー削除のパターンを図示(ねんのため)

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

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

Google Search

Popular posts

  • macOS 13, Ventura(継続更新)
  • アラートダイアログ上にWebViewで3Dコンテンツを表示(WebGL+three.js)v3
  • UI Browserがgithub上でソース公開され、オープンソースに
  • macOS 13 TTS Voice環境に変更
  • Xcode 14.2でAppleScript App Templateを復活させる
  • 2022年に書いた価値あるAppleScript
  • ChatGPTで文章のベクトル化(Embedding)
  • 新発売:AppleScriptからSiriを呼び出そう!
  • iWork 12.2がリリースされた
  • 従来と異なるmacOS 13の性格?
  • 新発売:CotEditor Scripting Book with AppleScript
  • macOS 13対応アップデート:AppleScript実践的テクニック集(1)GUI Scripting
  • AS関連データの取り扱いを容易にする(はずの)privateDataTypeLib
  • macOS 13でNSNotFoundバグふたたび
  • macOS 12.5.1、11.6.8でFinderのselectionでスクリーンショット画像をopenできない問題
  • ChatGPTでchatに対する応答文を取得
  • 新発売:iWork Scripting Book with AppleScript
  • Finderの隠し命令openVirtualLocationが発見される
  • macOS 13.1アップデートでスクリプトエディタの挙動がようやくまともに
  • あのコン過去ログビューワー(暫定版)

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1390) 10.14savvy (586) 10.15savvy (434) 11.0savvy (277) 12.0savvy (185) 13.0savvy (55) CotEditor (60) Finder (47) iTunes (19) Keynote (98) NSAlert (60) NSArray (51) NSBezierPath (18) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (18) 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 (56) Pages (37) Safari (41) Script Editor (20) WKUserContentController (21) WKUserScript (20) WKUserScriptInjectionTimeAtDocumentEnd (18) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • Clipboard
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • drive
  • 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
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • 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)
  • 未分類

アーカイブ

  • 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