Menu

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

AppleScriptの穴

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

タグ: 10.15savvy

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

Pixelmator Pro AppleScriptコンテストに「もぐら叩きゲーム」を応募

Posted on 9月 29, 2020 by Takaaki Naganoya

LateNight Software主催のPixelmator Pro AppleScriptコンテストに応募してみました。

応募内容は、「もぐら叩きゲーム」です。

Pixelmator Proというグラフィックソフトを使ってもぐら叩きゲーム。不可能ではありません。

Pixelmator ProのAppleScript用語辞書をながめていたら、レイヤーごとの表示/非表示を制御できることがわかったので、レイヤーをセルに見立ててパラパラアニメーション的なものを表示しつつCocoaの機能を使ってキースキャンするとできそうだと思っていました。作ってみたら、問題なくできてしまったと。

このもぐら1匹バージョンのもぐら叩きは1時間ぐらいで出来たのですが、3匹バージョンを試してみたところ、とても100行に収まりきらない感じだったので、3匹バージョン構想は破棄しました(時間かけるような内容でもないですし)。

コンテストのレギュレーションを詳細にチェックすると、1つの外部ファイルの読み込みはOKということになっており、表示用のPixelmator Pro書類がこれに該当するかどうか、という点が気になっていました。

こういうレギュレーションの機敏については、コンテスト開催側の胸先三寸で決められる部分なので、主催者側に判断をおまかせするしかありません。

あとは、環境に応じて時間待ちループ時間を大幅に変えないとダメそうです。AppleScriptObjCのプログラムは、HDDで動いているMac上だと極端に遅くなる傾向があるので、たまたま手元でmacOS 10.15.7を動かしている隔離環境(10.15のテスト環境)だとずいぶん動作が遅い(実際にはAppleScriptの実行が速すぎてウェイト入れまくっているんですが)印象を受けました。

このあたり、実行環境のパフォーマンスを計測して時間待ちの長さを適宜調節すべきなんですが、そういうパフォーマンス計測だけで数十行ぐらいは平気でかかってしまうので、100行以内というレギュレーションだとかなり無理な感じがします。Pixelmator Proに新規書類作成などのコマンドを送ってみて、どのぐらいの時間で処理できるかをその場で計測し、パフォーマンスを計ってウェイト時間を調整するべきなんでしょう。

ただ、コンテスト用のScriptだし、なるべくシンプルなものがいいんでしょう。音がないとさびしいので、iTunesなりMusic.appをコントロールしてBGMを鳴らそうと思っていたんですが、行数が足りなくてダメでした。

Pixelmator Pro向けには、KamenokoのデータをPixelmator Proのネイティブオブジェクトで内容を再現するものを試作して動かしています。ただ、1書類の内容を再構成すると40秒ぐらいかかるのと、Pixelmator Proのオブジェクトで再現するよりPDFベースでコピペしたほうが綺麗だったので、そのプログラムはお蔵入りしています。

この手の「とてもゲームが作れるようには見えない」アプリケーションを使って別のものを仕立てるのは、実は慣れたもので……

Mac World Expo/Tokyoでデモした「FMバトラー」(ファイルメーカーProをAppleScriptでコントロールしてホームページ対戦ゲームに仕立てたデモプログラム)など、これまでにもいろいろ作ってきました。

さらに、Cocoaの機能がAppleScriptから直接呼べるようになったので、複数キーの同時入力受付(正確には、ShiftやControlなどのModifier Keyのキースキャン)といったあからさまにゲームが作りやすそうな機能を利用できるようになったので、過去の無理やりつくったデモ用ゲーム風システムよりも、今回は作りやすかったといえます。

でも、真剣に「Pixelmator Proで込み入ったゲームを作れるんだろうか?」と試してみたところ、そこまでのパワーはありませんでした。オブジェクトの属性値の変更も、様子を見ながら限定されたものを操作するのは向いているものの、大量のオブジェクト操作を行うとアプリケーション側がついてきません。

きしくも、応募作品のもぐら叩きゲームは「奇跡的にちょうどいいバランス」で成立していることがわかりました。

後日、「外部プログラムの威力を利用して画像認識機能をPixelmator Proに足してみては?」と、Web APIとかdarknet(YOLO v3 model)を併用して画像認識した内容をレイヤー名に反映させたりと試していたところ……Pixelmator Proにやられました。

Pixelmator Proにはデフォルトで画像認識機能が入っていて、簡単な動物などの写真はインポートした瞬間に画像認識されて、それっぽいレイヤー名を自動で命名することが判明!

Pixelmator Proのバンドルパッケージを開けてみると、いくつもCore ML Modelのファイルが入っており、深層学習データを併用してさまざまな処理を行なっていることが伺われました。


▲Finder上からPixelmator Pro書類に画像をドラッグ&ドロップすると、その場で画像認識されて「それっぽい」レイヤー名が自動で割り振られる。「犬」とか「鳥」といった名前はPixelmator Proが自動でつけたもの


▲「どうせ認識しないだろ」と思って、ガンダムの画像をドロップしたら「おもちゃ」と認識。たった34MBの深層学習データでどうしたらここまで認識できるのやら。学習データだけでなく、別の手段も併用している???(画像取得元のURLの情報を取っているとか?)

もしかして、各種レイヤーの画像を随時(保存時にでも)画像認識して、ユーザーごとの画像⇄レイヤー名の関連性を学習して、再インポート時には過去の画像から類推して近いものを提案するのでは? などと思ってしまうところです。

これはオシャレです! センスよすぎです。さりげなさすぎて気づきませんでした。出しぬこうと悪だくみしてみたら、相手の方がはるかに上手だったということが判明したのでした。アプリケーションの機能で感動したのは久しぶりです。

Posted in news | Tagged 10.15savvy Pixelmator Pro | Leave a comment

前後に存在するスペースと、文字列中に存在する2個以上の連続するスペースを削除して返す

Posted on 9月 29, 2020 by Takaaki Naganoya

それほど長くない文字列の空白文字列クリーニングを行うAppleScriptです。

 "    First model, with mechanical scroll wheel.           10 GB model released later                             ."

のようなデータを、

 "First model, with mechanical scroll wheel.  10 GB model released later ."

のようにクリーニングします。

フィールド文字列のクリーニング用なので、だいたい256バイト以内。長くても1024バイト程度のデータを想定しています。

とくに、データが長くなった場合に備えての高速化対応処理はしていませんが、それでもCocoaの正規表現系の機能を使った実装よりもだいたい5倍ぐらいは高速です。

画像処理ぐらいのデータ量があるとCocoa系の機能を使ったほうがはるかに高速ですが、この手の小ぶりなデータの処理にはNativeなAppleScriptの処理を行ったほうが高速です。

文字列の先頭と末尾に入っている無駄なスペース(空白文字)を除去し、文字列本体中に入っている「2つ以上連続して存在するスペース」についても除去します。

AppleScript名:前後に存在するスペースと、文字列中に存在する2個以上の連続するスペースを削除して返す.scpt
— Created 2020-09-27 by Takaaki Naganoya
— 2020 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

–指定文字列の前後に存在するスペースと、文字列本体中に存在する2個以上の連続するスペースを削除して返す
set a0Str to " First model, with mechanical scroll wheel. 10 GB model released later ."
set aRes to removeWhiteSpaceRepeatation(a0Str, " ") of me
–> "First model, with mechanical scroll wheel. 10 GB model released later ."

–クリーニング対象文字(たぶんスペース)が処理対象文字列の前後にあったり、途中に2つ以上連続して存在している場合には削除
on removeWhiteSpaceRepeatation(a0Str as string, aChar as string)
  if length of aChar is not equal to 1 then return false
  
  
set a1Str to trimFromHeadAndTail(a0Str, aChar) of me
  
–> "First model, with mechanical scroll wheel. 10 GB model released later ."
  
  
set sucList to detectSuccsessionOfSpace(a1Str, aChar) of me
  
–> {{43, 53}, {80, 108}}
  
  
if sucList = {} then return a1Str
  
  
set allRes to removeRepeatedSpaceChar(a1Str, sucList)
  
  
return allRes
end removeWhiteSpaceRepeatation

–同一文字(スペース)の連続出現リスト({{start pos 1, end pos 1}, {start pos 2, end pos 2}……})をもとにテキストを切り抜く
on removeRepeatedSpaceChar(a1Str as string, sucList as list)
  set aList to characters of a1Str
  
  
set aLen to length of aList
  
set outStr to ""
  
set aCount to 1
  
copy contents of item aCount of sucList to {sItem, eItem}
  
  
repeat with i in sucList
    copy i to {tmpS, tmpE}
    
if aCount = tmpS then
      –Skip
      
copy tmpE to aCount
    else
      set tmpStr to text (aCount) thru tmpS of a1Str
      
set outStr to outStr & tmpStr
      
copy tmpE to aCount
    end if
  end repeat
  
  
if tmpE < aLen then
    set tmpStr to text (tmpE + 1) thru -1 of a1Str
    
set outStr to outStr & tmpStr
  end if
  
  
return outStr
end removeRepeatedSpaceChar

–対象文字列で、2個以上同一文字(スペースを想定)が連続して存在する場合には削除する
on detectSuccsessionOfSpace(a1Str as string, sucTargChar as string)
  set aList to characters of a1Str
  
set aLen to length of aList
  
set newList to {}
  
  
set tmpS to 0
  
set tmpE to 0
  
set spcF to false –false:spaceではない。true:spaceをみつけた
  
set spcCount to 0
  
  
repeat with i from 1 to aLen
    set j to contents of item i of aList
    
    
if j = sucTargChar then –Space 1 char (must be a char)
      
      
if spcF = true then
        –スペースが連続している最中
        
set spcCount to spcCount + 1
      else
        –スペースの連続部分(?)の先頭をフェッチした状態
        
set spcF to true
        
set spcCount to 1
        
copy i to tmpS
      end if
      
    else
      –連続スペースの末端部分
      
if spcF = true then
        copy i to tmpE
        
if spcCount > 1 then
          set the end of newList to {tmpS, tmpE – 1}
        end if
        
set spcCount to 0
        
set spcF to false
      else
        –何もしない
      end if
    end if
    
  end repeat
  
  
return newList
end detectSuccsessionOfSpace

–文字列の先頭と末尾から連続するスペースを検索して削除する
on trimFromHeadAndTail(aStr as string, trimChar as string)
  set aLen to length of aStr
  
set aList to characters of aStr
  
  
–Find not target character from head to tail
  
set aCount to 1
  
repeat with i in aList
    set j to contents of i
    
if j is not equal to trimChar then
      exit repeat
    end if
    
set aCount to aCount + 1
  end repeat
  
  
if aLen ≤ aCount then return ""
  
  
–Find not target character from tail to head
  
set bCount to 1
  
repeat with ii in (reverse of aList)
    set jj to contents of ii
    
if jj is not equal to trimChar then
      exit repeat
    end if
    
set bCount to bCount + 1
  end repeat
  
  
set resStr to text aCount thru (aLen – bCount + 1) of aStr
  
return resStr
end trimFromHeadAndTail

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

★Click Here to Open This Script 

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

mergelyでdiff表示

Posted on 9月 27, 2020 by Takaaki Naganoya

alert dialog上のWebViewに、オープンソースのJavaScript Library「mergely」を呼び出すHTMLを表示し、指定の文字列のdiff表示を行うAppleScriptです。

–> Download diff_disp

CDN上のmergely.jsおよびcssを呼び出しているので、実行にはインターネット接続を必要とします。

Webダイアログ表示部分はscript bundleの中に入れてあるので、上記のアーカイブをダウンロード&アーカイブ展開したものを実行してください。下記のリストではWebダイアログ部分は含んでいないので、Script Linkをクリックして内容をスクリプトエディタに転送して実行しても、必要なファイルが入っていないため動きません(Script Linkではバンドル構造を転送することはできません)。あくまで掲載リストは参考にしていただくためのものです。本Scriptの本体部分はバンドル内に同梱しているHTML(の中のJavaScript部分)です。

diff表示用の部品がOSに用意されていると楽ですが、macOS上のdiff表示用ツール「FileMerge」のdiff表示部品が再利用可能な状態で提供されていないため、よそで部品を探してくることに。FileMerge自体はAppleScript用語辞書を持っていないため、ダイレクトにaliasを指定して2つのファイルの差分表示を行わせることはできません(do shell scriptコマンド経由でオープンさせることは可能)。

サードパーティのGUIアプリケーションでdiff表示機能を持つものをコントロールする場合には、BBEditのdiff表示機能を呼び出すのが手頃で使いやすいでしょうか。

独立した(他のGUIアプリケーションに依存しない)ソリューションとして提供できる形態を想定すると、部品として組み込めるものを探すことになります。この条件に見合うdiff表示用部品はいろいろ探してはいるものの、なかなかいいものが見当たりません。UKDiffViewはAppleのFileMergeに似たルック&フィールを提供する最強クラスの部品ですが、メンテナンスされていなくて現行環境で動かすように書き換えるには手間がかかりそうです(自分には無理です)。

Double PDFをMac App Storeに申請したときには、Reviewでリジェクトをくらっていた中で苦し紛れに「Vimdiff」でdiff表示するバージョンを提出したこともありましたが、これは「Terminal.appをコントロールするアプリケーションは提出不可」というルールに明記されていない理由によりリジェクトを食らいました(セキュリティ上の理由だったか)。

mergelyは(使いこなせれば)なかなかいい部品に見えます。目下、自分はパラメータに改行を含んだ文字列を指定できていないので、そのあたり試行錯誤する必要があることでしょう。

AppleScript名:mergelyでdiff表示.scptd
set aStr to "左側のフィールドの文章をここに書いた。犬と猫を見かけた。"
set bStr to "右側のフィールドの文章をここに書いた。犬と蛇を見かけた。"
set aSize to {1024, 220}
dispDiff(aStr, bStr, aSize) of diffDispLib

script diffDispLib
  –  Created by: Takaaki Naganoya
  
–  Created on: 2020/09/27
  
—
  
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
  
–  https://mergely.com
  
use AppleScript version "2.7" — High Sierra (10.13) or later
  
use framework "Foundation"
  
use scripting additions
  
use webD : script "webDialogLib"
  
  
on dispDiff(aStr, bStr, aSize)
    using terms from scripting additions
      set mePath to path to me
      
set resPath to (mePath as string) & "Contents:Resources:index.html"
      
set myStr to (read (resPath as alias) as «class utf8») as string
    end using terms from
    
    
set aString to current application’s NSString’s stringWithFormat_(myStr, aStr, bStr) as string
    
set paramObj to {myMessage:"Browse diff", mySubMessage:"This is an mergely test", htmlStr:aString, viewSize:aSize}
    
    
webD’s displayWebDialog(paramObj)
  end dispDiff
end script

★Click Here to Open This Script 

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

iWork Appsのv10.2アップデートが公開される

Posted on 9月 23, 2020 by Takaaki Naganoya

AppleがKeynote/Pages/Numbersのv10.2アッップデートを公開しました。このv10.2から対象OSがmacOS 10.15以降になり、macOS 10.14では最新のKeynote v10.2を使えなくなったことになります。

Keynote v10.2のAppleScript系の機能の差分チェックを(sdefファイルベースで)行ってみたところ、iWorkアプリケーション中でKeynoteのみ機能追加されたことがわかりました。

Keynoteにムービー書き出し機能のAppleScriptオプション機能が追加される

exportコマンドのexport optionsで「movie codecs」と「movie framerates」の指定ができるように機能追加されています。

movie codecs enum
h.264 : H.264
AppleProRes422 : Apple ProRes 422
AppleProRes4444 : Apple ProRes 4444
AppleProRes422LT : Apple ProRes 422LT
AppleProRes422HQ : Apple ProRes 422HQ
AppleProRes422Proxy : Apple ProRes 422Proxy
HEVC : HEVC

movie framerates enum
FPS12 : 12 FPS
FPS2398 : 23.98 FPS
FPS24 : 24 FPS
FPS25 : 25 FPS
FPS2997 : 29.97 FPS
FPS30 : 30 FPS
FPS50 : 50 FPS
FPS5994 : 59.94 FPS
FPS60 : 60 FPS

風の噂によるとどうもARM Macはムービー書き出しが高速なようなので、そのあたりをアピールするためにもムービー書き出し系の機能の拡充は必要ということなのでしょう。

KeynoteのAppleScript用語辞書に構文確認をパスできないバグ持ち予約語が存在

同時に、「こんなんAppleScriptの処理系でコンパイル(構文確認)通るわけないやん、メーカーが何やってますのん?」という予約語がsdef内に書かれていることが一目でわかりました。

「h.264?」

この「h.264」の予約語はexportコマンドのexport optionsのmovie codecsのEnum内に書かれています。

        <enumeration name="movie codecs" code="Knmc">
            <enumerator name="h.264" code="Kmc1" description="H.264">
                <cocoa string-value="AVVideoCodecTypeH264" />
            </enumerator>

macOS 10.15.6上で確認したところ、見事に構文確認時にエラーになります。

Apple製のアプリケーションのAppleによるスクリプティング定義内容がまともに動きません。こうした事態は理解に苦しむものがあります。100%動作確認していないとしか思えません。

ここは、記号入りの予約語では言語処理系的に構文確認すらパスできないので、「h.264」ではなく記号を含まない「h264」ないし「H264」という予約語にすべきです。AppleScript系の機能を追加していただくのは前向きでよいと思いますが、メーカーとして一度も動作確認しないで機能をリリースするというのはいかがなものでしょう?

そんなところに凝っていないで、選択中のオブジェクトを取れる属性「selected objects」とか、テキストオブジェクトの縦書き制御属性「vertical」などをつけたほうが実用性があって助かります。機能追加自体はたいした作業ではありませんが、ぜひ動作確認した上でリリースしていただきたいところです。

AppleScript名:keynote movie export test
–Works with Keynote v10.2 or later
set aTagFile to ((path to desktop) as string) & "testOut.m4v"

tell application "Keynote"
  set exOpt to {compression factor:1.0, movie format:native size, class:export options}
  
–set exOpt to {compression factor:1.0, movie format:native size, movie codec:h.264, class:export options}–this cause error
  
export document 1 to file aTagFile as QuickTime movie with properties exOpt
  
end tell

★Click Here to Open This Script 

日頃からMac App Storeのレビューアーの血も涙もない(でも、ツッコミどころ満載の)リジェクトに遭っている身からすれば、こんなのリジェクト案件です。

個人的には信頼度の問題からmacOS 10.15は「パス」なので、macOS 11.0 Big SurがRelease時にコケないことを祈るのみです(メールが消えるとかいう話が一番OSの信頼度を下げる)。macOS 10.13, “Vista”という史上最悪・最低の大失敗をやらかして以来、「Release版のOSがBetaよりも低品質」という昨今のmacOS。10.13もBetaの時にはよかったのに、Release版で大崩壊を起こして見るも無残な姿に成り果てました。10.14もBetaの段階でGUI Scriptingの認証系でひどいバグがあって、「とても使えない」と判断。10.14.6まで待ってようやく手を出す気になったほど。

macOS 11.0, Big SurはBeta段階でも珍しく好印象で(GUIまわりの仕様はコロコロ変わるけど)、macOS 10.15みたいにBeta段階で「もう、これはダメ!」という話も聞きません(Relase時に紹介記事を書かなかったOSは10.15がはじめてです。10.15の崩壊度はひどかった)。macOS 11.0, Big Surには、macOS 10.13のような「Release版の大崩壊」を起こしてほしくないものです。

Posted in Bug sdef | Tagged 10.15savvy 11.0savvy Keynote Numbers Pages | Leave a comment

SFSymbolsフォントにAppleScript

Posted on 9月 23, 2020 by Takaaki Naganoya

macOS 10.15.x以降で使用できる、よく使われるアプリ内アイコンをフォント化した「SF Symbols」フォントが配布されており、このフォントにAppleScriptアイコンが用意されていることを見つけました(たいした発見ではありません。「へーそうなんだー」ぐらいの内容です)。

「SF Symbolsベータ」アプリケーションをインストールすると、さまざまなカテゴリに区分されたアイコン文字を閲覧、コピーすることができます。

このように、macOS 10.15.x以降にSFSymbolsフォントがインストールされていれば、Keynote書類上に文字情報をコピーすることも可能です(文字なので)。

もしやと思い、macOSの日本語Input Methodのユーザー辞書にこのAppleScriptアイコンを登録。

テキストエディタ(CotEditor)上で「あっぷるすくりぷと」と入力して変換すると、AppleScriptアイコンに変換されました。なるほど。たしかに文字ですわ。

–> ASInput demo movie

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

SFPSDWriterのじっけん v2

Posted on 9月 21, 2020 by Takaaki Naganoya

AppleScriptからPhotoshopのデータ(PSD)を出力するテストプログラムです。

AppleScriptにはPhotoshopのデータを書き出す関数や機能はとくに用意されていないため、Photoshopのデータを書くためにはPhotoshopにコマンドを送って実行してもらうのが定番です。

この定番の方法だと、Photoshopが存在しない環境でPhotoshopのデータを作ることができません。この問題を解決するためにはオープンソースで公開されている「Photoshopデータを書くプログラム部品」を呼び出すことになります。

Photoshopデータについては一定の需要があるためか、AdobeがPhotoshopデータ形式の詳細な資料を公開しているためか、Reader(読むプログラム)とWriter(書くプログラム)の2通りのプログラムが存在します。

■PSD Reader/Parser
PSD-Font-Reader
psdparse

■PSD Writer
FMPSD
PSDWriter
SFPSDWriter

ここでは、「SFPSDWriter」内に含まれる「SFPSDWriter」Frameworkを呼び出しています。

–> Download SFPSDWriter.framework(To ~/Library/Frameworks)

実行にあたっては、macOS 10.14以降ではScript Debuggerを用いるか、お使いのMacをSIP解除してScript Editor上で呼び出して実行する必要があります。

ちょっと書き換えるとXcode上でも呼び出せることでしょう。Mac App Storeに出すAppleScript Cocoaアプリケーション(Sandbox対応)内で利用する場合には、ファイル書き込みパスをユーザーに明示的に選択させる必要があるため、choose file nameダイアログでファイル名を入力・選択してもらうようにすべきです(デフォルト指定のファイル名をUUIDで自動生成するとか)。

本AppleScriptはKamenokoから書き出せるデータを増やすべく「Photoshop形式のデータを書けたらどうだろう?」と実験してみた残骸です。結局、PDFで書き出せるしPDFなら拡大縮小しても荒くなったりしないので、PDFのほうがいいという結論に。

Pixelmator Proのデータ形式とかPSD形式で書き出す実験は行っているのですが、処理結果を見るとどちらも「PDF形式のほうがいい」という結論に至っています。


▲ベクターデータではないので、拡大するとアラが見える

AppleScript名:SFPSDWriterのじっけん v2
— Created 2016-03-12 by Takaaki Naganoya
— Modified 2019-02-27 by Takaaki Naganoya
— Modified 2020–09-21 by Takaaki Naganoya
— 2020 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "SFPSDWriter" –https://github.com/shinyfrog/SFPSDWriter

property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSUUID : a reference to current application’s NSUUID
property NSImage : a reference to current application’s NSImage
property SFPSDWriter : a reference to current application’s SFPSDWriter
property NSWorkspace : a reference to current application’s NSWorkspace

property SFPSDResolutionUnitPPI : 1
property SFPSDResolutionUnitPPC : 2

set anWriter to (SFPSDWriter’s alloc()’s initWithDocumentSize:(current application’s CGSizeMake(1200, 400)) andResolution:72.0 andResolutionUnit:(SFPSDResolutionUnitPPI))

set aCount to 1

repeat with yPos from 0 to 400 by 110
  repeat with xPos from 0 to 1024 by 110
    set aImage to (current application’s NSImage’s alloc()’s initWithSize:{100, 100})
    
set aColor to current application’s NSColor’s redColor()
    
my drawCircleOnNSIMage(aImage, 100, 0, 0, aColor)
    
    (
anWriter’s addLayerWithNSImage:aImage andName:("Layer_" & aCount as string) andOpacity:1.0 andOffset:{x:(xPos as real), y:(yPos as real)})
    
set aCount to aCount + 1
  end repeat
end repeat

set aPSD to anWriter’s createPSDData()

set theName to NSUUID’s UUID()’s UUIDString()
set pathString to NSString’s stringWithString:("~/Desktop/output_" & theName & ".psd")
set newPath to pathString’s stringByExpandingTildeInPath()

aPSD’s writeToFile:newPath atomically:true

#  MARK: Call By Reference
on drawCircleOnNSIMage(aImage, aRadius, aXpos, aYpos, aColor)
  set aBezier to generateCircle(aRadius, aXpos, aYpos) of me
  (
aImage)’s lockFocus()
  
aColor’s |set|()
  
aBezier’s fill() –ぬりつぶし
  (
aImage)’s unlockFocus()
end drawCircleOnNSIMage

#  MARK: circleのBezier曲線を作成して返す
on generateCircle(theRadius, x, y)
  set aRect to current application’s NSMakeRect(x, y, theRadius, theRadius)
  
set aCirCle to current application’s NSBezierPath’s bezierPath()
  
aCirCle’s appendBezierPathWithOvalInRect:aRect
  
return aCirCle
end generateCircle

★Click Here to Open This Script 

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

Pixelmator Pro 1.8 AppleScriptコンテスト開催

Posted on 9月 18, 2020 by Takaaki Naganoya

Late Night Software Blogの告知がTwitterに流れてきていました。Pixelmator Pro v1.8にてAppleScriptに対応したことを祝して、Late Night Software主催でPixelmator ProのAppleScriptプログラミングコンテストが開催されるとのこと。

Pixelmator Proはいわば「IllustratorとPhotoshopを足して2で割った」ようなアプリケーション。Photoshopの代用になる廉価なアプリケーション、という路線です(旧Macromedia FireWorksに近いかも)。基本的にはラスター画像の処理ソフトで、ビットマップイメージを作成するものです。ベクター図形や文字などもキャンバス上に配置できますが、最終的には画像化されます。ラスター画像に対して非破壊で各種フィルタ処理が行えることが売りです。Web画像素材やアプリケーションのアイコン画像作成といった用途、写真のレタッチなどに使われているようです。登場直後にAppleScript対応リクエストを出していたものの、今回10年越しぐらいで実現して腰を抜かしました。

さて、コンテストに話を戻します。Pixelmator Pro v1.8の試用版を使うことで、同アプリケーションのScriptを書いて試せるとのこと(やっています)。辞書内容は事前に確認していましたが、ツッコミどころがあまりないぐらい、さまざまな機能が載っていました。「え、こんな機能まで乗せてるの?」という謎の充実度を見せており(Pixelmator Pro本体に搭載されていないQRコードの検出機能とか)、AS機能の開発に元AppleのSal Soghoianが協力したという話もうなづけます。

以下、コンテストのレギュレーションです。

*締め切り日:2020年10月8日 00:00(PST、日本標準時より1時間早い。別名「Shane Stanley時間」)
*Late Night Softwareのフォーラムで「いいね」が押された数で競う(あ、これ女性と子供が有利なやつだ ^ー^;)
*賞品はPixelmator ProのMac App Storeクーポンコード。優勝者は複数(Winnersと書いてある)だが、どうも人数は決めていない様子。
→ 入賞枠は3とのこと(補足)
*コンテスト応募は、LateNight Softwareのフォーラムに「pixelmatorpro」と「contest」のタグをつけて投稿すること
*AppleScriptの行数は100行まで(えーー)。コメントと空き行は除く。継続記号(┐)で続けた行も区切ってカウントされる。1行が200文字を超えてはいけない
*全Script行数の25%以上、Pixelmator Proの機能を呼び出さなくてはならない
*ScriptはmacOS 10.15, Catalina上で動作しなくてはならない
*ScriptはすべてAppleScriptでなくてはならない(JXAやshell scriptその他はダメ)。ASOCはOK
*外部Script Librariesの使用禁止(BridgePlusが使えない。これは痛い)
*Scriptはサードパーティのソフトウェア使用禁止。macOS Catalinaの標準搭載アプリケーション(ただし、Keynote、Pages、Numbersは使用OK)および(当然)Pixelmator Proのコントロールはしてよいものとする
*Scriptは製作者提供の外部データを1つに限り読み込んでよいものとする
*インターネット上のデータの読み込みはOK
*ScriptのInfo欄にスクリーンショットを入れてもいいよ
*楽しんでくれ。嫌がらせや破壊行為はNG
*ルールの明示化のためにルール自体の補足・説明を(主催者が)随時行えるものとする
*Script Debugger上で動作すること

……巨大Scriptで一部のScripterがコンテストを蹂躙することを避けつつ、「このあたり、穴場だよね?」という箇所を埋めてあります。あっと驚く参加者(たぶん、最年少参加者)が優勝をもぎ取って、真の実力者(Edama2さんみたいな)が投稿したScriptが全力でスルーされつつPixelmator Pro Scriptingの肥やしになりそうな、よく考えられたレギュレーションです(コンテストってそういうもんなんで)。

そして、一部のScripterが巨大な外部ライブラリを使ってコンテストを荒らすことを防ぐ、いいレギュレーションだと思います(Piyomaru Software対策)。

macOS標準装備のScript Editorと、LateNight Softwareが提供しているScript Debuggerの間で、(主にCocoa Scriptingで)若干の挙動の違いがありますが、レギュレーションではScript Debugger上で動作することを明記しています。まー、こんな100行程度のScriptでCocoa Scripting使ってもたいした処理が書けないんで、Cocoaの使いこなしで発生する実力差を相殺したいんだと思います。

自分が参加するとしたら、優勝狙いではなく「AppleScriptでこんなことできないでしょ」という連中を一発で黙らせるような破壊力のあるものを投稿して、それでも優勝しないという内容でしょう。ただ、100行以内だと「秘密兵器」を仕込むほどの分量がありませんね。

「1つの外部ファイルを読み込んでよい」というあたりが狙い所でしょうか。ここで勝負が決まると思います。ベトナムとかマレーシアの女子中学生あたりが優勝しそうだと予想。

Pixelmator ProのAppleScript用語辞書にはサンプルコードが多数掲載されており、それらを試してみるだけでもかなりのことがわかってきます。ただ、サンプルは行数を減らして見せるよう書かれているため、表記ゆらぎが大きく、オブジェクト階層を素直にtell文で順序立てて書くようなScriptに書き直さないと「部品」としては使いにくい印象も受けました。

実際に、Pixelmator ProのScriptingを行って、Kamenokoのネイティブデータにアクセスしてデータ書き出しを行ってみましたが、これだけでも数百行のコード規模になっているので、100行だけだと実に過酷だと感じましたわー。

Posted in news | Tagged 10.15savvy Pixelmator Pro | Leave a comment

Safari 14が配布開始に

Posted on 9月 17, 2020 by Takaaki Naganoya

WebP、WebM、VP9などのデータフォーマットに対応したSafari v14がmacOS 10.14.x、10.15,x向けに配信されました。macOS標準のソフトウェアアップデート経由でアップデートできます。

AppleScript用語辞書(sdef)を前バージョンの13.1.3と比較してみたところ、とくに差異はみあたりません。

Posted in Release | Tagged 10.14savvy 10.15savvy 11.0savvy Safari | Leave a comment

Mac App Storeで「White Pages」を販売開始

Posted on 9月 12, 2020 by Takaaki Naganoya

例によってAppleScriptで開発したアプリケーション「White Pages」のMac App Storeでの販売を開始しました。macOS 10.13以降に対応しています。

PDFの空白ページを削除・出力するアプリケーションです。空白ページの検出のため、全ページを画像にレンダリングして、空白判定。空白判定には速度と精度で定評のある空白画像検出ルーチンを使用しています。

決して、ページごとに文字の有無を判断するだけのソフト(Fredrik Method)ではありません。それだと、グラフィックだけのページを「空白」と判定してしまいますので。

アイコンは、macOS 11.0, Big Surに合わせた形状。手の色を赤くしているのは、何らかの特定の人種を想起させるような塗り色を避けたためです。

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

Mac App Storeで「Table Dripper」を販売開始

Posted on 9月 11, 2020 by Takaaki Naganoya

例によってAppleScriptで開発したアプリケーション「Table Dripper」のMac App Storeでの販売を開始しました。macOS 10.14以降に対応しています(動作原理的にmacOS 10.13対応は無理だった、、、)。

Safari/Google Chrome/Microsoft Edgeで表示中のWebサイトのTableデータをCSVに変換してダウンロードしてNumbers.appでオープンするアプリケーションです。

Mac App Storeの審査に10日かかって焦りました(機能のコンパクトさに反比例して審査期間が長い。たぶん、開発期間よりも審査期間の方が長い)。

すでに、他のChromiumベースのWebブラウザ「Brave」と「Vivaldi」への対応が済んでおり、次のアップデートでこれらにも対応します。AppleScript用語辞書(sdef)を持っているWebブラウザであっても、do javascript的なコマンドが実装されていないと、本アプリケーションでは対応できません(FireFox、Opera)。まして、AppleScriptにまったく対応していないWebブラウザでは、対応のしようがありません(Sleipnirなど)。

4つのアプリケーションをコントロールするアプリケーションをMac App Storeに申請したのははじめてです。

そろそろ、Script EditorとScript DebuggerをコントロールするアプリケーションをMac App Storeに申請することに。これも、審査が荒れる(期間が長くなる)ことが見込まれます。

Posted in PRODUCTS | Tagged 10.14savvy 10.15savvy 11.0savvy Google Chrome Microsoft Edge Safari | Leave a comment

現在のスライドと次のスライドでオーバーラップしている画像とグループを検出して位置をそろえる

Posted on 9月 10, 2020 by Takaaki Naganoya

Keynoteの最前面の書類で、現在表示中のスライドと次のスライドの間で、矩形座標が重なっている「画像」と「グループアイテム」(複数のオブジェクトをグループ化したアイテム)を検出して、現在のスライドの開始位置に場所をそろえるAppleScriptです。

# 最初掲載したもの(v1)は、動作しているものの処理内容に誤りがあったので修正しました(v2)

連続したスライド上に画面図を配置して、その画面図の位置をそろえるためのものです。何回か書いたような気がします。見た目より書くのが大変ではないので、ついつい書いてしまう処理です。

単にそれぞれの対象候補のオブジェクトの矩形開始座標と幅&高さをリスト化して、それをNSRectに変換して重ね合わせが発生していないかをCocoaの機能で判定しているだけです。この、一番めんどくさい部分をCocoaに丸投げしているので、おおよそ知性というものを感じさせないレベルのScriptです。

画像やグループアイテム 以外の表オブジェクト同士の重なりあいの検出を行うものに書き換えるのは簡単ですが、複数のオブジェクトの重なり合いが発生している場合には対処できません。

AppleScript名:現在のスライドと次のスライドでオーバーラップしている画像とグループを検出して位置をそろえる v2.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/09/10
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

tell application "Keynote"
  set dCount to count every document
  
if dCount = 0 then return –ドキュメントがオープンしていないと処理終了
  
  
tell front document
    set allNum to count every slide
    
if allNum < 2 then return –slideの枚数が少なかった場合に処理終了
    
    
set curSlide to current slide
    
if allNum = curSlide then return –current slideが末尾だった場合処理終了
    
    
set sNum to slide number of curSlide
    
set nextSlide to slide (sNum + 1)
    
    
–最初のページ(スライド)からオブジェクトを収集
    
tell current slide
      set curObj1 to every image
      
set curObj2 to every group
      
set curObjList to curObj1 & curObj2
      
if curObjList = {} then return
    end tell
    
    
–次のページ(スライド)からオブジェクトを収集
    
tell nextSlide
      set nextObj1 to every image
      
set nextObj2 to every group
      
set nextObjList to nextObj1 & nextObj2
      
if nextObjList = {} then return
    end tell
    
    
set nexObjRes to calcOverlappedObj(curObjList, nextObjList) of me
    
repeat with i in nexObjRes
      copy i to {origID, targID}
      
set aOrigObj to contents of item origID of curObjList
      
set aTargObj to contents of item origID of nextObjList
      
set origPos to position of aOrigObj
      
set position of aTargObj to origPos
    end repeat
    
    
set current slide to slide sNum
  end tell
end tell

–与えられた2つのリストに入っているKeynoteオブジェクトの矩形座標が重なっているものをIDペアで出力する
–同時に複数のオブジェクトが重なっていないことが前提
on calcOverlappedObj(objList1, objList2)
  tell application "Keynote"
    –最初のページのオブジェクトからオブジェクトIDとNSRectからなるリストを作成
    
set objRecList1 to {}
    
set aCount to 1
    
repeat with i in objList1
      if contents of i is not equal to {} then
        set {x1, y1} to position of i
        
set aRect to {origin:{x:x1, y:y1}, |size|:{|width|:(width of i), |height|:(height of i)}}
        
        
set the end of objRecList1 to {objID:aCount, rect:aRect}
      end if
      
set aCount to aCount + 1
    end repeat
    
    
–次のページのオブジェクトからオブジェクトIDとNSRectからなるリストを作成
    
set objRecList2 to {}
    
set aCount to 1
    
repeat with i in objList2
      if contents of i is not equal to {} then
        set {x1, y1} to position of i
        
set aRect to {origin:{x:x1, y:y1}, |size|:{|width|:(width of i), |height|:(height of i)}}
        
        
set the end of objRecList2 to {objID:aCount, rect:aRect}
      end if
      
set aCount to aCount + 1
    end repeat
    
    
–最初のページのオブジェクトと次のページのオブジェクトで矩形エリアが重なっているオブジェクトを抽出してそれぞれのIDをペアにしたリストを作成
    
set matchList to {}
    
repeat with i in objRecList1
      
      
set origRect to rect of i
      
set origID to objID of i
      
      
repeat with ii in objRecList2
        
        
set targRect to rect of ii
        
set targID to objID of ii
        
set tRes to detectRectanglesCollision(origRect, targRect) of me
        
        
if tRes = true then
          set the end of matchList to {origID, targID}
        end if
      end repeat
      
    end repeat
    
    
return matchList
  end tell
end calcOverlappedObj

–NSRect同士の衝突判定
on detectRectanglesCollision(aRect, bRect)
  set a1Res to (current application’s NSIntersectionRect(aRect, bRect)) as {record, list}
  
set tmpClass to class of a1Res
  
  
if tmpClass = record then
    –macOS 10.10, 10.11, 10.12
    
return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}})
  else if tmpClass = list then
    –macOS 10.13 or later
    
return not (a1Res = {{0.0, 0.0}, {0.0, 0.0}})
  end if
end detectRectanglesCollision

★Click Here to Open This Script 

Posted in list Record | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy Keynote | Leave a comment

指定Finderウィンドウがどのディスプレイ上に表示されているかをIDで返す(0はじまり)

Posted on 9月 7, 2020 by Takaaki Naganoya

指定座標がどのディスプレイ上に表示されているかをIDで返すAppleScriptです。

試しに、Finderの最前面のウィンドウの始点座標を取得して、どのディスプレイ上に表示されているかを地道にループで計算しています。

0はメニューを配置しているメインディスプレイで、その後のIDについてはNSScreen’s screens()の出現順に割り振られています。

MacBook Pro 10,1にディスプレイ3枚接続して(通常状態)、さらにUSB経由でiPadをDuet Displayで外部ディスプレイ化。4枚のディスプレイで動作確認しています。

本来、どのディスプレイ上にあるかをきっちり判定できるはずなのですが、最後のIDのものだけうまく判定できていないので例外処理しています。

このあたりの動作内容が怪しかったので、ながらく放置状態になっていましたが、実際にディスプレイを4枚つないで動作確認してみたら大丈夫そうだったので掲載することに。

AppleScript名:指定Finderウィンドウがどのディスプレイ上に表示されているかをIDで返す(0はじまり).scptd
— Created 2015-11-01 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

tell application "Finder"
  if (count every window) = 0 then return
  
tell front window
    set {xPos, yPos} to position
    
log {xPos, yPos}
  end tell
end tell

set dispID to getPointInWhichScreen(xPos, yPos) of me

–指定座標がどのディスプレイ上に表示されているかをIDで返す(0はじまり。0はメインディスプレイ)
on getPointInWhichScreen(xPos, yPos)
  set dList to getScreensResol() of me
  
  
set aPoint to current application’s NSMakePoint(xPos, yPos)
  
set dCount to 0
  
repeat with i in dList
    set dRes to current application’s NSPointInRect(aPoint, i) as boolean
    
    
if dRes = true then
      return dCount
    end if
    
set dCount to dCount + 1
  end repeat
  
  
return dCount – 1 –ちょっと怪しいが、動作している様子
end getPointInWhichScreen

on getScreensResol()
  set dispList to (current application’s NSScreen’s screens()) as list
  
set dList to {}
  
repeat with i in dispList
    set framePref to i’s visibleFrame()
    
set {xPos, yPos} to first item of framePref
    
set theInfo to (i’s deviceDescription()’s NSDeviceSize) as record
    
set a1Rect to {origin:{x:xPos, y:yPos}, |size|:theInfo}
    
set the end of dList to a1Rect
  end repeat
  
return dList
end getScreensResol

★Click Here to Open This Script 

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

PDFにパスワードが設定されている場合には、そのパーミッション情報を取得する

Posted on 8月 31, 2020 by Takaaki Naganoya

指定のPDFをチェックし、オープンするのにパスワードが設定されているとか、コピーが禁止されていないかといったパーミッションを調査するAppleScriptです。

API Lebel in this script Desc
(no api) openPermission document allows opening
allowsCopying copyPermission document allows copying of content to the Pasteboard
allowsPrinting printPermission document allows printing
allowsCommenting commentPermission document allows to create or modify document annotations, including form field entries
allowsContentAccessibility contentAccessPermission document allows to extract content from the document
allowsDocumentAssembly assemblyPermission document allows manage a document by inserting, deleting, and rotating pages
allowsDocumentChanges docchangePermission document allows modify the document contents except for document attributes
allowsFormFieldEntry formPermission document allows modify form field entries even if you can’t edit document annotations

PDFのオープン自体にパスワードロックがかかっている状態を検出するAPIがとくになかったので、いろいろ試行錯誤してOpenをロックしてある状態を検出してみました。

検出は、パスワード未指定でUnlockを試みるというもので、実際にパスワードを設定したPDFを相手に試行錯誤して求めてみました。

このUnlock操作に対してfalseが返ってくることでPDFオープンに対してパスワードが設定されているものと判断しています。

AppleScript名:PDFにパスワードが設定されている場合には、そのパーミッション情報を取得する
— Created 2015-11-02 13:48:32 +0900 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "QuartzCore"

set aPath to (choose file of type {"com.adobe.pdf"} with prompt "Select PDF to check")

set aRes to my retProtectedPDFPermissions(aPath)
–>  missing value (パスワードは設定されていない)

–> {openPermission:false, copyPermission:true, printPermission:true, commentPermission:true, contentAccessPermission:true, assemblyPermission:true, docchangePermission:true, formPermission:true}–オープンするためにはパスワードが必要(openPermission)

–指定のPDFにパスワードが設定されているかどうかをチェック
on retProtectedPDFPermissions(aPath)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aPath)
  
set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
  
set anEncF to aPDFdoc’s isEncrypted()
  
if anEncF = false then return missing value
  
  
set passLocked to aPDFdoc’s unlockWithPassword:""
  
  
set cpPerm to aPDFdoc’s allowsCopying() as boolean
  
set prPerm to aPDFdoc’s allowsPrinting() as boolean
  
set cmPerm to aPDFdoc’s allowsCommenting() as boolean
  
set caPerm to aPDFdoc’s allowsContentAccessibility() as boolean
  
set daPerm to aPDFdoc’s allowsDocumentAssembly() as boolean
  
set dcPerm to aPDFdoc’s allowsDocumentChanges() as boolean
  
set ffPerm to aPDFdoc’s allowsFormFieldEntry() as boolean
  
  
return {openPermission:passLocked, copyPermission:cpPerm, printPermission:prPerm, commentPermission:cmPerm, contentAccessPermission:caPerm, assemblyPermission:daPerm, docchangePermission:dcPerm, formPermission:ffPerm}
end retProtectedPDFPermissions

★Click Here to Open This Script 

Posted in file PDF | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy NSURL PDFDocument | Leave a comment

Mac App Storeで新アプリケーション「RBC」(Rename by contents)を販売開始

Posted on 8月 25, 2020 by Takaaki Naganoya

Mac App Storeに新アプリケーション「Rename by contents」を提出しました。Now On Saleです。

論文PDFのリネーム用ツールであり、「PDFの1ページ目の一番大きな文字の文をファイル名として採用する」というものです。macOS 10.13以降用で、Intel 64バイナリでビルドしてあります。全部AppleScriptで書いてあるので、ARM 64e向けにビルドし直すのもとくに問題ありません。

–> Watch Demo Movie

このアプリケーションほか、小物アプリケーションをMac App Storeに提出する方向で作業をすすめていますが、今回の審査は一番手間取りました。割と日常的に使っている小物アプリケーションは、小物アプリケーションらしくいろいろUIの味付けを変えているのですが、そういうアレンジしている部分を「HIG(Human Interface Guideline)に反する」という理由でリジェクトされました。

たとえば、こうした小物アプリケーションの場合に、メインウィンドウを閉じられたくない(処理がめんどくさいから)という事情があり、メインウィンドウのクローズボタンを無効にしていることがよくあります。

ウィンドウさえクローズされなければ問題は発生しないので、クローズ機能自体にフタをしてしまえばよいという話です。ただ、HIGの原則からいえば「クローズボタンがないのはダメ」なので、Mac App Store版のアプリケーションではこの「クローズボタンの無効化」は禁じ手ということになります。

クローズボタンを有効化して、メインウィンドウが閉じられたらアプリケーションを自動終了させる処理をコピペで書き足して、最終的にリジェクトを回避できました。

ちなみに、これとほぼ同時に作りはじめた別のアプリケーション「Foreign Love」(指定アプリケーションを他の言語環境で起動)は、現行のSandboxの仕様上、Sandbox環境では機能を発揮できないことが判明してオクラ入りしました。

ほかにもこまごまとしたリジェクト理由でAppleのレビュー担当(名前は知らない。毎回違うはず)とやりとりしていましたが、正直なところ小さいアプリケーションをMac App Storeに通すほうが大変な気がしました。ただ、この手の申請作業に慣れてきたような気がします。

あと、XcodeのOSACompile ビルドオプション、「Save as Execute-only」でデフォルトだとビルド時に「ソースを開示したままビルド」になっているので、AppleScriptのコードを全表示させたビルドをさせようとするのに何回も煮え湯を飲まされました。とても怖いdeath。

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

アラートダイアログ上にCollection Viewを表示

Posted on 8月 24, 2020 by Takaaki Naganoya

emada2さんからの投稿です。Collection Viewの利用については、Kamenokoの開発時に導入検討したことがありますが、Objective-CのサンプルコードをAppleScriptに翻訳しきれなくて中途半端に放置していました。

まとまった形でCollection Viewのサンプルコードが出てきたのは、おそらくこれが初めてだと思います。ありがとうございます。

Collection Viewを箱庭ダイアログに乗せることができました。
でも残念なのは、itemPrototypeは10.14でDeprecatedになっているので将来的に長く使えないでしょう
その他のやり方を探してappleのサンプルコードをみたら、swift 3で書かれていているので10.14でビルドできませんでした。
なのでまだまだCollection Viewを使いこなすのは難しそうです😢

–> Download Script Bundle

@property (nullable, strong) NSCollectionViewItem *itemPrototype API_DEPRECATED("Use -registerNib:forItemWithIdentifier: or -registerClass:forItemWithIdentifier: instead.", macos(10.5,10.14));
AppleScript名:アラートダイアログ上にCollection Viewを表示
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "AppKit"
use framework "AppleScriptObjC"
use framework "CoreFoundation"
use framework "Foundation"
use scripting additions

on run
  my testRun()
end run

on testRun()
  set aMainMes to "アプリケーションの選択"
  
set aSubMes to "適切なものを以下からえらんでください"
  
  
#ダイアログ内のビューサイズを指定
  
set aHeight to 384
  
set aWidth to 512 + 12 –> スクロールバーの分
  
  
#アプリケーションフォルダ内のアプリケーションを取得
  
set aFolder to path to applications folder
  
set aPath to aFolder’s POSIX path
  
set aURL to current application’s NSURL’s fileURLWithPath:aPath
  
  
# 指定フォルダの直下のファイルを取得
  
set filePaths to current application’s NSFileManager’s defaultManager’s ¬
    contentsOfDirectoryAtURL:aURL ¬
      includingPropertiesForKeys:{current application’s NSURLNameKey} ¬
      
options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) ¬
      
|error|:(missing value)
  
  
set filePaths to filePaths as list
  
set thisFileType to "com.apple.application-bundle"
  
  
set dataSourceList to {}
  
repeat with anItem in filePaths
    
    
set aPath to anItem’s contents’s POSIX path
    
set aURL to (current application’s NSURL’s fileURLWithPath:aPath)
    
    
set {aResult, aUTI, aError} to (aURL’s getResourceValue:(reference) ¬
      forKey:(current application’s NSURLTypeIdentifierKey) ¬
      
|error|:(reference))
    
    
if (aUTI as text) is thisFileType then
      set iconImage to (current application’s NSWorkspace’s sharedWorkspace’s iconForFile:aPath)
      
set dict to {fileURL:aURL, icon:iconImage}
      
set dataSourceList’s end to dict
    end if
  end repeat
  
  
set execButtonTitle to "OK😄"
  
  
set dateObj to my chooseItemByCollectionView:aMainMes subMes:aSubMes myWidth:aWidth myHeight:aHeight myDataSource:dataSourceList okTitle:execButtonTitle
end testRun

on chooseItemByCollectionView:(aMainMes as text) subMes:(aSubMes as text) myWidth:(aWidth as integer) myHeight:(aHeight as integer) myDataSource:(dataSourceList as list) okTitle:(execButtonTitle as text)
  
  
# Script Bundle内のResourcesフォルダを求める
  
set resourcePath to POSIX path of (path to me) & "Contents/Resources/"
  
set theBundle to current application’s NSBundle’s bundleWithPath:resourcePath
  
theBundle’s loadAppleScriptObjectiveCScripts()
  
  
# subClasses.scptを呼び出す
  
set DialogCore to current application’s AppDelegate’s new()
  
set fRes to DialogCore’s chooseItemByCollectionView:aMainMes subMes:aSubMes myWidth:aWidth myHeight:aHeight myDataSource:dataSourceList okTitle:execButtonTitle
  
  
if fRes is missing value then error number -128
  
return fRes as list
end chooseItemByCollectionView:subMes:myWidth:myHeight:myDataSource:okTitle:

★Click Here to Open This Script 

AppleScript名:subClasses
script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
on applicationShouldTerminateAfterLastWindowClosed:sender
    return true
  end applicationShouldTerminateAfterLastWindowClosed:
  
  
——————
  
  
on applicationWillFinishLaunching:aNotification
    log my testRun()
  end applicationWillFinishLaunching:
  
  
on testRun()
    set aMainMes to "アプリケーションの選択"
    
set aSubMes to "適切なものを以下からえらんでください"
    
    
#ダイアログ内のビューサイズを指定
    
set aHeight to 384
    
set aWidth to 512 + 12 –> スクロールバーの分
    
    
#アプリケーションフォルダ内のアプリケーションを取得
    
set aFolder to path to applications folder
    
set aPath to aFolder’s POSIX path
    
set aURL to current application’s NSURL’s fileURLWithPath:aPath
    
    
# 指定フォルダの直下のファイルを取得
    
set filePaths to current application’s NSFileManager’s defaultManager’s ¬
      contentsOfDirectoryAtURL:aURL ¬
        includingPropertiesForKeys:{current application’s NSURLNameKey} ¬
        
options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) ¬
        
|error|:(missing value)
    
    
set filePaths to filePaths as list
    
set thisFileType to "com.apple.application-bundle"
    
    
set dataSourceList to {}
    
repeat with anItem in filePaths
      
      
set aPath to anItem’s contents’s POSIX path
      
set aURL to (current application’s NSURL’s fileURLWithPath:aPath)
      
      
set {aResult, aUTI, aError} to (aURL’s getResourceValue:(reference) ¬
        forKey:(current application’s NSURLTypeIdentifierKey) ¬
        
|error|:(reference))
      
      
if (aUTI as text) is thisFileType then
        set iconImage to (current application’s NSWorkspace’s sharedWorkspace’s iconForFile:aPath)
        
set dict to {fileURL:aURL, icon:iconImage}
        
set dataSourceList’s end to dict
      end if
    end repeat
    
    
set execButtonTitle to "OK😄"
    
    
set dateObj to my chooseItemByCollectionView:aMainMes subMes:aSubMes myWidth:aWidth myHeight:aHeight myDataSource:dataSourceList okTitle:execButtonTitle
  end testRun
  
  
# アラートダイアログでCollectionViewを表示
  
property _retrieve_data : missing value
  
on chooseItemByCollectionView:(aMainMes as text) subMes:(aSubMes as text) myWidth:(aWidth as integer) myHeight:(aHeight as integer) myDataSource:(dataSourceList as list) okTitle:(execButtonTitle as text)
    
    
set paramObj to {myMessage:aMainMes}
    
set paramObj to paramObj & {mySubMessage:aSubMes}
    
set paramObj to paramObj & {myDataSource:dataSourceList}
    
set paramObj to paramObj & {myWidth:aWidth}
    
set paramObj to paramObj & {myHeight:aHeight}
    
set paramObj to paramObj & {myOKTitile:execButtonTitle}
    
    
my performSelectorOnMainThread:"raizeAlert:" withObject:paramObj waitUntilDone:true
    
    
if (my _retrieve_data) is missing value then error number -128
    
return (my _retrieve_data)
  end chooseItemByCollectionView:subMes:myWidth:myHeight:myDataSource:okTitle:
  
  
## retrieve date
  
on raizeAlert:paramObj
    
    
set mesText to paramObj’s myMessage as text
    
set infoText to paramObj’s mySubMessage as text
    
set dataSourceList to paramObj’s myDataSource as list
    
set viewWidth to paramObj’s myWidth as integer
    
set viewHeight to paramObj’s myHeight as integer
    
set okButton to paramObj’s myOKTitile as text
    
    
# set up view
    
set {thisView, collectionView} to my makeContentView(dataSourceList, viewWidth, viewHeight)
    
    
### set up alert
    
tell current application’s NSAlert’s new()
      addButtonWithTitle_(okButton)
      
addButtonWithTitle_("Cancel")
      
setAccessoryView_(thisView)
      
–setIcon_(aImage)
      
setInformativeText_(infoText)
      
setMessageText_(mesText)
      
tell |window|()
        setInitialFirstResponder_(thisView)
      end tell
      
#### show alert in modal loop
      
if runModal() is (current application’s NSAlertSecondButtonReturn) then return
    end tell
    
    
### retrieve data
    
set aIndexSet to collectionView’s selectionIndexes()
    
set theArray to current application’s NSArrayController’s alloc()’s initWithContent:(collectionView’s content())
    
set chooseItems to ((theArray)’s arrangedObjects()’s objectsAtIndexes:aIndexSet) as list
    
    
# reset
    
set _retrieve_data to {}
    
    
repeat with anItem in chooseItems
      set (my _retrieve_data)’s end to anItem’s contents
    end repeat
    
    
return my _retrieve_data
  end raizeAlert:
  
  
# set up view
  
on makeContentView(dataSourceList, viewWidth, viewHeight)
    
    
set thisRect to current application’s NSMakeRect(0, 0, viewWidth, viewHeight)
    
    
tell current application’s NSCollectionView’s alloc
      tell initWithFrame_(thisRect)
        setItemPrototype_(current application’s YKZCollectionViewItem’s new())
        
        
setAllowsEmptySelection_(true)
        
setAllowsMultipleSelection_(true)
        
setContent_(dataSourceList)
        
setSelectable_(true)
        
        
set collectionView to it
      end tell
    end tell
    
    
# Viewを作成
    
tell current application’s NSScrollView’s alloc()
      tell initWithFrame_(thisRect)
        setBorderType_(current application’s NSBezelBorder)
        
setDocumentView_(collectionView)
        
setHasHorizontalScroller_(true)
        
setHasVerticalScroller_(true)
        
set baseView to it
      end tell
    end tell
    
    
return {baseView, collectionView}
  end makeContentView
end script

#MARK: –
script YKZView
  property parent : class "NSView"
  
  
property imageView : missing value
  
  
property selected : false
  
property viewItemHeight : 128
  
property viewItemWidth : 128
  
  
on initWithFrame:rect
    
    
set myRect to current application’s NSMakeRect(0, 0, viewItemWidth, viewItemHeight)
    
continue initWithFrame:myRect
    
    
set aHeight to viewItemHeight – 10
    
set aWidth to viewItemWidth – 10
    
set newRect to current application’s NSMakeRect(5, 5, aWidth, aHeight)
    
    
tell current application’s NSImageView’s alloc()
      tell initWithFrame_(newRect)
        setImageScaling_(current application’s NSImageScaleProportionallyUpOrDown)
        
setImageAlignment_(current application’s NSImageAlignCenter)
        
set my imageView to it
      end tell
    end tell
    
    
my addSubview:(my imageView)
    
return me
  end initWithFrame:
  
  
on drawRect:rect
    if my selected then
      current application’s NSColor’s redColor()’s |set|()
    else
      current application’s NSColor’s controlBackgroundColor()’s |set|()
    end if
    
current application’s NSRectFill(rect)
    
continue drawRect:rect
  end drawRect:
end script

#MARK: –
script YKZCollectionViewItem
  property parent : class "NSCollectionViewItem"
  
  
on loadView()
    my setView:(current application’s YKZView’s alloc()’s initWithFrame:(current application’s NSZeroRect))
  end loadView
  
  
on setRepresentedObject:representedObject
    –continue setRepresentedObject:representedObject
    
if representedObject is missing value then return
    (
my view())’s imageView’s setImage:(representedObject’s icon)
  end setRepresentedObject:
  
  
on setSelected:isSelected
    set (my view())’s selected to isSelected
    (
my view())’s setNeedsDisplay:true
    
continue setSelected:isSelected
  end setSelected:
end script

★Click Here to Open This Script 

Posted in dialog file File path | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy NSAlert NSArrayController NSBundle NSCollectionView NSCollectionViewItem NSColor NSFileManager NSImageView NSURL NSWorkspace | Leave a comment

指定アプリケーションのバイナリアーキテクチャ判定 v3

Posted on 8月 18, 2020 by Takaaki Naganoya

指定のアプリケーションファイルが32bitバイナリかどうかを判定するAppleScriptの改訂版です。

本Scriptシリーズは対象のアプリケーションが起動している状態で対象CPUアーキテクチャを判定するものではなく、起動していない状態で判定するものです。

PPC 32 / PPC 64 / Intel 32 / Intel 64 / ARM 64の各アーキテクチャの判定を行います。FAT Binaryの場合には複数のアーキテクチャが返ってきます。


▲本Scriptの応用例

AppleScript名:指定アプリケーションのバイナリアーキテクチャ判定 v3.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/08/18
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set anApp to choose file of type {"com.apple.application-bundle"} default location (path to applications folder)
–set anApp to choose file default location (path to applications folder)
set app32 to chk32Binary(anApp) of me
–> {"PPC 32", "Intel x32"}

on chk32Binary(anAlias)
  set aPOSIX to POSIX path of anAlias
  
set aURL to current application’s |NSURL|’s fileURLWithPath:(aPOSIX)
  
set aBundle to current application’s NSBundle’s bundleWithURL:aURL
  
  
set F1 to (aBundle = missing value) as boolean
  
if F1 is not equal to false then return calcIllegular(aPOSIX) of me
  
  
set aDict to aBundle’s executableArchitectures()
  
set F2 to (aDict = missing value) as boolean
  
if F2 is equal to true then return calcIllegular(aPOSIX) of me
  
  
set aList to (aDict’s valueForKeyPath:"stringValue") as list
  
  
set arList to {}
  
repeat with i in aList
    set j to contents of i
    
    
if j = "7" then –NSBundleExecutableArchitectureI386
      set the end of arList to "Intel 32"
    else if j = "18" then –NSBundleExecutableArchitecturePPC
      set the end of arList to "PPC 32"
    else if j = "16777223" then –NSBundleExecutableArchitectureX86_64
      set the end of arList to "Intel 64"
    else if j = "16777234" then –NSBundleExecutableArchitecturePPC64
      set the end of arList to "PPC 64"
    else if j = "16777228" then –NSBundleExecutableArchitectureARM64
      set the end of arList to "ARM 64"
    end if
  end repeat
  
  
return arList
end chk32Binary

on calcIllegular(aPOSIX)
  –Old Style Bundle for PPC
  
set sRes to do shell script "file " & quoted form of aPOSIX
  
if sRes contains "Mach-O executable ppc" then return {"PPC 32"} –NSBundleExecutableArchitecturePPC
  
return missing value
end calcIllegular

★Click Here to Open This Script 

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

指定アプリケーションのバイナリアーキテクチャ判定

Posted on 8月 18, 2020 by Takaaki Naganoya

指定のアプリケーションファイルが32bitバイナリかどうかを判定するAppleScriptです。

実行ファイルのパスを求めて、fileコマンドで情報を取得します。本Scriptでは32bitバイナリであるかどうかの判定のみ行なっていますが、CPUアーキテクチャに着目してPPC/Intel 32/Intel 64/ARMの判定を行えるように作り込めます。

また、アプリケーションでありながらもバンドル形式になっていない実行ファイル(古い時代のファイルだったり、サードパーティの開発環境だったり)も存在しているため、NSBundleを求めたときにmissing valueが返ってくることもあります。

1ファイルだけ処理できてもあまり意味がないので、指定フォルダ以下のすべてのアプリケーションファイルをリストアップして、ループで処理するようなことをやることになるでしょう。

--PPC 32bit
/Applications/okaeri_up/v2.0b/Okaeri.app/Contents/MacOS/Okaeri: Mach-O executable ppc

--PPC/Intel 32bit FAT Binary
/Applications/Adobe Illustrator CS3/Adobe Illustrator.app//Contents/MacOS/Adobe Illustrator: Mach-O universal binary with 2 architectures: [i386:Mach-O executable i386] [ppc]
/Applications/Adobe Illustrator CS3/Adobe Illustrator.app//Contents/MacOS/Adobe Illustrator (for architecture i386):	Mach-O executable i386
/Applications/Adobe Illustrator CS3/Adobe Illustrator.app//Contents/MacOS/Adobe Illustrator (for architecture ppc):	Mach-O executable ppc

--Intel 32
/Applications/Adobe Illustrator CS5/Adobe Illustrator.app//Contents/MacOS/Adobe Illustrator: Mach-O executable i386

--Intel 32/64bit FAT Binary
/Applications/System Preferences.app//Contents/MacOS/System Preferences: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [i386:Mach-O executable i386]
/Applications/System Preferences.app//Contents/MacOS/System Preferences (for architecture x86_64):	Mach-O 64-bit executable x86_64
/Applications/System Preferences.app//Contents/MacOS/System Preferences (for architecture i386):	Mach-O executable i386

--Intel 64
/Applications/Adobe Illustrator 2020/Adobe Illustrator.app//Contents/MacOS/Adobe Illustrator: Mach-O 64-bit executable x86_64

--Intel/PPC 64bit FAT Binary
/Applications/Geekbench 2.1/Geekbench (64-bit).app/Contents/MacOS/Geekbench: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [ppc64]
/Applications/Geekbench 2.1/Geekbench (64-bit).app/Contents/MacOS/Geekbench (for architecture x86_64):	Mach-O 64-bit executable x86_64
/Applications/Geekbench 2.1/Geekbench (64-bit).app/Contents/MacOS/Geekbench (for architecture ppc64):	Mach-O executable ppc64

--Intel 64/ARM 64 FAT Binary
/System/Applications/Utilities/Script Editor.app/Contents/MacOS/Script Editor: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/System/Applications/Utilities/Script Editor.app/Contents/MacOS/Script Editor (for architecture x86_64):	Mach-O 64-bit executable x86_64
/System/Applications/Utilities/Script Editor.app/Contents/MacOS/Script Editor (for architecture arm64e):	Mach-O 64-bit executable arm64e
AppleScript名:指定アプリケーションのバイナリアーキテクチャ判定.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/08/18
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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


set anApp to choose file of type {“com.apple.application-bundle”} default location (path to applications folder)


set app32 to chk32Binary(anApp) of me
–> true –32bit
–> false –64bit


on chk32Binary(anApp)
  set aExec to getAppPropertyFromInfoPlist(anApp, “CFBundleExecutable”) of me
set posixPath to (POSIX path of anApp) & “/Contents/MacOS/” & aExec


  set aRes to do shell script “file “ & quoted form of posixPath
log aRes
if aRes contains “Mach-O executable i386” then
    return true –32bit
  else
    return false –64bit
  end if
end chk32Binary


on getAppPropertyFromInfoPlist(anAlias, aKey as string)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
set aBundle to current application’s NSBundle’s bundleWithURL:aURL
set aDict to aBundle’s infoDictionary()
set vRes to (aDict’s valueForKey:aKey) as string
return vRes as string
end getAppPropertyFromInfoPlist


★Click Here to Open This Script 
Posted in file File path | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy NSBundle NSURL | Leave a comment

display selected application’s plist on Finder

Posted on 8月 17, 2020 by Takaaki Naganoya

Finder上で選択中のアプリケーションのplistファイルを探してFinder上で選択表示するAppleScriptです。

AppleScript名:display selected application’s plist on Finder.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/08/17
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.5" –macOS 10.11 or later
use scripting additions
use framework "Foundation"
use framework "AppKit"

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSPredicate : a reference to current application’s NSPredicate
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey

tell application "Finder"
  set aliasList to selection as alias list
end tell

–Filter selection application bundle only
set aRes to filterAliasListByUTI(aliasList, "com.apple.application-bundle") of me
set aLen to length of aRes
if aLen = 0 then return

–Pick up the first element
set anApp to contents of first item of aRes

set aRes to getBundleIDFromPath(POSIX path of anApp) of me
set pListName to aRes & ".plist"

set prefPath to POSIX path of (path to preferences) & pListName
set aExt to current application’s NSFileManager’s defaultManager()’s fileExistsAtPath:prefPath
if aExt = true then
  revealAFileByFinder(prefPath) of me
end if

on filterAliasListByUTI(aliasList as list, acceptUTI as string)
  set fList to {}
  
repeat with i in aliasList
    set aUTI to getUTIfromPath(i) of me
    
if aUTI is not equal to missing value then
      set uRes to filterUTIList({aUTI}, acceptUTI) of me
      
      
if uRes is not equal to {} then
        set the end of fList to contents of i
      end if
    end if
  end repeat
  
return fList
end filterAliasListByUTI

–Application path –> Bundle ID
on getBundleIDFromPath(aPOSIXpath as string)
  set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath
  
set aWorkspace to current application’s NSWorkspace’s sharedWorkspace()
  
set appURL to aWorkspace’s URLForApplicationToOpenURL:aURL
  
set aBundle to current application’s NSBundle’s bundleWithURL:appURL
  
set anID to aBundle’s bundleIdentifier()
  
return anID as string
end getBundleIDFromPath

on revealAFileByFinder(aPOSIXpath as string)
  set pathStr to current application’s NSString’s stringWithString:aPOSIXpath
  
set parentPath to pathStr’s stringByDeletingLastPathComponent()
  
set aRes to current application’s NSWorkspace’s sharedWorkspace()’s selectFile:pathStr inFileViewerRootedAtPath:parentPath
end revealAFileByFinder

–Alias –> UTI
on getUTIfromPath(anAlias)
  set aPOSIXpath to POSIX path of anAlias
  
set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath
  
if aURL = missing value then return missing value
  
set aRes to aURL’s resourceValuesForKeys:{current application’s NSURLTypeIdentifierKey} |error|:(missing value)
  
if aRes = missing value then return missing value
  
return (aRes’s NSURLTypeIdentifierKey) as string
end getUTIfromPath

on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

★Click Here to Open This Script 

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

Post navigation

  • Older posts
  • Newer posts

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

Google Search

Popular Posts

  • 画面上の指定座標にマウスカーソルを強制移動させてクリック
  • AppleScript disassembler
  • ディスプレイの設定切り替えをAppleScriptでも行えるSwitchResX
  • 配列の要素数を取得する
  • 【基礎】AppleScriptの実行を(操作により)中断する
  • LAN上のHDDをマウントする v2
  • macOS 10.14 AppleScriptリリースノート
  • mouseClickを用いて指定座標をクリック
  • Numbersで選択中の表のセルの範囲を背景色で頻度集計
  • ファイルパスの変換(Alias→POSIX path→NSURL→POSIX path→file→Alias)
  • CotEditorで編集中のMarkdown書類をPDFプレビュー
  • Safariで表示中のWebページの最終更新日時を取得
  • 文字置換 v2
  • (GET)国土地理院APIで現在位置の標高を取得する
  • 配列の指定要素を検索する(テキスト)
  • Keynoteの最前面のドキュメントの現在のスライドに指定月の日曜日はじまりカレンダーを表で作成
  • CIFilterとGPUImageで画像差分検出演算を比較
  • JPEG画像の破損チェック
  • 頭のいいタイマー割り込み実行
  • Elgato Stream DeckをAppleScriptでフル活用

Tags

10.11savvy (1109) 10.12savvy (1249) 10.13savvy (1384) 10.14savvy (504) 10.15savvy (295) 11.0savvy (103) CotEditor (47) Finder (43) iTunes (25) Keynote (58) NSAlert (59) NSAlertSecondButtonReturn (16) NSArray (50) NSBitmapImageRep (20) NSBundle (19) NSButton (33) NSColor (48) NSDictionary (26) NSFileManager (23) NSFont (18) NSImage (40) NSJSONSerialization (20) NSMutableArray (61) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (55) NSScreen (30) NSScrollView (22) NSString (113) NSURL (93) NSURLRequest (22) NSUTF8StringEncoding (29) NSUUID (18) NSView (33) NSWindow (17) NSWorkspace (19) Numbers (42) Pages (16) Safari (34) System Events (16) WKUserContentController (20) WKUserScript (19) WKUserScriptInjectionTimeAtDocumentEnd (17) WKWebView (21) WKWebViewConfiguration (21)

カテゴリー

  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Bluetooth
  • boolean
  • Bug
  • Calendar
  • call by reference
  • Clipboard
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • drive
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • History
  • How To
  • Icon
  • Image
  • Input Method
  • Internet
  • JavaScript
  • JXA
  • Keychain
  • Language
  • list
  • Locale
  • Machine Learning
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • OCR
  • OSA
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • shell script
  • 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)
  • 未分類

アーカイブ

  • 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
Proudly powered by WordPress
Theme: Flint by Star Verte LLC